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