@aglyn/plugins-workflows 1.0.0-beta.221 → 1.0.0-beta.223

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 (101) hide show
  1. package/README.md +22 -14
  2. package/package.json +12 -12
  3. package/src/lib/components/automation-step-fields.component.d.ts +16 -16
  4. package/src/lib/components/automation-step-fields.component.js +146 -12
  5. package/src/lib/components/automation-step-fields.component.js.map +1 -1
  6. package/src/lib/components/automation-trigger-conditions.component.d.ts +25 -3
  7. package/src/lib/components/automation-trigger-conditions.component.js +89 -10
  8. package/src/lib/components/automation-trigger-conditions.component.js.map +1 -1
  9. package/src/lib/components/host-actions-card.component.js +126 -84
  10. package/src/lib/components/host-actions-card.component.js.map +1 -1
  11. package/src/lib/components/host-webhooks-card.component.js +2 -1
  12. package/src/lib/components/host-webhooks-card.component.js.map +1 -1
  13. package/src/lib/components/host-workflows-card.component.js +31 -10
  14. package/src/lib/components/host-workflows-card.component.js.map +1 -1
  15. package/src/lib/components/org-automation-editor.component.d.ts +2 -1
  16. package/src/lib/components/org-automation-editor.component.js +20 -11
  17. package/src/lib/components/org-automation-editor.component.js.map +1 -1
  18. package/src/lib/components/org-automations-card.component.js +2 -1
  19. package/src/lib/components/org-automations-card.component.js.map +1 -1
  20. package/src/lib/components/run-quota-line.component.d.ts +17 -4
  21. package/src/lib/components/run-quota-line.component.js +16 -7
  22. package/src/lib/components/run-quota-line.component.js.map +1 -1
  23. package/src/lib/components/site-org-automations-panel.component.js +2 -1
  24. package/src/lib/components/site-org-automations-panel.component.js.map +1 -1
  25. package/src/lib/components/workflows-console-page.js +18 -7
  26. package/src/lib/components/workflows-console-page.js.map +1 -1
  27. package/src/lib/declarations.d.ts +28 -0
  28. package/src/lib/declarations.js +37 -0
  29. package/src/lib/declarations.js.map +1 -0
  30. package/src/lib/declarations.server.js +17 -0
  31. package/src/lib/declarations.server.js.map +1 -1
  32. package/src/lib/engine/email-merge.d.ts +69 -0
  33. package/src/lib/engine/email-merge.js +98 -0
  34. package/src/lib/engine/email-merge.js.map +1 -0
  35. package/src/lib/engine/run-event-actions.d.ts +35 -10
  36. package/src/lib/engine/run-event-actions.js +256 -369
  37. package/src/lib/engine/run-event-actions.js.map +1 -1
  38. package/src/lib/engine/run-event-automations.d.ts +1 -1
  39. package/src/lib/engine/run-event-automations.js.map +1 -1
  40. package/src/lib/engine/run-event-workflows.d.ts +2 -1
  41. package/src/lib/engine/run-event-workflows.js +71 -30
  42. package/src/lib/engine/run-event-workflows.js.map +1 -1
  43. package/src/lib/engine/run-meter.d.ts +98 -0
  44. package/src/lib/engine/run-meter.js +121 -0
  45. package/src/lib/engine/run-meter.js.map +1 -0
  46. package/src/lib/engine/run-org-automations.d.ts +3 -2
  47. package/src/lib/engine/run-org-automations.js +17 -12
  48. package/src/lib/engine/run-org-automations.js.map +1 -1
  49. package/src/lib/engine/triggered-docs.d.ts +39 -0
  50. package/src/lib/engine/triggered-docs.js +47 -0
  51. package/src/lib/engine/triggered-docs.js.map +1 -0
  52. package/src/lib/engine/workflow-steps.d.ts +1 -1
  53. package/src/lib/engine/workflow-steps.js +3 -2
  54. package/src/lib/engine/workflow-steps.js.map +1 -1
  55. package/src/lib/model/host-actions.d.ts +284 -0
  56. package/src/lib/model/host-actions.js +316 -0
  57. package/src/lib/model/host-actions.js.map +1 -0
  58. package/src/lib/model/org-automations.d.ts +8 -5
  59. package/src/lib/model/org-automations.js +14 -8
  60. package/src/lib/model/org-automations.js.map +1 -1
  61. package/src/lib/model/step-outcomes.d.ts +2 -2
  62. package/src/lib/model/step-outcomes.js +1 -1
  63. package/src/lib/model/step-outcomes.js.map +1 -1
  64. package/src/lib/plugin.js +10 -0
  65. package/src/lib/plugin.js.map +1 -1
  66. package/src/lib/server/action-test-run-route.d.ts +3 -2
  67. package/src/lib/server/action-test-run-route.js +3 -2
  68. package/src/lib/server/action-test-run-route.js.map +1 -1
  69. package/src/lib/server/org-automations-routes.d.ts +42 -1
  70. package/src/lib/server/org-automations-routes.js +120 -72
  71. package/src/lib/server/org-automations-routes.js.map +1 -1
  72. package/src/lib/server-automation-drafts.d.ts +2 -2
  73. package/src/lib/server-automation-drafts.js +11 -7
  74. package/src/lib/server-automation-drafts.js.map +1 -1
  75. package/src/lib/server.js +19 -13
  76. package/src/lib/server.js.map +1 -1
  77. package/src/lib/testing/stand-in-crm-steps.d.ts +45 -0
  78. package/src/lib/testing/stand-in-crm-steps.js +97 -0
  79. package/src/lib/testing/stand-in-crm-steps.js.map +1 -0
  80. package/src/lib/testing/stand-in-dataset-list.js +11 -3
  81. package/src/lib/testing/stand-in-dataset-list.js.map +1 -1
  82. package/src/lib/testing/stand-in-dataset-steps.d.ts +43 -0
  83. package/src/lib/testing/stand-in-dataset-steps.js +65 -0
  84. package/src/lib/testing/stand-in-dataset-steps.js.map +1 -0
  85. package/src/lib/testing/stand-in-person-records.d.ts +35 -0
  86. package/src/lib/testing/stand-in-person-records.js +54 -0
  87. package/src/lib/testing/stand-in-person-records.js.map +1 -0
  88. package/src/lib/testing/stand-in-recipes.d.ts +36 -0
  89. package/src/lib/testing/stand-in-recipes.js +206 -0
  90. package/src/lib/testing/stand-in-recipes.js.map +1 -0
  91. package/src/lib/transfer/org-automations-package.d.ts +54 -0
  92. package/src/lib/transfer/org-automations-package.js +167 -0
  93. package/src/lib/transfer/org-automations-package.js.map +1 -0
  94. package/src/lib/transfer/org-automations-package.server.d.ts +38 -0
  95. package/src/lib/transfer/org-automations-package.server.js +296 -0
  96. package/src/lib/transfer/org-automations-package.server.js.map +1 -0
  97. package/src/lib/usage-axes.js +5 -1
  98. package/src/lib/usage-axes.js.map +1 -1
  99. package/src/lib/engine/crm-action-steps.d.ts +0 -142
  100. package/src/lib/engine/crm-action-steps.js +0 -452
  101. package/src/lib/engine/crm-action-steps.js.map +0 -1
@@ -19,6 +19,22 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
19
19
  import { ACTION_MAX_CONDITIONS, normalizeTriggerConditions } from "@aglyn/aglyn";
20
20
  import { Button, IconButton, MenuItem, Stack, TextField, Typography } from "@mui/material";
21
21
  import { placeholderState } from "./automation-step-fields.component.js";
22
+ /**
23
+ * ONE TRIGGER-CONDITION EDITOR FOR EVERY AUTOMATION THAT HAS A TRIGGER.
24
+ *
25
+ * The structured payload conditions (AGL-557), chainable with AND/OR
26
+ * (AGL-565): the no-code sibling of the filter expression — "only when
27
+ * `subscribe` is not empty". A site action and an org automation (AGL-3302)
28
+ * take the same clauses and are judged by the same evaluator, so they are
29
+ * edited by the same rows.
30
+ */ /**
31
+ * "Form is …" (AGL-3458): a row that picks ONE FORM by id. Stored as the
32
+ * plain clause `formId equals <id>` — the evaluator has no form operator and
33
+ * needs none — and read back into this row, so a condition on which form it
34
+ * was is chosen from the site's forms rather than typed, and survives the
35
+ * form being renamed where `formName equals …` silently stops matching.
36
+ */ export const FORM_IS_OP = 'formIs';
37
+ /** The payload key a "Form is" row compares. */ export const FORM_ID_FIELD = 'formId';
22
38
  export const EMPTY_CONDITION_ROW = {
23
39
  op: '',
24
40
  field: '',
@@ -30,11 +46,16 @@ export const EMPTY_CONDITION_ROW = {
30
46
  * row.
31
47
  */ export function conditionRowsFromTrigger(trigger) {
32
48
  const rows = normalizeTriggerConditions(trigger).map((condition)=>{
33
- var _condition_op, _condition_field, _condition_value;
34
- return {
49
+ var _condition_value, _condition_op, _condition_field, _condition_value1;
50
+ var _condition_field1;
51
+ return ((_condition_field1 = condition.field) == null ? void 0 : _condition_field1.trim()) === FORM_ID_FIELD && condition.op === 'equals' ? {
52
+ op: FORM_IS_OP,
53
+ field: FORM_ID_FIELD,
54
+ value: (_condition_value = condition.value) != null ? _condition_value : ''
55
+ } : {
35
56
  op: (_condition_op = condition.op) != null ? _condition_op : '',
36
57
  field: (_condition_field = condition.field) != null ? _condition_field : '',
37
- value: (_condition_value = condition.value) != null ? _condition_value : ''
58
+ value: (_condition_value1 = condition.value) != null ? _condition_value1 : ''
38
59
  };
39
60
  });
40
61
  return rows.length ? rows : [
@@ -47,7 +68,11 @@ export const EMPTY_CONDITION_ROW = {
47
68
  */ export function conditionsFromRows(rows, combinator) {
48
69
  if (!rows.some((row)=>row.op)) return {};
49
70
  return {
50
- conditions: rows.filter((row)=>row.op).map((row)=>_extends({
71
+ conditions: rows.filter((row)=>row.op).map((row)=>row.op === FORM_IS_OP ? {
72
+ field: FORM_ID_FIELD,
73
+ op: 'equals',
74
+ value: row.value.trim()
75
+ } : _extends({
51
76
  field: row.field.trim(),
52
77
  op: row.op
53
78
  }, row.op !== 'notEmpty' ? {
@@ -56,7 +81,8 @@ export const EMPTY_CONDITION_ROW = {
56
81
  combinator
57
82
  };
58
83
  }
59
- /** The condition rows, "Add condition", and the AND/OR choice once there are two. */ export function TriggerConditionRows({ rows, combinator, onRowsChange, onCombinatorChange }) {
84
+ /** The condition rows, "Add condition", and the AND/OR choice once there are two. */ export function TriggerConditionRows({ rows, combinator, onRowsChange, onCombinatorChange, formOptions }) {
85
+ const offerForms = Boolean(formOptions) || rows.some((row)=>row.op === FORM_IS_OP);
60
86
  return /*#__PURE__*/ _jsxs(_Fragment, {
61
87
  children: [
62
88
  rows.map((row, index)=>/*#__PURE__*/ _jsxs(Stack, {
@@ -75,9 +101,25 @@ export const EMPTY_CONDITION_ROW = {
75
101
  select: true,
76
102
  label: index === 0 ? 'Only run when' : 'Condition',
77
103
  value: row.op,
78
- onChange: (event)=>onRowsChange((previous)=>previous.map((previousRow, index2)=>index2 === index ? _extends({}, previousRow, {
79
- op: event.target.value
80
- }) : previousRow)),
104
+ onChange: (event)=>onRowsChange((previous)=>previous.map((previousRow, index2)=>{
105
+ if (index2 !== index) return previousRow;
106
+ const op = event.target.value;
107
+ // Into and out of "Form is", the field is the form's id or
108
+ // nothing — never a leftover the author did not type.
109
+ if (op === FORM_IS_OP) return {
110
+ op,
111
+ field: FORM_ID_FIELD,
112
+ value: ''
113
+ };
114
+ if (previousRow.op === FORM_IS_OP) return {
115
+ op,
116
+ field: '',
117
+ value: ''
118
+ };
119
+ return _extends({}, previousRow, {
120
+ op
121
+ });
122
+ })),
81
123
  size: "small",
82
124
  sx: {
83
125
  minWidth: 180
@@ -98,10 +140,47 @@ export const EMPTY_CONDITION_ROW = {
98
140
  /*#__PURE__*/ _jsx(MenuItem, {
99
141
  value: "contains",
100
142
  children: 'A field contains…'
101
- })
143
+ }),
144
+ offerForms ? /*#__PURE__*/ _jsx(MenuItem, {
145
+ value: FORM_IS_OP,
146
+ children: 'Form is…'
147
+ }) : null
102
148
  ]
103
149
  }),
104
- row.op ? /*#__PURE__*/ _jsx(TextField, {
150
+ row.op === FORM_IS_OP ? formOptions ? /*#__PURE__*/ _jsxs(TextField, {
151
+ select: true,
152
+ label: "Form",
153
+ value: row.value,
154
+ error: !row.value,
155
+ helperText: row.value ? undefined : 'Pick the form',
156
+ onChange: (event)=>onRowsChange((previous)=>previous.map((previousRow, index2)=>index2 === index ? _extends({}, previousRow, {
157
+ value: event.target.value
158
+ }) : previousRow)),
159
+ size: "small",
160
+ sx: {
161
+ flex: 1
162
+ },
163
+ children: [
164
+ row.value && !formOptions.some((form)=>form.id === row.value) ? /*#__PURE__*/ _jsx(MenuItem, {
165
+ value: row.value,
166
+ children: `A form that is gone (${row.value})`
167
+ }) : null,
168
+ formOptions.map((form)=>/*#__PURE__*/ _jsx(MenuItem, {
169
+ value: form.id,
170
+ children: form.name
171
+ }, form.id))
172
+ ]
173
+ }) : /*#__PURE__*/ _jsx(TextField, {
174
+ label: "Form id",
175
+ value: row.value,
176
+ onChange: (event)=>onRowsChange((previous)=>previous.map((previousRow, index2)=>index2 === index ? _extends({}, previousRow, {
177
+ value: event.target.value
178
+ }) : previousRow)),
179
+ size: "small",
180
+ sx: {
181
+ flex: 1
182
+ }
183
+ }) : row.op ? /*#__PURE__*/ _jsx(TextField, {
105
184
  label: "Field",
106
185
  placeholder: "subscribe",
107
186
  value: row.field,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/components/automation-trigger-conditions.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_CONDITIONS,\n type HostActionTrigger,\n type HostActionTriggerCondition,\n normalizeTriggerConditions,\n type TriggerCombinator,\n type TriggerConditionOp,\n} from '@aglyn/aglyn'\nimport {\n Button,\n IconButton,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { placeholderState } from './automation-step-fields.component'\n\n/**\n * ONE TRIGGER-CONDITION EDITOR FOR EVERY AUTOMATION THAT HAS A TRIGGER.\n *\n * The structured payload conditions (AGL-557), chainable with AND/OR\n * (AGL-565): the no-code sibling of the filter expression — \"only when\n * `subscribe` is not empty\". A site action and an org automation (AGL-3302)\n * take the same clauses and are judged by the same evaluator, so they are\n * edited by the same rows.\n */\n\n/** One editable condition row; a lone row with an empty op means \"always run\". */\nexport interface ConditionRowDraft {\n op: '' | TriggerConditionOp\n field: string\n value: string\n}\n\nexport const EMPTY_CONDITION_ROW: ConditionRowDraft = {\n op: '',\n field: '',\n value: '',\n}\n\n/**\n * A stored trigger's clauses as editor rows. A legacy single-condition trigger\n * normalizes to one row, and a trigger with none opens on the lone \"always\"\n * row.\n */\nexport function conditionRowsFromTrigger(\n trigger:\n | Pick<HostActionTrigger, 'condition' | 'conditions'>\n | null\n | undefined,\n): ConditionRowDraft[] {\n const rows = normalizeTriggerConditions(trigger).map(\n (condition): ConditionRowDraft => ({\n op: condition.op ?? '',\n field: condition.field ?? '',\n value: condition.value ?? '',\n }),\n )\n return rows.length ? rows : [EMPTY_CONDITION_ROW]\n}\n\n/**\n * The rows as the stored clause list, or nothing when every row says\n * \"always\". Blank fields are kept, so the validator names what is missing.\n */\nexport function conditionsFromRows(\n rows: readonly ConditionRowDraft[],\n combinator: TriggerCombinator,\n): { conditions?: HostActionTriggerCondition[]; combinator?: TriggerCombinator } {\n if (!rows.some((row) => row.op)) return {}\n return {\n conditions: rows\n .filter((row) => row.op)\n .map((row) => ({\n field: row.field.trim(),\n op: row.op as TriggerConditionOp,\n ...(row.op !== 'notEmpty' ? { value: row.value.trim() } : {}),\n })),\n combinator,\n }\n}\n\nexport interface TriggerConditionRowsProps {\n rows: readonly ConditionRowDraft[]\n combinator: TriggerCombinator\n /** Replaces the rows, from the rows as they stand. */\n onRowsChange: (\n update: (previous: ConditionRowDraft[]) => ConditionRowDraft[],\n ) => void\n onCombinatorChange: (combinator: TriggerCombinator) => void\n}\n\n/** The condition rows, \"Add condition\", and the AND/OR choice once there are two. */\nexport function TriggerConditionRows({\n rows,\n combinator,\n onRowsChange,\n onCombinatorChange,\n}: TriggerConditionRowsProps) {\n return (\n <>\n {rows.map((row, index) => (\n <Stack\n key={index}\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center' }}\n >\n {index > 0 ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {combinator === 'or' ? 'or' : 'and'}\n </Typography>\n ) : null}\n <TextField\n select\n label={index === 0 ? 'Only run when' : 'Condition'}\n value={row.op}\n onChange={(event) =>\n onRowsChange((previous) =>\n previous.map((previousRow, index2) =>\n index2 === index\n ? {\n ...previousRow,\n op: event.target.value as ConditionRowDraft['op'],\n }\n : previousRow,\n ),\n )\n }\n size=\"small\"\n sx={{ minWidth: 180 }}\n >\n {/* \"Always\" only exists while this is the sole row —\n multi-row chains clear by removing rows instead. */}\n {rows.length === 1 ? (\n <MenuItem value=\"\">{'Always (no condition)'}</MenuItem>\n ) : null}\n <MenuItem value=\"notEmpty\">{'A field is not empty'}</MenuItem>\n <MenuItem value=\"equals\">{'A field equals…'}</MenuItem>\n <MenuItem value=\"contains\">{'A field contains…'}</MenuItem>\n </TextField>\n {row.op ? (\n <TextField\n label=\"Field\"\n placeholder=\"subscribe\"\n value={row.field}\n onChange={(event) =>\n onRowsChange((previous) =>\n previous.map((previousRow, index2) =>\n index2 === index\n ? { ...previousRow, field: event.target.value }\n : previousRow,\n ),\n )\n }\n size=\"small\"\n sx={{ flex: 1 }}\n />\n ) : null}\n {row.op === 'equals' || row.op === 'contains' ? (\n <TextField\n label=\"Value\"\n placeholder=\"Yes\"\n {...placeholderState(\n row.value,\n 'Replace the placeholder with the value to match',\n )}\n value={row.value}\n onChange={(event) =>\n onRowsChange((previous) =>\n previous.map((previousRow, index2) =>\n index2 === index\n ? { ...previousRow, value: event.target.value }\n : previousRow,\n ),\n )\n }\n size=\"small\"\n sx={{ flex: 1 }}\n />\n ) : null}\n {rows.length > 1 ? (\n <IconButton\n size=\"small\"\n aria-label=\"remove condition\"\n onClick={() =>\n onRowsChange((previous) =>\n previous.length > 1\n ? previous.filter((_, index2) => index2 !== index)\n : [EMPTY_CONDITION_ROW],\n )\n }\n >\n {'×'}\n </IconButton>\n ) : null}\n </Stack>\n ))}\n {rows.every((row) => row.op) ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Button\n size=\"small\"\n disabled={rows.length >= ACTION_MAX_CONDITIONS}\n onClick={() =>\n onRowsChange((previous) => [\n ...previous,\n // New rows start on the simplest operator so the field input\n // is immediately visible.\n { op: 'notEmpty', field: '', value: '' },\n ])\n }\n >\n {'Add condition'}\n </Button>\n {rows.length >= 2 ? (\n // AND/OR combinator (AGL-565); applies to every row.\n <TextField\n select\n label=\"Match\"\n value={combinator}\n onChange={(event) =>\n onCombinatorChange(event.target.value as TriggerCombinator)\n }\n size=\"small\"\n sx={{ minWidth: 220 }}\n >\n <MenuItem value=\"and\">{'All conditions match (AND)'}</MenuItem>\n <MenuItem value=\"or\">{'Any condition matches (OR)'}</MenuItem>\n </TextField>\n ) : null}\n </Stack>\n ) : null}\n </>\n )\n}\nTriggerConditionRows.displayName = 'TriggerConditionRows'\n"],"names":["ACTION_MAX_CONDITIONS","normalizeTriggerConditions","Button","IconButton","MenuItem","Stack","TextField","Typography","placeholderState","EMPTY_CONDITION_ROW","op","field","value","conditionRowsFromTrigger","trigger","rows","map","condition","length","conditionsFromRows","combinator","some","row","conditions","filter","trim","TriggerConditionRows","onRowsChange","onCombinatorChange","index","direction","spacing","sx","alignItems","variant","color","select","label","onChange","event","previous","previousRow","index2","target","size","minWidth","placeholder","flex","aria-label","onClick","_","every","disabled","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/components/automation-trigger-conditions.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_CONDITIONS,\n normalizeTriggerConditions,\n type TriggerCombinator,\n type TriggerConditionOp,\n} from '@aglyn/aglyn'\nimport {\n Button,\n IconButton,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { placeholderState } from './automation-step-fields.component'\nimport type { HostActionTrigger, HostActionTriggerCondition } from '../model/host-actions'\n\n/**\n * ONE TRIGGER-CONDITION EDITOR FOR EVERY AUTOMATION THAT HAS A TRIGGER.\n *\n * The structured payload conditions (AGL-557), chainable with AND/OR\n * (AGL-565): the no-code sibling of the filter expression — \"only when\n * `subscribe` is not empty\". A site action and an org automation (AGL-3302)\n * take the same clauses and are judged by the same evaluator, so they are\n * edited by the same rows.\n */\n\n/**\n * \"Form is …\" (AGL-3458): a row that picks ONE FORM by id. Stored as the\n * plain clause `formId equals <id>` — the evaluator has no form operator and\n * needs none — and read back into this row, so a condition on which form it\n * was is chosen from the site's forms rather than typed, and survives the\n * form being renamed where `formName equals …` silently stops matching.\n */\nexport const FORM_IS_OP = 'formIs'\n\n/** The payload key a \"Form is\" row compares. */\nexport const FORM_ID_FIELD = 'formId'\n\n/** One editable condition row; a lone row with an empty op means \"always run\". */\nexport interface ConditionRowDraft {\n op: '' | TriggerConditionOp | typeof FORM_IS_OP\n field: string\n value: string\n}\n\n/** A form a \"Form is\" row can pick. */\nexport interface ConditionFormOption {\n id: string\n name: string\n}\n\nexport const EMPTY_CONDITION_ROW: ConditionRowDraft = {\n op: '',\n field: '',\n value: '',\n}\n\n/**\n * A stored trigger's clauses as editor rows. A legacy single-condition trigger\n * normalizes to one row, and a trigger with none opens on the lone \"always\"\n * row.\n */\nexport function conditionRowsFromTrigger(\n trigger:\n | Pick<HostActionTrigger, 'condition' | 'conditions'>\n | null\n | undefined,\n): ConditionRowDraft[] {\n const rows = normalizeTriggerConditions(trigger).map(\n (condition): ConditionRowDraft =>\n condition.field?.trim() === FORM_ID_FIELD && condition.op === 'equals'\n ? { op: FORM_IS_OP, field: FORM_ID_FIELD, value: condition.value ?? '' }\n : {\n op: condition.op ?? '',\n field: condition.field ?? '',\n value: condition.value ?? '',\n },\n )\n return rows.length ? rows : [EMPTY_CONDITION_ROW]\n}\n\n/**\n * The rows as the stored clause list, or nothing when every row says\n * \"always\". Blank fields are kept, so the validator names what is missing.\n */\nexport function conditionsFromRows(\n rows: readonly ConditionRowDraft[],\n combinator: TriggerCombinator,\n): { conditions?: HostActionTriggerCondition[]; combinator?: TriggerCombinator } {\n if (!rows.some((row) => row.op)) return {}\n return {\n conditions: rows\n .filter((row) => row.op)\n .map((row) =>\n row.op === FORM_IS_OP\n ? { field: FORM_ID_FIELD, op: 'equals' as const, value: row.value.trim() }\n : {\n field: row.field.trim(),\n op: row.op as TriggerConditionOp,\n ...(row.op !== 'notEmpty' ? { value: row.value.trim() } : {}),\n },\n ),\n combinator,\n }\n}\n\nexport interface TriggerConditionRowsProps {\n rows: readonly ConditionRowDraft[]\n combinator: TriggerCombinator\n /** Replaces the rows, from the rows as they stand. */\n onRowsChange: (\n update: (previous: ConditionRowDraft[]) => ConditionRowDraft[],\n ) => void\n onCombinatorChange: (combinator: TriggerCombinator) => void\n /**\n * The site's forms, for a \"Form is\" row — given only where the trigger's\n * event carries the form's id. Absent, the row is offered only to show a\n * stored one, and its form is typed by id.\n */\n formOptions?: readonly ConditionFormOption[]\n}\n\n/** The condition rows, \"Add condition\", and the AND/OR choice once there are two. */\nexport function TriggerConditionRows({\n rows,\n combinator,\n onRowsChange,\n onCombinatorChange,\n formOptions,\n}: TriggerConditionRowsProps) {\n const offerForms = Boolean(formOptions) || rows.some((row) => row.op === FORM_IS_OP)\n return (\n <>\n {rows.map((row, index) => (\n <Stack\n key={index}\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center' }}\n >\n {index > 0 ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {combinator === 'or' ? 'or' : 'and'}\n </Typography>\n ) : null}\n <TextField\n select\n label={index === 0 ? 'Only run when' : 'Condition'}\n value={row.op}\n onChange={(event) =>\n onRowsChange((previous) =>\n previous.map((previousRow, index2) => {\n if (index2 !== index) return previousRow\n const op = event.target.value as ConditionRowDraft['op']\n // Into and out of \"Form is\", the field is the form's id or\n // nothing — never a leftover the author did not type.\n if (op === FORM_IS_OP) return { op, field: FORM_ID_FIELD, value: '' }\n if (previousRow.op === FORM_IS_OP) return { op, field: '', value: '' }\n return { ...previousRow, op }\n }),\n )\n }\n size=\"small\"\n sx={{ minWidth: 180 }}\n >\n {/* \"Always\" only exists while this is the sole row —\n multi-row chains clear by removing rows instead. */}\n {rows.length === 1 ? (\n <MenuItem value=\"\">{'Always (no condition)'}</MenuItem>\n ) : null}\n <MenuItem value=\"notEmpty\">{'A field is not empty'}</MenuItem>\n <MenuItem value=\"equals\">{'A field equals…'}</MenuItem>\n <MenuItem value=\"contains\">{'A field contains…'}</MenuItem>\n {offerForms ? <MenuItem value={FORM_IS_OP}>{'Form is…'}</MenuItem> : null}\n </TextField>\n {row.op === FORM_IS_OP ? (\n formOptions ? (\n <TextField\n select\n label=\"Form\"\n value={row.value}\n error={!row.value}\n helperText={row.value ? undefined : 'Pick the form'}\n onChange={(event) =>\n onRowsChange((previous) =>\n previous.map((previousRow, index2) =>\n index2 === index ? { ...previousRow, value: event.target.value } : previousRow,\n ),\n )\n }\n size=\"small\"\n sx={{ flex: 1 }}\n >\n {/* A stored id that is no longer among the site's live forms\n stays visible, so a save does not silently drop it. */}\n {row.value && !formOptions.some((form) => form.id === row.value) ? (\n <MenuItem value={row.value}>{`A form that is gone (${row.value})`}</MenuItem>\n ) : null}\n {formOptions.map((form) => (\n <MenuItem key={form.id} value={form.id}>\n {form.name}\n </MenuItem>\n ))}\n </TextField>\n ) : (\n <TextField\n label=\"Form id\"\n value={row.value}\n onChange={(event) =>\n onRowsChange((previous) =>\n previous.map((previousRow, index2) =>\n index2 === index ? { ...previousRow, value: event.target.value } : previousRow,\n ),\n )\n }\n size=\"small\"\n sx={{ flex: 1 }}\n />\n )\n ) : row.op ? (\n <TextField\n label=\"Field\"\n placeholder=\"subscribe\"\n value={row.field}\n onChange={(event) =>\n onRowsChange((previous) =>\n previous.map((previousRow, index2) =>\n index2 === index\n ? { ...previousRow, field: event.target.value }\n : previousRow,\n ),\n )\n }\n size=\"small\"\n sx={{ flex: 1 }}\n />\n ) : null}\n {row.op === 'equals' || row.op === 'contains' ? (\n <TextField\n label=\"Value\"\n placeholder=\"Yes\"\n {...placeholderState(\n row.value,\n 'Replace the placeholder with the value to match',\n )}\n value={row.value}\n onChange={(event) =>\n onRowsChange((previous) =>\n previous.map((previousRow, index2) =>\n index2 === index\n ? { ...previousRow, value: event.target.value }\n : previousRow,\n ),\n )\n }\n size=\"small\"\n sx={{ flex: 1 }}\n />\n ) : null}\n {rows.length > 1 ? (\n <IconButton\n size=\"small\"\n aria-label=\"remove condition\"\n onClick={() =>\n onRowsChange((previous) =>\n previous.length > 1\n ? previous.filter((_, index2) => index2 !== index)\n : [EMPTY_CONDITION_ROW],\n )\n }\n >\n {'×'}\n </IconButton>\n ) : null}\n </Stack>\n ))}\n {rows.every((row) => row.op) ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Button\n size=\"small\"\n disabled={rows.length >= ACTION_MAX_CONDITIONS}\n onClick={() =>\n onRowsChange((previous) => [\n ...previous,\n // New rows start on the simplest operator so the field input\n // is immediately visible.\n { op: 'notEmpty', field: '', value: '' },\n ])\n }\n >\n {'Add condition'}\n </Button>\n {rows.length >= 2 ? (\n // AND/OR combinator (AGL-565); applies to every row.\n <TextField\n select\n label=\"Match\"\n value={combinator}\n onChange={(event) =>\n onCombinatorChange(event.target.value as TriggerCombinator)\n }\n size=\"small\"\n sx={{ minWidth: 220 }}\n >\n <MenuItem value=\"and\">{'All conditions match (AND)'}</MenuItem>\n <MenuItem value=\"or\">{'Any condition matches (OR)'}</MenuItem>\n </TextField>\n ) : null}\n </Stack>\n ) : null}\n </>\n )\n}\nTriggerConditionRows.displayName = 'TriggerConditionRows'\n"],"names":["ACTION_MAX_CONDITIONS","normalizeTriggerConditions","Button","IconButton","MenuItem","Stack","TextField","Typography","placeholderState","FORM_IS_OP","FORM_ID_FIELD","EMPTY_CONDITION_ROW","op","field","value","conditionRowsFromTrigger","trigger","rows","map","condition","trim","length","conditionsFromRows","combinator","some","row","conditions","filter","TriggerConditionRows","onRowsChange","onCombinatorChange","formOptions","offerForms","Boolean","index","direction","spacing","sx","alignItems","variant","color","select","label","onChange","event","previous","previousRow","index2","target","size","minWidth","error","helperText","undefined","flex","form","id","name","placeholder","aria-label","onClick","_","every","disabled","displayName"],"mappings":"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"}