@industry-theme/backlogmd-kanban-panel 1.0.21 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/panels/KanbanPanel.d.ts.map +1 -1
- package/dist/panels/KanbanPanel.stories.d.ts.map +1 -1
- package/dist/panels/MilestonePanel.stories.d.ts.map +1 -1
- package/dist/panels/kanban/components/KanbanColumn.d.ts.map +1 -1
- package/dist/panels/kanban/hooks/useKanbanData.d.ts +15 -25
- package/dist/panels/kanban/hooks/useKanbanData.d.ts.map +1 -1
- package/dist/panels/kanban/mocks/mockData.d.ts +1 -1
- package/dist/panels/kanban/mocks/mockData.d.ts.map +1 -1
- package/dist/panels.bundle.js +103 -228
- package/dist/panels.bundle.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KanbanPanel.d.ts","sourceRoot":"","sources":["../../src/panels/KanbanPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyD,MAAM,OAAO,CAAC;AAc9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAYpD;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"KanbanPanel.d.ts","sourceRoot":"","sources":["../../src/panels/KanbanPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyD,MAAM,OAAO,CAAC;AAc9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAYpD;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAserD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KanbanPanel.stories.d.ts","sourceRoot":"","sources":["../../src/panels/KanbanPanel.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAW5D,QAAA,MAAM,IAAI;;;;;;;;;;;;CAkB0B,CAAC;AAErC,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"KanbanPanel.stories.d.ts","sourceRoot":"","sources":["../../src/panels/KanbanPanel.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAW5D,QAAA,MAAM,IAAI;;;;;;;;;;;;CAkB0B,CAAC;AAErC,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AA2InC,eAAO,MAAM,UAAU,EAAE,KA0BxB,CAAC;AAKF,eAAO,MAAM,YAAY,EAAE,KAc1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MilestonePanel.stories.d.ts","sourceRoot":"","sources":["../../src/panels/MilestonePanel.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAU5D,QAAA,MAAM,IAAI;;;;;;;;;;;;CAkB6B,CAAC;AAExC,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"MilestonePanel.stories.d.ts","sourceRoot":"","sources":["../../src/panels/MilestonePanel.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAU5D,QAAA,MAAM,IAAI;;;;;;;;;;;;CAkB6B,CAAC;AAExC,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAwLnC,eAAO,MAAM,UAAU,EAAE,KAyBxB,CAAC;AAKF,eAAO,MAAM,cAAc,EAAE,KAa5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KanbanColumn.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/components/KanbanColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,UAAU,iBAAiB;IACzB,mDAAmD;IACnD,QAAQ,EAAE,YAAY,CAAC;IACvB,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACnC,sEAAsE;IACtE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"KanbanColumn.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/components/KanbanColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,UAAU,iBAAiB;IACzB,mDAAmD;IACnD,QAAQ,EAAE,YAAY,CAAC;IACvB,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACnC,sEAAsE;IACtE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAqKpD,CAAC"}
|
|
@@ -7,14 +7,10 @@ export interface ColumnState {
|
|
|
7
7
|
hasMore: boolean;
|
|
8
8
|
isLoadingMore: boolean;
|
|
9
9
|
}
|
|
10
|
-
/**
|
|
11
|
-
export type
|
|
12
|
-
/** Status column names (for 3-column view) */
|
|
13
|
-
export type StatusColumn = 'todo' | 'in-progress' | 'completed';
|
|
10
|
+
/** Status column names */
|
|
11
|
+
export type StatusColumn = 'todo' | 'in-progress' | 'done';
|
|
14
12
|
/** Display labels for status columns */
|
|
15
13
|
export declare const STATUS_DISPLAY_LABELS: Record<StatusColumn, string>;
|
|
16
|
-
/** Display labels for source columns (legacy) */
|
|
17
|
-
export declare const SOURCE_DISPLAY_LABELS: Record<SourceColumn, string>;
|
|
18
14
|
/** Status-based column state (computed from source data) */
|
|
19
15
|
export interface StatusColumnState {
|
|
20
16
|
tasks: Task[];
|
|
@@ -29,26 +25,23 @@ export interface ActiveTasksState {
|
|
|
29
25
|
}
|
|
30
26
|
export interface UseKanbanDataResult {
|
|
31
27
|
tasks: Task[];
|
|
32
|
-
/** Source columns: "tasks" and "completed" */
|
|
33
|
-
sources: SourceColumn[];
|
|
34
28
|
isLoading: boolean;
|
|
35
29
|
error: string | null;
|
|
36
30
|
isBacklogProject: boolean;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
loadMore: (source: SourceColumn) => Promise<void>;
|
|
31
|
+
/** Per-status column pagination state */
|
|
32
|
+
columnStates: Map<StatusColumn, ColumnState>;
|
|
33
|
+
/** Load more tasks for a specific status column */
|
|
34
|
+
loadMore: (status: StatusColumn) => Promise<void>;
|
|
42
35
|
refreshData: () => Promise<void>;
|
|
43
36
|
updateTaskStatus: (taskId: string, newStatus: string) => Promise<void>;
|
|
44
|
-
/** Status columns
|
|
37
|
+
/** Status columns: To Do, In Progress, Done */
|
|
45
38
|
statusColumns: StatusColumn[];
|
|
46
|
-
/** Tasks grouped by status (To Do, In Progress,
|
|
39
|
+
/** Tasks grouped by status (To Do, In Progress, Done) */
|
|
47
40
|
tasksByStatus: Map<StatusColumn, StatusColumnState>;
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
/** Load more
|
|
51
|
-
|
|
41
|
+
/** Total tasks pagination state */
|
|
42
|
+
totalTasksState: ActiveTasksState;
|
|
43
|
+
/** Load more tasks */
|
|
44
|
+
loadMoreTasks: () => Promise<void>;
|
|
52
45
|
/** Move task to a new status column (optimistic update - no persistence) */
|
|
53
46
|
moveTaskOptimistic: (taskId: string, toColumn: StatusColumn) => void;
|
|
54
47
|
/** Find a task by ID */
|
|
@@ -61,17 +54,14 @@ export interface UseKanbanDataResult {
|
|
|
61
54
|
interface UseKanbanDataOptions {
|
|
62
55
|
context?: PanelContextValue;
|
|
63
56
|
actions?: PanelActions;
|
|
64
|
-
/** Number of
|
|
57
|
+
/** Number of tasks to load per page (default: 20) */
|
|
65
58
|
tasksLimit?: number;
|
|
66
|
-
/** Number of completed tasks to load (default: 5) */
|
|
67
|
-
completedLimit?: number;
|
|
68
59
|
}
|
|
69
60
|
/**
|
|
70
61
|
* Hook for managing kanban board data with lazy loading
|
|
71
62
|
*
|
|
72
|
-
* Uses
|
|
73
|
-
* Only loads
|
|
74
|
-
* Completed tasks are sorted by ID descending (most recent first).
|
|
63
|
+
* Uses 3-column view based on task status: To Do, In Progress, Done.
|
|
64
|
+
* Only loads tasks from the tasks/ directory.
|
|
75
65
|
*/
|
|
76
66
|
export declare function useKanbanData(options?: UseKanbanDataOptions): UseKanbanDataResult;
|
|
77
67
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useKanbanData.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/hooks/useKanbanData.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,KAAK,IAAI,EAAwB,MAAM,kBAAkB,CAAC;AAEzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEtE,kCAAkC;AAClC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,
|
|
1
|
+
{"version":3,"file":"useKanbanData.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/hooks/useKanbanData.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,KAAK,IAAI,EAAwB,MAAM,kBAAkB,CAAC;AAEzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEtE,kCAAkC;AAClC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,0BAA0B;AAC1B,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,aAAa,GAAG,MAAM,CAAC;AAE3D,wCAAwC;AACxC,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAI9D,CAAC;AAgBF,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,oCAAoC;AACpC,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,yCAAyC;IACzC,YAAY,EAAE,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAC7C,mDAAmD;IACnD,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,+CAA+C;IAC/C,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,yDAAyD;IACzD,aAAa,EAAE,GAAG,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;IACpD,mCAAmC;IACnC,eAAe,EAAE,gBAAgB,CAAC;IAClC,sBAAsB;IACtB,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,4EAA4E;IAC5E,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IACrE,wBAAwB;IACxB,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,SAAS,CAAC;IAClD,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACnB;AAED,UAAU,oBAAoB;IAC5B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,mBAAmB,CAqXrB"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import type { Task } from '@backlog-md/core';
|
|
8
8
|
/**
|
|
9
9
|
* Generate mock tasks for testing the kanban board
|
|
10
|
-
* Creates
|
|
10
|
+
* Creates 30 tasks with evenly distributed statuses (To Do, In Progress, Done)
|
|
11
11
|
*/
|
|
12
12
|
export declare function generateMockTasks(): Task[];
|
|
13
13
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockData.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/mocks/mockData.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"mockData.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/mocks/mockData.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAiE7C;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,EAAE,CA6B1C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C;AAED;;GAEG;AACH,wBAAgB,kBAAkB;;;;;;;;;;;;EAcjC"}
|
package/dist/panels.bundle.js
CHANGED
|
@@ -5866,35 +5866,32 @@ class PanelFileSystemAdapter {
|
|
|
5866
5866
|
const STATUS_DISPLAY_LABELS = {
|
|
5867
5867
|
"todo": "To Do",
|
|
5868
5868
|
"in-progress": "In Progress",
|
|
5869
|
-
"
|
|
5869
|
+
"done": "Done"
|
|
5870
5870
|
};
|
|
5871
5871
|
const COLUMN_TO_STATUS = {
|
|
5872
5872
|
"todo": "To Do",
|
|
5873
5873
|
"in-progress": "In Progress",
|
|
5874
|
-
"
|
|
5874
|
+
"done": "Done"
|
|
5875
5875
|
};
|
|
5876
|
-
const DEFAULT_SOURCES = ["tasks", "completed"];
|
|
5877
5876
|
const DEFAULT_TASKS_LIMIT = 20;
|
|
5878
|
-
const DEFAULT_COMPLETED_LIMIT = 5;
|
|
5879
5877
|
function useKanbanData(options) {
|
|
5880
5878
|
const {
|
|
5881
5879
|
context,
|
|
5882
5880
|
actions,
|
|
5883
|
-
tasksLimit = DEFAULT_TASKS_LIMIT
|
|
5884
|
-
completedLimit = DEFAULT_COMPLETED_LIMIT
|
|
5881
|
+
tasksLimit = DEFAULT_TASKS_LIMIT
|
|
5885
5882
|
} = options || {};
|
|
5886
5883
|
const [tasks, setTasks] = useState([]);
|
|
5887
|
-
const [sources] = useState(DEFAULT_SOURCES);
|
|
5888
5884
|
const [isLoading, setIsLoading] = useState(true);
|
|
5889
5885
|
const [error, setError] = useState(null);
|
|
5890
5886
|
const [isBacklogProject, setIsBacklogProject] = useState(false);
|
|
5891
5887
|
const [canWrite, setCanWrite] = useState(false);
|
|
5892
|
-
const [tasksBySource, setTasksBySource] = useState(
|
|
5893
|
-
/* @__PURE__ */ new Map()
|
|
5894
|
-
);
|
|
5895
5888
|
const [columnStates, setColumnStates] = useState(
|
|
5896
5889
|
/* @__PURE__ */ new Map()
|
|
5897
5890
|
);
|
|
5891
|
+
const [totalLoaded, setTotalLoaded] = useState(0);
|
|
5892
|
+
const [totalCount, setTotalCount] = useState(0);
|
|
5893
|
+
const [hasMore, setHasMore] = useState(false);
|
|
5894
|
+
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
|
5898
5895
|
const coreRef = useRef(null);
|
|
5899
5896
|
const activeFilePathRef = useRef(null);
|
|
5900
5897
|
const contextRef = useRef(context);
|
|
@@ -5924,13 +5921,27 @@ function useKanbanData(options) {
|
|
|
5924
5921
|
}
|
|
5925
5922
|
}, []);
|
|
5926
5923
|
const fileTreeVersionRef = useRef(null);
|
|
5924
|
+
const buildColumnStates = useCallback((allTasks) => {
|
|
5925
|
+
const statusColumns2 = ["todo", "in-progress", "done"];
|
|
5926
|
+
const newColumnStates = /* @__PURE__ */ new Map();
|
|
5927
|
+
for (const column of statusColumns2) {
|
|
5928
|
+
const status = COLUMN_TO_STATUS[column];
|
|
5929
|
+
const columnTasks = allTasks.filter((t) => t.status === status);
|
|
5930
|
+
newColumnStates.set(column, {
|
|
5931
|
+
tasks: columnTasks,
|
|
5932
|
+
total: columnTasks.length,
|
|
5933
|
+
hasMore: false,
|
|
5934
|
+
isLoadingMore: false
|
|
5935
|
+
});
|
|
5936
|
+
}
|
|
5937
|
+
return newColumnStates;
|
|
5938
|
+
}, []);
|
|
5927
5939
|
const loadBacklogData = useCallback(async () => {
|
|
5928
5940
|
var _a, _b, _c;
|
|
5929
5941
|
if (!context || !actions) {
|
|
5930
5942
|
console.log("[useKanbanData] No context provided");
|
|
5931
5943
|
setIsBacklogProject(false);
|
|
5932
5944
|
setTasks([]);
|
|
5933
|
-
setTasksBySource(/* @__PURE__ */ new Map());
|
|
5934
5945
|
setColumnStates(/* @__PURE__ */ new Map());
|
|
5935
5946
|
setIsLoading(false);
|
|
5936
5947
|
coreRef.current = null;
|
|
@@ -5942,7 +5953,6 @@ function useKanbanData(options) {
|
|
|
5942
5953
|
console.log("[useKanbanData] FileTree not available");
|
|
5943
5954
|
setIsBacklogProject(false);
|
|
5944
5955
|
setTasks([]);
|
|
5945
|
-
setTasksBySource(/* @__PURE__ */ new Map());
|
|
5946
5956
|
setColumnStates(/* @__PURE__ */ new Map());
|
|
5947
5957
|
coreRef.current = null;
|
|
5948
5958
|
fileTreeVersionRef.current = null;
|
|
@@ -5973,7 +5983,6 @@ function useKanbanData(options) {
|
|
|
5973
5983
|
console.log("[useKanbanData] Not a Backlog.md project");
|
|
5974
5984
|
setIsBacklogProject(false);
|
|
5975
5985
|
setTasks([]);
|
|
5976
|
-
setTasksBySource(/* @__PURE__ */ new Map());
|
|
5977
5986
|
setColumnStates(/* @__PURE__ */ new Map());
|
|
5978
5987
|
coreRef.current = null;
|
|
5979
5988
|
return;
|
|
@@ -5983,133 +5992,74 @@ function useKanbanData(options) {
|
|
|
5983
5992
|
setCanWrite(fs.canWrite);
|
|
5984
5993
|
await core2.initializeLazy(filePaths);
|
|
5985
5994
|
coreRef.current = core2;
|
|
5986
|
-
const paginatedResult = await core2.
|
|
5987
|
-
tasksLimit,
|
|
5988
|
-
|
|
5989
|
-
offset: 0,
|
|
5990
|
-
tasksSortDirection: "asc",
|
|
5991
|
-
completedSortByIdDesc: true
|
|
5995
|
+
const paginatedResult = await core2.loadMoreForSource("tasks", 0, {
|
|
5996
|
+
limit: tasksLimit,
|
|
5997
|
+
sortDirection: "asc"
|
|
5992
5998
|
});
|
|
5993
|
-
const
|
|
5994
|
-
const
|
|
5995
|
-
let allTasks = [];
|
|
5996
|
-
for (const source2 of paginatedResult.sources) {
|
|
5997
|
-
const columnResult = paginatedResult.bySource.get(source2);
|
|
5998
|
-
if (columnResult) {
|
|
5999
|
-
newTasksBySource.set(source2, columnResult.items);
|
|
6000
|
-
newColumnStates.set(source2, {
|
|
6001
|
-
tasks: columnResult.items,
|
|
6002
|
-
total: columnResult.total,
|
|
6003
|
-
hasMore: columnResult.hasMore,
|
|
6004
|
-
isLoadingMore: false
|
|
6005
|
-
});
|
|
6006
|
-
allTasks = allTasks.concat(columnResult.items);
|
|
6007
|
-
} else {
|
|
6008
|
-
newTasksBySource.set(source2, []);
|
|
6009
|
-
newColumnStates.set(source2, {
|
|
6010
|
-
tasks: [],
|
|
6011
|
-
total: 0,
|
|
6012
|
-
hasMore: false,
|
|
6013
|
-
isLoadingMore: false
|
|
6014
|
-
});
|
|
6015
|
-
}
|
|
6016
|
-
}
|
|
6017
|
-
const totalTasks = Array.from(paginatedResult.bySource.values()).reduce(
|
|
6018
|
-
(sum, col) => sum + col.total,
|
|
6019
|
-
0
|
|
6020
|
-
);
|
|
5999
|
+
const allTasks = paginatedResult.items;
|
|
6000
|
+
const total = paginatedResult.total;
|
|
6021
6001
|
console.log(
|
|
6022
|
-
`[useKanbanData] Loaded ${allTasks.length}/${
|
|
6002
|
+
`[useKanbanData] Loaded ${allTasks.length}/${total} tasks`
|
|
6023
6003
|
);
|
|
6024
6004
|
fileTreeVersionRef.current = currentVersion;
|
|
6005
|
+
const newColumnStates = buildColumnStates(allTasks);
|
|
6025
6006
|
setTasks(allTasks);
|
|
6026
|
-
setTasksBySource(newTasksBySource);
|
|
6027
6007
|
setColumnStates(newColumnStates);
|
|
6008
|
+
setTotalLoaded(allTasks.length);
|
|
6009
|
+
setTotalCount(total);
|
|
6010
|
+
setHasMore(paginatedResult.hasMore);
|
|
6028
6011
|
} catch (err) {
|
|
6029
6012
|
console.error("[useKanbanData] Failed to load Backlog.md data:", err);
|
|
6030
6013
|
setError(err instanceof Error ? err.message : "Failed to load backlog data");
|
|
6031
6014
|
setIsBacklogProject(false);
|
|
6032
6015
|
setTasks([]);
|
|
6033
|
-
setTasksBySource(/* @__PURE__ */ new Map());
|
|
6034
6016
|
setColumnStates(/* @__PURE__ */ new Map());
|
|
6035
6017
|
coreRef.current = null;
|
|
6036
6018
|
fileTreeVersionRef.current = null;
|
|
6037
6019
|
} finally {
|
|
6038
6020
|
setIsLoading(false);
|
|
6039
6021
|
}
|
|
6040
|
-
}, [context, actions, fetchFileContent, tasksLimit,
|
|
6022
|
+
}, [context, actions, fetchFileContent, tasksLimit, buildColumnStates]);
|
|
6041
6023
|
useEffect(() => {
|
|
6042
6024
|
loadBacklogData();
|
|
6043
6025
|
}, [loadBacklogData]);
|
|
6044
|
-
const
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
if (state) {
|
|
6059
|
-
newStates.set(source2, { ...state, isLoadingMore: true });
|
|
6060
|
-
}
|
|
6061
|
-
return newStates;
|
|
6026
|
+
const loadMoreTasks = useCallback(async () => {
|
|
6027
|
+
const core2 = coreRef.current;
|
|
6028
|
+
if (!core2) {
|
|
6029
|
+
console.warn("[useKanbanData] Core not available for loadMore");
|
|
6030
|
+
return;
|
|
6031
|
+
}
|
|
6032
|
+
if (!hasMore || isLoadingMore) {
|
|
6033
|
+
return;
|
|
6034
|
+
}
|
|
6035
|
+
setIsLoadingMore(true);
|
|
6036
|
+
try {
|
|
6037
|
+
const result = await core2.loadMoreForSource("tasks", totalLoaded, {
|
|
6038
|
+
limit: tasksLimit,
|
|
6039
|
+
sortDirection: "asc"
|
|
6062
6040
|
});
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
newStates.set(source2, {
|
|
6084
|
-
tasks: newTasks,
|
|
6085
|
-
total: result.total,
|
|
6086
|
-
hasMore: result.hasMore,
|
|
6087
|
-
isLoadingMore: false
|
|
6088
|
-
});
|
|
6089
|
-
}
|
|
6090
|
-
return newStates;
|
|
6091
|
-
});
|
|
6092
|
-
setTasksBySource((prev) => {
|
|
6093
|
-
const newMap = new Map(prev);
|
|
6094
|
-
const currentTasks = newMap.get(source2) || [];
|
|
6095
|
-
newMap.set(source2, [...currentTasks, ...result.items]);
|
|
6096
|
-
return newMap;
|
|
6097
|
-
});
|
|
6098
|
-
setTasks((prev) => [...prev, ...result.items]);
|
|
6099
|
-
} catch (err) {
|
|
6100
|
-
console.error(`[useKanbanData] Failed to load more for "${source2}":`, err);
|
|
6101
|
-
setError(err instanceof Error ? err.message : "Failed to load more tasks");
|
|
6102
|
-
setColumnStates((prev) => {
|
|
6103
|
-
const newStates = new Map(prev);
|
|
6104
|
-
const state = newStates.get(source2);
|
|
6105
|
-
if (state) {
|
|
6106
|
-
newStates.set(source2, { ...state, isLoadingMore: false });
|
|
6107
|
-
}
|
|
6108
|
-
return newStates;
|
|
6109
|
-
});
|
|
6110
|
-
}
|
|
6041
|
+
console.log(
|
|
6042
|
+
`[useKanbanData] Loaded ${result.items.length} more tasks (${totalLoaded + result.items.length}/${result.total})`
|
|
6043
|
+
);
|
|
6044
|
+
const newTasks = [...tasks, ...result.items];
|
|
6045
|
+
setTasks(newTasks);
|
|
6046
|
+
setTotalLoaded(newTasks.length);
|
|
6047
|
+
setTotalCount(result.total);
|
|
6048
|
+
setHasMore(result.hasMore);
|
|
6049
|
+
const newColumnStates = buildColumnStates(newTasks);
|
|
6050
|
+
setColumnStates(newColumnStates);
|
|
6051
|
+
} catch (err) {
|
|
6052
|
+
console.error("[useKanbanData] Failed to load more tasks:", err);
|
|
6053
|
+
setError(err instanceof Error ? err.message : "Failed to load more tasks");
|
|
6054
|
+
} finally {
|
|
6055
|
+
setIsLoadingMore(false);
|
|
6056
|
+
}
|
|
6057
|
+
}, [tasks, hasMore, isLoadingMore, totalLoaded, tasksLimit, buildColumnStates]);
|
|
6058
|
+
const loadMore = useCallback(
|
|
6059
|
+
async (_status) => {
|
|
6060
|
+
await loadMoreTasks();
|
|
6111
6061
|
},
|
|
6112
|
-
[
|
|
6062
|
+
[loadMoreTasks]
|
|
6113
6063
|
);
|
|
6114
6064
|
const refreshData = useCallback(async () => {
|
|
6115
6065
|
await loadBacklogData();
|
|
@@ -6141,44 +6091,17 @@ function useKanbanData(options) {
|
|
|
6141
6091
|
const moveTaskOptimistic = useCallback(
|
|
6142
6092
|
(taskId, toColumn) => {
|
|
6143
6093
|
const newStatus = COLUMN_TO_STATUS[toColumn];
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
const
|
|
6149
|
-
|
|
6150
|
-
const activeIndex = activeTasks.findIndex((t) => t.id === taskId);
|
|
6151
|
-
if (activeIndex !== -1) {
|
|
6152
|
-
taskToMove = activeTasks[activeIndex];
|
|
6153
|
-
activeTasks.splice(activeIndex, 1);
|
|
6154
|
-
}
|
|
6155
|
-
if (!taskToMove) {
|
|
6156
|
-
const completedIndex = completedTasks.findIndex((t) => t.id === taskId);
|
|
6157
|
-
if (completedIndex !== -1) {
|
|
6158
|
-
taskToMove = completedTasks[completedIndex];
|
|
6159
|
-
completedTasks.splice(completedIndex, 1);
|
|
6160
|
-
}
|
|
6161
|
-
}
|
|
6162
|
-
if (!taskToMove) {
|
|
6163
|
-
console.warn(`[useKanbanData] Task ${taskId} not found for move`);
|
|
6164
|
-
return prev;
|
|
6165
|
-
}
|
|
6166
|
-
const updatedTask = { ...taskToMove, status: newStatus };
|
|
6167
|
-
if (isMovingToCompleted) {
|
|
6168
|
-
completedTasks.unshift(updatedTask);
|
|
6169
|
-
} else {
|
|
6170
|
-
activeTasks.push(updatedTask);
|
|
6171
|
-
}
|
|
6172
|
-
newMap.set("tasks", activeTasks);
|
|
6173
|
-
newMap.set("completed", completedTasks);
|
|
6094
|
+
setTasks((prev) => {
|
|
6095
|
+
const newTasks = prev.map(
|
|
6096
|
+
(t) => t.id === taskId ? { ...t, status: newStatus } : t
|
|
6097
|
+
);
|
|
6098
|
+
const newColumnStates = buildColumnStates(newTasks);
|
|
6099
|
+
setColumnStates(newColumnStates);
|
|
6174
6100
|
console.log(`[useKanbanData] Moved task ${taskId} to ${toColumn} (${newStatus})`);
|
|
6175
|
-
return
|
|
6101
|
+
return newTasks;
|
|
6176
6102
|
});
|
|
6177
|
-
setTasks(
|
|
6178
|
-
(prev) => prev.map((t) => t.id === taskId ? { ...t, status: newStatus } : t)
|
|
6179
|
-
);
|
|
6180
6103
|
},
|
|
6181
|
-
[]
|
|
6104
|
+
[buildColumnStates]
|
|
6182
6105
|
);
|
|
6183
6106
|
const getTaskById = useCallback(
|
|
6184
6107
|
(taskId) => {
|
|
@@ -6186,50 +6109,39 @@ function useKanbanData(options) {
|
|
|
6186
6109
|
},
|
|
6187
6110
|
[tasks]
|
|
6188
6111
|
);
|
|
6189
|
-
const statusColumns = ["todo", "in-progress", "
|
|
6112
|
+
const statusColumns = ["todo", "in-progress", "done"];
|
|
6190
6113
|
const tasksByStatus = (() => {
|
|
6191
6114
|
const result = /* @__PURE__ */ new Map();
|
|
6192
|
-
const
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6115
|
+
for (const column of statusColumns) {
|
|
6116
|
+
const state = columnStates.get(column);
|
|
6117
|
+
result.set(column, {
|
|
6118
|
+
tasks: (state == null ? void 0 : state.tasks) || [],
|
|
6119
|
+
count: (state == null ? void 0 : state.total) || 0
|
|
6120
|
+
});
|
|
6121
|
+
}
|
|
6199
6122
|
return result;
|
|
6200
6123
|
})();
|
|
6201
|
-
const
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
isLoadingMore: (activeColumnState == null ? void 0 : activeColumnState.isLoadingMore) || false
|
|
6208
|
-
};
|
|
6209
|
-
})();
|
|
6210
|
-
const loadMoreActive = useCallback(async () => {
|
|
6211
|
-
await loadMore("tasks");
|
|
6212
|
-
}, [loadMore]);
|
|
6124
|
+
const totalTasksState = {
|
|
6125
|
+
total: totalCount,
|
|
6126
|
+
loaded: totalLoaded,
|
|
6127
|
+
hasMore,
|
|
6128
|
+
isLoadingMore
|
|
6129
|
+
};
|
|
6213
6130
|
return {
|
|
6214
6131
|
tasks,
|
|
6215
|
-
sources,
|
|
6216
6132
|
isLoading,
|
|
6217
6133
|
error,
|
|
6218
6134
|
isBacklogProject,
|
|
6219
|
-
tasksBySource,
|
|
6220
6135
|
columnStates,
|
|
6221
6136
|
loadMore,
|
|
6222
6137
|
refreshData,
|
|
6223
6138
|
updateTaskStatus,
|
|
6224
|
-
// New 3-column view exports
|
|
6225
6139
|
statusColumns,
|
|
6226
6140
|
tasksByStatus,
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
// Drag-and-drop support
|
|
6141
|
+
totalTasksState,
|
|
6142
|
+
loadMoreTasks,
|
|
6230
6143
|
moveTaskOptimistic,
|
|
6231
6144
|
getTaskById,
|
|
6232
|
-
// Write support
|
|
6233
6145
|
canWrite,
|
|
6234
6146
|
core: coreRef.current
|
|
6235
6147
|
};
|
|
@@ -6430,8 +6342,6 @@ const KanbanColumn = ({
|
|
|
6430
6342
|
flex: fullWidth ? "1 1 auto" : "1 1 0",
|
|
6431
6343
|
// Grow to fill available width equally
|
|
6432
6344
|
minWidth: fullWidth ? void 0 : "280px",
|
|
6433
|
-
maxWidth: fullWidth ? void 0 : "500px",
|
|
6434
|
-
// Cap max width for readability
|
|
6435
6345
|
alignSelf: "stretch",
|
|
6436
6346
|
// Fill parent height via flexbox
|
|
6437
6347
|
minHeight: 0,
|
|
@@ -7378,10 +7288,8 @@ const KanbanPanel = ({
|
|
|
7378
7288
|
const {
|
|
7379
7289
|
statusColumns,
|
|
7380
7290
|
tasksByStatus,
|
|
7381
|
-
|
|
7382
|
-
|
|
7383
|
-
activeTasksState,
|
|
7384
|
-
loadMoreActive,
|
|
7291
|
+
totalTasksState,
|
|
7292
|
+
loadMoreTasks,
|
|
7385
7293
|
error,
|
|
7386
7294
|
isBacklogProject,
|
|
7387
7295
|
refreshData,
|
|
@@ -7392,8 +7300,7 @@ const KanbanPanel = ({
|
|
|
7392
7300
|
} = useKanbanData({
|
|
7393
7301
|
context,
|
|
7394
7302
|
actions,
|
|
7395
|
-
tasksLimit: 20
|
|
7396
|
-
completedLimit: 5
|
|
7303
|
+
tasksLimit: 20
|
|
7397
7304
|
});
|
|
7398
7305
|
const handleDragStart = useCallback((event) => {
|
|
7399
7306
|
const { active } = event;
|
|
@@ -7413,7 +7320,7 @@ const KanbanPanel = ({
|
|
|
7413
7320
|
const statusToColumn = {
|
|
7414
7321
|
"To Do": "todo",
|
|
7415
7322
|
"In Progress": "in-progress",
|
|
7416
|
-
"Done": "
|
|
7323
|
+
"Done": "done"
|
|
7417
7324
|
};
|
|
7418
7325
|
const currentColumn = statusToColumn[task.status] || "todo";
|
|
7419
7326
|
if (currentColumn !== targetColumn) {
|
|
@@ -7563,31 +7470,6 @@ const KanbanPanel = ({
|
|
|
7563
7470
|
)
|
|
7564
7471
|
] }),
|
|
7565
7472
|
isBacklogProject && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "16px", flexWrap: "wrap" }, children: [
|
|
7566
|
-
!isNarrowView && /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: statusColumns.map((status) => {
|
|
7567
|
-
const statusState = tasksByStatus.get(status);
|
|
7568
|
-
const count = (statusState == null ? void 0 : statusState.count) || 0;
|
|
7569
|
-
const completedState = columnStates.get("completed");
|
|
7570
|
-
const displayCount = status === "completed" && completedState ? `${count}/${completedState.total}` : count;
|
|
7571
|
-
return /* @__PURE__ */ jsxs(
|
|
7572
|
-
"span",
|
|
7573
|
-
{
|
|
7574
|
-
style: {
|
|
7575
|
-
fontSize: theme2.fontSizes[1],
|
|
7576
|
-
color: theme2.colors.textSecondary,
|
|
7577
|
-
background: theme2.colors.backgroundSecondary,
|
|
7578
|
-
padding: "4px 10px",
|
|
7579
|
-
borderRadius: theme2.radii[1],
|
|
7580
|
-
fontWeight: theme2.fontWeights.medium
|
|
7581
|
-
},
|
|
7582
|
-
children: [
|
|
7583
|
-
STATUS_DISPLAY_LABELS[status],
|
|
7584
|
-
": ",
|
|
7585
|
-
displayCount
|
|
7586
|
-
]
|
|
7587
|
-
},
|
|
7588
|
-
status
|
|
7589
|
-
);
|
|
7590
|
-
}) }),
|
|
7591
7473
|
canWrite && /* @__PURE__ */ jsxs(
|
|
7592
7474
|
"button",
|
|
7593
7475
|
{
|
|
@@ -7612,11 +7494,11 @@ const KanbanPanel = ({
|
|
|
7612
7494
|
]
|
|
7613
7495
|
}
|
|
7614
7496
|
),
|
|
7615
|
-
|
|
7497
|
+
totalTasksState.hasMore && /* @__PURE__ */ jsx(
|
|
7616
7498
|
"button",
|
|
7617
7499
|
{
|
|
7618
|
-
onClick:
|
|
7619
|
-
disabled:
|
|
7500
|
+
onClick: loadMoreTasks,
|
|
7501
|
+
disabled: totalTasksState.isLoadingMore,
|
|
7620
7502
|
style: {
|
|
7621
7503
|
background: theme2.colors.backgroundSecondary,
|
|
7622
7504
|
color: theme2.colors.text,
|
|
@@ -7625,11 +7507,11 @@ const KanbanPanel = ({
|
|
|
7625
7507
|
padding: "6px 12px",
|
|
7626
7508
|
fontSize: theme2.fontSizes[1],
|
|
7627
7509
|
fontWeight: theme2.fontWeights.medium,
|
|
7628
|
-
cursor:
|
|
7629
|
-
opacity:
|
|
7510
|
+
cursor: totalTasksState.isLoadingMore ? "wait" : "pointer",
|
|
7511
|
+
opacity: totalTasksState.isLoadingMore ? 0.7 : 1,
|
|
7630
7512
|
transition: "opacity 0.2s ease"
|
|
7631
7513
|
},
|
|
7632
|
-
children:
|
|
7514
|
+
children: totalTasksState.isLoadingMore ? "Loading..." : `Load more (${totalTasksState.total - totalTasksState.loaded} remaining)`
|
|
7633
7515
|
}
|
|
7634
7516
|
)
|
|
7635
7517
|
] })
|
|
@@ -7758,26 +7640,19 @@ const KanbanPanel = ({
|
|
|
7758
7640
|
style: {
|
|
7759
7641
|
display: "flex",
|
|
7760
7642
|
gap: "16px",
|
|
7761
|
-
|
|
7643
|
+
width: "100%",
|
|
7762
7644
|
paddingBottom: "8px",
|
|
7763
|
-
minWidth: "100%",
|
|
7764
7645
|
alignItems: "stretch"
|
|
7765
7646
|
},
|
|
7766
7647
|
children: statusColumns.filter((status) => !isNarrowView || status === selectedTab).map((status) => {
|
|
7767
7648
|
const statusState = tasksByStatus.get(status);
|
|
7768
7649
|
const columnTasks = (statusState == null ? void 0 : statusState.tasks) || [];
|
|
7769
|
-
const isCompleted = status === "completed";
|
|
7770
|
-
const completedState = columnStates.get("completed");
|
|
7771
7650
|
return /* @__PURE__ */ jsx(
|
|
7772
7651
|
KanbanColumn,
|
|
7773
7652
|
{
|
|
7774
7653
|
columnId: status,
|
|
7775
7654
|
status: STATUS_DISPLAY_LABELS[status],
|
|
7776
7655
|
tasks: columnTasks,
|
|
7777
|
-
total: isCompleted ? completedState == null ? void 0 : completedState.total : void 0,
|
|
7778
|
-
hasMore: isCompleted ? completedState == null ? void 0 : completedState.hasMore : false,
|
|
7779
|
-
isLoadingMore: isCompleted ? completedState == null ? void 0 : completedState.isLoadingMore : false,
|
|
7780
|
-
onLoadMore: isCompleted ? () => loadMore("completed") : void 0,
|
|
7781
7656
|
onTaskClick: handleTaskClick,
|
|
7782
7657
|
fullWidth: isNarrowView
|
|
7783
7658
|
},
|