sanity-plugin-workflow 1.0.0-beta.3 → 1.0.0-beta.4
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/README.md +2 -0
- package/lib/index.esm.js +1498 -1389
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +1495 -1386
- package/lib/index.js.map +1 -1
- package/package.json +4 -3
- package/src/components/DocumentCard/core/PublishedStatus.tsx +10 -3
- package/src/components/DocumentCard/index.tsx +5 -5
- package/src/components/DocumentList.tsx +122 -0
- package/src/components/Filters.tsx +3 -3
- package/src/components/Validators.tsx +36 -3
- package/src/components/WorkflowTool.tsx +102 -104
- package/src/constants/index.ts +1 -1
- package/src/helpers/filterItemsAndSort.ts +2 -0
- package/src/hooks/useWorkflowDocuments.tsx +6 -6
- package/src/index.ts +5 -5
- package/src/schema/workflow/workflow.metadata.ts +1 -1
- package/src/tools/index.ts +1 -1
package/lib/index.esm.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
var _templateObject, _templateObject2, _templateObject3;
|
|
2
2
|
function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
|
|
3
|
-
import {
|
|
4
|
-
import { EditIcon, AddIcon, PublishIcon, ErrorOutlineIcon, WarningOutlineIcon, CheckmarkIcon, DragHandleIcon, UserIcon, ResetIcon, InfoOutlineIcon, SplitVerticalIcon, UsersIcon, ArrowRightIcon, ArrowLeftIcon } from '@sanity/icons';
|
|
3
|
+
import { useClient, useValidationStatus, useCurrentUser, useSchema, Preview, useFormValue, defineType, defineField, UserAvatar, useTimeAgo, TextWithTone, definePlugin } from 'sanity';
|
|
5
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
-
import
|
|
7
|
-
import
|
|
5
|
+
import { UsersIcon, SplitVerticalIcon, CheckmarkIcon, ArrowRightIcon, ArrowLeftIcon, EditIcon, AddIcon, PublishIcon, ErrorOutlineIcon, WarningOutlineIcon, DragHandleIcon, UserIcon, ResetIcon, InfoOutlineIcon } from '@sanity/icons';
|
|
6
|
+
import React, { useState, useCallback, useMemo, useEffect, useRef } from 'react';
|
|
8
7
|
import { UserSelectMenu, useListeningQuery, useProjectUsers, Feedback } from 'sanity-plugin-utils';
|
|
9
|
-
import {
|
|
8
|
+
import { useToast, Button, Spinner, Card, Flex, Box, Text, useClickOutside, Popover, Grid, Tooltip, useTheme, Stack, MenuButton, Menu, Badge, Container } from '@sanity/ui';
|
|
9
|
+
import { LexoRank } from 'lexorank';
|
|
10
10
|
import { useRouter } from 'sanity/router';
|
|
11
|
+
import { Draggable, DragDropContext, Droppable } from '@hello-pangea/dnd';
|
|
11
12
|
import groq from 'groq';
|
|
12
|
-
import {
|
|
13
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
13
14
|
import styled, { css } from 'styled-components';
|
|
14
15
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
15
16
|
function defineStates(states) {
|
|
@@ -39,69 +40,6 @@ const DEFAULT_CONFIG = {
|
|
|
39
40
|
transitions: ["changesRequested"]
|
|
40
41
|
}])
|
|
41
42
|
};
|
|
42
|
-
function EditButton(props) {
|
|
43
|
-
const {
|
|
44
|
-
id,
|
|
45
|
-
type,
|
|
46
|
-
disabled = false
|
|
47
|
-
} = props;
|
|
48
|
-
const {
|
|
49
|
-
navigateIntent
|
|
50
|
-
} = useRouter();
|
|
51
|
-
return /* @__PURE__ */jsx(Button, {
|
|
52
|
-
onClick: () => navigateIntent("edit", {
|
|
53
|
-
id,
|
|
54
|
-
type
|
|
55
|
-
}),
|
|
56
|
-
mode: "ghost",
|
|
57
|
-
fontSize: 1,
|
|
58
|
-
padding: 2,
|
|
59
|
-
tabIndex: -1,
|
|
60
|
-
icon: EditIcon,
|
|
61
|
-
text: "Edit",
|
|
62
|
-
disabled
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
function AvatarGroup(props) {
|
|
66
|
-
const currentUser = useCurrentUser();
|
|
67
|
-
const {
|
|
68
|
-
users,
|
|
69
|
-
max = 4
|
|
70
|
-
} = props;
|
|
71
|
-
const len = users == null ? void 0 : users.length;
|
|
72
|
-
const {
|
|
73
|
-
me,
|
|
74
|
-
visibleUsers
|
|
75
|
-
} = React.useMemo(() => {
|
|
76
|
-
return {
|
|
77
|
-
me: (currentUser == null ? void 0 : currentUser.id) ? users.find(u => u.id === currentUser.id) : void 0,
|
|
78
|
-
visibleUsers: users.filter(u => u.id !== (currentUser == null ? void 0 : currentUser.id)).slice(0, max - 1)
|
|
79
|
-
};
|
|
80
|
-
}, [users, max, currentUser]);
|
|
81
|
-
if (!(users == null ? void 0 : users.length)) {
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
return /* @__PURE__ */jsxs(Flex, {
|
|
85
|
-
align: "center",
|
|
86
|
-
gap: 1,
|
|
87
|
-
children: [me ? /* @__PURE__ */jsx(UserAvatar, {
|
|
88
|
-
user: me
|
|
89
|
-
}) : null, visibleUsers.map(user => /* @__PURE__ */jsx(Box, {
|
|
90
|
-
style: {
|
|
91
|
-
marginRight: -8
|
|
92
|
-
},
|
|
93
|
-
children: /* @__PURE__ */jsx(UserAvatar, {
|
|
94
|
-
user
|
|
95
|
-
})
|
|
96
|
-
}, user.id)), len > max && /* @__PURE__ */jsx(Box, {
|
|
97
|
-
paddingLeft: 2,
|
|
98
|
-
children: /* @__PURE__ */jsxs(Text, {
|
|
99
|
-
size: 1,
|
|
100
|
-
children: ["+", len - max]
|
|
101
|
-
})
|
|
102
|
-
})]
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
43
|
function UserAssignment(props) {
|
|
106
44
|
const {
|
|
107
45
|
assignees,
|
|
@@ -184,698 +122,479 @@ function UserAssignment(props) {
|
|
|
184
122
|
onRemove: removeAssignee
|
|
185
123
|
});
|
|
186
124
|
}
|
|
187
|
-
function
|
|
188
|
-
const {
|
|
189
|
-
assignees,
|
|
190
|
-
userList,
|
|
191
|
-
documentId,
|
|
192
|
-
disabled = false
|
|
193
|
-
} = props;
|
|
194
|
-
const [button] = React.useState(null);
|
|
195
|
-
const [popover, setPopover] = React.useState(null);
|
|
196
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
|
197
|
-
const close = React.useCallback(() => setIsOpen(false), []);
|
|
198
|
-
const open = React.useCallback(() => setIsOpen(true), []);
|
|
199
|
-
useClickOutside(close, [button, popover]);
|
|
200
|
-
return /* @__PURE__ */jsx(Popover, {
|
|
201
|
-
ref: setPopover,
|
|
202
|
-
content: /* @__PURE__ */jsx(UserAssignment, {
|
|
203
|
-
userList,
|
|
204
|
-
assignees,
|
|
205
|
-
documentId
|
|
206
|
-
}),
|
|
207
|
-
portal: true,
|
|
208
|
-
open: isOpen,
|
|
209
|
-
children: !assignees || assignees.length === 0 ? /* @__PURE__ */jsx(Button, {
|
|
210
|
-
onClick: open,
|
|
211
|
-
fontSize: 1,
|
|
212
|
-
padding: 2,
|
|
213
|
-
tabIndex: -1,
|
|
214
|
-
icon: AddIcon,
|
|
215
|
-
text: "Assign",
|
|
216
|
-
tone: "positive",
|
|
217
|
-
mode: "ghost",
|
|
218
|
-
disabled
|
|
219
|
-
}) : /* @__PURE__ */jsx(Grid, {
|
|
220
|
-
children: /* @__PURE__ */jsx(Button, {
|
|
221
|
-
onClick: open,
|
|
222
|
-
padding: 0,
|
|
223
|
-
mode: "bleed",
|
|
224
|
-
disabled,
|
|
225
|
-
children: /* @__PURE__ */jsx(AvatarGroup, {
|
|
226
|
-
users: userList.filter(u => assignees.includes(u.id))
|
|
227
|
-
})
|
|
228
|
-
})
|
|
229
|
-
})
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
function TimeAgo(_ref) {
|
|
233
|
-
let {
|
|
234
|
-
time
|
|
235
|
-
} = _ref;
|
|
236
|
-
const timeAgo = useTimeAgo(time);
|
|
237
|
-
return /* @__PURE__ */jsxs("span", {
|
|
238
|
-
title: timeAgo,
|
|
239
|
-
children: [timeAgo, " ago"]
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
function DraftStatus(props) {
|
|
125
|
+
function useWorkflowMetadata(id, states) {
|
|
243
126
|
const {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
children: /* @__PURE__ */jsx(Text, {
|
|
252
|
-
size: 1,
|
|
253
|
-
children: document ? /* @__PURE__ */jsxs(Fragment, {
|
|
254
|
-
children: ["Edited ", updatedAt && /* @__PURE__ */jsx(TimeAgo, {
|
|
255
|
-
time: updatedAt
|
|
256
|
-
})]
|
|
257
|
-
}) : /* @__PURE__ */jsx(Fragment, {
|
|
258
|
-
children: "No unpublished edits"
|
|
259
|
-
})
|
|
260
|
-
})
|
|
261
|
-
}),
|
|
262
|
-
children: /* @__PURE__ */jsx(TextWithTone, {
|
|
263
|
-
tone: "caution",
|
|
264
|
-
dimmed: !document,
|
|
265
|
-
muted: !document,
|
|
266
|
-
size: 1,
|
|
267
|
-
children: /* @__PURE__ */jsx(EditIcon, {})
|
|
268
|
-
})
|
|
127
|
+
data: metadata,
|
|
128
|
+
loading,
|
|
129
|
+
error
|
|
130
|
+
} = useListeningQuery("*[_type == \"workflow.metadata\" && documentId == $id][0]", {
|
|
131
|
+
params: {
|
|
132
|
+
id
|
|
133
|
+
}
|
|
269
134
|
});
|
|
135
|
+
if (metadata == null ? void 0 : metadata.state) {
|
|
136
|
+
return {
|
|
137
|
+
data: {
|
|
138
|
+
metadata,
|
|
139
|
+
state: states.find(s => s.id === metadata.state)
|
|
140
|
+
},
|
|
141
|
+
loading,
|
|
142
|
+
error
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
data: {},
|
|
147
|
+
loading,
|
|
148
|
+
error
|
|
149
|
+
};
|
|
270
150
|
}
|
|
271
|
-
function
|
|
151
|
+
function AssignWorkflow(props, states) {
|
|
152
|
+
var _a, _b;
|
|
272
153
|
const {
|
|
273
|
-
|
|
154
|
+
id
|
|
274
155
|
} = props;
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
content: /* @__PURE__ */jsx(Box, {
|
|
279
|
-
padding: 2,
|
|
280
|
-
children: /* @__PURE__ */jsx(Text, {
|
|
281
|
-
size: 1,
|
|
282
|
-
children: document ? /* @__PURE__ */jsxs(Fragment, {
|
|
283
|
-
children: ["Published ", updatedAt && /* @__PURE__ */jsx(TimeAgo, {
|
|
284
|
-
time: updatedAt
|
|
285
|
-
})]
|
|
286
|
-
}) : /* @__PURE__ */jsx(Fragment, {
|
|
287
|
-
children: "Not published"
|
|
288
|
-
})
|
|
289
|
-
})
|
|
290
|
-
}),
|
|
291
|
-
children: /* @__PURE__ */jsx(TextWithTone, {
|
|
292
|
-
tone: "positive",
|
|
293
|
-
dimmed: !document,
|
|
294
|
-
muted: !document,
|
|
295
|
-
size: 1,
|
|
296
|
-
children: /* @__PURE__ */jsx(PublishIcon, {})
|
|
297
|
-
})
|
|
156
|
+
const [isDialogOpen, setDialogOpen] = useState(false);
|
|
157
|
+
const userList = useProjectUsers({
|
|
158
|
+
apiVersion: API_VERSION
|
|
298
159
|
});
|
|
299
|
-
}
|
|
300
|
-
function ValidationStatus(props) {
|
|
301
160
|
const {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
161
|
+
data,
|
|
162
|
+
loading,
|
|
163
|
+
error
|
|
164
|
+
} = useWorkflowMetadata(id, states);
|
|
165
|
+
if (error) {
|
|
166
|
+
console.error(error);
|
|
167
|
+
}
|
|
168
|
+
if (!(data == null ? void 0 : data.metadata)) {
|
|
305
169
|
return null;
|
|
306
170
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
171
|
+
return {
|
|
172
|
+
icon: UsersIcon,
|
|
173
|
+
type: "dialog",
|
|
174
|
+
disabled: !data || loading || error,
|
|
175
|
+
label: "Assign",
|
|
176
|
+
title: data ? null : "Document is not in Workflow",
|
|
177
|
+
dialog: isDialogOpen && {
|
|
178
|
+
type: "popover",
|
|
179
|
+
onClose: () => {
|
|
180
|
+
setDialogOpen(false);
|
|
181
|
+
},
|
|
182
|
+
content: /* @__PURE__ */jsx(UserAssignment, {
|
|
183
|
+
userList,
|
|
184
|
+
assignees: (_b = (_a = data.metadata) == null ? void 0 : _a.assignees) != null ? _b : [],
|
|
185
|
+
documentId: id
|
|
315
186
|
})
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
})
|
|
322
|
-
});
|
|
187
|
+
},
|
|
188
|
+
onHandle: () => {
|
|
189
|
+
setDialogOpen(true);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
323
192
|
}
|
|
324
|
-
function
|
|
193
|
+
function BeginWorkflow(props, states) {
|
|
325
194
|
const {
|
|
326
|
-
|
|
327
|
-
|
|
195
|
+
id,
|
|
196
|
+
draft
|
|
328
197
|
} = props;
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
198
|
+
const {
|
|
199
|
+
data,
|
|
200
|
+
loading,
|
|
201
|
+
error
|
|
202
|
+
} = useWorkflowMetadata(id, states);
|
|
203
|
+
const client = useClient({
|
|
204
|
+
apiVersion: API_VERSION
|
|
205
|
+
});
|
|
206
|
+
const toast = useToast();
|
|
207
|
+
const [beginning, setBeginning] = useState(false);
|
|
208
|
+
const [complete, setComplete] = useState(false);
|
|
209
|
+
if (error) {
|
|
210
|
+
console.error(error);
|
|
211
|
+
}
|
|
212
|
+
const handle = useCallback(async () => {
|
|
213
|
+
setBeginning(true);
|
|
214
|
+
const lowestOrderFirstState = await client.fetch("*[_type == \"workflow.metadata\" && state == $state]|order(orderRank)[0].orderRank", {
|
|
215
|
+
state: states[0].id
|
|
216
|
+
});
|
|
217
|
+
client.createIfNotExists({
|
|
218
|
+
_id: "workflow-metadata.".concat(id),
|
|
219
|
+
_type: "workflow.metadata",
|
|
220
|
+
documentId: id,
|
|
221
|
+
state: states[0].id,
|
|
222
|
+
orderRank: lowestOrderFirstState ? LexoRank.parse(lowestOrderFirstState).genNext().toString() : LexoRank.min().toString()
|
|
223
|
+
},
|
|
224
|
+
// Faster!
|
|
225
|
+
{
|
|
226
|
+
visibility: "async"
|
|
227
|
+
}).then(() => {
|
|
335
228
|
toast.push({
|
|
336
229
|
status: "success",
|
|
337
|
-
title: "Workflow
|
|
338
|
-
description:
|
|
339
|
-
});
|
|
340
|
-
}).catch(() => {
|
|
341
|
-
toast.push({
|
|
342
|
-
status: "error",
|
|
343
|
-
title: "Could not complete Workflow",
|
|
344
|
-
description: id
|
|
230
|
+
title: "Workflow started",
|
|
231
|
+
description: "Document is now \"".concat(states[0].title, "\"")
|
|
345
232
|
});
|
|
233
|
+
setBeginning(false);
|
|
234
|
+
setComplete(true);
|
|
346
235
|
});
|
|
347
|
-
}, [client, toast]);
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
236
|
+
}, [id, states, client, toast]);
|
|
237
|
+
if (!draft || complete || data.metadata) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
icon: SplitVerticalIcon,
|
|
242
|
+
type: "dialog",
|
|
243
|
+
disabled: (data == null ? void 0 : data.metadata) || loading || error || beginning || complete,
|
|
244
|
+
label: beginning ? "Beginning..." : "Begin Workflow",
|
|
245
|
+
onHandle: () => {
|
|
246
|
+
handle();
|
|
247
|
+
}
|
|
248
|
+
};
|
|
359
249
|
}
|
|
360
|
-
function
|
|
250
|
+
function CompleteWorkflow(props, states) {
|
|
361
251
|
var _a;
|
|
362
252
|
const {
|
|
363
|
-
|
|
364
|
-
userRoleCanDrop,
|
|
365
|
-
isDragging,
|
|
366
|
-
item,
|
|
367
|
-
states,
|
|
368
|
-
toggleInvalidDocumentId,
|
|
369
|
-
userList
|
|
253
|
+
id
|
|
370
254
|
} = props;
|
|
371
255
|
const {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
const {
|
|
379
|
-
validation = [],
|
|
380
|
-
isValidating
|
|
381
|
-
} = useValidationStatus(documentId != null ? documentId : "", item._type);
|
|
382
|
-
const cardTone = useMemo(() => {
|
|
383
|
-
let tone = defaultCardTone;
|
|
384
|
-
if (!userRoleCanDrop) return isDarkMode ? "default" : "transparent";
|
|
385
|
-
if (!documentId) return tone;
|
|
386
|
-
if (isDragging) tone = "positive";
|
|
387
|
-
if (!isValidating && validation.length > 0) {
|
|
388
|
-
if (validation.some(v => v.level === "error")) {
|
|
389
|
-
tone = "critical";
|
|
390
|
-
} else {
|
|
391
|
-
tone = "caution";
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
return tone;
|
|
395
|
-
}, [isDarkMode, userRoleCanDrop, defaultCardTone, documentId, isDragging, validation, isValidating]);
|
|
396
|
-
useEffect(() => {
|
|
397
|
-
if (!isValidating && validation.length > 0) {
|
|
398
|
-
if (validation.some(v => v.level === "error")) {
|
|
399
|
-
toggleInvalidDocumentId(documentId, "ADD");
|
|
400
|
-
} else {
|
|
401
|
-
toggleInvalidDocumentId(documentId, "REMOVE");
|
|
402
|
-
}
|
|
403
|
-
} else {
|
|
404
|
-
toggleInvalidDocumentId(documentId, "REMOVE");
|
|
405
|
-
}
|
|
406
|
-
}, [documentId, isValidating, toggleInvalidDocumentId, validation]);
|
|
407
|
-
const hasError = useMemo(() => isValidating ? false : validation.some(v => v.level === "error"), [isValidating, validation]);
|
|
408
|
-
const isLastState = useMemo(() => {
|
|
409
|
-
var _a2;
|
|
410
|
-
return states[states.length - 1].id === ((_a2 = item._metadata) == null ? void 0 : _a2.state);
|
|
411
|
-
}, [states, item._metadata.state]);
|
|
412
|
-
return /* @__PURE__ */jsx(Box, {
|
|
413
|
-
paddingBottom: 3,
|
|
414
|
-
paddingX: 3,
|
|
415
|
-
children: /* @__PURE__ */jsx(Card, {
|
|
416
|
-
radius: 2,
|
|
417
|
-
shadow: isDragging ? 3 : 1,
|
|
418
|
-
tone: cardTone,
|
|
419
|
-
children: /* @__PURE__ */jsxs(Stack, {
|
|
420
|
-
children: [/* @__PURE__ */jsx(Card, {
|
|
421
|
-
borderBottom: true,
|
|
422
|
-
radius: 2,
|
|
423
|
-
padding: 3,
|
|
424
|
-
paddingLeft: 2,
|
|
425
|
-
tone: cardTone,
|
|
426
|
-
style: {
|
|
427
|
-
pointerEvents: "none"
|
|
428
|
-
},
|
|
429
|
-
children: /* @__PURE__ */jsxs(Flex, {
|
|
430
|
-
align: "center",
|
|
431
|
-
justify: "space-between",
|
|
432
|
-
gap: 1,
|
|
433
|
-
children: [/* @__PURE__ */jsx(Box, {
|
|
434
|
-
flex: 1,
|
|
435
|
-
children: /* @__PURE__ */jsx(Preview, {
|
|
436
|
-
layout: "default",
|
|
437
|
-
value: item,
|
|
438
|
-
schemaType: schema.get(item._type)
|
|
439
|
-
})
|
|
440
|
-
}), /* @__PURE__ */jsx(Box, {
|
|
441
|
-
style: {
|
|
442
|
-
flexShrink: 0
|
|
443
|
-
},
|
|
444
|
-
children: hasError || isDragDisabled ? null : /* @__PURE__ */jsx(DragHandleIcon, {})
|
|
445
|
-
})]
|
|
446
|
-
})
|
|
447
|
-
}), /* @__PURE__ */jsx(Card, {
|
|
448
|
-
padding: 2,
|
|
449
|
-
radius: 2,
|
|
450
|
-
tone: "inherit",
|
|
451
|
-
children: /* @__PURE__ */jsxs(Flex, {
|
|
452
|
-
align: "center",
|
|
453
|
-
justify: "space-between",
|
|
454
|
-
gap: 3,
|
|
455
|
-
children: [/* @__PURE__ */jsx(Box, {
|
|
456
|
-
flex: 1,
|
|
457
|
-
children: documentId && /* @__PURE__ */jsx(UserDisplay, {
|
|
458
|
-
userList,
|
|
459
|
-
assignees,
|
|
460
|
-
documentId,
|
|
461
|
-
disabled: !userRoleCanDrop
|
|
462
|
-
})
|
|
463
|
-
}), validation.length > 0 ? /* @__PURE__ */jsx(ValidationStatus, {
|
|
464
|
-
validation
|
|
465
|
-
}) : null, /* @__PURE__ */jsx(DraftStatus, {
|
|
466
|
-
document: item
|
|
467
|
-
}), /* @__PURE__ */jsx(PublishedStatus, {
|
|
468
|
-
document: item
|
|
469
|
-
}), /* @__PURE__ */jsx(EditButton, {
|
|
470
|
-
id: item._id,
|
|
471
|
-
type: item._type,
|
|
472
|
-
disabled: !userRoleCanDrop
|
|
473
|
-
}), isLastState ? /* @__PURE__ */jsx(CompleteButton, {
|
|
474
|
-
documentId,
|
|
475
|
-
disabled: !userRoleCanDrop
|
|
476
|
-
}) : null]
|
|
477
|
-
})
|
|
478
|
-
})]
|
|
479
|
-
})
|
|
480
|
-
})
|
|
256
|
+
data,
|
|
257
|
+
loading,
|
|
258
|
+
error
|
|
259
|
+
} = useWorkflowMetadata(id, states);
|
|
260
|
+
const client = useClient({
|
|
261
|
+
apiVersion: API_VERSION
|
|
481
262
|
});
|
|
263
|
+
if (error) {
|
|
264
|
+
console.error(error);
|
|
265
|
+
}
|
|
266
|
+
const handle = useCallback(() => {
|
|
267
|
+
client.delete("workflow-metadata.".concat(id));
|
|
268
|
+
}, [id, client]);
|
|
269
|
+
const isLastState = ((_a = data == null ? void 0 : data.state) == null ? void 0 : _a.id) === states[states.length - 1].id;
|
|
270
|
+
if (!data.metadata) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
icon: CheckmarkIcon,
|
|
275
|
+
type: "dialog",
|
|
276
|
+
disabled: loading || error || !isLastState,
|
|
277
|
+
label: "Complete Workflow",
|
|
278
|
+
title: isLastState ? "Removes the document from the Workflow process" : "Cannot remove from workflow until in the last state",
|
|
279
|
+
onHandle: () => {
|
|
280
|
+
handle();
|
|
281
|
+
},
|
|
282
|
+
color: "positive"
|
|
283
|
+
};
|
|
482
284
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
285
|
+
function arraysContainMatchingString(one, two) {
|
|
286
|
+
return one.some(item => two.includes(item));
|
|
287
|
+
}
|
|
288
|
+
function UpdateWorkflow(props, allStates, actionState) {
|
|
289
|
+
var _a, _b, _c, _d;
|
|
290
|
+
const {
|
|
291
|
+
id,
|
|
292
|
+
type
|
|
293
|
+
} = props;
|
|
294
|
+
const {
|
|
295
|
+
validation,
|
|
296
|
+
isValidating
|
|
297
|
+
} = useValidationStatus(id, type);
|
|
298
|
+
const hasValidationErrors = !isValidating && (validation == null ? void 0 : validation.length) > 0 && validation.find(v => v.level === "error");
|
|
299
|
+
const user = useCurrentUser();
|
|
486
300
|
const client = useClient({
|
|
487
301
|
apiVersion: API_VERSION
|
|
488
302
|
});
|
|
303
|
+
const toast = useToast();
|
|
304
|
+
const currentUser = useCurrentUser();
|
|
489
305
|
const {
|
|
490
306
|
data,
|
|
491
307
|
loading,
|
|
492
308
|
error
|
|
493
|
-
} =
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
var _a;
|
|
509
|
-
if (((_a = item == null ? void 0 : item._metadata) == null ? void 0 : _a.documentId) === draggedId) {
|
|
510
|
-
return {
|
|
511
|
-
...item,
|
|
512
|
-
_metadata: {
|
|
513
|
-
...item._metadata,
|
|
514
|
-
state: destination.droppableId,
|
|
515
|
-
orderRank: newOrder,
|
|
516
|
-
// This value won't be written to the document
|
|
517
|
-
// It's done so that un/publish operations don't happen twice
|
|
518
|
-
// Because a moved document's card will update once optimistically
|
|
519
|
-
// and then again when the document is updated
|
|
520
|
-
optimistic: true
|
|
521
|
-
}
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
|
-
return item;
|
|
525
|
-
});
|
|
526
|
-
setLocalDocuments(newLocalDocuments);
|
|
527
|
-
const newStateId = destination.droppableId;
|
|
528
|
-
const newState = states.find(s => s.id === newStateId);
|
|
529
|
-
const document = localDocuments.find(d => {
|
|
530
|
-
var _a;
|
|
531
|
-
return ((_a = d == null ? void 0 : d._metadata) == null ? void 0 : _a.documentId) === draggedId;
|
|
532
|
-
});
|
|
533
|
-
if (!(newState == null ? void 0 : newState.id)) {
|
|
309
|
+
} = useWorkflowMetadata(id, allStates);
|
|
310
|
+
const {
|
|
311
|
+
state: currentState
|
|
312
|
+
} = data;
|
|
313
|
+
const {
|
|
314
|
+
assignees = []
|
|
315
|
+
} = (_a = data == null ? void 0 : data.metadata) != null ? _a : {};
|
|
316
|
+
if (error) {
|
|
317
|
+
console.error(error);
|
|
318
|
+
}
|
|
319
|
+
const onHandle = (documentId, newState) => {
|
|
320
|
+
client.patch("workflow-metadata.".concat(documentId)).set({
|
|
321
|
+
state: newState.id
|
|
322
|
+
}).commit().then(() => {
|
|
323
|
+
props.onComplete();
|
|
534
324
|
toast.push({
|
|
535
|
-
|
|
536
|
-
|
|
325
|
+
status: "success",
|
|
326
|
+
title: "Document state now \"".concat(newState.title, "\"")
|
|
537
327
|
});
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
328
|
+
}).catch(err => {
|
|
329
|
+
props.onComplete();
|
|
330
|
+
console.error(err);
|
|
541
331
|
toast.push({
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
});
|
|
545
|
-
return null;
|
|
546
|
-
}
|
|
547
|
-
const {
|
|
548
|
-
_id,
|
|
549
|
-
_type
|
|
550
|
-
} = document;
|
|
551
|
-
const {
|
|
552
|
-
_rev,
|
|
553
|
-
documentId
|
|
554
|
-
} = document._metadata || {};
|
|
555
|
-
client.patch("workflow-metadata.".concat(documentId)).ifRevisionId(_rev).set({
|
|
556
|
-
state: newStateId,
|
|
557
|
-
orderRank: newOrder
|
|
558
|
-
}).commit().then(() => {
|
|
559
|
-
var _a;
|
|
560
|
-
return toast.push({
|
|
561
|
-
title: "Moved to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
|
|
562
|
-
status: "success"
|
|
563
|
-
});
|
|
564
|
-
}).catch(() => {
|
|
565
|
-
var _a;
|
|
566
|
-
setLocalDocuments(currentLocalData);
|
|
567
|
-
return toast.push({
|
|
568
|
-
title: "Failed to move to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
|
|
569
|
-
status: "error"
|
|
332
|
+
status: "error",
|
|
333
|
+
title: "Document state update failed"
|
|
570
334
|
});
|
|
571
335
|
});
|
|
336
|
+
};
|
|
337
|
+
if (!data.metadata || currentState && currentState.id === actionState.id) {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
const currentStateIndex = allStates.findIndex(s => s.id === (currentState == null ? void 0 : currentState.id));
|
|
341
|
+
const actionStateIndex = allStates.findIndex(s => s.id === actionState.id);
|
|
342
|
+
const direction = actionStateIndex > currentStateIndex ? "promote" : "demote";
|
|
343
|
+
const DirectionIcon = direction === "promote" ? ArrowRightIcon : ArrowLeftIcon;
|
|
344
|
+
const directionLabel = direction === "promote" ? "Promote" : "Demote";
|
|
345
|
+
let title = "".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
|
|
346
|
+
const userRoleCanUpdateState = ((_b = user == null ? void 0 : user.roles) == null ? void 0 : _b.length) && ((_c = actionState == null ? void 0 : actionState.roles) == null ? void 0 : _c.length) ?
|
|
347
|
+
// If the Action state is limited to specific roles
|
|
348
|
+
// check that the current user has one of those roles
|
|
349
|
+
arraysContainMatchingString(user.roles.map(r => r.name), actionState.roles) :
|
|
350
|
+
// No roles specified on the next state, so anyone can update
|
|
351
|
+
((_d = actionState == null ? void 0 : actionState.roles) == null ? void 0 : _d.length) !== 0;
|
|
352
|
+
if (!userRoleCanUpdateState) {
|
|
353
|
+
title = "Your User role cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
|
|
354
|
+
}
|
|
355
|
+
const actionStateIsAValidTransition = (currentState == null ? void 0 : currentState.id) && currentState.transitions.length ?
|
|
356
|
+
// If the Current State limits transitions to specific States
|
|
357
|
+
// Check that the Action State is in Current State's transitions array
|
|
358
|
+
currentState.transitions.includes(actionState.id) :
|
|
359
|
+
// Otherwise this isn't a problem
|
|
360
|
+
true;
|
|
361
|
+
if (!actionStateIsAValidTransition) {
|
|
362
|
+
title = "You cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\" from \"").concat(currentState == null ? void 0 : currentState.title, "\"");
|
|
363
|
+
}
|
|
364
|
+
const userAssignmentCanUpdateState = actionState.requireAssignment ?
|
|
365
|
+
// If the Action State requires assigned users
|
|
366
|
+
// Check the current user ID is in the assignees array
|
|
367
|
+
currentUser && assignees.length && assignees.includes(currentUser.id) :
|
|
368
|
+
// Otherwise this isn't a problem
|
|
369
|
+
true;
|
|
370
|
+
if (!userAssignmentCanUpdateState) {
|
|
371
|
+
title = "You must be assigned to the document to ".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
|
|
372
|
+
}
|
|
373
|
+
if (hasValidationErrors) {
|
|
374
|
+
title = "Document has validation errors, cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
icon: DirectionIcon,
|
|
378
|
+
disabled: loading || error || isValidating || hasValidationErrors || !currentState || !userRoleCanUpdateState || !actionStateIsAValidTransition || !userAssignmentCanUpdateState,
|
|
379
|
+
title,
|
|
380
|
+
label: actionState.title,
|
|
381
|
+
onHandle: () => onHandle(id, actionState)
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function AssigneesBadge(states, documentId, currentUser) {
|
|
385
|
+
var _a;
|
|
386
|
+
const {
|
|
387
|
+
data,
|
|
388
|
+
loading,
|
|
389
|
+
error
|
|
390
|
+
} = useWorkflowMetadata(documentId, states);
|
|
391
|
+
const {
|
|
392
|
+
metadata
|
|
393
|
+
} = data;
|
|
394
|
+
const userList = useProjectUsers({
|
|
395
|
+
apiVersion: API_VERSION
|
|
396
|
+
});
|
|
397
|
+
if (loading || error || !metadata) {
|
|
398
|
+
if (error) {
|
|
399
|
+
console.error(error);
|
|
400
|
+
}
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
if (!((_a = metadata == null ? void 0 : metadata.assignees) == null ? void 0 : _a.length)) {
|
|
572
404
|
return {
|
|
573
|
-
|
|
574
|
-
_type,
|
|
575
|
-
documentId,
|
|
576
|
-
state: newState
|
|
405
|
+
label: "Unassigned"
|
|
577
406
|
};
|
|
578
|
-
}
|
|
407
|
+
}
|
|
408
|
+
const {
|
|
409
|
+
assignees
|
|
410
|
+
} = metadata != null ? metadata : [];
|
|
411
|
+
const hasMe = currentUser ? assignees.some(assignee => assignee === currentUser.id) : false;
|
|
412
|
+
const assigneesCount = hasMe ? assignees.length - 1 : assignees.length;
|
|
413
|
+
const assigneeUsers = userList.filter(user => assignees.includes(user.id));
|
|
414
|
+
const title = assigneeUsers.map(user => user.displayName).join(", ");
|
|
415
|
+
let label;
|
|
416
|
+
if (hasMe && assigneesCount === 0) {
|
|
417
|
+
label = "Assigned to Me";
|
|
418
|
+
} else if (hasMe && assigneesCount > 0) {
|
|
419
|
+
label = "Me and ".concat(assigneesCount, " ").concat(assigneesCount === 1 ? "other" : "others");
|
|
420
|
+
} else {
|
|
421
|
+
label = "".concat(assigneesCount, " assigned");
|
|
422
|
+
}
|
|
579
423
|
return {
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
424
|
+
label,
|
|
425
|
+
title,
|
|
426
|
+
color: "primary"
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
function StateBadge(states, documentId) {
|
|
430
|
+
const {
|
|
431
|
+
data,
|
|
432
|
+
loading,
|
|
433
|
+
error
|
|
434
|
+
} = useWorkflowMetadata(documentId, states);
|
|
435
|
+
const {
|
|
436
|
+
state
|
|
437
|
+
} = data;
|
|
438
|
+
if (loading || error) {
|
|
439
|
+
if (error) {
|
|
440
|
+
console.error(error);
|
|
587
441
|
}
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
if (!state) {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
label: state.title,
|
|
449
|
+
// title: state.title,
|
|
450
|
+
color: state == null ? void 0 : state.color
|
|
588
451
|
};
|
|
589
452
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
radius: 3,
|
|
612
|
-
children: /* @__PURE__ */jsx(Grid, {
|
|
613
|
-
gap: 2,
|
|
614
|
-
children
|
|
615
|
-
})
|
|
616
|
-
})
|
|
617
|
-
}, "floater") : null
|
|
453
|
+
function EditButton(props) {
|
|
454
|
+
const {
|
|
455
|
+
id,
|
|
456
|
+
type,
|
|
457
|
+
disabled = false
|
|
458
|
+
} = props;
|
|
459
|
+
const {
|
|
460
|
+
navigateIntent
|
|
461
|
+
} = useRouter();
|
|
462
|
+
return /* @__PURE__ */jsx(Button, {
|
|
463
|
+
onClick: () => navigateIntent("edit", {
|
|
464
|
+
id,
|
|
465
|
+
type
|
|
466
|
+
}),
|
|
467
|
+
mode: "ghost",
|
|
468
|
+
fontSize: 1,
|
|
469
|
+
padding: 2,
|
|
470
|
+
tabIndex: -1,
|
|
471
|
+
icon: EditIcon,
|
|
472
|
+
text: "Edit",
|
|
473
|
+
disabled
|
|
618
474
|
});
|
|
619
475
|
}
|
|
620
|
-
function
|
|
621
|
-
|
|
476
|
+
function Field(props) {
|
|
477
|
+
var _a;
|
|
478
|
+
const schema = useSchema();
|
|
479
|
+
const {
|
|
622
480
|
data,
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
} =
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
const toast = useToast();
|
|
630
|
-
const documentsWithoutValidMetadataIds = (data == null ? void 0 : data.length) ? data.reduce((acc, cur) => {
|
|
631
|
-
var _a;
|
|
632
|
-
const {
|
|
633
|
-
documentId,
|
|
634
|
-
state
|
|
635
|
-
} = (_a = cur._metadata) != null ? _a : {};
|
|
636
|
-
const stateExists = states.find(s => s.id === state);
|
|
637
|
-
return !stateExists && documentId ? [...acc, documentId] : acc;
|
|
638
|
-
}, []) : [];
|
|
639
|
-
const documentsWithInvalidUserIds = (data == null ? void 0 : data.length) ? data.reduce((acc, cur) => {
|
|
640
|
-
var _a;
|
|
641
|
-
const {
|
|
642
|
-
documentId,
|
|
643
|
-
assignees
|
|
644
|
-
} = (_a = cur._metadata) != null ? _a : {};
|
|
645
|
-
const allAssigneesExist = (assignees == null ? void 0 : assignees.length) ? assignees == null ? void 0 : assignees.every(a => userList.find(u => u.id === a)) : true;
|
|
646
|
-
return !allAssigneesExist && documentId ? [...acc, documentId] : acc;
|
|
647
|
-
}, []) : [];
|
|
648
|
-
const documentsWithoutOrderIds = (data == null ? void 0 : data.length) ? data.reduce((acc, cur) => {
|
|
649
|
-
var _a;
|
|
650
|
-
const {
|
|
651
|
-
documentId,
|
|
652
|
-
orderRank
|
|
653
|
-
} = (_a = cur._metadata) != null ? _a : {};
|
|
654
|
-
return !orderRank && documentId ? [...acc, documentId] : acc;
|
|
655
|
-
}, []) : [];
|
|
656
|
-
const correctDocuments = React.useCallback(async ids => {
|
|
657
|
-
toast.push({
|
|
658
|
-
title: "Correcting...",
|
|
659
|
-
status: "info"
|
|
660
|
-
});
|
|
661
|
-
const tx = ids.reduce((item, documentId) => {
|
|
662
|
-
return item.patch("workflow-metadata.".concat(documentId), {
|
|
663
|
-
set: {
|
|
664
|
-
state: states[0].id
|
|
665
|
-
}
|
|
666
|
-
});
|
|
667
|
-
}, client.transaction());
|
|
668
|
-
await tx.commit();
|
|
669
|
-
toast.push({
|
|
670
|
-
title: "Corrected ".concat(ids.length === 1 ? "1 Document" : "".concat(ids.length, " Documents")),
|
|
671
|
-
status: "success"
|
|
672
|
-
});
|
|
673
|
-
}, [client, states, toast]);
|
|
674
|
-
const removeUsersFromDocuments = React.useCallback(async ids => {
|
|
675
|
-
toast.push({
|
|
676
|
-
title: "Removing users...",
|
|
677
|
-
status: "info"
|
|
678
|
-
});
|
|
679
|
-
const tx = ids.reduce((item, documentId) => {
|
|
680
|
-
var _a, _b;
|
|
681
|
-
const {
|
|
682
|
-
assignees
|
|
683
|
-
} = (_b = (_a = data.find(d => d._id === documentId)) == null ? void 0 : _a._metadata) != null ? _b : {};
|
|
684
|
-
const validAssignees = (assignees == null ? void 0 : assignees.length) ?
|
|
685
|
-
// eslint-disable-next-line max-nested-callbacks
|
|
686
|
-
assignees.filter(a => {
|
|
687
|
-
var _a2;
|
|
688
|
-
return (_a2 = userList.find(u => u.id === a)) == null ? void 0 : _a2.id;
|
|
689
|
-
}) : [];
|
|
690
|
-
return item.patch("workflow-metadata.".concat(documentId), {
|
|
691
|
-
set: {
|
|
692
|
-
assignees: validAssignees
|
|
693
|
-
}
|
|
694
|
-
});
|
|
695
|
-
}, client.transaction());
|
|
696
|
-
await tx.commit();
|
|
697
|
-
toast.push({
|
|
698
|
-
title: "Corrected ".concat(ids.length === 1 ? "1 Document" : "".concat(ids.length, " Documents")),
|
|
699
|
-
status: "success"
|
|
700
|
-
});
|
|
701
|
-
}, [client, data, toast, userList]);
|
|
702
|
-
const addOrderToDocuments = React.useCallback(async ids => {
|
|
703
|
-
var _a, _b;
|
|
704
|
-
toast.push({
|
|
705
|
-
title: "Adding ordering...",
|
|
706
|
-
status: "info"
|
|
707
|
-
});
|
|
708
|
-
const firstOrder = (_b = (_a = data[0]) == null ? void 0 : _a._metadata) == null ? void 0 : _b.orderRank;
|
|
709
|
-
let newLexo = firstOrder && data.length !== ids.length ? LexoRank.parse(firstOrder) : LexoRank.min();
|
|
710
|
-
const tx = client.transaction();
|
|
711
|
-
for (let index = 0; index < ids.length; index += 1) {
|
|
712
|
-
newLexo = newLexo.genNext().genNext();
|
|
713
|
-
tx.patch("workflow-metadata.".concat(ids[index]), {
|
|
714
|
-
set: {
|
|
715
|
-
orderRank: newLexo.toString()
|
|
716
|
-
}
|
|
717
|
-
});
|
|
481
|
+
loading,
|
|
482
|
+
error
|
|
483
|
+
} = useListeningQuery("*[_id in [$id, $draftId]]|order(_updatedAt)[0]", {
|
|
484
|
+
params: {
|
|
485
|
+
id: String(props.value),
|
|
486
|
+
draftId: "drafts.".concat(String(props.value))
|
|
718
487
|
}
|
|
719
|
-
await tx.commit();
|
|
720
|
-
toast.push({
|
|
721
|
-
title: "Added order to ".concat(ids.length === 1 ? "1 Document" : "".concat(ids.length, " Documents")),
|
|
722
|
-
status: "success"
|
|
723
|
-
});
|
|
724
|
-
}, [data, client, toast]);
|
|
725
|
-
return /* @__PURE__ */jsxs(FloatingCard, {
|
|
726
|
-
children: [documentsWithoutValidMetadataIds.length > 0 ? /* @__PURE__ */jsx(Button, {
|
|
727
|
-
tone: "caution",
|
|
728
|
-
onClick: () => correctDocuments(documentsWithoutValidMetadataIds),
|
|
729
|
-
text: documentsWithoutValidMetadataIds.length === 1 ? "Correct 1 Document State" : "Correct ".concat(documentsWithoutValidMetadataIds.length, " Document States")
|
|
730
|
-
}) : null, documentsWithInvalidUserIds.length > 0 ? /* @__PURE__ */jsx(Button, {
|
|
731
|
-
tone: "caution",
|
|
732
|
-
onClick: () => removeUsersFromDocuments(documentsWithInvalidUserIds),
|
|
733
|
-
text: documentsWithInvalidUserIds.length === 1 ? "Remove Invalid Users from 1 Document" : "Remove Invalid Users from ".concat(documentsWithInvalidUserIds.length, " Documents")
|
|
734
|
-
}) : null, documentsWithoutOrderIds.length > 0 ? /* @__PURE__ */jsx(Button, {
|
|
735
|
-
tone: "caution",
|
|
736
|
-
onClick: () => addOrderToDocuments(documentsWithoutOrderIds),
|
|
737
|
-
text: documentsWithoutOrderIds.length === 1 ? "Set Order for 1 Document" : "Set Order for ".concat(documentsWithoutOrderIds.length, " Documents")
|
|
738
|
-
}) : null]
|
|
739
488
|
});
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
toggleSelectedSchemaType
|
|
750
|
-
} = props;
|
|
751
|
-
const currentUser = useCurrentUser();
|
|
752
|
-
const schema = useSchema();
|
|
753
|
-
const onAdd = useCallback(id => {
|
|
754
|
-
if (!selectedUserIds.includes(id)) {
|
|
755
|
-
toggleSelectedUser(id);
|
|
756
|
-
}
|
|
757
|
-
}, [selectedUserIds, toggleSelectedUser]);
|
|
758
|
-
const onRemove = useCallback(id => {
|
|
759
|
-
if (selectedUserIds.includes(id)) {
|
|
760
|
-
toggleSelectedUser(id);
|
|
761
|
-
}
|
|
762
|
-
}, [selectedUserIds, toggleSelectedUser]);
|
|
763
|
-
const onClear = useCallback(() => {
|
|
764
|
-
resetSelectedUsers();
|
|
765
|
-
}, [resetSelectedUsers]);
|
|
766
|
-
if (uniqueAssignedUsers.length === 0 && schemaTypes.length < 2) {
|
|
767
|
-
return null;
|
|
489
|
+
if (loading) {
|
|
490
|
+
return /* @__PURE__ */jsx(Spinner, {});
|
|
491
|
+
}
|
|
492
|
+
const schemaType = schema.get((_a = data == null ? void 0 : data._type) != null ? _a : "");
|
|
493
|
+
if (error || !(data == null ? void 0 : data._type) || !schemaType) {
|
|
494
|
+
return /* @__PURE__ */jsx(Feedback, {
|
|
495
|
+
tone: "critical",
|
|
496
|
+
title: "Error with query"
|
|
497
|
+
});
|
|
768
498
|
}
|
|
769
|
-
const meInUniqueAssignees = (currentUser == null ? void 0 : currentUser.id) && uniqueAssignedUsers.find(u => u.id === currentUser.id);
|
|
770
|
-
const uniqueAssigneesNotMe = uniqueAssignedUsers.filter(u => u.id !== (currentUser == null ? void 0 : currentUser.id));
|
|
771
499
|
return /* @__PURE__ */jsx(Card, {
|
|
772
|
-
|
|
500
|
+
border: true,
|
|
773
501
|
padding: 2,
|
|
774
|
-
borderBottom: true,
|
|
775
|
-
style: {
|
|
776
|
-
overflowX: "hidden"
|
|
777
|
-
},
|
|
778
502
|
children: /* @__PURE__ */jsxs(Flex, {
|
|
779
503
|
align: "center",
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
})
|
|
873
|
-
});
|
|
874
|
-
}
|
|
875
|
-
function filterItemsAndSort(items, stateId) {
|
|
876
|
-
let selectedUsers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
|
|
504
|
+
justify: "space-between",
|
|
505
|
+
gap: 2,
|
|
506
|
+
children: [/* @__PURE__ */jsx(Preview, {
|
|
507
|
+
layout: "default",
|
|
508
|
+
value: data,
|
|
509
|
+
schemaType
|
|
510
|
+
}), /* @__PURE__ */jsx(EditButton, {
|
|
511
|
+
id: data._id,
|
|
512
|
+
type: data._type
|
|
513
|
+
})]
|
|
514
|
+
})
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
const UserAssignmentInput = props => {
|
|
518
|
+
var _a;
|
|
519
|
+
const documentId = useFormValue(["documentId"]);
|
|
520
|
+
const userList = useProjectUsers({
|
|
521
|
+
apiVersion: API_VERSION
|
|
522
|
+
});
|
|
523
|
+
const stringValue = Array.isArray(props == null ? void 0 : props.value) && ((_a = props == null ? void 0 : props.value) == null ? void 0 : _a.length) ? props.value.map(item => String(item)) : [];
|
|
524
|
+
return /* @__PURE__ */jsx(Card, {
|
|
525
|
+
border: true,
|
|
526
|
+
padding: 1,
|
|
527
|
+
children: /* @__PURE__ */jsx(UserAssignment, {
|
|
528
|
+
userList,
|
|
529
|
+
assignees: stringValue,
|
|
530
|
+
documentId: String(documentId)
|
|
531
|
+
})
|
|
532
|
+
});
|
|
533
|
+
};
|
|
534
|
+
function initialRank() {
|
|
535
|
+
let lastRankValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
|
|
536
|
+
const lastRank = lastRankValue && typeof lastRankValue === "string" ? LexoRank.parse(lastRankValue) : LexoRank.min();
|
|
537
|
+
const nextRank = lastRank.genNext().genNext();
|
|
538
|
+
return nextRank.value;
|
|
539
|
+
}
|
|
540
|
+
var metadata = states => defineType({
|
|
541
|
+
type: "document",
|
|
542
|
+
name: "workflow.metadata",
|
|
543
|
+
title: "Workflow metadata",
|
|
544
|
+
liveEdit: true,
|
|
545
|
+
fields: [defineField({
|
|
546
|
+
name: "state",
|
|
547
|
+
description: "The current \"State\" of the document. Field is read only as changing it would not fire the state's \"operation\" setting. These are fired in the Document Actions and in the custom Tool.",
|
|
548
|
+
readOnly: true,
|
|
549
|
+
type: "string",
|
|
550
|
+
options: {
|
|
551
|
+
list: states.length ? states.map(state => ({
|
|
552
|
+
value: state.id,
|
|
553
|
+
title: state.title
|
|
554
|
+
})) : [],
|
|
555
|
+
layout: "radio"
|
|
556
|
+
}
|
|
557
|
+
}), defineField({
|
|
558
|
+
name: "documentId",
|
|
559
|
+
title: "Document ID",
|
|
560
|
+
description: "Used to help identify the target document that this metadata is tracking state for.",
|
|
561
|
+
type: "string",
|
|
562
|
+
readOnly: true,
|
|
563
|
+
components: {
|
|
564
|
+
input: Field
|
|
565
|
+
}
|
|
566
|
+
}), defineField({
|
|
567
|
+
name: "orderRank",
|
|
568
|
+
description: "Used to maintain order position of cards in the Tool.",
|
|
569
|
+
type: "string",
|
|
570
|
+
readOnly: true,
|
|
571
|
+
initialValue: async (p, _ref) => {
|
|
572
|
+
let {
|
|
573
|
+
getClient
|
|
574
|
+
} = _ref;
|
|
575
|
+
const lastDocOrderRank = await getClient({
|
|
576
|
+
apiVersion: API_VERSION
|
|
577
|
+
}).fetch("*[_type == $type]|order(@[$order] desc)[0][$order]", {
|
|
578
|
+
order: "orderRank",
|
|
579
|
+
type: "workflow.metadata"
|
|
580
|
+
});
|
|
581
|
+
return initialRank(lastDocOrderRank);
|
|
582
|
+
}
|
|
583
|
+
}), defineField({
|
|
584
|
+
type: "array",
|
|
585
|
+
name: "assignees",
|
|
586
|
+
of: [{
|
|
587
|
+
type: "string"
|
|
588
|
+
}],
|
|
589
|
+
components: {
|
|
590
|
+
input: UserAssignmentInput
|
|
591
|
+
}
|
|
592
|
+
})]
|
|
593
|
+
});
|
|
594
|
+
function filterItemsAndSort(items, stateId) {
|
|
595
|
+
let selectedUsers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
|
|
877
596
|
let selectedSchemaTypes = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
878
|
-
return items.filter(item => {
|
|
597
|
+
return items.filter(item => item == null ? void 0 : item._id).filter(item => {
|
|
879
598
|
var _a;
|
|
880
599
|
return ((_a = item == null ? void 0 : item._metadata) == null ? void 0 : _a.state) === stateId;
|
|
881
600
|
}).filter(item => {
|
|
@@ -893,754 +612,1144 @@ function filterItemsAndSort(items, stateId) {
|
|
|
893
612
|
return aOrderRank.localeCompare(bOrderRank);
|
|
894
613
|
});
|
|
895
614
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
const {
|
|
901
|
-
text,
|
|
902
|
-
icon
|
|
903
|
-
} = props;
|
|
904
|
-
const Icon = icon;
|
|
905
|
-
return /* @__PURE__ */jsx(Tooltip, {
|
|
906
|
-
portal: true,
|
|
907
|
-
content: /* @__PURE__ */jsx(Box, {
|
|
908
|
-
padding: 2,
|
|
909
|
-
children: /* @__PURE__ */jsx(Text, {
|
|
910
|
-
size: 1,
|
|
911
|
-
children: text
|
|
912
|
-
})
|
|
913
|
-
}),
|
|
914
|
-
children: /* @__PURE__ */jsx(Text, {
|
|
915
|
-
size: 1,
|
|
916
|
-
children: /* @__PURE__ */jsx(Icon, {})
|
|
917
|
-
})
|
|
918
|
-
});
|
|
919
|
-
}
|
|
920
|
-
const StyledStickyCard = styled(Card)(() => css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n position: sticky;\n top: 0;\n z-index: 1;\n "]))));
|
|
921
|
-
function StateTitle(props) {
|
|
922
|
-
const {
|
|
923
|
-
state,
|
|
924
|
-
requireAssignment,
|
|
925
|
-
userRoleCanDrop,
|
|
926
|
-
isDropDisabled,
|
|
927
|
-
draggingFrom
|
|
928
|
-
} = props;
|
|
929
|
-
let tone = "default";
|
|
930
|
-
const isSource = draggingFrom === state.id;
|
|
931
|
-
if (draggingFrom) {
|
|
932
|
-
tone = isDropDisabled || isSource ? "default" : "positive";
|
|
933
|
-
}
|
|
934
|
-
return /* @__PURE__ */jsx(StyledStickyCard, {
|
|
935
|
-
paddingY: 4,
|
|
936
|
-
padding: 3,
|
|
937
|
-
tone: "inherit",
|
|
938
|
-
children: /* @__PURE__ */jsxs(Flex, {
|
|
939
|
-
gap: 3,
|
|
940
|
-
align: "center",
|
|
941
|
-
children: [/* @__PURE__ */jsx(Badge, {
|
|
942
|
-
mode: draggingFrom && !isDropDisabled || isSource ? "default" : "outline",
|
|
943
|
-
tone,
|
|
944
|
-
muted: !userRoleCanDrop || isDropDisabled,
|
|
945
|
-
children: state.title
|
|
946
|
-
}), userRoleCanDrop ? null : /* @__PURE__ */jsx(Status, {
|
|
947
|
-
text: "You do not have permissions to move documents to this State",
|
|
948
|
-
icon: InfoOutlineIcon
|
|
949
|
-
}), requireAssignment ? /* @__PURE__ */jsx(Status, {
|
|
950
|
-
text: "You must be assigned to the document to move documents to this State",
|
|
951
|
-
icon: UserIcon
|
|
952
|
-
}) : null]
|
|
953
|
-
})
|
|
954
|
-
});
|
|
955
|
-
}
|
|
956
|
-
function WorkflowTool(props) {
|
|
957
|
-
var _a, _b, _c;
|
|
958
|
-
const {
|
|
959
|
-
schemaTypes = [],
|
|
960
|
-
states = []
|
|
961
|
-
} = (_b = (_a = props == null ? void 0 : props.tool) == null ? void 0 : _a.options) != null ? _b : {};
|
|
962
|
-
const isDarkMode = useTheme().sanity.color.dark;
|
|
963
|
-
const defaultCardTone = isDarkMode ? "default" : "transparent";
|
|
964
|
-
const userList = useProjectUsers({
|
|
615
|
+
const QUERY = groq(_templateObject || (_templateObject = _taggedTemplateLiteral(["*[_type == \"workflow.metadata\"]|order(orderRank){\n \"_metadata\": {\n _rev,\n assignees,\n documentId,\n state,\n orderRank\n },\n ...(\n *[_id in [^.documentId, \"drafts.\" + ^.documentId]]|order(_updatedAt)[0]{ \n _id, \n _type, \n _rev, \n _updatedAt \n }\n )\n}"])));
|
|
616
|
+
function useWorkflowDocuments(schemaTypes) {
|
|
617
|
+
const toast = useToast();
|
|
618
|
+
const client = useClient({
|
|
965
619
|
apiVersion: API_VERSION
|
|
966
620
|
});
|
|
967
|
-
const user = useCurrentUser();
|
|
968
|
-
const userRoleNames = ((_c = user == null ? void 0 : user.roles) == null ? void 0 : _c.length) ? user == null ? void 0 : user.roles.map(r => r.name) : [];
|
|
969
|
-
const {
|
|
970
|
-
workflowData,
|
|
971
|
-
operations
|
|
972
|
-
} = useWorkflowDocuments(schemaTypes);
|
|
973
621
|
const {
|
|
974
622
|
data,
|
|
975
623
|
loading,
|
|
976
624
|
error
|
|
977
|
-
} =
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
const
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
625
|
+
} = useListeningQuery(QUERY, {
|
|
626
|
+
params: {
|
|
627
|
+
schemaTypes
|
|
628
|
+
},
|
|
629
|
+
initialValue: []
|
|
630
|
+
});
|
|
631
|
+
const [localDocuments, setLocalDocuments] = React.useState([]);
|
|
632
|
+
React.useEffect(() => {
|
|
633
|
+
if (data) {
|
|
634
|
+
setLocalDocuments(data);
|
|
635
|
+
}
|
|
636
|
+
}, [data]);
|
|
637
|
+
const move = React.useCallback((draggedId, destination, states, newOrder) => {
|
|
638
|
+
const currentLocalData = localDocuments;
|
|
639
|
+
const newLocalDocuments = localDocuments.map(item => {
|
|
640
|
+
var _a;
|
|
641
|
+
if (((_a = item == null ? void 0 : item._metadata) == null ? void 0 : _a.documentId) === draggedId) {
|
|
642
|
+
return {
|
|
643
|
+
...item,
|
|
644
|
+
_metadata: {
|
|
645
|
+
...item._metadata,
|
|
646
|
+
state: destination.droppableId,
|
|
647
|
+
orderRank: newOrder,
|
|
648
|
+
// This value won't be written to the document
|
|
649
|
+
// It's done so that un/publish operations don't happen twice
|
|
650
|
+
// Because a moved document's card will update once optimistically
|
|
651
|
+
// and then again when the document is updated
|
|
652
|
+
optimistic: true
|
|
653
|
+
}
|
|
654
|
+
};
|
|
1006
655
|
}
|
|
656
|
+
return item;
|
|
657
|
+
});
|
|
658
|
+
setLocalDocuments(newLocalDocuments);
|
|
659
|
+
const newStateId = destination.droppableId;
|
|
660
|
+
const newState = states.find(s => s.id === newStateId);
|
|
661
|
+
const document = localDocuments.find(d => {
|
|
662
|
+
var _a;
|
|
663
|
+
return ((_a = d == null ? void 0 : d._metadata) == null ? void 0 : _a.documentId) === draggedId;
|
|
664
|
+
});
|
|
665
|
+
if (!(newState == null ? void 0 : newState.id)) {
|
|
666
|
+
toast.push({
|
|
667
|
+
title: "Could not find target state ".concat(newStateId),
|
|
668
|
+
status: "error"
|
|
669
|
+
});
|
|
670
|
+
return null;
|
|
1007
671
|
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
672
|
+
if (!document) {
|
|
673
|
+
toast.push({
|
|
674
|
+
title: "Could not find dragged document in data",
|
|
675
|
+
status: "error"
|
|
676
|
+
});
|
|
677
|
+
return null;
|
|
1014
678
|
}
|
|
1015
|
-
const undroppableExceptSelf = undroppableStateIds.filter(id => id !== currentStateId);
|
|
1016
|
-
if (undroppableExceptSelf.length) {
|
|
1017
|
-
setUndroppableStates(undroppableExceptSelf);
|
|
1018
|
-
}
|
|
1019
|
-
}, [data, states, user]);
|
|
1020
|
-
const handleDragEnd = React.useCallback(result => {
|
|
1021
|
-
var _a2, _b2, _c2, _d, _e, _f;
|
|
1022
|
-
setUndroppableStates([]);
|
|
1023
|
-
setDraggingFrom("");
|
|
1024
679
|
const {
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
const itemBeforeRank = (_e = itemBefore == null ? void 0 : itemBefore._metadata) == null ? void 0 : _e.orderRank;
|
|
1049
|
-
const itemBeforeRankParsed = itemBefore._metadata.orderRank ? LexoRank.parse(itemBeforeRank) : LexoRank.min();
|
|
1050
|
-
const itemAfter = destinationStateItems[destination.index + 1];
|
|
1051
|
-
const itemAfterRank = (_f = itemAfter == null ? void 0 : itemAfter._metadata) == null ? void 0 : _f.orderRank;
|
|
1052
|
-
const itemAfterRankParsed = itemAfter._metadata.orderRank ? LexoRank.parse(itemAfterRank) : LexoRank.max();
|
|
1053
|
-
newOrder = itemBeforeRankParsed.between(itemAfterRankParsed).toString();
|
|
1054
|
-
}
|
|
1055
|
-
move(draggableId, destination, states, newOrder);
|
|
1056
|
-
}, [data, move, states]);
|
|
1057
|
-
const uniqueAssignedUsers = React.useMemo(() => {
|
|
1058
|
-
const uniqueUserIds = data.reduce((acc, item) => {
|
|
1059
|
-
var _a2;
|
|
1060
|
-
const {
|
|
1061
|
-
assignees = []
|
|
1062
|
-
} = (_a2 = item._metadata) != null ? _a2 : {};
|
|
1063
|
-
const newAssignees = (assignees == null ? void 0 : assignees.length) ? assignees.filter(a => !acc.includes(a)) : [];
|
|
1064
|
-
return newAssignees.length ? [...acc, ...newAssignees] : acc;
|
|
1065
|
-
}, []);
|
|
1066
|
-
return userList.filter(u => uniqueUserIds.includes(u.id));
|
|
1067
|
-
}, [data, userList]);
|
|
1068
|
-
const [selectedUserIds, setSelectedUserIds] = React.useState(uniqueAssignedUsers.map(u => u.id));
|
|
1069
|
-
const toggleSelectedUser = React.useCallback(userId => {
|
|
1070
|
-
setSelectedUserIds(prev => prev.includes(userId) ? prev.filter(u => u !== userId) : [...prev, userId]);
|
|
1071
|
-
}, []);
|
|
1072
|
-
const resetSelectedUsers = React.useCallback(() => {
|
|
1073
|
-
setSelectedUserIds([]);
|
|
1074
|
-
}, []);
|
|
1075
|
-
const [selectedSchemaTypes, setSelectedSchemaTypes] = React.useState(schemaTypes);
|
|
1076
|
-
const toggleSelectedSchemaType = React.useCallback(schemaType => {
|
|
1077
|
-
setSelectedSchemaTypes(prev => prev.includes(schemaType) ? prev.filter(u => u !== schemaType) : [...prev, schemaType]);
|
|
1078
|
-
}, []);
|
|
1079
|
-
const [invalidDocumentIds, setInvalidDocumentIds] = React.useState([]);
|
|
1080
|
-
const toggleInvalidDocumentId = React.useCallback((docId, action) => {
|
|
1081
|
-
setInvalidDocumentIds(prev => action === "ADD" ? [...prev, docId] : prev.filter(id => id !== docId));
|
|
1082
|
-
}, []);
|
|
1083
|
-
if (!(states == null ? void 0 : states.length)) {
|
|
1084
|
-
return /* @__PURE__ */jsx(Container, {
|
|
1085
|
-
width: 1,
|
|
1086
|
-
padding: 5,
|
|
1087
|
-
children: /* @__PURE__ */jsx(Feedback, {
|
|
1088
|
-
tone: "caution",
|
|
1089
|
-
title: "Plugin options error",
|
|
1090
|
-
description: "No States defined in plugin config"
|
|
1091
|
-
})
|
|
680
|
+
_id,
|
|
681
|
+
_type
|
|
682
|
+
} = document;
|
|
683
|
+
const {
|
|
684
|
+
_rev,
|
|
685
|
+
documentId
|
|
686
|
+
} = document._metadata || {};
|
|
687
|
+
client.patch("workflow-metadata.".concat(documentId)).ifRevisionId(_rev).set({
|
|
688
|
+
state: newStateId,
|
|
689
|
+
orderRank: newOrder
|
|
690
|
+
}).commit().then(() => {
|
|
691
|
+
var _a;
|
|
692
|
+
return toast.push({
|
|
693
|
+
title: "Moved to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
|
|
694
|
+
status: "success"
|
|
695
|
+
});
|
|
696
|
+
}).catch(() => {
|
|
697
|
+
var _a;
|
|
698
|
+
setLocalDocuments(currentLocalData);
|
|
699
|
+
return toast.push({
|
|
700
|
+
title: "Failed to move to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
|
|
701
|
+
status: "error"
|
|
702
|
+
});
|
|
1092
703
|
});
|
|
704
|
+
return {
|
|
705
|
+
_id,
|
|
706
|
+
_type,
|
|
707
|
+
documentId,
|
|
708
|
+
state: newState
|
|
709
|
+
};
|
|
710
|
+
}, [client, toast, localDocuments]);
|
|
711
|
+
return {
|
|
712
|
+
workflowData: {
|
|
713
|
+
data: localDocuments,
|
|
714
|
+
loading,
|
|
715
|
+
error
|
|
716
|
+
},
|
|
717
|
+
operations: {
|
|
718
|
+
move
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
function AvatarGroup(props) {
|
|
723
|
+
const currentUser = useCurrentUser();
|
|
724
|
+
const {
|
|
725
|
+
users,
|
|
726
|
+
max = 4
|
|
727
|
+
} = props;
|
|
728
|
+
const len = users == null ? void 0 : users.length;
|
|
729
|
+
const {
|
|
730
|
+
me,
|
|
731
|
+
visibleUsers
|
|
732
|
+
} = React.useMemo(() => {
|
|
733
|
+
return {
|
|
734
|
+
me: (currentUser == null ? void 0 : currentUser.id) ? users.find(u => u.id === currentUser.id) : void 0,
|
|
735
|
+
visibleUsers: users.filter(u => u.id !== (currentUser == null ? void 0 : currentUser.id)).slice(0, max - 1)
|
|
736
|
+
};
|
|
737
|
+
}, [users, max, currentUser]);
|
|
738
|
+
if (!(users == null ? void 0 : users.length)) {
|
|
739
|
+
return null;
|
|
1093
740
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
741
|
+
return /* @__PURE__ */jsxs(Flex, {
|
|
742
|
+
align: "center",
|
|
743
|
+
gap: 1,
|
|
744
|
+
children: [me ? /* @__PURE__ */jsx(UserAvatar, {
|
|
745
|
+
user: me
|
|
746
|
+
}) : null, visibleUsers.map(user => /* @__PURE__ */jsx(Box, {
|
|
747
|
+
style: {
|
|
748
|
+
marginRight: -8
|
|
749
|
+
},
|
|
750
|
+
children: /* @__PURE__ */jsx(UserAvatar, {
|
|
751
|
+
user
|
|
1101
752
|
})
|
|
1102
|
-
})
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
children: [/* @__PURE__ */jsx(Validators, {
|
|
1108
|
-
data,
|
|
1109
|
-
userList,
|
|
1110
|
-
states
|
|
1111
|
-
}), /* @__PURE__ */jsx(Filters, {
|
|
1112
|
-
uniqueAssignedUsers,
|
|
1113
|
-
selectedUserIds,
|
|
1114
|
-
toggleSelectedUser,
|
|
1115
|
-
resetSelectedUsers,
|
|
1116
|
-
schemaTypes,
|
|
1117
|
-
selectedSchemaTypes,
|
|
1118
|
-
toggleSelectedSchemaType
|
|
1119
|
-
}), /* @__PURE__ */jsx(DragDropContext, {
|
|
1120
|
-
onDragStart: handleDragStart,
|
|
1121
|
-
onDragEnd: handleDragEnd,
|
|
1122
|
-
children: /* @__PURE__ */jsx(Grid, {
|
|
1123
|
-
columns: states.length,
|
|
1124
|
-
height: "fill",
|
|
1125
|
-
children: states.map((state, stateIndex) => {
|
|
1126
|
-
var _a2, _b2;
|
|
1127
|
-
const userRoleCanDrop = ((_a2 = state == null ? void 0 : state.roles) == null ? void 0 : _a2.length) ? arraysContainMatchingString(state.roles, userRoleNames) : true;
|
|
1128
|
-
const isDropDisabled = !userRoleCanDrop || undroppableStates.includes(state.id);
|
|
1129
|
-
return /* @__PURE__ */jsxs(Card, {
|
|
1130
|
-
borderLeft: stateIndex > 0,
|
|
1131
|
-
tone: defaultCardTone,
|
|
1132
|
-
height: "fill",
|
|
1133
|
-
overflow: "auto",
|
|
1134
|
-
children: [/* @__PURE__ */jsx(StateTitle, {
|
|
1135
|
-
state,
|
|
1136
|
-
requireAssignment: (_b2 = state.requireAssignment) != null ? _b2 : false,
|
|
1137
|
-
userRoleCanDrop,
|
|
1138
|
-
isDropDisabled,
|
|
1139
|
-
draggingFrom
|
|
1140
|
-
}), /* @__PURE__ */jsx(Droppable, {
|
|
1141
|
-
droppableId: state.id,
|
|
1142
|
-
isDropDisabled,
|
|
1143
|
-
children: (provided, snapshot) => /* @__PURE__ */jsxs(Card, {
|
|
1144
|
-
ref: provided.innerRef,
|
|
1145
|
-
tone: snapshot.isDraggingOver ? "primary" : defaultCardTone,
|
|
1146
|
-
height: "fill",
|
|
1147
|
-
paddingTop: 1,
|
|
1148
|
-
children: [loading ? /* @__PURE__ */jsx(Flex, {
|
|
1149
|
-
padding: 5,
|
|
1150
|
-
align: "center",
|
|
1151
|
-
justify: "center",
|
|
1152
|
-
children: /* @__PURE__ */jsx(Spinner, {
|
|
1153
|
-
muted: true
|
|
1154
|
-
})
|
|
1155
|
-
}) : null, data.length > 0 && filterItemsAndSort(data, state.id, selectedUserIds, selectedSchemaTypes).map((item, itemIndex) => {
|
|
1156
|
-
var _a3, _b3, _c2, _d;
|
|
1157
|
-
const isInvalid = invalidDocumentIds.includes(String((_a3 = item == null ? void 0 : item._metadata) == null ? void 0 : _a3.documentId));
|
|
1158
|
-
const meInAssignees = (user == null ? void 0 : user.id) ? (_c2 = (_b3 = item == null ? void 0 : item._metadata) == null ? void 0 : _b3.assignees) == null ? void 0 : _c2.includes(user.id) : false;
|
|
1159
|
-
const isDragDisabled = !userRoleCanDrop || isInvalid || !(state.requireAssignment ? state.requireAssignment && meInAssignees : true);
|
|
1160
|
-
const {
|
|
1161
|
-
documentId
|
|
1162
|
-
} = (_d = item._metadata) != null ? _d : {};
|
|
1163
|
-
if (!documentId) {
|
|
1164
|
-
return null;
|
|
1165
|
-
}
|
|
1166
|
-
return /* @__PURE__ */jsx(Draggable, {
|
|
1167
|
-
draggableId: documentId,
|
|
1168
|
-
index: itemIndex,
|
|
1169
|
-
isDragDisabled,
|
|
1170
|
-
children: (draggableProvided, draggableSnapshot) => /* @__PURE__ */jsx("div", {
|
|
1171
|
-
ref: draggableProvided.innerRef,
|
|
1172
|
-
...draggableProvided.draggableProps,
|
|
1173
|
-
...draggableProvided.dragHandleProps,
|
|
1174
|
-
children: /* @__PURE__ */jsx(DocumentCard, {
|
|
1175
|
-
userRoleCanDrop,
|
|
1176
|
-
isDragDisabled,
|
|
1177
|
-
isDragging: draggableSnapshot.isDragging,
|
|
1178
|
-
item,
|
|
1179
|
-
toggleInvalidDocumentId,
|
|
1180
|
-
userList,
|
|
1181
|
-
states
|
|
1182
|
-
})
|
|
1183
|
-
})
|
|
1184
|
-
}, documentId);
|
|
1185
|
-
}), provided.placeholder]
|
|
1186
|
-
})
|
|
1187
|
-
})]
|
|
1188
|
-
}, state.id);
|
|
1189
|
-
})
|
|
753
|
+
}, user.id)), len > max && /* @__PURE__ */jsx(Box, {
|
|
754
|
+
paddingLeft: 2,
|
|
755
|
+
children: /* @__PURE__ */jsxs(Text, {
|
|
756
|
+
size: 1,
|
|
757
|
+
children: ["+", len - max]
|
|
1190
758
|
})
|
|
1191
759
|
})]
|
|
1192
760
|
});
|
|
1193
761
|
}
|
|
1194
|
-
|
|
1195
|
-
name: "workflow",
|
|
1196
|
-
title: "Workflow",
|
|
1197
|
-
component: WorkflowTool,
|
|
1198
|
-
icon: SplitVerticalIcon,
|
|
1199
|
-
options
|
|
1200
|
-
});
|
|
1201
|
-
function Field(props) {
|
|
1202
|
-
var _a;
|
|
1203
|
-
const schema = useSchema();
|
|
762
|
+
function UserDisplay(props) {
|
|
1204
763
|
const {
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
764
|
+
assignees,
|
|
765
|
+
userList,
|
|
766
|
+
documentId,
|
|
767
|
+
disabled = false
|
|
768
|
+
} = props;
|
|
769
|
+
const [button] = React.useState(null);
|
|
770
|
+
const [popover, setPopover] = React.useState(null);
|
|
771
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
772
|
+
const close = React.useCallback(() => setIsOpen(false), []);
|
|
773
|
+
const open = React.useCallback(() => setIsOpen(true), []);
|
|
774
|
+
useClickOutside(close, [button, popover]);
|
|
775
|
+
return /* @__PURE__ */jsx(Popover, {
|
|
776
|
+
ref: setPopover,
|
|
777
|
+
content: /* @__PURE__ */jsx(UserAssignment, {
|
|
778
|
+
userList,
|
|
779
|
+
assignees,
|
|
780
|
+
documentId
|
|
781
|
+
}),
|
|
782
|
+
portal: true,
|
|
783
|
+
open: isOpen,
|
|
784
|
+
children: !assignees || assignees.length === 0 ? /* @__PURE__ */jsx(Button, {
|
|
785
|
+
onClick: open,
|
|
786
|
+
fontSize: 1,
|
|
787
|
+
padding: 2,
|
|
788
|
+
tabIndex: -1,
|
|
789
|
+
icon: AddIcon,
|
|
790
|
+
text: "Assign",
|
|
791
|
+
tone: "positive",
|
|
792
|
+
mode: "ghost",
|
|
793
|
+
disabled
|
|
794
|
+
}) : /* @__PURE__ */jsx(Grid, {
|
|
795
|
+
children: /* @__PURE__ */jsx(Button, {
|
|
796
|
+
onClick: open,
|
|
797
|
+
padding: 0,
|
|
798
|
+
mode: "bleed",
|
|
799
|
+
disabled,
|
|
800
|
+
children: /* @__PURE__ */jsx(AvatarGroup, {
|
|
801
|
+
users: userList.filter(u => assignees.includes(u.id))
|
|
802
|
+
})
|
|
803
|
+
})
|
|
804
|
+
})
|
|
1213
805
|
});
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
806
|
+
}
|
|
807
|
+
function CompleteButton(props) {
|
|
808
|
+
const {
|
|
809
|
+
documentId,
|
|
810
|
+
disabled = false
|
|
811
|
+
} = props;
|
|
812
|
+
const client = useClient({
|
|
813
|
+
apiVersion: API_VERSION
|
|
814
|
+
});
|
|
815
|
+
const toast = useToast();
|
|
816
|
+
const handleComplete = React.useCallback(id => {
|
|
817
|
+
client.delete("workflow-metadata.".concat(id)).then(() => {
|
|
818
|
+
toast.push({
|
|
819
|
+
status: "success",
|
|
820
|
+
title: "Workflow completed",
|
|
821
|
+
description: id
|
|
822
|
+
});
|
|
823
|
+
}).catch(() => {
|
|
824
|
+
toast.push({
|
|
825
|
+
status: "error",
|
|
826
|
+
title: "Could not complete Workflow",
|
|
827
|
+
description: id
|
|
828
|
+
});
|
|
1222
829
|
});
|
|
1223
|
-
}
|
|
1224
|
-
return /* @__PURE__ */jsx(
|
|
1225
|
-
|
|
830
|
+
}, [client, toast]);
|
|
831
|
+
return /* @__PURE__ */jsx(Button, {
|
|
832
|
+
onClick: () => handleComplete(documentId),
|
|
833
|
+
text: "Complete",
|
|
834
|
+
icon: CheckmarkIcon,
|
|
835
|
+
tone: "positive",
|
|
836
|
+
mode: "ghost",
|
|
837
|
+
fontSize: 1,
|
|
1226
838
|
padding: 2,
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
justify: "space-between",
|
|
1230
|
-
gap: 2,
|
|
1231
|
-
children: [/* @__PURE__ */jsx(Preview, {
|
|
1232
|
-
layout: "default",
|
|
1233
|
-
value: data,
|
|
1234
|
-
schemaType
|
|
1235
|
-
}), /* @__PURE__ */jsx(EditButton, {
|
|
1236
|
-
id: data._id,
|
|
1237
|
-
type: data._type
|
|
1238
|
-
})]
|
|
1239
|
-
})
|
|
839
|
+
tabIndex: -1,
|
|
840
|
+
disabled
|
|
1240
841
|
});
|
|
1241
842
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
border: true,
|
|
1251
|
-
padding: 1,
|
|
1252
|
-
children: /* @__PURE__ */jsx(UserAssignment, {
|
|
1253
|
-
userList,
|
|
1254
|
-
assignees: stringValue,
|
|
1255
|
-
documentId: String(documentId)
|
|
1256
|
-
})
|
|
843
|
+
function TimeAgo(_ref2) {
|
|
844
|
+
let {
|
|
845
|
+
time
|
|
846
|
+
} = _ref2;
|
|
847
|
+
const timeAgo = useTimeAgo(time);
|
|
848
|
+
return /* @__PURE__ */jsxs("span", {
|
|
849
|
+
title: timeAgo,
|
|
850
|
+
children: [timeAgo, " ago"]
|
|
1257
851
|
});
|
|
1258
|
-
};
|
|
1259
|
-
function initialRank() {
|
|
1260
|
-
let lastRankValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
|
|
1261
|
-
const lastRank = lastRankValue && typeof lastRankValue === "string" ? LexoRank.parse(lastRankValue) : LexoRank.min();
|
|
1262
|
-
const nextRank = lastRank.genNext().genNext();
|
|
1263
|
-
return nextRank.value;
|
|
1264
852
|
}
|
|
1265
|
-
|
|
1266
|
-
type: "document",
|
|
1267
|
-
name: "workflow.metadata",
|
|
1268
|
-
title: "Workflow metadata",
|
|
1269
|
-
liveEdit: true,
|
|
1270
|
-
fields: [defineField({
|
|
1271
|
-
name: "state",
|
|
1272
|
-
description: "The current \"State\" of the document. Field is read only as changing it would not fire the state's \"operation\" setting. These are fired in the Document Actions and in the custom Tool.",
|
|
1273
|
-
readOnly: true,
|
|
1274
|
-
type: "string",
|
|
1275
|
-
options: {
|
|
1276
|
-
list: states.length ? states.map(state => ({
|
|
1277
|
-
value: state.id,
|
|
1278
|
-
title: state.title
|
|
1279
|
-
})) : [],
|
|
1280
|
-
layout: "radio"
|
|
1281
|
-
}
|
|
1282
|
-
}), defineField({
|
|
1283
|
-
name: "documentId",
|
|
1284
|
-
title: "Document ID",
|
|
1285
|
-
description: "Used to help identify the target document that this metadata is tracking state for.",
|
|
1286
|
-
type: "string",
|
|
1287
|
-
readOnly: true,
|
|
1288
|
-
components: {
|
|
1289
|
-
input: Field
|
|
1290
|
-
}
|
|
1291
|
-
}), defineField({
|
|
1292
|
-
name: "orderRank",
|
|
1293
|
-
description: "Used to maintain order position of cards in the Tool.",
|
|
1294
|
-
type: "string",
|
|
1295
|
-
readOnly: true,
|
|
1296
|
-
initialValue: async (p, _ref4) => {
|
|
1297
|
-
let {
|
|
1298
|
-
getClient
|
|
1299
|
-
} = _ref4;
|
|
1300
|
-
const lastDocOrderRank = await getClient({
|
|
1301
|
-
apiVersion: API_VERSION
|
|
1302
|
-
}).fetch("*[_type == $type]|order(@[$order] desc)[0][$order]", {
|
|
1303
|
-
order: "orderRank",
|
|
1304
|
-
type: "workflow.metadata"
|
|
1305
|
-
});
|
|
1306
|
-
return initialRank(lastDocOrderRank);
|
|
1307
|
-
}
|
|
1308
|
-
}), defineField({
|
|
1309
|
-
type: "array",
|
|
1310
|
-
name: "assignees",
|
|
1311
|
-
of: [{
|
|
1312
|
-
type: "string"
|
|
1313
|
-
}],
|
|
1314
|
-
components: {
|
|
1315
|
-
input: UserAssignmentInput
|
|
1316
|
-
}
|
|
1317
|
-
})]
|
|
1318
|
-
});
|
|
1319
|
-
function useWorkflowMetadata(id, states) {
|
|
853
|
+
function DraftStatus(props) {
|
|
1320
854
|
const {
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
855
|
+
document
|
|
856
|
+
} = props;
|
|
857
|
+
const updatedAt = document && "_updatedAt" in document && document._updatedAt;
|
|
858
|
+
return /* @__PURE__ */jsx(Tooltip, {
|
|
859
|
+
portal: true,
|
|
860
|
+
content: /* @__PURE__ */jsx(Box, {
|
|
861
|
+
padding: 2,
|
|
862
|
+
children: /* @__PURE__ */jsx(Text, {
|
|
863
|
+
size: 1,
|
|
864
|
+
children: document ? /* @__PURE__ */jsxs(Fragment, {
|
|
865
|
+
children: ["Edited ", updatedAt && /* @__PURE__ */jsx(TimeAgo, {
|
|
866
|
+
time: updatedAt
|
|
867
|
+
})]
|
|
868
|
+
}) : /* @__PURE__ */jsx(Fragment, {
|
|
869
|
+
children: "No unpublished edits"
|
|
870
|
+
})
|
|
871
|
+
})
|
|
872
|
+
}),
|
|
873
|
+
children: /* @__PURE__ */jsx(TextWithTone, {
|
|
874
|
+
tone: "caution",
|
|
875
|
+
dimmed: !document,
|
|
876
|
+
muted: !document,
|
|
877
|
+
size: 1,
|
|
878
|
+
children: /* @__PURE__ */jsx(EditIcon, {})
|
|
879
|
+
})
|
|
1328
880
|
});
|
|
1329
|
-
if (metadata == null ? void 0 : metadata.state) {
|
|
1330
|
-
return {
|
|
1331
|
-
data: {
|
|
1332
|
-
metadata,
|
|
1333
|
-
state: states.find(s => s.id === metadata.state)
|
|
1334
|
-
},
|
|
1335
|
-
loading,
|
|
1336
|
-
error
|
|
1337
|
-
};
|
|
1338
|
-
}
|
|
1339
|
-
return {
|
|
1340
|
-
data: {},
|
|
1341
|
-
loading,
|
|
1342
|
-
error
|
|
1343
|
-
};
|
|
1344
881
|
}
|
|
1345
|
-
function
|
|
1346
|
-
var _a, _b;
|
|
882
|
+
function PublishedStatus(props) {
|
|
1347
883
|
const {
|
|
1348
|
-
|
|
884
|
+
document
|
|
1349
885
|
} = props;
|
|
1350
|
-
const
|
|
1351
|
-
|
|
1352
|
-
|
|
886
|
+
const updatedAt = document && "_updatedAt" in document && document._updatedAt;
|
|
887
|
+
return /* @__PURE__ */jsx(Tooltip, {
|
|
888
|
+
portal: true,
|
|
889
|
+
content: /* @__PURE__ */jsx(Box, {
|
|
890
|
+
padding: 2,
|
|
891
|
+
children: /* @__PURE__ */jsx(Text, {
|
|
892
|
+
size: 1,
|
|
893
|
+
children: document ? /* @__PURE__ */jsxs(Fragment, {
|
|
894
|
+
children: ["Published ", updatedAt && /* @__PURE__ */jsx(TimeAgo, {
|
|
895
|
+
time: updatedAt
|
|
896
|
+
})]
|
|
897
|
+
}) : /* @__PURE__ */jsx(Fragment, {
|
|
898
|
+
children: "Not published"
|
|
899
|
+
})
|
|
900
|
+
})
|
|
901
|
+
}),
|
|
902
|
+
children: /* @__PURE__ */jsx(TextWithTone, {
|
|
903
|
+
tone: "positive",
|
|
904
|
+
dimmed: !document,
|
|
905
|
+
muted: !document,
|
|
906
|
+
size: 1,
|
|
907
|
+
children: /* @__PURE__ */jsx(PublishIcon, {})
|
|
908
|
+
})
|
|
1353
909
|
});
|
|
910
|
+
}
|
|
911
|
+
function ValidationStatus(props) {
|
|
1354
912
|
const {
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
} = useWorkflowMetadata(id, states);
|
|
1359
|
-
if (error) {
|
|
1360
|
-
console.error(error);
|
|
1361
|
-
}
|
|
1362
|
-
if (!(data == null ? void 0 : data.metadata)) {
|
|
913
|
+
validation = []
|
|
914
|
+
} = props;
|
|
915
|
+
if (!validation.length) {
|
|
1363
916
|
return null;
|
|
1364
917
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
onClose: () => {
|
|
1374
|
-
setDialogOpen(false);
|
|
1375
|
-
},
|
|
1376
|
-
content: /* @__PURE__ */jsx(UserAssignment, {
|
|
1377
|
-
userList,
|
|
1378
|
-
assignees: (_b = (_a = data.metadata) == null ? void 0 : _a.assignees) != null ? _b : [],
|
|
1379
|
-
documentId: id
|
|
918
|
+
const hasError = validation.some(item => item.level === "error");
|
|
919
|
+
return /* @__PURE__ */jsx(Tooltip, {
|
|
920
|
+
portal: true,
|
|
921
|
+
content: /* @__PURE__ */jsx(Box, {
|
|
922
|
+
padding: 2,
|
|
923
|
+
children: /* @__PURE__ */jsx(Text, {
|
|
924
|
+
size: 1,
|
|
925
|
+
children: validation.length === 1 ? "1 validation issue" : "".concat(validation.length, " validation issues")
|
|
1380
926
|
})
|
|
1381
|
-
},
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
}
|
|
1387
|
-
function BeginWorkflow(props, states) {
|
|
1388
|
-
const {
|
|
1389
|
-
id,
|
|
1390
|
-
draft
|
|
1391
|
-
} = props;
|
|
1392
|
-
const {
|
|
1393
|
-
data,
|
|
1394
|
-
loading,
|
|
1395
|
-
error
|
|
1396
|
-
} = useWorkflowMetadata(id, states);
|
|
1397
|
-
const client = useClient({
|
|
1398
|
-
apiVersion: API_VERSION
|
|
927
|
+
}),
|
|
928
|
+
children: /* @__PURE__ */jsx(TextWithTone, {
|
|
929
|
+
tone: hasError ? "critical" : "caution",
|
|
930
|
+
size: 1,
|
|
931
|
+
children: hasError ? /* @__PURE__ */jsx(ErrorOutlineIcon, {}) : /* @__PURE__ */jsx(WarningOutlineIcon, {})
|
|
932
|
+
})
|
|
1399
933
|
});
|
|
1400
|
-
const toast = useToast();
|
|
1401
|
-
const [beginning, setBeginning] = useState(false);
|
|
1402
|
-
const [complete, setComplete] = useState(false);
|
|
1403
|
-
if (error) {
|
|
1404
|
-
console.error(error);
|
|
1405
|
-
}
|
|
1406
|
-
const handle = useCallback(async () => {
|
|
1407
|
-
setBeginning(true);
|
|
1408
|
-
const lowestOrderFirstState = await client.fetch("*[_type == \"workflow.metadata\" && state == $state]|order(orderRank)[0].orderRank", {
|
|
1409
|
-
state: states[0].id
|
|
1410
|
-
});
|
|
1411
|
-
client.createIfNotExists({
|
|
1412
|
-
_id: "workflow-metadata.".concat(id),
|
|
1413
|
-
_type: "workflow.metadata",
|
|
1414
|
-
documentId: id,
|
|
1415
|
-
state: states[0].id,
|
|
1416
|
-
orderRank: lowestOrderFirstState ? LexoRank.parse(lowestOrderFirstState).genNext().toString() : LexoRank.min().toString()
|
|
1417
|
-
},
|
|
1418
|
-
// Faster!
|
|
1419
|
-
{
|
|
1420
|
-
visibility: "async"
|
|
1421
|
-
}).then(() => {
|
|
1422
|
-
toast.push({
|
|
1423
|
-
status: "success",
|
|
1424
|
-
title: "Workflow started",
|
|
1425
|
-
description: "Document is now \"".concat(states[0].title, "\"")
|
|
1426
|
-
});
|
|
1427
|
-
setBeginning(false);
|
|
1428
|
-
setComplete(true);
|
|
1429
|
-
});
|
|
1430
|
-
}, [id, states, client, toast]);
|
|
1431
|
-
if (!draft || complete || data.metadata) {
|
|
1432
|
-
return null;
|
|
1433
|
-
}
|
|
1434
|
-
return {
|
|
1435
|
-
icon: SplitVerticalIcon,
|
|
1436
|
-
type: "dialog",
|
|
1437
|
-
disabled: (data == null ? void 0 : data.metadata) || loading || error || beginning || complete,
|
|
1438
|
-
label: beginning ? "Beginning..." : "Begin Workflow",
|
|
1439
|
-
onHandle: () => {
|
|
1440
|
-
handle();
|
|
1441
|
-
}
|
|
1442
|
-
};
|
|
1443
934
|
}
|
|
1444
|
-
function
|
|
935
|
+
function DocumentCard(props) {
|
|
1445
936
|
var _a;
|
|
1446
937
|
const {
|
|
1447
|
-
|
|
938
|
+
isDragDisabled,
|
|
939
|
+
userRoleCanDrop,
|
|
940
|
+
isDragging,
|
|
941
|
+
item,
|
|
942
|
+
states,
|
|
943
|
+
toggleInvalidDocumentId,
|
|
944
|
+
userList
|
|
1448
945
|
} = props;
|
|
1449
946
|
const {
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
const
|
|
1455
|
-
|
|
947
|
+
assignees = [],
|
|
948
|
+
documentId
|
|
949
|
+
} = (_a = item._metadata) != null ? _a : {};
|
|
950
|
+
const schema = useSchema();
|
|
951
|
+
const isDarkMode = useTheme().sanity.color.dark;
|
|
952
|
+
const defaultCardTone = isDarkMode ? "transparent" : "default";
|
|
953
|
+
const {
|
|
954
|
+
validation = [],
|
|
955
|
+
isValidating
|
|
956
|
+
} = useValidationStatus(documentId != null ? documentId : "", item._type);
|
|
957
|
+
const cardTone = useMemo(() => {
|
|
958
|
+
let tone = defaultCardTone;
|
|
959
|
+
if (!userRoleCanDrop) return isDarkMode ? "default" : "transparent";
|
|
960
|
+
if (!documentId) return tone;
|
|
961
|
+
if (isDragging) tone = "positive";
|
|
962
|
+
if (!isValidating && validation.length > 0) {
|
|
963
|
+
if (validation.some(v => v.level === "error")) {
|
|
964
|
+
tone = "critical";
|
|
965
|
+
} else {
|
|
966
|
+
tone = "caution";
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
return tone;
|
|
970
|
+
}, [isDarkMode, userRoleCanDrop, defaultCardTone, documentId, isDragging, validation, isValidating]);
|
|
971
|
+
useEffect(() => {
|
|
972
|
+
if (!isValidating && validation.length > 0) {
|
|
973
|
+
if (validation.some(v => v.level === "error")) {
|
|
974
|
+
toggleInvalidDocumentId(documentId, "ADD");
|
|
975
|
+
} else {
|
|
976
|
+
toggleInvalidDocumentId(documentId, "REMOVE");
|
|
977
|
+
}
|
|
978
|
+
} else {
|
|
979
|
+
toggleInvalidDocumentId(documentId, "REMOVE");
|
|
980
|
+
}
|
|
981
|
+
}, [documentId, isValidating, toggleInvalidDocumentId, validation]);
|
|
982
|
+
const hasError = useMemo(() => isValidating ? false : validation.some(v => v.level === "error"), [isValidating, validation]);
|
|
983
|
+
const isLastState = useMemo(() => {
|
|
984
|
+
var _a2;
|
|
985
|
+
return states[states.length - 1].id === ((_a2 = item._metadata) == null ? void 0 : _a2.state);
|
|
986
|
+
}, [states, item._metadata.state]);
|
|
987
|
+
return /* @__PURE__ */jsx(Box, {
|
|
988
|
+
paddingBottom: 3,
|
|
989
|
+
paddingX: 3,
|
|
990
|
+
children: /* @__PURE__ */jsx(Card, {
|
|
991
|
+
radius: 2,
|
|
992
|
+
shadow: isDragging ? 3 : 1,
|
|
993
|
+
tone: cardTone,
|
|
994
|
+
children: /* @__PURE__ */jsxs(Stack, {
|
|
995
|
+
children: [/* @__PURE__ */jsx(Card, {
|
|
996
|
+
borderBottom: true,
|
|
997
|
+
radius: 2,
|
|
998
|
+
padding: 3,
|
|
999
|
+
paddingLeft: 2,
|
|
1000
|
+
tone: cardTone,
|
|
1001
|
+
style: {
|
|
1002
|
+
pointerEvents: "none"
|
|
1003
|
+
},
|
|
1004
|
+
children: /* @__PURE__ */jsxs(Flex, {
|
|
1005
|
+
align: "center",
|
|
1006
|
+
justify: "space-between",
|
|
1007
|
+
gap: 1,
|
|
1008
|
+
children: [/* @__PURE__ */jsx(Box, {
|
|
1009
|
+
flex: 1,
|
|
1010
|
+
children: /* @__PURE__ */jsx(Preview, {
|
|
1011
|
+
layout: "default",
|
|
1012
|
+
value: item,
|
|
1013
|
+
schemaType: schema.get(item._type)
|
|
1014
|
+
})
|
|
1015
|
+
}), /* @__PURE__ */jsx(Box, {
|
|
1016
|
+
style: {
|
|
1017
|
+
flexShrink: 0
|
|
1018
|
+
},
|
|
1019
|
+
children: hasError || isDragDisabled ? null : /* @__PURE__ */jsx(DragHandleIcon, {})
|
|
1020
|
+
})]
|
|
1021
|
+
})
|
|
1022
|
+
}), /* @__PURE__ */jsx(Card, {
|
|
1023
|
+
padding: 2,
|
|
1024
|
+
radius: 2,
|
|
1025
|
+
tone: "inherit",
|
|
1026
|
+
children: /* @__PURE__ */jsxs(Flex, {
|
|
1027
|
+
align: "center",
|
|
1028
|
+
justify: "space-between",
|
|
1029
|
+
gap: 3,
|
|
1030
|
+
children: [/* @__PURE__ */jsx(Box, {
|
|
1031
|
+
flex: 1,
|
|
1032
|
+
children: documentId && /* @__PURE__ */jsx(UserDisplay, {
|
|
1033
|
+
userList,
|
|
1034
|
+
assignees,
|
|
1035
|
+
documentId,
|
|
1036
|
+
disabled: !userRoleCanDrop
|
|
1037
|
+
})
|
|
1038
|
+
}), validation.length > 0 ? /* @__PURE__ */jsx(ValidationStatus, {
|
|
1039
|
+
validation
|
|
1040
|
+
}) : null, /* @__PURE__ */jsx(DraftStatus, {
|
|
1041
|
+
document: item
|
|
1042
|
+
}), /* @__PURE__ */jsx(PublishedStatus, {
|
|
1043
|
+
document: item
|
|
1044
|
+
}), /* @__PURE__ */jsx(EditButton, {
|
|
1045
|
+
id: item._id,
|
|
1046
|
+
type: item._type,
|
|
1047
|
+
disabled: !userRoleCanDrop
|
|
1048
|
+
}), isLastState ? /* @__PURE__ */jsx(CompleteButton, {
|
|
1049
|
+
documentId,
|
|
1050
|
+
disabled: !userRoleCanDrop
|
|
1051
|
+
}) : null]
|
|
1052
|
+
})
|
|
1053
|
+
})]
|
|
1054
|
+
})
|
|
1055
|
+
})
|
|
1456
1056
|
});
|
|
1457
|
-
if (error) {
|
|
1458
|
-
console.error(error);
|
|
1459
|
-
}
|
|
1460
|
-
const handle = useCallback(() => {
|
|
1461
|
-
client.delete("workflow-metadata.".concat(id));
|
|
1462
|
-
}, [id, client]);
|
|
1463
|
-
const isLastState = ((_a = data == null ? void 0 : data.state) == null ? void 0 : _a.id) === states[states.length - 1].id;
|
|
1464
|
-
if (!data.metadata) {
|
|
1465
|
-
return null;
|
|
1466
|
-
}
|
|
1467
|
-
return {
|
|
1468
|
-
icon: CheckmarkIcon,
|
|
1469
|
-
type: "dialog",
|
|
1470
|
-
disabled: loading || error || !isLastState,
|
|
1471
|
-
label: "Complete Workflow",
|
|
1472
|
-
title: isLastState ? "Removes the document from the Workflow process" : "Cannot remove from workflow until in the last state",
|
|
1473
|
-
onHandle: () => {
|
|
1474
|
-
handle();
|
|
1475
|
-
},
|
|
1476
|
-
color: "positive"
|
|
1477
|
-
};
|
|
1478
1057
|
}
|
|
1479
|
-
function
|
|
1480
|
-
var _a;
|
|
1481
|
-
const {
|
|
1482
|
-
data,
|
|
1483
|
-
loading,
|
|
1484
|
-
error
|
|
1485
|
-
} = useWorkflowMetadata(documentId, states);
|
|
1058
|
+
function DocumentList(props) {
|
|
1486
1059
|
const {
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1060
|
+
data = [],
|
|
1061
|
+
invalidDocumentIds,
|
|
1062
|
+
selectedSchemaTypes,
|
|
1063
|
+
selectedUserIds,
|
|
1064
|
+
state,
|
|
1065
|
+
states,
|
|
1066
|
+
toggleInvalidDocumentId,
|
|
1067
|
+
user,
|
|
1068
|
+
userList,
|
|
1069
|
+
userRoleCanDrop
|
|
1070
|
+
} = props;
|
|
1071
|
+
const dataFiltered = useMemo(() => {
|
|
1072
|
+
return data.length ? filterItemsAndSort(data, state.id, selectedUserIds, selectedSchemaTypes) : [];
|
|
1073
|
+
}, [data, selectedSchemaTypes, selectedUserIds, state.id]);
|
|
1074
|
+
const parentRef = useRef(null);
|
|
1075
|
+
const rowVirtualizer = useVirtualizer({
|
|
1076
|
+
count: data.length,
|
|
1077
|
+
getScrollElement: () => parentRef.current,
|
|
1078
|
+
getItemKey: index => {
|
|
1079
|
+
var _a, _b, _c;
|
|
1080
|
+
return (_c = (_b = (_a = dataFiltered[index]) == null ? void 0 : _a._metadata) == null ? void 0 : _b.documentId) != null ? _c : index;
|
|
1081
|
+
},
|
|
1082
|
+
estimateSize: () => 113,
|
|
1083
|
+
overscan: 5
|
|
1491
1084
|
});
|
|
1492
|
-
if (
|
|
1493
|
-
if (error) {
|
|
1494
|
-
console.error(error);
|
|
1495
|
-
}
|
|
1085
|
+
if (!data.length) {
|
|
1496
1086
|
return null;
|
|
1497
1087
|
}
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1088
|
+
return /* @__PURE__ */jsx("div", {
|
|
1089
|
+
ref: parentRef,
|
|
1090
|
+
style: {
|
|
1091
|
+
height: "100%",
|
|
1092
|
+
overflow: "auto",
|
|
1093
|
+
paddingTop: 1,
|
|
1094
|
+
// Smooths scrollbar behaviour
|
|
1095
|
+
overflowAnchor: "none",
|
|
1096
|
+
scrollBehavior: "auto"
|
|
1097
|
+
},
|
|
1098
|
+
children: rowVirtualizer.getVirtualItems().map(virtualItem => {
|
|
1099
|
+
var _a;
|
|
1100
|
+
const item = dataFiltered[virtualItem.index];
|
|
1101
|
+
const {
|
|
1102
|
+
documentId,
|
|
1103
|
+
assignees
|
|
1104
|
+
} = (_a = item == null ? void 0 : item._metadata) != null ? _a : {};
|
|
1105
|
+
if (!documentId) {
|
|
1106
|
+
return null;
|
|
1107
|
+
}
|
|
1108
|
+
const isInvalid = invalidDocumentIds.includes(documentId);
|
|
1109
|
+
const meInAssignees = (user == null ? void 0 : user.id) ? assignees == null ? void 0 : assignees.includes(user.id) : false;
|
|
1110
|
+
const isDragDisabled = !userRoleCanDrop || isInvalid || !(state.requireAssignment ? state.requireAssignment && meInAssignees : true);
|
|
1111
|
+
return /* @__PURE__ */jsx(Draggable, {
|
|
1112
|
+
draggableId: documentId,
|
|
1113
|
+
index: virtualItem.index,
|
|
1114
|
+
isDragDisabled,
|
|
1115
|
+
children: (draggableProvided, draggableSnapshot) => /* @__PURE__ */jsx("div", {
|
|
1116
|
+
ref: draggableProvided.innerRef,
|
|
1117
|
+
...draggableProvided.draggableProps,
|
|
1118
|
+
...draggableProvided.dragHandleProps,
|
|
1119
|
+
children: /* @__PURE__ */jsx(DocumentCard, {
|
|
1120
|
+
userRoleCanDrop,
|
|
1121
|
+
isDragDisabled,
|
|
1122
|
+
isDragging: draggableSnapshot.isDragging,
|
|
1123
|
+
item,
|
|
1124
|
+
toggleInvalidDocumentId,
|
|
1125
|
+
userList,
|
|
1126
|
+
states
|
|
1127
|
+
})
|
|
1128
|
+
})
|
|
1129
|
+
}, documentId);
|
|
1130
|
+
})
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
function Filters(props) {
|
|
1503
1134
|
const {
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
}
|
|
1518
|
-
return {
|
|
1519
|
-
label,
|
|
1520
|
-
title,
|
|
1521
|
-
color: "primary"
|
|
1522
|
-
};
|
|
1523
|
-
}
|
|
1524
|
-
function StateBadge(states, documentId) {
|
|
1525
|
-
const {
|
|
1526
|
-
data,
|
|
1527
|
-
loading,
|
|
1528
|
-
error
|
|
1529
|
-
} = useWorkflowMetadata(documentId, states);
|
|
1530
|
-
const {
|
|
1531
|
-
state
|
|
1532
|
-
} = data;
|
|
1533
|
-
if (loading || error) {
|
|
1534
|
-
if (error) {
|
|
1535
|
-
console.error(error);
|
|
1135
|
+
uniqueAssignedUsers = [],
|
|
1136
|
+
selectedUserIds,
|
|
1137
|
+
schemaTypes,
|
|
1138
|
+
selectedSchemaTypes,
|
|
1139
|
+
toggleSelectedUser,
|
|
1140
|
+
resetSelectedUsers,
|
|
1141
|
+
toggleSelectedSchemaType
|
|
1142
|
+
} = props;
|
|
1143
|
+
const currentUser = useCurrentUser();
|
|
1144
|
+
const schema = useSchema();
|
|
1145
|
+
const onAdd = useCallback(id => {
|
|
1146
|
+
if (!selectedUserIds.includes(id)) {
|
|
1147
|
+
toggleSelectedUser(id);
|
|
1536
1148
|
}
|
|
1149
|
+
}, [selectedUserIds, toggleSelectedUser]);
|
|
1150
|
+
const onRemove = useCallback(id => {
|
|
1151
|
+
if (selectedUserIds.includes(id)) {
|
|
1152
|
+
toggleSelectedUser(id);
|
|
1153
|
+
}
|
|
1154
|
+
}, [selectedUserIds, toggleSelectedUser]);
|
|
1155
|
+
const onClear = useCallback(() => {
|
|
1156
|
+
resetSelectedUsers();
|
|
1157
|
+
}, [resetSelectedUsers]);
|
|
1158
|
+
if (uniqueAssignedUsers.length === 0 && schemaTypes.length < 2) {
|
|
1537
1159
|
return null;
|
|
1538
1160
|
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1161
|
+
const meInUniqueAssignees = (currentUser == null ? void 0 : currentUser.id) && uniqueAssignedUsers.find(u => u.id === currentUser.id);
|
|
1162
|
+
const uniqueAssigneesNotMe = uniqueAssignedUsers.filter(u => u.id !== (currentUser == null ? void 0 : currentUser.id));
|
|
1163
|
+
return /* @__PURE__ */jsx(Card, {
|
|
1164
|
+
tone: "primary",
|
|
1165
|
+
padding: 2,
|
|
1166
|
+
borderBottom: true,
|
|
1167
|
+
style: {
|
|
1168
|
+
overflowX: "hidden"
|
|
1169
|
+
},
|
|
1170
|
+
children: /* @__PURE__ */jsxs(Flex, {
|
|
1171
|
+
align: "center",
|
|
1172
|
+
children: [/* @__PURE__ */jsx(Flex, {
|
|
1173
|
+
align: "center",
|
|
1174
|
+
gap: 1,
|
|
1175
|
+
flex: 1,
|
|
1176
|
+
children: uniqueAssignedUsers.length > 5 ? /* @__PURE__ */jsx(Card, {
|
|
1177
|
+
tone: "default",
|
|
1178
|
+
children: /* @__PURE__ */jsx(MenuButton, {
|
|
1179
|
+
button: /* @__PURE__ */jsx(Button, {
|
|
1180
|
+
text: "Filter Assignees",
|
|
1181
|
+
tone: "primary",
|
|
1182
|
+
icon: UserIcon
|
|
1183
|
+
}),
|
|
1184
|
+
id: "user-filters",
|
|
1185
|
+
menu: /* @__PURE__ */jsx(Menu, {
|
|
1186
|
+
children: /* @__PURE__ */jsx(UserSelectMenu, {
|
|
1187
|
+
value: selectedUserIds,
|
|
1188
|
+
userList: uniqueAssignedUsers,
|
|
1189
|
+
onAdd,
|
|
1190
|
+
onRemove,
|
|
1191
|
+
onClear,
|
|
1192
|
+
labels: {
|
|
1193
|
+
addMe: "Filter mine",
|
|
1194
|
+
removeMe: "Clear mine",
|
|
1195
|
+
clear: "Clear filters"
|
|
1196
|
+
}
|
|
1197
|
+
})
|
|
1198
|
+
}),
|
|
1199
|
+
popover: {
|
|
1200
|
+
portal: true
|
|
1201
|
+
}
|
|
1202
|
+
})
|
|
1203
|
+
}) : /* @__PURE__ */jsxs(Fragment, {
|
|
1204
|
+
children: [meInUniqueAssignees ? /* @__PURE__ */jsxs(Fragment, {
|
|
1205
|
+
children: [/* @__PURE__ */jsx(Button, {
|
|
1206
|
+
padding: 0,
|
|
1207
|
+
mode: selectedUserIds.includes(currentUser.id) ? "default" : "bleed",
|
|
1208
|
+
onClick: () => toggleSelectedUser(currentUser.id),
|
|
1209
|
+
children: /* @__PURE__ */jsx(Flex, {
|
|
1210
|
+
padding: 1,
|
|
1211
|
+
align: "center",
|
|
1212
|
+
justify: "center",
|
|
1213
|
+
children: /* @__PURE__ */jsx(UserAvatar, {
|
|
1214
|
+
user: currentUser.id,
|
|
1215
|
+
size: 1,
|
|
1216
|
+
withTooltip: true
|
|
1217
|
+
})
|
|
1218
|
+
})
|
|
1219
|
+
}), /* @__PURE__ */jsx(Card, {
|
|
1220
|
+
borderRight: true,
|
|
1221
|
+
style: {
|
|
1222
|
+
height: 30
|
|
1223
|
+
},
|
|
1224
|
+
tone: "inherit"
|
|
1225
|
+
})]
|
|
1226
|
+
}) : null, uniqueAssigneesNotMe.map(user => /* @__PURE__ */jsx(Button, {
|
|
1227
|
+
padding: 0,
|
|
1228
|
+
mode: selectedUserIds.includes(user.id) ? "default" : "bleed",
|
|
1229
|
+
onClick: () => toggleSelectedUser(user.id),
|
|
1230
|
+
children: /* @__PURE__ */jsx(Flex, {
|
|
1231
|
+
padding: 1,
|
|
1232
|
+
align: "center",
|
|
1233
|
+
justify: "center",
|
|
1234
|
+
children: /* @__PURE__ */jsx(UserAvatar, {
|
|
1235
|
+
user,
|
|
1236
|
+
size: 1,
|
|
1237
|
+
withTooltip: true
|
|
1238
|
+
})
|
|
1239
|
+
})
|
|
1240
|
+
}, user.id)), selectedUserIds.length > 0 ? /* @__PURE__ */jsx(Button, {
|
|
1241
|
+
text: "Clear",
|
|
1242
|
+
onClick: resetSelectedUsers,
|
|
1243
|
+
mode: "ghost",
|
|
1244
|
+
icon: ResetIcon
|
|
1245
|
+
}) : null]
|
|
1246
|
+
})
|
|
1247
|
+
}), schemaTypes.length > 0 ? /* @__PURE__ */jsx(Flex, {
|
|
1248
|
+
align: "center",
|
|
1249
|
+
gap: 1,
|
|
1250
|
+
children: schemaTypes.map(typeName => {
|
|
1251
|
+
var _a, _b;
|
|
1252
|
+
const schemaType = schema.get(typeName);
|
|
1253
|
+
if (!schemaType) {
|
|
1254
|
+
return null;
|
|
1255
|
+
}
|
|
1256
|
+
return /* @__PURE__ */jsx(Button, {
|
|
1257
|
+
text: (_a = schemaType == null ? void 0 : schemaType.title) != null ? _a : typeName,
|
|
1258
|
+
icon: (_b = schemaType == null ? void 0 : schemaType.icon) != null ? _b : void 0,
|
|
1259
|
+
mode: selectedSchemaTypes.includes(typeName) ? "default" : "ghost",
|
|
1260
|
+
onClick: () => toggleSelectedSchemaType(typeName)
|
|
1261
|
+
}, typeName);
|
|
1262
|
+
})
|
|
1263
|
+
}) : null]
|
|
1264
|
+
})
|
|
1265
|
+
});
|
|
1547
1266
|
}
|
|
1548
|
-
function
|
|
1549
|
-
var _a, _b, _c, _d;
|
|
1267
|
+
function Status(props) {
|
|
1550
1268
|
const {
|
|
1551
|
-
|
|
1552
|
-
|
|
1269
|
+
text,
|
|
1270
|
+
icon
|
|
1553
1271
|
} = props;
|
|
1272
|
+
const Icon = icon;
|
|
1273
|
+
return /* @__PURE__ */jsx(Tooltip, {
|
|
1274
|
+
portal: true,
|
|
1275
|
+
content: /* @__PURE__ */jsx(Box, {
|
|
1276
|
+
padding: 2,
|
|
1277
|
+
children: /* @__PURE__ */jsx(Text, {
|
|
1278
|
+
size: 1,
|
|
1279
|
+
children: text
|
|
1280
|
+
})
|
|
1281
|
+
}),
|
|
1282
|
+
children: /* @__PURE__ */jsx(Text, {
|
|
1283
|
+
size: 1,
|
|
1284
|
+
children: /* @__PURE__ */jsx(Icon, {})
|
|
1285
|
+
})
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
const StyledStickyCard = styled(Card)(() => css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n position: sticky;\n top: 0;\n z-index: 1;\n "]))));
|
|
1289
|
+
function StateTitle(props) {
|
|
1554
1290
|
const {
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1291
|
+
state,
|
|
1292
|
+
requireAssignment,
|
|
1293
|
+
userRoleCanDrop,
|
|
1294
|
+
isDropDisabled,
|
|
1295
|
+
draggingFrom
|
|
1296
|
+
} = props;
|
|
1297
|
+
let tone = "default";
|
|
1298
|
+
const isSource = draggingFrom === state.id;
|
|
1299
|
+
if (draggingFrom) {
|
|
1300
|
+
tone = isDropDisabled || isSource ? "default" : "positive";
|
|
1301
|
+
}
|
|
1302
|
+
return /* @__PURE__ */jsx(StyledStickyCard, {
|
|
1303
|
+
paddingY: 4,
|
|
1304
|
+
padding: 3,
|
|
1305
|
+
tone: "inherit",
|
|
1306
|
+
children: /* @__PURE__ */jsxs(Flex, {
|
|
1307
|
+
gap: 3,
|
|
1308
|
+
align: "center",
|
|
1309
|
+
children: [/* @__PURE__ */jsx(Badge, {
|
|
1310
|
+
mode: draggingFrom && !isDropDisabled || isSource ? "default" : "outline",
|
|
1311
|
+
tone,
|
|
1312
|
+
muted: !userRoleCanDrop || isDropDisabled,
|
|
1313
|
+
children: state.title
|
|
1314
|
+
}), userRoleCanDrop ? null : /* @__PURE__ */jsx(Status, {
|
|
1315
|
+
text: "You do not have permissions to move documents to this State",
|
|
1316
|
+
icon: InfoOutlineIcon
|
|
1317
|
+
}), requireAssignment ? /* @__PURE__ */jsx(Status, {
|
|
1318
|
+
text: "You must be assigned to the document to move documents to this State",
|
|
1319
|
+
icon: UserIcon
|
|
1320
|
+
}) : null]
|
|
1321
|
+
})
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
const StyledFloatingCard = styled(Card)(() => css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n position: fixed;\n bottom: 0;\n left: 0;\n z-index: 1000;\n "]))));
|
|
1325
|
+
function FloatingCard(_ref3) {
|
|
1326
|
+
let {
|
|
1327
|
+
children
|
|
1328
|
+
} = _ref3;
|
|
1329
|
+
const childrenHaveValues = Array.isArray(children) ? children.some(Boolean) : Boolean(children);
|
|
1330
|
+
return /* @__PURE__ */jsx(AnimatePresence, {
|
|
1331
|
+
children: childrenHaveValues ? /* @__PURE__ */jsx(motion.div, {
|
|
1332
|
+
initial: {
|
|
1333
|
+
opacity: 0
|
|
1334
|
+
},
|
|
1335
|
+
animate: {
|
|
1336
|
+
opacity: 1
|
|
1337
|
+
},
|
|
1338
|
+
exit: {
|
|
1339
|
+
opacity: 0
|
|
1340
|
+
},
|
|
1341
|
+
children: /* @__PURE__ */jsx(StyledFloatingCard, {
|
|
1342
|
+
shadow: 3,
|
|
1343
|
+
padding: 3,
|
|
1344
|
+
margin: 3,
|
|
1345
|
+
radius: 3,
|
|
1346
|
+
children: /* @__PURE__ */jsx(Grid, {
|
|
1347
|
+
gap: 2,
|
|
1348
|
+
children
|
|
1349
|
+
})
|
|
1350
|
+
})
|
|
1351
|
+
}, "floater") : null
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
function Validators(_ref4) {
|
|
1355
|
+
let {
|
|
1356
|
+
data,
|
|
1357
|
+
userList,
|
|
1358
|
+
states
|
|
1359
|
+
} = _ref4;
|
|
1560
1360
|
const client = useClient({
|
|
1561
1361
|
apiVersion: API_VERSION
|
|
1562
1362
|
});
|
|
1563
|
-
const toast = useToast();
|
|
1564
|
-
const
|
|
1363
|
+
const toast = useToast();
|
|
1364
|
+
const documentsWithoutValidMetadataIds = (data == null ? void 0 : data.length) ? data.reduce((acc, cur) => {
|
|
1365
|
+
var _a;
|
|
1366
|
+
const {
|
|
1367
|
+
documentId,
|
|
1368
|
+
state
|
|
1369
|
+
} = (_a = cur._metadata) != null ? _a : {};
|
|
1370
|
+
const stateExists = states.find(s => s.id === state);
|
|
1371
|
+
return !stateExists && documentId ? [...acc, documentId] : acc;
|
|
1372
|
+
}, []) : [];
|
|
1373
|
+
const documentsWithInvalidUserIds = (data == null ? void 0 : data.length) ? data.reduce((acc, cur) => {
|
|
1374
|
+
var _a;
|
|
1375
|
+
const {
|
|
1376
|
+
documentId,
|
|
1377
|
+
assignees
|
|
1378
|
+
} = (_a = cur._metadata) != null ? _a : {};
|
|
1379
|
+
const allAssigneesExist = (assignees == null ? void 0 : assignees.length) ? assignees == null ? void 0 : assignees.every(a => userList.find(u => u.id === a)) : true;
|
|
1380
|
+
return !allAssigneesExist && documentId ? [...acc, documentId] : acc;
|
|
1381
|
+
}, []) : [];
|
|
1382
|
+
const documentsWithoutOrderIds = (data == null ? void 0 : data.length) ? data.reduce((acc, cur) => {
|
|
1383
|
+
var _a;
|
|
1384
|
+
const {
|
|
1385
|
+
documentId,
|
|
1386
|
+
orderRank
|
|
1387
|
+
} = (_a = cur._metadata) != null ? _a : {};
|
|
1388
|
+
return !orderRank && documentId ? [...acc, documentId] : acc;
|
|
1389
|
+
}, []) : [];
|
|
1390
|
+
const correctDocuments = React.useCallback(async ids => {
|
|
1391
|
+
toast.push({
|
|
1392
|
+
title: "Correcting...",
|
|
1393
|
+
status: "info"
|
|
1394
|
+
});
|
|
1395
|
+
const tx = ids.reduce((item, documentId) => {
|
|
1396
|
+
return item.patch("workflow-metadata.".concat(documentId), {
|
|
1397
|
+
set: {
|
|
1398
|
+
state: states[0].id
|
|
1399
|
+
}
|
|
1400
|
+
});
|
|
1401
|
+
}, client.transaction());
|
|
1402
|
+
await tx.commit();
|
|
1403
|
+
toast.push({
|
|
1404
|
+
title: "Corrected ".concat(ids.length === 1 ? "1 Document" : "".concat(ids.length, " Documents")),
|
|
1405
|
+
status: "success"
|
|
1406
|
+
});
|
|
1407
|
+
}, [client, states, toast]);
|
|
1408
|
+
const removeUsersFromDocuments = React.useCallback(async ids => {
|
|
1409
|
+
toast.push({
|
|
1410
|
+
title: "Removing users...",
|
|
1411
|
+
status: "info"
|
|
1412
|
+
});
|
|
1413
|
+
const tx = ids.reduce((item, documentId) => {
|
|
1414
|
+
var _a, _b;
|
|
1415
|
+
const {
|
|
1416
|
+
assignees
|
|
1417
|
+
} = (_b = (_a = data.find(d => d._id === documentId)) == null ? void 0 : _a._metadata) != null ? _b : {};
|
|
1418
|
+
const validAssignees = (assignees == null ? void 0 : assignees.length) ?
|
|
1419
|
+
// eslint-disable-next-line max-nested-callbacks
|
|
1420
|
+
assignees.filter(a => {
|
|
1421
|
+
var _a2;
|
|
1422
|
+
return (_a2 = userList.find(u => u.id === a)) == null ? void 0 : _a2.id;
|
|
1423
|
+
}) : [];
|
|
1424
|
+
return item.patch("workflow-metadata.".concat(documentId), {
|
|
1425
|
+
set: {
|
|
1426
|
+
assignees: validAssignees
|
|
1427
|
+
}
|
|
1428
|
+
});
|
|
1429
|
+
}, client.transaction());
|
|
1430
|
+
await tx.commit();
|
|
1431
|
+
toast.push({
|
|
1432
|
+
title: "Corrected ".concat(ids.length === 1 ? "1 Document" : "".concat(ids.length, " Documents")),
|
|
1433
|
+
status: "success"
|
|
1434
|
+
});
|
|
1435
|
+
}, [client, data, toast, userList]);
|
|
1436
|
+
const addOrderToDocuments = React.useCallback(async ids => {
|
|
1437
|
+
var _a, _b;
|
|
1438
|
+
toast.push({
|
|
1439
|
+
title: "Adding ordering...",
|
|
1440
|
+
status: "info"
|
|
1441
|
+
});
|
|
1442
|
+
const firstOrder = (_b = (_a = data[0]) == null ? void 0 : _a._metadata) == null ? void 0 : _b.orderRank;
|
|
1443
|
+
let newLexo = firstOrder && data.length !== ids.length ? LexoRank.parse(firstOrder) : LexoRank.min();
|
|
1444
|
+
const tx = client.transaction();
|
|
1445
|
+
for (let index = 0; index < ids.length; index += 1) {
|
|
1446
|
+
newLexo = newLexo.genNext().genNext();
|
|
1447
|
+
tx.patch("workflow-metadata.".concat(ids[index]), {
|
|
1448
|
+
set: {
|
|
1449
|
+
orderRank: newLexo.toString()
|
|
1450
|
+
}
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
await tx.commit();
|
|
1454
|
+
toast.push({
|
|
1455
|
+
title: "Added order to ".concat(ids.length === 1 ? "1 Document" : "".concat(ids.length, " Documents")),
|
|
1456
|
+
status: "success"
|
|
1457
|
+
});
|
|
1458
|
+
}, [data, client, toast]);
|
|
1459
|
+
const orphanedMetadataDocumentIds = React.useMemo(() => {
|
|
1460
|
+
return data.length ? data.filter(doc => !(doc == null ? void 0 : doc._id)).map(doc => doc._metadata.documentId) : [];
|
|
1461
|
+
}, [data]);
|
|
1462
|
+
const handleOrphans = React.useCallback(() => {
|
|
1463
|
+
toast.push({
|
|
1464
|
+
title: "Removing orphaned metadata...",
|
|
1465
|
+
status: "info"
|
|
1466
|
+
});
|
|
1467
|
+
const tx = client.transaction();
|
|
1468
|
+
orphanedMetadataDocumentIds.forEach(id => {
|
|
1469
|
+
tx.delete("workflow-metadata.".concat(id));
|
|
1470
|
+
});
|
|
1471
|
+
tx.commit();
|
|
1472
|
+
toast.push({
|
|
1473
|
+
title: "Removed ".concat(orphanedMetadataDocumentIds.length, " orphaned metadata documents"),
|
|
1474
|
+
status: "success"
|
|
1475
|
+
});
|
|
1476
|
+
}, [client, orphanedMetadataDocumentIds, toast]);
|
|
1477
|
+
return /* @__PURE__ */jsxs(FloatingCard, {
|
|
1478
|
+
children: [documentsWithoutValidMetadataIds.length > 0 ? /* @__PURE__ */jsx(Button, {
|
|
1479
|
+
tone: "caution",
|
|
1480
|
+
onClick: () => correctDocuments(documentsWithoutValidMetadataIds),
|
|
1481
|
+
text: documentsWithoutValidMetadataIds.length === 1 ? "Correct 1 Document State" : "Correct ".concat(documentsWithoutValidMetadataIds.length, " Document States")
|
|
1482
|
+
}) : null, documentsWithInvalidUserIds.length > 0 ? /* @__PURE__ */jsx(Button, {
|
|
1483
|
+
tone: "caution",
|
|
1484
|
+
onClick: () => removeUsersFromDocuments(documentsWithInvalidUserIds),
|
|
1485
|
+
text: documentsWithInvalidUserIds.length === 1 ? "Remove Invalid Users from 1 Document" : "Remove Invalid Users from ".concat(documentsWithInvalidUserIds.length, " Documents")
|
|
1486
|
+
}) : null, documentsWithoutOrderIds.length > 0 ? /* @__PURE__ */jsx(Button, {
|
|
1487
|
+
tone: "caution",
|
|
1488
|
+
onClick: () => addOrderToDocuments(documentsWithoutOrderIds),
|
|
1489
|
+
text: documentsWithoutOrderIds.length === 1 ? "Set Order for 1 Document" : "Set Order for ".concat(documentsWithoutOrderIds.length, " Documents")
|
|
1490
|
+
}) : null, orphanedMetadataDocumentIds.length > 0 ? /* @__PURE__ */jsx(Button, {
|
|
1491
|
+
text: "Cleanup orphaned metadata",
|
|
1492
|
+
onClick: handleOrphans,
|
|
1493
|
+
tone: "caution"
|
|
1494
|
+
}) : null]
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
function WorkflowTool(props) {
|
|
1498
|
+
var _a, _b, _c;
|
|
1499
|
+
const {
|
|
1500
|
+
schemaTypes = [],
|
|
1501
|
+
states = []
|
|
1502
|
+
} = (_b = (_a = props == null ? void 0 : props.tool) == null ? void 0 : _a.options) != null ? _b : {};
|
|
1503
|
+
const isDarkMode = useTheme().sanity.color.dark;
|
|
1504
|
+
const defaultCardTone = isDarkMode ? "default" : "transparent";
|
|
1505
|
+
const userList = useProjectUsers({
|
|
1506
|
+
apiVersion: API_VERSION
|
|
1507
|
+
});
|
|
1508
|
+
const user = useCurrentUser();
|
|
1509
|
+
const userRoleNames = ((_c = user == null ? void 0 : user.roles) == null ? void 0 : _c.length) ? user == null ? void 0 : user.roles.map(r => r.name) : [];
|
|
1510
|
+
const {
|
|
1511
|
+
workflowData,
|
|
1512
|
+
operations
|
|
1513
|
+
} = useWorkflowDocuments(schemaTypes);
|
|
1565
1514
|
const {
|
|
1566
1515
|
data,
|
|
1567
1516
|
loading,
|
|
1568
1517
|
error
|
|
1569
|
-
} =
|
|
1570
|
-
const {
|
|
1571
|
-
state: currentState
|
|
1572
|
-
} = data;
|
|
1518
|
+
} = workflowData;
|
|
1573
1519
|
const {
|
|
1574
|
-
|
|
1575
|
-
} =
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1520
|
+
move
|
|
1521
|
+
} = operations;
|
|
1522
|
+
const [undroppableStates, setUndroppableStates] = React.useState([]);
|
|
1523
|
+
const [draggingFrom, setDraggingFrom] = React.useState("");
|
|
1524
|
+
const handleDragStart = React.useCallback(start => {
|
|
1525
|
+
var _a2, _b2;
|
|
1526
|
+
const {
|
|
1527
|
+
draggableId,
|
|
1528
|
+
source
|
|
1529
|
+
} = start;
|
|
1530
|
+
const {
|
|
1531
|
+
droppableId: currentStateId
|
|
1532
|
+
} = source;
|
|
1533
|
+
setDraggingFrom(currentStateId);
|
|
1534
|
+
const document = data.find(item => {
|
|
1535
|
+
var _a3;
|
|
1536
|
+
return ((_a3 = item._metadata) == null ? void 0 : _a3.documentId) === draggableId;
|
|
1537
|
+
});
|
|
1538
|
+
const state = states.find(s => s.id === currentStateId);
|
|
1539
|
+
if (!document || !state) return;
|
|
1540
|
+
const undroppableStateIds = [];
|
|
1541
|
+
const statesThatRequireAssignmentIds = states.filter(s => s.requireAssignment).map(s => s.id);
|
|
1542
|
+
if (statesThatRequireAssignmentIds.length) {
|
|
1543
|
+
const documentAssignees = (_b2 = (_a2 = document._metadata) == null ? void 0 : _a2.assignees) != null ? _b2 : [];
|
|
1544
|
+
const userIsAssignedToDocument = (user == null ? void 0 : user.id) ? documentAssignees.includes(user.id) : false;
|
|
1545
|
+
if (!userIsAssignedToDocument) {
|
|
1546
|
+
undroppableStateIds.push(...statesThatRequireAssignmentIds);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
const statesThatCannotBeTransitionedToIds = state.transitions && state.transitions.length ? states.filter(s => {
|
|
1550
|
+
var _a3;
|
|
1551
|
+
return !((_a3 = state.transitions) == null ? void 0 : _a3.includes(s.id));
|
|
1552
|
+
}).map(s => s.id) : [];
|
|
1553
|
+
if (statesThatCannotBeTransitionedToIds.length) {
|
|
1554
|
+
undroppableStateIds.push(...statesThatCannotBeTransitionedToIds);
|
|
1555
|
+
}
|
|
1556
|
+
const undroppableExceptSelf = undroppableStateIds.filter(id => id !== currentStateId);
|
|
1557
|
+
if (undroppableExceptSelf.length) {
|
|
1558
|
+
setUndroppableStates(undroppableExceptSelf);
|
|
1559
|
+
}
|
|
1560
|
+
}, [data, states, user]);
|
|
1561
|
+
const handleDragEnd = React.useCallback(result => {
|
|
1562
|
+
var _a2, _b2, _c2, _d, _e, _f;
|
|
1563
|
+
setUndroppableStates([]);
|
|
1564
|
+
setDraggingFrom("");
|
|
1565
|
+
const {
|
|
1566
|
+
draggableId,
|
|
1567
|
+
source,
|
|
1568
|
+
destination
|
|
1569
|
+
} = result;
|
|
1570
|
+
if (
|
|
1571
|
+
// No destination?
|
|
1572
|
+
!destination ||
|
|
1573
|
+
// No change in position?
|
|
1574
|
+
destination.droppableId === source.droppableId && destination.index === source.index) {
|
|
1575
|
+
return;
|
|
1576
|
+
}
|
|
1577
|
+
const destinationStateItems = [...filterItemsAndSort(data, destination.droppableId, [], null)];
|
|
1578
|
+
let newOrder;
|
|
1579
|
+
if (!destinationStateItems.length) {
|
|
1580
|
+
newOrder = LexoRank.min().toString();
|
|
1581
|
+
} else if (destination.index === 0) {
|
|
1582
|
+
const firstItemOrderRank = (_b2 = (_a2 = [...destinationStateItems].shift()) == null ? void 0 : _a2._metadata) == null ? void 0 : _b2.orderRank;
|
|
1583
|
+
newOrder = firstItemOrderRank && typeof firstItemOrderRank === "string" ? LexoRank.parse(firstItemOrderRank).genPrev().toString() : LexoRank.min().toString();
|
|
1584
|
+
} else if (destination.index + 1 === destinationStateItems.length) {
|
|
1585
|
+
const lastItemOrderRank = (_d = (_c2 = [...destinationStateItems].pop()) == null ? void 0 : _c2._metadata) == null ? void 0 : _d.orderRank;
|
|
1586
|
+
newOrder = lastItemOrderRank && typeof lastItemOrderRank === "string" ? LexoRank.parse(lastItemOrderRank).genNext().toString() : LexoRank.min().toString();
|
|
1587
|
+
} else {
|
|
1588
|
+
const itemBefore = destinationStateItems[destination.index - 1];
|
|
1589
|
+
const itemBeforeRank = (_e = itemBefore == null ? void 0 : itemBefore._metadata) == null ? void 0 : _e.orderRank;
|
|
1590
|
+
const itemBeforeRankParsed = itemBefore._metadata.orderRank ? LexoRank.parse(itemBeforeRank) : LexoRank.min();
|
|
1591
|
+
const itemAfter = destinationStateItems[destination.index];
|
|
1592
|
+
const itemAfterRank = (_f = itemAfter == null ? void 0 : itemAfter._metadata) == null ? void 0 : _f.orderRank;
|
|
1593
|
+
const itemAfterRankParsed = itemAfter._metadata.orderRank ? LexoRank.parse(itemAfterRank) : LexoRank.max();
|
|
1594
|
+
newOrder = itemBeforeRankParsed.between(itemAfterRankParsed).toString();
|
|
1595
|
+
}
|
|
1596
|
+
move(draggableId, destination, states, newOrder);
|
|
1597
|
+
}, [data, move, states]);
|
|
1598
|
+
const uniqueAssignedUsers = React.useMemo(() => {
|
|
1599
|
+
const uniqueUserIds = data.reduce((acc, item) => {
|
|
1600
|
+
var _a2;
|
|
1601
|
+
const {
|
|
1602
|
+
assignees = []
|
|
1603
|
+
} = (_a2 = item._metadata) != null ? _a2 : {};
|
|
1604
|
+
const newAssignees = (assignees == null ? void 0 : assignees.length) ? assignees.filter(a => !acc.includes(a)) : [];
|
|
1605
|
+
return newAssignees.length ? [...acc, ...newAssignees] : acc;
|
|
1606
|
+
}, []);
|
|
1607
|
+
return userList.filter(u => uniqueUserIds.includes(u.id));
|
|
1608
|
+
}, [data, userList]);
|
|
1609
|
+
const [selectedUserIds, setSelectedUserIds] = React.useState(uniqueAssignedUsers.map(u => u.id));
|
|
1610
|
+
const toggleSelectedUser = React.useCallback(userId => {
|
|
1611
|
+
setSelectedUserIds(prev => prev.includes(userId) ? prev.filter(u => u !== userId) : [...prev, userId]);
|
|
1612
|
+
}, []);
|
|
1613
|
+
const resetSelectedUsers = React.useCallback(() => {
|
|
1614
|
+
setSelectedUserIds([]);
|
|
1615
|
+
}, []);
|
|
1616
|
+
const [selectedSchemaTypes, setSelectedSchemaTypes] = React.useState(schemaTypes);
|
|
1617
|
+
const toggleSelectedSchemaType = React.useCallback(schemaType => {
|
|
1618
|
+
setSelectedSchemaTypes(prev => prev.includes(schemaType) ? prev.filter(u => u !== schemaType) : [...prev, schemaType]);
|
|
1619
|
+
}, []);
|
|
1620
|
+
const [invalidDocumentIds, setInvalidDocumentIds] = React.useState([]);
|
|
1621
|
+
const toggleInvalidDocumentId = React.useCallback((docId, action) => {
|
|
1622
|
+
setInvalidDocumentIds(prev => action === "ADD" ? [...prev, docId] : prev.filter(id => id !== docId));
|
|
1623
|
+
}, []);
|
|
1624
|
+
if (!(states == null ? void 0 : states.length)) {
|
|
1625
|
+
return /* @__PURE__ */jsx(Container, {
|
|
1626
|
+
width: 1,
|
|
1627
|
+
padding: 5,
|
|
1628
|
+
children: /* @__PURE__ */jsx(Feedback, {
|
|
1629
|
+
tone: "caution",
|
|
1630
|
+
title: "Plugin options error",
|
|
1631
|
+
description: "No States defined in plugin config"
|
|
1632
|
+
})
|
|
1595
1633
|
});
|
|
1596
|
-
};
|
|
1597
|
-
if (!data.metadata || currentState && currentState.id === actionState.id) {
|
|
1598
|
-
return null;
|
|
1599
|
-
}
|
|
1600
|
-
const currentStateIndex = allStates.findIndex(s => s.id === (currentState == null ? void 0 : currentState.id));
|
|
1601
|
-
const actionStateIndex = allStates.findIndex(s => s.id === actionState.id);
|
|
1602
|
-
const direction = actionStateIndex > currentStateIndex ? "promote" : "demote";
|
|
1603
|
-
const DirectionIcon = direction === "promote" ? ArrowRightIcon : ArrowLeftIcon;
|
|
1604
|
-
const directionLabel = direction === "promote" ? "Promote" : "Demote";
|
|
1605
|
-
let title = "".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
|
|
1606
|
-
const userRoleCanUpdateState = ((_b = user == null ? void 0 : user.roles) == null ? void 0 : _b.length) && ((_c = actionState == null ? void 0 : actionState.roles) == null ? void 0 : _c.length) ?
|
|
1607
|
-
// If the Action state is limited to specific roles
|
|
1608
|
-
// check that the current user has one of those roles
|
|
1609
|
-
arraysContainMatchingString(user.roles.map(r => r.name), actionState.roles) :
|
|
1610
|
-
// No roles specified on the next state, so anyone can update
|
|
1611
|
-
((_d = actionState == null ? void 0 : actionState.roles) == null ? void 0 : _d.length) !== 0;
|
|
1612
|
-
if (!userRoleCanUpdateState) {
|
|
1613
|
-
title = "Your User role cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
|
|
1614
|
-
}
|
|
1615
|
-
const actionStateIsAValidTransition = (currentState == null ? void 0 : currentState.id) && currentState.transitions.length ?
|
|
1616
|
-
// If the Current State limits transitions to specific States
|
|
1617
|
-
// Check that the Action State is in Current State's transitions array
|
|
1618
|
-
currentState.transitions.includes(actionState.id) :
|
|
1619
|
-
// Otherwise this isn't a problem
|
|
1620
|
-
true;
|
|
1621
|
-
if (!actionStateIsAValidTransition) {
|
|
1622
|
-
title = "You cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\" from \"").concat(currentState == null ? void 0 : currentState.title, "\"");
|
|
1623
|
-
}
|
|
1624
|
-
const userAssignmentCanUpdateState = actionState.requireAssignment ?
|
|
1625
|
-
// If the Action State requires assigned users
|
|
1626
|
-
// Check the current user ID is in the assignees array
|
|
1627
|
-
currentUser && assignees.length && assignees.includes(currentUser.id) :
|
|
1628
|
-
// Otherwise this isn't a problem
|
|
1629
|
-
true;
|
|
1630
|
-
if (!userAssignmentCanUpdateState) {
|
|
1631
|
-
title = "You must be assigned to the document to ".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
|
|
1632
1634
|
}
|
|
1633
|
-
if (
|
|
1634
|
-
|
|
1635
|
+
if (error && !data.length) {
|
|
1636
|
+
return /* @__PURE__ */jsx(Container, {
|
|
1637
|
+
width: 1,
|
|
1638
|
+
padding: 5,
|
|
1639
|
+
children: /* @__PURE__ */jsx(Feedback, {
|
|
1640
|
+
tone: "critical",
|
|
1641
|
+
title: "Error querying for Workflow documents"
|
|
1642
|
+
})
|
|
1643
|
+
});
|
|
1635
1644
|
}
|
|
1636
|
-
return {
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1645
|
+
return /* @__PURE__ */jsxs(Flex, {
|
|
1646
|
+
direction: "column",
|
|
1647
|
+
height: "fill",
|
|
1648
|
+
overflow: "hidden",
|
|
1649
|
+
children: [/* @__PURE__ */jsx(Validators, {
|
|
1650
|
+
data,
|
|
1651
|
+
userList,
|
|
1652
|
+
states
|
|
1653
|
+
}), /* @__PURE__ */jsx(Filters, {
|
|
1654
|
+
uniqueAssignedUsers,
|
|
1655
|
+
selectedUserIds,
|
|
1656
|
+
toggleSelectedUser,
|
|
1657
|
+
resetSelectedUsers,
|
|
1658
|
+
schemaTypes,
|
|
1659
|
+
selectedSchemaTypes,
|
|
1660
|
+
toggleSelectedSchemaType
|
|
1661
|
+
}), /* @__PURE__ */jsx(DragDropContext, {
|
|
1662
|
+
onDragStart: handleDragStart,
|
|
1663
|
+
onDragEnd: handleDragEnd,
|
|
1664
|
+
children: /* @__PURE__ */jsx(Grid, {
|
|
1665
|
+
columns: states.length,
|
|
1666
|
+
height: "fill",
|
|
1667
|
+
children: states.map((state, stateIndex) => {
|
|
1668
|
+
var _a2, _b2;
|
|
1669
|
+
const userRoleCanDrop = ((_a2 = state == null ? void 0 : state.roles) == null ? void 0 : _a2.length) ? arraysContainMatchingString(state.roles, userRoleNames) : true;
|
|
1670
|
+
const isDropDisabled = !userRoleCanDrop || undroppableStates.includes(state.id);
|
|
1671
|
+
return /* @__PURE__ */jsx(Card, {
|
|
1672
|
+
borderLeft: stateIndex > 0,
|
|
1673
|
+
tone: defaultCardTone,
|
|
1674
|
+
children: /* @__PURE__ */jsxs(Flex, {
|
|
1675
|
+
direction: "column",
|
|
1676
|
+
height: "fill",
|
|
1677
|
+
children: [/* @__PURE__ */jsx(StateTitle, {
|
|
1678
|
+
state,
|
|
1679
|
+
requireAssignment: (_b2 = state.requireAssignment) != null ? _b2 : false,
|
|
1680
|
+
userRoleCanDrop,
|
|
1681
|
+
isDropDisabled,
|
|
1682
|
+
draggingFrom
|
|
1683
|
+
}), /* @__PURE__ */jsx(Box, {
|
|
1684
|
+
flex: 1,
|
|
1685
|
+
children: /* @__PURE__ */jsx(Droppable, {
|
|
1686
|
+
droppableId: state.id,
|
|
1687
|
+
isDropDisabled,
|
|
1688
|
+
mode: "virtual",
|
|
1689
|
+
renderClone: (provided, snapshot, rubric) => {
|
|
1690
|
+
const item = data.find(doc => {
|
|
1691
|
+
var _a3;
|
|
1692
|
+
return ((_a3 = doc == null ? void 0 : doc._metadata) == null ? void 0 : _a3.documentId) === rubric.draggableId;
|
|
1693
|
+
});
|
|
1694
|
+
return /* @__PURE__ */jsx("div", {
|
|
1695
|
+
...provided.draggableProps,
|
|
1696
|
+
...provided.dragHandleProps,
|
|
1697
|
+
ref: provided.innerRef,
|
|
1698
|
+
children: item ? /* @__PURE__ */jsx(DocumentCard, {
|
|
1699
|
+
isDragDisabled: false,
|
|
1700
|
+
userRoleCanDrop,
|
|
1701
|
+
isDragging: snapshot.isDragging,
|
|
1702
|
+
item,
|
|
1703
|
+
states,
|
|
1704
|
+
toggleInvalidDocumentId,
|
|
1705
|
+
userList
|
|
1706
|
+
}) : /* @__PURE__ */jsx(Feedback, {
|
|
1707
|
+
title: "Item not found",
|
|
1708
|
+
tone: "caution"
|
|
1709
|
+
})
|
|
1710
|
+
});
|
|
1711
|
+
},
|
|
1712
|
+
children: (provided, snapshot) => /* @__PURE__ */jsxs(Card, {
|
|
1713
|
+
ref: provided.innerRef,
|
|
1714
|
+
tone: snapshot.isDraggingOver ? "primary" : defaultCardTone,
|
|
1715
|
+
height: "fill",
|
|
1716
|
+
paddingTop: 1,
|
|
1717
|
+
children: [loading ? /* @__PURE__ */jsx(Flex, {
|
|
1718
|
+
padding: 5,
|
|
1719
|
+
align: "center",
|
|
1720
|
+
justify: "center",
|
|
1721
|
+
children: /* @__PURE__ */jsx(Spinner, {
|
|
1722
|
+
muted: true
|
|
1723
|
+
})
|
|
1724
|
+
}) : null, /* @__PURE__ */jsx(DocumentList, {
|
|
1725
|
+
data,
|
|
1726
|
+
invalidDocumentIds,
|
|
1727
|
+
selectedSchemaTypes,
|
|
1728
|
+
selectedUserIds,
|
|
1729
|
+
state,
|
|
1730
|
+
states,
|
|
1731
|
+
toggleInvalidDocumentId,
|
|
1732
|
+
user,
|
|
1733
|
+
userList,
|
|
1734
|
+
userRoleCanDrop
|
|
1735
|
+
})]
|
|
1736
|
+
})
|
|
1737
|
+
})
|
|
1738
|
+
})]
|
|
1739
|
+
})
|
|
1740
|
+
}, state.id);
|
|
1741
|
+
})
|
|
1742
|
+
})
|
|
1743
|
+
})]
|
|
1744
|
+
});
|
|
1643
1745
|
}
|
|
1746
|
+
const workflowTool = options => ({
|
|
1747
|
+
name: "workflow",
|
|
1748
|
+
title: "Workflow",
|
|
1749
|
+
component: WorkflowTool,
|
|
1750
|
+
icon: SplitVerticalIcon,
|
|
1751
|
+
options
|
|
1752
|
+
});
|
|
1644
1753
|
const workflow = definePlugin(function () {
|
|
1645
1754
|
let config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_CONFIG;
|
|
1646
1755
|
const {
|