Gantt Overview
RevoGrid Gantt is an Enterprise plugin layered on top of the base grid. RevoGrid owns rendering, virtualization, editing, and keyboard interactions. Gantt adds task timeline projection, dependency links, scheduling rules, resources/assignments, critical path, baselines, and timeline tools.
Source code
import { defineCustomElements } from '@revolist/revogrid/loader';
defineCustomElements();
import {
defineGanttToolbar,
GanttPlugin,
} from '@revolist/revogrid-enterprise';
import { currentTheme } from '../composables/useRandomData';
import './gantt-task-editor-form.css';
import {
SHOWCASE_ASSIGNMENTS,
SHOWCASE_DEPENDENCIES,
SHOWCASE_RESOURCES,
SHOWCASE_TOOLBAR_COLUMNS,
STANDARD_CALENDAR,
} from './gantt-project-data';
import {
createInitialTaskSource,
TASK_EDITOR_COLUMNS,
TASK_EDITOR_DIALOG_CONFIG,
TASK_EDITOR_GANTT_CONFIG,
} from './GanttTaskEditorFormShared';
const { isDark } = currentTheme();
type TaskEditorGridElement = HTMLRevoGridElement & Record<string, any>;
function createElement<K extends keyof HTMLElementTagNameMap>(
tagName: K,
className?: string,
): HTMLElementTagNameMap[K] {
const element = document.createElement(tagName);
if (className) {
element.className = className;
}
return element;
}
export function load(parentSelector: string | Element) {
const parent = typeof parentSelector === 'string'
? document.querySelector(parentSelector)
: parentSelector;
if (!parent) {
return () => {};
}
const taskSource = createInitialTaskSource();
const root = createElement('section', 'gantt-task-editor-demo');
const toolbar = createElement('div', 'gantt-task-editor-toolbar');
const grid = document.createElement('revo-grid') as TaskEditorGridElement;
grid.className = 'gantt-task-editor-grid';
grid.theme = isDark() ? 'darkCompact' : 'compact';
grid.hideAttribution = true;
grid.plugins = [GanttPlugin as any];
grid.columns = TASK_EDITOR_COLUMNS;
grid.gantt = TASK_EDITOR_GANTT_CONFIG;
grid.ganttCalendars = [STANDARD_CALENDAR];
grid.ganttDependencies = SHOWCASE_DEPENDENCIES;
grid.ganttResources = SHOWCASE_RESOURCES;
grid.ganttAssignments = SHOWCASE_ASSIGNMENTS;
grid.ganttTaskEditorDialog = TASK_EDITOR_DIALOG_CONFIG;
root.appendChild(toolbar);
root.appendChild(grid);
parent.appendChild(root);
defineGanttToolbar(toolbar, {
grid,
columns: SHOWCASE_TOOLBAR_COLUMNS,
controls: {
export: false,
baseline: false,
},
});
grid.source = taskSource;
return () => {
root.remove();
};
}
import React, { useEffect, useMemo, useRef } from 'react';
import { RevoGrid } from '@revolist/react-datagrid';
import { defineGanttToolbar, GanttPlugin } from '@revolist/revogrid-enterprise';
import { currentTheme } from '../composables/useRandomData';
import {
SHOWCASE_ASSIGNMENTS,
SHOWCASE_DEPENDENCIES,
SHOWCASE_RESOURCES,
SHOWCASE_TOOLBAR_COLUMNS,
STANDARD_CALENDAR,
} from './gantt-project-data';
import {
createInitialTaskSource,
TASK_EDITOR_COLUMNS,
TASK_EDITOR_DIALOG_CONFIG,
TASK_EDITOR_GANTT_CONFIG,
} from './GanttTaskEditorFormShared';
import './gantt-task-editor-form.css';
const { isDark } = currentTheme();
export default function GanttTaskEditorForm() {
const gridRef = useRef<HTMLRevoGridElement>(null);
const toolbarRef = useRef<HTMLDivElement>(null);
const source = useMemo(() => createInitialTaskSource(), []);
const plugins = useMemo(() => [GanttPlugin], []);
const columns = useMemo(() => TASK_EDITOR_COLUMNS, []);
const gantt = useMemo(() => TASK_EDITOR_GANTT_CONFIG, []);
const calendars = useMemo(() => [STANDARD_CALENDAR], []);
const dependencies = useMemo(() => SHOWCASE_DEPENDENCIES, []);
const resources = useMemo(() => SHOWCASE_RESOURCES, []);
const assignments = useMemo(() => SHOWCASE_ASSIGNMENTS, []);
const taskEditorDialog = useMemo(() => TASK_EDITOR_DIALOG_CONFIG, []);
useEffect(() => {
const toolbar = toolbarRef.current;
const grid = gridRef.current;
if (!toolbar || !grid) {
return undefined;
}
defineGanttToolbar(toolbar, {
grid,
columns: SHOWCASE_TOOLBAR_COLUMNS,
controls: {
export: false,
baseline: false,
},
});
return () => {
toolbar.textContent = '';
};
}, []);
return (
<section className="gantt-task-editor-demo">
<div ref={toolbarRef} className="gantt-task-editor-toolbar" />
<RevoGrid
ref={gridRef}
className="gantt-task-editor-grid"
theme={isDark() ? 'darkCompact' : 'compact'}
hideAttribution
plugins={plugins}
source={source}
columns={columns}
gantt={gantt}
ganttCalendars={calendars}
ganttDependencies={dependencies}
ganttResources={resources}
ganttAssignments={assignments}
ganttTaskEditorDialog={taskEditorDialog}
/>
</section>
);
}
<template>
<section class="gantt-task-editor-demo">
<div ref="toolbarRef" class="gantt-task-editor-toolbar"></div>
<RevoGrid
ref="gridRef"
class="gantt-task-editor-grid"
hide-attribution
:theme="isDark ? 'darkCompact' : 'compact'"
:plugins="plugins"
:source="tasks"
:columns="columns"
:gantt.prop="ganttConfig"
:gantt-calendars.prop="calendars"
:gantt-dependencies.prop="dependencies"
:gantt-resources.prop="resources"
:gantt-assignments.prop="assignments"
:gantt-task-editor-dialog.prop="taskEditorDialog"
/>
</section>
</template>
<script setup lang="ts">
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
import RevoGrid from '@revolist/vue3-datagrid';
import { defineGanttToolbar, GanttPlugin } from '@revolist/revogrid-enterprise';
import { currentThemeVue } from '../composables/useRandomData';
import {
SHOWCASE_ASSIGNMENTS,
SHOWCASE_DEPENDENCIES,
SHOWCASE_RESOURCES,
SHOWCASE_TOOLBAR_COLUMNS,
STANDARD_CALENDAR,
} from './gantt-project-data';
import {
createInitialTaskSource,
TASK_EDITOR_COLUMNS,
TASK_EDITOR_DIALOG_CONFIG,
TASK_EDITOR_GANTT_CONFIG,
} from './GanttTaskEditorFormShared';
import './gantt-task-editor-form.css';
const { isDark } = currentThemeVue();
const plugins = ref([GanttPlugin]);
const columns = ref(TASK_EDITOR_COLUMNS);
const tasks = ref(createInitialTaskSource());
const ganttConfig = ref(TASK_EDITOR_GANTT_CONFIG);
const calendars = ref([STANDARD_CALENDAR]);
const dependencies = ref(SHOWCASE_DEPENDENCIES);
const resources = ref(SHOWCASE_RESOURCES);
const assignments = ref(SHOWCASE_ASSIGNMENTS);
const taskEditorDialog = ref(TASK_EDITOR_DIALOG_CONFIG);
const gridRef = ref<InstanceType<typeof RevoGrid> | HTMLRevoGridElement | null>(null);
const toolbarRef = ref<HTMLElement | null>(null);
let toolbarMounted = false;
let toolbarFrame = 0;
function getGridEl(): HTMLRevoGridElement | null {
const refValue = gridRef.value as (InstanceType<typeof RevoGrid> & { $el?: HTMLRevoGridElement }) | HTMLRevoGridElement | null;
const candidate = (refValue && '$el' in refValue ? refValue.$el : refValue) ?? null;
return candidate instanceof HTMLElement && candidate.tagName.toLowerCase() === 'revo-grid'
? candidate as HTMLRevoGridElement
: null;
}
function mountToolbar() {
if (toolbarMounted) {
return;
}
const grid = getGridEl();
if (!toolbarRef.value || !grid) {
toolbarFrame = requestAnimationFrame(mountToolbar);
return;
}
toolbarMounted = true;
defineGanttToolbar(toolbarRef.value, {
grid,
columns: SHOWCASE_TOOLBAR_COLUMNS,
controls: {
export: false,
baseline: false,
},
});
}
onMounted(async () => {
await nextTick();
mountToolbar();
});
onBeforeUnmount(() => {
if (toolbarFrame) {
cancelAnimationFrame(toolbarFrame);
}
if (toolbarRef.value) {
toolbarRef.value.textContent = '';
}
});
</script>
import { AfterViewInit, Component, ElementRef, NO_ERRORS_SCHEMA, ViewChild, ViewEncapsulation } from '@angular/core';
import { RevoGrid } from '@revolist/angular-datagrid';
import { defineGanttToolbar, GanttPlugin } from '@revolist/revogrid-enterprise';
import { currentTheme } from '../composables/useRandomData';
import {
SHOWCASE_ASSIGNMENTS,
SHOWCASE_DEPENDENCIES,
SHOWCASE_RESOURCES,
SHOWCASE_TOOLBAR_COLUMNS,
STANDARD_CALENDAR,
} from './gantt-project-data';
import {
createInitialTaskSource,
TASK_EDITOR_COLUMNS,
TASK_EDITOR_DIALOG_CONFIG,
TASK_EDITOR_GANTT_CONFIG,
} from './GanttTaskEditorFormShared';
@Component({
selector: 'gantt-task-editor-form-grid',
standalone: true,
// Allows Angular demos to bind RevoGrid plugin props that are not wrapper inputs.
schemas: [NO_ERRORS_SCHEMA],
imports: [RevoGrid],
template: `
<section class="gantt-task-editor-demo">
<div #toolbar class="gantt-task-editor-toolbar"></div>
<revo-grid
#grid
class="gantt-task-editor-grid"
[theme]="theme"
[hideAttribution]="true"
[plugins]="plugins"
[source]="tasks"
[columns]="columns"
[gantt]="ganttConfig"
[ganttCalendars]="calendars"
[ganttDependencies]="dependencies"
[ganttResources]="resources"
[ganttAssignments]="assignments"
[ganttTaskEditorDialog]="taskEditorDialog"
></revo-grid>
</section>
`,
styleUrls: ['./gantt-task-editor-form.css'],
encapsulation: ViewEncapsulation.None,
})
export class GanttTaskEditorFormGridComponent implements AfterViewInit {
@ViewChild('grid', { read: ElementRef }) gridRef!: ElementRef<HTMLRevoGridElement>;
@ViewChild('toolbar', { read: ElementRef }) toolbarRef!: ElementRef<HTMLElement>;
theme = currentTheme().isDark() ? 'darkCompact' : 'compact';
plugins = [GanttPlugin];
columns = TASK_EDITOR_COLUMNS;
tasks = createInitialTaskSource();
ganttConfig = TASK_EDITOR_GANTT_CONFIG;
calendars = [STANDARD_CALENDAR];
dependencies = SHOWCASE_DEPENDENCIES;
resources = SHOWCASE_RESOURCES;
assignments = SHOWCASE_ASSIGNMENTS;
taskEditorDialog = TASK_EDITOR_DIALOG_CONFIG;
ngAfterViewInit(): void {
defineGanttToolbar(this.toolbarRef.nativeElement, {
grid: this.gridRef.nativeElement,
columns: SHOWCASE_TOOLBAR_COLUMNS,
controls: {
export: false,
baseline: false,
},
});
}
}
/**
* Shared project data for all Gantt documentation examples.
* Uses the "Website Redesign" project — simple enough to follow,
* rich enough to show hierarchy, milestones, dependencies, and baselines.
*/
import type {
ColumnRegular,
} from '@revolist/revogrid';
import type {
TaskEntity,
DependencyEntity,
CalendarEntity,
ResourceEntity,
AssignmentEntity,
BaselineSnapshot,
GanttPluginConfig,
} from '@revolist/revogrid-enterprise';
import { createDefaultTaskTableColumn } from '@revolist/revogrid-enterprise';
// ─── IDs ─────────────────────────────────────────────────────────────────────
export const PROJECT_ID = 'project-web-redesign';
export const CALENDAR_ID = 'cal-standard';
export const CALENDAR_US_ID = 'cal-us';
// ─── Base config (override per example) ──────────────────────────────────────
export const GANTT_BASE_CONFIG = {
id: PROJECT_ID,
name: 'Website Redesign',
version: '1',
currency: 'USD',
timeZone: 'UTC',
primaryCalendarId: CALENDAR_ID,
updatedAt: '2026-04-06T00:00:00Z',
zoomPreset: 'week' as const,
};
// ─── Calendars ────────────────────────────────────────────────────────────────
export const STANDARD_CALENDAR: CalendarEntity = {
id: CALENDAR_ID,
name: 'Standard',
timeZone: 'UTC',
workingDays: [1, 2, 3, 4, 5],
holidays: [],
hoursPerDay: 8,
};
export const US_CALENDAR: CalendarEntity = {
id: CALENDAR_US_ID,
name: 'US Standard',
timeZone: 'America/New_York',
workingDays: [1, 2, 3, 4, 5],
holidays: ['2026-05-25', '2026-07-04'],
hoursPerDay: 8,
};
// ─── Tasks ────────────────────────────────────────────────────────────────────
export const TASKS: TaskEntity[] = [
{
id: 't1', projectId: PROJECT_ID, parentId: null,
wbsCode: '1', name: 'Design', type: 'summary', status: 'in-progress',
startDate: '2026-04-06', endDate: '2026-04-24', durationDays: 15,
progressPercent: 60, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't2', projectId: PROJECT_ID, parentId: 't1',
wbsCode: '1.1', name: 'Wireframes', type: 'task', status: 'done',
startDate: '2026-04-06', endDate: '2026-04-10', durationDays: 5,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't3', projectId: PROJECT_ID, parentId: 't1',
wbsCode: '1.2', name: 'Design Review', type: 'milestone', status: 'done',
startDate: '2026-04-10', endDate: '2026-04-10', durationDays: 0,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: true, tags: ['milestone'],
},
{
id: 't4', projectId: PROJECT_ID, parentId: 't1',
wbsCode: '1.3', name: 'Visual Design', type: 'task', status: 'in-progress',
startDate: '2026-04-13', endDate: '2026-04-24', durationDays: 10,
progressPercent: 40, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't5', projectId: PROJECT_ID, parentId: null,
wbsCode: '2', name: 'Development', type: 'summary', status: 'not-started',
startDate: '2026-04-27', endDate: '2026-05-20', durationDays: 18,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't6', projectId: PROJECT_ID, parentId: 't5',
wbsCode: '2.1', name: 'Frontend', type: 'task', status: 'not-started',
startDate: '2026-04-27', endDate: '2026-05-13', durationDays: 13,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't7', projectId: PROJECT_ID, parentId: 't5',
wbsCode: '2.2', name: 'Backend', type: 'task', status: 'not-started',
startDate: '2026-04-27', endDate: '2026-05-20', durationDays: 18,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't8', projectId: PROJECT_ID, parentId: null,
wbsCode: '3', name: 'Launch', type: 'milestone', status: 'not-started',
startDate: '2026-05-20', endDate: '2026-05-20', durationDays: 0,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: ['milestone'],
},
];
/** Tasks with Visual Design slipped +3 days — used in the baseline example. */
export const TASKS_SLIPPED: TaskEntity[] = TASKS.map((task) => {
if (task.id === 't4') {
return { ...task, endDate: '2026-04-27', durationDays: 13, progressPercent: 30 };
}
if (task.id === 't1') {
return { ...task, endDate: '2026-04-27', durationDays: 18, progressPercent: 50 };
}
if (task.id === 't5') {
return { ...task, startDate: '2026-04-28', endDate: '2026-05-21' };
}
if (task.id === 't6') {
return { ...task, startDate: '2026-04-28', endDate: '2026-05-14' };
}
if (task.id === 't7') {
return { ...task, startDate: '2026-04-28', endDate: '2026-05-21' };
}
if (task.id === 't8') {
return { ...task, startDate: '2026-05-21', endDate: '2026-05-21' };
}
return task;
});
/** Tasks with scheduling constraints — used in the scheduling example. */
export const TASKS_SCHEDULED: TaskEntity[] = TASKS.map((task) => {
if (task.id === 't6') {
return {
...task, startDate: '2026-05-04', endDate: '2026-05-20',
constraintType: 'start-no-earlier-than', constraintDate: '2026-05-04',
};
}
if (task.id === 't7') {
return { ...task, durationDays: 24, endDate: '2026-05-28', deadlineDate: '2026-05-22' };
}
if (task.id === 't8') {
return { ...task, startDate: '2026-05-28', endDate: '2026-05-28' };
}
return task;
});
// ─── Dependencies ─────────────────────────────────────────────────────────────
export const DEPENDENCIES: DependencyEntity[] = [
{ id: 'd1', predecessorTaskId: 't2', successorTaskId: 't3', type: 'finish-to-start', lagDays: 0 },
{ id: 'd2', predecessorTaskId: 't3', successorTaskId: 't4', type: 'finish-to-start', lagDays: 1 },
{ id: 'd3', predecessorTaskId: 't4', successorTaskId: 't6', type: 'finish-to-start', lagDays: 1 },
{ id: 'd4', predecessorTaskId: 't4', successorTaskId: 't7', type: 'finish-to-start', lagDays: 1 },
{ id: 'd5', predecessorTaskId: 't6', successorTaskId: 't8', type: 'finish-to-start', lagDays: 0 },
{ id: 'd6', predecessorTaskId: 't7', successorTaskId: 't8', type: 'finish-to-start', lagDays: 0 },
];
// ─── Resources & Assignments ──────────────────────────────────────────────────
export const RESOURCES: ResourceEntity[] = [
{ id: 'r1', name: 'Alice Chen', role: 'Designer', calendarId: CALENDAR_ID, allocationCapacity: 1, hourlyCost: 95 },
{ id: 'r2', name: 'Bob Kim', role: 'Frontend Dev', calendarId: CALENDAR_ID, allocationCapacity: 1, hourlyCost: 110 },
{ id: 'r3', name: 'Carla Díaz', role: 'Backend Dev', calendarId: CALENDAR_ID, allocationCapacity: 1, hourlyCost: 105 },
];
export const ASSIGNMENTS: AssignmentEntity[] = [
{ id: 'a1', taskId: 't2', resourceId: 'r1', allocationUnits: 1, responsibility: 'assigned' },
{ id: 'a2', taskId: 't4', resourceId: 'r1', allocationUnits: 1, responsibility: 'assigned' },
{ id: 'a3', taskId: 't6', resourceId: 'r2', allocationUnits: 1, responsibility: 'assigned' },
{ id: 'a4', taskId: 't7', resourceId: 'r3', allocationUnits: 1, responsibility: 'assigned' },
];
// ─── Baseline ─────────────────────────────────────────────────────────────────
export const BASELINES: BaselineSnapshot[] = [
{
id: 'baseline-approved',
name: 'Approved Plan',
capturedAt: '2026-04-01T08:00:00Z',
tasks: [
{ taskId: 't1', startDate: '2026-04-06', endDate: '2026-04-24', durationDays: 15, progressPercent: 0 },
{ taskId: 't2', startDate: '2026-04-06', endDate: '2026-04-10', durationDays: 5, progressPercent: 0 },
{ taskId: 't3', startDate: '2026-04-10', endDate: '2026-04-10', durationDays: 0, progressPercent: 0 },
{ taskId: 't4', startDate: '2026-04-13', endDate: '2026-04-24', durationDays: 10, progressPercent: 0 },
{ taskId: 't5', startDate: '2026-04-27', endDate: '2026-05-20', durationDays: 18, progressPercent: 0 },
{ taskId: 't6', startDate: '2026-04-27', endDate: '2026-05-13', durationDays: 13, progressPercent: 0 },
{ taskId: 't7', startDate: '2026-04-27', endDate: '2026-05-20', durationDays: 18, progressPercent: 0 },
{ taskId: 't8', startDate: '2026-05-20', endDate: '2026-05-20', durationDays: 0, progressPercent: 0 },
],
},
];
// ─── Default columns (basic examples) ────────────────────────────────────────
export const DEFAULT_COLUMNS = [
createDefaultTaskTableColumn('wbs'),
createDefaultTaskTableColumn('name'),
createDefaultTaskTableColumn('assignees'),
createDefaultTaskTableColumn('cost' as any),
createDefaultTaskTableColumn('startDate'),
createDefaultTaskTableColumn('endDate'),
createDefaultTaskTableColumn('duration'),
createDefaultTaskTableColumn('percentDone'),
].filter(Boolean);
// ─── Showcase column options (all 10, with visibility flags) ─────────────────
export const SHOWCASE_COLUMN_OPTIONS = [
{ prop: 'wbs', label: 'WBS', defaultVisible: true },
{ prop: 'name', label: 'Name', defaultVisible: true },
{ prop: 'assignees', label: 'Assignees', defaultVisible: true },
{ prop: 'cost', label: 'Cost', defaultVisible: true },
{ prop: 'startDate', label: 'Start Date', defaultVisible: true },
{ prop: 'endDate', label: 'End Date', defaultVisible: false },
{ prop: 'duration', label: 'Duration', defaultVisible: true },
{ prop: 'percentDone', label: '% Done', defaultVisible: false },
{ prop: 'predecessors', label: 'Predecessors', defaultVisible: false },
{ prop: 'successors', label: 'Successors', defaultVisible: false },
{ prop: 'status', label: 'Status', defaultVisible: true },
] as const;
export const SHOWCASE_TOOLBAR_COLUMNS = [
{ prop: 'name', label: 'Task', visible: true },
{ prop: 'assignees', label: 'Assignees', visible: true },
{ prop: 'cost', label: 'Cost', visible: true },
{ prop: 'startDate', label: 'Start', visible: true },
{ prop: 'duration', label: 'Dur', visible: true },
];
export type ShowcaseColumnProp = (typeof SHOWCASE_COLUMN_OPTIONS)[number]['prop'];
/** All 10 showcase columns as RevoGrid column definitions. */
export const SHOWCASE_COLUMNS = SHOWCASE_COLUMN_OPTIONS
.map((c) => createDefaultTaskTableColumn(c.prop as any))
.filter((c): c is NonNullable<typeof c> => Boolean(c));
/** Props that are hidden by default in the showcase. */
export const SHOWCASE_DEFAULT_HIDDEN: string[] = SHOWCASE_COLUMN_OPTIONS
.filter((c) => !c.defaultVisible)
.map((c) => c.prop as string);
type ShowcaseTaskEntity = TaskEntity & {
estimatedCost?: number;
};
export const SHOWCASE_PROJECT_ID = 'project-launch-saas';
export const SHOWCASE_GANTT_CONFIG = {
...GANTT_BASE_CONFIG,
id: SHOWCASE_PROJECT_ID,
name: 'Launch SaaS Product',
updatedAt: '2026-04-28T10:00:00Z',
zoomPreset: 'day-week' as const,
allowTaskCreate: true,
visuals: {
showBaseline: true,
showCriticalPath: true,
showTaskLabels: true,
shadeNonWorkingTime: true,
showTodayLine: true,
milestoneLines: [
{ id: 'public-launch', date: '2026-05-23', label: 'Launch', color: '#facc15' },
],
},
scheduling: {
excludeHolidaysFromDuration: true,
},
} satisfies GanttPluginConfig;
export const SHOWCASE_TASKS: ShowcaseTaskEntity[] = [
{
id: 'launch', projectId: SHOWCASE_PROJECT_ID, parentId: null,
wbsCode: '', name: 'Launch SaaS Product', type: 'summary', status: 'blocked',
startDate: '2026-04-06', endDate: '2026-05-23', durationDays: 47,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
estimatedCost: 248400,
},
{
id: 'backend', projectId: SHOWCASE_PROJECT_ID, parentId: 'launch',
wbsCode: '1', name: 'Backend Setup', type: 'summary', status: 'blocked',
startDate: '2026-04-06', endDate: '2026-04-18', durationDays: 12,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: true, tags: ['Backend'],
estimatedCost: 32400,
},
{
id: 'design', projectId: SHOWCASE_PROJECT_ID, parentId: 'launch',
wbsCode: '2', name: 'Design', type: 'summary', status: 'blocked',
startDate: '2026-04-06', endDate: '2026-04-24', durationDays: 18,
progressPercent: 97, calendarId: CALENDAR_ID, isCritical: true, tags: ['Design'],
estimatedCost: 14800,
},
{
id: 'frontend', projectId: SHOWCASE_PROJECT_ID, parentId: 'launch',
wbsCode: '3', name: 'Frontend Development', type: 'summary', status: 'blocked',
startDate: '2026-04-14', endDate: '2026-05-10', durationDays: 24,
progressPercent: 50, calendarId: CALENDAR_ID, isCritical: true, tags: ['Frontend'],
estimatedCost: 38600,
},
{
id: 'devops', projectId: SHOWCASE_PROJECT_ID, parentId: 'launch',
wbsCode: '4', name: 'DevOps', type: 'summary', status: 'blocked',
startDate: '2026-04-10', endDate: '2026-05-12', durationDays: 32,
progressPercent: 85, calendarId: CALENDAR_ID, isCritical: true, tags: ['DevOps'],
estimatedCost: 21800,
},
{
id: 'iac', projectId: SHOWCASE_PROJECT_ID, parentId: 'devops',
wbsCode: '4.1', name: 'Infrastructure as Code', type: 'task', status: 'done',
startDate: '2026-04-10', endDate: '2026-04-18', durationDays: 8,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: false, tags: ['DevOps'],
estimatedCost: 7800,
},
{
id: 'ci-cd', projectId: SHOWCASE_PROJECT_ID, parentId: 'devops',
wbsCode: '4.2', name: 'CI / CD Pipeline', type: 'task', status: 'done',
startDate: '2026-04-16', endDate: '2026-04-24', durationDays: 8,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: false, tags: ['DevOps'],
estimatedCost: 5200,
},
{
id: 'monitoring', projectId: SHOWCASE_PROJECT_ID, parentId: 'devops',
wbsCode: '4.3', name: 'Monitoring & Logging', type: 'task', status: 'blocked',
startDate: '2026-04-22', endDate: '2026-04-30', durationDays: 8,
progressPercent: 55, calendarId: CALENDAR_ID, isCritical: false, tags: ['DevOps'],
estimatedCost: 4400,
},
{
id: 'prod-deploy', projectId: SHOWCASE_PROJECT_ID, parentId: 'launch',
wbsCode: '5', name: 'Production Deploy', type: 'milestone', status: 'not-started',
startDate: '2026-05-12', endDate: '2026-05-12', durationDays: 0,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: ['Milestone'],
},
{
id: 'qa', projectId: SHOWCASE_PROJECT_ID, parentId: 'launch',
wbsCode: '6', name: 'QA', type: 'summary', status: 'blocked',
startDate: '2026-04-20', endDate: '2026-05-18', durationDays: 28,
progressPercent: 32, calendarId: CALENDAR_ID, isCritical: true, tags: ['QA'],
estimatedCost: 12200,
},
{
id: 'test-plan', projectId: SHOWCASE_PROJECT_ID, parentId: 'qa',
wbsCode: '6.1', name: 'Test Plan', type: 'task', status: 'done',
startDate: '2026-04-20', endDate: '2026-04-24', durationDays: 4,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: false, tags: ['QA'],
estimatedCost: 2800,
},
{
id: 'unit-tests', projectId: SHOWCASE_PROJECT_ID, parentId: 'qa',
wbsCode: '6.2', name: 'Unit Tests', type: 'task', status: 'in-progress',
startDate: '2026-04-24', endDate: '2026-05-04', durationDays: 10,
progressPercent: 62, calendarId: CALENDAR_ID, isCritical: false, tags: ['QA'],
estimatedCost: 4200,
},
{
id: 'integration-tests', projectId: SHOWCASE_PROJECT_ID, parentId: 'qa',
wbsCode: '6.3', name: 'Integration Tests', type: 'task', status: 'not-started',
startDate: '2026-05-02', endDate: '2026-05-12', durationDays: 10,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: ['QA'],
estimatedCost: 3400,
},
{
id: 'uat', projectId: SHOWCASE_PROJECT_ID, parentId: 'qa',
wbsCode: '6.4', name: 'User Acceptance Test', type: 'task', status: 'not-started',
startDate: '2026-05-10', endDate: '2026-05-18', durationDays: 8,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: ['QA'],
estimatedCost: 1800,
},
{
id: 'security', projectId: SHOWCASE_PROJECT_ID, parentId: 'launch',
wbsCode: '7', name: 'Security', type: 'summary', status: 'not-started',
startDate: '2026-05-06', endDate: '2026-05-21', durationDays: 15,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: ['Security'],
estimatedCost: 7200,
},
{
id: 'pentest', projectId: SHOWCASE_PROJECT_ID, parentId: 'security',
wbsCode: '7.1', name: 'Penetration Testing', type: 'task', status: 'not-started',
startDate: '2026-05-06', endDate: '2026-05-14', durationDays: 8,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: ['Security'],
estimatedCost: 4800,
},
{
id: 'audit', projectId: SHOWCASE_PROJECT_ID, parentId: 'security',
wbsCode: '7.2', name: 'Audit & Compliance', type: 'task', status: 'not-started',
startDate: '2026-05-12', endDate: '2026-05-21', durationDays: 9,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: ['Security'],
estimatedCost: 2400,
},
{
id: 'public-launch', projectId: SHOWCASE_PROJECT_ID, parentId: 'launch',
wbsCode: '8', name: 'Public Launch', type: 'milestone', status: 'not-started',
startDate: '2026-05-23', endDate: '2026-05-23', durationDays: 0,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: ['Milestone'],
},
];
export const SHOWCASE_DEPENDENCIES: DependencyEntity[] = [
{ id: 'sd-1', predecessorTaskId: 'iac', successorTaskId: 'ci-cd', type: 'finish-to-start', lagDays: 0 },
{ id: 'sd-2', predecessorTaskId: 'ci-cd', successorTaskId: 'monitoring', type: 'finish-to-start', lagDays: 0 },
{ id: 'sd-3', predecessorTaskId: 'test-plan', successorTaskId: 'unit-tests', type: 'finish-to-start', lagDays: 0 },
{ id: 'sd-4', predecessorTaskId: 'unit-tests', successorTaskId: 'integration-tests', type: 'finish-to-start', lagDays: 0 },
{ id: 'sd-5', predecessorTaskId: 'integration-tests', successorTaskId: 'uat', type: 'finish-to-start', lagDays: 0 },
{ id: 'sd-6', predecessorTaskId: 'audit', successorTaskId: 'public-launch', type: 'finish-to-start', lagDays: 0 },
];
export const SHOWCASE_RESOURCES: ResourceEntity[] = [
{ id: 'nk', name: 'Nina Kim', role: 'Platform Engineer', calendarId: CALENDAR_ID, allocationCapacity: 1, hourlyCost: 125 },
{ id: 'rp', name: 'Ravi Patel', role: 'QA Lead', calendarId: CALENDAR_ID, allocationCapacity: 1, hourlyCost: 100 },
{ id: 'jd', name: 'Jordan Diaz', role: 'Automation Engineer', calendarId: CALENDAR_ID, allocationCapacity: 1, hourlyCost: 95 },
{ id: 'sr', name: 'Sam Rivera', role: 'Product Owner', calendarId: CALENDAR_ID, allocationCapacity: 1, hourlyCost: 90 },
{ id: 'vk', name: 'Vera Khan', role: 'Security Engineer', calendarId: CALENDAR_ID, allocationCapacity: 1, hourlyCost: 115 },
];
export const SHOWCASE_ASSIGNMENTS: AssignmentEntity[] = [
{ id: 'sa-1', taskId: 'iac', resourceId: 'nk', allocationUnits: 1, responsibility: 'Owner' },
{ id: 'sa-2', taskId: 'ci-cd', resourceId: 'nk', allocationUnits: 1, responsibility: 'Owner' },
{ id: 'sa-3', taskId: 'monitoring', resourceId: 'nk', allocationUnits: 1, responsibility: 'Owner' },
{ id: 'sa-4', taskId: 'test-plan', resourceId: 'rp', allocationUnits: 1, responsibility: 'Owner' },
{ id: 'sa-5', taskId: 'unit-tests', resourceId: 'rp', allocationUnits: 1, responsibility: 'Lead' },
{ id: 'sa-6', taskId: 'unit-tests', resourceId: 'jd', allocationUnits: 1, responsibility: 'Automation' },
{ id: 'sa-7', taskId: 'integration-tests', resourceId: 'rp', allocationUnits: 1, responsibility: 'Owner' },
{ id: 'sa-8', taskId: 'uat', resourceId: 'rp', allocationUnits: 1, responsibility: 'Lead' },
{ id: 'sa-9', taskId: 'uat', resourceId: 'sr', allocationUnits: 1, responsibility: 'Signoff' },
{ id: 'sa-10', taskId: 'pentest', resourceId: 'vk', allocationUnits: 1, responsibility: 'Owner' },
{ id: 'sa-11', taskId: 'audit', resourceId: 'vk', allocationUnits: 1, responsibility: 'Lead' },
{ id: 'sa-12', taskId: 'audit', resourceId: 'jd', allocationUnits: 1, responsibility: 'Compliance' },
];
export const SHOWCASE_BASELINES: BaselineSnapshot[] = [
{
id: 'showcase-approved',
name: 'Approved launch plan',
capturedAt: '2026-04-01T08:00:00Z',
tasks: SHOWCASE_TASKS.map((task) => ({
taskId: task.id,
startDate: task.startDate,
endDate: task.endDate,
durationDays: task.durationDays,
progressPercent: 0,
})),
},
];
const SHOWCASE_STATUS_COLOR: Record<string, string> = {
'not-started': '#525866',
'in-progress': '#f59e0b',
done: '#39d07d',
blocked: '#ff4d4f',
};
const SHOWCASE_TAG_COLORS: Record<string, { color: string; bg: string; border: string }> = {
Backend: { color: '#ff66b3', bg: 'rgba(255, 102, 179, 0.14)', border: 'rgba(255, 102, 179, 0.35)' },
Design: { color: '#a78bfa', bg: 'rgba(167, 139, 250, 0.14)', border: 'rgba(167, 139, 250, 0.36)' },
Frontend: { color: '#34d399', bg: 'rgba(52, 211, 153, 0.14)', border: 'rgba(52, 211, 153, 0.36)' },
DevOps: { color: '#fb923c', bg: 'rgba(251, 146, 60, 0.14)', border: 'rgba(251, 146, 60, 0.36)' },
QA: { color: '#60a5fa', bg: 'rgba(96, 165, 250, 0.14)', border: 'rgba(96, 165, 250, 0.36)' },
Security: { color: '#facc15', bg: 'rgba(250, 204, 21, 0.13)', border: 'rgba(250, 204, 21, 0.36)' },
};
function renderShowcaseNameCell(h: Parameters<Required<ColumnRegular>['cellTemplate']>[0], model: any) {
const tag = model.tags?.[0];
const tagStyle = tag && SHOWCASE_TAG_COLORS[tag]
? {
'--showcase-tag-color': SHOWCASE_TAG_COLORS[tag].color,
'--showcase-tag-bg': SHOWCASE_TAG_COLORS[tag].bg,
'--showcase-tag-border': SHOWCASE_TAG_COLORS[tag].border,
}
: {};
return h('div', { class: { 'gantt-showcase-task-cell': true } }, [
h('span', {
class: {
'gantt-showcase-status-dot': true,
'gantt-showcase-status-dot--milestone': model.taskKind === 'milestone',
},
style: { '--showcase-status-color': SHOWCASE_STATUS_COLOR[model.statusKey ?? 'not-started'] ?? SHOWCASE_STATUS_COLOR['not-started'] },
}),
h('span', { class: { 'gantt-showcase-task-name': true }, title: model.name }, model.name),
tag && SHOWCASE_TAG_COLORS[tag]
? h('span', { class: { 'gantt-showcase-tag': true }, style: tagStyle }, tag)
: null,
]);
}
function showcaseCellProperties({ model }: any) {
return {
class: {
'gantt-showcase-cell--root': model.id === 'launch',
'gantt-showcase-cell--summary': model.taskKind === 'summary',
},
};
}
export const SHOWCASE_COLUMNS_POLISHED: ColumnRegular[] = [
{
...createDefaultTaskTableColumn('name'),
name: 'Task',
size: 292,
cellTemplate: (h, { model }) => renderShowcaseNameCell(h, model),
cellProperties: showcaseCellProperties,
},
{
...createDefaultTaskTableColumn('assignees'),
size: 102,
cellProperties: showcaseCellProperties,
},
{
...createDefaultTaskTableColumn('cost' as any),
size: 114,
cellProperties: showcaseCellProperties,
},
{
...createDefaultTaskTableColumn('startDate'),
name: 'Start',
size: 116,
cellProperties: showcaseCellProperties,
},
{
...createDefaultTaskTableColumn('duration'),
name: 'Dur',
size: 90,
cellProperties: showcaseCellProperties,
},
];
type ShowcaseTaskColor = { barColor: string; progressColor: string; textColor?: string };
export const GANTT_SHOWCASE_DEFAULT_TASK_COLOR: ShowcaseTaskColor = {
barColor: '#64748b',
progressColor: '#94a3b8',
textColor: '#ffffff',
};
export const GANTT_SHOWCASE_TASK_COLORS: Record<string, ShowcaseTaskColor> = {
launch: { barColor: '#a5a7b0', progressColor: '#8f929d', textColor: '#f8fafc' },
backend: { barColor: '#ff77d2', progressColor: '#f43f9e' },
design: { barColor: '#d9b4ff', progressColor: '#a78bfa', textColor: '#25143f' },
frontend: { barColor: '#5eead4', progressColor: '#34d399', textColor: '#092f25' },
devops: { barColor: '#ffd45a', progressColor: '#fb923c', textColor: '#2d1f02' },
iac: { barColor: '#b66b2e', progressColor: '#f97316' },
'ci-cd': { barColor: '#b66b2e', progressColor: '#f97316' },
monitoring: { barColor: '#5a2c12', progressColor: '#f97316' },
'prod-deploy': { barColor: '#facc15', progressColor: '#facc15', textColor: '#18181b' },
qa: { barColor: '#60a5fa', progressColor: '#7dd3fc', textColor: '#061633' },
'test-plan': { barColor: '#4d76b2', progressColor: '#7dd3fc' },
'unit-tests': { barColor: '#1e3558', progressColor: '#4f7dbd' },
'integration-tests': { barColor: '#102441', progressColor: '#60a5fa' },
uat: { barColor: '#102441', progressColor: '#60a5fa' },
security: { barColor: '#facc15', progressColor: '#eab308', textColor: '#18181b' },
pentest: { barColor: '#2f2610', progressColor: '#facc15' },
audit: { barColor: '#2f2610', progressColor: '#facc15' },
'public-launch': { barColor: '#facc15', progressColor: '#facc15', textColor: '#18181b' },
};
export function getShowcaseTaskBarColor({ row }: any) {
const assigneeCount = row.assigneeDetails?.length ?? 0;
return {
...GANTT_SHOWCASE_DEFAULT_TASK_COLOR,
...GANTT_SHOWCASE_TASK_COLORS[row.id],
...(assigneeCount && row.taskKind !== 'summary' ? { className: 'gantt-bar--with-assignee' } : {}),
};
}
export function renderShowcaseTaskBarContent({ h, row, defaultContent }: any) {
if (!row.assigneeDetails?.length || row.taskKind === 'summary') {
return defaultContent;
}
return [
...defaultContent,
h('span', { class: { 'gantt-bar__assignee-badge': true } }, row.assigneeDetails[0].initials),
];
}
// ─── Typed config builders ────────────────────────────────────────────────────
export function makeGanttConfig(overrides: Partial<GanttPluginConfig> = {}): GanttPluginConfig {
return { ...GANTT_BASE_CONFIG, ...overrides } as GanttPluginConfig;
}
This document crossmatches the desired Scheduler, Gantt, and shared planning-platform feature list against the current implementation in packages/enterprise/plugins/gantt.
Status:
Existing ✅- implemented now.Partial ☑️- foundation exists, but product/API/UX work is still needed.Planned 🚧- roadmap item.
Gantt
Project planning with task hierarchy, dependencies, milestones, baselines, calendars, resources, and scheduling logic.
| Feature group | Feature | Status | Notes |
|---|---|---|---|
| Task model | Task tree / work breakdown structure | ✅ | Tasks use parentId and wbsCode. |
| Task model | Summary tasks | ✅ | Summary task type and parent rollups exist. |
| Task model | Regular tasks | ✅ | Standard task type exists. |
| Task model | Milestones | ✅ | Milestone task type exists. |
| Task model | Collapsible task groups | ✅ | Tree plugin integration exists. |
| Task model | Parent-child rollups | ✅ | Schedule and cost rollups exist. |
| Dependencies | Finish-to-Start | ✅ | Supported dependency type. |
| Dependencies | Start-to-Start | ✅ | Supported dependency type. |
| Dependencies | Finish-to-Finish | ✅ | Supported dependency type. |
| Dependencies | Start-to-Finish | ✅ | Supported dependency type. |
| Dependencies | Lead and lag time | ✅ | Positive lag and negative lead are supported. |
| Dependencies | Dependency validation | ✅ | Validation and diagnostics exist. |
| Dependencies | Move task dependencies | ✅ | Dependency drag/link editing exists. |
| Dependencies | Hide dependency arrows | ✅ | gantt.visuals.showDependencies = false hides dependency overlays without mutating ganttDependencies. |
| Scheduling | Auto-scheduling | ✅ | Dependency-aware recalculation exists. |
| Scheduling | Manual scheduling | ✅ | Manual tasks preserve authored dates and can warn. |
| Scheduling | Forward scheduling | ✅ | Project-start scheduling exists. |
| Scheduling | Backward scheduling | ✅ | Project-finish scheduling exists. |
| Scheduling | Task constraints | ✅ | Start/finish no-earlier/no-later and must-start/must-finish constraints exist. |
| Scheduling | Deadline markers | ✅ | Deadline fields and indicators exist. |
| Scheduling | Duration calculation | ✅ | Calendar-aware duration logic exists. |
| Scheduling | Start / finish date calculation | ✅ | Engine computes effective dates. |
| Scheduling | Task splitting | ✅ | Split ranges affect date math and rendering. |
| Critical path | Critical path | ✅ | Critical path calculation and highlighting exist. |
| Critical path | Total slack | ✅ | totalSlackDays is projected. |
| Critical path | Free slack | 🚧 | Separate free-slack field is not implemented. |
| Baselines | Baselines | ✅ | Baseline snapshots and baseline bars exist. |
| Baselines | Baseline variance | ✅ | Start, finish, duration, and progress variance fields exist. |
| Progress | Percent complete | ✅ | Progress field and editing exist. |
| Progress | Progress tracking | ✅ | Actual dates, remaining duration, and progress-aware scheduling exist. |
| Calendars | Project calendar | ✅ | Primary project calendar exists. |
| Calendars | Task calendar | ✅ | Tasks reference calendars. |
| Calendars | Resource calendar | ✅ | Resources reference calendars. |
| Calendars | Working / non-working days | ✅ | Calendar working weekdays exist. |
| Calendars | Holidays | ✅ | Calendar holidays exist. |
| Resources | Resource assignment | ✅ | Assignment model exists. |
| Resources | Resource workload view | ✅ | Resource planning mode exists. |
| Resources | Resource utilization | ✅ | Load summaries and capacity display exist. |
| Resources | Over-allocation warnings | ✅ | Resource allocation diagnostics exist. |
| Cost | Cost fields | ✅ | Explicit and calculated costs exist. |
| Customization | Custom task fields | ☑️ | Rows can carry custom data; formal custom field schema is planned. |
| Customization | Custom columns | ☑️ | RevoGrid column foundation and packaged Gantt column presets exist; broader custom-column API is planned. |
| Editing | Inline grid editing | ✅ | Grid edits patch task fields. |
| Editing | Drag task bars | ✅ | Task bar drag exists. |
| Editing | Resize task bars | ✅ | Task bar resize exists. |
| Editing | Progress drag/edit | ✅ | Progress interaction exists. |
| Timeline | Zoom levels | ✅ | Preset and custom zoom exist. |
| Timeline | Timeline markers | ✅ | Time ranges, project line, today line, milestone lines, and task markers exist. |
| Timeline | Today line | ✅ | Today line is supported. |
| Selection | Multi-selection | ☑️ | RevoGrid selection exists; multi-task Gantt operations are planned. |
| Keyboard | Keyboard navigation | ☑️ | RevoGrid foundation exists; Gantt-specific shortcuts are planned. |
| History | Undo / redo | ✅ | Gantt history snapshots exist. |
| Import/export | Grid import / export | ✅ | CSV export is available in RevoGrid core; Excel import/export is available in RevoGrid Pro, with Gantt toolbar action helpers. |
| Import/export | Gantt project import / export | ✅ | Typed project snapshots include clone/export/parse JSON helpers, REST/GraphQL adapter examples, and a PostgreSQL persistence recipe; broader project-file adapters are planned. |
| Import/export | MS Project-style compatibility layer | 🚧 | 🚧. |
| Performance | Large project virtualization | ☑️ | RevoGrid virtualization exists; Gantt-specific server/window model is planned. |
| Performance | Server-side loading for enterprise datasets | 🚧 | Not implemented. |
Scheduler
Resource planning for teams, equipment, rooms, vehicles, and operations.
| Feature group | Feature | Status | Notes |
|---|---|---|---|
| Timeline views | Resource timeline view | ✅ | Resource planning mode renders resource rows with load bars. |
| Timeline views | Day / week / month / custom range views | ✅ | Default timeline zoom levels include day-week, week-month, month-quarter, quarter-year, year-quarter, and multi-year-quarter; intraday presets are opt-in for performance, and custom zoom levels are configurable. |
| Timeline views | Horizontal scheduling mode | ✅ | Current resource planning and Gantt timeline are horizontal. |
| Timeline views | Vertical scheduling mode | 🚧 | Needs dedicated Scheduler layout. |
| Resource management | Resource scheduling | ☑️ | Resources, assignments, capacity, and calendars exist; dedicated events/bookings/jobs model is planned. |
| Resource management | Multi-resource assignment | ✅ | Multiple resources can be assigned to a task. |
| Resource management | Resource grouping | 🚧 | Resource filtering exists, but grouping UI/API is planned. |
| Resource management | Nested resource trees | 🚧 | Needs resource hierarchy model/projection. |
| Event editing | Drag-and-drop event creation | ☑️ | Task drag-create exists; Scheduler event creation is planned. |
| Event editing | Drag-and-drop event moving | ☑️ | Task bar moving exists; Scheduler event moving is planned. |
| Event editing | Event resizing | ☑️ | Task resizing exists; Scheduler event resizing is planned. |
| Event editing | Event splitting | ☑️ | Task split ranges exist; Scheduler event split UX is planned. |
| Event editing | Event merging | 🚧 | Not implemented. |
| Event layout | Overlapping event layout | 🚧 | Needs Scheduler event layout engine. |
| Event layout | Stack / pack / overlap display modes | 🚧 | Needs configurable event display modes. |
| Editing modes | Read-only mode | ✅ | gantt.readOnly blocks packaged task, dependency, and assignment mutation services. |
| Editing modes | Editable mode | ☑️ | Task editing exists; Scheduler event editing is planned. |
| Calendars | Custom working hours | ☑️ | Calendars support working days, holidays, and hours/day; intraday hours are planned. |
| Calendars | Non-working time highlighting | ✅ | Timeline can shade non-working time. |
| Calendars | Timezone support | ✅ | Project and calendars carry IANA time zones. |
| Recurrence | Recurring events | 🚧 | Not implemented. |
| Recurrence | Event exceptions | 🚧 | Not implemented. |
| Validation | Event validation hooks | ☑️ | Cancelable before-change hooks exist for tasks, dependencies, and assignments. Event-specific hooks are planned. |
| Validation | Conflict detection | ☑️ | Resource over-allocation and scheduling diagnostics exist; booking conflict rules are planned. |
| Validation | Capacity warnings | ✅ | Resource planning supports capacity and over-allocation display. |
| Validation | Availability rules | ☑️ | Resource calendars exist; richer availability rules are planned. |
| Validation | Locked events | ☑️ | Gantt tasks support locked; Scheduler event locks remain planned. |
| Rendering | Custom event templates | ☑️ | Task renderer hooks exist; Scheduler event renderer API is planned. |
| Rendering | Custom resource rows | ☑️ | Resource row projection exists; public custom resource row API is planned. |
| Rendering | Custom timeline headers | ✅ | Timeline zoom/header configuration exists. |
| Rendering | Tooltips and popovers | ☑️ | Task tooltip hook and Gantt task detail popover model exist; richer Scheduler popovers are planned. |
| Grid UX | Inline editing | ✅ | Grid edits update task data. |
| Grid UX | Keyboard navigation | ☑️ | RevoGrid foundation exists; Scheduler-specific keyboard workflows are planned. |
| Grid UX | Copy / paste | ☑️ | RevoGrid foundation exists; Scheduler-specific behavior is planned. |
| Grid UX | Undo / redo | ✅ | Gantt integrates with history snapshots. |
| Grid UX | Filtering and search | ✅ | Tree-aware Gantt search exists. |
| Performance | Virtual scrolling for large datasets | ☑️ | RevoGrid virtualization exists; Scheduler-specific data windowing is planned. |
| Performance | Lazy loading by date range | 🚧 | Not implemented. |
| Export | Excel export | ✅ | Supported through RevoGrid Pro ExportExcelPlugin for grid data. Timeline-image/workbook specialization can be added later. |
| Export | Excel import | ✅ | Supported through RevoGrid Pro ExportExcelPlugin; Gantt-specific project mapping can be added later. |
| Export | CSV export | ✅ | Supported through RevoGrid core ExportFilePlugin when grid exporting is enabled. |
| Export | PDF export | ☑️ | Print-oriented reporting recipe exists; timeline/PDF layout export is not provided by the current grid export plugins. A combined PDF + Excel reporting recipe documents the recommended toolbar wiring. |
Shared RevoGrid Planning Platform
Built on the same high-performance grid engine and scheduling foundation.
| Feature group | Feature | Status | Notes |
|---|---|---|---|
| Data model | Tasks | ✅ | TaskEntity. |
| Data model | Events | 🚧 | Scheduler event entity is planned. |
| Data model | Resources | ✅ | ResourceEntity. |
| Data model | Assignments | ✅ | AssignmentEntity. |
| Data model | Dependencies | ✅ | DependencyEntity. |
| Data model | Calendars | ✅ | CalendarEntity. |
| Data model | Baselines | ✅ | BaselineSnapshot. |
| Data model | Time ranges | ✅ | Timeline visual ranges exist. |
| Data model | Constraints | ✅ | Task constraints exist. |
| Data model | Custom metadata | ☑️ | Tags/notes and row extensibility exist; typed metadata schema is planned. |
| Data model | Custom field schemas | 🚧 | Not implemented. |
| Data model | Typed data models | ✅ | Typed config, entities, events, and projected rows exist. |
| Data model | Framework-agnostic core | ✅ | Engine/projection/core are framework-independent TypeScript modules. |
| Scheduling engine | Calendar-aware date calculation | ✅ | Implemented. |
| Scheduling engine | Dependency-aware recalculation | ✅ | Implemented. |
| Scheduling engine | Forward scheduling | ✅ | Implemented. |
| Scheduling engine | Backward scheduling | ✅ | Implemented. |
| Scheduling engine | Manual vs automatic scheduling | ✅ | Implemented. |
| Scheduling engine | Constraint handling | ✅ | Implemented. |
| Scheduling engine | Critical path calculation | ✅ | Implemented. |
| Scheduling engine | Resource conflict detection | ✅ | Implemented as resource over-allocation diagnostics. |
| Scheduling engine | Configurable validation rules | ☑️ | Policy options and cancelable hooks exist; rule registry is planned. |
| Scheduling engine | Transaction-based updates | ☑️ | Mutation services exist; public transaction API is planned. |
| Scheduling engine | Batch recalculation | ✅ | Engine recalculates resolved project snapshots. |
| Scheduling engine | Deterministic scheduling results | ✅ | Implemented. |
| Grid foundation | RevoGrid-powered left-side grid | ✅ | Gantt projects rows and columns into RevoGrid. |
| Grid foundation | Virtualized rows and columns | ✅ | RevoGrid foundation. |
| Grid foundation | Frozen columns | ✅ | RevoGrid/Pro foundation. |
| Grid foundation | Column grouping | ✅ | RevoGrid foundation. |
| Grid foundation | Column resizing | ✅ | RevoGrid foundation. |
| Grid foundation | Column reordering | ✅ | RevoGrid foundation. |
| Grid foundation | Custom cell renderers | ✅ | RevoGrid templates and Gantt bar hooks. |
| Grid foundation | Custom editors | ☑️ | RevoGrid editor foundation exists; Gantt editor forms are planned. |
| Grid foundation | Tree data | ✅ | Tree plugin integration. |
| Grid foundation | Row grouping | ☑️ | RevoGrid/Pro foundation exists; Gantt-specific row grouping is planned. |
| Grid foundation | Sorting | ☑️ | RevoGrid foundation exists; scheduler-safe sorting policy is planned. |
| Grid foundation | Filtering | ✅ | Gantt search and RevoGrid filtering foundation. |
| Grid foundation | Selection | ✅ | RevoGrid foundation. |
| Grid foundation | Clipboard | ✅ | RevoGrid/Pro foundation. |
| Grid foundation | Keyboard navigation | ✅ | RevoGrid foundation. |
| Grid foundation | Theming | ✅ | Gantt SCSS and RevoGrid theming foundation. |
| Grid foundation | Plugin architecture | ✅ | Gantt composes feature tools and Pro plugins. |
| Enterprise performance | Virtual rendering | ✅ | RevoGrid foundation. |
| Enterprise performance | Large dataset support | ☑️ | Rendering foundation exists; server/window data model is planned. |
| Enterprise performance | Lazy loading | 🚧 | Not implemented. |
| Enterprise performance | Date-range loading | 🚧 | Not implemented. |
| Enterprise performance | Viewport-aware loading | 🚧 | Not implemented. |
| Enterprise performance | Server-side data model | 🚧 | Not implemented. |
| Enterprise performance | Incremental updates | ☑️ | Local mutation services exist; remote incremental sync is planned. |
| Enterprise performance | Real-time updates | 🚧 | Not implemented. |
| Enterprise performance | Optimistic updates | 🚧 | Not implemented. |
| Enterprise performance | WebSocket-ready data flow | 🚧 | Not implemented. |
| Enterprise performance | Batched mutations | ☑️ | Controlled local mutations exist; explicit batch API is planned. |
| Enterprise performance | Minimal re-rendering | ☑️ | Grid sync update modes exist. |
| Framework support | React | ✅ | Gantt demos/components exist. |
| Framework support | Vue | ✅ | Gantt demos/components exist. |
| Framework support | Angular | ✅ | Gantt demos/components exist. |
| Framework support | Svelte | ☑️ | Svelte usage example exists; packaged wrapper/API docs are planned. |
| Extensibility | Custom task renderer | ✅ | Task bar color/content/tooltip hooks. |
| Extensibility | Custom event renderer | 🚧 | Requires Scheduler event model. |
| Extensibility | Custom dependency renderer | ☑️ | Dependency layer exists; public renderer hook is planned. |
| Extensibility | Custom tooltip renderer | ✅ | Task tooltip hook and built-in tooltip field selection exist. |
| Extensibility | Custom editor forms | ✅ | Task editor form schema, submit normalization helper, and packaged Preact row-context-menu dialog plugin exist; the packaged dialog edits task fields and resource assignments. |
| Extensibility | Custom validation | ☑️ | Cancelable before-change events and validation recipe examples exist; validation registry is planned. |
| Extensibility | Custom scheduling rules | 🚧 | 🚧. |
| Extensibility | Custom calendars | ✅ | Calendar entities are configurable. |
| Extensibility | Custom export pipeline | ☑️ | Gantt Excel row mapping, toolbar export actions, print recipe, and combined PDF + Excel reporting recipe exist; full pipeline hooks are planned. |
| Extensibility | Custom context menu | ✅ | Gantt enables row, column, and timeline context menus by default, prepends default actions through RevoGrid Pro ContextMenuPlugin, preserves custom menu items, and supports opt-out through gantt.contextMenu. |
| Extensibility | Plugin API | ✅ | Gantt plugin and feature-tool architecture exist. |
| Extensibility | Event lifecycle hooks | ✅ | Before-change and interaction events exist. |
| Extensibility | Typed API | ✅ | Typed config/entities/events exist. |
| Collaboration | Optimistic editing | 🚧 | 🚧. |
| Collaboration | Conflict resolution hooks | 🚧 | 🚧. |
| Collaboration | Change history | ✅ | History integration exists. |
| Collaboration | Audit log support | 🚧 | 🚧. |
| Collaboration | User presence markers | 🚧 | 🚧. |
| Collaboration | Comments on tasks/events | 🚧 | 🚧. |
| Collaboration | Locking / checkout mode | ☑️ | Gantt task locked prevents packaged task mutation paths; broader checkout workflows are planned. |
| Collaboration | Role-based editability | ☑️ | Role/permission helpers exist for before-change hooks; packaged policy wiring is planned. |
| Collaboration | Read-only views | ✅ | gantt.readOnly blocks packaged task, dependency, and assignment mutations. |
| Collaboration | Approval workflow hooks | 🚧 | 🚧. |
| Export and integration | CSV export | ✅ | RevoGrid core ExportFilePlugin exports visible grid data as CSV. |
| Export and integration | Excel export | ✅ | RevoGrid Pro ExportExcelPlugin exports grid data to .xlsx. |
| Export and integration | Excel import | ✅ | RevoGrid Pro ExportExcelPlugin imports .xlsx/.xls into the grid. |
| Export and integration | PDF export | ☑️ | Print-oriented reporting recipe exists; native PDF export is not implemented by core/Pro/Gantt export plugins. |
| Export and integration | PNG export | 🚧 | Not implemented by core/Pro/Gantt export plugins. |
| Export and integration | JSON import/export | ✅ | Gantt core exports clone/export/parse helpers for typed project snapshots. |
| Export and integration | iCalendar support for Scheduler | 🚧 | 🚧. |
| Export and integration | MS Project-style import/export layer | 🚧 | 🚧. |
| Export and integration | REST API integration | ☑️ | Project snapshot REST adapter example exists; production backend templates are planned. |
| Export and integration | GraphQL integration | ☑️ | Project snapshot GraphQL adapter example exists; production backend templates are planned. |
| Export and integration | Server-side adapter examples | ☑️ | REST, GraphQL, and PostgreSQL/Supabase-style examples exist; Firebase and server-window examples are planned. |
| Export and integration | Supabase / Firebase / PostgreSQL examples | ☑️ | PostgreSQL SQL builders and Supabase-style adapter exist; Firebase example is planned. |
| Export and integration | Headless scheduling engine mode | ☑️ | Engine is framework-independent; public headless API/package is planned. |
Feature: Gantt Task Editor Dialog Plugin
Status: Existing ✅
The packaged task editor dialog provides an MS Project-style “Task Information” entry point without forcing application teams to build the popup UI from scratch. GanttPlugin installs GanttTaskEditorDialogPlugin by default for every Gantt instance; the plugin mounts a Preact <dialog> host beside the grid, prepends Edit task... to the row context menu, renders the task editor schema from TASK_EDITOR_FIELD_SCHEMA, and normalizes submissions with normalizeTaskEditorSubmit().
Design notes:
- The plugin is still exported as a separate enterprise plugin for backwards compatibility, but
GanttPluginauto-installs it so teams do not need to register it manually for normal Gantt usage. - Row context menus get
Edit task...from the task editor plugin andAdd taskfrom the Gantt context-menu tool by default; both compose with custom row context-menu configuration instead of replacing application items. gantt.contextMenu = falseopts out of generated Gantt menu items;ganttTaskEditorDialog.contextMenucan independently disable or re-enable the packaged edit-task menu entry.- Newly created tasks open in the editor by default after
gantt-task-created;ganttTaskEditorDialog.openOnCreate = falsekeeps creation silent for applications that want a custom follow-up flow. - The dialog is closed by default. Its CSS explicitly hides
dialog:not([open])so the browser default dialog box never occupies layout before a user opens it. - Default submit behavior applies task field patches through the Gantt runtime/provider edit path, not by replacing
grid.sourcedirectly. Applications can intercept throughganttTaskEditorDialog.onSubmit; returningfalseskips the default update. - History covers task editor task field patches, resource assignment changes, dependency tab changes, direct external
grid.sourceedits observed by Gantt, and toolbar-driven task/dependency/baseline changes. - Task resolution prefers Gantt task-bar
data-gantt-task-id, then focused row data, then row text fallback for framework/browser context-menu timing differences. - Read-only projects hide the context-menu item unless
ganttTaskEditorDialog.readOnlyoverrides the behavior.
Current Extra Strengths Beyond The Initial List
| Area | Feature | Status |
|---|---|---|
| Scheduling | Backward/project-finish scheduling | ✅ |
| Scheduling | Resource leveling modes: off, warn, auto | ✅ |
| Scheduling | Slack-bound resource leveling | ✅ |
| Scheduling | Progress-aware remaining-duration scheduling | ✅ |
| Scheduling | Fixed-duration, fixed-work, and fixed-units effort modes | ✅ |
| Diagnostics | Scheduler warnings projected into row data | ✅ |
| Diagnostics | Dependency validation summary helper | ✅ |
| Diagnostics | Resource over-allocation summary helper | ✅ |
| Dependencies | Predecessor/successor text parser and formatter | ✅ |
| Timeline | Custom milestone flag lines | ✅ |
| Timeline | Custom task marker hook | ✅ |
| Timeline | Custom task bar color/content/tooltip hooks | ✅ |
| Toolbar | Baseline capture, critical-path toggle, and timeline navigation actions | ✅ |
| Rendering | Read-only and locked-task indicator metadata | ✅ |
| Cost | Assignment-derived cost and parent cost rollups | ✅ |
| History | Structural undo/redo for task hierarchy and dependencies | ✅ |
| Search | Tree-aware search preserving ancestors and descendants | ✅ |
Roadmap Summary
| Priority area | 🚧 work |
|---|---|
| Scheduler product layer | Event model, booking/job/shift terminology, dedicated views, recurrence, exceptions, vertical mode, event layout modes, Scheduler-specific renderers and validation. |
| Enterprise data | Lazy loading, date-range loading, viewport-aware loading, server-side model, real-time adapters, optimistic updates, WebSocket-ready data flow. |
| Collaboration | Presence, comments, audit logs, role-based editability, locking/check-out, conflict resolution, approval hooks. |
| Import/export | Native PDF/PNG export, iCalendar, MS Project-style compatibility layer. CSV export and Excel import/export already come from RevoGrid core/Pro; Gantt adds toolbar helpers, Excel row mapping, print recipe, and JSON project snapshot helpers. |
| Extensibility | Custom dependency renderer, editor forms, scheduling-rule registry, export pipeline. |
| Integrations | Firebase, production server-side templates, headless scheduling engine API/package, packaged Svelte docs/wrapper. REST, GraphQL, and PostgreSQL/Supabase-style examples now exist. |