@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.cjs
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: !0
|
|
5
5
|
});
|
|
6
6
|
|
|
7
|
-
var workflowEngine = require("@sanity/workflow-engine"), jsxRuntime = require("react/jsx-runtime"), ui = require("@sanity/ui"), react = require("react"), structure = require("sanity/structure"), Add = require("@sanity/icons/Add"), csm = require("@sanity/client/csm"), ChevronRight = require("@sanity/icons/ChevronRight"), Calendar = require("@sanity/icons/Calendar"), Close = require("@sanity/icons/Close"), User = require("@sanity/icons/User"), Checkmark = require("@sanity/icons/Checkmark"), Empty$1 = require("@sanity/icons/Empty"), sanity = require("sanity"), ErrorOutline = require("@sanity/icons/ErrorOutline"), WarningOutline = require("@sanity/icons/WarningOutline"), CheckmarkCircle = require("@sanity/icons/CheckmarkCircle"), Circle = require("@sanity/icons/Circle"), CloseCircle = require("@sanity/icons/CloseCircle"), RemoveCircle = require("@sanity/icons/RemoveCircle"), Clock = require("@sanity/icons/Clock"), Edit = require("@sanity/icons/Edit"), content = require("@sanity/util/content"), router = require("sanity/router"), Launch = require("@sanity/icons/Launch"), InfoOutline = require("@sanity/icons/InfoOutline"), Search = require("@sanity/icons/Search"), workflowStudio = require("@sanity/workflow-studio"), ChevronDown = require("@sanity/icons/ChevronDown"), SplitVertical = require("@sanity/icons/SplitVertical");
|
|
7
|
+
var workflowEngine = require("@sanity/workflow-engine"), jsxRuntime = require("react/jsx-runtime"), ui = require("@sanity/ui"), react = require("react"), structure = require("sanity/structure"), Add = require("@sanity/icons/Add"), csm = require("@sanity/client/csm"), ChevronRight = require("@sanity/icons/ChevronRight"), Calendar = require("@sanity/icons/Calendar"), Close = require("@sanity/icons/Close"), User = require("@sanity/icons/User"), Checkmark = require("@sanity/icons/Checkmark"), Empty$1 = require("@sanity/icons/Empty"), sanity = require("sanity"), ErrorOutline = require("@sanity/icons/ErrorOutline"), WarningOutline = require("@sanity/icons/WarningOutline"), CheckmarkCircle = require("@sanity/icons/CheckmarkCircle"), Circle = require("@sanity/icons/Circle"), CloseCircle = require("@sanity/icons/CloseCircle"), RemoveCircle = require("@sanity/icons/RemoveCircle"), Clock = require("@sanity/icons/Clock"), Bolt = require("@sanity/icons/Bolt"), Edit = require("@sanity/icons/Edit"), content = require("@sanity/util/content"), router = require("sanity/router"), Launch = require("@sanity/icons/Launch"), InfoOutline = require("@sanity/icons/InfoOutline"), Search = require("@sanity/icons/Search"), workflowStudio = require("@sanity/workflow-studio"), ChevronDown = require("@sanity/icons/ChevronDown"), SplitVertical = require("@sanity/icons/SplitVertical");
|
|
8
8
|
|
|
9
9
|
function mappingForDocType(mappings, docType) {
|
|
10
10
|
return mappings.find(m => m.docType === docType);
|
|
@@ -314,7 +314,8 @@ const activityNotActiveSentence = {
|
|
|
314
314
|
"instance-completed": () => "This workflow is already complete.",
|
|
315
315
|
"mutation-guard-denied": () => "An earlier step is holding this document.",
|
|
316
316
|
"requirements-unmet": () => "This step isn't ready yet — a required condition hasn't been met.",
|
|
317
|
-
"stage-terminal": () => "This stage is finished."
|
|
317
|
+
"stage-terminal": () => "This stage is finished.",
|
|
318
|
+
"subject-permission-denied": () => "You don't have permission to change the document this step works on."
|
|
318
319
|
};
|
|
319
320
|
|
|
320
321
|
function describeDisabledReason(reason) {
|
|
@@ -826,20 +827,9 @@ function UserAvatarGroup({ids: ids}) {
|
|
|
826
827
|
});
|
|
827
828
|
}
|
|
828
829
|
|
|
829
|
-
function TodoCheckbox({
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
"aria-label": "Saving…",
|
|
833
|
-
justify: "center",
|
|
834
|
-
style: {
|
|
835
|
-
width: 17,
|
|
836
|
-
height: 17
|
|
837
|
-
},
|
|
838
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {
|
|
839
|
-
muted: !0,
|
|
840
|
-
size: 1
|
|
841
|
-
})
|
|
842
|
-
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Checkbox, {
|
|
830
|
+
function TodoCheckbox({checked: checked, canClick: canClick, onToggle: onToggle}) {
|
|
831
|
+
/* @__PURE__ */
|
|
832
|
+
return jsxRuntime.jsx(ui.Checkbox, {
|
|
843
833
|
checked: checked,
|
|
844
834
|
disabled: !canClick,
|
|
845
835
|
onChange: onToggle,
|
|
@@ -982,10 +972,10 @@ function AssigneeControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
|
982
972
|
}) : chip;
|
|
983
973
|
}
|
|
984
974
|
|
|
985
|
-
function AddItemControl({
|
|
975
|
+
function AddItemControl({onAdd: onAdd, button: button, busy: busy}) {
|
|
986
976
|
const [open, setOpen] = react.useState(!1), [label, setLabel] = react.useState(""), submit = () => {
|
|
987
977
|
const trimmed = label.trim();
|
|
988
|
-
trimmed
|
|
978
|
+
!trimmed || busy || (setOpen(!1), setLabel(""), onAdd(trimmed));
|
|
989
979
|
};
|
|
990
980
|
/* @__PURE__ */
|
|
991
981
|
return jsxRuntime.jsx(DismissablePopover, {
|
|
@@ -1017,13 +1007,11 @@ function AddItemControl({busy: busy, onAdd: onAdd, button: button}) {
|
|
|
1017
1007
|
open: open,
|
|
1018
1008
|
placement: "bottom-start",
|
|
1019
1009
|
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1020
|
-
onClick: () =>
|
|
1010
|
+
onClick: () => setOpen(v => !v),
|
|
1021
1011
|
style: {
|
|
1022
1012
|
display: "inline-flex"
|
|
1023
1013
|
},
|
|
1024
|
-
children:
|
|
1025
|
-
muted: !0
|
|
1026
|
-
}) : button
|
|
1014
|
+
children: button
|
|
1027
1015
|
})
|
|
1028
1016
|
});
|
|
1029
1017
|
}
|
|
@@ -1052,7 +1040,7 @@ function rowInteractivity(row) {
|
|
|
1052
1040
|
};
|
|
1053
1041
|
}
|
|
1054
1042
|
|
|
1055
|
-
function ActionItemRowView({row: row,
|
|
1043
|
+
function ActionItemRowView({row: row, showBreadcrumb: showBreadcrumb, onToggle: onToggle, onPatch: onPatch}) {
|
|
1056
1044
|
const {canClick: canClick, hint: hint} = rowInteractivity(row), editable = row.editTarget !== void 0, body = /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
1057
1045
|
align: "center",
|
|
1058
1046
|
gap: 2,
|
|
@@ -1063,7 +1051,6 @@ function ActionItemRowView({row: row, busy: busy, showBreadcrumb: showBreadcrumb
|
|
|
1063
1051
|
flexShrink: 0
|
|
1064
1052
|
},
|
|
1065
1053
|
children: /* @__PURE__ */ jsxRuntime.jsx(TodoCheckbox, {
|
|
1066
|
-
busy: busy,
|
|
1067
1054
|
canClick: canClick,
|
|
1068
1055
|
checked: isTodoDone(row.item),
|
|
1069
1056
|
onToggle: onToggle
|
|
@@ -1134,12 +1121,10 @@ function RowBreadcrumb({row: row}) {
|
|
|
1134
1121
|
});
|
|
1135
1122
|
}
|
|
1136
1123
|
|
|
1137
|
-
const ADD_KEY = "__add__";
|
|
1138
|
-
|
|
1139
1124
|
function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1, identity: identity, activityFilter: activityFilter, variant: variant = "section"}) {
|
|
1140
|
-
const {instance: instance} = entry, {editFieldFor: editFieldFor, fireActionFor: fireActionFor} = useWorkflowContext(), toast = ui.useToast(), [
|
|
1141
|
-
if (!
|
|
1142
|
-
|
|
1125
|
+
const {instance: instance} = entry, {editFieldFor: editFieldFor, fireActionFor: fireActionFor} = useWorkflowContext(), toast = ui.useToast(), [busy, setBusy] = react.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 => {
|
|
1126
|
+
if (!busy) {
|
|
1127
|
+
setBusy(!0);
|
|
1143
1128
|
try {
|
|
1144
1129
|
await op();
|
|
1145
1130
|
} catch (err) {
|
|
@@ -1149,7 +1134,7 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1149
1134
|
description: describeError(err)
|
|
1150
1135
|
});
|
|
1151
1136
|
} finally {
|
|
1152
|
-
|
|
1137
|
+
setBusy(!1);
|
|
1153
1138
|
}
|
|
1154
1139
|
}
|
|
1155
1140
|
}, patchItem = (row, patch) => {
|
|
@@ -1158,7 +1143,7 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1158
1143
|
...it,
|
|
1159
1144
|
...patch
|
|
1160
1145
|
} : it);
|
|
1161
|
-
return run(
|
|
1146
|
+
return run(() => editFieldFor(instance._id, {
|
|
1162
1147
|
target: target,
|
|
1163
1148
|
mode: "set",
|
|
1164
1149
|
value: next
|
|
@@ -1168,11 +1153,11 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1168
1153
|
status: toggledTodoStatus(row.item)
|
|
1169
1154
|
});
|
|
1170
1155
|
const tick = row.tick;
|
|
1171
|
-
return tick && tick.actionEval.allowed && !isTodoDone(row.item) ? run(
|
|
1156
|
+
return tick && tick.actionEval.allowed && !isTodoDone(row.item) ? run(() => fireActionFor(instance._id, {
|
|
1172
1157
|
activity: tick.activity,
|
|
1173
1158
|
action: tick.actionEval.action.name
|
|
1174
1159
|
})) : Promise.resolve();
|
|
1175
|
-
}, addItem = label => appendTarget ? run(
|
|
1160
|
+
}, addItem = label => appendTarget ? run(() => editFieldFor(instance._id, {
|
|
1176
1161
|
target: appendTarget,
|
|
1177
1162
|
mode: "append",
|
|
1178
1163
|
value: {
|
|
@@ -1182,7 +1167,6 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1182
1167
|
})) : Promise.resolve();
|
|
1183
1168
|
if (rows.length === 0 && !appendTarget) return null;
|
|
1184
1169
|
const rowKey = row => `${row.scope}:${row.activityName ?? ""}:${row.fieldName}:${row.item._key}`, rowProps = row => ({
|
|
1185
|
-
busy: busyKey === row.item._key,
|
|
1186
1170
|
onPatch: patch => {
|
|
1187
1171
|
patchItem(row, patch);
|
|
1188
1172
|
},
|
|
@@ -1201,7 +1185,7 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1201
1185
|
}, rowKey(row)))
|
|
1202
1186
|
}), appendTarget ? /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
1203
1187
|
children: /* @__PURE__ */ jsxRuntime.jsx(AddItemControl, {
|
|
1204
|
-
busy:
|
|
1188
|
+
busy: busy,
|
|
1205
1189
|
button: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
1206
1190
|
fontSize: 1,
|
|
1207
1191
|
icon: Add.AddIcon,
|
|
@@ -1227,7 +1211,7 @@ function ActionItemsList({entry: entry, assignedToMeOnly: assignedToMeOnly = !1,
|
|
|
1227
1211
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1228
1212
|
paddingRight: 2,
|
|
1229
1213
|
children: /* @__PURE__ */ jsxRuntime.jsx(AddItemControl, {
|
|
1230
|
-
busy:
|
|
1214
|
+
busy: busy,
|
|
1231
1215
|
button: /* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
1232
1216
|
text: "Add action item",
|
|
1233
1217
|
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
@@ -1354,7 +1338,7 @@ function groupEditableByActivity(fields) {
|
|
|
1354
1338
|
}
|
|
1355
1339
|
|
|
1356
1340
|
function deriveActivityPresentation(args) {
|
|
1357
|
-
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(workflowEngine.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 => {
|
|
1341
|
+
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(workflowEngine.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 => {
|
|
1358
1342
|
const writes = writtenFieldNames(a.action);
|
|
1359
1343
|
return !(writes.length > 0 && writes.every(name => editableNames.has(name)));
|
|
1360
1344
|
}), blockedReason = status === "active" && actions.length > 0 && actions.every(a => !a.allowed) ? actions.find(a => a.disabledReason)?.disabledReason : void 0, ticks = tickActionNames({
|
|
@@ -1631,8 +1615,8 @@ function activityStateOf(instance, activityName) {
|
|
|
1631
1615
|
return workflowEngine.findCurrentActivityEntry(instance, activityName)?.fields ?? [];
|
|
1632
1616
|
}
|
|
1633
1617
|
|
|
1634
|
-
function assigneeEntriesOf(state,
|
|
1635
|
-
return state.filter(s => s._type === "assignees" && (s.value.length > 0 || s.name
|
|
1618
|
+
function assigneeEntriesOf(state, assignFields) {
|
|
1619
|
+
return state.filter(s => s._type === "assignees" && (s.value.length > 0 || assignFields.has(s.name)));
|
|
1636
1620
|
}
|
|
1637
1621
|
|
|
1638
1622
|
function hasActivityActionItems(entry, activityName) {
|
|
@@ -1648,19 +1632,39 @@ function deriveActivityDetail(args) {
|
|
|
1648
1632
|
state: state,
|
|
1649
1633
|
workflowFields: instance.fields ?? [],
|
|
1650
1634
|
editableFields: activityEditables
|
|
1651
|
-
}),
|
|
1635
|
+
}), assignFields = new Map(activityEditables.filter(f => f.type === "assignees").map(f => [ f.name, f ]));
|
|
1652
1636
|
return {
|
|
1653
1637
|
activityEval: activityEval,
|
|
1654
1638
|
state: state,
|
|
1655
1639
|
presentation: presentation,
|
|
1656
1640
|
title: activityEval.activity.title ?? activityEval.activity.name,
|
|
1657
|
-
|
|
1658
|
-
assigneeEntries: assigneeEntriesOf(state,
|
|
1641
|
+
assignFields: assignFields,
|
|
1642
|
+
assigneeEntries: assigneeEntriesOf(state, assignFields),
|
|
1659
1643
|
hasActionItems: hasActivityActionItems(entry, activityName),
|
|
1660
1644
|
hasActions: presentation.manualTarget !== void 0 || presentation.hasVisibleActions
|
|
1661
1645
|
};
|
|
1662
1646
|
}
|
|
1663
1647
|
|
|
1648
|
+
function stageTitle(definition, stageName) {
|
|
1649
|
+
return definition?.stages.find(stage => stage.name === stageName)?.title ?? stageName;
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
function isHotField(evaluation, fieldName) {
|
|
1653
|
+
return (insightFor(evaluation, fieldName)?.involvedIn.length ?? 0) > 0;
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
function advanceTargetTitle(evaluation, fieldName) {
|
|
1657
|
+
if (evaluation === void 0) return;
|
|
1658
|
+
const involved = new Set((insightFor(evaluation, fieldName)?.involvedIn ?? []).flatMap(site => site.kind === "transition" ? [ site.transition ] : []));
|
|
1659
|
+
if (involved.size === 0) return;
|
|
1660
|
+
const halting = evaluation.currentStage.transitions.find(t => t.filterSatisfied || t.unevaluable);
|
|
1661
|
+
if (!(halting === void 0 || !halting.filterSatisfied) && involved.has(halting.transition.name)) return stageTitle(evaluation.definition, halting.transition.to);
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
function insightFor(evaluation, fieldName) {
|
|
1665
|
+
return evaluation?.fieldInsights.find(insight => insight.field === fieldName);
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1664
1668
|
function noteRow(args) {
|
|
1665
1669
|
return {
|
|
1666
1670
|
_key: content.randomKey(),
|
|
@@ -1681,6 +1685,14 @@ function FieldInput$1({field: field, value: value, onChange: onChange, onEnter:
|
|
|
1681
1685
|
onChange: e => onChange(e.currentTarget.checked)
|
|
1682
1686
|
});
|
|
1683
1687
|
|
|
1688
|
+
case "date":
|
|
1689
|
+
/* @__PURE__ */
|
|
1690
|
+
return jsxRuntime.jsx(ui.TextInput, {
|
|
1691
|
+
onChange: e => onChange(e.currentTarget.value === "" ? null : e.currentTarget.value),
|
|
1692
|
+
type: "date",
|
|
1693
|
+
value: typeof value == "string" ? value : ""
|
|
1694
|
+
});
|
|
1695
|
+
|
|
1684
1696
|
case "datetime":
|
|
1685
1697
|
/* @__PURE__ */
|
|
1686
1698
|
return jsxRuntime.jsx(ui.TextInput, {
|
|
@@ -1698,6 +1710,14 @@ function FieldInput$1({field: field, value: value, onChange: onChange, onEnter:
|
|
|
1698
1710
|
value: value == null ? "" : String(value)
|
|
1699
1711
|
});
|
|
1700
1712
|
|
|
1713
|
+
case "text":
|
|
1714
|
+
/* @__PURE__ */
|
|
1715
|
+
return jsxRuntime.jsx(ui.TextArea, {
|
|
1716
|
+
onChange: e => onChange(e.currentTarget.value),
|
|
1717
|
+
rows: 3,
|
|
1718
|
+
value: value == null ? "" : String(value)
|
|
1719
|
+
});
|
|
1720
|
+
|
|
1701
1721
|
default:
|
|
1702
1722
|
/* @__PURE__ */
|
|
1703
1723
|
return jsxRuntime.jsx(ui.TextInput, {
|
|
@@ -2077,7 +2097,7 @@ function ValueDisplay({field: field, value: value}) {
|
|
|
2077
2097
|
}
|
|
2078
2098
|
|
|
2079
2099
|
function EditableFieldControl({instanceId: instanceId, field: field, hideLabel: hideLabel}) {
|
|
2080
|
-
const {editFieldFor: editFieldFor, byInstance: byInstance} = useWorkflowContext(), me = sanity.useCurrentUser(),
|
|
2100
|
+
const {editFieldFor: editFieldFor, previewFieldFor: previewFieldFor, discardFieldPreviewFor: discardFieldPreviewFor, byInstance: byInstance} = useWorkflowContext(), me = sanity.useCurrentUser(), held = byInstance.get(instanceId), entry = held ? workflowEngine.resolveFieldEntry(held.instance, field) : void 0, evaluation = held?.evaluation, target = editTargetOf(field), advanceTo = advanceTargetTitle(evaluation, field.name);
|
|
2081
2101
|
/* @__PURE__ */
|
|
2082
2102
|
return jsxRuntime.jsx(EditableField, {
|
|
2083
2103
|
field: field,
|
|
@@ -2087,17 +2107,27 @@ function EditableFieldControl({instanceId: instanceId, field: field, hideLabel:
|
|
|
2087
2107
|
...hideLabel === void 0 ? {} : {
|
|
2088
2108
|
hideLabel: hideLabel
|
|
2089
2109
|
},
|
|
2110
|
+
hot: isHotField(evaluation, field.name),
|
|
2111
|
+
...advanceTo === void 0 ? {} : {
|
|
2112
|
+
advanceTo: advanceTo
|
|
2113
|
+
},
|
|
2090
2114
|
onSave: value => editFieldFor(instanceId, {
|
|
2091
|
-
target:
|
|
2115
|
+
target: target,
|
|
2092
2116
|
mode: "set",
|
|
2093
2117
|
value: value
|
|
2094
2118
|
}).then(() => {}),
|
|
2119
|
+
onPreview: value => previewFieldFor(instanceId, {
|
|
2120
|
+
target: target,
|
|
2121
|
+
mode: "set",
|
|
2122
|
+
value: value
|
|
2123
|
+
}),
|
|
2124
|
+
onDiscardPreview: () => discardFieldPreviewFor(instanceId, target),
|
|
2095
2125
|
onUnset: () => editFieldFor(instanceId, {
|
|
2096
|
-
target:
|
|
2126
|
+
target: target,
|
|
2097
2127
|
mode: "unset"
|
|
2098
2128
|
}).then(() => {}),
|
|
2099
2129
|
onAppend: body => editFieldFor(instanceId, {
|
|
2100
|
-
target:
|
|
2130
|
+
target: target,
|
|
2101
2131
|
mode: "append",
|
|
2102
2132
|
value: noteRow({
|
|
2103
2133
|
body: body,
|
|
@@ -2164,21 +2194,28 @@ function FieldLabel({label: label, hide: hide}) {
|
|
|
2164
2194
|
});
|
|
2165
2195
|
}
|
|
2166
2196
|
|
|
2167
|
-
function
|
|
2168
|
-
const toast = ui.useToast()
|
|
2197
|
+
function useSaveFailureToast() {
|
|
2198
|
+
const toast = ui.useToast();
|
|
2199
|
+
return err => {
|
|
2200
|
+
console.error("[workflow-studio-plugin] field save failed:", err), toast.push({
|
|
2201
|
+
status: "error",
|
|
2202
|
+
title: "Saving failed",
|
|
2203
|
+
description: describeError(err)
|
|
2204
|
+
});
|
|
2205
|
+
};
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
function useSaveField() {
|
|
2209
|
+
const reportFailure = useSaveFailureToast(), [saving, setSaving] = react.useState(!1);
|
|
2169
2210
|
return {
|
|
2170
2211
|
saving: saving,
|
|
2171
2212
|
save: async commit => {
|
|
2172
2213
|
if (!saving) {
|
|
2173
2214
|
setSaving(!0);
|
|
2174
2215
|
try {
|
|
2175
|
-
await commit()
|
|
2216
|
+
await commit();
|
|
2176
2217
|
} catch (err) {
|
|
2177
|
-
|
|
2178
|
-
status: "error",
|
|
2179
|
-
title: "Saving failed",
|
|
2180
|
-
description: describeError(err)
|
|
2181
|
-
});
|
|
2218
|
+
reportFailure(err);
|
|
2182
2219
|
} finally {
|
|
2183
2220
|
setSaving(!1);
|
|
2184
2221
|
}
|
|
@@ -2188,7 +2225,7 @@ function useSaveField(args) {
|
|
|
2188
2225
|
}
|
|
2189
2226
|
|
|
2190
2227
|
function ActorField({field: field, label: label, hideLabel: hideLabel, onSave: onSave, onUnset: onUnset}) {
|
|
2191
|
-
const [open, setOpen] = react.useState(!1), {saving: saving, save: save} = useSaveField(
|
|
2228
|
+
const [open, setOpen] = react.useState(!1), {saving: saving, save: save} = useSaveField(), cur = field.value, pick = member => {
|
|
2192
2229
|
setOpen(!1), !saving && (member && member.id !== cur?.id ? save(() => onSave(personActor(member))) : onUnset !== void 0 && cur && save(onUnset));
|
|
2193
2230
|
}, value = cur ? /* @__PURE__ */ jsxRuntime.jsx(ActorName, {
|
|
2194
2231
|
id: cur.id
|
|
@@ -2271,10 +2308,14 @@ function ArrayField({field: field, label: label, hideLabel: hideLabel}) {
|
|
|
2271
2308
|
}
|
|
2272
2309
|
|
|
2273
2310
|
function NotesField({field: field, label: label, hideLabel: hideLabel, onAppend: onAppend}) {
|
|
2274
|
-
const [body, setBody] = react.useState(""), {saving: saving, save: save} = useSaveField({
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2311
|
+
const [body, setBody] = react.useState(""), {saving: saving, save: save} = useSaveField(), rows = arrayRowsOf(field.value), trimmed = body.trim(), add = () => {
|
|
2312
|
+
saving || trimmed === "" || (setBody(""), save(async () => {
|
|
2313
|
+
try {
|
|
2314
|
+
await onAppend(trimmed);
|
|
2315
|
+
} catch (err) {
|
|
2316
|
+
throw setBody(trimmed), err;
|
|
2317
|
+
}
|
|
2318
|
+
}));
|
|
2278
2319
|
};
|
|
2279
2320
|
/* @__PURE__ */
|
|
2280
2321
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
@@ -2293,7 +2334,6 @@ function NotesField({field: field, label: label, hideLabel: hideLabel, onAppend:
|
|
|
2293
2334
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
2294
2335
|
flex: 1,
|
|
2295
2336
|
children: /* @__PURE__ */ jsxRuntime.jsx(ui.TextArea, {
|
|
2296
|
-
disabled: saving,
|
|
2297
2337
|
fontSize: 1,
|
|
2298
2338
|
onChange: e => setBody(e.currentTarget.value),
|
|
2299
2339
|
placeholder: "Add an entry…",
|
|
@@ -2302,9 +2342,8 @@ function NotesField({field: field, label: label, hideLabel: hideLabel, onAppend:
|
|
|
2302
2342
|
})
|
|
2303
2343
|
}),
|
|
2304
2344
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
2305
|
-
disabled:
|
|
2345
|
+
disabled: trimmed === "",
|
|
2306
2346
|
fontSize: 1,
|
|
2307
|
-
loading: saving,
|
|
2308
2347
|
onClick: add,
|
|
2309
2348
|
padding: 2,
|
|
2310
2349
|
text: "Add",
|
|
@@ -2315,7 +2354,7 @@ function NotesField({field: field, label: label, hideLabel: hideLabel, onAppend:
|
|
|
2315
2354
|
}
|
|
2316
2355
|
|
|
2317
2356
|
function BooleanSwitchField({field: field, label: label, hideLabel: hideLabel, onSave: onSave}) {
|
|
2318
|
-
const {
|
|
2357
|
+
const {save: save} = useSaveField(), committed = field.value === !0;
|
|
2319
2358
|
/* @__PURE__ */
|
|
2320
2359
|
return jsxRuntime.jsxs(ui.Flex, {
|
|
2321
2360
|
align: "center",
|
|
@@ -2327,68 +2366,56 @@ function BooleanSwitchField({field: field, label: label, hideLabel: hideLabel, o
|
|
|
2327
2366
|
label: label
|
|
2328
2367
|
}),
|
|
2329
2368
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, {
|
|
2330
|
-
checked:
|
|
2331
|
-
disabled: saving,
|
|
2369
|
+
checked: committed,
|
|
2332
2370
|
onChange: () => {
|
|
2333
|
-
|
|
2334
|
-
setOptimistic(next), save(() => onSave(next)).finally(() => setOptimistic(null));
|
|
2371
|
+
save(() => onSave(!committed));
|
|
2335
2372
|
}
|
|
2336
2373
|
}) ]
|
|
2337
2374
|
});
|
|
2338
2375
|
}
|
|
2339
2376
|
|
|
2340
|
-
function
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2377
|
+
function sameValue(a, b) {
|
|
2378
|
+
return (a ?? void 0) === (b ?? void 0);
|
|
2379
|
+
}
|
|
2380
|
+
|
|
2381
|
+
function GenericField({field: field, label: label, hideLabel: hideLabel, onSave: onSave, onPreview: onPreview, onDiscardPreview: onDiscardPreview}) {
|
|
2382
|
+
const reportFailure = useSaveFailureToast(), [draft, setDraft] = react.useState(field.value), [baseline, setBaseline] = react.useState(field.value), dirty = !sameValue(draft, baseline), focused = react.useRef(!1), previewed = react.useRef(!1), commit = () => {
|
|
2383
|
+
if (!dirty) return;
|
|
2384
|
+
const value = draft, prev = baseline;
|
|
2385
|
+
setBaseline(value), previewed.current = !1, onSave(value).catch(err => {
|
|
2386
|
+
reportFailure(err), setBaseline(current => sameValue(current, value) ? prev : current),
|
|
2387
|
+
setDraft(current => sameValue(current, value) ? prev : current);
|
|
2388
|
+
});
|
|
2389
|
+
}, settle = () => {
|
|
2390
|
+
dirty ? commit() : previewed.current && (previewed.current = !1, onDiscardPreview?.());
|
|
2391
|
+
}, settleRef = react.useRef(settle);
|
|
2392
|
+
settleRef.current = settle, react.useEffect(() => () => settleRef.current(), []);
|
|
2393
|
+
const adopted = react.useRef(field.value);
|
|
2344
2394
|
return react.useEffect(() => {
|
|
2345
|
-
|
|
2346
|
-
|
|
2395
|
+
sameValue(adopted.current, field.value) || focused.current || dirty || (adopted.current = field.value,
|
|
2396
|
+
setBaseline(field.value), setDraft(field.value));
|
|
2397
|
+
}, [ field.value, dirty ]), field.editable ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
2347
2398
|
gap: 2,
|
|
2348
2399
|
children: [
|
|
2349
2400
|
/* @__PURE__ */ jsxRuntime.jsx(FieldLabel, {
|
|
2350
2401
|
hide: hideLabel,
|
|
2351
2402
|
label: label
|
|
2352
2403
|
}),
|
|
2353
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
value
|
|
2364
|
-
}
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
2369
|
-
"aria-label": "Save",
|
|
2370
|
-
fontSize: 1,
|
|
2371
|
-
icon: Checkmark.CheckmarkIcon,
|
|
2372
|
-
loading: saving,
|
|
2373
|
-
onClick: () => save(() => onSave(draft)),
|
|
2374
|
-
padding: 2,
|
|
2375
|
-
tone: "primary"
|
|
2376
|
-
})
|
|
2377
|
-
}),
|
|
2378
|
-
/* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
2379
|
-
text: "Cancel",
|
|
2380
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
2381
|
-
"aria-label": "Cancel",
|
|
2382
|
-
disabled: saving,
|
|
2383
|
-
fontSize: 1,
|
|
2384
|
-
icon: Close.CloseIcon,
|
|
2385
|
-
mode: "bleed",
|
|
2386
|
-
onClick: () => {
|
|
2387
|
-
setDraft(field.value), setEditing(!1);
|
|
2388
|
-
},
|
|
2389
|
-
padding: 2
|
|
2390
|
-
})
|
|
2391
|
-
}) ]
|
|
2404
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
2405
|
+
onBlur: () => {
|
|
2406
|
+
focused.current = !1, settle();
|
|
2407
|
+
},
|
|
2408
|
+
onFocus: () => {
|
|
2409
|
+
focused.current = !0;
|
|
2410
|
+
},
|
|
2411
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(FieldInput$1, {
|
|
2412
|
+
field: field,
|
|
2413
|
+
onChange: value => {
|
|
2414
|
+
setDraft(value), previewed.current = !0, onPreview?.(value);
|
|
2415
|
+
},
|
|
2416
|
+
onEnter: commit,
|
|
2417
|
+
value: draft
|
|
2418
|
+
})
|
|
2392
2419
|
}) ]
|
|
2393
2420
|
}) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
2394
2421
|
align: "center",
|
|
@@ -2398,14 +2425,7 @@ function GenericField({field: field, label: label, hideLabel: hideLabel, onSave:
|
|
|
2398
2425
|
/* @__PURE__ */ jsxRuntime.jsx(FieldLabel, {
|
|
2399
2426
|
hide: hideLabel,
|
|
2400
2427
|
label: label
|
|
2401
|
-
}),
|
|
2402
|
-
hint: "Edit",
|
|
2403
|
-
onClick: () => setEditing(!0),
|
|
2404
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ValueDisplay, {
|
|
2405
|
-
field: field,
|
|
2406
|
-
value: field.value
|
|
2407
|
-
})
|
|
2408
|
-
}) :
|
|
2428
|
+
}),
|
|
2409
2429
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
2410
2430
|
align: "center",
|
|
2411
2431
|
gap: 2,
|
|
@@ -2422,13 +2442,33 @@ function GenericField({field: field, label: label, hideLabel: hideLabel, onSave:
|
|
|
2422
2442
|
});
|
|
2423
2443
|
}
|
|
2424
2444
|
|
|
2425
|
-
function
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2445
|
+
function HotFieldHint() {
|
|
2446
|
+
/* @__PURE__ */
|
|
2447
|
+
return jsxRuntime.jsx(HoverHint, {
|
|
2448
|
+
text: "Editing this can move the workflow",
|
|
2449
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
2450
|
+
"aria-label": "Editing this can move the workflow",
|
|
2451
|
+
muted: !0,
|
|
2452
|
+
size: 1,
|
|
2453
|
+
style: {
|
|
2454
|
+
cursor: "help"
|
|
2455
|
+
},
|
|
2456
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Bolt.BoltIcon, {})
|
|
2457
|
+
})
|
|
2458
|
+
});
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
function AdvanceHint({stageTitle: stageTitle2}) {
|
|
2462
|
+
/* @__PURE__ */
|
|
2463
|
+
return jsxRuntime.jsxs(ui.Text, {
|
|
2464
|
+
muted: !0,
|
|
2465
|
+
size: 1,
|
|
2466
|
+
children: [ "Committing will advance to ", stageTitle2 ]
|
|
2467
|
+
});
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
function fieldArm({arm: arm, entry: entry, onUnset: onUnset, onAppend: onAppend, onPreview: onPreview, onDiscardPreview: onDiscardPreview}) {
|
|
2471
|
+
const {field: field} = arm;
|
|
2432
2472
|
return field.type === "actor" ? /* @__PURE__ */ jsxRuntime.jsx(ActorField, {
|
|
2433
2473
|
...arm,
|
|
2434
2474
|
...onUnset === void 0 ? {} : {
|
|
@@ -2444,7 +2484,45 @@ function EditableField({field: field, entry: entry, onSave: onSave, onUnset: onU
|
|
|
2444
2484
|
}) : field.type === "boolean" && field.editable ? /* @__PURE__ */ jsxRuntime.jsx(BooleanSwitchField, {
|
|
2445
2485
|
...arm
|
|
2446
2486
|
}) : /* @__PURE__ */ jsxRuntime.jsx(GenericField, {
|
|
2447
|
-
...arm
|
|
2487
|
+
...arm,
|
|
2488
|
+
...onPreview === void 0 ? {} : {
|
|
2489
|
+
onPreview: onPreview
|
|
2490
|
+
},
|
|
2491
|
+
...onDiscardPreview === void 0 ? {} : {
|
|
2492
|
+
onDiscardPreview: onDiscardPreview
|
|
2493
|
+
}
|
|
2494
|
+
});
|
|
2495
|
+
}
|
|
2496
|
+
|
|
2497
|
+
function EditableField({field: field, entry: entry, onSave: onSave, onUnset: onUnset, onAppend: onAppend, onPreview: onPreview, onDiscardPreview: onDiscardPreview, hot: hot = !1, advanceTo: advanceTo, hideLabel: hideLabel = !1}) {
|
|
2498
|
+
const label = field.title ?? field.name, content2 = fieldArm({
|
|
2499
|
+
arm: {
|
|
2500
|
+
field: field,
|
|
2501
|
+
label: label,
|
|
2502
|
+
hideLabel: hideLabel,
|
|
2503
|
+
onSave: onSave
|
|
2504
|
+
},
|
|
2505
|
+
entry: entry,
|
|
2506
|
+
onUnset: onUnset,
|
|
2507
|
+
onAppend: onAppend,
|
|
2508
|
+
onPreview: onPreview,
|
|
2509
|
+
onDiscardPreview: onDiscardPreview
|
|
2510
|
+
}), decorated = field.editable;
|
|
2511
|
+
/* @__PURE__ */
|
|
2512
|
+
return jsxRuntime.jsxs(ui.Stack, {
|
|
2513
|
+
gap: 2,
|
|
2514
|
+
children: [
|
|
2515
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
2516
|
+
align: "center",
|
|
2517
|
+
gap: 2,
|
|
2518
|
+
children: [
|
|
2519
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
2520
|
+
flex: 1,
|
|
2521
|
+
children: content2
|
|
2522
|
+
}), decorated && hot ? /* @__PURE__ */ jsxRuntime.jsx(HotFieldHint, {}) : null ]
|
|
2523
|
+
}), decorated && advanceTo !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(AdvanceHint, {
|
|
2524
|
+
stageTitle: advanceTo
|
|
2525
|
+
}) : null ]
|
|
2448
2526
|
});
|
|
2449
2527
|
}
|
|
2450
2528
|
|
|
@@ -3212,7 +3290,7 @@ function ActivityDetailDialog({entry: entry, activityName: activityName, breadcr
|
|
|
3212
3290
|
}
|
|
3213
3291
|
|
|
3214
3292
|
function DetailRows({detail: detail, entry: entry, instanceId: instanceId, activityName: activityName}) {
|
|
3215
|
-
const {activityEval: activityEval, presentation: presentation,
|
|
3293
|
+
const {activityEval: activityEval, presentation: presentation, assignFields: assignFields} = detail;
|
|
3216
3294
|
/* @__PURE__ */
|
|
3217
3295
|
return jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
3218
3296
|
children: [
|
|
@@ -3230,21 +3308,25 @@ function DetailRows({detail: detail, entry: entry, instanceId: instanceId, activ
|
|
|
3230
3308
|
children: ACTIVITY_STATUS_LABEL[activityEval.status]
|
|
3231
3309
|
}) ]
|
|
3232
3310
|
})
|
|
3233
|
-
}), detail.assigneeEntries.map(entry_ =>
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3311
|
+
}), detail.assigneeEntries.map(entry_ => {
|
|
3312
|
+
const assignField = assignFields.get(entry_.name);
|
|
3313
|
+
/* @__PURE__ */
|
|
3314
|
+
return jsxRuntime.jsx(LabeledRow, {
|
|
3315
|
+
label: entry_.title ?? "Assignees",
|
|
3316
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
3317
|
+
align: "center",
|
|
3318
|
+
gap: 2,
|
|
3319
|
+
wrap: "wrap",
|
|
3320
|
+
children: [
|
|
3321
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldValue, {
|
|
3322
|
+
field: entry_
|
|
3323
|
+
}), assignField ? /* @__PURE__ */ jsxRuntime.jsx(AssignActivityControl, {
|
|
3324
|
+
field: assignField,
|
|
3325
|
+
instanceId: instanceId
|
|
3326
|
+
}) : null ]
|
|
3327
|
+
})
|
|
3328
|
+
}, entry_._key);
|
|
3329
|
+
}), presentation.dates.map(d => /* @__PURE__ */ jsxRuntime.jsx(LabeledRow, {
|
|
3248
3330
|
label: d.title ?? d.name,
|
|
3249
3331
|
children: /* @__PURE__ */ jsxRuntime.jsx(BareValue, {
|
|
3250
3332
|
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
@@ -3407,10 +3489,6 @@ function useInstanceTitle(entry) {
|
|
|
3407
3489
|
return instanceTitle(entry.instance, definition);
|
|
3408
3490
|
}
|
|
3409
3491
|
|
|
3410
|
-
function stageTitle(instance, definition) {
|
|
3411
|
-
return definition?.stages.find(s => s.name === instance.currentStage)?.title ?? instance.currentStage;
|
|
3412
|
-
}
|
|
3413
|
-
|
|
3414
3492
|
function InstanceStatusBadge({instance: instance, definition: definition}) {
|
|
3415
3493
|
const state = workflowEngine.terminalState(instance);
|
|
3416
3494
|
return state === "aborted" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, {
|
|
@@ -3424,7 +3502,7 @@ function InstanceStatusBadge({instance: instance, definition: definition}) {
|
|
|
3424
3502
|
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, {
|
|
3425
3503
|
fontSize: 1,
|
|
3426
3504
|
tone: "primary",
|
|
3427
|
-
children: stageTitle(
|
|
3505
|
+
children: stageTitle(definition, instance.currentStage)
|
|
3428
3506
|
});
|
|
3429
3507
|
}
|
|
3430
3508
|
|
|
@@ -3464,7 +3542,6 @@ function StageGlyph(props) {
|
|
|
3464
3542
|
}
|
|
3465
3543
|
|
|
3466
3544
|
function CurrentStageIndicator({instance: instance, definition: definition}) {
|
|
3467
|
-
const stage = definition?.stages.find(s => s.name === instance.currentStage);
|
|
3468
3545
|
/* @__PURE__ */
|
|
3469
3546
|
return jsxRuntime.jsxs(ui.Flex, {
|
|
3470
3547
|
align: "center",
|
|
@@ -3477,7 +3554,7 @@ function CurrentStageIndicator({instance: instance, definition: definition}) {
|
|
|
3477
3554
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
3478
3555
|
size: 1,
|
|
3479
3556
|
weight: "medium",
|
|
3480
|
-
children:
|
|
3557
|
+
children: stageTitle(definition, instance.currentStage)
|
|
3481
3558
|
}) ]
|
|
3482
3559
|
});
|
|
3483
3560
|
}
|
|
@@ -3819,11 +3896,11 @@ function ActivityTab({instance: instance, definition: definition}) {
|
|
|
3819
3896
|
}
|
|
3820
3897
|
|
|
3821
3898
|
function makeTitleResolver(definition) {
|
|
3822
|
-
const
|
|
3899
|
+
const activities = (definition?.stages ?? []).flatMap(s => s.activities ?? []);
|
|
3823
3900
|
return {
|
|
3824
3901
|
action: (activityName, actionName) => activities.find(t => t.name === activityName)?.actions?.find(a => a.name === actionName)?.title ?? actionName,
|
|
3825
3902
|
activity: name => activities.find(t => t.name === name)?.title ?? name,
|
|
3826
|
-
stage: name =>
|
|
3903
|
+
stage: name => stageTitle(definition, name)
|
|
3827
3904
|
};
|
|
3828
3905
|
}
|
|
3829
3906
|
|
|
@@ -3903,8 +3980,7 @@ function InstanceMenuItem({entry: entry, selected: selected, onSelect: onSelect}
|
|
|
3903
3980
|
|
|
3904
3981
|
function instanceNotice(entry) {
|
|
3905
3982
|
const {instance: instance, committed: committed, evaluation: evaluation} = entry, state = workflowEngine.terminalState(instance);
|
|
3906
|
-
|
|
3907
|
-
return jsxRuntime.jsx(ui.Card, {
|
|
3983
|
+
return state !== "in-flight" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
3908
3984
|
border: !0,
|
|
3909
3985
|
padding: 3,
|
|
3910
3986
|
radius: 2,
|
|
@@ -3913,24 +3989,27 @@ function instanceNotice(entry) {
|
|
|
3913
3989
|
size: 1,
|
|
3914
3990
|
children: state === "aborted" ? "This workflow was aborted — no open tasks." : "This workflow is complete — no open tasks."
|
|
3915
3991
|
})
|
|
3916
|
-
})
|
|
3917
|
-
const freshness = evaluationFreshness({
|
|
3992
|
+
}) : evaluationFreshness({
|
|
3918
3993
|
committed: committed,
|
|
3919
3994
|
evaluation: evaluation
|
|
3920
|
-
})
|
|
3921
|
-
return freshness === "pending" ? /* @__PURE__ */ jsxRuntime.jsx(LoadingRow, {
|
|
3995
|
+
}) === "pending" ? /* @__PURE__ */ jsxRuntime.jsx(LoadingRow, {
|
|
3922
3996
|
label: "Evaluating…",
|
|
3923
3997
|
padding: 4
|
|
3924
|
-
}) : freshness === "stale" ? /* @__PURE__ */ jsxRuntime.jsx(LoadingRow, {
|
|
3925
|
-
label: "Updating…",
|
|
3926
|
-
padding: 4
|
|
3927
3998
|
}) : null;
|
|
3928
3999
|
}
|
|
3929
4000
|
|
|
4001
|
+
function evaluationSyncing(entry) {
|
|
4002
|
+
const {instance: instance, committed: committed, evaluation: evaluation} = entry;
|
|
4003
|
+
return workflowEngine.terminalState(instance) === "in-flight" && evaluationFreshness({
|
|
4004
|
+
committed: committed,
|
|
4005
|
+
evaluation: evaluation
|
|
4006
|
+
}) === "stale";
|
|
4007
|
+
}
|
|
4008
|
+
|
|
3930
4009
|
const NO_EDITABLES = /* @__PURE__ */ new Map;
|
|
3931
4010
|
|
|
3932
4011
|
function InstanceStateTab({entry: entry}) {
|
|
3933
|
-
const {instance: instance} = entry, definition = useDefinition(entry),
|
|
4012
|
+
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);
|
|
3934
4013
|
/* @__PURE__ */
|
|
3935
4014
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
3936
4015
|
gap: 4,
|
|
@@ -3948,7 +4027,7 @@ function InstanceStateTab({entry: entry}) {
|
|
|
3948
4027
|
return jsxRuntime.jsx(ScopeGroup, {
|
|
3949
4028
|
editables: current ? editablesByName("stage") : NO_EDITABLES,
|
|
3950
4029
|
fields: st.fields ?? [],
|
|
3951
|
-
heading: `Stage · ${
|
|
4030
|
+
heading: `Stage · ${stageTitle(definition, st.name)}${suffix}`,
|
|
3952
4031
|
instanceId: instance._id
|
|
3953
4032
|
}, `s-${i}`);
|
|
3954
4033
|
}) ]
|
|
@@ -4152,7 +4231,7 @@ function StageIndicator({entry: entry, definition: definition}) {
|
|
|
4152
4231
|
}
|
|
4153
4232
|
|
|
4154
4233
|
function InstancePanel({entry: entry, entries: entries, onSelect: onSelect}) {
|
|
4155
|
-
const definition = useDefinition(entry), {instance: instance, ready: ready} = entry, identity = useAssignmentIdentity(), [assignedToMe, setAssignedToMe] = react.useState(!1), [openActivity, setOpenActivity] = react.useState(null), [segment, setSegment] = react.useState("state"),
|
|
4234
|
+
const definition = useDefinition(entry), {instance: instance, ready: ready} = entry, identity = useAssignmentIdentity(), [assignedToMe, setAssignedToMe] = react.useState(!1), [openActivity, setOpenActivity] = react.useState(null), [segment, setSegment] = react.useState("state"), currentStageTitle = stageTitle(definition, instance.currentStage), notice = instanceNotice(entry), syncing = evaluationSyncing(entry);
|
|
4156
4235
|
/* @__PURE__ */
|
|
4157
4236
|
return jsxRuntime.jsxs(ui.Flex, {
|
|
4158
4237
|
direction: "column",
|
|
@@ -4179,8 +4258,18 @@ function InstancePanel({entry: entry, entries: entries, onSelect: onSelect}) {
|
|
|
4179
4258
|
}),
|
|
4180
4259
|
/* @__PURE__ */ jsxRuntime.jsx(PendingWorkBadge, {
|
|
4181
4260
|
instance: instance
|
|
4182
|
-
}),
|
|
4183
|
-
|
|
4261
|
+
}),
|
|
4262
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
4263
|
+
align: "center",
|
|
4264
|
+
flex: "none",
|
|
4265
|
+
justify: "center",
|
|
4266
|
+
style: {
|
|
4267
|
+
width: 19,
|
|
4268
|
+
height: 19
|
|
4269
|
+
},
|
|
4270
|
+
children: !ready || syncing ? /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {
|
|
4271
|
+
muted: !0
|
|
4272
|
+
}) : null
|
|
4184
4273
|
}),
|
|
4185
4274
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
4186
4275
|
flex: 1
|
|
@@ -4240,20 +4329,29 @@ function InstancePanel({entry: entry, entries: entries, onSelect: onSelect}) {
|
|
|
4240
4329
|
size: 1,
|
|
4241
4330
|
children: "Couldn’t load this workflow’s definition — stage and action titles fall back to raw names."
|
|
4242
4331
|
})
|
|
4243
|
-
}), notice ??
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4332
|
+
}), notice ??
|
|
4333
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
4334
|
+
style: {
|
|
4335
|
+
opacity: syncing ? .5 : 1,
|
|
4336
|
+
pointerEvents: syncing ? "none" : void 0,
|
|
4337
|
+
transition: "opacity 150ms ease-in"
|
|
4338
|
+
},
|
|
4339
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
4340
|
+
"aria-busy": syncing,
|
|
4341
|
+
children: [
|
|
4342
|
+
/* @__PURE__ */ jsxRuntime.jsx(ActivitiesList, {
|
|
4343
|
+
assignedToMeOnly: assignedToMe,
|
|
4344
|
+
entry: entry,
|
|
4345
|
+
identity: identity,
|
|
4346
|
+
onOpenActivity: setOpenActivity,
|
|
4347
|
+
stageTitle: currentStageTitle
|
|
4348
|
+
}),
|
|
4349
|
+
/* @__PURE__ */ jsxRuntime.jsx(ActionItemsList, {
|
|
4350
|
+
assignedToMeOnly: assignedToMe,
|
|
4351
|
+
entry: entry,
|
|
4352
|
+
identity: identity
|
|
4353
|
+
}) ]
|
|
4354
|
+
})
|
|
4257
4355
|
}),
|
|
4258
4356
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
4259
4357
|
border: !0,
|
|
@@ -4296,7 +4394,7 @@ function InstancePanel({entry: entry, entries: entries, onSelect: onSelect}) {
|
|
|
4296
4394
|
})
|
|
4297
4395
|
}), openActivity ? /* @__PURE__ */ jsxRuntime.jsx(ActivityDetailDialog, {
|
|
4298
4396
|
activityName: openActivity,
|
|
4299
|
-
breadcrumb: [ instanceTitle(instance, definition),
|
|
4397
|
+
breadcrumb: [ instanceTitle(instance, definition), currentStageTitle ],
|
|
4300
4398
|
entry: entry,
|
|
4301
4399
|
onClose: () => setOpenActivity(null)
|
|
4302
4400
|
}) : null ]
|
|
@@ -4357,7 +4455,7 @@ function useRefcountedIds() {
|
|
|
4357
4455
|
};
|
|
4358
4456
|
}
|
|
4359
4457
|
|
|
4360
|
-
const REPORT_KEYS = [ "evaluation", "ready", "guards", "fireAction", "editField" ];
|
|
4458
|
+
const REPORT_KEYS = [ "evaluation", "ready", "guards", "fireAction", "editField", "previewField", "discardFieldPreview" ];
|
|
4361
4459
|
|
|
4362
4460
|
function sameReport(a, b) {
|
|
4363
4461
|
return REPORT_KEYS.every(key => a[key] === b[key]);
|
|
@@ -4401,7 +4499,7 @@ class InstanceEvaluatorBoundary extends react.Component {
|
|
|
4401
4499
|
}
|
|
4402
4500
|
|
|
4403
4501
|
function InstanceEvaluator(props) {
|
|
4404
|
-
const {engine: engine, instanceId: instanceId, grantsFromPath: grantsFromPath, onReport: onReport} = props, {evaluation: evaluation, ready: ready, guards: guards, fireAction: fireAction, editField: editField} = workflowStudio.useWorkflowSession({
|
|
4502
|
+
const {engine: engine, instanceId: instanceId, grantsFromPath: grantsFromPath, onReport: onReport} = props, {evaluation: evaluation, ready: ready, guards: guards, fireAction: fireAction, editField: editField, previewField: previewField, discardFieldPreview: discardFieldPreview} = workflowStudio.useWorkflowSession({
|
|
4405
4503
|
engine: engine,
|
|
4406
4504
|
instanceId: instanceId,
|
|
4407
4505
|
grantsFromPath: grantsFromPath
|
|
@@ -4412,9 +4510,11 @@ function InstanceEvaluator(props) {
|
|
|
4412
4510
|
ready: ready,
|
|
4413
4511
|
guards: guards,
|
|
4414
4512
|
fireAction: fireAction,
|
|
4415
|
-
editField: editField
|
|
4513
|
+
editField: editField,
|
|
4514
|
+
previewField: previewField,
|
|
4515
|
+
discardFieldPreview: discardFieldPreview
|
|
4416
4516
|
});
|
|
4417
|
-
}, [ instanceId, evaluation, ready, guards, fireAction, editField, onReport ]),
|
|
4517
|
+
}, [ instanceId, evaluation, ready, guards, fireAction, editField, previewField, discardFieldPreview, onReport ]),
|
|
4418
4518
|
react.useEffect(() => () => onReport(instanceId, void 0), [ instanceId, onReport ]),
|
|
4419
4519
|
null;
|
|
4420
4520
|
}
|
|
@@ -4478,7 +4578,10 @@ function WorkflowProvider(props) {
|
|
|
4478
4578
|
...config.effectHandlers ? {
|
|
4479
4579
|
effectHandlers: config.effectHandlers
|
|
4480
4580
|
} : {}
|
|
4481
|
-
}), grantsFromPath =
|
|
4581
|
+
}), grantsFromPath = workflowEngine.aclPathForResource({
|
|
4582
|
+
type: "dataset",
|
|
4583
|
+
id: `${projectId}.${workflowDataset}`
|
|
4584
|
+
}), {ids: registered, acquire: register, release: unregister} = useRefcountedIds(), {ids: requested, acquire: requestInstance, release: releaseInstance} = useRefcountedIds(), [seeded, setSeeded] = react.useState(/* @__PURE__ */ new Map), seedInstance = react.useCallback(instance => {
|
|
4482
4585
|
setSeeded(prev => new Map(prev).set(instance._id, instance));
|
|
4483
4586
|
}, []), [startRequest, setStartRequest] = react.useState(void 0), openStartDialog = react.useCallback(r => setStartRequest(r), []), closeStartDialog = react.useCallback(() => setStartRequest(void 0), []), [reports, setReports] = react.useState(/* @__PURE__ */ new Map), onReport = react.useCallback((instanceId, report) => {
|
|
4484
4587
|
setReports(prev => nextReports(prev, {
|
|
@@ -4508,7 +4611,11 @@ function WorkflowProvider(props) {
|
|
|
4508
4611
|
const report = reportsRef.current.get(instanceId);
|
|
4509
4612
|
return report ? report.editField(args).then(async res => (await drainCommitted(instanceId),
|
|
4510
4613
|
res)) : notReady(args);
|
|
4511
|
-
}, [ drainCommitted ]),
|
|
4614
|
+
}, [ drainCommitted ]), previewFieldFor = react.useCallback((instanceId, args) => {
|
|
4615
|
+
reportsRef.current.get(instanceId)?.previewField(args);
|
|
4616
|
+
}, []), discardFieldPreviewFor = react.useCallback((instanceId, target) => {
|
|
4617
|
+
reportsRef.current.get(instanceId)?.discardFieldPreview(target);
|
|
4618
|
+
}, []), drainEffectsFor = react.useCallback(async instanceId => {
|
|
4512
4619
|
await engine.drainEffects({
|
|
4513
4620
|
instanceId: instanceId
|
|
4514
4621
|
});
|
|
@@ -4578,6 +4685,8 @@ function WorkflowProvider(props) {
|
|
|
4578
4685
|
loading: loading,
|
|
4579
4686
|
fireActionFor: fireActionFor,
|
|
4580
4687
|
editFieldFor: editFieldFor,
|
|
4688
|
+
previewFieldFor: previewFieldFor,
|
|
4689
|
+
discardFieldPreviewFor: discardFieldPreviewFor,
|
|
4581
4690
|
drainEffectsFor: drainEffectsFor,
|
|
4582
4691
|
completeEffectFor: completeEffectFor,
|
|
4583
4692
|
engine: engine,
|
|
@@ -4585,7 +4694,7 @@ function WorkflowProvider(props) {
|
|
|
4585
4694
|
mappings: config.mappings,
|
|
4586
4695
|
mappingIssues: issues,
|
|
4587
4696
|
effectHandlers: engine.effectHandlers
|
|
4588
|
-
}), [ register, unregister, isDocResolved, byDocument, byInstance, requestInstance, releaseInstance, seedInstance, openStartDialog, closeStartDialog, startRequest, loading, fireActionFor, editFieldFor, drainEffectsFor, completeEffectFor, engine, binding, config.mappings, issues ]);
|
|
4697
|
+
}), [ register, unregister, isDocResolved, byDocument, byInstance, requestInstance, releaseInstance, seedInstance, openStartDialog, closeStartDialog, startRequest, loading, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding, config.mappings, issues ]);
|
|
4589
4698
|
/* @__PURE__ */
|
|
4590
4699
|
return jsxRuntime.jsxs(WorkflowContext.Provider, {
|
|
4591
4700
|
value: value,
|