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