@sanity/workflow-studio-plugin 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +71 -0
- package/dist/index.cjs +298 -189
- package/dist/index.js +301 -190
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { latestDeployedDefinitions, missingRequiredInputs, gdrRef, releaseRef, rejectedRefTypes, findOpenStageEntry, ENGINE_API_VERSION, WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE, isTodoListEntry, isTodoListItem, ActionDisabledError, ActionParamsInvalidError, errorMessage, MutationGuardDeniedError, isTerminalActivityStatus, findCurrentActivityEntry, tryParseGdr, resourceFromParsed, resolveFieldEntry, isNotesEntry, extractDocumentId, parseDefinitionSnapshot, terminalState, parentRef, gdrFromResource, instanceWatchesDocument, definitionsListGroq, definitionLookupGroq, documentActionDenials, deniedGuardLabels, deniedGuardRefs, isTerminalStage } from "@sanity/workflow-engine";
|
|
1
|
+
import { latestDeployedDefinitions, missingRequiredInputs, gdrRef, releaseRef, rejectedRefTypes, findOpenStageEntry, ENGINE_API_VERSION, WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE, isTodoListEntry, isTodoListItem, ActionDisabledError, ActionParamsInvalidError, errorMessage, MutationGuardDeniedError, isTerminalActivityStatus, findCurrentActivityEntry, tryParseGdr, resourceFromParsed, resolveFieldEntry, isNotesEntry, extractDocumentId, parseDefinitionSnapshot, terminalState, parentRef, gdrFromResource, instanceWatchesDocument, aclPathForResource, definitionsListGroq, definitionLookupGroq, documentActionDenials, deniedGuardLabels, deniedGuardRefs, isTerminalStage } from "@sanity/workflow-engine";
|
|
2
2
|
|
|
3
3
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
4
4
|
|
|
5
|
-
import { Tooltip, Box, Text, Button, Card, Flex, useClickOutsideEvent, Popover, useTheme_v2, Spinner, Avatar, TextInput, AvatarStack, Checkbox, useToast, Stack, Badge, Switch, Code,
|
|
5
|
+
import { Tooltip, Box, Text, Button, Card, Flex, useClickOutsideEvent, Popover, useTheme_v2, Spinner, Avatar, TextInput, AvatarStack, Checkbox, useToast, Stack, Badge, TextArea, Switch, Code, Autocomplete, Dialog, TabList, Tab, Select, TabPanel, MenuButton, Menu, MenuItem } from "@sanity/ui";
|
|
6
6
|
|
|
7
7
|
import { createContext, useEffect, useContext, Fragment as Fragment$1, useRef, useState, useMemo, useCallback, Component } from "react";
|
|
8
8
|
|
|
@@ -40,6 +40,8 @@ import { RemoveCircleIcon } from "@sanity/icons/RemoveCircle";
|
|
|
40
40
|
|
|
41
41
|
import { ClockIcon } from "@sanity/icons/Clock";
|
|
42
42
|
|
|
43
|
+
import { BoltIcon } from "@sanity/icons/Bolt";
|
|
44
|
+
|
|
43
45
|
import { EditIcon } from "@sanity/icons/Edit";
|
|
44
46
|
|
|
45
47
|
import { randomKey } from "@sanity/util/content";
|
|
@@ -366,7 +368,8 @@ const activityNotActiveSentence = {
|
|
|
366
368
|
"instance-completed": () => "This workflow is already complete.",
|
|
367
369
|
"mutation-guard-denied": () => "An earlier step is holding this document.",
|
|
368
370
|
"requirements-unmet": () => "This step isn't ready yet — a required condition hasn't been met.",
|
|
369
|
-
"stage-terminal": () => "This stage is finished."
|
|
371
|
+
"stage-terminal": () => "This stage is finished.",
|
|
372
|
+
"subject-permission-denied": () => "You don't have permission to change the document this step works on."
|
|
370
373
|
};
|
|
371
374
|
|
|
372
375
|
function describeDisabledReason(reason) {
|
|
@@ -878,20 +881,9 @@ function UserAvatarGroup({ids: ids}) {
|
|
|
878
881
|
});
|
|
879
882
|
}
|
|
880
883
|
|
|
881
|
-
function TodoCheckbox({
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
"aria-label": "Saving…",
|
|
885
|
-
justify: "center",
|
|
886
|
-
style: {
|
|
887
|
-
width: 17,
|
|
888
|
-
height: 17
|
|
889
|
-
},
|
|
890
|
-
children: /* @__PURE__ */ jsx(Spinner, {
|
|
891
|
-
muted: !0,
|
|
892
|
-
size: 1
|
|
893
|
-
})
|
|
894
|
-
}) : /* @__PURE__ */ jsx(Checkbox, {
|
|
884
|
+
function TodoCheckbox({checked: checked, canClick: canClick, onToggle: onToggle}) {
|
|
885
|
+
/* @__PURE__ */
|
|
886
|
+
return jsx(Checkbox, {
|
|
895
887
|
checked: checked,
|
|
896
888
|
disabled: !canClick,
|
|
897
889
|
onChange: onToggle,
|
|
@@ -1034,10 +1026,10 @@ function AssigneeControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
|
1034
1026
|
}) : chip;
|
|
1035
1027
|
}
|
|
1036
1028
|
|
|
1037
|
-
function AddItemControl({
|
|
1029
|
+
function AddItemControl({onAdd: onAdd, button: button, busy: busy}) {
|
|
1038
1030
|
const [open, setOpen] = useState(!1), [label, setLabel] = useState(""), submit = () => {
|
|
1039
1031
|
const trimmed = label.trim();
|
|
1040
|
-
trimmed
|
|
1032
|
+
!trimmed || busy || (setOpen(!1), setLabel(""), onAdd(trimmed));
|
|
1041
1033
|
};
|
|
1042
1034
|
/* @__PURE__ */
|
|
1043
1035
|
return jsx(DismissablePopover, {
|
|
@@ -1069,13 +1061,11 @@ function AddItemControl({busy: busy, onAdd: onAdd, button: button}) {
|
|
|
1069
1061
|
open: open,
|
|
1070
1062
|
placement: "bottom-start",
|
|
1071
1063
|
children: /* @__PURE__ */ jsx(Box, {
|
|
1072
|
-
onClick: () =>
|
|
1064
|
+
onClick: () => setOpen(v => !v),
|
|
1073
1065
|
style: {
|
|
1074
1066
|
display: "inline-flex"
|
|
1075
1067
|
},
|
|
1076
|
-
children:
|
|
1077
|
-
muted: !0
|
|
1078
|
-
}) : button
|
|
1068
|
+
children: button
|
|
1079
1069
|
})
|
|
1080
1070
|
});
|
|
1081
1071
|
}
|
|
@@ -1104,7 +1094,7 @@ function rowInteractivity(row) {
|
|
|
1104
1094
|
};
|
|
1105
1095
|
}
|
|
1106
1096
|
|
|
1107
|
-
function ActionItemRowView({row: row,
|
|
1097
|
+
function ActionItemRowView({row: row, showBreadcrumb: showBreadcrumb, onToggle: onToggle, onPatch: onPatch}) {
|
|
1108
1098
|
const {canClick: canClick, hint: hint} = rowInteractivity(row), editable = row.editTarget !== void 0, body = /* @__PURE__ */ jsxs(Flex, {
|
|
1109
1099
|
align: "center",
|
|
1110
1100
|
gap: 2,
|
|
@@ -1115,7 +1105,6 @@ function ActionItemRowView({row: row, busy: busy, showBreadcrumb: showBreadcrumb
|
|
|
1115
1105
|
flexShrink: 0
|
|
1116
1106
|
},
|
|
1117
1107
|
children: /* @__PURE__ */ jsx(TodoCheckbox, {
|
|
1118
|
-
busy: busy,
|
|
1119
1108
|
canClick: canClick,
|
|
1120
1109
|
checked: isTodoDone(row.item),
|
|
1121
1110
|
onToggle: onToggle
|
|
@@ -1186,12 +1175,10 @@ function RowBreadcrumb({row: row}) {
|
|
|
1186
1175
|
});
|
|
1187
1176
|
}
|
|
1188
1177
|
|
|
1189
|
-
const ADD_KEY = "__add__";
|
|
1190
|
-
|
|
1191
1178
|
function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1, identity: identity, activityFilter: activityFilter, variant: variant = "section"}) {
|
|
1192
|
-
const {instance: instance} = entry, {editFieldFor: editFieldFor, fireActionFor: fireActionFor} = useWorkflowContext(), toast = useToast(), [
|
|
1193
|
-
if (!
|
|
1194
|
-
|
|
1179
|
+
const {instance: instance} = entry, {editFieldFor: editFieldFor, fireActionFor: fireActionFor} = useWorkflowContext(), toast = useToast(), [busy, setBusy] = useState(!1), derivation = deriveActionItems(entry), rows = derivation.rows.filter(row => activityFilter === void 0 || row.activityName === activityFilter || row.tick?.activity === activityFilter).filter(row => !assignedToMeOnly || identity !== void 0 && isItemAssignedTo(row.item, identity)), appendTarget = activityFilter === void 0 ? derivation.appendTargets[0] : derivation.appendTargets.find(t => t.activity === activityFilter), run = async op => {
|
|
1180
|
+
if (!busy) {
|
|
1181
|
+
setBusy(!0);
|
|
1195
1182
|
try {
|
|
1196
1183
|
await op();
|
|
1197
1184
|
} catch (err) {
|
|
@@ -1201,7 +1188,7 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1201
1188
|
description: describeError(err)
|
|
1202
1189
|
});
|
|
1203
1190
|
} finally {
|
|
1204
|
-
|
|
1191
|
+
setBusy(!1);
|
|
1205
1192
|
}
|
|
1206
1193
|
}
|
|
1207
1194
|
}, patchItem = (row, patch) => {
|
|
@@ -1210,7 +1197,7 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1210
1197
|
...it,
|
|
1211
1198
|
...patch
|
|
1212
1199
|
} : it);
|
|
1213
|
-
return run(
|
|
1200
|
+
return run(() => editFieldFor(instance._id, {
|
|
1214
1201
|
target: target,
|
|
1215
1202
|
mode: "set",
|
|
1216
1203
|
value: next
|
|
@@ -1220,11 +1207,11 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1220
1207
|
status: toggledTodoStatus(row.item)
|
|
1221
1208
|
});
|
|
1222
1209
|
const tick = row.tick;
|
|
1223
|
-
return tick && tick.actionEval.allowed && !isTodoDone(row.item) ? run(
|
|
1210
|
+
return tick && tick.actionEval.allowed && !isTodoDone(row.item) ? run(() => fireActionFor(instance._id, {
|
|
1224
1211
|
activity: tick.activity,
|
|
1225
1212
|
action: tick.actionEval.action.name
|
|
1226
1213
|
})) : Promise.resolve();
|
|
1227
|
-
}, addItem = label => appendTarget ? run(
|
|
1214
|
+
}, addItem = label => appendTarget ? run(() => editFieldFor(instance._id, {
|
|
1228
1215
|
target: appendTarget,
|
|
1229
1216
|
mode: "append",
|
|
1230
1217
|
value: {
|
|
@@ -1234,7 +1221,6 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1234
1221
|
})) : Promise.resolve();
|
|
1235
1222
|
if (rows.length === 0 && !appendTarget) return null;
|
|
1236
1223
|
const rowKey = row => `${row.scope}:${row.activityName ?? ""}:${row.fieldName}:${row.item._key}`, rowProps = row => ({
|
|
1237
|
-
busy: busyKey === row.item._key,
|
|
1238
1224
|
onPatch: patch => {
|
|
1239
1225
|
patchItem(row, patch);
|
|
1240
1226
|
},
|
|
@@ -1253,7 +1239,7 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1253
1239
|
}, rowKey(row)))
|
|
1254
1240
|
}), appendTarget ? /* @__PURE__ */ jsx(Flex, {
|
|
1255
1241
|
children: /* @__PURE__ */ jsx(AddItemControl, {
|
|
1256
|
-
busy:
|
|
1242
|
+
busy: busy,
|
|
1257
1243
|
button: /* @__PURE__ */ jsx(Button, {
|
|
1258
1244
|
fontSize: 1,
|
|
1259
1245
|
icon: AddIcon,
|
|
@@ -1279,7 +1265,7 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1279
1265
|
/* @__PURE__ */ jsx(Box, {
|
|
1280
1266
|
paddingRight: 2,
|
|
1281
1267
|
children: /* @__PURE__ */ jsx(AddItemControl, {
|
|
1282
|
-
busy:
|
|
1268
|
+
busy: busy,
|
|
1283
1269
|
button: /* @__PURE__ */ jsx(HoverHint, {
|
|
1284
1270
|
text: "Add action item",
|
|
1285
1271
|
children: /* @__PURE__ */ jsx(Button, {
|
|
@@ -1406,7 +1392,7 @@ function groupEditableByActivity(fields) {
|
|
|
1406
1392
|
}
|
|
1407
1393
|
|
|
1408
1394
|
function deriveActivityPresentation(args) {
|
|
1409
|
-
const {activity: activity, status: status, actions: actions, kind: kind} = args.activityEval, editableNames = new Set(args.editableFields.map(f => f.name)), dates = args.state.filter(s => s._type === "datetime" && !!s.value), writtenNames = new Set(actions.flatMap(a => writtenFieldNames(a.action))), todoListNames = new Set(args.state.filter(isTodoListEntry).map(s => s.name)), bodyFields = args.state.filter(s => s._type !== "assignees" && s._type !== "datetime" && !writtenNames.has(s.name) && !editableNames.has(s.name) && !todoListNames.has(s.name)), visibleActions = actions.filter(a => {
|
|
1395
|
+
const {activity: activity, status: status, actions: actions, kind: kind} = args.activityEval, editableNames = new Set(args.editableFields.map(f => f.name)), dates = args.state.filter(s => (s._type === "date" || s._type === "datetime") && !!s.value && !editableNames.has(s.name)), writtenNames = new Set(actions.flatMap(a => writtenFieldNames(a.action))), todoListNames = new Set(args.state.filter(isTodoListEntry).map(s => s.name)), bodyFields = args.state.filter(s => s._type !== "assignees" && s._type !== "date" && s._type !== "datetime" && !writtenNames.has(s.name) && !editableNames.has(s.name) && !todoListNames.has(s.name)), visibleActions = actions.filter(a => {
|
|
1410
1396
|
const writes = writtenFieldNames(a.action);
|
|
1411
1397
|
return !(writes.length > 0 && writes.every(name => editableNames.has(name)));
|
|
1412
1398
|
}), blockedReason = status === "active" && actions.length > 0 && actions.every(a => !a.allowed) ? actions.find(a => a.disabledReason)?.disabledReason : void 0, ticks = tickActionNames({
|
|
@@ -1683,8 +1669,8 @@ function activityStateOf(instance, activityName) {
|
|
|
1683
1669
|
return findCurrentActivityEntry(instance, activityName)?.fields ?? [];
|
|
1684
1670
|
}
|
|
1685
1671
|
|
|
1686
|
-
function assigneeEntriesOf(state,
|
|
1687
|
-
return state.filter(s => s._type === "assignees" && (s.value.length > 0 || s.name
|
|
1672
|
+
function assigneeEntriesOf(state, assignFields) {
|
|
1673
|
+
return state.filter(s => s._type === "assignees" && (s.value.length > 0 || assignFields.has(s.name)));
|
|
1688
1674
|
}
|
|
1689
1675
|
|
|
1690
1676
|
function hasActivityActionItems(entry, activityName) {
|
|
@@ -1700,19 +1686,39 @@ function deriveActivityDetail(args) {
|
|
|
1700
1686
|
state: state,
|
|
1701
1687
|
workflowFields: instance.fields ?? [],
|
|
1702
1688
|
editableFields: activityEditables
|
|
1703
|
-
}),
|
|
1689
|
+
}), assignFields = new Map(activityEditables.filter(f => f.type === "assignees").map(f => [ f.name, f ]));
|
|
1704
1690
|
return {
|
|
1705
1691
|
activityEval: activityEval,
|
|
1706
1692
|
state: state,
|
|
1707
1693
|
presentation: presentation,
|
|
1708
1694
|
title: activityEval.activity.title ?? activityEval.activity.name,
|
|
1709
|
-
|
|
1710
|
-
assigneeEntries: assigneeEntriesOf(state,
|
|
1695
|
+
assignFields: assignFields,
|
|
1696
|
+
assigneeEntries: assigneeEntriesOf(state, assignFields),
|
|
1711
1697
|
hasActionItems: hasActivityActionItems(entry, activityName),
|
|
1712
1698
|
hasActions: presentation.manualTarget !== void 0 || presentation.hasVisibleActions
|
|
1713
1699
|
};
|
|
1714
1700
|
}
|
|
1715
1701
|
|
|
1702
|
+
function stageTitle(definition, stageName) {
|
|
1703
|
+
return definition?.stages.find(stage => stage.name === stageName)?.title ?? stageName;
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
function isHotField(evaluation, fieldName) {
|
|
1707
|
+
return (insightFor(evaluation, fieldName)?.involvedIn.length ?? 0) > 0;
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
function advanceTargetTitle(evaluation, fieldName) {
|
|
1711
|
+
if (evaluation === void 0) return;
|
|
1712
|
+
const involved = new Set((insightFor(evaluation, fieldName)?.involvedIn ?? []).flatMap(site => site.kind === "transition" ? [ site.transition ] : []));
|
|
1713
|
+
if (involved.size === 0) return;
|
|
1714
|
+
const halting = evaluation.currentStage.transitions.find(t => t.filterSatisfied || t.unevaluable);
|
|
1715
|
+
if (!(halting === void 0 || !halting.filterSatisfied) && involved.has(halting.transition.name)) return stageTitle(evaluation.definition, halting.transition.to);
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
function insightFor(evaluation, fieldName) {
|
|
1719
|
+
return evaluation?.fieldInsights.find(insight => insight.field === fieldName);
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1716
1722
|
function noteRow(args) {
|
|
1717
1723
|
return {
|
|
1718
1724
|
_key: randomKey(),
|
|
@@ -1733,6 +1739,14 @@ function FieldInput$1({field: field, value: value, onChange: onChange, onEnter:
|
|
|
1733
1739
|
onChange: e => onChange(e.currentTarget.checked)
|
|
1734
1740
|
});
|
|
1735
1741
|
|
|
1742
|
+
case "date":
|
|
1743
|
+
/* @__PURE__ */
|
|
1744
|
+
return jsx(TextInput, {
|
|
1745
|
+
onChange: e => onChange(e.currentTarget.value === "" ? null : e.currentTarget.value),
|
|
1746
|
+
type: "date",
|
|
1747
|
+
value: typeof value == "string" ? value : ""
|
|
1748
|
+
});
|
|
1749
|
+
|
|
1736
1750
|
case "datetime":
|
|
1737
1751
|
/* @__PURE__ */
|
|
1738
1752
|
return jsx(TextInput, {
|
|
@@ -1750,6 +1764,14 @@ function FieldInput$1({field: field, value: value, onChange: onChange, onEnter:
|
|
|
1750
1764
|
value: value == null ? "" : String(value)
|
|
1751
1765
|
});
|
|
1752
1766
|
|
|
1767
|
+
case "text":
|
|
1768
|
+
/* @__PURE__ */
|
|
1769
|
+
return jsx(TextArea, {
|
|
1770
|
+
onChange: e => onChange(e.currentTarget.value),
|
|
1771
|
+
rows: 3,
|
|
1772
|
+
value: value == null ? "" : String(value)
|
|
1773
|
+
});
|
|
1774
|
+
|
|
1753
1775
|
default:
|
|
1754
1776
|
/* @__PURE__ */
|
|
1755
1777
|
return jsx(TextInput, {
|
|
@@ -2129,7 +2151,7 @@ function ValueDisplay({field: field, value: value}) {
|
|
|
2129
2151
|
}
|
|
2130
2152
|
|
|
2131
2153
|
function EditableFieldControl({instanceId: instanceId, field: field, hideLabel: hideLabel}) {
|
|
2132
|
-
const {editFieldFor: editFieldFor, byInstance: byInstance} = useWorkflowContext(), me = useCurrentUser(),
|
|
2154
|
+
const {editFieldFor: editFieldFor, previewFieldFor: previewFieldFor, discardFieldPreviewFor: discardFieldPreviewFor, byInstance: byInstance} = useWorkflowContext(), me = useCurrentUser(), held = byInstance.get(instanceId), entry = held ? resolveFieldEntry(held.instance, field) : void 0, evaluation = held?.evaluation, target = editTargetOf(field), advanceTo = advanceTargetTitle(evaluation, field.name);
|
|
2133
2155
|
/* @__PURE__ */
|
|
2134
2156
|
return jsx(EditableField, {
|
|
2135
2157
|
field: field,
|
|
@@ -2139,17 +2161,27 @@ function EditableFieldControl({instanceId: instanceId, field: field, hideLabel:
|
|
|
2139
2161
|
...hideLabel === void 0 ? {} : {
|
|
2140
2162
|
hideLabel: hideLabel
|
|
2141
2163
|
},
|
|
2164
|
+
hot: isHotField(evaluation, field.name),
|
|
2165
|
+
...advanceTo === void 0 ? {} : {
|
|
2166
|
+
advanceTo: advanceTo
|
|
2167
|
+
},
|
|
2142
2168
|
onSave: value => editFieldFor(instanceId, {
|
|
2143
|
-
target:
|
|
2169
|
+
target: target,
|
|
2144
2170
|
mode: "set",
|
|
2145
2171
|
value: value
|
|
2146
2172
|
}).then(() => {}),
|
|
2173
|
+
onPreview: value => previewFieldFor(instanceId, {
|
|
2174
|
+
target: target,
|
|
2175
|
+
mode: "set",
|
|
2176
|
+
value: value
|
|
2177
|
+
}),
|
|
2178
|
+
onDiscardPreview: () => discardFieldPreviewFor(instanceId, target),
|
|
2147
2179
|
onUnset: () => editFieldFor(instanceId, {
|
|
2148
|
-
target:
|
|
2180
|
+
target: target,
|
|
2149
2181
|
mode: "unset"
|
|
2150
2182
|
}).then(() => {}),
|
|
2151
2183
|
onAppend: body => editFieldFor(instanceId, {
|
|
2152
|
-
target:
|
|
2184
|
+
target: target,
|
|
2153
2185
|
mode: "append",
|
|
2154
2186
|
value: noteRow({
|
|
2155
2187
|
body: body,
|
|
@@ -2216,21 +2248,28 @@ function FieldLabel({label: label, hide: hide}) {
|
|
|
2216
2248
|
});
|
|
2217
2249
|
}
|
|
2218
2250
|
|
|
2219
|
-
function
|
|
2220
|
-
const toast = useToast()
|
|
2251
|
+
function useSaveFailureToast() {
|
|
2252
|
+
const toast = useToast();
|
|
2253
|
+
return err => {
|
|
2254
|
+
console.error("[workflow-studio-plugin] field save failed:", err), toast.push({
|
|
2255
|
+
status: "error",
|
|
2256
|
+
title: "Saving failed",
|
|
2257
|
+
description: describeError(err)
|
|
2258
|
+
});
|
|
2259
|
+
};
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
function useSaveField() {
|
|
2263
|
+
const reportFailure = useSaveFailureToast(), [saving, setSaving] = useState(!1);
|
|
2221
2264
|
return {
|
|
2222
2265
|
saving: saving,
|
|
2223
2266
|
save: async commit => {
|
|
2224
2267
|
if (!saving) {
|
|
2225
2268
|
setSaving(!0);
|
|
2226
2269
|
try {
|
|
2227
|
-
await commit()
|
|
2270
|
+
await commit();
|
|
2228
2271
|
} catch (err) {
|
|
2229
|
-
|
|
2230
|
-
status: "error",
|
|
2231
|
-
title: "Saving failed",
|
|
2232
|
-
description: describeError(err)
|
|
2233
|
-
});
|
|
2272
|
+
reportFailure(err);
|
|
2234
2273
|
} finally {
|
|
2235
2274
|
setSaving(!1);
|
|
2236
2275
|
}
|
|
@@ -2240,7 +2279,7 @@ function useSaveField(args) {
|
|
|
2240
2279
|
}
|
|
2241
2280
|
|
|
2242
2281
|
function ActorField({field: field, label: label, hideLabel: hideLabel, onSave: onSave, onUnset: onUnset}) {
|
|
2243
|
-
const [open, setOpen] = useState(!1), {saving: saving, save: save} = useSaveField(
|
|
2282
|
+
const [open, setOpen] = useState(!1), {saving: saving, save: save} = useSaveField(), cur = field.value, pick = member => {
|
|
2244
2283
|
setOpen(!1), !saving && (member && member.id !== cur?.id ? save(() => onSave(personActor(member))) : onUnset !== void 0 && cur && save(onUnset));
|
|
2245
2284
|
}, value = cur ? /* @__PURE__ */ jsx(ActorName, {
|
|
2246
2285
|
id: cur.id
|
|
@@ -2323,10 +2362,14 @@ function ArrayField({field: field, label: label, hideLabel: hideLabel}) {
|
|
|
2323
2362
|
}
|
|
2324
2363
|
|
|
2325
2364
|
function NotesField({field: field, label: label, hideLabel: hideLabel, onAppend: onAppend}) {
|
|
2326
|
-
const [body, setBody] = useState(""), {saving: saving, save: save} = useSaveField({
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2365
|
+
const [body, setBody] = useState(""), {saving: saving, save: save} = useSaveField(), rows = arrayRowsOf(field.value), trimmed = body.trim(), add = () => {
|
|
2366
|
+
saving || trimmed === "" || (setBody(""), save(async () => {
|
|
2367
|
+
try {
|
|
2368
|
+
await onAppend(trimmed);
|
|
2369
|
+
} catch (err) {
|
|
2370
|
+
throw setBody(trimmed), err;
|
|
2371
|
+
}
|
|
2372
|
+
}));
|
|
2330
2373
|
};
|
|
2331
2374
|
/* @__PURE__ */
|
|
2332
2375
|
return jsxs(Stack, {
|
|
@@ -2345,7 +2388,6 @@ function NotesField({field: field, label: label, hideLabel: hideLabel, onAppend:
|
|
|
2345
2388
|
/* @__PURE__ */ jsx(Box, {
|
|
2346
2389
|
flex: 1,
|
|
2347
2390
|
children: /* @__PURE__ */ jsx(TextArea, {
|
|
2348
|
-
disabled: saving,
|
|
2349
2391
|
fontSize: 1,
|
|
2350
2392
|
onChange: e => setBody(e.currentTarget.value),
|
|
2351
2393
|
placeholder: "Add an entry…",
|
|
@@ -2354,9 +2396,8 @@ function NotesField({field: field, label: label, hideLabel: hideLabel, onAppend:
|
|
|
2354
2396
|
})
|
|
2355
2397
|
}),
|
|
2356
2398
|
/* @__PURE__ */ jsx(Button, {
|
|
2357
|
-
disabled:
|
|
2399
|
+
disabled: trimmed === "",
|
|
2358
2400
|
fontSize: 1,
|
|
2359
|
-
loading: saving,
|
|
2360
2401
|
onClick: add,
|
|
2361
2402
|
padding: 2,
|
|
2362
2403
|
text: "Add",
|
|
@@ -2367,7 +2408,7 @@ function NotesField({field: field, label: label, hideLabel: hideLabel, onAppend:
|
|
|
2367
2408
|
}
|
|
2368
2409
|
|
|
2369
2410
|
function BooleanSwitchField({field: field, label: label, hideLabel: hideLabel, onSave: onSave}) {
|
|
2370
|
-
const {
|
|
2411
|
+
const {save: save} = useSaveField(), committed = field.value === !0;
|
|
2371
2412
|
/* @__PURE__ */
|
|
2372
2413
|
return jsxs(Flex, {
|
|
2373
2414
|
align: "center",
|
|
@@ -2379,68 +2420,56 @@ function BooleanSwitchField({field: field, label: label, hideLabel: hideLabel, o
|
|
|
2379
2420
|
label: label
|
|
2380
2421
|
}),
|
|
2381
2422
|
/* @__PURE__ */ jsx(Switch, {
|
|
2382
|
-
checked:
|
|
2383
|
-
disabled: saving,
|
|
2423
|
+
checked: committed,
|
|
2384
2424
|
onChange: () => {
|
|
2385
|
-
|
|
2386
|
-
setOptimistic(next), save(() => onSave(next)).finally(() => setOptimistic(null));
|
|
2425
|
+
save(() => onSave(!committed));
|
|
2387
2426
|
}
|
|
2388
2427
|
}) ]
|
|
2389
2428
|
});
|
|
2390
2429
|
}
|
|
2391
2430
|
|
|
2392
|
-
function
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2431
|
+
function sameValue(a, b) {
|
|
2432
|
+
return (a ?? void 0) === (b ?? void 0);
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
function GenericField({field: field, label: label, hideLabel: hideLabel, onSave: onSave, onPreview: onPreview, onDiscardPreview: onDiscardPreview}) {
|
|
2436
|
+
const reportFailure = useSaveFailureToast(), [draft, setDraft] = useState(field.value), [baseline, setBaseline] = useState(field.value), dirty = !sameValue(draft, baseline), focused = useRef(!1), previewed = useRef(!1), commit = () => {
|
|
2437
|
+
if (!dirty) return;
|
|
2438
|
+
const value = draft, prev = baseline;
|
|
2439
|
+
setBaseline(value), previewed.current = !1, onSave(value).catch(err => {
|
|
2440
|
+
reportFailure(err), setBaseline(current => sameValue(current, value) ? prev : current),
|
|
2441
|
+
setDraft(current => sameValue(current, value) ? prev : current);
|
|
2442
|
+
});
|
|
2443
|
+
}, settle = () => {
|
|
2444
|
+
dirty ? commit() : previewed.current && (previewed.current = !1, onDiscardPreview?.());
|
|
2445
|
+
}, settleRef = useRef(settle);
|
|
2446
|
+
settleRef.current = settle, useEffect(() => () => settleRef.current(), []);
|
|
2447
|
+
const adopted = useRef(field.value);
|
|
2396
2448
|
return useEffect(() => {
|
|
2397
|
-
|
|
2398
|
-
|
|
2449
|
+
sameValue(adopted.current, field.value) || focused.current || dirty || (adopted.current = field.value,
|
|
2450
|
+
setBaseline(field.value), setDraft(field.value));
|
|
2451
|
+
}, [ field.value, dirty ]), field.editable ? /* @__PURE__ */ jsxs(Stack, {
|
|
2399
2452
|
gap: 2,
|
|
2400
2453
|
children: [
|
|
2401
2454
|
/* @__PURE__ */ jsx(FieldLabel, {
|
|
2402
2455
|
hide: hideLabel,
|
|
2403
2456
|
label: label
|
|
2404
2457
|
}),
|
|
2405
|
-
/* @__PURE__ */
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
value
|
|
2416
|
-
}
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
children: /* @__PURE__ */ jsx(Button, {
|
|
2421
|
-
"aria-label": "Save",
|
|
2422
|
-
fontSize: 1,
|
|
2423
|
-
icon: CheckmarkIcon,
|
|
2424
|
-
loading: saving,
|
|
2425
|
-
onClick: () => save(() => onSave(draft)),
|
|
2426
|
-
padding: 2,
|
|
2427
|
-
tone: "primary"
|
|
2428
|
-
})
|
|
2429
|
-
}),
|
|
2430
|
-
/* @__PURE__ */ jsx(HoverHint, {
|
|
2431
|
-
text: "Cancel",
|
|
2432
|
-
children: /* @__PURE__ */ jsx(Button, {
|
|
2433
|
-
"aria-label": "Cancel",
|
|
2434
|
-
disabled: saving,
|
|
2435
|
-
fontSize: 1,
|
|
2436
|
-
icon: CloseIcon,
|
|
2437
|
-
mode: "bleed",
|
|
2438
|
-
onClick: () => {
|
|
2439
|
-
setDraft(field.value), setEditing(!1);
|
|
2440
|
-
},
|
|
2441
|
-
padding: 2
|
|
2442
|
-
})
|
|
2443
|
-
}) ]
|
|
2458
|
+
/* @__PURE__ */ jsx(Box, {
|
|
2459
|
+
onBlur: () => {
|
|
2460
|
+
focused.current = !1, settle();
|
|
2461
|
+
},
|
|
2462
|
+
onFocus: () => {
|
|
2463
|
+
focused.current = !0;
|
|
2464
|
+
},
|
|
2465
|
+
children: /* @__PURE__ */ jsx(FieldInput$1, {
|
|
2466
|
+
field: field,
|
|
2467
|
+
onChange: value => {
|
|
2468
|
+
setDraft(value), previewed.current = !0, onPreview?.(value);
|
|
2469
|
+
},
|
|
2470
|
+
onEnter: commit,
|
|
2471
|
+
value: draft
|
|
2472
|
+
})
|
|
2444
2473
|
}) ]
|
|
2445
2474
|
}) : /* @__PURE__ */ jsxs(Flex, {
|
|
2446
2475
|
align: "center",
|
|
@@ -2450,14 +2479,7 @@ function GenericField({field: field, label: label, hideLabel: hideLabel, onSave:
|
|
|
2450
2479
|
/* @__PURE__ */ jsx(FieldLabel, {
|
|
2451
2480
|
hide: hideLabel,
|
|
2452
2481
|
label: label
|
|
2453
|
-
}),
|
|
2454
|
-
hint: "Edit",
|
|
2455
|
-
onClick: () => setEditing(!0),
|
|
2456
|
-
children: /* @__PURE__ */ jsx(ValueDisplay, {
|
|
2457
|
-
field: field,
|
|
2458
|
-
value: field.value
|
|
2459
|
-
})
|
|
2460
|
-
}) :
|
|
2482
|
+
}),
|
|
2461
2483
|
/* @__PURE__ */ jsxs(Flex, {
|
|
2462
2484
|
align: "center",
|
|
2463
2485
|
gap: 2,
|
|
@@ -2474,13 +2496,33 @@ function GenericField({field: field, label: label, hideLabel: hideLabel, onSave:
|
|
|
2474
2496
|
});
|
|
2475
2497
|
}
|
|
2476
2498
|
|
|
2477
|
-
function
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2499
|
+
function HotFieldHint() {
|
|
2500
|
+
/* @__PURE__ */
|
|
2501
|
+
return jsx(HoverHint, {
|
|
2502
|
+
text: "Editing this can move the workflow",
|
|
2503
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
2504
|
+
"aria-label": "Editing this can move the workflow",
|
|
2505
|
+
muted: !0,
|
|
2506
|
+
size: 1,
|
|
2507
|
+
style: {
|
|
2508
|
+
cursor: "help"
|
|
2509
|
+
},
|
|
2510
|
+
children: /* @__PURE__ */ jsx(BoltIcon, {})
|
|
2511
|
+
})
|
|
2512
|
+
});
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
function AdvanceHint({stageTitle: stageTitle2}) {
|
|
2516
|
+
/* @__PURE__ */
|
|
2517
|
+
return jsxs(Text, {
|
|
2518
|
+
muted: !0,
|
|
2519
|
+
size: 1,
|
|
2520
|
+
children: [ "Committing will advance to ", stageTitle2 ]
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
function fieldArm({arm: arm, entry: entry, onUnset: onUnset, onAppend: onAppend, onPreview: onPreview, onDiscardPreview: onDiscardPreview}) {
|
|
2525
|
+
const {field: field} = arm;
|
|
2484
2526
|
return field.type === "actor" ? /* @__PURE__ */ jsx(ActorField, {
|
|
2485
2527
|
...arm,
|
|
2486
2528
|
...onUnset === void 0 ? {} : {
|
|
@@ -2496,7 +2538,45 @@ function EditableField({field: field, entry: entry, onSave: onSave, onUnset: onU
|
|
|
2496
2538
|
}) : field.type === "boolean" && field.editable ? /* @__PURE__ */ jsx(BooleanSwitchField, {
|
|
2497
2539
|
...arm
|
|
2498
2540
|
}) : /* @__PURE__ */ jsx(GenericField, {
|
|
2499
|
-
...arm
|
|
2541
|
+
...arm,
|
|
2542
|
+
...onPreview === void 0 ? {} : {
|
|
2543
|
+
onPreview: onPreview
|
|
2544
|
+
},
|
|
2545
|
+
...onDiscardPreview === void 0 ? {} : {
|
|
2546
|
+
onDiscardPreview: onDiscardPreview
|
|
2547
|
+
}
|
|
2548
|
+
});
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
function EditableField({field: field, entry: entry, onSave: onSave, onUnset: onUnset, onAppend: onAppend, onPreview: onPreview, onDiscardPreview: onDiscardPreview, hot: hot = !1, advanceTo: advanceTo, hideLabel: hideLabel = !1}) {
|
|
2552
|
+
const label = field.title ?? field.name, content = fieldArm({
|
|
2553
|
+
arm: {
|
|
2554
|
+
field: field,
|
|
2555
|
+
label: label,
|
|
2556
|
+
hideLabel: hideLabel,
|
|
2557
|
+
onSave: onSave
|
|
2558
|
+
},
|
|
2559
|
+
entry: entry,
|
|
2560
|
+
onUnset: onUnset,
|
|
2561
|
+
onAppend: onAppend,
|
|
2562
|
+
onPreview: onPreview,
|
|
2563
|
+
onDiscardPreview: onDiscardPreview
|
|
2564
|
+
}), decorated = field.editable;
|
|
2565
|
+
/* @__PURE__ */
|
|
2566
|
+
return jsxs(Stack, {
|
|
2567
|
+
gap: 2,
|
|
2568
|
+
children: [
|
|
2569
|
+
/* @__PURE__ */ jsxs(Flex, {
|
|
2570
|
+
align: "center",
|
|
2571
|
+
gap: 2,
|
|
2572
|
+
children: [
|
|
2573
|
+
/* @__PURE__ */ jsx(Box, {
|
|
2574
|
+
flex: 1,
|
|
2575
|
+
children: content
|
|
2576
|
+
}), decorated && hot ? /* @__PURE__ */ jsx(HotFieldHint, {}) : null ]
|
|
2577
|
+
}), decorated && advanceTo !== void 0 ? /* @__PURE__ */ jsx(AdvanceHint, {
|
|
2578
|
+
stageTitle: advanceTo
|
|
2579
|
+
}) : null ]
|
|
2500
2580
|
});
|
|
2501
2581
|
}
|
|
2502
2582
|
|
|
@@ -3264,7 +3344,7 @@ function ActivityDetailDialog({entry: entry, activityName: activityName, breadcr
|
|
|
3264
3344
|
}
|
|
3265
3345
|
|
|
3266
3346
|
function DetailRows({detail: detail, entry: entry, instanceId: instanceId, activityName: activityName}) {
|
|
3267
|
-
const {activityEval: activityEval, presentation: presentation,
|
|
3347
|
+
const {activityEval: activityEval, presentation: presentation, assignFields: assignFields} = detail;
|
|
3268
3348
|
/* @__PURE__ */
|
|
3269
3349
|
return jsxs(Fragment, {
|
|
3270
3350
|
children: [
|
|
@@ -3282,21 +3362,25 @@ function DetailRows({detail: detail, entry: entry, instanceId: instanceId, activ
|
|
|
3282
3362
|
children: ACTIVITY_STATUS_LABEL[activityEval.status]
|
|
3283
3363
|
}) ]
|
|
3284
3364
|
})
|
|
3285
|
-
}), detail.assigneeEntries.map(entry_ =>
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3365
|
+
}), detail.assigneeEntries.map(entry_ => {
|
|
3366
|
+
const assignField = assignFields.get(entry_.name);
|
|
3367
|
+
/* @__PURE__ */
|
|
3368
|
+
return jsx(LabeledRow, {
|
|
3369
|
+
label: entry_.title ?? "Assignees",
|
|
3370
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
3371
|
+
align: "center",
|
|
3372
|
+
gap: 2,
|
|
3373
|
+
wrap: "wrap",
|
|
3374
|
+
children: [
|
|
3375
|
+
/* @__PURE__ */ jsx(FieldValue, {
|
|
3376
|
+
field: entry_
|
|
3377
|
+
}), assignField ? /* @__PURE__ */ jsx(AssignActivityControl, {
|
|
3378
|
+
field: assignField,
|
|
3379
|
+
instanceId: instanceId
|
|
3380
|
+
}) : null ]
|
|
3381
|
+
})
|
|
3382
|
+
}, entry_._key);
|
|
3383
|
+
}), presentation.dates.map(d => /* @__PURE__ */ jsx(LabeledRow, {
|
|
3300
3384
|
label: d.title ?? d.name,
|
|
3301
3385
|
children: /* @__PURE__ */ jsx(BareValue, {
|
|
3302
3386
|
children: /* @__PURE__ */ jsx(Text, {
|
|
@@ -3459,10 +3543,6 @@ function useInstanceTitle(entry) {
|
|
|
3459
3543
|
return instanceTitle(entry.instance, definition);
|
|
3460
3544
|
}
|
|
3461
3545
|
|
|
3462
|
-
function stageTitle(instance, definition) {
|
|
3463
|
-
return definition?.stages.find(s => s.name === instance.currentStage)?.title ?? instance.currentStage;
|
|
3464
|
-
}
|
|
3465
|
-
|
|
3466
3546
|
function InstanceStatusBadge({instance: instance, definition: definition}) {
|
|
3467
3547
|
const state = terminalState(instance);
|
|
3468
3548
|
return state === "aborted" ? /* @__PURE__ */ jsx(Badge, {
|
|
@@ -3476,7 +3556,7 @@ function InstanceStatusBadge({instance: instance, definition: definition}) {
|
|
|
3476
3556
|
}) : /* @__PURE__ */ jsx(Badge, {
|
|
3477
3557
|
fontSize: 1,
|
|
3478
3558
|
tone: "primary",
|
|
3479
|
-
children: stageTitle(
|
|
3559
|
+
children: stageTitle(definition, instance.currentStage)
|
|
3480
3560
|
});
|
|
3481
3561
|
}
|
|
3482
3562
|
|
|
@@ -3516,7 +3596,6 @@ function StageGlyph(props) {
|
|
|
3516
3596
|
}
|
|
3517
3597
|
|
|
3518
3598
|
function CurrentStageIndicator({instance: instance, definition: definition}) {
|
|
3519
|
-
const stage = definition?.stages.find(s => s.name === instance.currentStage);
|
|
3520
3599
|
/* @__PURE__ */
|
|
3521
3600
|
return jsxs(Flex, {
|
|
3522
3601
|
align: "center",
|
|
@@ -3529,7 +3608,7 @@ function CurrentStageIndicator({instance: instance, definition: definition}) {
|
|
|
3529
3608
|
/* @__PURE__ */ jsx(Text, {
|
|
3530
3609
|
size: 1,
|
|
3531
3610
|
weight: "medium",
|
|
3532
|
-
children:
|
|
3611
|
+
children: stageTitle(definition, instance.currentStage)
|
|
3533
3612
|
}) ]
|
|
3534
3613
|
});
|
|
3535
3614
|
}
|
|
@@ -3871,11 +3950,11 @@ function ActivityTab({instance: instance, definition: definition}) {
|
|
|
3871
3950
|
}
|
|
3872
3951
|
|
|
3873
3952
|
function makeTitleResolver(definition) {
|
|
3874
|
-
const
|
|
3953
|
+
const activities = (definition?.stages ?? []).flatMap(s => s.activities ?? []);
|
|
3875
3954
|
return {
|
|
3876
3955
|
action: (activityName, actionName) => activities.find(t => t.name === activityName)?.actions?.find(a => a.name === actionName)?.title ?? actionName,
|
|
3877
3956
|
activity: name => activities.find(t => t.name === name)?.title ?? name,
|
|
3878
|
-
stage: name =>
|
|
3957
|
+
stage: name => stageTitle(definition, name)
|
|
3879
3958
|
};
|
|
3880
3959
|
}
|
|
3881
3960
|
|
|
@@ -3955,8 +4034,7 @@ function InstanceMenuItem({entry: entry, selected: selected, onSelect: onSelect}
|
|
|
3955
4034
|
|
|
3956
4035
|
function instanceNotice(entry) {
|
|
3957
4036
|
const {instance: instance, committed: committed, evaluation: evaluation} = entry, state = terminalState(instance);
|
|
3958
|
-
|
|
3959
|
-
return jsx(Card, {
|
|
4037
|
+
return state !== "in-flight" ? /* @__PURE__ */ jsx(Card, {
|
|
3960
4038
|
border: !0,
|
|
3961
4039
|
padding: 3,
|
|
3962
4040
|
radius: 2,
|
|
@@ -3965,24 +4043,27 @@ function instanceNotice(entry) {
|
|
|
3965
4043
|
size: 1,
|
|
3966
4044
|
children: state === "aborted" ? "This workflow was aborted — no open tasks." : "This workflow is complete — no open tasks."
|
|
3967
4045
|
})
|
|
3968
|
-
})
|
|
3969
|
-
const freshness = evaluationFreshness({
|
|
4046
|
+
}) : evaluationFreshness({
|
|
3970
4047
|
committed: committed,
|
|
3971
4048
|
evaluation: evaluation
|
|
3972
|
-
})
|
|
3973
|
-
return freshness === "pending" ? /* @__PURE__ */ jsx(LoadingRow, {
|
|
4049
|
+
}) === "pending" ? /* @__PURE__ */ jsx(LoadingRow, {
|
|
3974
4050
|
label: "Evaluating…",
|
|
3975
4051
|
padding: 4
|
|
3976
|
-
}) : freshness === "stale" ? /* @__PURE__ */ jsx(LoadingRow, {
|
|
3977
|
-
label: "Updating…",
|
|
3978
|
-
padding: 4
|
|
3979
4052
|
}) : null;
|
|
3980
4053
|
}
|
|
3981
4054
|
|
|
4055
|
+
function evaluationSyncing(entry) {
|
|
4056
|
+
const {instance: instance, committed: committed, evaluation: evaluation} = entry;
|
|
4057
|
+
return terminalState(instance) === "in-flight" && evaluationFreshness({
|
|
4058
|
+
committed: committed,
|
|
4059
|
+
evaluation: evaluation
|
|
4060
|
+
}) === "stale";
|
|
4061
|
+
}
|
|
4062
|
+
|
|
3982
4063
|
const NO_EDITABLES = /* @__PURE__ */ new Map;
|
|
3983
4064
|
|
|
3984
4065
|
function InstanceStateTab({entry: entry}) {
|
|
3985
|
-
const {instance: instance} = entry, definition = useDefinition(entry),
|
|
4066
|
+
const {instance: instance} = entry, definition = useDefinition(entry), editables = (entry.evaluation?.editableFields ?? []).filter(f => f.scope !== "activity"), editablesByName = scope => new Map(editables.filter(f => f.scope === scope).map(f => [ f.name, f ])), anyState = instance.fields.length > 0 || instance.stages.some(s => s.fields.length > 0);
|
|
3986
4067
|
/* @__PURE__ */
|
|
3987
4068
|
return jsxs(Stack, {
|
|
3988
4069
|
gap: 4,
|
|
@@ -4000,7 +4081,7 @@ function InstanceStateTab({entry: entry}) {
|
|
|
4000
4081
|
return jsx(ScopeGroup, {
|
|
4001
4082
|
editables: current ? editablesByName("stage") : NO_EDITABLES,
|
|
4002
4083
|
fields: st.fields ?? [],
|
|
4003
|
-
heading: `Stage · ${
|
|
4084
|
+
heading: `Stage · ${stageTitle(definition, st.name)}${suffix}`,
|
|
4004
4085
|
instanceId: instance._id
|
|
4005
4086
|
}, `s-${i}`);
|
|
4006
4087
|
}) ]
|
|
@@ -4204,7 +4285,7 @@ function StageIndicator({entry: entry, definition: definition}) {
|
|
|
4204
4285
|
}
|
|
4205
4286
|
|
|
4206
4287
|
function InstancePanel({entry: entry, entries: entries, onSelect: onSelect}) {
|
|
4207
|
-
const definition = useDefinition(entry), {instance: instance, ready: ready} = entry, identity = useAssignmentIdentity(), [assignedToMe, setAssignedToMe] = useState(!1), [openActivity, setOpenActivity] = useState(null), [segment, setSegment] = useState("state"),
|
|
4288
|
+
const definition = useDefinition(entry), {instance: instance, ready: ready} = entry, identity = useAssignmentIdentity(), [assignedToMe, setAssignedToMe] = useState(!1), [openActivity, setOpenActivity] = useState(null), [segment, setSegment] = useState("state"), currentStageTitle = stageTitle(definition, instance.currentStage), notice = instanceNotice(entry), syncing = evaluationSyncing(entry);
|
|
4208
4289
|
/* @__PURE__ */
|
|
4209
4290
|
return jsxs(Flex, {
|
|
4210
4291
|
direction: "column",
|
|
@@ -4231,8 +4312,18 @@ function InstancePanel({entry: entry, entries: entries, onSelect: onSelect}) {
|
|
|
4231
4312
|
}),
|
|
4232
4313
|
/* @__PURE__ */ jsx(PendingWorkBadge, {
|
|
4233
4314
|
instance: instance
|
|
4234
|
-
}),
|
|
4235
|
-
|
|
4315
|
+
}),
|
|
4316
|
+
/* @__PURE__ */ jsx(Flex, {
|
|
4317
|
+
align: "center",
|
|
4318
|
+
flex: "none",
|
|
4319
|
+
justify: "center",
|
|
4320
|
+
style: {
|
|
4321
|
+
width: 19,
|
|
4322
|
+
height: 19
|
|
4323
|
+
},
|
|
4324
|
+
children: !ready || syncing ? /* @__PURE__ */ jsx(Spinner, {
|
|
4325
|
+
muted: !0
|
|
4326
|
+
}) : null
|
|
4236
4327
|
}),
|
|
4237
4328
|
/* @__PURE__ */ jsx(Box, {
|
|
4238
4329
|
flex: 1
|
|
@@ -4292,20 +4383,29 @@ function InstancePanel({entry: entry, entries: entries, onSelect: onSelect}) {
|
|
|
4292
4383
|
size: 1,
|
|
4293
4384
|
children: "Couldn’t load this workflow’s definition — stage and action titles fall back to raw names."
|
|
4294
4385
|
})
|
|
4295
|
-
}), notice ??
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4386
|
+
}), notice ??
|
|
4387
|
+
/* @__PURE__ */ jsx(Box, {
|
|
4388
|
+
style: {
|
|
4389
|
+
opacity: syncing ? .5 : 1,
|
|
4390
|
+
pointerEvents: syncing ? "none" : void 0,
|
|
4391
|
+
transition: "opacity 150ms ease-in"
|
|
4392
|
+
},
|
|
4393
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
4394
|
+
"aria-busy": syncing,
|
|
4395
|
+
children: [
|
|
4396
|
+
/* @__PURE__ */ jsx(ActivitiesList, {
|
|
4397
|
+
assignedToMeOnly: assignedToMe,
|
|
4398
|
+
entry: entry,
|
|
4399
|
+
identity: identity,
|
|
4400
|
+
onOpenActivity: setOpenActivity,
|
|
4401
|
+
stageTitle: currentStageTitle
|
|
4402
|
+
}),
|
|
4403
|
+
/* @__PURE__ */ jsx(ActionItemsList, {
|
|
4404
|
+
assignedToMeOnly: assignedToMe,
|
|
4405
|
+
entry: entry,
|
|
4406
|
+
identity: identity
|
|
4407
|
+
}) ]
|
|
4408
|
+
})
|
|
4309
4409
|
}),
|
|
4310
4410
|
/* @__PURE__ */ jsx(Card, {
|
|
4311
4411
|
border: !0,
|
|
@@ -4348,7 +4448,7 @@ function InstancePanel({entry: entry, entries: entries, onSelect: onSelect}) {
|
|
|
4348
4448
|
})
|
|
4349
4449
|
}), openActivity ? /* @__PURE__ */ jsx(ActivityDetailDialog, {
|
|
4350
4450
|
activityName: openActivity,
|
|
4351
|
-
breadcrumb: [ instanceTitle(instance, definition),
|
|
4451
|
+
breadcrumb: [ instanceTitle(instance, definition), currentStageTitle ],
|
|
4352
4452
|
entry: entry,
|
|
4353
4453
|
onClose: () => setOpenActivity(null)
|
|
4354
4454
|
}) : null ]
|
|
@@ -4409,7 +4509,7 @@ function useRefcountedIds() {
|
|
|
4409
4509
|
};
|
|
4410
4510
|
}
|
|
4411
4511
|
|
|
4412
|
-
const REPORT_KEYS = [ "evaluation", "ready", "guards", "fireAction", "editField" ];
|
|
4512
|
+
const REPORT_KEYS = [ "evaluation", "ready", "guards", "fireAction", "editField", "previewField", "discardFieldPreview" ];
|
|
4413
4513
|
|
|
4414
4514
|
function sameReport(a, b) {
|
|
4415
4515
|
return REPORT_KEYS.every(key => a[key] === b[key]);
|
|
@@ -4453,7 +4553,7 @@ class InstanceEvaluatorBoundary extends Component {
|
|
|
4453
4553
|
}
|
|
4454
4554
|
|
|
4455
4555
|
function InstanceEvaluator(props) {
|
|
4456
|
-
const {engine: engine, instanceId: instanceId, grantsFromPath: grantsFromPath, onReport: onReport} = props, {evaluation: evaluation, ready: ready, guards: guards, fireAction: fireAction, editField: editField} = useWorkflowSession({
|
|
4556
|
+
const {engine: engine, instanceId: instanceId, grantsFromPath: grantsFromPath, onReport: onReport} = props, {evaluation: evaluation, ready: ready, guards: guards, fireAction: fireAction, editField: editField, previewField: previewField, discardFieldPreview: discardFieldPreview} = useWorkflowSession({
|
|
4457
4557
|
engine: engine,
|
|
4458
4558
|
instanceId: instanceId,
|
|
4459
4559
|
grantsFromPath: grantsFromPath
|
|
@@ -4464,9 +4564,11 @@ function InstanceEvaluator(props) {
|
|
|
4464
4564
|
ready: ready,
|
|
4465
4565
|
guards: guards,
|
|
4466
4566
|
fireAction: fireAction,
|
|
4467
|
-
editField: editField
|
|
4567
|
+
editField: editField,
|
|
4568
|
+
previewField: previewField,
|
|
4569
|
+
discardFieldPreview: discardFieldPreview
|
|
4468
4570
|
});
|
|
4469
|
-
}, [ instanceId, evaluation, ready, guards, fireAction, editField, onReport ]),
|
|
4571
|
+
}, [ instanceId, evaluation, ready, guards, fireAction, editField, previewField, discardFieldPreview, onReport ]),
|
|
4470
4572
|
useEffect(() => () => onReport(instanceId, void 0), [ instanceId, onReport ]), null;
|
|
4471
4573
|
}
|
|
4472
4574
|
|
|
@@ -4529,7 +4631,10 @@ function WorkflowProvider(props) {
|
|
|
4529
4631
|
...config.effectHandlers ? {
|
|
4530
4632
|
effectHandlers: config.effectHandlers
|
|
4531
4633
|
} : {}
|
|
4532
|
-
}), grantsFromPath =
|
|
4634
|
+
}), grantsFromPath = aclPathForResource({
|
|
4635
|
+
type: "dataset",
|
|
4636
|
+
id: `${projectId}.${workflowDataset}`
|
|
4637
|
+
}), {ids: registered, acquire: register, release: unregister} = useRefcountedIds(), {ids: requested, acquire: requestInstance, release: releaseInstance} = useRefcountedIds(), [seeded, setSeeded] = useState(/* @__PURE__ */ new Map), seedInstance = useCallback(instance => {
|
|
4533
4638
|
setSeeded(prev => new Map(prev).set(instance._id, instance));
|
|
4534
4639
|
}, []), [startRequest, setStartRequest] = useState(void 0), openStartDialog = useCallback(r => setStartRequest(r), []), closeStartDialog = useCallback(() => setStartRequest(void 0), []), [reports, setReports] = useState(/* @__PURE__ */ new Map), onReport = useCallback((instanceId, report) => {
|
|
4535
4640
|
setReports(prev => nextReports(prev, {
|
|
@@ -4559,7 +4664,11 @@ function WorkflowProvider(props) {
|
|
|
4559
4664
|
const report = reportsRef.current.get(instanceId);
|
|
4560
4665
|
return report ? report.editField(args).then(async res => (await drainCommitted(instanceId),
|
|
4561
4666
|
res)) : notReady(args);
|
|
4562
|
-
}, [ drainCommitted ]),
|
|
4667
|
+
}, [ drainCommitted ]), previewFieldFor = useCallback((instanceId, args) => {
|
|
4668
|
+
reportsRef.current.get(instanceId)?.previewField(args);
|
|
4669
|
+
}, []), discardFieldPreviewFor = useCallback((instanceId, target) => {
|
|
4670
|
+
reportsRef.current.get(instanceId)?.discardFieldPreview(target);
|
|
4671
|
+
}, []), drainEffectsFor = useCallback(async instanceId => {
|
|
4563
4672
|
await engine.drainEffects({
|
|
4564
4673
|
instanceId: instanceId
|
|
4565
4674
|
});
|
|
@@ -4629,6 +4738,8 @@ function WorkflowProvider(props) {
|
|
|
4629
4738
|
loading: loading,
|
|
4630
4739
|
fireActionFor: fireActionFor,
|
|
4631
4740
|
editFieldFor: editFieldFor,
|
|
4741
|
+
previewFieldFor: previewFieldFor,
|
|
4742
|
+
discardFieldPreviewFor: discardFieldPreviewFor,
|
|
4632
4743
|
drainEffectsFor: drainEffectsFor,
|
|
4633
4744
|
completeEffectFor: completeEffectFor,
|
|
4634
4745
|
engine: engine,
|
|
@@ -4636,7 +4747,7 @@ function WorkflowProvider(props) {
|
|
|
4636
4747
|
mappings: config.mappings,
|
|
4637
4748
|
mappingIssues: issues,
|
|
4638
4749
|
effectHandlers: engine.effectHandlers
|
|
4639
|
-
}), [ register, unregister, isDocResolved, byDocument, byInstance, requestInstance, releaseInstance, seedInstance, openStartDialog, closeStartDialog, startRequest, loading, fireActionFor, editFieldFor, drainEffectsFor, completeEffectFor, engine, binding, config.mappings, issues ]);
|
|
4750
|
+
}), [ register, unregister, isDocResolved, byDocument, byInstance, requestInstance, releaseInstance, seedInstance, openStartDialog, closeStartDialog, startRequest, loading, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding, config.mappings, issues ]);
|
|
4640
4751
|
/* @__PURE__ */
|
|
4641
4752
|
return jsxs(WorkflowContext.Provider, {
|
|
4642
4753
|
value: value,
|