@object-ui/plugin-gantt 5.0.1 → 5.0.2
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 +33 -0
- package/dist/index.js +244 -216
- package/dist/index.umd.cjs +1 -1
- package/dist/packages/plugin-gantt/src/GanttView.d.ts.map +1 -1
- package/dist/packages/plugin-gantt/src/useGanttTranslation.d.ts +22 -0
- package/dist/packages/plugin-gantt/src/useGanttTranslation.d.ts.map +1 -0
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @object-ui/plugin-gantt
|
|
2
2
|
|
|
3
|
+
## 5.0.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- cab6a93: **plugin-grid:** column summary footer now formats values using the
|
|
8
|
+
column's type metadata. Currency columns render `Sum: $1,760,000.00`
|
|
9
|
+
instead of bare `Sum: 1,760,000`; percent columns honor `0–1` vs
|
|
10
|
+
`0–100` value ranges; avg uses two fraction digits. `useColumnSummary`
|
|
11
|
+
accepts an optional `fieldMetadata` map (typically `objectSchema.fields`)
|
|
12
|
+
so per-field `type`, `currency`, `defaultCurrency`, `precision` are
|
|
13
|
+
respected.
|
|
14
|
+
|
|
15
|
+
**plugin-gantt:** added safe-fallback `useGanttTranslation` hook. All
|
|
16
|
+
hardcoded toolbar `aria-label`s and the `Task Name` / `Start` / `End` /
|
|
17
|
+
`Today` column-header strings now flow through `t('gantt.*')`. A new
|
|
18
|
+
`gantt.*` section is exported from the en/zh/ja/ko/de/fr/es/pt/ru/ar
|
|
19
|
+
locales.
|
|
20
|
+
|
|
21
|
+
**app-shell:** `ReportView` no longer hardcodes the `Edit` button label
|
|
22
|
+
or the `Loading report…` fallback — they now use `common.edit` and
|
|
23
|
+
`common.loading`.
|
|
24
|
+
|
|
25
|
+
**i18n:** added top-level `gantt` section (with English fallbacks in
|
|
26
|
+
non-en/zh locales) and the `common.addToFavorites` /
|
|
27
|
+
`common.removeFromFavorites` keys across all ten built-in locales so
|
|
28
|
+
the `builtInLocales` parity tests pass.
|
|
29
|
+
- @object-ui/components@5.0.2
|
|
30
|
+
- @object-ui/fields@5.0.2
|
|
31
|
+
- @object-ui/react@5.0.2
|
|
32
|
+
- @object-ui/plugin-detail@5.0.2
|
|
33
|
+
- @object-ui/types@5.0.2
|
|
34
|
+
- @object-ui/core@5.0.2
|
|
35
|
+
|
|
3
36
|
## 5.0.1
|
|
4
37
|
|
|
5
38
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -1,32 +1,60 @@
|
|
|
1
1
|
import * as e from "react";
|
|
2
2
|
import { useCallback as t, useEffect as n, useMemo as r, useState as i } from "react";
|
|
3
3
|
import { ComponentRegistry as a, buildExpandFields as o, extractRecords as s } from "@object-ui/core";
|
|
4
|
-
import { useNavigationOverlay as c,
|
|
5
|
-
import { GanttConfigSchema as
|
|
6
|
-
import { RecordDetailDrawer as
|
|
7
|
-
import { AlertDialog as
|
|
8
|
-
import { getSemanticColorName as
|
|
9
|
-
import { CalendarDays as
|
|
10
|
-
import { Fragment as
|
|
4
|
+
import { useNavigationOverlay as c, useObjectTranslation as l, useSchemaContext as u } from "@object-ui/react";
|
|
5
|
+
import { GanttConfigSchema as d } from "@objectstack/spec/ui";
|
|
6
|
+
import { RecordDetailDrawer as f, deriveRecordPageHref as p } from "@object-ui/plugin-detail";
|
|
7
|
+
import { AlertDialog as m, AlertDialogAction as h, AlertDialogCancel as g, AlertDialogContent as _, AlertDialogDescription as v, AlertDialogFooter as y, AlertDialogHeader as b, AlertDialogTitle as x, Button as S, cn as C, useResizeObserver as w } from "@object-ui/components";
|
|
8
|
+
import { getSemanticColorName as T, getSemanticHex as E } from "@object-ui/fields";
|
|
9
|
+
import { CalendarDays as ee, ChevronLeft as D, ChevronRight as O, PanelLeft as te, PanelLeftClose as k, ZoomIn as ne, ZoomOut as A } from "lucide-react";
|
|
10
|
+
import { Fragment as j, jsx as M, jsxs as N } from "react/jsx-runtime";
|
|
11
|
+
//#region src/useGanttTranslation.ts
|
|
12
|
+
var P = {
|
|
13
|
+
"gantt.column.taskName": "Task Name",
|
|
14
|
+
"gantt.column.start": "Start",
|
|
15
|
+
"gantt.column.end": "End",
|
|
16
|
+
"gantt.toolbar.prevPeriod": "Previous period",
|
|
17
|
+
"gantt.toolbar.nextPeriod": "Next period",
|
|
18
|
+
"gantt.toolbar.zoomIn": "Zoom in",
|
|
19
|
+
"gantt.toolbar.zoomOut": "Zoom out",
|
|
20
|
+
"gantt.toolbar.jumpToToday": "Jump to today",
|
|
21
|
+
"gantt.toolbar.today": "Today",
|
|
22
|
+
"gantt.toolbar.showTaskList": "Show task list",
|
|
23
|
+
"gantt.toolbar.hideTaskList": "Hide task list"
|
|
24
|
+
}, F = "gantt.column.taskName";
|
|
25
|
+
function I(e, t) {
|
|
26
|
+
let n = P[e] || e;
|
|
27
|
+
if (t) for (let [e, r] of Object.entries(t)) n = n.replace(`{{${e}}}`, String(r));
|
|
28
|
+
return n;
|
|
29
|
+
}
|
|
30
|
+
function re() {
|
|
31
|
+
try {
|
|
32
|
+
let e = l();
|
|
33
|
+
return e.t(F) === F ? { t: I } : { t: e.t };
|
|
34
|
+
} catch {
|
|
35
|
+
return { t: I };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
11
39
|
//#region src/GanttView.tsx
|
|
12
|
-
function
|
|
40
|
+
function L(e) {
|
|
13
41
|
return e < 640 ? 35 : e < 1024 ? 50 : 60;
|
|
14
42
|
}
|
|
15
|
-
function
|
|
43
|
+
function ie(e) {
|
|
16
44
|
return e < 640 ? 140 : e < 1024 ? 220 : 320;
|
|
17
45
|
}
|
|
18
|
-
function
|
|
46
|
+
function R(e) {
|
|
19
47
|
return e >= 280;
|
|
20
48
|
}
|
|
21
|
-
function
|
|
49
|
+
function ae(e) {
|
|
22
50
|
return e < 640 ? 32 : 40;
|
|
23
51
|
}
|
|
24
|
-
function
|
|
25
|
-
let
|
|
52
|
+
function z({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a, className: o, inlineEdit: s = !1 }) {
|
|
53
|
+
let { t: c } = re(), [l, u] = e.useState(/* @__PURE__ */ new Date()), d = e.useRef(null), { width: f } = w(d), p = f || (typeof window < "u" ? window.innerWidth : 1024), m = p < 640, h = ae(p), g = L(p), [_, v] = e.useState(null), y = _ ?? g, [b, x] = e.useState(!1), T = e.useRef(!1);
|
|
26
54
|
e.useEffect(() => {
|
|
27
|
-
!
|
|
28
|
-
}, [
|
|
29
|
-
let
|
|
55
|
+
!T.current && m && (x(!0), T.current = !0);
|
|
56
|
+
}, [m]);
|
|
57
|
+
let E = b ? 0 : ie(p), P = R(E), [F, I] = e.useState(null), [z, B] = e.useState({}), [V, H] = e.useState(null), U = e.useRef(null);
|
|
30
58
|
e.useEffect(() => {
|
|
31
59
|
U.current = V;
|
|
32
60
|
}, [V]);
|
|
@@ -42,7 +70,7 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
42
70
|
let e = (e) => {
|
|
43
71
|
let t = U.current;
|
|
44
72
|
if (!t) return;
|
|
45
|
-
let n = Math.round((e.clientX - t.originClientX) / Math.max(
|
|
73
|
+
let n = Math.round((e.clientX - t.originClientX) / Math.max(y, 1));
|
|
46
74
|
n !== t.dayDelta && H({
|
|
47
75
|
...t,
|
|
48
76
|
dayDelta: n
|
|
@@ -71,7 +99,7 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
71
99
|
};
|
|
72
100
|
}, [
|
|
73
101
|
V,
|
|
74
|
-
|
|
102
|
+
y,
|
|
75
103
|
t,
|
|
76
104
|
a,
|
|
77
105
|
G
|
|
@@ -103,65 +131,65 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
103
131
|
isWeekend: t.getDay() === 0 || t.getDay() === 6
|
|
104
132
|
}), t.setDate(t.getDate() + 1);
|
|
105
133
|
return e;
|
|
106
|
-
}, [q]), Y = e.useRef(null), X = e.useRef(null),
|
|
134
|
+
}, [q]), Y = e.useRef(null), X = e.useRef(null), oe = e.useRef(null), Z = e.useRef(null), Q = e.useRef(null), se = e.useCallback((e) => {
|
|
107
135
|
if (e.touches.length === 2) {
|
|
108
136
|
let t = e.touches[0].clientX - e.touches[1].clientX, n = e.touches[0].clientY - e.touches[1].clientY;
|
|
109
137
|
Q.current = {
|
|
110
138
|
baseDistance: Math.max(1, Math.sqrt(t * t + n * n)),
|
|
111
|
-
baseColumn:
|
|
139
|
+
baseColumn: y
|
|
112
140
|
};
|
|
113
141
|
}
|
|
114
|
-
}, [
|
|
142
|
+
}, [y]), ce = e.useCallback((e) => {
|
|
115
143
|
if (e.touches.length !== 2 || !Q.current) return;
|
|
116
144
|
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;
|
|
117
|
-
|
|
118
|
-
}, []),
|
|
145
|
+
v(Math.max(15, Math.min(120, Math.round(Q.current.baseColumn * r))));
|
|
146
|
+
}, []), le = e.useCallback(() => {
|
|
119
147
|
Q.current = null;
|
|
120
148
|
}, []), $ = e.useMemo(() => {
|
|
121
149
|
let e = /* @__PURE__ */ new Date();
|
|
122
150
|
if (e < q.start || e > q.end) return null;
|
|
123
151
|
let t = (e.getTime() - q.start.getTime()) / (1440 * 60 * 1e3);
|
|
124
|
-
return Math.round(t *
|
|
125
|
-
}, [q,
|
|
152
|
+
return Math.round(t * y);
|
|
153
|
+
}, [q, y]), ue = e.useCallback(() => {
|
|
126
154
|
if ($ == null || !Z.current) return;
|
|
127
155
|
let e = Math.max(0, $ - Z.current.clientWidth / 2);
|
|
128
156
|
Z.current.scrollTo({
|
|
129
157
|
left: e,
|
|
130
158
|
behavior: "smooth"
|
|
131
159
|
});
|
|
132
|
-
}, [$]),
|
|
160
|
+
}, [$]), de = (e) => {
|
|
133
161
|
Y.current && (Y.current.scrollLeft = e.currentTarget.scrollLeft), X.current && (X.current.scrollTop = e.currentTarget.scrollTop);
|
|
134
|
-
},
|
|
162
|
+
}, fe = (e) => {
|
|
135
163
|
q.end.getTime() - q.start.getTime();
|
|
136
|
-
let t =
|
|
164
|
+
let t = y, n = 1e3 * 60 * 60 * 24, r = e.start.getTime() - q.start.getTime(), i = e.end.getTime() - e.start.getTime();
|
|
137
165
|
return {
|
|
138
166
|
left: r / n * t,
|
|
139
167
|
width: Math.max(i / n * t, t)
|
|
140
168
|
};
|
|
141
169
|
};
|
|
142
|
-
return /* @__PURE__ */
|
|
143
|
-
ref:
|
|
144
|
-
className:
|
|
145
|
-
children: [/* @__PURE__ */
|
|
170
|
+
return /* @__PURE__ */ N("div", {
|
|
171
|
+
ref: d,
|
|
172
|
+
className: C("flex flex-col h-full bg-background overflow-hidden min-w-0", o),
|
|
173
|
+
children: [/* @__PURE__ */ N("div", {
|
|
146
174
|
className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 p-2 border-b bg-card",
|
|
147
|
-
children: [/* @__PURE__ */
|
|
175
|
+
children: [/* @__PURE__ */ N("div", {
|
|
148
176
|
className: "flex items-center gap-2",
|
|
149
177
|
children: [
|
|
150
|
-
/* @__PURE__ */
|
|
178
|
+
/* @__PURE__ */ M(S, {
|
|
151
179
|
variant: "ghost",
|
|
152
180
|
size: "icon",
|
|
153
181
|
className: "h-8 w-8",
|
|
154
|
-
"aria-label": "
|
|
155
|
-
children: /* @__PURE__ */
|
|
182
|
+
"aria-label": c("gantt.toolbar.prevPeriod"),
|
|
183
|
+
children: /* @__PURE__ */ M(D, { className: "h-4 w-4" })
|
|
156
184
|
}),
|
|
157
|
-
/* @__PURE__ */
|
|
185
|
+
/* @__PURE__ */ M(S, {
|
|
158
186
|
variant: "ghost",
|
|
159
187
|
size: "icon",
|
|
160
188
|
className: "h-8 w-8",
|
|
161
|
-
"aria-label": "
|
|
162
|
-
children: /* @__PURE__ */
|
|
189
|
+
"aria-label": c("gantt.toolbar.nextPeriod"),
|
|
190
|
+
children: /* @__PURE__ */ M(O, { className: "h-4 w-4" })
|
|
163
191
|
}),
|
|
164
|
-
/* @__PURE__ */
|
|
192
|
+
/* @__PURE__ */ M("span", {
|
|
165
193
|
className: "font-semibold text-xs sm:text-sm",
|
|
166
194
|
children: q.start.toLocaleDateString(void 0, {
|
|
167
195
|
month: "long",
|
|
@@ -169,108 +197,108 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
169
197
|
})
|
|
170
198
|
})
|
|
171
199
|
]
|
|
172
|
-
}), /* @__PURE__ */
|
|
200
|
+
}), /* @__PURE__ */ N("div", {
|
|
173
201
|
className: "flex items-center gap-2",
|
|
174
202
|
children: [
|
|
175
|
-
/* @__PURE__ */
|
|
203
|
+
/* @__PURE__ */ N("div", {
|
|
176
204
|
className: "flex bg-muted rounded-md p-1",
|
|
177
|
-
children: [/* @__PURE__ */
|
|
205
|
+
children: [/* @__PURE__ */ M(S, {
|
|
178
206
|
variant: "ghost",
|
|
179
207
|
size: "icon",
|
|
180
208
|
className: "h-6 w-6",
|
|
181
|
-
onClick: () =>
|
|
182
|
-
"aria-label": "
|
|
183
|
-
children: /* @__PURE__ */
|
|
184
|
-
}), /* @__PURE__ */
|
|
209
|
+
onClick: () => v(Math.max(15, y - 10)),
|
|
210
|
+
"aria-label": c("gantt.toolbar.zoomOut"),
|
|
211
|
+
children: /* @__PURE__ */ M(A, { className: "h-3 w-3" })
|
|
212
|
+
}), /* @__PURE__ */ M(S, {
|
|
185
213
|
variant: "ghost",
|
|
186
214
|
size: "icon",
|
|
187
215
|
className: "h-6 w-6",
|
|
188
|
-
onClick: () =>
|
|
189
|
-
"aria-label": "
|
|
190
|
-
children: /* @__PURE__ */
|
|
216
|
+
onClick: () => v(Math.min(120, y + 10)),
|
|
217
|
+
"aria-label": c("gantt.toolbar.zoomIn"),
|
|
218
|
+
children: /* @__PURE__ */ M(ne, { className: "h-3 w-3" })
|
|
191
219
|
})]
|
|
192
220
|
}),
|
|
193
|
-
/* @__PURE__ */
|
|
221
|
+
/* @__PURE__ */ M(S, {
|
|
194
222
|
variant: "ghost",
|
|
195
223
|
size: "icon",
|
|
196
224
|
className: "h-8 w-8",
|
|
197
|
-
onClick: () =>
|
|
198
|
-
"aria-label":
|
|
199
|
-
"aria-pressed":
|
|
225
|
+
onClick: () => x((e) => !e),
|
|
226
|
+
"aria-label": c(b ? "gantt.toolbar.showTaskList" : "gantt.toolbar.hideTaskList"),
|
|
227
|
+
"aria-pressed": b,
|
|
200
228
|
"data-testid": "gantt-toggle-task-list",
|
|
201
|
-
children:
|
|
229
|
+
children: M(b ? te : k, { className: "h-4 w-4" })
|
|
202
230
|
}),
|
|
203
|
-
/* @__PURE__ */
|
|
231
|
+
/* @__PURE__ */ M(S, {
|
|
204
232
|
variant: "ghost",
|
|
205
233
|
size: "icon",
|
|
206
234
|
className: "h-8 w-8",
|
|
207
|
-
onClick:
|
|
235
|
+
onClick: ue,
|
|
208
236
|
disabled: $ == null,
|
|
209
|
-
"aria-label": "
|
|
237
|
+
"aria-label": c("gantt.toolbar.jumpToToday"),
|
|
210
238
|
"data-testid": "gantt-jump-today",
|
|
211
|
-
children: /* @__PURE__ */
|
|
239
|
+
children: /* @__PURE__ */ M(ee, { className: "h-4 w-4" })
|
|
212
240
|
})
|
|
213
241
|
]
|
|
214
242
|
})]
|
|
215
|
-
}), /* @__PURE__ */
|
|
243
|
+
}), /* @__PURE__ */ N("div", {
|
|
216
244
|
className: "flex flex-col flex-1 overflow-hidden",
|
|
217
|
-
children: [/* @__PURE__ */
|
|
245
|
+
children: [/* @__PURE__ */ N("div", {
|
|
218
246
|
className: "flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]",
|
|
219
|
-
children: [/* @__PURE__ */
|
|
247
|
+
children: [/* @__PURE__ */ N("div", {
|
|
220
248
|
className: "flex items-center font-medium text-xs text-muted-foreground px-2 sm:px-4 border-r bg-card z-20 shadow-sm",
|
|
221
249
|
style: {
|
|
222
|
-
width:
|
|
223
|
-
minWidth:
|
|
250
|
+
width: E,
|
|
251
|
+
minWidth: E
|
|
224
252
|
},
|
|
225
|
-
children: [/* @__PURE__ */
|
|
253
|
+
children: [/* @__PURE__ */ M("div", {
|
|
226
254
|
className: "flex-1 truncate",
|
|
227
|
-
children: "
|
|
228
|
-
}),
|
|
255
|
+
children: c("gantt.column.taskName")
|
|
256
|
+
}), P && /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ M("div", {
|
|
229
257
|
className: "w-16 sm:w-20 text-right",
|
|
230
|
-
children: "
|
|
231
|
-
}), /* @__PURE__ */
|
|
258
|
+
children: c("gantt.column.start")
|
|
259
|
+
}), /* @__PURE__ */ M("div", {
|
|
232
260
|
className: "w-16 sm:w-20 text-right",
|
|
233
|
-
children: "
|
|
261
|
+
children: c("gantt.column.end")
|
|
234
262
|
})] })]
|
|
235
|
-
}), /* @__PURE__ */
|
|
263
|
+
}), /* @__PURE__ */ M("div", {
|
|
236
264
|
className: "flex-1 overflow-hidden",
|
|
237
265
|
ref: Y,
|
|
238
|
-
children: /* @__PURE__ */
|
|
266
|
+
children: /* @__PURE__ */ M("div", {
|
|
239
267
|
className: "flex h-full",
|
|
240
|
-
style: { width: J.length *
|
|
241
|
-
children: J.map((e, t) => /* @__PURE__ */
|
|
242
|
-
className:
|
|
268
|
+
style: { width: J.length * y },
|
|
269
|
+
children: J.map((e, t) => /* @__PURE__ */ N("div", {
|
|
270
|
+
className: C("flex flex-col items-center justify-center border-r text-xs text-muted-foreground h-full", e.isWeekend && "bg-muted/50"),
|
|
243
271
|
style: {
|
|
244
|
-
width:
|
|
245
|
-
minWidth:
|
|
272
|
+
width: y,
|
|
273
|
+
minWidth: y
|
|
246
274
|
},
|
|
247
|
-
children: [/* @__PURE__ */
|
|
275
|
+
children: [/* @__PURE__ */ M("span", {
|
|
248
276
|
className: "font-medium text-foreground",
|
|
249
277
|
children: e.label
|
|
250
|
-
}), /* @__PURE__ */
|
|
278
|
+
}), /* @__PURE__ */ M("span", {
|
|
251
279
|
className: "text-[10px] opacity-70",
|
|
252
280
|
children: e.date.toLocaleDateString(void 0, { weekday: "narrow" })
|
|
253
281
|
})]
|
|
254
282
|
}, t))
|
|
255
283
|
})
|
|
256
284
|
})]
|
|
257
|
-
}), /* @__PURE__ */
|
|
285
|
+
}), /* @__PURE__ */ N("div", {
|
|
258
286
|
className: "flex flex-1 overflow-hidden",
|
|
259
|
-
children: [/* @__PURE__ */
|
|
287
|
+
children: [/* @__PURE__ */ M("div", {
|
|
260
288
|
className: "overflow-hidden border-r bg-card z-10 shadow-sm",
|
|
261
289
|
ref: X,
|
|
262
290
|
style: {
|
|
263
|
-
width:
|
|
264
|
-
minWidth:
|
|
291
|
+
width: E,
|
|
292
|
+
minWidth: E
|
|
265
293
|
},
|
|
266
294
|
children: t.map((e) => {
|
|
267
|
-
let t = s &&
|
|
268
|
-
return /* @__PURE__ */
|
|
295
|
+
let t = s && F === e.id;
|
|
296
|
+
return /* @__PURE__ */ N("div", {
|
|
269
297
|
className: "group/task-row flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation",
|
|
270
|
-
style: { height:
|
|
298
|
+
style: { height: h },
|
|
271
299
|
onClick: () => !t && i?.(e),
|
|
272
300
|
onDoubleClick: () => {
|
|
273
|
-
s && a && (
|
|
301
|
+
s && a && (I(e.id), B({
|
|
274
302
|
title: e.title,
|
|
275
303
|
start: e.start.toLocaleDateString("en-CA"),
|
|
276
304
|
end: e.end.toLocaleDateString("en-CA"),
|
|
@@ -278,12 +306,12 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
278
306
|
}));
|
|
279
307
|
},
|
|
280
308
|
children: [
|
|
281
|
-
/* @__PURE__ */
|
|
309
|
+
/* @__PURE__ */ N("div", {
|
|
282
310
|
className: "flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2",
|
|
283
|
-
children: [/* @__PURE__ */
|
|
311
|
+
children: [/* @__PURE__ */ M("div", {
|
|
284
312
|
className: "w-2 h-2 rounded-full shrink-0",
|
|
285
313
|
style: { backgroundColor: e.color || "#3b82f6" }
|
|
286
|
-
}), t ? /* @__PURE__ */
|
|
314
|
+
}), t ? /* @__PURE__ */ M("input", {
|
|
287
315
|
className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
|
|
288
316
|
value: z.title || "",
|
|
289
317
|
onChange: (e) => B((t) => ({
|
|
@@ -296,16 +324,16 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
296
324
|
start: new Date(z.start),
|
|
297
325
|
end: new Date(z.end),
|
|
298
326
|
progress: Number(z.progress) || 0
|
|
299
|
-
}),
|
|
327
|
+
}), I(null)) : t.key === "Escape" && I(null);
|
|
300
328
|
},
|
|
301
329
|
onClick: (e) => e.stopPropagation(),
|
|
302
330
|
autoFocus: !0
|
|
303
|
-
}) : /* @__PURE__ */
|
|
331
|
+
}) : /* @__PURE__ */ N("span", {
|
|
304
332
|
className: "flex flex-col min-w-0",
|
|
305
|
-
children: [/* @__PURE__ */
|
|
333
|
+
children: [/* @__PURE__ */ M("span", {
|
|
306
334
|
className: "truncate",
|
|
307
335
|
children: e.title
|
|
308
|
-
}), /* @__PURE__ */
|
|
336
|
+
}), /* @__PURE__ */ N("span", {
|
|
309
337
|
className: "text-[10px] text-muted-foreground sm:hidden",
|
|
310
338
|
children: [
|
|
311
339
|
e.start.toLocaleDateString(void 0, {
|
|
@@ -321,11 +349,11 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
321
349
|
})]
|
|
322
350
|
})]
|
|
323
351
|
}),
|
|
324
|
-
/* @__PURE__ */
|
|
352
|
+
/* @__PURE__ */ M("div", {
|
|
325
353
|
className: "w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block",
|
|
326
|
-
hidden: !
|
|
327
|
-
style:
|
|
328
|
-
children: t ? /* @__PURE__ */
|
|
354
|
+
hidden: !P,
|
|
355
|
+
style: P ? void 0 : { display: "none" },
|
|
356
|
+
children: t ? /* @__PURE__ */ M("input", {
|
|
329
357
|
type: "date",
|
|
330
358
|
className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
|
|
331
359
|
value: z.start || "",
|
|
@@ -339,11 +367,11 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
339
367
|
day: "numeric"
|
|
340
368
|
})
|
|
341
369
|
}),
|
|
342
|
-
/* @__PURE__ */
|
|
370
|
+
/* @__PURE__ */ M("div", {
|
|
343
371
|
className: "w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block",
|
|
344
|
-
hidden: !
|
|
345
|
-
style:
|
|
346
|
-
children: t ? /* @__PURE__ */
|
|
372
|
+
hidden: !P,
|
|
373
|
+
style: P ? void 0 : { display: "none" },
|
|
374
|
+
children: t ? /* @__PURE__ */ M("input", {
|
|
347
375
|
type: "date",
|
|
348
376
|
className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
|
|
349
377
|
value: z.end || "",
|
|
@@ -360,56 +388,56 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
360
388
|
]
|
|
361
389
|
}, e.id);
|
|
362
390
|
})
|
|
363
|
-
}), /* @__PURE__ */
|
|
391
|
+
}), /* @__PURE__ */ M("div", {
|
|
364
392
|
className: "flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]",
|
|
365
393
|
ref: (e) => {
|
|
366
|
-
|
|
394
|
+
oe.current = e, Z.current = e;
|
|
367
395
|
},
|
|
368
|
-
onScroll:
|
|
369
|
-
onTouchStart:
|
|
370
|
-
onTouchMove:
|
|
371
|
-
onTouchEnd:
|
|
396
|
+
onScroll: de,
|
|
397
|
+
onTouchStart: se,
|
|
398
|
+
onTouchMove: ce,
|
|
399
|
+
onTouchEnd: le,
|
|
372
400
|
"data-testid": "gantt-timeline",
|
|
373
|
-
children: /* @__PURE__ */
|
|
401
|
+
children: /* @__PURE__ */ N("div", {
|
|
374
402
|
className: "relative",
|
|
375
|
-
style: { width: J.length *
|
|
376
|
-
children: [$ != null && /* @__PURE__ */
|
|
403
|
+
style: { width: J.length * y },
|
|
404
|
+
children: [$ != null && /* @__PURE__ */ M("div", {
|
|
377
405
|
className: "absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none",
|
|
378
406
|
style: { left: $ },
|
|
379
407
|
"data-testid": "gantt-today-marker",
|
|
380
|
-
"aria-label": "
|
|
381
|
-
children: /* @__PURE__ */
|
|
408
|
+
"aria-label": c("gantt.toolbar.today"),
|
|
409
|
+
children: /* @__PURE__ */ M("div", {
|
|
382
410
|
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",
|
|
383
|
-
children: "
|
|
411
|
+
children: c("gantt.toolbar.today")
|
|
384
412
|
})
|
|
385
|
-
}), /* @__PURE__ */
|
|
413
|
+
}), /* @__PURE__ */ N("div", {
|
|
386
414
|
className: "relative",
|
|
387
415
|
children: [
|
|
388
|
-
/* @__PURE__ */
|
|
416
|
+
/* @__PURE__ */ M("div", {
|
|
389
417
|
className: "absolute inset-0 flex pointer-events-none z-0",
|
|
390
|
-
children: J.map((e, t) => /* @__PURE__ */
|
|
391
|
-
className:
|
|
418
|
+
children: J.map((e, t) => /* @__PURE__ */ M("div", {
|
|
419
|
+
className: C("border-r h-full", e.isWeekend && "bg-muted/20"),
|
|
392
420
|
style: {
|
|
393
|
-
width:
|
|
394
|
-
minWidth:
|
|
421
|
+
width: y,
|
|
422
|
+
minWidth: y
|
|
395
423
|
}
|
|
396
424
|
}, t))
|
|
397
425
|
}),
|
|
398
426
|
t.map((e) => {
|
|
399
|
-
let t =
|
|
427
|
+
let t = fe(e), n = V?.taskId === e.id, r = t;
|
|
400
428
|
if (n && V) {
|
|
401
429
|
let t = G(V);
|
|
402
|
-
r =
|
|
430
|
+
r = fe({
|
|
403
431
|
...e,
|
|
404
432
|
start: t.start,
|
|
405
433
|
end: t.end
|
|
406
434
|
});
|
|
407
435
|
}
|
|
408
436
|
let o = !!a;
|
|
409
|
-
return /* @__PURE__ */
|
|
437
|
+
return /* @__PURE__ */ N("div", {
|
|
410
438
|
className: "relative border-b hover:bg-black/5",
|
|
411
|
-
style: { height:
|
|
412
|
-
children: [n && /* @__PURE__ */
|
|
439
|
+
style: { height: h },
|
|
440
|
+
children: [n && /* @__PURE__ */ M("div", {
|
|
413
441
|
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",
|
|
414
442
|
style: {
|
|
415
443
|
left: t.left,
|
|
@@ -417,8 +445,8 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
417
445
|
opacity: .35
|
|
418
446
|
},
|
|
419
447
|
"aria-hidden": "true"
|
|
420
|
-
}), /* @__PURE__ */
|
|
421
|
-
className:
|
|
448
|
+
}), /* @__PURE__ */ N("div", {
|
|
449
|
+
className: C("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"),
|
|
422
450
|
style: {
|
|
423
451
|
left: r.left,
|
|
424
452
|
width: r.width,
|
|
@@ -432,14 +460,14 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
432
460
|
t.button === 0 && K(e, "move", t);
|
|
433
461
|
} : void 0,
|
|
434
462
|
children: [
|
|
435
|
-
o && r.width >= 14 && /* @__PURE__ */
|
|
463
|
+
o && r.width >= 14 && /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ M("div", {
|
|
436
464
|
className: "absolute left-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40",
|
|
437
465
|
"data-testid": `gantt-task-resize-left-${e.id}`,
|
|
438
466
|
onPointerDown: (t) => {
|
|
439
467
|
t.button === 0 && K(e, "resize-left", t);
|
|
440
468
|
},
|
|
441
469
|
onClick: (e) => e.stopPropagation()
|
|
442
|
-
}), /* @__PURE__ */
|
|
470
|
+
}), /* @__PURE__ */ M("div", {
|
|
443
471
|
className: "absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40",
|
|
444
472
|
"data-testid": `gantt-task-resize-right-${e.id}`,
|
|
445
473
|
onPointerDown: (t) => {
|
|
@@ -447,11 +475,11 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
447
475
|
},
|
|
448
476
|
onClick: (e) => e.stopPropagation()
|
|
449
477
|
})] }),
|
|
450
|
-
e.progress > 0 && /* @__PURE__ */
|
|
478
|
+
e.progress > 0 && /* @__PURE__ */ M("div", {
|
|
451
479
|
className: "absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm pointer-events-none",
|
|
452
480
|
style: { width: `${e.progress}%` }
|
|
453
481
|
}),
|
|
454
|
-
/* @__PURE__ */
|
|
482
|
+
/* @__PURE__ */ M("span", {
|
|
455
483
|
className: "text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none",
|
|
456
484
|
children: n ? `${G(V).start.toLocaleDateString(void 0, {
|
|
457
485
|
month: "numeric",
|
|
@@ -465,10 +493,10 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
465
493
|
})]
|
|
466
494
|
}, e.id);
|
|
467
495
|
}),
|
|
468
|
-
/* @__PURE__ */
|
|
496
|
+
/* @__PURE__ */ M("div", {
|
|
469
497
|
className: "absolute top-0 bottom-0 w-px bg-red-500 z-20 pointer-events-none",
|
|
470
|
-
style: { left: ((/* @__PURE__ */ new Date()).getTime() - q.start.getTime()) / (1e3 * 60 * 60 * 24) *
|
|
471
|
-
children: /* @__PURE__ */
|
|
498
|
+
style: { left: ((/* @__PURE__ */ new Date()).getTime() - q.start.getTime()) / (1e3 * 60 * 60 * 24) * y },
|
|
499
|
+
children: /* @__PURE__ */ M("div", { className: "w-2 h-2 rounded-full bg-red-500 -ml-[3px]" })
|
|
472
500
|
})
|
|
473
501
|
]
|
|
474
502
|
})]
|
|
@@ -480,7 +508,7 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
|
|
|
480
508
|
}
|
|
481
509
|
//#endregion
|
|
482
510
|
//#region src/ObjectGantt.tsx
|
|
483
|
-
function
|
|
511
|
+
function B(e) {
|
|
484
512
|
return e.data ? e.data : e.staticData ? {
|
|
485
513
|
provider: "value",
|
|
486
514
|
items: e.staticData
|
|
@@ -489,7 +517,7 @@ function re(e) {
|
|
|
489
517
|
object: e.objectName
|
|
490
518
|
} : null;
|
|
491
519
|
}
|
|
492
|
-
function
|
|
520
|
+
function V(e) {
|
|
493
521
|
if (e) {
|
|
494
522
|
if (typeof e == "string") {
|
|
495
523
|
let t = e.split(" "), n = t[0], r = t[1]?.toLowerCase() === "desc" ? "desc" : "asc";
|
|
@@ -498,7 +526,7 @@ function R(e) {
|
|
|
498
526
|
if (Array.isArray(e)) return e.reduce((e, t) => (t.field && t.order && (e[t.field] = t.order), e), {});
|
|
499
527
|
}
|
|
500
528
|
}
|
|
501
|
-
function
|
|
529
|
+
function H(e) {
|
|
502
530
|
let t = null;
|
|
503
531
|
if (e.startDateField && e.endDateField) return t = {
|
|
504
532
|
startDateField: e.startDateField,
|
|
@@ -509,33 +537,33 @@ function z(e) {
|
|
|
509
537
|
colorField: e.colorField
|
|
510
538
|
}, t;
|
|
511
539
|
if (e.gantt && (t = e.gantt), t) {
|
|
512
|
-
let e =
|
|
540
|
+
let e = d.safeParse(t);
|
|
513
541
|
return e.success || console.warn("[ObjectGantt] Invalid gantt configuration:", e.error.format()), t;
|
|
514
542
|
}
|
|
515
543
|
return null;
|
|
516
544
|
}
|
|
517
|
-
var
|
|
518
|
-
let [
|
|
545
|
+
var U = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: d, ...S }) => {
|
|
546
|
+
let [C, w] = i([]), [ee, D] = i(!0), [O, te] = i(null), [k, ne] = i(null), A = B(e), P = r(() => A, [JSON.stringify(A)]), F = H(e), I = P?.provider === "value";
|
|
519
547
|
n(() => {
|
|
520
548
|
(async () => {
|
|
521
549
|
try {
|
|
522
|
-
if (D(!0),
|
|
523
|
-
|
|
550
|
+
if (D(!0), S.data && Array.isArray(S.data)) {
|
|
551
|
+
w(S.data), D(!1);
|
|
524
552
|
return;
|
|
525
553
|
}
|
|
526
554
|
if (I && P?.provider === "value") {
|
|
527
|
-
|
|
555
|
+
w(P.items), D(!1);
|
|
528
556
|
return;
|
|
529
557
|
}
|
|
530
558
|
if (!a || typeof a.find != "function") throw Error("DataSource required for object/api providers");
|
|
531
559
|
if (P?.provider === "object") {
|
|
532
560
|
let t = P.object, n = o(k?.fields);
|
|
533
|
-
|
|
561
|
+
w(s(await a.find(t, {
|
|
534
562
|
$filter: e.filter,
|
|
535
|
-
$orderby:
|
|
563
|
+
$orderby: V(e.sort),
|
|
536
564
|
...n.length > 0 ? { $expand: n } : {}
|
|
537
565
|
})));
|
|
538
|
-
} else P?.provider === "api" && (console.warn("API provider not yet implemented for ObjectGantt"),
|
|
566
|
+
} else P?.provider === "api" && (console.warn("API provider not yet implemented for ObjectGantt"), w([]));
|
|
539
567
|
D(!1);
|
|
540
568
|
} catch (e) {
|
|
541
569
|
te(e), D(!1);
|
|
@@ -565,8 +593,8 @@ var B = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: b
|
|
|
565
593
|
I,
|
|
566
594
|
P
|
|
567
595
|
]);
|
|
568
|
-
let
|
|
569
|
-
if (!F || !
|
|
596
|
+
let re = r(() => {
|
|
597
|
+
if (!F || !C.length) return [];
|
|
570
598
|
let { startDateField: e, endDateField: t, titleField: n, progressField: r, dependenciesField: i, colorField: a } = F, o = (e, t) => {
|
|
571
599
|
if (!t) return;
|
|
572
600
|
let n = t.split("."), r = e;
|
|
@@ -591,13 +619,13 @@ var B = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: b
|
|
|
591
619
|
for (let e of t) if (e != null && String(e).trim() !== "") return String(e);
|
|
592
620
|
return "Untitled";
|
|
593
621
|
};
|
|
594
|
-
return
|
|
622
|
+
return C.map((n, o) => {
|
|
595
623
|
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
624
|
if (!p) {
|
|
597
625
|
let e = n.status ?? n.state ?? n.priority ?? n.severity;
|
|
598
626
|
if (e != null && e !== "") {
|
|
599
|
-
let t =
|
|
600
|
-
t && (p =
|
|
627
|
+
let t = T(void 0, e);
|
|
628
|
+
t && (p = E(t));
|
|
601
629
|
}
|
|
602
630
|
}
|
|
603
631
|
return {
|
|
@@ -611,14 +639,14 @@ var B = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: b
|
|
|
611
639
|
data: n
|
|
612
640
|
};
|
|
613
641
|
}).filter((e) => !isNaN(e.start.getTime()) && !isNaN(e.end.getTime()));
|
|
614
|
-
}, [
|
|
642
|
+
}, [C, F]), L = e.navigation ?? {
|
|
615
643
|
mode: "drawer",
|
|
616
644
|
width: "min(960px, 60vw)"
|
|
617
|
-
},
|
|
618
|
-
navigation:
|
|
645
|
+
}, ie = L.mode === "drawer" || L.mode === "modal" || L.mode === "split" || L.mode === "popover", R = c({
|
|
646
|
+
navigation: L,
|
|
619
647
|
objectName: e.objectName,
|
|
620
|
-
onRowClick:
|
|
621
|
-
}),
|
|
648
|
+
onRowClick: ie ? void 0 : d
|
|
649
|
+
}), ae = t(async (t, n) => {
|
|
622
650
|
if (!F) return;
|
|
623
651
|
let r = P?.provider === "object" ? P.object : e.objectName;
|
|
624
652
|
if (!r || !a || typeof a.update != "function") return;
|
|
@@ -626,153 +654,153 @@ var B = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: b
|
|
|
626
654
|
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;
|
|
627
655
|
let u = t.data?.id ?? t.data?._id ?? t.id;
|
|
628
656
|
if (u == null) return;
|
|
629
|
-
let d =
|
|
630
|
-
|
|
657
|
+
let d = C;
|
|
658
|
+
w((e) => e.map((e) => String(e.id ?? e._id) === String(u) ? {
|
|
631
659
|
...e,
|
|
632
660
|
...l
|
|
633
661
|
} : e));
|
|
634
662
|
try {
|
|
635
663
|
await a.update(r, String(u), l);
|
|
636
664
|
} catch (e) {
|
|
637
|
-
console.error("[ObjectGantt] Failed to persist task update:", e),
|
|
665
|
+
console.error("[ObjectGantt] Failed to persist task update:", e), w(d);
|
|
638
666
|
}
|
|
639
667
|
}, [
|
|
640
668
|
F,
|
|
641
669
|
P,
|
|
642
670
|
a,
|
|
643
671
|
e.objectName,
|
|
644
|
-
|
|
645
|
-
]), [
|
|
646
|
-
|
|
647
|
-
}, []),
|
|
648
|
-
if (!
|
|
672
|
+
C
|
|
673
|
+
]), [U, W] = i(null), [G, K] = i(!1), q = t((e) => {
|
|
674
|
+
W(e);
|
|
675
|
+
}, []), J = t(async () => {
|
|
676
|
+
if (!U) return;
|
|
649
677
|
let t = P?.provider === "object" ? P.object : e.objectName;
|
|
650
678
|
if (!t || !a?.delete) {
|
|
651
|
-
|
|
679
|
+
W(null);
|
|
652
680
|
return;
|
|
653
681
|
}
|
|
654
|
-
let n =
|
|
682
|
+
let n = U.data?.id ?? U.data?._id ?? U.id;
|
|
655
683
|
if (n == null) {
|
|
656
|
-
|
|
684
|
+
W(null);
|
|
657
685
|
return;
|
|
658
686
|
}
|
|
659
|
-
|
|
660
|
-
let r =
|
|
661
|
-
|
|
687
|
+
K(!0);
|
|
688
|
+
let r = C;
|
|
689
|
+
w((e) => e.filter((e) => String(e.id ?? e._id) !== String(n)));
|
|
662
690
|
try {
|
|
663
|
-
await a.delete(t, String(n)),
|
|
691
|
+
await a.delete(t, String(n)), W(null);
|
|
664
692
|
} catch (e) {
|
|
665
|
-
console.error("[ObjectGantt] Failed to delete:", e),
|
|
693
|
+
console.error("[ObjectGantt] Failed to delete:", e), w(r), W(null);
|
|
666
694
|
} finally {
|
|
667
|
-
|
|
695
|
+
K(!1);
|
|
668
696
|
}
|
|
669
697
|
}, [
|
|
670
|
-
|
|
698
|
+
U,
|
|
671
699
|
P,
|
|
672
700
|
a,
|
|
673
701
|
e.objectName,
|
|
674
|
-
|
|
702
|
+
C
|
|
675
703
|
]);
|
|
676
|
-
return
|
|
704
|
+
return ee ? /* @__PURE__ */ M("div", {
|
|
677
705
|
className: l,
|
|
678
|
-
children: /* @__PURE__ */
|
|
706
|
+
children: /* @__PURE__ */ M("div", {
|
|
679
707
|
className: "flex items-center justify-center h-96",
|
|
680
|
-
children: /* @__PURE__ */
|
|
708
|
+
children: /* @__PURE__ */ M("div", {
|
|
681
709
|
className: "text-muted-foreground",
|
|
682
710
|
children: "Loading Gantt chart..."
|
|
683
711
|
})
|
|
684
712
|
})
|
|
685
|
-
}) : O ? /* @__PURE__ */
|
|
713
|
+
}) : O ? /* @__PURE__ */ M("div", {
|
|
686
714
|
className: l,
|
|
687
|
-
children: /* @__PURE__ */
|
|
715
|
+
children: /* @__PURE__ */ M("div", {
|
|
688
716
|
className: "flex items-center justify-center h-96",
|
|
689
|
-
children: /* @__PURE__ */
|
|
717
|
+
children: /* @__PURE__ */ N("div", {
|
|
690
718
|
className: "text-destructive",
|
|
691
719
|
children: ["Error: ", O.message]
|
|
692
720
|
})
|
|
693
721
|
})
|
|
694
|
-
}) : F ? /* @__PURE__ */
|
|
722
|
+
}) : F ? /* @__PURE__ */ N("div", {
|
|
695
723
|
className: l,
|
|
696
724
|
children: [
|
|
697
|
-
/* @__PURE__ */
|
|
725
|
+
/* @__PURE__ */ M("div", {
|
|
698
726
|
className: "h-[calc(100vh-200px)] min-h-[600px]",
|
|
699
|
-
children: /* @__PURE__ */
|
|
700
|
-
tasks:
|
|
727
|
+
children: /* @__PURE__ */ M(z, {
|
|
728
|
+
tasks: re,
|
|
701
729
|
onTaskClick: (e) => {
|
|
702
|
-
|
|
730
|
+
R.handleClick(e.data), u?.(e.data);
|
|
703
731
|
},
|
|
704
|
-
onTaskUpdate:
|
|
705
|
-
onTaskDelete:
|
|
732
|
+
onTaskUpdate: ae,
|
|
733
|
+
onTaskDelete: q,
|
|
706
734
|
inlineEdit: !0
|
|
707
735
|
})
|
|
708
736
|
}),
|
|
709
|
-
|
|
710
|
-
let t = P?.provider === "object" ? P.object : e.objectName, n =
|
|
737
|
+
R.isOverlay && R.isOpen && R.selectedRecord && (() => {
|
|
738
|
+
let t = P?.provider === "object" ? P.object : e.objectName, n = R.selectedRecord, r = n.id ?? n._id;
|
|
711
739
|
if (!t || r == null) return null;
|
|
712
740
|
let i = F?.titleField ? String(n[F.titleField] ?? "Task Details") : "Task Details";
|
|
713
|
-
return /* @__PURE__ */
|
|
741
|
+
return /* @__PURE__ */ M(f, {
|
|
714
742
|
open: !0,
|
|
715
|
-
onClose:
|
|
743
|
+
onClose: R.close,
|
|
716
744
|
title: i,
|
|
717
745
|
record: n,
|
|
718
746
|
objectName: t,
|
|
719
747
|
recordId: r,
|
|
720
748
|
dataSource: a,
|
|
721
749
|
objectSchema: k,
|
|
722
|
-
width:
|
|
723
|
-
fullPageHref:
|
|
750
|
+
width: R.width,
|
|
751
|
+
fullPageHref: p(t, r) ?? void 0,
|
|
724
752
|
onFieldSave: async (e, n) => {
|
|
725
|
-
a?.update && (await a.update(t, String(r), { [e]: n }),
|
|
753
|
+
a?.update && (await a.update(t, String(r), { [e]: n }), w((t) => t.map((t) => String(t.id ?? t._id) === String(r) ? {
|
|
726
754
|
...t,
|
|
727
755
|
[e]: n
|
|
728
756
|
} : t)));
|
|
729
757
|
},
|
|
730
758
|
onDelete: async () => {
|
|
731
|
-
a?.delete && (await a.delete(t, String(r)),
|
|
759
|
+
a?.delete && (await a.delete(t, String(r)), w((e) => e.filter((e) => String(e.id ?? e._id) !== String(r))));
|
|
732
760
|
}
|
|
733
761
|
});
|
|
734
762
|
})(),
|
|
735
|
-
/* @__PURE__ */
|
|
736
|
-
open: !!
|
|
763
|
+
/* @__PURE__ */ M(m, {
|
|
764
|
+
open: !!U,
|
|
737
765
|
onOpenChange: (e) => {
|
|
738
|
-
!e && !
|
|
766
|
+
!e && !G && W(null);
|
|
739
767
|
},
|
|
740
|
-
children: /* @__PURE__ */
|
|
768
|
+
children: /* @__PURE__ */ N(_, { children: [/* @__PURE__ */ N(b, { children: [/* @__PURE__ */ M(x, { children: "Delete this task?" }), /* @__PURE__ */ M(v, { children: U ? /* @__PURE__ */ N(j, { children: [
|
|
741
769
|
"\"",
|
|
742
|
-
|
|
770
|
+
U.title,
|
|
743
771
|
"\" will be permanently removed. This action cannot be undone."
|
|
744
|
-
] }) : null })] }), /* @__PURE__ */
|
|
745
|
-
disabled:
|
|
772
|
+
] }) : null })] }), /* @__PURE__ */ N(y, { children: [/* @__PURE__ */ M(g, {
|
|
773
|
+
disabled: G,
|
|
746
774
|
children: "Cancel"
|
|
747
|
-
}), /* @__PURE__ */
|
|
775
|
+
}), /* @__PURE__ */ M(h, {
|
|
748
776
|
onClick: (e) => {
|
|
749
|
-
e.preventDefault(),
|
|
777
|
+
e.preventDefault(), J();
|
|
750
778
|
},
|
|
751
|
-
disabled:
|
|
779
|
+
disabled: G,
|
|
752
780
|
"data-testid": "gantt-delete-confirm",
|
|
753
781
|
className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
754
|
-
children:
|
|
782
|
+
children: G ? "Deleting…" : "Delete"
|
|
755
783
|
})] })] })
|
|
756
784
|
})
|
|
757
785
|
]
|
|
758
|
-
}) : /* @__PURE__ */
|
|
786
|
+
}) : /* @__PURE__ */ M("div", {
|
|
759
787
|
className: l,
|
|
760
|
-
children: /* @__PURE__ */
|
|
788
|
+
children: /* @__PURE__ */ M("div", {
|
|
761
789
|
className: "flex items-center justify-center h-96",
|
|
762
|
-
children: /* @__PURE__ */
|
|
790
|
+
children: /* @__PURE__ */ M("div", {
|
|
763
791
|
className: "text-muted-foreground",
|
|
764
792
|
children: "Gantt configuration required. Please specify startDateField, endDateField, and titleField."
|
|
765
793
|
})
|
|
766
794
|
})
|
|
767
795
|
});
|
|
768
|
-
},
|
|
769
|
-
let { dataSource: t } =
|
|
770
|
-
return /* @__PURE__ */
|
|
796
|
+
}, W = ({ schema: e }) => {
|
|
797
|
+
let { dataSource: t } = u() || {};
|
|
798
|
+
return /* @__PURE__ */ M(U, {
|
|
771
799
|
schema: e,
|
|
772
800
|
dataSource: t
|
|
773
801
|
});
|
|
774
802
|
};
|
|
775
|
-
a.register("object-gantt",
|
|
803
|
+
a.register("object-gantt", W, {
|
|
776
804
|
namespace: "plugin-gantt",
|
|
777
805
|
label: "Object Gantt",
|
|
778
806
|
category: "view",
|
|
@@ -787,7 +815,7 @@ a.register("object-gantt", V, {
|
|
|
787
815
|
label: "Gantt Config",
|
|
788
816
|
description: "startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField"
|
|
789
817
|
}]
|
|
790
|
-
}), a.register("gantt",
|
|
818
|
+
}), a.register("gantt", W, {
|
|
791
819
|
namespace: "view",
|
|
792
820
|
label: "Gantt View",
|
|
793
821
|
category: "view",
|
|
@@ -804,4 +832,4 @@ a.register("object-gantt", V, {
|
|
|
804
832
|
}]
|
|
805
833
|
});
|
|
806
834
|
//#endregion
|
|
807
|
-
export {
|
|
835
|
+
export { z as GanttView, U as ObjectGantt, W 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(`@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
|
+
(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);var _={"gantt.column.taskName":`Task Name`,"gantt.column.start":`Start`,"gantt.column.end":`End`,"gantt.toolbar.prevPeriod":`Previous period`,"gantt.toolbar.nextPeriod":`Next period`,"gantt.toolbar.zoomIn":`Zoom in`,"gantt.toolbar.zoomOut":`Zoom out`,"gantt.toolbar.jumpToToday":`Jump to today`,"gantt.toolbar.today":`Today`,"gantt.toolbar.showTaskList":`Show task list`,"gantt.toolbar.hideTaskList":`Hide task list`},v=`gantt.column.taskName`;function y(e,t){let n=_[e]||e;if(t)for(let[e,r]of Object.entries(t))n=n.replace(`{{${e}}}`,String(r));return n}function b(){try{let e=(0,r.useObjectTranslation)();return e.t(v)===v?{t:y}:{t:e.t}}catch{return{t:y}}}function x(e){return e<640?35:e<1024?50:60}function S(e){return e<640?140:e<1024?220:320}function C(e){return e>=280}function w(e){return e<640?32:40}function T({tasks:e,startDate:n,endDate:r,onTaskClick:i,onTaskUpdate:a,className:s,inlineEdit:u=!1}){let{t:d}=b(),[f,p]=t.useState(new Date),m=t.useRef(null),{width:h}=(0,o.useResizeObserver)(m),g=h||(typeof window<`u`?window.innerWidth:1024),_=g<640,v=w(g),y=x(g),[T,E]=t.useState(null),D=T??y,[O,k]=t.useState(!1),A=t.useRef(!1);t.useEffect(()=>{!A.current&&_&&(k(!0),A.current=!0)},[_]);let j=O?0:S(g),M=C(j),[N,P]=t.useState(null),[F,I]=t.useState({}),[L,R]=t.useState(null),z=t.useRef(null);t.useEffect(()=>{z.current=L},[L]);let B=t.useRef(!1),V=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(!L)return;let t=e=>{let t=z.current;if(!t)return;let n=Math.round((e.clientX-t.originClientX)/Math.max(D,1));n!==t.dayDelta&&R({...t,dayDelta:n})},n=()=>{let t=z.current;if(t){if(t.dayDelta!==0){let n=e.find(e=>e.id===t.taskId);if(n&&a){let{start:e,end:r}=V(t);a(n,{start:e,end:r})}B.current=!0,window.setTimeout(()=>{B.current=!1},0)}R(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)}},[L,D,e,a,V]);let H=t.useCallback((e,t,n)=>{a&&(n.stopPropagation(),n.preventDefault(),R({taskId:e.id,mode:t,originStart:new Date(e.start),originEnd:new Date(e.end),originClientX:n.clientX,dayDelta:0}))},[a]),U=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]),W=t.useMemo(()=>{let e=[],t=new Date(U.start);for(;t<=U.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},[U]),G=t.useRef(null),K=t.useRef(null),q=t.useRef(null),J=t.useRef(null),Y=t.useRef(null),X=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;Y.current={baseDistance:Math.max(1,Math.sqrt(t*t+n*n)),baseColumn:D}}},[D]),Z=t.useCallback(e=>{if(e.touches.length!==2||!Y.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))/Y.current.baseDistance;E(Math.max(15,Math.min(120,Math.round(Y.current.baseColumn*r))))},[]),ee=t.useCallback(()=>{Y.current=null},[]),Q=t.useMemo(()=>{let e=new Date;if(e<U.start||e>U.end)return null;let t=(e.getTime()-U.start.getTime())/(1440*60*1e3);return Math.round(t*D)},[U,D]),te=t.useCallback(()=>{if(Q==null||!J.current)return;let e=Math.max(0,Q-J.current.clientWidth/2);J.current.scrollTo({left:e,behavior:`smooth`})},[Q]),ne=e=>{G.current&&(G.current.scrollLeft=e.currentTarget.scrollLeft),K.current&&(K.current.scrollTop=e.currentTarget.scrollTop)},$=e=>{U.end.getTime()-U.start.getTime();let t=D,n=1e3*60*60*24,r=e.start.getTime()-U.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:m,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":d(`gantt.toolbar.prevPeriod`),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":d(`gantt.toolbar.nextPeriod`),children:(0,l.jsx)(c.ChevronRight,{className:`h-4 w-4`})}),(0,l.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:U.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:()=>E(Math.max(15,D-10)),"aria-label":d(`gantt.toolbar.zoomOut`),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:()=>E(Math.min(120,D+10)),"aria-label":d(`gantt.toolbar.zoomIn`),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:()=>k(e=>!e),"aria-label":d(O?`gantt.toolbar.showTaskList`:`gantt.toolbar.hideTaskList`),"aria-pressed":O,"data-testid":`gantt-toggle-task-list`,children:O?(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:te,disabled:Q==null,"aria-label":d(`gantt.toolbar.jumpToToday`),"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:j,minWidth:j},children:[(0,l.jsx)(`div`,{className:`flex-1 truncate`,children:d(`gantt.column.taskName`)}),M&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:d(`gantt.column.start`)}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:d(`gantt.column.end`)})]})]}),(0,l.jsx)(`div`,{className:`flex-1 overflow-hidden`,ref:G,children:(0,l.jsx)(`div`,{className:`flex h-full`,style:{width:W.length*D},children:W.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:D,minWidth:D},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:K,style:{width:j,minWidth:j},children:e.map(e=>{let t=u&&N===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:v},onClick:()=>!t&&i?.(e),onDoubleClick:()=>{u&&a&&(P(e.id),I({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:F.title||``,onChange:e=>I(t=>({...t,title:e.target.value})),onKeyDown:t=>{t.key===`Enter`?(a?.(e,{title:F.title,start:new Date(F.start),end:new Date(F.end),progress:Number(F.progress)||0}),P(null)):t.key===`Escape`&&P(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:!M,style:M?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:F.start||``,onChange:e=>I(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:!M,style:M?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:F.end||``,onChange:e=>I(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=>{q.current=e,J.current=e},onScroll:ne,onTouchStart:X,onTouchMove:Z,onTouchEnd:ee,"data-testid":`gantt-timeline`,children:(0,l.jsxs)(`div`,{className:`relative`,style:{width:W.length*D},children:[Q!=null&&(0,l.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none`,style:{left:Q},"data-testid":`gantt-today-marker`,"aria-label":d(`gantt.toolbar.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:d(`gantt.toolbar.today`)})}),(0,l.jsxs)(`div`,{className:`relative`,children:[(0,l.jsx)(`div`,{className:`absolute inset-0 flex pointer-events-none z-0`,children:W.map((e,t)=>(0,l.jsx)(`div`,{className:(0,o.cn)(`border-r h-full`,e.isWeekend&&`bg-muted/20`),style:{width:D,minWidth:D}},t))}),e.map(e=>{let t=$(e),n=L?.taskId===e.id,r=t;if(n&&L){let t=V(L);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:v},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:()=>{B.current||i?.(e)},onPointerDown:s?t=>{t.button===0&&H(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&&H(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&&H(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?`${V(L).start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})} → ${V(L).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()-U.start.getTime())/(1e3*60*60*24)*D},children:(0,l.jsx)(`div`,{className:`w-2 h-2 rounded-full bg-red-500 -ml-[3px]`})})]})]})})]})]})]})}function E(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function D(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 O(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 k=({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),x=E(e),S=(0,t.useMemo)(()=>x,[JSON.stringify(x)]),C=O(e),w=S?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(g(!0),f.data&&Array.isArray(f.data)){m(f.data),g(!1);return}if(w&&S?.provider===`value`){m(S.items),g(!1);return}if(!i||typeof i.find!=`function`)throw Error(`DataSource required for object/api providers`);if(S?.provider===`object`){let t=S.object,r=(0,n.buildExpandFields)(y?.fields);m((0,n.extractRecords)(await i.find(t,{$filter:e.filter,$orderby:D(e.sort),...r.length>0?{$expand:r}:{}})))}else S?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectGantt`),m([]));g(!1)}catch(e){v(e),g(!1)}})()},[S,i,w,e.filter,e.sort,y]),(0,t.useEffect)(()=>{!w&&i&&(async()=>{try{if(!i)return;let t=S?.provider===`object`?S.object:e.objectName;if(!t)return;b(await i.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,i,w,S]);let k=(0,t.useMemo)(()=>{if(!C||!p.length)return[];let{startDateField:e,endDateField:t,titleField:n,progressField:r,dependenciesField:i,colorField:a}=C,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,C]),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(!C)return;let r=S?.provider===`object`?S.object:e.objectName;if(!r||!i||typeof i.update!=`function`)return;let{startDateField:a,endDateField:o,titleField:s,progressField:c}=C,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)}},[C,S,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=S?.provider===`object`?S.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,S,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]})})}):C?(0,l.jsxs)(`div`,{className:c,children:[(0,l.jsx)(`div`,{className:`h-[calc(100vh-200px)] min-h-[600px]`,children:(0,l.jsx)(T,{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=S?.provider===`object`?S.object:e.objectName,n=M.selectedRecord,r=n.id??n._id;if(!t||r==null)return null;let o=C?.titleField?String(n[C.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.`})})})},A=({schema:e})=>{let{dataSource:t}=(0,r.useSchemaContext)()||{};return(0,l.jsx)(k,{schema:e,dataSource:t})};n.ComponentRegistry.register(`object-gantt`,A,{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`,A,{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=T,e.ObjectGantt=k,e.ObjectGanttRenderer=A});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GanttView.d.ts","sourceRoot":"","sources":["../../../../src/GanttView.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"GanttView.d.ts","sourceRoot":"","sources":["../../../../src/GanttView.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqDH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,IAAI,CAAA;IACX,GAAG,EAAE,IAAI,CAAA;IACT,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,GAAG,CAAA;IACV,YAAY,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;CACnC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,aAAa,CAAA;IACxB,SAAS,CAAC,EAAE,IAAI,CAAA;IAChB,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,UAAU,CAAC,CAAC,KAAK,IAAI,CAAA;IACnH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACxC,oDAAoD;IACpD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,SAAS,EACT,OAAO,EACP,WAAW,EACX,YAAY,EACZ,SAAS,EACT,UAAkB,GACnB,EAAE,cAAc,2CA8kBhB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Default English translations for ObjectGantt. Mirrors the
|
|
10
|
+
* createSafeTranslationHook pattern used by plugin-detail / plugin-timeline so
|
|
11
|
+
* the Gantt keeps working when rendered standalone (Storybook, tests, embed)
|
|
12
|
+
* without an I18nProvider on the React tree.
|
|
13
|
+
*/
|
|
14
|
+
export declare const GANTT_DEFAULT_TRANSLATIONS: Record<string, string>;
|
|
15
|
+
declare function fallback(key: string, options?: Record<string, unknown>): string;
|
|
16
|
+
export declare function useGanttTranslation(): {
|
|
17
|
+
t: typeof fallback;
|
|
18
|
+
} | {
|
|
19
|
+
t: import('i18next').TFunction<string, undefined>;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=useGanttTranslation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGanttTranslation.d.ts","sourceRoot":"","sources":["../../../../src/useGanttTranslation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAY7D,CAAC;AAIF,iBAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAQxE;AAED,wBAAgB,mBAAmB;;;;EAWlC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/plugin-gantt",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.2",
|
|
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.16.0",
|
|
29
|
-
"@object-ui/components": "5.0.
|
|
30
|
-
"@object-ui/core": "5.0.
|
|
31
|
-
"@object-ui/fields": "5.0.
|
|
32
|
-
"@object-ui/plugin-detail": "5.0.
|
|
33
|
-
"@object-ui/react": "5.0.
|
|
34
|
-
"@object-ui/types": "5.0.
|
|
29
|
+
"@object-ui/components": "5.0.2",
|
|
30
|
+
"@object-ui/core": "5.0.2",
|
|
31
|
+
"@object-ui/fields": "5.0.2",
|
|
32
|
+
"@object-ui/plugin-detail": "5.0.2",
|
|
33
|
+
"@object-ui/react": "5.0.2",
|
|
34
|
+
"@object-ui/types": "5.0.2"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": "^18.0.0 || ^19.0.0",
|