Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ migrate_working_dir/
.flutter-plugins
.flutter-plugins-dependencies
build/

# Local-only — Claude Code config and reference docs, not part of the package.
.claude/
doc/timeline-flutter-port/
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,56 @@ GanttActivity(
)
```

#### Extending with your own data (status, priority, assignee, checklist rows...)

`flutter_gantt` stays fully generic — it has no concept of a task's status, priority, or
assignee. Two extension points let an app add those without forking the package; the package
itself never reads either, it just carries them through to your own rendering code.

**1. Attach your own data via `GanttActivity<T>.data`**

```dart
// Your own type — the package never inspects it. A record works fine, so
// does a class.
typedef TaskMeta = ({TaskStatus status, TaskPriority? priority, User assignee});

GanttActivity(
key: 'task1',
start: DateTime.now(),
end: DateTime.now().add(const Duration(days: 5)),
title: 'Design review',
data: (status: TaskStatus.inProgress, priority: TaskPriority.high, assignee: currentUser),
)
```

**2. Read it back in a `GanttListColumn.cellBuilder`**

```dart
Gantt(
listColumns: [
GanttListColumn(header: 'Task', flex: 3, cellBuilder: (context, a) => Text(a.title ?? '')),
GanttListColumn(
header: 'Status',
cellBuilder: (context, a) {
final meta = a.data as TaskMeta?;
return meta == null ? const SizedBox.shrink() : StatusGlyph(meta.status);
},
),
],
)
```

Every `cellBuilder`/`builder` you supply receives the plain `GanttActivity` — casting
`activity.data as YourType?` is how you get your fields back. The same `data` payload also
drives per-activity styling if you want it to (e.g. a `colorResolver` that picks a bar color
from `activity.data`).

The same idea makes a "checklist row" work: set `showCell: false` on an activity and supply
`titleWidget:` (a checkbox + name, say) instead of `title:` — the row keeps its dates (for
dependency arrows/group capsules) but renders as plain content instead of a bar, and can't be
dragged. See `example/lib/main.dart`'s `SubitemChecklistTitle`/`TaskMeta`/`User` for a
complete, runnable version of both patterns.

#### ISO Weeks

```dart
Expand Down
Binary file added assets/fonts/Montserrat-Black-w900.ttf
Binary file not shown.
Binary file added assets/fonts/Montserrat-Bold-w700.ttf
Binary file not shown.
Binary file added assets/fonts/Montserrat-Extra-Bold-w800.ttf
Binary file not shown.
Binary file added assets/fonts/Montserrat-Extra-Light-w200.ttf
Binary file not shown.
Binary file added assets/fonts/Montserrat-Light-w300.ttf
Binary file not shown.
Binary file added assets/fonts/Montserrat-Medium-w500.ttf
Binary file not shown.
Binary file added assets/fonts/Montserrat-Regular-w400.ttf
Binary file not shown.
Binary file added assets/fonts/Montserrat-Semi-Bold-w600.ttf
Binary file not shown.
Binary file added assets/fonts/Montserrat-Thin-w100.ttf
Binary file not shown.
16 changes: 16 additions & 0 deletions assets/icons/task-level-0.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions assets/icons/task-level-1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions assets/icons/task-level-2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
156 changes: 156 additions & 0 deletions example/demo_activities.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
{
"meta": {
"generatedFrom": "example/lib/main.dart (_MyHomePageState.initState)",
"referenceDate": "2026-08-25",
"note": "Dates below are computed from 'now' = referenceDate, matching the Duration offsets in the Dart source (now-3, now+6, monthAgo-3, etc.)."
},
"activities": [
{
"key": "task1",
"title": "Main Task",
"tooltip": "WO-1001 | Top-level task across multiple days",
"start": "2026-08-22",
"end": "2026-08-31",
"status": "inProgress",
"priority": "high",
"assigneeName": "Nguyễn Văn A",
"orderId": "1", //sắp xếp thứ tự cùng level (sắp xếp bên thanh timeline)
"children": [
{
"key": "task1.sub2",
"title": "Subtask 2",
"tooltip": "WO-1001-2 | Subtask with nested children",
"start": "2026-08-25",
"end": "2026-08-30",
"dependsOn": ["task1.sub1"],
"status": "inProgress",
"priority": "medium",
"assigneeName": "Trần Thị B",
"actions": ["addNested"],
"children": [
{
"key": "task1.sub2.subA",
"title": "Nested Subtask A",
"tooltip": "WO-1001-2A | Second-level task",
"start": "2026-08-26",
"end": "2026-08-28",
"showCell": false,
"status": "completed",
"priority": null,
"assigneeName": "Trần Thị B"
},
{
"key": "task1.sub2.subB",
"title": "Nested Subtask B",
"tooltip": "WO-1001-2B | Continued",
"start": "2026-08-27",
"end": "2026-08-29",
"showCell": false,
"status": "notStarted",
"priority": null,
"assigneeName": "Lê Văn C"
},
{
"key": "task1.sub2.subC",
"title": "Nested Subtask C",
"tooltip": "WO-1001-2B | Continued",
"start": "2026-08-27",
"end": "2026-08-29",
"showCell": false,
"status": "notStarted",
"priority": null,
"assigneeName": "Lê Văn D"
}
]
},
{
"key": "task1.sub3",
"title": "Subtask 3",
"tooltip": "WO-1001-2 | Subtask with nested children",
"start": "2026-08-25",
"end": "2026-08-30",
"dependsOn": ["task1.sub1"],
"status": "notStarted",
"priority": "low",
"assigneeName": "Lê Văn C",
"actions": ["addNested"],
"children": [
{
"key": "task1.sub3.subA",
"title": "Nested Subtask A3",
"tooltip": "WO-1001-2A | Second-level task",
"start": "2026-08-26",
"end": "2026-08-28",
"showCell": false,
"status": "notStarted",
"priority": null,
"assigneeName": "Lê Văn C"
},
{
"key": "task1.sub3.subB",
"title": "Nested Subtask B3",
"tooltip": "WO-1001-2B | Continued",
"start": "2026-08-27",
"end": "2026-08-29",
"showCell": false,
"status": "notStarted",
"priority": null,
"assigneeName": "Phạm Thị D"
}
]
}
]
},
{
"key": "task2",
"title": "Independent Task",
"tooltip": "A separate task",
"start": "2026-08-26",
"end": "2026-09-02",
"status": "inProgress",
"priority": "medium",
"assigneeName": "Huỳnh Thị Phương"
},
{
"key": "task3",
"title": "Archived Task",
"tooltip": "Task from one month ago",
"start": "2026-07-23",
"end": "2026-07-29",
"status": "completed",
"priority": null,
"assigneeName": "Nguyễn Văn A"
},
{
"key": "task4",
"title": "Older Task",
"tooltip": "Past task",
"start": "2026-08-15",
"end": "2026-08-21",
"progress": 1.0,
"status": "completed",
"priority": "low",
"assigneeName": "Trần Thị B"
},
{
"key": "task5",
"title": "Planned Future Task",
"tooltip": "Future scheduled task",
"start": "2026-09-19",
"end": "2026-09-26",
"status": "notStarted",
"priority": "high",
"assigneeName": "Lê Văn C"
},
{
"key": "task6",
"title": "Ongoing Project [Long task] Lorem ipsum dolor sit amet consectetur adipiscing elit quisque faucibus ex sapien vitae pellentesque sem placerat in id cursus mi pretium tellus duis convallis tempus leo eu aenean sed diam.",
"tooltip": "Spanning multiple weeks",
"start": "2026-08-15",
"end": "2026-09-24",
"status": "overdue",
"priority": "high",
"assigneeName": "Phạm Thị D"
}
]
}
Binary file added example/flutter_01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading