@object-ui/plugin-gantt 4.0.8 → 4.0.9
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/CHANGELOG.md +11 -0
- package/dist/index.js +211 -203
- package/dist/index.umd.cjs +1 -1
- package/dist/packages/plugin-gantt/src/ObjectGantt.d.ts.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @object-ui/plugin-gantt
|
|
2
2
|
|
|
3
|
+
## 4.0.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @object-ui/types@4.0.9
|
|
8
|
+
- @object-ui/core@4.0.9
|
|
9
|
+
- @object-ui/react@4.0.9
|
|
10
|
+
- @object-ui/components@4.0.9
|
|
11
|
+
- @object-ui/fields@4.0.9
|
|
12
|
+
- @object-ui/plugin-detail@4.0.9
|
|
13
|
+
|
|
3
14
|
## 4.0.8
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -4,28 +4,29 @@ import { ComponentRegistry as a, buildExpandFields as o, extractRecords as s } f
|
|
|
4
4
|
import { useNavigationOverlay as c, useSchemaContext as l } from "@object-ui/react";
|
|
5
5
|
import { GanttConfigSchema as u } from "@objectstack/spec/ui";
|
|
6
6
|
import { RecordDetailDrawer as d, deriveRecordPageHref as f } from "@object-ui/plugin-detail";
|
|
7
|
-
import { AlertDialog as p, AlertDialogAction as m, AlertDialogCancel as
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { AlertDialog as p, AlertDialogAction as m, AlertDialogCancel as h, AlertDialogContent as ee, AlertDialogDescription as g, AlertDialogFooter as _, AlertDialogHeader as v, AlertDialogTitle as y, Button as b, cn as x, useResizeObserver as S } from "@object-ui/components";
|
|
8
|
+
import { getSemanticColorName as C, getSemanticHex as w } from "@object-ui/fields";
|
|
9
|
+
import { CalendarDays as T, ChevronLeft as E, ChevronRight as D, PanelLeft as O, PanelLeftClose as te, ZoomIn as k, ZoomOut as ne } from "lucide-react";
|
|
10
|
+
import { Fragment as A, jsx as j, jsxs as M } from "react/jsx-runtime";
|
|
10
11
|
//#region src/GanttView.tsx
|
|
11
|
-
function
|
|
12
|
+
function N(e) {
|
|
12
13
|
return e < 640 ? 35 : e < 1024 ? 50 : 60;
|
|
13
14
|
}
|
|
14
|
-
function
|
|
15
|
+
function P(e) {
|
|
15
16
|
return e < 640 ? 140 : e < 1024 ? 220 : 320;
|
|
16
17
|
}
|
|
17
|
-
function
|
|
18
|
+
function F(e) {
|
|
18
19
|
return e >= 280;
|
|
19
20
|
}
|
|
20
|
-
function
|
|
21
|
+
function I(e) {
|
|
21
22
|
return e < 640 ? 32 : 40;
|
|
22
23
|
}
|
|
23
|
-
function
|
|
24
|
-
let [c, l] = e.useState(/* @__PURE__ */ new Date()), u = e.useRef(null), { width: d } =
|
|
24
|
+
function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a, className: o, inlineEdit: s = !1 }) {
|
|
25
|
+
let [c, l] = e.useState(/* @__PURE__ */ new Date()), u = e.useRef(null), { width: d } = S(u), f = d || (typeof window < "u" ? window.innerWidth : 1024), p = f < 640, m = I(f), h = N(f), [ee, g] = e.useState(null), _ = ee ?? h, [v, y] = e.useState(!1), C = e.useRef(!1);
|
|
25
26
|
e.useEffect(() => {
|
|
26
|
-
!
|
|
27
|
+
!C.current && p && (y(!0), C.current = !0);
|
|
27
28
|
}, [p]);
|
|
28
|
-
let
|
|
29
|
+
let w = v ? 0 : P(f), L = F(w), [re, R] = e.useState(null), [z, B] = e.useState({}), [V, H] = e.useState(null), U = e.useRef(null);
|
|
29
30
|
e.useEffect(() => {
|
|
30
31
|
U.current = V;
|
|
31
32
|
}, [V]);
|
|
@@ -41,7 +42,7 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
41
42
|
let e = (e) => {
|
|
42
43
|
let t = U.current;
|
|
43
44
|
if (!t) return;
|
|
44
|
-
let n = Math.round((e.clientX - t.originClientX) / Math.max(
|
|
45
|
+
let n = Math.round((e.clientX - t.originClientX) / Math.max(_, 1));
|
|
45
46
|
n !== t.dayDelta && H({
|
|
46
47
|
...t,
|
|
47
48
|
dayDelta: n
|
|
@@ -70,7 +71,7 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
70
71
|
};
|
|
71
72
|
}, [
|
|
72
73
|
V,
|
|
73
|
-
|
|
74
|
+
_,
|
|
74
75
|
t,
|
|
75
76
|
a,
|
|
76
77
|
G
|
|
@@ -107,21 +108,21 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
107
108
|
let t = e.touches[0].clientX - e.touches[1].clientX, n = e.touches[0].clientY - e.touches[1].clientY;
|
|
108
109
|
Q.current = {
|
|
109
110
|
baseDistance: Math.max(1, Math.sqrt(t * t + n * n)),
|
|
110
|
-
baseColumn:
|
|
111
|
+
baseColumn: _
|
|
111
112
|
};
|
|
112
113
|
}
|
|
113
|
-
}, [
|
|
114
|
+
}, [_]), oe = e.useCallback((e) => {
|
|
114
115
|
if (e.touches.length !== 2 || !Q.current) return;
|
|
115
116
|
let t = e.touches[0].clientX - e.touches[1].clientX, n = e.touches[0].clientY - e.touches[1].clientY, r = Math.max(1, Math.sqrt(t * t + n * n)) / Q.current.baseDistance;
|
|
116
|
-
|
|
117
|
+
g(Math.max(15, Math.min(120, Math.round(Q.current.baseColumn * r))));
|
|
117
118
|
}, []), se = e.useCallback(() => {
|
|
118
119
|
Q.current = null;
|
|
119
120
|
}, []), $ = e.useMemo(() => {
|
|
120
121
|
let e = /* @__PURE__ */ new Date();
|
|
121
122
|
if (e < q.start || e > q.end) return null;
|
|
122
123
|
let t = (e.getTime() - q.start.getTime()) / (1440 * 60 * 1e3);
|
|
123
|
-
return Math.round(t *
|
|
124
|
-
}, [q,
|
|
124
|
+
return Math.round(t * _);
|
|
125
|
+
}, [q, _]), ce = e.useCallback(() => {
|
|
125
126
|
if ($ == null || !Z.current) return;
|
|
126
127
|
let e = Math.max(0, $ - Z.current.clientWidth / 2);
|
|
127
128
|
Z.current.scrollTo({
|
|
@@ -132,35 +133,35 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
132
133
|
Y.current && (Y.current.scrollLeft = e.currentTarget.scrollLeft), X.current && (X.current.scrollTop = e.currentTarget.scrollTop);
|
|
133
134
|
}, ue = (e) => {
|
|
134
135
|
q.end.getTime() - q.start.getTime();
|
|
135
|
-
let t =
|
|
136
|
+
let t = _, n = 1e3 * 60 * 60 * 24, r = e.start.getTime() - q.start.getTime(), i = e.end.getTime() - e.start.getTime();
|
|
136
137
|
return {
|
|
137
138
|
left: r / n * t,
|
|
138
139
|
width: Math.max(i / n * t, t)
|
|
139
140
|
};
|
|
140
141
|
};
|
|
141
|
-
return /* @__PURE__ */
|
|
142
|
+
return /* @__PURE__ */ M("div", {
|
|
142
143
|
ref: u,
|
|
143
|
-
className:
|
|
144
|
-
children: [/* @__PURE__ */
|
|
144
|
+
className: x("flex flex-col h-full bg-background overflow-hidden min-w-0", o),
|
|
145
|
+
children: [/* @__PURE__ */ M("div", {
|
|
145
146
|
className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 p-2 border-b bg-card",
|
|
146
|
-
children: [/* @__PURE__ */
|
|
147
|
+
children: [/* @__PURE__ */ M("div", {
|
|
147
148
|
className: "flex items-center gap-2",
|
|
148
149
|
children: [
|
|
149
|
-
/* @__PURE__ */
|
|
150
|
+
/* @__PURE__ */ j(b, {
|
|
150
151
|
variant: "ghost",
|
|
151
152
|
size: "icon",
|
|
152
153
|
className: "h-8 w-8",
|
|
153
154
|
"aria-label": "Previous period",
|
|
154
|
-
children: /* @__PURE__ */
|
|
155
|
+
children: /* @__PURE__ */ j(E, { className: "h-4 w-4" })
|
|
155
156
|
}),
|
|
156
|
-
/* @__PURE__ */
|
|
157
|
+
/* @__PURE__ */ j(b, {
|
|
157
158
|
variant: "ghost",
|
|
158
159
|
size: "icon",
|
|
159
160
|
className: "h-8 w-8",
|
|
160
161
|
"aria-label": "Next period",
|
|
161
|
-
children: /* @__PURE__ */
|
|
162
|
+
children: /* @__PURE__ */ j(D, { className: "h-4 w-4" })
|
|
162
163
|
}),
|
|
163
|
-
/* @__PURE__ */
|
|
164
|
+
/* @__PURE__ */ j("span", {
|
|
164
165
|
className: "font-semibold text-xs sm:text-sm",
|
|
165
166
|
children: q.start.toLocaleDateString(void 0, {
|
|
166
167
|
month: "long",
|
|
@@ -168,38 +169,38 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
168
169
|
})
|
|
169
170
|
})
|
|
170
171
|
]
|
|
171
|
-
}), /* @__PURE__ */
|
|
172
|
+
}), /* @__PURE__ */ M("div", {
|
|
172
173
|
className: "flex items-center gap-2",
|
|
173
174
|
children: [
|
|
174
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ M("div", {
|
|
175
176
|
className: "flex bg-muted rounded-md p-1",
|
|
176
|
-
children: [/* @__PURE__ */
|
|
177
|
+
children: [/* @__PURE__ */ j(b, {
|
|
177
178
|
variant: "ghost",
|
|
178
179
|
size: "icon",
|
|
179
180
|
className: "h-6 w-6",
|
|
180
|
-
onClick: () =>
|
|
181
|
+
onClick: () => g(Math.max(15, _ - 10)),
|
|
181
182
|
"aria-label": "Zoom out",
|
|
182
|
-
children: /* @__PURE__ */
|
|
183
|
-
}), /* @__PURE__ */
|
|
183
|
+
children: /* @__PURE__ */ j(ne, { className: "h-3 w-3" })
|
|
184
|
+
}), /* @__PURE__ */ j(b, {
|
|
184
185
|
variant: "ghost",
|
|
185
186
|
size: "icon",
|
|
186
187
|
className: "h-6 w-6",
|
|
187
|
-
onClick: () =>
|
|
188
|
+
onClick: () => g(Math.min(120, _ + 10)),
|
|
188
189
|
"aria-label": "Zoom in",
|
|
189
|
-
children: /* @__PURE__ */
|
|
190
|
+
children: /* @__PURE__ */ j(k, { className: "h-3 w-3" })
|
|
190
191
|
})]
|
|
191
192
|
}),
|
|
192
|
-
/* @__PURE__ */
|
|
193
|
+
/* @__PURE__ */ j(b, {
|
|
193
194
|
variant: "ghost",
|
|
194
195
|
size: "icon",
|
|
195
196
|
className: "h-8 w-8",
|
|
196
|
-
onClick: () =>
|
|
197
|
-
"aria-label":
|
|
198
|
-
"aria-pressed":
|
|
197
|
+
onClick: () => y((e) => !e),
|
|
198
|
+
"aria-label": v ? "Show task list" : "Hide task list",
|
|
199
|
+
"aria-pressed": v,
|
|
199
200
|
"data-testid": "gantt-toggle-task-list",
|
|
200
|
-
children:
|
|
201
|
+
children: j(v ? O : te, { className: "h-4 w-4" })
|
|
201
202
|
}),
|
|
202
|
-
/* @__PURE__ */
|
|
203
|
+
/* @__PURE__ */ j(b, {
|
|
203
204
|
variant: "ghost",
|
|
204
205
|
size: "icon",
|
|
205
206
|
className: "h-8 w-8",
|
|
@@ -207,64 +208,64 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
207
208
|
disabled: $ == null,
|
|
208
209
|
"aria-label": "Jump to today",
|
|
209
210
|
"data-testid": "gantt-jump-today",
|
|
210
|
-
children: /* @__PURE__ */
|
|
211
|
+
children: /* @__PURE__ */ j(T, { className: "h-4 w-4" })
|
|
211
212
|
})
|
|
212
213
|
]
|
|
213
214
|
})]
|
|
214
|
-
}), /* @__PURE__ */
|
|
215
|
+
}), /* @__PURE__ */ M("div", {
|
|
215
216
|
className: "flex flex-col flex-1 overflow-hidden",
|
|
216
|
-
children: [/* @__PURE__ */
|
|
217
|
+
children: [/* @__PURE__ */ M("div", {
|
|
217
218
|
className: "flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]",
|
|
218
|
-
children: [/* @__PURE__ */
|
|
219
|
+
children: [/* @__PURE__ */ M("div", {
|
|
219
220
|
className: "flex items-center font-medium text-xs text-muted-foreground px-2 sm:px-4 border-r bg-card z-20 shadow-sm",
|
|
220
221
|
style: {
|
|
221
|
-
width:
|
|
222
|
-
minWidth:
|
|
222
|
+
width: w,
|
|
223
|
+
minWidth: w
|
|
223
224
|
},
|
|
224
|
-
children: [/* @__PURE__ */
|
|
225
|
+
children: [/* @__PURE__ */ j("div", {
|
|
225
226
|
className: "flex-1 truncate",
|
|
226
227
|
children: "Task Name"
|
|
227
|
-
}),
|
|
228
|
+
}), L && /* @__PURE__ */ M(A, { children: [/* @__PURE__ */ j("div", {
|
|
228
229
|
className: "w-16 sm:w-20 text-right",
|
|
229
230
|
children: "Start"
|
|
230
|
-
}), /* @__PURE__ */
|
|
231
|
+
}), /* @__PURE__ */ j("div", {
|
|
231
232
|
className: "w-16 sm:w-20 text-right",
|
|
232
233
|
children: "End"
|
|
233
234
|
})] })]
|
|
234
|
-
}), /* @__PURE__ */
|
|
235
|
+
}), /* @__PURE__ */ j("div", {
|
|
235
236
|
className: "flex-1 overflow-hidden",
|
|
236
237
|
ref: Y,
|
|
237
|
-
children: /* @__PURE__ */
|
|
238
|
+
children: /* @__PURE__ */ j("div", {
|
|
238
239
|
className: "flex h-full",
|
|
239
|
-
style: { width: J.length *
|
|
240
|
-
children: J.map((e, t) => /* @__PURE__ */
|
|
241
|
-
className:
|
|
240
|
+
style: { width: J.length * _ },
|
|
241
|
+
children: J.map((e, t) => /* @__PURE__ */ M("div", {
|
|
242
|
+
className: x("flex flex-col items-center justify-center border-r text-xs text-muted-foreground h-full", e.isWeekend && "bg-muted/50"),
|
|
242
243
|
style: {
|
|
243
|
-
width:
|
|
244
|
-
minWidth:
|
|
244
|
+
width: _,
|
|
245
|
+
minWidth: _
|
|
245
246
|
},
|
|
246
|
-
children: [/* @__PURE__ */
|
|
247
|
+
children: [/* @__PURE__ */ j("span", {
|
|
247
248
|
className: "font-medium text-foreground",
|
|
248
249
|
children: e.label
|
|
249
|
-
}), /* @__PURE__ */
|
|
250
|
+
}), /* @__PURE__ */ j("span", {
|
|
250
251
|
className: "text-[10px] opacity-70",
|
|
251
252
|
children: e.date.toLocaleDateString(void 0, { weekday: "narrow" })
|
|
252
253
|
})]
|
|
253
254
|
}, t))
|
|
254
255
|
})
|
|
255
256
|
})]
|
|
256
|
-
}), /* @__PURE__ */
|
|
257
|
+
}), /* @__PURE__ */ M("div", {
|
|
257
258
|
className: "flex flex-1 overflow-hidden",
|
|
258
|
-
children: [/* @__PURE__ */
|
|
259
|
+
children: [/* @__PURE__ */ j("div", {
|
|
259
260
|
className: "overflow-hidden border-r bg-card z-10 shadow-sm",
|
|
260
261
|
ref: X,
|
|
261
262
|
style: {
|
|
262
|
-
width:
|
|
263
|
-
minWidth:
|
|
263
|
+
width: w,
|
|
264
|
+
minWidth: w
|
|
264
265
|
},
|
|
265
266
|
children: t.map((e) => {
|
|
266
|
-
let t = s &&
|
|
267
|
-
return /* @__PURE__ */
|
|
267
|
+
let t = s && re === e.id;
|
|
268
|
+
return /* @__PURE__ */ M("div", {
|
|
268
269
|
className: "group/task-row flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation",
|
|
269
270
|
style: { height: m },
|
|
270
271
|
onClick: () => !t && i?.(e),
|
|
@@ -277,12 +278,12 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
277
278
|
}));
|
|
278
279
|
},
|
|
279
280
|
children: [
|
|
280
|
-
/* @__PURE__ */
|
|
281
|
+
/* @__PURE__ */ M("div", {
|
|
281
282
|
className: "flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2",
|
|
282
|
-
children: [/* @__PURE__ */
|
|
283
|
+
children: [/* @__PURE__ */ j("div", {
|
|
283
284
|
className: "w-2 h-2 rounded-full shrink-0",
|
|
284
285
|
style: { backgroundColor: e.color || "#3b82f6" }
|
|
285
|
-
}), t ? /* @__PURE__ */
|
|
286
|
+
}), t ? /* @__PURE__ */ j("input", {
|
|
286
287
|
className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
|
|
287
288
|
value: z.title || "",
|
|
288
289
|
onChange: (e) => B((t) => ({
|
|
@@ -299,12 +300,12 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
299
300
|
},
|
|
300
301
|
onClick: (e) => e.stopPropagation(),
|
|
301
302
|
autoFocus: !0
|
|
302
|
-
}) : /* @__PURE__ */
|
|
303
|
+
}) : /* @__PURE__ */ M("span", {
|
|
303
304
|
className: "flex flex-col min-w-0",
|
|
304
|
-
children: [/* @__PURE__ */
|
|
305
|
+
children: [/* @__PURE__ */ j("span", {
|
|
305
306
|
className: "truncate",
|
|
306
307
|
children: e.title
|
|
307
|
-
}), /* @__PURE__ */
|
|
308
|
+
}), /* @__PURE__ */ M("span", {
|
|
308
309
|
className: "text-[10px] text-muted-foreground sm:hidden",
|
|
309
310
|
children: [
|
|
310
311
|
e.start.toLocaleDateString(void 0, {
|
|
@@ -320,11 +321,11 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
320
321
|
})]
|
|
321
322
|
})]
|
|
322
323
|
}),
|
|
323
|
-
/* @__PURE__ */
|
|
324
|
+
/* @__PURE__ */ j("div", {
|
|
324
325
|
className: "w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block",
|
|
325
|
-
hidden: !
|
|
326
|
-
style:
|
|
327
|
-
children: t ? /* @__PURE__ */
|
|
326
|
+
hidden: !L,
|
|
327
|
+
style: L ? void 0 : { display: "none" },
|
|
328
|
+
children: t ? /* @__PURE__ */ j("input", {
|
|
328
329
|
type: "date",
|
|
329
330
|
className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
|
|
330
331
|
value: z.start || "",
|
|
@@ -338,11 +339,11 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
338
339
|
day: "numeric"
|
|
339
340
|
})
|
|
340
341
|
}),
|
|
341
|
-
/* @__PURE__ */
|
|
342
|
+
/* @__PURE__ */ j("div", {
|
|
342
343
|
className: "w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block",
|
|
343
|
-
hidden: !
|
|
344
|
-
style:
|
|
345
|
-
children: t ? /* @__PURE__ */
|
|
344
|
+
hidden: !L,
|
|
345
|
+
style: L ? void 0 : { display: "none" },
|
|
346
|
+
children: t ? /* @__PURE__ */ j("input", {
|
|
346
347
|
type: "date",
|
|
347
348
|
className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
|
|
348
349
|
value: z.end || "",
|
|
@@ -359,7 +360,7 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
359
360
|
]
|
|
360
361
|
}, e.id);
|
|
361
362
|
})
|
|
362
|
-
}), /* @__PURE__ */
|
|
363
|
+
}), /* @__PURE__ */ j("div", {
|
|
363
364
|
className: "flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]",
|
|
364
365
|
ref: (e) => {
|
|
365
366
|
ie.current = e, Z.current = e;
|
|
@@ -369,28 +370,28 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
369
370
|
onTouchMove: oe,
|
|
370
371
|
onTouchEnd: se,
|
|
371
372
|
"data-testid": "gantt-timeline",
|
|
372
|
-
children: /* @__PURE__ */
|
|
373
|
+
children: /* @__PURE__ */ M("div", {
|
|
373
374
|
className: "relative",
|
|
374
|
-
style: { width: J.length *
|
|
375
|
-
children: [$ != null && /* @__PURE__ */
|
|
375
|
+
style: { width: J.length * _ },
|
|
376
|
+
children: [$ != null && /* @__PURE__ */ j("div", {
|
|
376
377
|
className: "absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none",
|
|
377
378
|
style: { left: $ },
|
|
378
379
|
"data-testid": "gantt-today-marker",
|
|
379
380
|
"aria-label": "Today",
|
|
380
|
-
children: /* @__PURE__ */
|
|
381
|
+
children: /* @__PURE__ */ j("div", {
|
|
381
382
|
className: "absolute -top-2 -translate-x-1/2 left-0 text-[10px] font-semibold text-white bg-red-500 rounded-sm px-1 py-0.5 whitespace-nowrap",
|
|
382
383
|
children: "Today"
|
|
383
384
|
})
|
|
384
|
-
}), /* @__PURE__ */
|
|
385
|
+
}), /* @__PURE__ */ M("div", {
|
|
385
386
|
className: "relative",
|
|
386
387
|
children: [
|
|
387
|
-
/* @__PURE__ */
|
|
388
|
+
/* @__PURE__ */ j("div", {
|
|
388
389
|
className: "absolute inset-0 flex pointer-events-none z-0",
|
|
389
|
-
children: J.map((e, t) => /* @__PURE__ */
|
|
390
|
-
className:
|
|
390
|
+
children: J.map((e, t) => /* @__PURE__ */ j("div", {
|
|
391
|
+
className: x("border-r h-full", e.isWeekend && "bg-muted/20"),
|
|
391
392
|
style: {
|
|
392
|
-
width:
|
|
393
|
-
minWidth:
|
|
393
|
+
width: _,
|
|
394
|
+
minWidth: _
|
|
394
395
|
}
|
|
395
396
|
}, t))
|
|
396
397
|
}),
|
|
@@ -405,10 +406,10 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
405
406
|
});
|
|
406
407
|
}
|
|
407
408
|
let o = !!a;
|
|
408
|
-
return /* @__PURE__ */
|
|
409
|
+
return /* @__PURE__ */ M("div", {
|
|
409
410
|
className: "relative border-b hover:bg-black/5",
|
|
410
411
|
style: { height: m },
|
|
411
|
-
children: [n && /* @__PURE__ */
|
|
412
|
+
children: [n && /* @__PURE__ */ j("div", {
|
|
412
413
|
className: "absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm border border-dashed border-primary/60 pointer-events-none",
|
|
413
414
|
style: {
|
|
414
415
|
left: t.left,
|
|
@@ -416,8 +417,8 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
416
417
|
opacity: .35
|
|
417
418
|
},
|
|
418
419
|
"aria-hidden": "true"
|
|
419
|
-
}), /* @__PURE__ */
|
|
420
|
-
className:
|
|
420
|
+
}), /* @__PURE__ */ M("div", {
|
|
421
|
+
className: x("absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm bg-primary border border-primary-foreground/20 shadow-sm hover:brightness-110 flex items-center px-2 group select-none", o ? "cursor-grab active:cursor-grabbing" : "cursor-pointer", n && "ring-2 ring-primary/60 brightness-110 z-10"),
|
|
421
422
|
style: {
|
|
422
423
|
left: r.left,
|
|
423
424
|
width: r.width,
|
|
@@ -431,14 +432,14 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
431
432
|
t.button === 0 && K(e, "move", t);
|
|
432
433
|
} : void 0,
|
|
433
434
|
children: [
|
|
434
|
-
o && r.width >= 14 && /* @__PURE__ */
|
|
435
|
+
o && r.width >= 14 && /* @__PURE__ */ M(A, { children: [/* @__PURE__ */ j("div", {
|
|
435
436
|
className: "absolute left-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40",
|
|
436
437
|
"data-testid": `gantt-task-resize-left-${e.id}`,
|
|
437
438
|
onPointerDown: (t) => {
|
|
438
439
|
t.button === 0 && K(e, "resize-left", t);
|
|
439
440
|
},
|
|
440
441
|
onClick: (e) => e.stopPropagation()
|
|
441
|
-
}), /* @__PURE__ */
|
|
442
|
+
}), /* @__PURE__ */ j("div", {
|
|
442
443
|
className: "absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40",
|
|
443
444
|
"data-testid": `gantt-task-resize-right-${e.id}`,
|
|
444
445
|
onPointerDown: (t) => {
|
|
@@ -446,11 +447,11 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
446
447
|
},
|
|
447
448
|
onClick: (e) => e.stopPropagation()
|
|
448
449
|
})] }),
|
|
449
|
-
e.progress > 0 && /* @__PURE__ */
|
|
450
|
+
e.progress > 0 && /* @__PURE__ */ j("div", {
|
|
450
451
|
className: "absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm pointer-events-none",
|
|
451
452
|
style: { width: `${e.progress}%` }
|
|
452
453
|
}),
|
|
453
|
-
/* @__PURE__ */
|
|
454
|
+
/* @__PURE__ */ j("span", {
|
|
454
455
|
className: "text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none",
|
|
455
456
|
children: n ? `${G(V).start.toLocaleDateString(void 0, {
|
|
456
457
|
month: "numeric",
|
|
@@ -464,10 +465,10 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
464
465
|
})]
|
|
465
466
|
}, e.id);
|
|
466
467
|
}),
|
|
467
|
-
/* @__PURE__ */
|
|
468
|
+
/* @__PURE__ */ j("div", {
|
|
468
469
|
className: "absolute top-0 bottom-0 w-px bg-red-500 z-20 pointer-events-none",
|
|
469
|
-
style: { left: ((/* @__PURE__ */ new Date()).getTime() - q.start.getTime()) / (1e3 * 60 * 60 * 24) *
|
|
470
|
-
children: /* @__PURE__ */
|
|
470
|
+
style: { left: ((/* @__PURE__ */ new Date()).getTime() - q.start.getTime()) / (1e3 * 60 * 60 * 24) * _ },
|
|
471
|
+
children: /* @__PURE__ */ j("div", { className: "w-2 h-2 rounded-full bg-red-500 -ml-[3px]" })
|
|
471
472
|
})
|
|
472
473
|
]
|
|
473
474
|
})]
|
|
@@ -479,7 +480,7 @@ function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
479
480
|
}
|
|
480
481
|
//#endregion
|
|
481
482
|
//#region src/ObjectGantt.tsx
|
|
482
|
-
function
|
|
483
|
+
function re(e) {
|
|
483
484
|
return e.data ? e.data : e.staticData ? {
|
|
484
485
|
provider: "value",
|
|
485
486
|
items: e.staticData
|
|
@@ -488,7 +489,7 @@ function F(e) {
|
|
|
488
489
|
object: e.objectName
|
|
489
490
|
} : null;
|
|
490
491
|
}
|
|
491
|
-
function
|
|
492
|
+
function R(e) {
|
|
492
493
|
if (e) {
|
|
493
494
|
if (typeof e == "string") {
|
|
494
495
|
let t = e.split(" "), n = t[0], r = t[1]?.toLowerCase() === "desc" ? "desc" : "asc";
|
|
@@ -497,7 +498,7 @@ function I(e) {
|
|
|
497
498
|
if (Array.isArray(e)) return e.reduce((e, t) => (t.field && t.order && (e[t.field] = t.order), e), {});
|
|
498
499
|
}
|
|
499
500
|
}
|
|
500
|
-
function
|
|
501
|
+
function z(e) {
|
|
501
502
|
let t = null;
|
|
502
503
|
if (e.startDateField && e.endDateField) return t = {
|
|
503
504
|
startDateField: e.startDateField,
|
|
@@ -513,47 +514,47 @@ function L(e) {
|
|
|
513
514
|
}
|
|
514
515
|
return null;
|
|
515
516
|
}
|
|
516
|
-
var
|
|
517
|
-
let [
|
|
517
|
+
var B = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: b, ...x }) => {
|
|
518
|
+
let [S, T] = i([]), [E, D] = i(!0), [O, te] = i(null), [k, ne] = i(null), N = re(e), P = r(() => N, [JSON.stringify(N)]), F = z(e), I = P?.provider === "value";
|
|
518
519
|
n(() => {
|
|
519
520
|
(async () => {
|
|
520
521
|
try {
|
|
521
|
-
if (
|
|
522
|
-
|
|
522
|
+
if (D(!0), x.data && Array.isArray(x.data)) {
|
|
523
|
+
T(x.data), D(!1);
|
|
523
524
|
return;
|
|
524
525
|
}
|
|
525
|
-
if (
|
|
526
|
-
|
|
526
|
+
if (I && P?.provider === "value") {
|
|
527
|
+
T(P.items), D(!1);
|
|
527
528
|
return;
|
|
528
529
|
}
|
|
529
530
|
if (!a || typeof a.find != "function") throw Error("DataSource required for object/api providers");
|
|
530
|
-
if (
|
|
531
|
-
let t =
|
|
532
|
-
|
|
531
|
+
if (P?.provider === "object") {
|
|
532
|
+
let t = P.object, n = o(k?.fields);
|
|
533
|
+
T(s(await a.find(t, {
|
|
533
534
|
$filter: e.filter,
|
|
534
|
-
$orderby:
|
|
535
|
+
$orderby: R(e.sort),
|
|
535
536
|
...n.length > 0 ? { $expand: n } : {}
|
|
536
537
|
})));
|
|
537
|
-
} else
|
|
538
|
-
|
|
538
|
+
} else P?.provider === "api" && (console.warn("API provider not yet implemented for ObjectGantt"), T([]));
|
|
539
|
+
D(!1);
|
|
539
540
|
} catch (e) {
|
|
540
|
-
|
|
541
|
+
te(e), D(!1);
|
|
541
542
|
}
|
|
542
543
|
})();
|
|
543
544
|
}, [
|
|
544
|
-
|
|
545
|
+
P,
|
|
545
546
|
a,
|
|
546
|
-
|
|
547
|
+
I,
|
|
547
548
|
e.filter,
|
|
548
549
|
e.sort,
|
|
549
|
-
|
|
550
|
+
k
|
|
550
551
|
]), n(() => {
|
|
551
|
-
!
|
|
552
|
+
!I && a && (async () => {
|
|
552
553
|
try {
|
|
553
554
|
if (!a) return;
|
|
554
|
-
let t =
|
|
555
|
+
let t = P?.provider === "object" ? P.object : e.objectName;
|
|
555
556
|
if (!t) return;
|
|
556
|
-
|
|
557
|
+
ne(await a.getObjectSchema(t));
|
|
557
558
|
} catch (e) {
|
|
558
559
|
console.error("Failed to fetch object schema:", e);
|
|
559
560
|
}
|
|
@@ -561,12 +562,12 @@ var R = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: y
|
|
|
561
562
|
}, [
|
|
562
563
|
e.objectName,
|
|
563
564
|
a,
|
|
564
|
-
|
|
565
|
-
|
|
565
|
+
I,
|
|
566
|
+
P
|
|
566
567
|
]);
|
|
567
|
-
let
|
|
568
|
-
if (!
|
|
569
|
-
let { startDateField: e, endDateField: t, titleField: n, progressField: r, dependenciesField: i, colorField: a } =
|
|
568
|
+
let B = r(() => {
|
|
569
|
+
if (!F || !S.length) return [];
|
|
570
|
+
let { startDateField: e, endDateField: t, titleField: n, progressField: r, dependenciesField: i, colorField: a } = F, o = (e, t) => {
|
|
570
571
|
if (!t) return;
|
|
571
572
|
let n = t.split("."), r = e;
|
|
572
573
|
for (let e of n) {
|
|
@@ -590,8 +591,15 @@ var R = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: y
|
|
|
590
591
|
for (let e of t) if (e != null && String(e).trim() !== "") return String(e);
|
|
591
592
|
return "Untitled";
|
|
592
593
|
};
|
|
593
|
-
return
|
|
594
|
+
return S.map((n, o) => {
|
|
594
595
|
let c = n[e], l = n[t], u = s(n), d = r ? n[r] : 0, f = i ? n[i] : [], p = a ? n[a] : void 0;
|
|
596
|
+
if (!p) {
|
|
597
|
+
let e = n.status ?? n.state ?? n.priority ?? n.severity;
|
|
598
|
+
if (e != null && e !== "") {
|
|
599
|
+
let t = C(void 0, e);
|
|
600
|
+
t && (p = w(t));
|
|
601
|
+
}
|
|
602
|
+
}
|
|
595
603
|
return {
|
|
596
604
|
id: n.id || n._id || `task-${o}`,
|
|
597
605
|
title: u,
|
|
@@ -603,168 +611,168 @@ var R = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: y
|
|
|
603
611
|
data: n
|
|
604
612
|
};
|
|
605
613
|
}).filter((e) => !isNaN(e.start.getTime()) && !isNaN(e.end.getTime()));
|
|
606
|
-
}, [
|
|
614
|
+
}, [S, F]), V = e.navigation ?? {
|
|
607
615
|
mode: "drawer",
|
|
608
616
|
width: "min(960px, 60vw)"
|
|
609
|
-
},
|
|
610
|
-
navigation:
|
|
617
|
+
}, H = V.mode === "drawer" || V.mode === "modal" || V.mode === "split" || V.mode === "popover", U = c({
|
|
618
|
+
navigation: V,
|
|
611
619
|
objectName: e.objectName,
|
|
612
|
-
onRowClick:
|
|
613
|
-
}),
|
|
614
|
-
if (!
|
|
615
|
-
let r =
|
|
620
|
+
onRowClick: H ? void 0 : b
|
|
621
|
+
}), W = t(async (t, n) => {
|
|
622
|
+
if (!F) return;
|
|
623
|
+
let r = P?.provider === "object" ? P.object : e.objectName;
|
|
616
624
|
if (!r || !a || typeof a.update != "function") return;
|
|
617
|
-
let { startDateField: i, endDateField: o, titleField: s, progressField: c } =
|
|
625
|
+
let { startDateField: i, endDateField: o, titleField: s, progressField: c } = F, l = {};
|
|
618
626
|
if (n.start instanceof Date && (l[i] = n.start.toISOString()), n.end instanceof Date && (l[o] = n.end.toISOString()), typeof n.title == "string" && s && (l[s] = n.title), typeof n.progress == "number" && c && (l[c] = n.progress), Object.keys(l).length === 0) return;
|
|
619
627
|
let u = t.data?.id ?? t.data?._id ?? t.id;
|
|
620
628
|
if (u == null) return;
|
|
621
|
-
let d =
|
|
622
|
-
|
|
629
|
+
let d = S;
|
|
630
|
+
T((e) => e.map((e) => String(e.id ?? e._id) === String(u) ? {
|
|
623
631
|
...e,
|
|
624
632
|
...l
|
|
625
633
|
} : e));
|
|
626
634
|
try {
|
|
627
635
|
await a.update(r, String(u), l);
|
|
628
636
|
} catch (e) {
|
|
629
|
-
console.error("[ObjectGantt] Failed to persist task update:", e),
|
|
637
|
+
console.error("[ObjectGantt] Failed to persist task update:", e), T(d);
|
|
630
638
|
}
|
|
631
639
|
}, [
|
|
632
|
-
|
|
633
|
-
|
|
640
|
+
F,
|
|
641
|
+
P,
|
|
634
642
|
a,
|
|
635
643
|
e.objectName,
|
|
636
|
-
|
|
637
|
-
]), [
|
|
638
|
-
|
|
639
|
-
}, []),
|
|
640
|
-
if (!
|
|
641
|
-
let t =
|
|
644
|
+
S
|
|
645
|
+
]), [G, K] = i(null), [q, J] = i(!1), Y = t((e) => {
|
|
646
|
+
K(e);
|
|
647
|
+
}, []), X = t(async () => {
|
|
648
|
+
if (!G) return;
|
|
649
|
+
let t = P?.provider === "object" ? P.object : e.objectName;
|
|
642
650
|
if (!t || !a?.delete) {
|
|
643
|
-
|
|
651
|
+
K(null);
|
|
644
652
|
return;
|
|
645
653
|
}
|
|
646
|
-
let n =
|
|
654
|
+
let n = G.data?.id ?? G.data?._id ?? G.id;
|
|
647
655
|
if (n == null) {
|
|
648
|
-
|
|
656
|
+
K(null);
|
|
649
657
|
return;
|
|
650
658
|
}
|
|
651
|
-
|
|
652
|
-
let r =
|
|
653
|
-
|
|
659
|
+
J(!0);
|
|
660
|
+
let r = S;
|
|
661
|
+
T((e) => e.filter((e) => String(e.id ?? e._id) !== String(n)));
|
|
654
662
|
try {
|
|
655
|
-
await a.delete(t, String(n)),
|
|
663
|
+
await a.delete(t, String(n)), K(null);
|
|
656
664
|
} catch (e) {
|
|
657
|
-
console.error("[ObjectGantt] Failed to delete:", e),
|
|
665
|
+
console.error("[ObjectGantt] Failed to delete:", e), T(r), K(null);
|
|
658
666
|
} finally {
|
|
659
|
-
|
|
667
|
+
J(!1);
|
|
660
668
|
}
|
|
661
669
|
}, [
|
|
662
|
-
|
|
663
|
-
|
|
670
|
+
G,
|
|
671
|
+
P,
|
|
664
672
|
a,
|
|
665
673
|
e.objectName,
|
|
666
|
-
|
|
674
|
+
S
|
|
667
675
|
]);
|
|
668
|
-
return
|
|
676
|
+
return E ? /* @__PURE__ */ j("div", {
|
|
669
677
|
className: l,
|
|
670
|
-
children: /* @__PURE__ */
|
|
678
|
+
children: /* @__PURE__ */ j("div", {
|
|
671
679
|
className: "flex items-center justify-center h-96",
|
|
672
|
-
children: /* @__PURE__ */
|
|
680
|
+
children: /* @__PURE__ */ j("div", {
|
|
673
681
|
className: "text-muted-foreground",
|
|
674
682
|
children: "Loading Gantt chart..."
|
|
675
683
|
})
|
|
676
684
|
})
|
|
677
|
-
}) :
|
|
685
|
+
}) : O ? /* @__PURE__ */ j("div", {
|
|
678
686
|
className: l,
|
|
679
|
-
children: /* @__PURE__ */
|
|
687
|
+
children: /* @__PURE__ */ j("div", {
|
|
680
688
|
className: "flex items-center justify-center h-96",
|
|
681
|
-
children: /* @__PURE__ */
|
|
689
|
+
children: /* @__PURE__ */ M("div", {
|
|
682
690
|
className: "text-destructive",
|
|
683
|
-
children: ["Error: ",
|
|
691
|
+
children: ["Error: ", O.message]
|
|
684
692
|
})
|
|
685
693
|
})
|
|
686
|
-
}) :
|
|
694
|
+
}) : F ? /* @__PURE__ */ M("div", {
|
|
687
695
|
className: l,
|
|
688
696
|
children: [
|
|
689
|
-
/* @__PURE__ */
|
|
697
|
+
/* @__PURE__ */ j("div", {
|
|
690
698
|
className: "h-[calc(100vh-200px)] min-h-[600px]",
|
|
691
|
-
children: /* @__PURE__ */
|
|
692
|
-
tasks:
|
|
699
|
+
children: /* @__PURE__ */ j(L, {
|
|
700
|
+
tasks: B,
|
|
693
701
|
onTaskClick: (e) => {
|
|
694
|
-
|
|
702
|
+
U.handleClick(e.data), u?.(e.data);
|
|
695
703
|
},
|
|
696
|
-
onTaskUpdate:
|
|
697
|
-
onTaskDelete:
|
|
704
|
+
onTaskUpdate: W,
|
|
705
|
+
onTaskDelete: Y,
|
|
698
706
|
inlineEdit: !0
|
|
699
707
|
})
|
|
700
708
|
}),
|
|
701
|
-
|
|
702
|
-
let t =
|
|
709
|
+
U.isOverlay && U.isOpen && U.selectedRecord && (() => {
|
|
710
|
+
let t = P?.provider === "object" ? P.object : e.objectName, n = U.selectedRecord, r = n.id ?? n._id;
|
|
703
711
|
if (!t || r == null) return null;
|
|
704
|
-
let i =
|
|
705
|
-
return /* @__PURE__ */
|
|
712
|
+
let i = F?.titleField ? String(n[F.titleField] ?? "Task Details") : "Task Details";
|
|
713
|
+
return /* @__PURE__ */ j(d, {
|
|
706
714
|
open: !0,
|
|
707
|
-
onClose:
|
|
715
|
+
onClose: U.close,
|
|
708
716
|
title: i,
|
|
709
717
|
record: n,
|
|
710
718
|
objectName: t,
|
|
711
719
|
recordId: r,
|
|
712
720
|
dataSource: a,
|
|
713
|
-
objectSchema:
|
|
714
|
-
width:
|
|
721
|
+
objectSchema: k,
|
|
722
|
+
width: U.width,
|
|
715
723
|
fullPageHref: f(t, r) ?? void 0,
|
|
716
724
|
onFieldSave: async (e, n) => {
|
|
717
|
-
a?.update && (await a.update(t, String(r), { [e]: n }),
|
|
725
|
+
a?.update && (await a.update(t, String(r), { [e]: n }), T((t) => t.map((t) => String(t.id ?? t._id) === String(r) ? {
|
|
718
726
|
...t,
|
|
719
727
|
[e]: n
|
|
720
728
|
} : t)));
|
|
721
729
|
},
|
|
722
730
|
onDelete: async () => {
|
|
723
|
-
a?.delete && (await a.delete(t, String(r)),
|
|
731
|
+
a?.delete && (await a.delete(t, String(r)), T((e) => e.filter((e) => String(e.id ?? e._id) !== String(r))));
|
|
724
732
|
}
|
|
725
733
|
});
|
|
726
734
|
})(),
|
|
727
|
-
/* @__PURE__ */
|
|
728
|
-
open: !!
|
|
735
|
+
/* @__PURE__ */ j(p, {
|
|
736
|
+
open: !!G,
|
|
729
737
|
onOpenChange: (e) => {
|
|
730
|
-
!e && !
|
|
738
|
+
!e && !q && K(null);
|
|
731
739
|
},
|
|
732
|
-
children: /* @__PURE__ */
|
|
740
|
+
children: /* @__PURE__ */ M(ee, { children: [/* @__PURE__ */ M(v, { children: [/* @__PURE__ */ j(y, { children: "Delete this task?" }), /* @__PURE__ */ j(g, { children: G ? /* @__PURE__ */ M(A, { children: [
|
|
733
741
|
"\"",
|
|
734
|
-
|
|
742
|
+
G.title,
|
|
735
743
|
"\" will be permanently removed. This action cannot be undone."
|
|
736
|
-
] }) : null })] }), /* @__PURE__ */
|
|
737
|
-
disabled:
|
|
744
|
+
] }) : null })] }), /* @__PURE__ */ M(_, { children: [/* @__PURE__ */ j(h, {
|
|
745
|
+
disabled: q,
|
|
738
746
|
children: "Cancel"
|
|
739
|
-
}), /* @__PURE__ */
|
|
747
|
+
}), /* @__PURE__ */ j(m, {
|
|
740
748
|
onClick: (e) => {
|
|
741
|
-
e.preventDefault(),
|
|
749
|
+
e.preventDefault(), X();
|
|
742
750
|
},
|
|
743
|
-
disabled:
|
|
751
|
+
disabled: q,
|
|
744
752
|
"data-testid": "gantt-delete-confirm",
|
|
745
753
|
className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
746
|
-
children:
|
|
754
|
+
children: q ? "Deleting…" : "Delete"
|
|
747
755
|
})] })] })
|
|
748
756
|
})
|
|
749
757
|
]
|
|
750
|
-
}) : /* @__PURE__ */
|
|
758
|
+
}) : /* @__PURE__ */ j("div", {
|
|
751
759
|
className: l,
|
|
752
|
-
children: /* @__PURE__ */
|
|
760
|
+
children: /* @__PURE__ */ j("div", {
|
|
753
761
|
className: "flex items-center justify-center h-96",
|
|
754
|
-
children: /* @__PURE__ */
|
|
762
|
+
children: /* @__PURE__ */ j("div", {
|
|
755
763
|
className: "text-muted-foreground",
|
|
756
764
|
children: "Gantt configuration required. Please specify startDateField, endDateField, and titleField."
|
|
757
765
|
})
|
|
758
766
|
})
|
|
759
767
|
});
|
|
760
|
-
},
|
|
768
|
+
}, V = ({ schema: e }) => {
|
|
761
769
|
let { dataSource: t } = l() || {};
|
|
762
|
-
return /* @__PURE__ */
|
|
770
|
+
return /* @__PURE__ */ j(B, {
|
|
763
771
|
schema: e,
|
|
764
772
|
dataSource: t
|
|
765
773
|
});
|
|
766
774
|
};
|
|
767
|
-
a.register("object-gantt",
|
|
775
|
+
a.register("object-gantt", V, {
|
|
768
776
|
namespace: "plugin-gantt",
|
|
769
777
|
label: "Object Gantt",
|
|
770
778
|
category: "view",
|
|
@@ -779,7 +787,7 @@ a.register("object-gantt", z, {
|
|
|
779
787
|
label: "Gantt Config",
|
|
780
788
|
description: "startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField"
|
|
781
789
|
}]
|
|
782
|
-
}), a.register("gantt",
|
|
790
|
+
}), a.register("gantt", V, {
|
|
783
791
|
namespace: "view",
|
|
784
792
|
label: "Gantt View",
|
|
785
793
|
category: "view",
|
|
@@ -796,4 +804,4 @@ a.register("object-gantt", z, {
|
|
|
796
804
|
}]
|
|
797
805
|
});
|
|
798
806
|
//#endregion
|
|
799
|
-
export {
|
|
807
|
+
export { L as GanttView, B as ObjectGantt, V as ObjectGanttRenderer };
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`),require(`@object-ui/core`),require(`@object-ui/react`),require(`@objectstack/spec/ui`),require(`@object-ui/plugin-detail`),require(`@object-ui/components`),require(`lucide-react`),require(`react/jsx-runtime`)):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/core`,`@object-ui/react`,`@objectstack/spec/ui`,`@object-ui/plugin-detail`,`@object-ui/components`,`lucide-react`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginGantt={},e.React,e.ObjectUICore,e.ObjectUIReact,e._objectstack_spec_ui,e._object_ui_plugin_detail,e.ObjectUIComponents,e.LucideReact,e.react_jsx_runtime))})(this,function(e,t,n,r,i,a,o,s,c){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var l=Object.create,u=Object.defineProperty,d=Object.getOwnPropertyDescriptor,f=Object.getOwnPropertyNames,p=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty,h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=f(t),a=0,o=i.length,s;a<o;a++)s=i[a],!m.call(e,s)&&s!==n&&u(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=d(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:l(p(e)),h(t||!e||!e.__esModule?u(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);function g(e){return e<640?35:e<1024?50:60}function _(e){return e<640?140:e<1024?220:320}function v(e){return e>=280}function y(e){return e<640?32:40}function b({tasks:e,startDate:n,endDate:r,onTaskClick:i,onTaskUpdate:a,className:l,inlineEdit:u=!1}){let[d,f]=t.useState(new Date),p=t.useRef(null),{width:m}=(0,o.useResizeObserver)(p),h=m||(typeof window<`u`?window.innerWidth:1024),b=h<640,x=y(h),S=g(h),[C,w]=t.useState(null),T=C??S,[E,D]=t.useState(!1),O=t.useRef(!1);t.useEffect(()=>{!O.current&&b&&(D(!0),O.current=!0)},[b]);let k=E?0:_(h),A=v(k),[j,M]=t.useState(null),[N,P]=t.useState({}),[F,I]=t.useState(null),L=t.useRef(null);t.useEffect(()=>{L.current=F},[F]);let R=t.useRef(!1),z=t.useCallback(e=>{let t=1e3*60*60*24,n=t,r=e.dayDelta*t,i=new Date(e.originStart),a=new Date(e.originEnd);return e.mode===`move`?(i=new Date(e.originStart.getTime()+r),a=new Date(e.originEnd.getTime()+r)):e.mode===`resize-left`?(i=new Date(e.originStart.getTime()+r),a.getTime()-i.getTime()<n&&(i=new Date(a.getTime()-n))):e.mode===`resize-right`&&(a=new Date(e.originEnd.getTime()+r),a.getTime()-i.getTime()<n&&(a=new Date(i.getTime()+n))),{start:i,end:a}},[]);t.useEffect(()=>{if(!F)return;let t=e=>{let t=L.current;if(!t)return;let n=Math.round((e.clientX-t.originClientX)/Math.max(T,1));n!==t.dayDelta&&I({...t,dayDelta:n})},n=()=>{let t=L.current;if(t){if(t.dayDelta!==0){let n=e.find(e=>e.id===t.taskId);if(n&&a){let{start:e,end:r}=z(t);a(n,{start:e,end:r})}R.current=!0,window.setTimeout(()=>{R.current=!1},0)}I(null)}};return window.addEventListener(`pointermove`,t),window.addEventListener(`pointerup`,n),window.addEventListener(`pointercancel`,n),()=>{window.removeEventListener(`pointermove`,t),window.removeEventListener(`pointerup`,n),window.removeEventListener(`pointercancel`,n)}},[F,T,e,a,z]);let B=t.useCallback((e,t,n)=>{a&&(n.stopPropagation(),n.preventDefault(),I({taskId:e.id,mode:t,originStart:new Date(e.start),originEnd:new Date(e.end),originClientX:n.clientX,dayDelta:0}))},[a]),V=t.useMemo(()=>{let t=n?new Date(n):new Date,i=r?new Date(r):new Date;return!n&&e.length>0&&(t=new Date(Math.min(...e.map(e=>e.start.getTime()))),t.setDate(t.getDate()-7)),!r&&e.length>0&&(i=new Date(Math.max(...e.map(e=>e.end.getTime()))),i.setDate(i.getDate()+14)),t.setHours(0,0,0,0),i.setHours(23,59,59,999),{start:t,end:i}},[n,r,e]),H=t.useMemo(()=>{let e=[],t=new Date(V.start);for(;t<=V.end;)e.push({date:new Date(t),label:t.getDate().toString(),isWeekend:t.getDay()===0||t.getDay()===6}),t.setDate(t.getDate()+1);return e},[V]),U=t.useRef(null),W=t.useRef(null),G=t.useRef(null),K=t.useRef(null),q=t.useRef(null),J=t.useCallback(e=>{if(e.touches.length===2){let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY;q.current={baseDistance:Math.max(1,Math.sqrt(t*t+n*n)),baseColumn:T}}},[T]),Y=t.useCallback(e=>{if(e.touches.length!==2||!q.current)return;let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY,r=Math.max(1,Math.sqrt(t*t+n*n))/q.current.baseDistance;w(Math.max(15,Math.min(120,Math.round(q.current.baseColumn*r))))},[]),X=t.useCallback(()=>{q.current=null},[]),Z=t.useMemo(()=>{let e=new Date;if(e<V.start||e>V.end)return null;let t=(e.getTime()-V.start.getTime())/(1440*60*1e3);return Math.round(t*T)},[V,T]),Q=t.useCallback(()=>{if(Z==null||!K.current)return;let e=Math.max(0,Z-K.current.clientWidth/2);K.current.scrollTo({left:e,behavior:`smooth`})},[Z]),ee=e=>{U.current&&(U.current.scrollLeft=e.currentTarget.scrollLeft),W.current&&(W.current.scrollTop=e.currentTarget.scrollTop)},$=e=>{V.end.getTime()-V.start.getTime();let t=T,n=1e3*60*60*24,r=e.start.getTime()-V.start.getTime(),i=e.end.getTime()-e.start.getTime();return{left:r/n*t,width:Math.max(i/n*t,t)}};return(0,c.jsxs)(`div`,{ref:p,className:(0,o.cn)(`flex flex-col h-full bg-background border rounded-lg overflow-hidden min-w-0`,l),children:[(0,c.jsxs)(`div`,{className:`flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 p-2 border-b bg-card`,children:[(0,c.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,c.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":`Previous period`,children:(0,c.jsx)(s.ChevronLeft,{className:`h-4 w-4`})}),(0,c.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":`Next period`,children:(0,c.jsx)(s.ChevronRight,{className:`h-4 w-4`})}),(0,c.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:V.start.toLocaleDateString(void 0,{month:`long`,year:`numeric`})})]}),(0,c.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,c.jsxs)(`div`,{className:`flex bg-muted rounded-md p-1`,children:[(0,c.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>w(Math.max(15,T-10)),"aria-label":`Zoom out`,children:(0,c.jsx)(s.ZoomOut,{className:`h-3 w-3`})}),(0,c.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>w(Math.min(120,T+10)),"aria-label":`Zoom in`,children:(0,c.jsx)(s.ZoomIn,{className:`h-3 w-3`})})]}),(0,c.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:()=>D(e=>!e),"aria-label":E?`Show task list`:`Hide task list`,"aria-pressed":E,"data-testid":`gantt-toggle-task-list`,children:E?(0,c.jsx)(s.PanelLeft,{className:`h-4 w-4`}):(0,c.jsx)(s.PanelLeftClose,{className:`h-4 w-4`})}),(0,c.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:Q,disabled:Z==null,"aria-label":`Jump to today`,"data-testid":`gantt-jump-today`,children:(0,c.jsx)(s.CalendarDays,{className:`h-4 w-4`})})]})]}),(0,c.jsxs)(`div`,{className:`flex flex-col flex-1 overflow-hidden`,children:[(0,c.jsxs)(`div`,{className:`flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]`,children:[(0,c.jsxs)(`div`,{className:`flex items-center font-medium text-xs text-muted-foreground px-2 sm:px-4 border-r bg-card z-20 shadow-sm`,style:{width:k,minWidth:k},children:[(0,c.jsx)(`div`,{className:`flex-1 truncate`,children:`Task Name`}),A&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:`Start`}),(0,c.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:`End`})]})]}),(0,c.jsx)(`div`,{className:`flex-1 overflow-hidden`,ref:U,children:(0,c.jsx)(`div`,{className:`flex h-full`,style:{width:H.length*T},children:H.map((e,t)=>(0,c.jsxs)(`div`,{className:(0,o.cn)(`flex flex-col items-center justify-center border-r text-xs text-muted-foreground h-full`,e.isWeekend&&`bg-muted/50`),style:{width:T,minWidth:T},children:[(0,c.jsx)(`span`,{className:`font-medium text-foreground`,children:e.label}),(0,c.jsx)(`span`,{className:`text-[10px] opacity-70`,children:e.date.toLocaleDateString(void 0,{weekday:`narrow`})})]},t))})})]}),(0,c.jsxs)(`div`,{className:`flex flex-1 overflow-hidden`,children:[(0,c.jsx)(`div`,{className:`overflow-hidden border-r bg-card z-10 shadow-sm`,ref:W,style:{width:k,minWidth:k},children:e.map(e=>{let t=u&&j===e.id;return(0,c.jsxs)(`div`,{className:`group/task-row flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation`,style:{height:x},onClick:()=>!t&&i?.(e),onDoubleClick:()=>{u&&a&&(M(e.id),P({title:e.title,start:e.start.toLocaleDateString(`en-CA`),end:e.end.toLocaleDateString(`en-CA`),progress:String(e.progress)}))},children:[(0,c.jsxs)(`div`,{className:`flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2`,children:[(0,c.jsx)(`div`,{className:`w-2 h-2 rounded-full shrink-0`,style:{backgroundColor:e.color||`#3b82f6`}}),t?(0,c.jsx)(`input`,{className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:N.title||``,onChange:e=>P(t=>({...t,title:e.target.value})),onKeyDown:t=>{t.key===`Enter`?(a?.(e,{title:N.title,start:new Date(N.start),end:new Date(N.end),progress:Number(N.progress)||0}),M(null)):t.key===`Escape`&&M(null)},onClick:e=>e.stopPropagation(),autoFocus:!0}):(0,c.jsxs)(`span`,{className:`flex flex-col min-w-0`,children:[(0,c.jsx)(`span`,{className:`truncate`,children:e.title}),(0,c.jsxs)(`span`,{className:`text-[10px] text-muted-foreground sm:hidden`,children:[e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`}),` → `,e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})]})]})]}),(0,c.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!A,style:A?void 0:{display:`none`},children:t?(0,c.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:N.start||``,onChange:e=>P(t=>({...t,start:e.target.value})),onClick:e=>e.stopPropagation()}):e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}),(0,c.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!A,style:A?void 0:{display:`none`},children:t?(0,c.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:N.end||``,onChange:e=>P(t=>({...t,end:e.target.value})),onClick:e=>e.stopPropagation()}):e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})})]},e.id)})}),(0,c.jsx)(`div`,{className:`flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]`,ref:e=>{G.current=e,K.current=e},onScroll:ee,onTouchStart:J,onTouchMove:Y,onTouchEnd:X,"data-testid":`gantt-timeline`,children:(0,c.jsxs)(`div`,{className:`relative`,style:{width:H.length*T},children:[Z!=null&&(0,c.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none`,style:{left:Z},"data-testid":`gantt-today-marker`,"aria-label":`Today`,children:(0,c.jsx)(`div`,{className:`absolute -top-2 -translate-x-1/2 left-0 text-[10px] font-semibold text-white bg-red-500 rounded-sm px-1 py-0.5 whitespace-nowrap`,children:`Today`})}),(0,c.jsxs)(`div`,{className:`relative`,children:[(0,c.jsx)(`div`,{className:`absolute inset-0 flex pointer-events-none z-0`,children:H.map((e,t)=>(0,c.jsx)(`div`,{className:(0,o.cn)(`border-r h-full`,e.isWeekend&&`bg-muted/20`),style:{width:T,minWidth:T}},t))}),e.map(e=>{let t=$(e),n=F?.taskId===e.id,r=t;if(n&&F){let t=z(F);r=$({...e,start:t.start,end:t.end})}let s=!!a;return(0,c.jsxs)(`div`,{className:`relative border-b hover:bg-black/5`,style:{height:x},children:[n&&(0,c.jsx)(`div`,{className:`absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm border border-dashed border-primary/60 pointer-events-none`,style:{left:t.left,width:t.width,opacity:.35},"aria-hidden":`true`}),(0,c.jsxs)(`div`,{className:(0,o.cn)(`absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm bg-primary border border-primary-foreground/20 shadow-sm hover:brightness-110 flex items-center px-2 group select-none`,s?`cursor-grab active:cursor-grabbing`:`cursor-pointer`,n&&`ring-2 ring-primary/60 brightness-110 z-10`),style:{left:r.left,width:r.width,backgroundColor:e.color||`#3b82f6`},"data-testid":`gantt-task-bar-${e.id}`,onClick:()=>{R.current||i?.(e)},onPointerDown:s?t=>{t.button===0&&B(e,`move`,t)}:void 0,children:[s&&r.width>=14&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40`,"data-testid":`gantt-task-resize-left-${e.id}`,onPointerDown:t=>{t.button===0&&B(e,`resize-left`,t)},onClick:e=>e.stopPropagation()}),(0,c.jsx)(`div`,{className:`absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40`,"data-testid":`gantt-task-resize-right-${e.id}`,onPointerDown:t=>{t.button===0&&B(e,`resize-right`,t)},onClick:e=>e.stopPropagation()})]}),e.progress>0&&(0,c.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm pointer-events-none`,style:{width:`${e.progress}%`}}),(0,c.jsx)(`span`,{className:`text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none`,children:n?`${z(F).start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})} → ${z(F).end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}`:`${Math.round(e.progress)}%`})]})]},e.id)}),(0,c.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500 z-20 pointer-events-none`,style:{left:(new Date().getTime()-V.start.getTime())/(1e3*60*60*24)*T},children:(0,c.jsx)(`div`,{className:`w-2 h-2 rounded-full bg-red-500 -ml-[3px]`})})]})]})})]})]})]})}function x(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function S(e){if(e){if(typeof e==`string`){let t=e.split(` `),n=t[0],r=t[1]?.toLowerCase()===`desc`?`desc`:`asc`;return{[n]:r}}if(Array.isArray(e))return e.reduce((e,t)=>(t.field&&t.order&&(e[t.field]=t.order),e),{})}}function C(e){let t=null;if(e.startDateField&&e.endDateField)return t={startDateField:e.startDateField,endDateField:e.endDateField,titleField:e.titleField||`name`,progressField:e.progressField,dependenciesField:e.dependenciesField||e.dependencyField,colorField:e.colorField},t;if(e.gantt&&(t=e.gantt),t){let e=i.GanttConfigSchema.safeParse(t);return e.success||console.warn(`[ObjectGantt] Invalid gantt configuration:`,e.error.format()),t}return null}var w=({schema:e,dataSource:i,className:s,onTaskClick:l,onRowClick:u,...d})=>{let[f,p]=(0,t.useState)([]),[m,h]=(0,t.useState)(!0),[g,_]=(0,t.useState)(null),[v,y]=(0,t.useState)(null),w=x(e),T=(0,t.useMemo)(()=>w,[JSON.stringify(w)]),E=C(e),D=T?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(h(!0),d.data&&Array.isArray(d.data)){p(d.data),h(!1);return}if(D&&T?.provider===`value`){p(T.items),h(!1);return}if(!i||typeof i.find!=`function`)throw Error(`DataSource required for object/api providers`);if(T?.provider===`object`){let t=T.object,r=(0,n.buildExpandFields)(v?.fields);p((0,n.extractRecords)(await i.find(t,{$filter:e.filter,$orderby:S(e.sort),...r.length>0?{$expand:r}:{}})))}else T?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectGantt`),p([]));h(!1)}catch(e){_(e),h(!1)}})()},[T,i,D,e.filter,e.sort,v]),(0,t.useEffect)(()=>{!D&&i&&(async()=>{try{if(!i)return;let t=T?.provider===`object`?T.object:e.objectName;if(!t)return;y(await i.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,i,D,T]);let O=(0,t.useMemo)(()=>{if(!E||!f.length)return[];let{startDateField:e,endDateField:t,titleField:n,progressField:r,dependenciesField:i,colorField:a}=E,o=(e,t)=>{if(!t)return;let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r},s=e=>{let t=[o(e,n),e?.name,e?.title,e?.subject,e?.label,e?.account?.name,e?.opportunity?.name,e?.contact&&[e.contact.first_name,e.contact.last_name].filter(Boolean).join(` `),e?.id,e?._id];for(let e of t)if(e!=null&&String(e).trim()!==``)return String(e);return`Untitled`};return f.map((n,o)=>{let c=n[e],l=n[t],u=s(n),d=r?n[r]:0,f=i?n[i]:[],p=a?n[a]:void 0;return{id:n.id||n._id||`task-${o}`,title:u,start:c?new Date(c):new Date,end:l?new Date(l):new Date,progress:Math.min(100,Math.max(0,d||0)),dependencies:Array.isArray(f)?f:[],color:p,data:n}}).filter(e=>!isNaN(e.start.getTime())&&!isNaN(e.end.getTime()))},[f,E]),k=e.navigation??{mode:`drawer`,width:`min(960px, 60vw)`},A=k.mode===`drawer`||k.mode===`modal`||k.mode===`split`||k.mode===`popover`,j=(0,r.useNavigationOverlay)({navigation:k,objectName:e.objectName,onRowClick:A?void 0:u}),M=(0,t.useCallback)(async(t,n)=>{if(!E)return;let r=T?.provider===`object`?T.object:e.objectName;if(!r||!i||typeof i.update!=`function`)return;let{startDateField:a,endDateField:o,titleField:s,progressField:c}=E,l={};if(n.start instanceof Date&&(l[a]=n.start.toISOString()),n.end instanceof Date&&(l[o]=n.end.toISOString()),typeof n.title==`string`&&s&&(l[s]=n.title),typeof n.progress==`number`&&c&&(l[c]=n.progress),Object.keys(l).length===0)return;let u=t.data?.id??t.data?._id??t.id;if(u==null)return;let d=f;p(e=>e.map(e=>String(e.id??e._id)===String(u)?{...e,...l}:e));try{await i.update(r,String(u),l)}catch(e){console.error(`[ObjectGantt] Failed to persist task update:`,e),p(d)}},[E,T,i,e.objectName,f]),[N,P]=(0,t.useState)(null),[F,I]=(0,t.useState)(!1),L=(0,t.useCallback)(e=>{P(e)},[]),R=(0,t.useCallback)(async()=>{if(!N)return;let t=T?.provider===`object`?T.object:e.objectName;if(!t||!i?.delete){P(null);return}let n=N.data?.id??N.data?._id??N.id;if(n==null){P(null);return}I(!0);let r=f;p(e=>e.filter(e=>String(e.id??e._id)!==String(n)));try{await i.delete(t,String(n)),P(null)}catch(e){console.error(`[ObjectGantt] Failed to delete:`,e),p(r),P(null)}finally{I(!1)}},[N,T,i,e.objectName,f]);return m?(0,c.jsx)(`div`,{className:s,children:(0,c.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,c.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading Gantt chart...`})})}):g?(0,c.jsx)(`div`,{className:s,children:(0,c.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,c.jsxs)(`div`,{className:`text-destructive`,children:[`Error: `,g.message]})})}):E?(0,c.jsxs)(`div`,{className:s,children:[(0,c.jsx)(`div`,{className:`h-[calc(100vh-200px)] min-h-[600px]`,children:(0,c.jsx)(b,{tasks:O,onTaskClick:e=>{j.handleClick(e.data),l?.(e.data)},onTaskUpdate:M,onTaskDelete:L,inlineEdit:!0})}),j.isOverlay&&j.isOpen&&j.selectedRecord&&(()=>{let t=T?.provider===`object`?T.object:e.objectName,n=j.selectedRecord,r=n.id??n._id;if(!t||r==null)return null;let o=E?.titleField?String(n[E.titleField]??`Task Details`):`Task Details`;return(0,c.jsx)(a.RecordDetailDrawer,{open:!0,onClose:j.close,title:o,record:n,objectName:t,recordId:r,dataSource:i,objectSchema:v,width:j.width,fullPageHref:(0,a.deriveRecordPageHref)(t,r)??void 0,onFieldSave:async(e,n)=>{i?.update&&(await i.update(t,String(r),{[e]:n}),p(t=>t.map(t=>String(t.id??t._id)===String(r)?{...t,[e]:n}:t)))},onDelete:async()=>{i?.delete&&(await i.delete(t,String(r)),p(e=>e.filter(e=>String(e.id??e._id)!==String(r))))}})})(),(0,c.jsx)(o.AlertDialog,{open:!!N,onOpenChange:e=>{!e&&!F&&P(null)},children:(0,c.jsxs)(o.AlertDialogContent,{children:[(0,c.jsxs)(o.AlertDialogHeader,{children:[(0,c.jsx)(o.AlertDialogTitle,{children:`Delete this task?`}),(0,c.jsx)(o.AlertDialogDescription,{children:N?(0,c.jsxs)(c.Fragment,{children:[`"`,N.title,`" will be permanently removed. This action cannot be undone.`]}):null})]}),(0,c.jsxs)(o.AlertDialogFooter,{children:[(0,c.jsx)(o.AlertDialogCancel,{disabled:F,children:`Cancel`}),(0,c.jsx)(o.AlertDialogAction,{onClick:e=>{e.preventDefault(),R()},disabled:F,"data-testid":`gantt-delete-confirm`,className:`bg-destructive text-destructive-foreground hover:bg-destructive/90`,children:F?`Deleting…`:`Delete`})]})]})})]}):(0,c.jsx)(`div`,{className:s,children:(0,c.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,c.jsx)(`div`,{className:`text-muted-foreground`,children:`Gantt configuration required. Please specify startDateField, endDateField, and titleField.`})})})},T=({schema:e})=>{let{dataSource:t}=(0,r.useSchemaContext)()||{};return(0,c.jsx)(w,{schema:e,dataSource:t})};n.ComponentRegistry.register(`object-gantt`,T,{namespace:`plugin-gantt`,label:`Object Gantt`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),n.ComponentRegistry.register(`gantt`,T,{namespace:`view`,label:`Gantt View`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),e.GanttView=b,e.ObjectGantt=w,e.ObjectGanttRenderer=T});
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`),require(`@object-ui/core`),require(`@object-ui/react`),require(`@objectstack/spec/ui`),require(`@object-ui/plugin-detail`),require(`@object-ui/components`),require(`@object-ui/fields`),require(`lucide-react`),require(`react/jsx-runtime`)):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/core`,`@object-ui/react`,`@objectstack/spec/ui`,`@object-ui/plugin-detail`,`@object-ui/components`,`@object-ui/fields`,`lucide-react`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginGantt={},e.React,e.ObjectUICore,e.ObjectUIReact,e._objectstack_spec_ui,e._object_ui_plugin_detail,e.ObjectUIComponents,e._object_ui_fields,e.LucideReact,e.react_jsx_runtime))})(this,function(e,t,n,r,i,a,o,s,c,l){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var u=Object.create,d=Object.defineProperty,f=Object.getOwnPropertyDescriptor,p=Object.getOwnPropertyNames,m=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty,g=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=p(t),a=0,o=i.length,s;a<o;a++)s=i[a],!h.call(e,s)&&s!==n&&d(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=f(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:u(m(e)),g(t||!e||!e.__esModule?d(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);function _(e){return e<640?35:e<1024?50:60}function v(e){return e<640?140:e<1024?220:320}function y(e){return e>=280}function b(e){return e<640?32:40}function x({tasks:e,startDate:n,endDate:r,onTaskClick:i,onTaskUpdate:a,className:s,inlineEdit:u=!1}){let[d,f]=t.useState(new Date),p=t.useRef(null),{width:m}=(0,o.useResizeObserver)(p),h=m||(typeof window<`u`?window.innerWidth:1024),g=h<640,x=b(h),S=_(h),[C,w]=t.useState(null),T=C??S,[E,D]=t.useState(!1),O=t.useRef(!1);t.useEffect(()=>{!O.current&&g&&(D(!0),O.current=!0)},[g]);let k=E?0:v(h),A=y(k),[j,M]=t.useState(null),[N,P]=t.useState({}),[F,I]=t.useState(null),L=t.useRef(null);t.useEffect(()=>{L.current=F},[F]);let R=t.useRef(!1),z=t.useCallback(e=>{let t=1e3*60*60*24,n=t,r=e.dayDelta*t,i=new Date(e.originStart),a=new Date(e.originEnd);return e.mode===`move`?(i=new Date(e.originStart.getTime()+r),a=new Date(e.originEnd.getTime()+r)):e.mode===`resize-left`?(i=new Date(e.originStart.getTime()+r),a.getTime()-i.getTime()<n&&(i=new Date(a.getTime()-n))):e.mode===`resize-right`&&(a=new Date(e.originEnd.getTime()+r),a.getTime()-i.getTime()<n&&(a=new Date(i.getTime()+n))),{start:i,end:a}},[]);t.useEffect(()=>{if(!F)return;let t=e=>{let t=L.current;if(!t)return;let n=Math.round((e.clientX-t.originClientX)/Math.max(T,1));n!==t.dayDelta&&I({...t,dayDelta:n})},n=()=>{let t=L.current;if(t){if(t.dayDelta!==0){let n=e.find(e=>e.id===t.taskId);if(n&&a){let{start:e,end:r}=z(t);a(n,{start:e,end:r})}R.current=!0,window.setTimeout(()=>{R.current=!1},0)}I(null)}};return window.addEventListener(`pointermove`,t),window.addEventListener(`pointerup`,n),window.addEventListener(`pointercancel`,n),()=>{window.removeEventListener(`pointermove`,t),window.removeEventListener(`pointerup`,n),window.removeEventListener(`pointercancel`,n)}},[F,T,e,a,z]);let B=t.useCallback((e,t,n)=>{a&&(n.stopPropagation(),n.preventDefault(),I({taskId:e.id,mode:t,originStart:new Date(e.start),originEnd:new Date(e.end),originClientX:n.clientX,dayDelta:0}))},[a]),V=t.useMemo(()=>{let t=n?new Date(n):new Date,i=r?new Date(r):new Date;return!n&&e.length>0&&(t=new Date(Math.min(...e.map(e=>e.start.getTime()))),t.setDate(t.getDate()-7)),!r&&e.length>0&&(i=new Date(Math.max(...e.map(e=>e.end.getTime()))),i.setDate(i.getDate()+14)),t.setHours(0,0,0,0),i.setHours(23,59,59,999),{start:t,end:i}},[n,r,e]),H=t.useMemo(()=>{let e=[],t=new Date(V.start);for(;t<=V.end;)e.push({date:new Date(t),label:t.getDate().toString(),isWeekend:t.getDay()===0||t.getDay()===6}),t.setDate(t.getDate()+1);return e},[V]),U=t.useRef(null),W=t.useRef(null),G=t.useRef(null),K=t.useRef(null),q=t.useRef(null),J=t.useCallback(e=>{if(e.touches.length===2){let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY;q.current={baseDistance:Math.max(1,Math.sqrt(t*t+n*n)),baseColumn:T}}},[T]),Y=t.useCallback(e=>{if(e.touches.length!==2||!q.current)return;let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY,r=Math.max(1,Math.sqrt(t*t+n*n))/q.current.baseDistance;w(Math.max(15,Math.min(120,Math.round(q.current.baseColumn*r))))},[]),X=t.useCallback(()=>{q.current=null},[]),Z=t.useMemo(()=>{let e=new Date;if(e<V.start||e>V.end)return null;let t=(e.getTime()-V.start.getTime())/(1440*60*1e3);return Math.round(t*T)},[V,T]),Q=t.useCallback(()=>{if(Z==null||!K.current)return;let e=Math.max(0,Z-K.current.clientWidth/2);K.current.scrollTo({left:e,behavior:`smooth`})},[Z]),ee=e=>{U.current&&(U.current.scrollLeft=e.currentTarget.scrollLeft),W.current&&(W.current.scrollTop=e.currentTarget.scrollTop)},$=e=>{V.end.getTime()-V.start.getTime();let t=T,n=1e3*60*60*24,r=e.start.getTime()-V.start.getTime(),i=e.end.getTime()-e.start.getTime();return{left:r/n*t,width:Math.max(i/n*t,t)}};return(0,l.jsxs)(`div`,{ref:p,className:(0,o.cn)(`flex flex-col h-full bg-background overflow-hidden min-w-0`,s),children:[(0,l.jsxs)(`div`,{className:`flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 p-2 border-b bg-card`,children:[(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":`Previous period`,children:(0,l.jsx)(c.ChevronLeft,{className:`h-4 w-4`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":`Next period`,children:(0,l.jsx)(c.ChevronRight,{className:`h-4 w-4`})}),(0,l.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:V.start.toLocaleDateString(void 0,{month:`long`,year:`numeric`})})]}),(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsxs)(`div`,{className:`flex bg-muted rounded-md p-1`,children:[(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>w(Math.max(15,T-10)),"aria-label":`Zoom out`,children:(0,l.jsx)(c.ZoomOut,{className:`h-3 w-3`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>w(Math.min(120,T+10)),"aria-label":`Zoom in`,children:(0,l.jsx)(c.ZoomIn,{className:`h-3 w-3`})})]}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:()=>D(e=>!e),"aria-label":E?`Show task list`:`Hide task list`,"aria-pressed":E,"data-testid":`gantt-toggle-task-list`,children:E?(0,l.jsx)(c.PanelLeft,{className:`h-4 w-4`}):(0,l.jsx)(c.PanelLeftClose,{className:`h-4 w-4`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:Q,disabled:Z==null,"aria-label":`Jump to today`,"data-testid":`gantt-jump-today`,children:(0,l.jsx)(c.CalendarDays,{className:`h-4 w-4`})})]})]}),(0,l.jsxs)(`div`,{className:`flex flex-col flex-1 overflow-hidden`,children:[(0,l.jsxs)(`div`,{className:`flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]`,children:[(0,l.jsxs)(`div`,{className:`flex items-center font-medium text-xs text-muted-foreground px-2 sm:px-4 border-r bg-card z-20 shadow-sm`,style:{width:k,minWidth:k},children:[(0,l.jsx)(`div`,{className:`flex-1 truncate`,children:`Task Name`}),A&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:`Start`}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:`End`})]})]}),(0,l.jsx)(`div`,{className:`flex-1 overflow-hidden`,ref:U,children:(0,l.jsx)(`div`,{className:`flex h-full`,style:{width:H.length*T},children:H.map((e,t)=>(0,l.jsxs)(`div`,{className:(0,o.cn)(`flex flex-col items-center justify-center border-r text-xs text-muted-foreground h-full`,e.isWeekend&&`bg-muted/50`),style:{width:T,minWidth:T},children:[(0,l.jsx)(`span`,{className:`font-medium text-foreground`,children:e.label}),(0,l.jsx)(`span`,{className:`text-[10px] opacity-70`,children:e.date.toLocaleDateString(void 0,{weekday:`narrow`})})]},t))})})]}),(0,l.jsxs)(`div`,{className:`flex flex-1 overflow-hidden`,children:[(0,l.jsx)(`div`,{className:`overflow-hidden border-r bg-card z-10 shadow-sm`,ref:W,style:{width:k,minWidth:k},children:e.map(e=>{let t=u&&j===e.id;return(0,l.jsxs)(`div`,{className:`group/task-row flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation`,style:{height:x},onClick:()=>!t&&i?.(e),onDoubleClick:()=>{u&&a&&(M(e.id),P({title:e.title,start:e.start.toLocaleDateString(`en-CA`),end:e.end.toLocaleDateString(`en-CA`),progress:String(e.progress)}))},children:[(0,l.jsxs)(`div`,{className:`flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2`,children:[(0,l.jsx)(`div`,{className:`w-2 h-2 rounded-full shrink-0`,style:{backgroundColor:e.color||`#3b82f6`}}),t?(0,l.jsx)(`input`,{className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:N.title||``,onChange:e=>P(t=>({...t,title:e.target.value})),onKeyDown:t=>{t.key===`Enter`?(a?.(e,{title:N.title,start:new Date(N.start),end:new Date(N.end),progress:Number(N.progress)||0}),M(null)):t.key===`Escape`&&M(null)},onClick:e=>e.stopPropagation(),autoFocus:!0}):(0,l.jsxs)(`span`,{className:`flex flex-col min-w-0`,children:[(0,l.jsx)(`span`,{className:`truncate`,children:e.title}),(0,l.jsxs)(`span`,{className:`text-[10px] text-muted-foreground sm:hidden`,children:[e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`}),` → `,e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})]})]})]}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!A,style:A?void 0:{display:`none`},children:t?(0,l.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:N.start||``,onChange:e=>P(t=>({...t,start:e.target.value})),onClick:e=>e.stopPropagation()}):e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!A,style:A?void 0:{display:`none`},children:t?(0,l.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:N.end||``,onChange:e=>P(t=>({...t,end:e.target.value})),onClick:e=>e.stopPropagation()}):e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})})]},e.id)})}),(0,l.jsx)(`div`,{className:`flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]`,ref:e=>{G.current=e,K.current=e},onScroll:ee,onTouchStart:J,onTouchMove:Y,onTouchEnd:X,"data-testid":`gantt-timeline`,children:(0,l.jsxs)(`div`,{className:`relative`,style:{width:H.length*T},children:[Z!=null&&(0,l.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none`,style:{left:Z},"data-testid":`gantt-today-marker`,"aria-label":`Today`,children:(0,l.jsx)(`div`,{className:`absolute -top-2 -translate-x-1/2 left-0 text-[10px] font-semibold text-white bg-red-500 rounded-sm px-1 py-0.5 whitespace-nowrap`,children:`Today`})}),(0,l.jsxs)(`div`,{className:`relative`,children:[(0,l.jsx)(`div`,{className:`absolute inset-0 flex pointer-events-none z-0`,children:H.map((e,t)=>(0,l.jsx)(`div`,{className:(0,o.cn)(`border-r h-full`,e.isWeekend&&`bg-muted/20`),style:{width:T,minWidth:T}},t))}),e.map(e=>{let t=$(e),n=F?.taskId===e.id,r=t;if(n&&F){let t=z(F);r=$({...e,start:t.start,end:t.end})}let s=!!a;return(0,l.jsxs)(`div`,{className:`relative border-b hover:bg-black/5`,style:{height:x},children:[n&&(0,l.jsx)(`div`,{className:`absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm border border-dashed border-primary/60 pointer-events-none`,style:{left:t.left,width:t.width,opacity:.35},"aria-hidden":`true`}),(0,l.jsxs)(`div`,{className:(0,o.cn)(`absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm bg-primary border border-primary-foreground/20 shadow-sm hover:brightness-110 flex items-center px-2 group select-none`,s?`cursor-grab active:cursor-grabbing`:`cursor-pointer`,n&&`ring-2 ring-primary/60 brightness-110 z-10`),style:{left:r.left,width:r.width,backgroundColor:e.color||`#3b82f6`},"data-testid":`gantt-task-bar-${e.id}`,onClick:()=>{R.current||i?.(e)},onPointerDown:s?t=>{t.button===0&&B(e,`move`,t)}:void 0,children:[s&&r.width>=14&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40`,"data-testid":`gantt-task-resize-left-${e.id}`,onPointerDown:t=>{t.button===0&&B(e,`resize-left`,t)},onClick:e=>e.stopPropagation()}),(0,l.jsx)(`div`,{className:`absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40`,"data-testid":`gantt-task-resize-right-${e.id}`,onPointerDown:t=>{t.button===0&&B(e,`resize-right`,t)},onClick:e=>e.stopPropagation()})]}),e.progress>0&&(0,l.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm pointer-events-none`,style:{width:`${e.progress}%`}}),(0,l.jsx)(`span`,{className:`text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none`,children:n?`${z(F).start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})} → ${z(F).end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}`:`${Math.round(e.progress)}%`})]})]},e.id)}),(0,l.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500 z-20 pointer-events-none`,style:{left:(new Date().getTime()-V.start.getTime())/(1e3*60*60*24)*T},children:(0,l.jsx)(`div`,{className:`w-2 h-2 rounded-full bg-red-500 -ml-[3px]`})})]})]})})]})]})]})}function S(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function C(e){if(e){if(typeof e==`string`){let t=e.split(` `),n=t[0],r=t[1]?.toLowerCase()===`desc`?`desc`:`asc`;return{[n]:r}}if(Array.isArray(e))return e.reduce((e,t)=>(t.field&&t.order&&(e[t.field]=t.order),e),{})}}function w(e){let t=null;if(e.startDateField&&e.endDateField)return t={startDateField:e.startDateField,endDateField:e.endDateField,titleField:e.titleField||`name`,progressField:e.progressField,dependenciesField:e.dependenciesField||e.dependencyField,colorField:e.colorField},t;if(e.gantt&&(t=e.gantt),t){let e=i.GanttConfigSchema.safeParse(t);return e.success||console.warn(`[ObjectGantt] Invalid gantt configuration:`,e.error.format()),t}return null}var T=({schema:e,dataSource:i,className:c,onTaskClick:u,onRowClick:d,...f})=>{let[p,m]=(0,t.useState)([]),[h,g]=(0,t.useState)(!0),[_,v]=(0,t.useState)(null),[y,b]=(0,t.useState)(null),T=S(e),E=(0,t.useMemo)(()=>T,[JSON.stringify(T)]),D=w(e),O=E?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(g(!0),f.data&&Array.isArray(f.data)){m(f.data),g(!1);return}if(O&&E?.provider===`value`){m(E.items),g(!1);return}if(!i||typeof i.find!=`function`)throw Error(`DataSource required for object/api providers`);if(E?.provider===`object`){let t=E.object,r=(0,n.buildExpandFields)(y?.fields);m((0,n.extractRecords)(await i.find(t,{$filter:e.filter,$orderby:C(e.sort),...r.length>0?{$expand:r}:{}})))}else E?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectGantt`),m([]));g(!1)}catch(e){v(e),g(!1)}})()},[E,i,O,e.filter,e.sort,y]),(0,t.useEffect)(()=>{!O&&i&&(async()=>{try{if(!i)return;let t=E?.provider===`object`?E.object:e.objectName;if(!t)return;b(await i.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,i,O,E]);let k=(0,t.useMemo)(()=>{if(!D||!p.length)return[];let{startDateField:e,endDateField:t,titleField:n,progressField:r,dependenciesField:i,colorField:a}=D,o=(e,t)=>{if(!t)return;let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r},c=e=>{let t=[o(e,n),e?.name,e?.title,e?.subject,e?.label,e?.account?.name,e?.opportunity?.name,e?.contact&&[e.contact.first_name,e.contact.last_name].filter(Boolean).join(` `),e?.id,e?._id];for(let e of t)if(e!=null&&String(e).trim()!==``)return String(e);return`Untitled`};return p.map((n,o)=>{let l=n[e],u=n[t],d=c(n),f=r?n[r]:0,p=i?n[i]:[],m=a?n[a]:void 0;if(!m){let e=n.status??n.state??n.priority??n.severity;if(e!=null&&e!==``){let t=(0,s.getSemanticColorName)(void 0,e);t&&(m=(0,s.getSemanticHex)(t))}}return{id:n.id||n._id||`task-${o}`,title:d,start:l?new Date(l):new Date,end:u?new Date(u):new Date,progress:Math.min(100,Math.max(0,f||0)),dependencies:Array.isArray(p)?p:[],color:m,data:n}}).filter(e=>!isNaN(e.start.getTime())&&!isNaN(e.end.getTime()))},[p,D]),A=e.navigation??{mode:`drawer`,width:`min(960px, 60vw)`},j=A.mode===`drawer`||A.mode===`modal`||A.mode===`split`||A.mode===`popover`,M=(0,r.useNavigationOverlay)({navigation:A,objectName:e.objectName,onRowClick:j?void 0:d}),N=(0,t.useCallback)(async(t,n)=>{if(!D)return;let r=E?.provider===`object`?E.object:e.objectName;if(!r||!i||typeof i.update!=`function`)return;let{startDateField:a,endDateField:o,titleField:s,progressField:c}=D,l={};if(n.start instanceof Date&&(l[a]=n.start.toISOString()),n.end instanceof Date&&(l[o]=n.end.toISOString()),typeof n.title==`string`&&s&&(l[s]=n.title),typeof n.progress==`number`&&c&&(l[c]=n.progress),Object.keys(l).length===0)return;let u=t.data?.id??t.data?._id??t.id;if(u==null)return;let d=p;m(e=>e.map(e=>String(e.id??e._id)===String(u)?{...e,...l}:e));try{await i.update(r,String(u),l)}catch(e){console.error(`[ObjectGantt] Failed to persist task update:`,e),m(d)}},[D,E,i,e.objectName,p]),[P,F]=(0,t.useState)(null),[I,L]=(0,t.useState)(!1),R=(0,t.useCallback)(e=>{F(e)},[]),z=(0,t.useCallback)(async()=>{if(!P)return;let t=E?.provider===`object`?E.object:e.objectName;if(!t||!i?.delete){F(null);return}let n=P.data?.id??P.data?._id??P.id;if(n==null){F(null);return}L(!0);let r=p;m(e=>e.filter(e=>String(e.id??e._id)!==String(n)));try{await i.delete(t,String(n)),F(null)}catch(e){console.error(`[ObjectGantt] Failed to delete:`,e),m(r),F(null)}finally{L(!1)}},[P,E,i,e.objectName,p]);return h?(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading Gantt chart...`})})}):_?(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsxs)(`div`,{className:`text-destructive`,children:[`Error: `,_.message]})})}):D?(0,l.jsxs)(`div`,{className:c,children:[(0,l.jsx)(`div`,{className:`h-[calc(100vh-200px)] min-h-[600px]`,children:(0,l.jsx)(x,{tasks:k,onTaskClick:e=>{M.handleClick(e.data),u?.(e.data)},onTaskUpdate:N,onTaskDelete:R,inlineEdit:!0})}),M.isOverlay&&M.isOpen&&M.selectedRecord&&(()=>{let t=E?.provider===`object`?E.object:e.objectName,n=M.selectedRecord,r=n.id??n._id;if(!t||r==null)return null;let o=D?.titleField?String(n[D.titleField]??`Task Details`):`Task Details`;return(0,l.jsx)(a.RecordDetailDrawer,{open:!0,onClose:M.close,title:o,record:n,objectName:t,recordId:r,dataSource:i,objectSchema:y,width:M.width,fullPageHref:(0,a.deriveRecordPageHref)(t,r)??void 0,onFieldSave:async(e,n)=>{i?.update&&(await i.update(t,String(r),{[e]:n}),m(t=>t.map(t=>String(t.id??t._id)===String(r)?{...t,[e]:n}:t)))},onDelete:async()=>{i?.delete&&(await i.delete(t,String(r)),m(e=>e.filter(e=>String(e.id??e._id)!==String(r))))}})})(),(0,l.jsx)(o.AlertDialog,{open:!!P,onOpenChange:e=>{!e&&!I&&F(null)},children:(0,l.jsxs)(o.AlertDialogContent,{children:[(0,l.jsxs)(o.AlertDialogHeader,{children:[(0,l.jsx)(o.AlertDialogTitle,{children:`Delete this task?`}),(0,l.jsx)(o.AlertDialogDescription,{children:P?(0,l.jsxs)(l.Fragment,{children:[`"`,P.title,`" will be permanently removed. This action cannot be undone.`]}):null})]}),(0,l.jsxs)(o.AlertDialogFooter,{children:[(0,l.jsx)(o.AlertDialogCancel,{disabled:I,children:`Cancel`}),(0,l.jsx)(o.AlertDialogAction,{onClick:e=>{e.preventDefault(),z()},disabled:I,"data-testid":`gantt-delete-confirm`,className:`bg-destructive text-destructive-foreground hover:bg-destructive/90`,children:I?`Deleting…`:`Delete`})]})]})})]}):(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsx)(`div`,{className:`text-muted-foreground`,children:`Gantt configuration required. Please specify startDateField, endDateField, and titleField.`})})})},E=({schema:e})=>{let{dataSource:t}=(0,r.useSchemaContext)()||{};return(0,l.jsx)(T,{schema:e,dataSource:t})};n.ComponentRegistry.register(`object-gantt`,E,{namespace:`plugin-gantt`,label:`Object Gantt`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),n.ComponentRegistry.register(`gantt`,E,{namespace:`view`,label:`Gantt View`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),e.GanttView=x,e.ObjectGantt=T,e.ObjectGanttRenderer=E});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectGantt.d.ts","sourceRoot":"","sources":["../../../../src/ObjectGantt.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAyB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"ObjectGantt.d.ts","sourceRoot":"","sources":["../../../../src/ObjectGantt.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAyB,MAAM,kBAAkB,CAAC;AAkB5F,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAClC;AAyFD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAuYlD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/plugin-gantt",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Gantt chart plugin for Object UI",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@objectstack/spec": "^4.0.5",
|
|
28
28
|
"lucide-react": "^1.14.0",
|
|
29
|
-
"@object-ui/components": "4.0.
|
|
30
|
-
"@object-ui/core": "4.0.
|
|
31
|
-
"@object-ui/fields": "4.0.
|
|
32
|
-
"@object-ui/plugin-detail": "4.0.
|
|
33
|
-
"@object-ui/react": "4.0.
|
|
34
|
-
"@object-ui/types": "4.0.
|
|
29
|
+
"@object-ui/components": "4.0.9",
|
|
30
|
+
"@object-ui/core": "4.0.9",
|
|
31
|
+
"@object-ui/fields": "4.0.9",
|
|
32
|
+
"@object-ui/plugin-detail": "4.0.9",
|
|
33
|
+
"@object-ui/react": "4.0.9",
|
|
34
|
+
"@object-ui/types": "4.0.9"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": "^18.0.0 || ^19.0.0",
|