@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
@@ -16,9 +16,10 @@
16
16
  */ 'use client';
17
17
  import { _ as _extends } from "@swc/helpers/_/_extends";
18
18
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
- import { ACTION_MAX_STEPS, checkEntitlement, createResourceUid, CRM_ACTION_RECIPES, ELEMENT_SCOPED_SITE_EVENTS, HOST_ACTION_STEP_LABELS, HOST_EVENT_TYPES, hostActionDocument, hostActionRecipeId, hostEventLabel, hostEventPayloadHint, isSiteEventType, pluginDocsHelp, SITE_EVENT_TYPES, validateHostAction } from "@aglyn/aglyn";
20
- import { automationPlaceholders, describeAutomationPlaceholder } from "@aglyn/aglyn/app-utils/automation-placeholders";
19
+ import { ACTION_MAX_STEPS, checkEntitlement, createResourceUid, ELEMENT_SCOPED_SITE_EVENTS, HOST_EVENT_TYPES, hostEventLabel, HOST_EVENT_PAYLOAD_KEYS, hostEventPayloadHint, isSiteEventType, pluginDocsHelp, SITE_EVENT_TYPES, triggerFilterProblem } from "@aglyn/aglyn";
21
20
  import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot-context";
21
+ import { interactionRecipe, interactionRecipes, interactionRecipeStamp } from "@aglyn/aglyn/plugin-manager/interaction-recipes";
22
+ import { pluginRecordListQuery, pluginRecordsFromRows } from "@aglyn/aglyn/plugin-manager/plugin-record-lists";
22
23
  import { AUTOMATION_EDITOR_ZONE, HOST_AUTOMATIONS_ZONE } from "./workflow-zones.js";
23
24
  import { CardDisplay, useConfirmationContext } from "@aglyn/shared-ui-jsx";
24
25
  import { ListPagination } from "@aglyn/shared-ui-jsx/components/list-pagination.component";
@@ -35,6 +36,9 @@ import { AutomationStepFields, defaultStep } from "./automation-step-fields.comp
35
36
  import { conditionRowsFromTrigger, conditionsFromRows, EMPTY_CONDITION_ROW, TriggerConditionRows } from "./automation-trigger-conditions.component.js";
36
37
  import HostRunHistoryCard from "./host-run-history-card.component.js";
37
38
  import { EDITOR_OPTION_CEILING, useAutomationStepPickers } from "./use-automation-step-pickers.js";
39
+ import { siteInteractionDocument } from "@aglyn/aglyn/app-utils/site-interactions";
40
+ import { HOST_ACTION_STEP_LABELS, stepRunsAfterWait, validateHostAction } from "../model/host-actions.js";
41
+ import { describeInteractionPlaceholder, interactionPlaceholders } from "@aglyn/aglyn/app-utils/draft-placeholders";
38
42
  const CUSTOM_EVENT_VALUE = '__custom__';
39
43
  /**
40
44
  * How many action documents the card reads.
@@ -86,7 +90,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
86
90
  conditionCombinator: ((_action_trigger12 = action.trigger) == null ? void 0 : _action_trigger12.combinator) === 'or' ? 'or' : 'and',
87
91
  // A recipe stamps what it builds, and a stored action carries what it
88
92
  // was saved with — one reader for both doors, unknown kept unknown.
89
- recipe: hostActionRecipeId(action)
93
+ recipe: interactionRecipeStamp(action)
90
94
  };
91
95
  }
92
96
  /** A trigger bound to one element, which makes the row an interaction. */ const LEAF_SELECTOR = /^\[data-aglyn="leaf:.+"\]$/;
@@ -96,8 +100,8 @@ const CUSTOM_EVENT_VALUE = '__custom__';
96
100
  * event, dataset append). Runs server-side via runEventActions; paid
97
101
  * feature (`actions` flag, Pro+, `actionRunsPerMonth` metered).
98
102
  */ export function HostActionsCard(props) {
99
- var _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _hostEventPayloadHint, _ref6, _ref7, _ref8, _ref9, _ref10, _ref11, _ref12, _ref13, _ref14, _ref15, _ref16, _ref17, _ref18, _ref19, _runsFor_name;
100
- var _CRM_ACTION_RECIPES_find;
103
+ var _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _triggerFilterProblem, _ref8, _ref9, _ref10, _ref11, _ref12, _ref13, _ref14, _ref15, _ref16, _ref17, _ref18, _ref19, _ref20, _ref21, _ref22, _ref23, _ref24, _ref25, _ref26, _runsFor_name;
104
+ var _pickFor_picks, _HOST_EVENT_PAYLOAD_KEYS_draft_trigger_event, _interactionRecipe, _pickFor_picks1, _pickFor_picks2, _pickFor_picks3, _pickFor_picks4, _pickFor_picks5;
101
105
  const { hostId, org } = props;
102
106
  // Org-shared data root (AGL-237). Null until the org lookup settles
103
107
  // (AGL-1061), and for a host with no owning org — the pre-migration host
@@ -277,60 +281,88 @@ const CUSTOM_EVENT_VALUE = '__custom__';
277
281
  *
278
282
  * A recipe opens the editor prefilled and writes nothing: the draft it
279
283
  * builds is the one Save would persist, and until then it is state in
280
- * this card and nowhere else. Three recipes open at once; "Tag by form"
281
- * needs a form first, and the form is this site's — `hosts/{hostId}/forms`
282
- * — so the picker is the one host-scoped piece of the feature, held here
283
- * rather than in the catalog.
284
+ * this card and nowhere else. The recipes are the plugins' that write them
285
+ * (`interaction-recipes`, AGL-3080) — the CRM's "Welcome a new lead" is the
286
+ * CRM's — and this card offers whatever they registered. Most open at once;
287
+ * one that picks a record first opens a picker, and the records are listed
288
+ * through the list source the plugin that keeps them publishes, for this
289
+ * site — the one host-scoped piece of the feature, held here rather than in
290
+ * the recipe.
284
291
  */ const [recipesAnchor, setRecipesAnchor] = useState(null);
285
- const [formPickFor, setFormPickFor] = useState(null);
286
- const [pickedFormId, setPickedFormId] = useState('');
292
+ const [pickFor, setPickFor] = useState(null);
293
+ const [pickedId, setPickedId] = useState('');
287
294
  /**
288
- * The form picker has been opened at least once — the `editorOpened`
289
- * latch's twin, and for the same reason: the forms window is read for
290
- * this picker only, and a reader who never opens it pays nothing.
291
- */ const [formPickerOpened, setFormPickerOpened] = useState(false);
292
- if (formPickFor && !formPickerOpened) setFormPickerOpened(true);
293
- const { data: formRead } = useFirestoreCollection(()=>formPickerOpened ? collectionCeiling(collection(firestore, 'hosts', hostId, 'forms'), EDITOR_OPTION_CEILING) : null, [
295
+ * The picker has been opened at least once — the `editorOpened` latch's
296
+ * twin, and for the same reason: the records are read for this picker only,
297
+ * and a reader who never opens it pays nothing.
298
+ */ const pickKind = (_ref2 = pickFor == null ? void 0 : (_pickFor_picks = pickFor.picks) == null ? void 0 : _pickFor_picks.kind) != null ? _ref2 : null;
299
+ const [pickedKind, setPickedKind] = useState(null);
300
+ if (pickKind && pickKind !== pickedKind) setPickedKind(pickKind);
301
+ const { data: pickRead } = useFirestoreCollection(()=>pickedKind ? pluginRecordListQuery(pickedKind, firestore, {
302
+ hostId,
303
+ limit: EDITOR_OPTION_CEILING + 1
304
+ }) : null, [
294
305
  firestore,
295
306
  hostId,
296
- formPickerOpened
307
+ pickedKind
297
308
  ], {
298
309
  idField: '$id'
299
310
  });
300
- const { rows: formDocs, truncated: formsTruncated } = ceilingedWindow(formRead, EDITOR_OPTION_CEILING);
301
- // An archived form collects nothing, so a recipe keyed on it would never
302
- // fire; the name falls back to the id the way every form list's does.
303
- const formOptions = (formDocs != null ? formDocs : []).filter((form)=>!form.archivedAt).map((form)=>{
304
- var _form_displayName;
305
- return {
306
- id: form.$id,
307
- name: String((_form_displayName = form.displayName) != null ? _form_displayName : '').trim() || form.$id
308
- };
309
- }).sort((a, b)=>a.name.localeCompare(b.name));
311
+ const { rows: pickRows, truncated: pickTruncated } = ceilingedWindow(pickRead, EDITOR_OPTION_CEILING);
312
+ // What the owner leaves out (an archived form collects nothing, so a recipe
313
+ // keyed on it would never fire) is not offered. The facts the owner shares
314
+ // ride along to the recipe, which may shape its draft by them (AGL-3458).
315
+ const pickOptions = pluginRecordsFromRows(pickedKind != null ? pickedKind : '', pickRows).map((record)=>({
316
+ id: record.id,
317
+ name: record.name,
318
+ facts: record.facts
319
+ })).sort((a, b)=>a.name.localeCompare(b.name));
320
+ /*
321
+ * The site's forms for the trigger's "Form is" condition (AGL-3458), for an
322
+ * event that carries the form's id — through the same list source the
323
+ * recipe picker reads, latched like it: read once the editor is open on
324
+ * such an event, and never before.
325
+ */ const eventCarriesFormId = Boolean(draft && ((_HOST_EVENT_PAYLOAD_KEYS_draft_trigger_event = HOST_EVENT_PAYLOAD_KEYS[draft.trigger.event]) == null ? void 0 : _HOST_EVENT_PAYLOAD_KEYS_draft_trigger_event.includes('formId')));
326
+ const [formConditionOpened, setFormConditionOpened] = useState(false);
327
+ if (eventCarriesFormId && !formConditionOpened) setFormConditionOpened(true);
328
+ const { data: formConditionRead } = useFirestoreCollection(()=>formConditionOpened ? pluginRecordListQuery('form', firestore, {
329
+ hostId,
330
+ limit: EDITOR_OPTION_CEILING + 1
331
+ }) : null, [
332
+ firestore,
333
+ hostId,
334
+ formConditionOpened
335
+ ], {
336
+ idField: '$id'
337
+ });
338
+ const formOptions = pluginRecordsFromRows('form', ceilingedWindow(formConditionRead, EDITOR_OPTION_CEILING).rows).map((record)=>({
339
+ id: record.id,
340
+ name: record.name
341
+ })).sort((a, b)=>a.name.localeCompare(b.name));
310
342
  const handleRecipe = useCallback((recipe)=>{
311
343
  setRecipesAnchor(null);
312
344
  if (!actionsEntitled()) return;
313
- if (recipe.needs === 'form') {
314
- setPickedFormId('');
315
- setFormPickFor(recipe);
345
+ if (recipe.picks) {
346
+ setPickedId('');
347
+ setPickFor(recipe);
316
348
  return;
317
349
  }
318
350
  setDraft(draftFromAction(recipe.build(), null));
319
351
  }, [
320
352
  actionsEntitled
321
353
  ]);
322
- const handleFormPicked = useCallback(()=>{
323
- const recipe = formPickFor;
324
- const form = formOptions.find((option)=>option.id === pickedFormId);
325
- if (!recipe || !form) return;
326
- setFormPickFor(null);
354
+ const handlePicked = useCallback(()=>{
355
+ const recipe = pickFor;
356
+ const picked = pickOptions.find((option)=>option.id === pickedId);
357
+ if (!recipe || !picked) return;
358
+ setPickFor(null);
327
359
  setDraft(draftFromAction(recipe.build({
328
- form
360
+ picked
329
361
  }), null));
330
362
  }, [
331
- formPickFor,
332
- formOptions,
333
- pickedFormId
363
+ pickFor,
364
+ pickOptions,
365
+ pickedId
334
366
  ]);
335
367
  // Run log + test runs (AGL-266).
336
368
  const [runsFor, setRunsFor] = useState(null);
@@ -468,7 +500,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
468
500
  unreadable: Boolean(draft.id) && actionsStatus === 'error',
469
501
  fromCache: Boolean(draft.id) && actionsFromCache
470
502
  }, async ()=>{
471
- await setDoc(doc(firestore, 'hosts', hostId, 'actions', id), _extends({}, hostActionDocument(candidate), {
503
+ await setDoc(doc(firestore, 'hosts', hostId, 'actions', id), _extends({}, siteInteractionDocument(candidate), {
472
504
  updatedAt: Timestamp.now()
473
505
  }, draft.id ? {} : {
474
506
  createdAt: Timestamp.now()
@@ -529,11 +561,11 @@ const CUSTOM_EVENT_VALUE = '__custom__';
529
561
  * step holding it fails every run and a condition holding one never
530
562
  * matches, so turning such an automation on is confirmed, naming what
531
563
  * is still missing.
532
- */ const missing = enabled ? automationPlaceholders(action) : [];
564
+ */ const missing = enabled ? interactionPlaceholders(action) : [];
533
565
  if (missing.length) {
534
566
  const confirmed = await confirm({
535
567
  title: 'Switch on with placeholders?',
536
- description: `"${action.name}" still has ${missing.length === 1 ? 'a placeholder' : `${missing.length} placeholders`} ` + `to fill in: ${missing.slice(0, 3).map(describeAutomationPlaceholder).join('; ')}` + `${missing.length > 3 ? '; …' : ''}. Open it with Edit to fill ` + `${missing.length === 1 ? 'it' : 'them'} in first.`,
568
+ description: `"${action.name}" still has ${missing.length === 1 ? 'a placeholder' : `${missing.length} placeholders`} ` + `to fill in: ${missing.slice(0, 3).map(describeInteractionPlaceholder).join('; ')}` + `${missing.length > 3 ? '; …' : ''}. Open it with Edit to fill ` + `${missing.length === 1 ? 'it' : 'them'} in first.`,
537
569
  confirmationText: 'Switch on anyway'
538
570
  }).then(()=>true).catch(()=>false);
539
571
  if (!confirmed) return;
@@ -565,7 +597,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
565
597
  visibleActions.map((action)=>{
566
598
  var _action_steps, _ref;
567
599
  var _action_trigger, _action_trigger1;
568
- const missing = automationPlaceholders(action).length;
600
+ const missing = interactionPlaceholders(action).length;
569
601
  return /*#__PURE__*/ _jsxs(Stack, {
570
602
  direction: "row",
571
603
  spacing: 1,
@@ -682,7 +714,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
682
714
  anchorEl: recipesAnchor,
683
715
  open: Boolean(recipesAnchor),
684
716
  onClose: ()=>setRecipesAnchor(null),
685
- children: CRM_ACTION_RECIPES.map((recipe)=>/*#__PURE__*/ _jsx(MenuItem, {
717
+ children: interactionRecipes().map((recipe)=>/*#__PURE__*/ _jsx(MenuItem, {
686
718
  onClick: ()=>handleRecipe(recipe),
687
719
  children: /*#__PURE__*/ _jsx(ListItemText, {
688
720
  primary: recipe.title,
@@ -734,7 +766,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
734
766
  (draft == null ? void 0 : draft.recipe) ? /*#__PURE__*/ _jsx(Typography, {
735
767
  variant: "body2",
736
768
  color: "text.secondary",
737
- children: `Started from the “${(_ref2 = (_CRM_ACTION_RECIPES_find = CRM_ACTION_RECIPES.find((recipe)=>recipe.id === draft.recipe)) == null ? void 0 : _CRM_ACTION_RECIPES_find.title) != null ? _ref2 : 'recipe'}” recipe — change anything, then save.`
769
+ children: `Started from the “${(_ref3 = (_interactionRecipe = interactionRecipe(draft.recipe)) == null ? void 0 : _interactionRecipe.title) != null ? _ref3 : 'recipe'}” recipe — change anything, then save.`
738
770
  }) : null,
739
771
  truncatedPickers.length > 0 ? /*#__PURE__*/ _jsx(Alert, {
740
772
  severity: "info",
@@ -745,7 +777,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
745
777
  }) : null,
746
778
  /*#__PURE__*/ _jsx(TextField, {
747
779
  label: "Name",
748
- value: (_ref3 = draft == null ? void 0 : draft.name) != null ? _ref3 : '',
780
+ value: (_ref4 = draft == null ? void 0 : draft.name) != null ? _ref4 : '',
749
781
  onChange: (event)=>patch((previous)=>_extends({}, previous, {
750
782
  name: event.target.value
751
783
  })),
@@ -762,7 +794,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
762
794
  /*#__PURE__*/ _jsxs(TextField, {
763
795
  select: true,
764
796
  label: "Trigger event",
765
- value: (_ref4 = draft == null ? void 0 : draft.trigger.event) != null ? _ref4 : '',
797
+ value: (_ref5 = draft == null ? void 0 : draft.trigger.event) != null ? _ref5 : '',
766
798
  onChange: (event)=>patch((previous)=>_extends({}, previous, {
767
799
  trigger: _extends({}, previous.trigger, {
768
800
  event: event.target.value
@@ -789,7 +821,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
789
821
  }),
790
822
  (draft == null ? void 0 : draft.trigger.event) === CUSTOM_EVENT_VALUE ? /*#__PURE__*/ _jsx(TextField, {
791
823
  label: "Custom event name",
792
- value: (_ref5 = draft == null ? void 0 : draft.customEvent) != null ? _ref5 : '',
824
+ value: (_ref6 = draft == null ? void 0 : draft.customEvent) != null ? _ref6 : '',
793
825
  onChange: (event)=>patch((previous)=>_extends({}, previous, {
794
826
  customEvent: event.target.value
795
827
  })),
@@ -799,12 +831,16 @@ const CUSTOM_EVENT_VALUE = '__custom__';
799
831
  }
800
832
  }) : /*#__PURE__*/ _jsx(TextField, {
801
833
  label: "Filter (optional)",
802
- placeholder: 'path == "/pricing"',
803
- // What the expression — and the conditions below — can name
804
- // for this event; nothing for an event whose payload is not
834
+ placeholder: "subscribe",
835
+ // A comparison belongs in the conditions below: the filter's
836
+ // evaluator is arithmetic, and `path == "/pricing"` throws on
837
+ // every event, so it is refused here (AGL-3458). Otherwise,
838
+ // what the expression — and the conditions — can name for
839
+ // this event; nothing for an event whose payload is not
805
840
  // written down, rather than a guess.
806
- helperText: (_hostEventPayloadHint = hostEventPayloadHint(draft == null ? void 0 : draft.trigger.event)) != null ? _hostEventPayloadHint : undefined,
807
- value: (_ref6 = draft == null ? void 0 : draft.trigger.filter) != null ? _ref6 : '',
841
+ error: Boolean(triggerFilterProblem(draft == null ? void 0 : draft.trigger.filter)),
842
+ helperText: (_ref7 = (_triggerFilterProblem = triggerFilterProblem(draft == null ? void 0 : draft.trigger.filter)) != null ? _triggerFilterProblem : hostEventPayloadHint(draft == null ? void 0 : draft.trigger.event)) != null ? _ref7 : undefined,
843
+ value: (_ref8 = draft == null ? void 0 : draft.trigger.filter) != null ? _ref8 : '',
808
844
  onChange: (event)=>patch((previous)=>_extends({}, previous, {
809
845
  trigger: _extends({}, previous.trigger, {
810
846
  filter: event.target.value
@@ -817,25 +853,27 @@ const CUSTOM_EVENT_VALUE = '__custom__';
817
853
  })
818
854
  ]
819
855
  }),
820
- /*#__PURE__*/ _jsx(TriggerConditionRows, {
821
- rows: (_ref7 = draft == null ? void 0 : draft.conditionRows) != null ? _ref7 : [],
822
- combinator: (_ref8 = draft == null ? void 0 : draft.conditionCombinator) != null ? _ref8 : 'and',
856
+ /*#__PURE__*/ _jsx(TriggerConditionRows, _extends({
857
+ rows: (_ref9 = draft == null ? void 0 : draft.conditionRows) != null ? _ref9 : [],
858
+ combinator: (_ref10 = draft == null ? void 0 : draft.conditionCombinator) != null ? _ref10 : 'and',
823
859
  onRowsChange: (update)=>patch((previous)=>_extends({}, previous, {
824
860
  conditionRows: update(previous.conditionRows)
825
861
  })),
826
862
  onCombinatorChange: (combinator)=>patch((previous)=>_extends({}, previous, {
827
863
  conditionCombinator: combinator
828
864
  }))
829
- }),
830
- isSiteEventType((_ref9 = draft == null ? void 0 : draft.trigger.event) != null ? _ref9 : '') ? // Site-event config (AGL-256): what/where the trigger watches.
865
+ }, eventCarriesFormId ? {
866
+ formOptions
867
+ } : {})),
868
+ isSiteEventType((_ref11 = draft == null ? void 0 : draft.trigger.event) != null ? _ref11 : '') ? // Site-event config (AGL-256): what/where the trigger watches.
831
869
  /*#__PURE__*/ _jsxs(Stack, {
832
870
  direction: "row",
833
871
  spacing: 1,
834
872
  children: [
835
- ELEMENT_SCOPED_SITE_EVENTS.includes((_ref10 = draft == null ? void 0 : draft.trigger.event) != null ? _ref10 : '') ? /*#__PURE__*/ _jsx(TextField, {
873
+ ELEMENT_SCOPED_SITE_EVENTS.includes((_ref12 = draft == null ? void 0 : draft.trigger.event) != null ? _ref12 : '') ? /*#__PURE__*/ _jsx(TextField, {
836
874
  label: "CSS selector",
837
875
  placeholder: "#pricing-table",
838
- value: (_ref11 = draft == null ? void 0 : draft.trigger.selector) != null ? _ref11 : '',
876
+ value: (_ref13 = draft == null ? void 0 : draft.trigger.selector) != null ? _ref13 : '',
839
877
  onChange: (event)=>patch((previous)=>_extends({}, previous, {
840
878
  trigger: _extends({}, previous.trigger, {
841
879
  selector: event.target.value
@@ -849,10 +887,10 @@ const CUSTOM_EVENT_VALUE = '__custom__';
849
887
  [
850
888
  'scrollDepth',
851
889
  'timeOnPage'
852
- ].includes((_ref12 = draft == null ? void 0 : draft.trigger.event) != null ? _ref12 : '') ? /*#__PURE__*/ _jsx(TextField, {
890
+ ].includes((_ref14 = draft == null ? void 0 : draft.trigger.event) != null ? _ref14 : '') ? /*#__PURE__*/ _jsx(TextField, {
853
891
  type: "number",
854
892
  label: (draft == null ? void 0 : draft.trigger.event) === 'scrollDepth' ? 'Scroll %' : 'Seconds',
855
- value: (_ref13 = draft == null ? void 0 : draft.trigger.threshold) != null ? _ref13 : '',
893
+ value: (_ref15 = draft == null ? void 0 : draft.trigger.threshold) != null ? _ref15 : '',
856
894
  onChange: (event)=>patch((previous)=>_extends({}, previous, {
857
895
  trigger: _extends({}, previous.trigger, {
858
896
  threshold: Number(event.target.value)
@@ -866,7 +904,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
866
904
  /*#__PURE__*/ _jsx(TextField, {
867
905
  label: "Only on pages (optional)",
868
906
  placeholder: "/pricing or /blog/*",
869
- value: (_ref14 = draft == null ? void 0 : draft.trigger.pathPattern) != null ? _ref14 : '',
907
+ value: (_ref16 = draft == null ? void 0 : draft.trigger.pathPattern) != null ? _ref16 : '',
870
908
  onChange: (event)=>patch((previous)=>_extends({}, previous, {
871
909
  trigger: _extends({}, previous.trigger, {
872
910
  pathPattern: event.target.value
@@ -928,7 +966,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
928
966
  sx: {
929
967
  width: 150
930
968
  },
931
- value: (_ref15 = draft == null ? void 0 : draft.trigger.cooldownMinutes) != null ? _ref15 : 60,
969
+ value: (_ref17 = draft == null ? void 0 : draft.trigger.cooldownMinutes) != null ? _ref17 : 60,
932
970
  onChange: (event)=>patch((previous)=>_extends({}, previous, {
933
971
  trigger: _extends({}, previous.trigger, {
934
972
  cooldownMinutes: Number(event.target.value)
@@ -942,7 +980,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
942
980
  color: "text.secondary",
943
981
  children: 'Steps (run in order)'
944
982
  }),
945
- ((_ref16 = draft == null ? void 0 : draft.steps) != null ? _ref16 : []).map((step, index)=>/*#__PURE__*/ _jsx(AutomationStepFields, {
983
+ ((_ref18 = draft == null ? void 0 : draft.steps) != null ? _ref18 : []).map((step, index)=>/*#__PURE__*/ _jsx(AutomationStepFields, {
946
984
  step: step,
947
985
  index: index,
948
986
  kind: step.type,
@@ -951,14 +989,18 @@ const CUSTOM_EVENT_VALUE = '__custom__';
951
989
  pickers: stepPickers,
952
990
  onSteps: (update)=>patch((previous)=>_extends({}, previous, {
953
991
  steps: update(previous.steps)
954
- }))
992
+ })),
993
+ replyContext: {
994
+ event: draft == null ? void 0 : draft.trigger.event,
995
+ afterWait: stepRunsAfterWait(draft == null ? void 0 : draft.steps, index)
996
+ }
955
997
  }, index)),
956
998
  /*#__PURE__*/ _jsx(Button, {
957
999
  size: "small",
958
1000
  sx: {
959
1001
  alignSelf: 'flex-start'
960
1002
  },
961
- disabled: ((_ref17 = draft == null ? void 0 : draft.steps.length) != null ? _ref17 : 0) >= ACTION_MAX_STEPS,
1003
+ disabled: ((_ref19 = draft == null ? void 0 : draft.steps.length) != null ? _ref19 : 0) >= ACTION_MAX_STEPS,
962
1004
  onClick: ()=>patch((previous)=>_extends({}, previous, {
963
1005
  steps: [
964
1006
  ...previous.steps,
@@ -987,13 +1029,13 @@ const CUSTOM_EVENT_VALUE = '__custom__';
987
1029
  ]
988
1030
  }),
989
1031
  /*#__PURE__*/ _jsxs(Dialog, {
990
- open: Boolean(formPickFor),
991
- onClose: ()=>setFormPickFor(null),
1032
+ open: Boolean(pickFor),
1033
+ onClose: ()=>setPickFor(null),
992
1034
  maxWidth: "xs",
993
1035
  fullWidth: true,
994
1036
  children: [
995
1037
  /*#__PURE__*/ _jsx(DialogTitle, {
996
- children: (_ref18 = formPickFor == null ? void 0 : formPickFor.title) != null ? _ref18 : ''
1038
+ children: (_ref20 = pickFor == null ? void 0 : pickFor.title) != null ? _ref20 : ''
997
1039
  }),
998
1040
  /*#__PURE__*/ _jsxs(DialogContent, {
999
1041
  sx: {
@@ -1006,29 +1048,29 @@ const CUSTOM_EVENT_VALUE = '__custom__';
1006
1048
  /*#__PURE__*/ _jsx(Typography, {
1007
1049
  variant: "body2",
1008
1050
  color: "text.secondary",
1009
- children: 'Pick the form whose new contacts get the tag. The action opens ' + 'ready to edit; nothing is saved until you save it.'
1051
+ children: `${(_ref21 = pickFor == null ? void 0 : (_pickFor_picks1 = pickFor.picks) == null ? void 0 : _pickFor_picks1.prompt) != null ? _ref21 : ''} The action opens ready to edit; ` + 'nothing is saved until you save it.'
1010
1052
  }),
1011
- formsTruncated ? /*#__PURE__*/ _jsx(Alert, {
1053
+ pickTruncated ? /*#__PURE__*/ _jsx(Alert, {
1012
1054
  severity: "info",
1013
- children: `Offering the first ${EDITOR_OPTION_CEILING} forms, ordered by ` + 'id. This site has more, so the form you want may not be listed.'
1055
+ children: `Offering the first ${EDITOR_OPTION_CEILING} ${(_ref22 = pickFor == null ? void 0 : (_pickFor_picks2 = pickFor.picks) == null ? void 0 : _pickFor_picks2.plural) != null ? _ref22 : ''}, ` + `ordered by id. This site has more, so the ` + `${((_ref23 = pickFor == null ? void 0 : (_pickFor_picks3 = pickFor.picks) == null ? void 0 : _pickFor_picks3.label) != null ? _ref23 : '').toLowerCase()} you want may not be listed.`
1014
1056
  }) : null,
1015
- formOptions.length ? /*#__PURE__*/ _jsx(TextField, {
1057
+ pickOptions.length ? /*#__PURE__*/ _jsx(TextField, {
1016
1058
  select: true,
1017
- label: "Form",
1018
- value: pickedFormId,
1019
- onChange: (event)=>setPickedFormId(event.target.value),
1059
+ label: (_ref24 = pickFor == null ? void 0 : (_pickFor_picks4 = pickFor.picks) == null ? void 0 : _pickFor_picks4.label) != null ? _ref24 : '',
1060
+ value: pickedId,
1061
+ onChange: (event)=>setPickedId(event.target.value),
1020
1062
  size: "small",
1021
1063
  sx: {
1022
1064
  mt: 1
1023
1065
  },
1024
- children: formOptions.map((option)=>/*#__PURE__*/ _jsx(MenuItem, {
1066
+ children: pickOptions.map((option)=>/*#__PURE__*/ _jsx(MenuItem, {
1025
1067
  value: option.id,
1026
1068
  children: option.name
1027
1069
  }, option.id))
1028
1070
  }) : /*#__PURE__*/ _jsx(Typography, {
1029
1071
  variant: "body2",
1030
1072
  color: "text.secondary",
1031
- children: 'This site has no forms yet. Add one in the besigner, then come back.'
1073
+ children: (_ref25 = pickFor == null ? void 0 : (_pickFor_picks5 = pickFor.picks) == null ? void 0 : _pickFor_picks5.none) != null ? _ref25 : ''
1032
1074
  })
1033
1075
  ]
1034
1076
  }),
@@ -1036,13 +1078,13 @@ const CUSTOM_EVENT_VALUE = '__custom__';
1036
1078
  children: [
1037
1079
  /*#__PURE__*/ _jsx(Button, {
1038
1080
  color: "inherit",
1039
- onClick: ()=>setFormPickFor(null),
1081
+ onClick: ()=>setPickFor(null),
1040
1082
  children: 'Cancel'
1041
1083
  }),
1042
1084
  /*#__PURE__*/ _jsx(Button, {
1043
1085
  variant: "contained",
1044
- disabled: !pickedFormId,
1045
- onClick: handleFormPicked,
1086
+ disabled: !pickedId,
1087
+ onClick: handlePicked,
1046
1088
  children: 'Use recipe'
1047
1089
  })
1048
1090
  ]
@@ -1057,7 +1099,7 @@ const CUSTOM_EVENT_VALUE = '__custom__';
1057
1099
  fullWidth: true,
1058
1100
  children: [
1059
1101
  /*#__PURE__*/ _jsx(DialogTitle, {
1060
- children: `Runs — ${(_ref19 = runsFor == null ? void 0 : runsFor.name) != null ? _ref19 : ''}`
1102
+ children: `Runs — ${(_ref26 = runsFor == null ? void 0 : runsFor.name) != null ? _ref26 : ''}`
1061
1103
  }),
1062
1104
  /*#__PURE__*/ _jsx(DialogContent, {
1063
1105
  children: runsFor ? /*#__PURE__*/ _jsx(HostRunHistoryCard, {