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