@aglyn/plugins-workflows 1.0.0-beta.179 → 1.0.0-beta.181

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.
Files changed (52) hide show
  1. package/package.json +12 -11
  2. package/src/lib/components/automation-trigger-conditions.component.d.ts +43 -0
  3. package/src/lib/components/automation-trigger-conditions.component.js +189 -0
  4. package/src/lib/components/automation-trigger-conditions.component.js.map +1 -0
  5. package/src/lib/components/host-actions-card.component.js +27 -176
  6. package/src/lib/components/host-actions-card.component.js.map +1 -1
  7. package/src/lib/components/org-automation-editor.component.d.ts +51 -0
  8. package/src/lib/components/org-automation-editor.component.js +310 -0
  9. package/src/lib/components/org-automation-editor.component.js.map +1 -0
  10. package/src/lib/components/org-automations-card.component.d.ts +28 -0
  11. package/src/lib/components/org-automations-card.component.js +373 -0
  12. package/src/lib/components/org-automations-card.component.js.map +1 -0
  13. package/src/lib/components/org-site-automation-list.component.d.ts +43 -0
  14. package/src/lib/components/org-site-automation-list.component.js +289 -0
  15. package/src/lib/components/org-site-automation-list.component.js.map +1 -0
  16. package/src/lib/components/site-org-automations-panel.component.d.ts +22 -0
  17. package/src/lib/components/site-org-automations-panel.component.js +201 -0
  18. package/src/lib/components/site-org-automations-panel.component.js.map +1 -0
  19. package/src/lib/components/use-org-automation-step-pickers.d.ts +20 -0
  20. package/src/lib/components/use-org-automation-step-pickers.js +108 -0
  21. package/src/lib/components/use-org-automation-step-pickers.js.map +1 -0
  22. package/src/lib/components/use-org-automations-api.d.ts +16 -0
  23. package/src/lib/components/use-org-automations-api.js +55 -0
  24. package/src/lib/components/use-org-automations-api.js.map +1 -0
  25. package/src/lib/components/workflows-console-page.js +63 -1
  26. package/src/lib/components/workflows-console-page.js.map +1 -1
  27. package/src/lib/components/workflows-console-sections.d.ts +19 -1
  28. package/src/lib/components/workflows-console-sections.js +37 -2
  29. package/src/lib/components/workflows-console-sections.js.map +1 -1
  30. package/src/lib/components/workflows-org-mount.d.ts +52 -0
  31. package/src/lib/components/workflows-org-mount.js +49 -0
  32. package/src/lib/components/workflows-org-mount.js.map +1 -0
  33. package/src/lib/engine/flow-enrollments.d.ts +26 -10
  34. package/src/lib/engine/flow-enrollments.js +14 -7
  35. package/src/lib/engine/flow-enrollments.js.map +1 -1
  36. package/src/lib/engine/run-event-actions.d.ts +57 -4
  37. package/src/lib/engine/run-event-actions.js +119 -19
  38. package/src/lib/engine/run-event-actions.js.map +1 -1
  39. package/src/lib/engine/run-org-automations.d.ts +75 -0
  40. package/src/lib/engine/run-org-automations.js +154 -0
  41. package/src/lib/engine/run-org-automations.js.map +1 -0
  42. package/src/lib/model/org-automations.d.ts +232 -0
  43. package/src/lib/model/org-automations.js +423 -0
  44. package/src/lib/model/org-automations.js.map +1 -0
  45. package/src/lib/plugin.js +26 -1
  46. package/src/lib/plugin.js.map +1 -1
  47. package/src/lib/server/org-automations-routes.d.ts +88 -0
  48. package/src/lib/server/org-automations-routes.js +474 -0
  49. package/src/lib/server/org-automations-routes.js.map +1 -0
  50. package/src/lib/server-console.d.ts +2 -1
  51. package/src/lib/server-console.js +12 -2
  52. package/src/lib/server-console.js.map +1 -1
@@ -0,0 +1,310 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ 'use client';
17
+ import { _ as _extends } from "@swc/helpers/_/_extends";
18
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
+ import { ACTION_MAX_STEPS, hostEventLabel, hostEventPayloadHint } from "@aglyn/aglyn";
20
+ import { hostIdsFromScope, hostScopeToken, isOrgWideScope, MAX_SCOPE_HOSTS, ORG_SCOPE_TOKEN } from "@aglyn/aglyn/app-utils/scope-tokens";
21
+ import { Alert, Button, Checkbox, Dialog, DialogActions, DialogContent, DialogTitle, FormControlLabel, FormGroup, MenuItem, Radio, RadioGroup, Stack, Switch, TextField, Typography } from "@mui/material";
22
+ import { useMemo } from "react";
23
+ import { isOrgAutomationTriggerEvent, ORG_AUTOMATION_STEP_KINDS, ORG_AUTOMATION_TRIGGER_EVENTS } from "../model/org-automations.js";
24
+ import { AutomationStepFields, defaultStep } from "./automation-step-fields.component.js";
25
+ import { conditionRowsFromTrigger, conditionsFromRows, EMPTY_CONDITION_ROW, TriggerConditionRows } from "./automation-trigger-conditions.component.js";
26
+ import { EDITOR_OPTION_CEILING } from "./use-automation-step-pickers.js";
27
+ import { useOrgAutomationStepPickers } from "./use-org-automation-step-pickers.js";
28
+ import { orgSiteOptions } from "./workflows-org-mount.js";
29
+ /** A blank draft: every site, one email step, switched on. */ export function newOrgAutomationDraft() {
30
+ return {
31
+ id: null,
32
+ name: '',
33
+ event: 'formSubmission',
34
+ filter: '',
35
+ conditionRows: [
36
+ EMPTY_CONDITION_ROW
37
+ ],
38
+ conditionCombinator: 'and',
39
+ steps: [
40
+ defaultStep('sendEmail')
41
+ ],
42
+ enabled: true,
43
+ placement: 'org',
44
+ siteIds: []
45
+ };
46
+ }
47
+ /** A stored org automation as the editor opens it. */ export function orgAutomationDraft(row) {
48
+ var _row_name, _ref, _row_steps;
49
+ var _row_trigger, _row_trigger1, _row_trigger2;
50
+ const event = isOrgAutomationTriggerEvent((_row_trigger = row.trigger) == null ? void 0 : _row_trigger.event) ? row.trigger.event : 'formSubmission';
51
+ return {
52
+ id: row.$id,
53
+ name: (_row_name = row.name) != null ? _row_name : '',
54
+ event,
55
+ filter: (_ref = (_row_trigger1 = row.trigger) == null ? void 0 : _row_trigger1.filter) != null ? _ref : '',
56
+ conditionRows: conditionRowsFromTrigger(row.trigger),
57
+ conditionCombinator: ((_row_trigger2 = row.trigger) == null ? void 0 : _row_trigger2.combinator) === 'or' ? 'or' : 'and',
58
+ steps: [
59
+ ...(_row_steps = row.steps) != null ? _row_steps : []
60
+ ],
61
+ enabled: row.enabled !== false,
62
+ placement: isOrgWideScope(row.visibleTo) ? 'org' : 'sites',
63
+ siteIds: hostIdsFromScope(row.visibleTo)
64
+ };
65
+ }
66
+ /** The placement a draft stores, as scope tokens. */ export function draftPlacement(draft) {
67
+ return draft.placement === 'org' ? [
68
+ ORG_SCOPE_TOKEN
69
+ ] : draft.siteIds.map(hostScopeToken);
70
+ }
71
+ /** The body `automations/manage` reads, from a draft. */ export function orgAutomationBody(draft) {
72
+ return {
73
+ name: draft.name.trim(),
74
+ trigger: _extends({
75
+ event: draft.event
76
+ }, draft.filter.trim() ? {
77
+ filter: draft.filter.trim()
78
+ } : {}, conditionsFromRows(draft.conditionRows, draft.conditionCombinator)),
79
+ steps: draft.steps,
80
+ enabled: draft.enabled,
81
+ visibleTo: draftPlacement(draft)
82
+ };
83
+ }
84
+ /**
85
+ * The org automation editor (AGL-3302): a name, a trigger an org automation
86
+ * can start on, the conditions, the steps from the org vocabulary, and the
87
+ * sites it runs on.
88
+ *
89
+ * The same step rows and condition rows the actions builder uses, offered
90
+ * only what an org automation may hold. Nothing is written from here: Save
91
+ * hands the draft to `automations/manage`, which checks it again.
92
+ */ export function OrgAutomationEditor(props) {
93
+ var _ref, _ref1, _ref2, _hostEventPayloadHint, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8;
94
+ const { mount, draft, onDraft, opened, saving, onSave, onClose } = props;
95
+ const placement = useMemo(()=>draft ? draftPlacement(draft) : [
96
+ ORG_SCOPE_TOKEN
97
+ ], [
98
+ draft
99
+ ]);
100
+ const { pickers, truncated } = useOrgAutomationStepPickers(mount.orgId, opened, placement);
101
+ const sites = useMemo(()=>orgSiteOptions(mount), [
102
+ mount
103
+ ]);
104
+ const tooManySites = ((_ref = draft == null ? void 0 : draft.siteIds.length) != null ? _ref : 0) > MAX_SCOPE_HOSTS;
105
+ return /*#__PURE__*/ _jsxs(Dialog, {
106
+ open: Boolean(draft),
107
+ onClose: onClose,
108
+ maxWidth: "md",
109
+ fullWidth: true,
110
+ children: [
111
+ /*#__PURE__*/ _jsx(DialogTitle, {
112
+ children: (draft == null ? void 0 : draft.id) ? 'Edit org automation' : 'Add org automation'
113
+ }),
114
+ /*#__PURE__*/ _jsxs(DialogContent, {
115
+ sx: {
116
+ display: 'flex',
117
+ flexDirection: 'column',
118
+ gap: 1.5,
119
+ pt: 1
120
+ },
121
+ children: [
122
+ /*#__PURE__*/ _jsx(Typography, {
123
+ variant: "body2",
124
+ color: "text.secondary",
125
+ children: 'Runs on every site you place it on, as that site: its email goes ' + 'from that site, its runs count on that site’s action runs, and ' + 'the site can pause it for itself.'
126
+ }),
127
+ truncated.length > 0 ? /*#__PURE__*/ _jsx(Alert, {
128
+ severity: "info",
129
+ children: `Offering the first ${EDITOR_OPTION_CEILING} rows, ordered by id, ` + `for: ${truncated.join(', ')}. The organization has more, so a ` + 'step target may not be listed below.'
130
+ }) : null,
131
+ /*#__PURE__*/ _jsx(TextField, {
132
+ label: "Name",
133
+ value: (_ref1 = draft == null ? void 0 : draft.name) != null ? _ref1 : '',
134
+ onChange: (event)=>onDraft((previous)=>_extends({}, previous, {
135
+ name: event.target.value
136
+ })),
137
+ size: "small",
138
+ autoFocus: true,
139
+ sx: {
140
+ mt: 1
141
+ }
142
+ }),
143
+ /*#__PURE__*/ _jsxs(Stack, {
144
+ direction: "row",
145
+ spacing: 1,
146
+ children: [
147
+ /*#__PURE__*/ _jsx(TextField, {
148
+ select: true,
149
+ label: "Trigger event",
150
+ value: (_ref2 = draft == null ? void 0 : draft.event) != null ? _ref2 : 'formSubmission',
151
+ onChange: (event)=>onDraft((previous)=>_extends({}, previous, {
152
+ event: event.target.value
153
+ })),
154
+ size: "small",
155
+ sx: {
156
+ minWidth: 200
157
+ },
158
+ children: ORG_AUTOMATION_TRIGGER_EVENTS.map((eventType)=>/*#__PURE__*/ _jsx(MenuItem, {
159
+ value: eventType,
160
+ children: hostEventLabel(eventType)
161
+ }, eventType))
162
+ }),
163
+ /*#__PURE__*/ _jsx(TextField, {
164
+ label: "Filter (optional)",
165
+ placeholder: 'source == "form"',
166
+ helperText: (_hostEventPayloadHint = hostEventPayloadHint(draft == null ? void 0 : draft.event)) != null ? _hostEventPayloadHint : undefined,
167
+ value: (_ref3 = draft == null ? void 0 : draft.filter) != null ? _ref3 : '',
168
+ onChange: (event)=>onDraft((previous)=>_extends({}, previous, {
169
+ filter: event.target.value
170
+ })),
171
+ size: "small",
172
+ sx: {
173
+ flex: 1
174
+ }
175
+ })
176
+ ]
177
+ }),
178
+ /*#__PURE__*/ _jsx(TriggerConditionRows, {
179
+ rows: (_ref4 = draft == null ? void 0 : draft.conditionRows) != null ? _ref4 : [],
180
+ combinator: (_ref5 = draft == null ? void 0 : draft.conditionCombinator) != null ? _ref5 : 'and',
181
+ onRowsChange: (update)=>onDraft((previous)=>_extends({}, previous, {
182
+ conditionRows: update(previous.conditionRows)
183
+ })),
184
+ onCombinatorChange: (combinator)=>onDraft((previous)=>_extends({}, previous, {
185
+ conditionCombinator: combinator
186
+ }))
187
+ }),
188
+ /*#__PURE__*/ _jsx(Typography, {
189
+ variant: "overline",
190
+ color: "text.secondary",
191
+ children: 'Runs on'
192
+ }),
193
+ /*#__PURE__*/ _jsxs(RadioGroup, {
194
+ row: true,
195
+ value: (_ref6 = draft == null ? void 0 : draft.placement) != null ? _ref6 : 'org',
196
+ onChange: (event)=>onDraft((previous)=>_extends({}, previous, {
197
+ placement: event.target.value === 'sites' ? 'sites' : 'org'
198
+ })),
199
+ children: [
200
+ /*#__PURE__*/ _jsx(FormControlLabel, {
201
+ value: "org",
202
+ control: /*#__PURE__*/ _jsx(Radio, {
203
+ size: "small"
204
+ }),
205
+ label: "Every site"
206
+ }),
207
+ /*#__PURE__*/ _jsx(FormControlLabel, {
208
+ value: "sites",
209
+ control: /*#__PURE__*/ _jsx(Radio, {
210
+ size: "small"
211
+ }),
212
+ label: "Chosen sites"
213
+ })
214
+ ]
215
+ }),
216
+ (draft == null ? void 0 : draft.placement) === 'sites' ? /*#__PURE__*/ _jsxs(FormGroup, {
217
+ "aria-label": "Sites it runs on",
218
+ children: [
219
+ !mount.hostsReady ? /*#__PURE__*/ _jsx(Typography, {
220
+ variant: "caption",
221
+ color: "text.secondary",
222
+ children: '…'
223
+ }) : !sites.length ? /*#__PURE__*/ _jsx(Typography, {
224
+ variant: "body2",
225
+ color: "text.secondary",
226
+ children: 'This organization has no sites yet.'
227
+ }) : sites.map((site)=>/*#__PURE__*/ _jsx(FormControlLabel, {
228
+ control: /*#__PURE__*/ _jsx(Checkbox, {
229
+ size: "small",
230
+ checked: draft.siteIds.includes(site.value),
231
+ onChange: (event)=>onDraft((previous)=>_extends({}, previous, {
232
+ siteIds: event.target.checked ? [
233
+ ...previous.siteIds,
234
+ site.value
235
+ ] : previous.siteIds.filter((id)=>id !== site.value)
236
+ }))
237
+ }),
238
+ label: site.label
239
+ }, site.value)),
240
+ tooManySites ? /*#__PURE__*/ _jsx(Typography, {
241
+ variant: "caption",
242
+ color: "error",
243
+ children: `Choose ${MAX_SCOPE_HOSTS} sites or fewer, or run it on every site.`
244
+ }) : null
245
+ ]
246
+ }) : null,
247
+ /*#__PURE__*/ _jsx(Typography, {
248
+ variant: "overline",
249
+ color: "text.secondary",
250
+ children: 'Steps (run in order)'
251
+ }),
252
+ ((_ref7 = draft == null ? void 0 : draft.steps) != null ? _ref7 : []).map((step, index)=>/*#__PURE__*/ _jsx(AutomationStepFields, {
253
+ step: step,
254
+ index: index,
255
+ kind: step.type,
256
+ kinds: ORG_AUTOMATION_STEP_KINDS,
257
+ stepForKind: (value)=>defaultStep(value),
258
+ pickers: pickers,
259
+ onSteps: (update)=>onDraft((previous)=>_extends({}, previous, {
260
+ steps: update(previous.steps)
261
+ }))
262
+ }, index)),
263
+ /*#__PURE__*/ _jsx(Button, {
264
+ size: "small",
265
+ sx: {
266
+ alignSelf: 'flex-start'
267
+ },
268
+ disabled: ((_ref8 = draft == null ? void 0 : draft.steps.length) != null ? _ref8 : 0) >= ACTION_MAX_STEPS,
269
+ onClick: ()=>onDraft((previous)=>_extends({}, previous, {
270
+ steps: [
271
+ ...previous.steps,
272
+ defaultStep('sendEmail')
273
+ ]
274
+ })),
275
+ children: 'Add step'
276
+ }),
277
+ /*#__PURE__*/ _jsx(FormControlLabel, {
278
+ control: /*#__PURE__*/ _jsx(Switch, {
279
+ size: "small",
280
+ checked: (draft == null ? void 0 : draft.enabled) !== false,
281
+ onChange: (event)=>onDraft((previous)=>_extends({}, previous, {
282
+ enabled: event.target.checked
283
+ }))
284
+ }),
285
+ label: "Switched on"
286
+ })
287
+ ]
288
+ }),
289
+ /*#__PURE__*/ _jsxs(DialogActions, {
290
+ children: [
291
+ /*#__PURE__*/ _jsx(Button, {
292
+ color: "inherit",
293
+ onClick: onClose,
294
+ children: 'Cancel'
295
+ }),
296
+ /*#__PURE__*/ _jsx(Button, {
297
+ variant: "contained",
298
+ color: "primary",
299
+ disabled: !(draft == null ? void 0 : draft.name.trim()) || saving,
300
+ onClick: onSave,
301
+ children: saving ? 'Saving…' : 'Save org automation'
302
+ })
303
+ ]
304
+ })
305
+ ]
306
+ });
307
+ }
308
+ OrgAutomationEditor.displayName = 'OrgAutomationEditor';
309
+
310
+ //# sourceMappingURL=org-automation-editor.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/components/org-automation-editor.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n ACTION_MAX_STEPS,\n type HostActionStep,\n type HostActionStepType,\n hostEventLabel,\n hostEventPayloadHint,\n type TriggerCombinator,\n} from '@aglyn/aglyn'\nimport {\n hostIdsFromScope,\n hostScopeToken,\n isOrgWideScope,\n MAX_SCOPE_HOSTS,\n ORG_SCOPE_TOKEN,\n} from '@aglyn/aglyn/app-utils/scope-tokens'\nimport {\n Alert,\n Button,\n Checkbox,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n FormControlLabel,\n FormGroup,\n MenuItem,\n Radio,\n RadioGroup,\n Stack,\n Switch,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useMemo } from 'react'\nimport {\n isOrgAutomationTriggerEvent,\n ORG_AUTOMATION_STEP_KINDS,\n ORG_AUTOMATION_TRIGGER_EVENTS,\n type OrgAutomationRow,\n type OrgAutomationTriggerEvent,\n} from '../model/org-automations'\nimport {\n AutomationStepFields,\n defaultStep,\n} from './automation-step-fields.component'\nimport {\n conditionRowsFromTrigger,\n conditionsFromRows,\n type ConditionRowDraft,\n EMPTY_CONDITION_ROW,\n TriggerConditionRows,\n} from './automation-trigger-conditions.component'\nimport { EDITOR_OPTION_CEILING } from './use-automation-step-pickers'\nimport { useOrgAutomationStepPickers } from './use-org-automation-step-pickers'\nimport { orgSiteOptions, type WorkflowsOrgMount } from './workflows-org-mount'\n\n/** An org automation as the editor holds it. */\nexport interface OrgAutomationDraft {\n /** The stored document's id, or null for a new one. */\n id: string | null\n name: string\n event: OrgAutomationTriggerEvent\n filter: string\n conditionRows: ConditionRowDraft[]\n conditionCombinator: TriggerCombinator\n steps: HostActionStep[]\n enabled: boolean\n /** `org` runs on every site; `sites` on the ones in `siteIds`. */\n placement: 'org' | 'sites'\n siteIds: string[]\n}\n\n/** A blank draft: every site, one email step, switched on. */\nexport function newOrgAutomationDraft(): OrgAutomationDraft {\n return {\n id: null,\n name: '',\n event: 'formSubmission',\n filter: '',\n conditionRows: [EMPTY_CONDITION_ROW],\n conditionCombinator: 'and',\n steps: [defaultStep('sendEmail')],\n enabled: true,\n placement: 'org',\n siteIds: [],\n }\n}\n\n/** A stored org automation as the editor opens it. */\nexport function orgAutomationDraft(row: OrgAutomationRow): OrgAutomationDraft {\n const event = isOrgAutomationTriggerEvent(row.trigger?.event)\n ? row.trigger.event\n : 'formSubmission'\n return {\n id: row.$id,\n name: row.name ?? '',\n event,\n filter: row.trigger?.filter ?? '',\n conditionRows: conditionRowsFromTrigger(row.trigger),\n conditionCombinator: row.trigger?.combinator === 'or' ? 'or' : 'and',\n steps: [...(row.steps ?? [])],\n enabled: row.enabled !== false,\n placement: isOrgWideScope(row.visibleTo) ? 'org' : 'sites',\n siteIds: hostIdsFromScope(row.visibleTo),\n }\n}\n\n/** The placement a draft stores, as scope tokens. */\nexport function draftPlacement(draft: OrgAutomationDraft): string[] {\n return draft.placement === 'org'\n ? [ORG_SCOPE_TOKEN]\n : draft.siteIds.map(hostScopeToken)\n}\n\n/** The body `automations/manage` reads, from a draft. */\nexport function orgAutomationBody(\n draft: OrgAutomationDraft,\n): Record<string, unknown> {\n return {\n name: draft.name.trim(),\n trigger: {\n event: draft.event,\n ...(draft.filter.trim() ? { filter: draft.filter.trim() } : {}),\n ...conditionsFromRows(draft.conditionRows, draft.conditionCombinator),\n },\n steps: draft.steps,\n enabled: draft.enabled,\n visibleTo: draftPlacement(draft),\n }\n}\n\nexport interface OrgAutomationEditorProps {\n mount: WorkflowsOrgMount\n /** The draft being edited, or null when the dialog is closed. */\n draft: OrgAutomationDraft | null\n onDraft: (update: (previous: OrgAutomationDraft) => OrgAutomationDraft) => void\n /** The editor has been opened at least once: the latch the pickers read on. */\n opened: boolean\n saving: boolean\n onSave: () => void\n onClose: () => void\n}\n\n/**\n * The org automation editor (AGL-3302): a name, a trigger an org automation\n * can start on, the conditions, the steps from the org vocabulary, and the\n * sites it runs on.\n *\n * The same step rows and condition rows the actions builder uses, offered\n * only what an org automation may hold. Nothing is written from here: Save\n * hands the draft to `automations/manage`, which checks it again.\n */\nexport function OrgAutomationEditor(props: OrgAutomationEditorProps) {\n const { mount, draft, onDraft, opened, saving, onSave, onClose } = props\n const placement = useMemo(\n () => (draft ? draftPlacement(draft) : [ORG_SCOPE_TOKEN]),\n [draft],\n )\n const { pickers, truncated } = useOrgAutomationStepPickers(\n mount.orgId,\n opened,\n placement,\n )\n const sites = useMemo(() => orgSiteOptions(mount), [mount])\n const tooManySites = (draft?.siteIds.length ?? 0) > MAX_SCOPE_HOSTS\n return (\n <Dialog open={Boolean(draft)} onClose={onClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>\n {draft?.id ? 'Edit org automation' : 'Add org automation'}\n </DialogTitle>\n <DialogContent\n sx={{ display: 'flex', flexDirection: 'column', gap: 1.5, pt: 1 }}\n >\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Runs on every site you place it on, as that site: its email goes ' +\n 'from that site, its runs count on that site’s action runs, and ' +\n 'the site can pause it for itself.'}\n </Typography>\n {truncated.length > 0 ? (\n <Alert severity=\"info\">\n {`Offering the first ${EDITOR_OPTION_CEILING} rows, ordered by id, ` +\n `for: ${truncated.join(', ')}. The organization has more, so a ` +\n 'step target may not be listed below.'}\n </Alert>\n ) : null}\n <TextField\n label=\"Name\"\n value={draft?.name ?? ''}\n onChange={(event) =>\n onDraft((previous) => ({ ...previous, name: event.target.value }))\n }\n size=\"small\"\n autoFocus\n sx={{ mt: 1 }}\n />\n <Stack direction=\"row\" spacing={1}>\n <TextField\n select\n label=\"Trigger event\"\n value={draft?.event ?? 'formSubmission'}\n onChange={(event) =>\n onDraft((previous) => ({\n ...previous,\n event: event.target.value as OrgAutomationTriggerEvent,\n }))\n }\n size=\"small\"\n sx={{ minWidth: 200 }}\n >\n {ORG_AUTOMATION_TRIGGER_EVENTS.map((eventType) => (\n <MenuItem key={eventType} value={eventType}>\n {hostEventLabel(eventType)}\n </MenuItem>\n ))}\n </TextField>\n <TextField\n label=\"Filter (optional)\"\n placeholder={'source == \"form\"'}\n helperText={hostEventPayloadHint(draft?.event) ?? undefined}\n value={draft?.filter ?? ''}\n onChange={(event) =>\n onDraft((previous) => ({ ...previous, filter: event.target.value }))\n }\n size=\"small\"\n sx={{ flex: 1 }}\n />\n </Stack>\n <TriggerConditionRows\n rows={draft?.conditionRows ?? []}\n combinator={draft?.conditionCombinator ?? 'and'}\n onRowsChange={(update) =>\n onDraft((previous) => ({\n ...previous,\n conditionRows: update(previous.conditionRows),\n }))\n }\n onCombinatorChange={(combinator) =>\n onDraft((previous) => ({\n ...previous,\n conditionCombinator: combinator,\n }))\n }\n />\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Runs on'}\n </Typography>\n <RadioGroup\n row\n value={draft?.placement ?? 'org'}\n onChange={(event) =>\n onDraft((previous) => ({\n ...previous,\n placement: event.target.value === 'sites' ? 'sites' : 'org',\n }))\n }\n >\n <FormControlLabel\n value=\"org\"\n control={<Radio size=\"small\" />}\n label=\"Every site\"\n />\n <FormControlLabel\n value=\"sites\"\n control={<Radio size=\"small\" />}\n label=\"Chosen sites\"\n />\n </RadioGroup>\n {draft?.placement === 'sites' ? (\n <FormGroup aria-label=\"Sites it runs on\">\n {!mount.hostsReady ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'…'}\n </Typography>\n ) : !sites.length ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'This organization has no sites yet.'}\n </Typography>\n ) : (\n sites.map((site) => (\n <FormControlLabel\n key={site.value}\n control={\n <Checkbox\n size=\"small\"\n checked={draft.siteIds.includes(site.value)}\n onChange={(event) =>\n onDraft((previous) => ({\n ...previous,\n siteIds: event.target.checked\n ? [...previous.siteIds, site.value]\n : previous.siteIds.filter((id) => id !== site.value),\n }))\n }\n />\n }\n label={site.label}\n />\n ))\n )}\n {tooManySites ? (\n <Typography variant=\"caption\" color=\"error\">\n {`Choose ${MAX_SCOPE_HOSTS} sites or fewer, or run it on every site.`}\n </Typography>\n ) : null}\n </FormGroup>\n ) : null}\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Steps (run in order)'}\n </Typography>\n {(draft?.steps ?? []).map((step, index) => (\n <AutomationStepFields\n key={index}\n step={step}\n index={index}\n kind={step.type}\n kinds={ORG_AUTOMATION_STEP_KINDS}\n stepForKind={(value) => defaultStep(value as HostActionStepType)}\n pickers={pickers}\n onSteps={(update) =>\n onDraft((previous) => ({\n ...previous,\n steps: update(previous.steps),\n }))\n }\n />\n ))}\n <Button\n size=\"small\"\n sx={{ alignSelf: 'flex-start' }}\n disabled={(draft?.steps.length ?? 0) >= ACTION_MAX_STEPS}\n onClick={() =>\n onDraft((previous) => ({\n ...previous,\n steps: [...previous.steps, defaultStep('sendEmail')],\n }))\n }\n >\n {'Add step'}\n </Button>\n <FormControlLabel\n control={\n <Switch\n size=\"small\"\n checked={draft?.enabled !== false}\n onChange={(event) =>\n onDraft((previous) => ({\n ...previous,\n enabled: event.target.checked,\n }))\n }\n />\n }\n label=\"Switched on\"\n />\n </DialogContent>\n <DialogActions>\n <Button color=\"inherit\" onClick={onClose}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={!draft?.name.trim() || saving}\n onClick={onSave}\n >\n {saving ? 'Saving…' : 'Save org automation'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\nOrgAutomationEditor.displayName = 'OrgAutomationEditor'\n"],"names":["ACTION_MAX_STEPS","hostEventLabel","hostEventPayloadHint","hostIdsFromScope","hostScopeToken","isOrgWideScope","MAX_SCOPE_HOSTS","ORG_SCOPE_TOKEN","Alert","Button","Checkbox","Dialog","DialogActions","DialogContent","DialogTitle","FormControlLabel","FormGroup","MenuItem","Radio","RadioGroup","Stack","Switch","TextField","Typography","useMemo","isOrgAutomationTriggerEvent","ORG_AUTOMATION_STEP_KINDS","ORG_AUTOMATION_TRIGGER_EVENTS","AutomationStepFields","defaultStep","conditionRowsFromTrigger","conditionsFromRows","EMPTY_CONDITION_ROW","TriggerConditionRows","EDITOR_OPTION_CEILING","useOrgAutomationStepPickers","orgSiteOptions","newOrgAutomationDraft","id","name","event","filter","conditionRows","conditionCombinator","steps","enabled","placement","siteIds","orgAutomationDraft","row","trigger","$id","combinator","visibleTo","draftPlacement","draft","map","orgAutomationBody","trim","OrgAutomationEditor","props","mount","onDraft","opened","saving","onSave","onClose","pickers","truncated","orgId","sites","tooManySites","length","open","Boolean","maxWidth","fullWidth","sx","display","flexDirection","gap","pt","variant","color","severity","join","label","value","onChange","previous","target","size","autoFocus","mt","direction","spacing","select","minWidth","eventType","placeholder","helperText","undefined","flex","rows","onRowsChange","update","onCombinatorChange","control","aria-label","hostsReady","site","checked","includes","step","index","kind","type","kinds","stepForKind","onSteps","alignSelf","disabled","onClick","displayName"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { type AglynOrgBilling } from '@aglyn/aglyn';
2
+ import { type WorkflowsOrgMount } from './workflows-org-mount';
3
+ export interface OrgAutomationsCardProps {
4
+ mount: WorkflowsOrgMount;
5
+ org?: Partial<AglynOrgBilling>;
6
+ /**
7
+ * Whether the reader may write the organization's automations — an owner,
8
+ * admin or editor. The route decides; this keeps a viewer from being
9
+ * offered controls that are about to refuse them.
10
+ */
11
+ canEdit: boolean;
12
+ }
13
+ /**
14
+ * THE ORGANIZATION'S AUTOMATIONS (AGL-3302): what the organization runs on
15
+ * the sites it chooses.
16
+ *
17
+ * One ceilinged read of the live automations — the org hub admits only
18
+ * org-wide members, who read every one — and every write through
19
+ * `automations/manage` or `automations/pause`, because the collection is
20
+ * closed to client writes. Each row says where it runs and where it is
21
+ * paused; a paused site is resumed from its chip, and any placed site can be
22
+ * paused from the row, which is the same control the site's own hub offers.
23
+ */
24
+ export declare function OrgAutomationsCard(props: OrgAutomationsCardProps): import("react").JSX.Element;
25
+ export declare namespace OrgAutomationsCard {
26
+ var displayName: string;
27
+ }
28
+ export default OrgAutomationsCard;