@aglyn/plugins-marketing 1.0.0-beta.229 → 1.0.0-beta.231

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 (51) hide show
  1. package/README.md +2 -2
  2. package/package.json +16 -15
  3. package/src/lib/components/campaign-conversions-card.js +23 -11
  4. package/src/lib/components/campaign-conversions-card.js.map +1 -1
  5. package/src/lib/components/campaign-list-zones.d.ts +33 -0
  6. package/src/lib/components/campaign-list-zones.js +30 -0
  7. package/src/lib/components/campaign-list-zones.js.map +1 -0
  8. package/src/lib/components/campaign-report-card.js +20 -3
  9. package/src/lib/components/campaign-report-card.js.map +1 -1
  10. package/src/lib/components/campaigns-card.js +42 -13
  11. package/src/lib/components/campaigns-card.js.map +1 -1
  12. package/src/lib/components/experiment-zones.d.ts +11 -0
  13. package/src/lib/components/experiment-zones.js.map +1 -1
  14. package/src/lib/components/host-experiments-card.component.js +5 -1
  15. package/src/lib/components/host-experiments-card.component.js.map +1 -1
  16. package/src/lib/components/host-overlays-card.component.js +139 -24
  17. package/src/lib/components/host-overlays-card.component.js.map +1 -1
  18. package/src/lib/components/marketing-insight-zones.d.ts +28 -0
  19. package/src/lib/components/marketing-insight-zones.js +30 -0
  20. package/src/lib/components/marketing-insight-zones.js.map +1 -0
  21. package/src/lib/components/overlay-zones.d.ts +84 -0
  22. package/src/lib/components/overlay-zones.js +38 -0
  23. package/src/lib/components/overlay-zones.js.map +1 -0
  24. package/src/lib/components/site-runtime.js +10 -1
  25. package/src/lib/components/site-runtime.js.map +1 -1
  26. package/src/lib/model/campaign-list-query.d.ts +2 -2
  27. package/src/lib/model/campaign-list-query.js.map +1 -1
  28. package/src/lib/model/index.d.ts +1 -0
  29. package/src/lib/model/index.js +1 -0
  30. package/src/lib/model/index.js.map +1 -1
  31. package/src/lib/model/overlay-drafts.d.ts +97 -0
  32. package/src/lib/model/overlay-drafts.js +192 -0
  33. package/src/lib/model/overlay-drafts.js.map +1 -0
  34. package/src/lib/plugin.js +12 -0
  35. package/src/lib/plugin.js.map +1 -1
  36. package/src/lib/server/email-events.js +8 -0
  37. package/src/lib/server/email-events.js.map +1 -1
  38. package/src/lib/server/marketing-ai-capabilities.d.ts +24 -0
  39. package/src/lib/server/marketing-ai-capabilities.js +225 -0
  40. package/src/lib/server/marketing-ai-capabilities.js.map +1 -0
  41. package/src/lib/server/marketing-drafts.d.ts +86 -0
  42. package/src/lib/server/marketing-drafts.js +354 -0
  43. package/src/lib/server/marketing-drafts.js.map +1 -0
  44. package/src/lib/server/marketing-figures.d.ts +18 -0
  45. package/src/lib/server/marketing-figures.js +259 -1
  46. package/src/lib/server/marketing-figures.js.map +1 -1
  47. package/src/lib/server/overlay-figures.d.ts +36 -0
  48. package/src/lib/server/overlay-figures.js +158 -0
  49. package/src/lib/server/overlay-figures.js.map +1 -0
  50. package/src/lib/server.js +10 -0
  51. package/src/lib/server.js.map +1 -1
@@ -18,7 +18,7 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
18
18
  import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
19
19
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
20
20
  import { checkEntitlement, createResourceUid, pluginDocsHelp } from "@aglyn/aglyn";
21
- import { compareOverlayPrecedence, overlayStatus } from "../model/index.js";
21
+ import { compareOverlayPrecedence, OVERLAY_COPY_LIMITS, OVERLAY_LIST_CEILING, OVERLAY_POPUP_TRIGGERS, overlayCopyFromProposal, overlayDraftFromProposal, overlayStatus } from "../model/index.js";
22
22
  import { mdiChevronDown, mdiChevronUp } from "@aglyn/shared-data-mdi";
23
23
  import { CardDisplay, MdiIcon, useConfirmationContext } from "@aglyn/shared-ui-jsx";
24
24
  import { ScrollTable } from "@aglyn/shared-ui-jsx/components/scroll-table.component";
@@ -31,6 +31,7 @@ import { useFirestore, useFirestoreCollection, useHostActivityLogger, writeGuard
31
31
  import { writeSiteWideChange } from "@aglyn/tenant-feature-instance/hooks/helpers/site-wide-change";
32
32
  import { overlayDisplayName, overlayEngagementLabel, overlayPagesLabel, overlayWindowLabel } from "./overlay-labels.js";
33
33
  import { OVERLAY_COPY_HELPER_TEXT, shownAsTypedHelperText, useOverlayCopyEditor } from "./use-overlay-copy-editor.js";
34
+ import { HostOverlaysZone, OverlayEditorZone } from "./overlay-zones.js";
34
35
  /**
35
36
  * How many overlays the card reads.
36
37
  *
@@ -38,7 +39,7 @@ import { OVERLAY_COPY_HELPER_TEXT, shownAsTypedHelperText, useOverlayCopyEditor
38
39
  * one list is deliberately not paginated. Generous on purpose: a site runs a
39
40
  * handful of banners and popups, and the number exists to bound a pathological
40
41
  * collection rather than to bound a normal one.
41
- */ const CEILING = 50;
42
+ */ const CEILING = OVERLAY_LIST_CEILING;
42
43
  const EMPTY_BAR = {
43
44
  kind: 'bar',
44
45
  enabled: true,
@@ -77,8 +78,8 @@ function parsePatterns(value) {
77
78
  * text and a popup's headline and body are edited through
78
79
  * `useOverlayCopyEditor`, like the single bar and popup cards (AGL-2885).
79
80
  */ export function HostOverlaysCard(props) {
80
- var _ref, _editor_name, _shownAsTypedHelperText, _ref1, _ref2, _ref3, _shownAsTypedHelperText1, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9, _editor_pathPatterns, _editor_excludePathPatterns;
81
- var _editor_bar, _editor_popup, _editor_popup1, _editor_bar1, _editor_popup2, _editor_popup3, _editor_bar2, _editor_bar3, _editor_bar4, _editor_bar5, _editor_popup4, _editor_popup5, _editor_popup6, _editor_popup7, _editor_popup8, _editor_popup9, _editor_popup10, _editor_popup11, _editor_popup12, _editor_popup13, _editor_bar6, _editor_popup14, _editor_popup15;
81
+ var _ref, _editor_name, _editor_$id, _editor_name1, _ref1, _ref2, _ref3, _ref4, _shownAsTypedHelperText, _ref5, _ref6, _ref7, _shownAsTypedHelperText1, _ref8, _ref9, _ref10, _ref11, _ref12, _ref13, _editor_pathPatterns, _editor_excludePathPatterns;
82
+ var _editor_bar, _editor_popup, _editor_popup1, _editor_bar1, _editor_popup2, _editor_popup3, _editor_bar2, _editor_popup4, _editor_popup5, _editor_popup6, _editor_popup7, _editor_popup8, _editor_popup9, _editor_bar3, _editor_bar4, _editor_bar5, _editor_bar6, _editor_popup10, _editor_popup11, _editor_popup12, _editor_popup13, _editor_popup14, _editor_popup15, _editor_popup16, _editor_popup17, _editor_popup18, _editor_popup19, _editor_bar7, _editor_popup20, _editor_popup21;
82
83
  const { hostId } = props;
83
84
  const firestore = useFirestore();
84
85
  const { data: user } = useUser();
@@ -259,6 +260,88 @@ function parsePatterns(value) {
259
260
  });
260
261
  }
261
262
  };
263
+ /*
264
+ * What a widget in the list's zone asks for (AGL-3603): a new overlay from
265
+ * proposed copy, cut to the overlay's limits and written SWITCHED OFF —
266
+ * through the same site-wide write a typed overlay takes — then opened in
267
+ * the editor, where a person reads it, changes it and turns it on.
268
+ */ const createOverlayDraft = async (kind, proposal)=>{
269
+ var _draft_name;
270
+ const draft = overlayDraftFromProposal(kind, proposal);
271
+ if (!draft) {
272
+ return {
273
+ ok: false,
274
+ error: kind === 'bar' ? 'There was no bar text to save.' : 'There was no popup body to save.'
275
+ };
276
+ }
277
+ const id = createResourceUid();
278
+ // The list orders on `name`, which every overlay carries, null or not.
279
+ const stored = _extends({}, draft, {
280
+ name: (_draft_name = draft.name) != null ? _draft_name : null
281
+ });
282
+ try {
283
+ await writeSiteWideChange({
284
+ firestore,
285
+ user,
286
+ hostId,
287
+ write: (batch)=>batch.set(doc(firestore, 'hosts', hostId, 'overlays', id), _extends({}, stored, {
288
+ createdAt: Timestamp.now(),
289
+ updatedAt: Timestamp.now()
290
+ }))
291
+ });
292
+ } catch (error) {
293
+ console.error(error);
294
+ return {
295
+ ok: false,
296
+ error: 'The overlay could not be saved. Try again.'
297
+ };
298
+ }
299
+ logActivity('Created overlay', _extends({
300
+ type: 'content',
301
+ id
302
+ }, draft.name ? {
303
+ name: draft.name
304
+ } : {}));
305
+ setEditor(_extends({}, draft, {
306
+ $id: id
307
+ }));
308
+ return {
309
+ ok: true,
310
+ id
311
+ };
312
+ };
313
+ /*
314
+ * What a widget in the editor's zone proposes (AGL-3603), put into the
315
+ * editor's own fields unsaved. Copy is stored as the editor stores typed
316
+ * copy, so a proposed variable name is kept the way a typed one is.
317
+ */ const proposeOverlayCopy = (proposal)=>{
318
+ if (!editor) return;
319
+ const values = overlayCopyFromProposal(editor.kind, proposal);
320
+ if (values.name) patch({
321
+ name: values.name
322
+ });
323
+ if (editor.kind === 'bar') {
324
+ if (values.text) patchBar({
325
+ text: copy.stored(values.text)
326
+ });
327
+ return;
328
+ }
329
+ patchPopup(_extends({}, values.headline ? {
330
+ headline: copy.stored(values.headline)
331
+ } : {}, values.body ? {
332
+ body: copy.stored(values.body)
333
+ } : {}, values.ctaLabel ? {
334
+ ctaLabel: values.ctaLabel
335
+ } : {}, values.trigger ? {
336
+ trigger: values.trigger
337
+ } : {}, values.triggerValue !== undefined ? {
338
+ triggerValue: values.triggerValue
339
+ } : {}));
340
+ };
341
+ const overlayRules = {
342
+ limits: OVERLAY_COPY_LIMITS,
343
+ triggers: OVERLAY_POPUP_TRIGGERS
344
+ };
262
345
  const handleDelete = async (overlay)=>{
263
346
  var _overlay_name;
264
347
  if (!overlay.$id) return;
@@ -389,17 +472,33 @@ function parsePatterns(value) {
389
472
  variant: "contained",
390
473
  onClick: ()=>setEditor(_extends({}, EMPTY_POPUP)),
391
474
  children: 'New popup'
392
- })
475
+ }),
476
+ /*#__PURE__*/ _jsx(HostOverlaysZone, _extends({
477
+ hostId: hostId,
478
+ createOverlayDraft: createOverlayDraft
479
+ }, overlayRules))
393
480
  ]
394
481
  }),
395
482
  truncated ? /*#__PURE__*/ _jsx(Alert, {
396
483
  severity: "info",
397
484
  children: `Showing ${CEILING} overlays, ordered by name. This site has ` + 'more than that — delete the ones you have finished with, or ' + 'the ones below the ceiling cannot be reordered against them.'
398
485
  }) : null,
399
- overlays.length === 0 ? /*#__PURE__*/ _jsx(Typography, {
400
- variant: "body2",
401
- color: "text.secondary",
402
- children: 'No overlays yet — the single announcement bar and popup ' + 'below keep working as your default surfaces.'
486
+ overlays.length === 0 ? /*#__PURE__*/ _jsxs(Stack, {
487
+ spacing: 1,
488
+ sx: {
489
+ alignItems: 'flex-start'
490
+ },
491
+ children: [
492
+ /*#__PURE__*/ _jsx(Typography, {
493
+ variant: "body2",
494
+ color: "text.secondary",
495
+ children: 'No overlays yet — the single announcement bar and popup ' + 'below keep working as your default surfaces.'
496
+ }),
497
+ /*#__PURE__*/ _jsx(HostOverlaysZone, _extends({
498
+ hostId: hostId,
499
+ createOverlayDraft: createOverlayDraft
500
+ }, overlayRules))
501
+ ]
403
502
  }) : /*#__PURE__*/ _jsxs(ScrollTable, {
404
503
  size: "small",
405
504
  children: [
@@ -539,13 +638,29 @@ function parsePatterns(value) {
539
638
  }),
540
639
  helperText: "Internal label shown in this list"
541
640
  }),
641
+ /*#__PURE__*/ _jsx(OverlayEditorZone, _extends({
642
+ hostId: hostId,
643
+ overlayId: (_editor_$id = editor.$id) != null ? _editor_$id : '',
644
+ kind: editor.kind,
645
+ copy: {
646
+ name: (_editor_name1 = editor.name) != null ? _editor_name1 : '',
647
+ text: copy.editable((_editor_bar2 = editor.bar) == null ? void 0 : _editor_bar2.text),
648
+ headline: copy.editable((_editor_popup4 = editor.popup) == null ? void 0 : _editor_popup4.headline),
649
+ body: copy.editable((_editor_popup5 = editor.popup) == null ? void 0 : _editor_popup5.body),
650
+ ctaLabel: (_ref1 = (_editor_popup6 = editor.popup) == null ? void 0 : _editor_popup6.ctaLabel) != null ? _ref1 : '',
651
+ ctaHref: (_ref2 = (_editor_popup7 = editor.popup) == null ? void 0 : _editor_popup7.ctaHref) != null ? _ref2 : '',
652
+ trigger: (_ref3 = (_editor_popup8 = editor.popup) == null ? void 0 : _editor_popup8.trigger) != null ? _ref3 : 'delay',
653
+ triggerValue: (_ref4 = (_editor_popup9 = editor.popup) == null ? void 0 : _editor_popup9.triggerValue) != null ? _ref4 : null
654
+ },
655
+ proposeValues: proposeOverlayCopy
656
+ }, overlayRules)),
542
657
  editor.kind === 'bar' ? /*#__PURE__*/ _jsxs(_Fragment, {
543
658
  children: [
544
659
  /*#__PURE__*/ _jsx(TextField, {
545
660
  size: "small",
546
661
  label: "Text",
547
662
  required: true,
548
- value: copy.editable((_editor_bar2 = editor.bar) == null ? void 0 : _editor_bar2.text),
663
+ value: copy.editable((_editor_bar3 = editor.bar) == null ? void 0 : _editor_bar3.text),
549
664
  onChange: (event)=>patchBar({
550
665
  text: copy.stored(event.target.value)
551
666
  }),
@@ -555,7 +670,7 @@ function parsePatterns(value) {
555
670
  /*#__PURE__*/ _jsx(TextField, {
556
671
  size: "small",
557
672
  label: "Link (optional)",
558
- value: (_ref1 = (_editor_bar3 = editor.bar) == null ? void 0 : _editor_bar3.href) != null ? _ref1 : '',
673
+ value: (_ref5 = (_editor_bar4 = editor.bar) == null ? void 0 : _editor_bar4.href) != null ? _ref5 : '',
559
674
  onChange: (event)=>patchBar({
560
675
  href: event.target.value
561
676
  })
@@ -567,7 +682,7 @@ function parsePatterns(value) {
567
682
  /*#__PURE__*/ _jsx(TextField, {
568
683
  size: "small",
569
684
  label: "Background color",
570
- value: (_ref2 = (_editor_bar4 = editor.bar) == null ? void 0 : _editor_bar4.backgroundColor) != null ? _ref2 : '',
685
+ value: (_ref6 = (_editor_bar5 = editor.bar) == null ? void 0 : _editor_bar5.backgroundColor) != null ? _ref6 : '',
571
686
  onChange: (event)=>patchBar({
572
687
  backgroundColor: event.target.value
573
688
  })
@@ -575,7 +690,7 @@ function parsePatterns(value) {
575
690
  /*#__PURE__*/ _jsx(TextField, {
576
691
  size: "small",
577
692
  label: "Text color",
578
- value: (_ref3 = (_editor_bar5 = editor.bar) == null ? void 0 : _editor_bar5.textColor) != null ? _ref3 : '',
693
+ value: (_ref7 = (_editor_bar6 = editor.bar) == null ? void 0 : _editor_bar6.textColor) != null ? _ref7 : '',
579
694
  onChange: (event)=>patchBar({
580
695
  textColor: event.target.value
581
696
  })
@@ -588,7 +703,7 @@ function parsePatterns(value) {
588
703
  /*#__PURE__*/ _jsx(TextField, {
589
704
  size: "small",
590
705
  label: "Headline",
591
- value: copy.editable((_editor_popup4 = editor.popup) == null ? void 0 : _editor_popup4.headline),
706
+ value: copy.editable((_editor_popup10 = editor.popup) == null ? void 0 : _editor_popup10.headline),
592
707
  onChange: (event)=>patchPopup({
593
708
  headline: copy.stored(event.target.value)
594
709
  }),
@@ -601,7 +716,7 @@ function parsePatterns(value) {
601
716
  required: true,
602
717
  multiline: true,
603
718
  minRows: 2,
604
- value: copy.editable((_editor_popup5 = editor.popup) == null ? void 0 : _editor_popup5.body),
719
+ value: copy.editable((_editor_popup11 = editor.popup) == null ? void 0 : _editor_popup11.body),
605
720
  onChange: (event)=>patchPopup({
606
721
  body: copy.stored(event.target.value)
607
722
  }),
@@ -615,7 +730,7 @@ function parsePatterns(value) {
615
730
  /*#__PURE__*/ _jsx(TextField, {
616
731
  size: "small",
617
732
  label: "CTA label",
618
- value: (_ref4 = (_editor_popup6 = editor.popup) == null ? void 0 : _editor_popup6.ctaLabel) != null ? _ref4 : '',
733
+ value: (_ref8 = (_editor_popup12 = editor.popup) == null ? void 0 : _editor_popup12.ctaLabel) != null ? _ref8 : '',
619
734
  onChange: (event)=>patchPopup({
620
735
  ctaLabel: event.target.value
621
736
  })
@@ -623,7 +738,7 @@ function parsePatterns(value) {
623
738
  /*#__PURE__*/ _jsx(TextField, {
624
739
  size: "small",
625
740
  label: "CTA link",
626
- value: (_ref5 = (_editor_popup7 = editor.popup) == null ? void 0 : _editor_popup7.ctaHref) != null ? _ref5 : '',
741
+ value: (_ref9 = (_editor_popup13 = editor.popup) == null ? void 0 : _editor_popup13.ctaHref) != null ? _ref9 : '',
627
742
  onChange: (event)=>patchPopup({
628
743
  ctaHref: event.target.value
629
744
  })
@@ -641,7 +756,7 @@ function parsePatterns(value) {
641
756
  sx: {
642
757
  minWidth: 140
643
758
  },
644
- value: (_ref6 = (_editor_popup8 = editor.popup) == null ? void 0 : _editor_popup8.trigger) != null ? _ref6 : 'delay',
759
+ value: (_ref10 = (_editor_popup14 = editor.popup) == null ? void 0 : _editor_popup14.trigger) != null ? _ref10 : 'delay',
645
760
  onChange: (event)=>patchPopup({
646
761
  trigger: event.target.value
647
762
  }),
@@ -663,8 +778,8 @@ function parsePatterns(value) {
663
778
  /*#__PURE__*/ _jsx(TextField, {
664
779
  size: "small",
665
780
  type: "number",
666
- label: ((_ref7 = (_editor_popup9 = editor.popup) == null ? void 0 : _editor_popup9.trigger) != null ? _ref7 : 'delay') === 'scroll' ? 'Scroll %' : 'Seconds',
667
- value: (_ref8 = (_editor_popup10 = editor.popup) == null ? void 0 : _editor_popup10.triggerValue) != null ? _ref8 : 3,
781
+ label: ((_ref11 = (_editor_popup15 = editor.popup) == null ? void 0 : _editor_popup15.trigger) != null ? _ref11 : 'delay') === 'scroll' ? 'Scroll %' : 'Seconds',
782
+ value: (_ref12 = (_editor_popup16 = editor.popup) == null ? void 0 : _editor_popup16.triggerValue) != null ? _ref12 : 3,
668
783
  onChange: (event)=>patchPopup({
669
784
  triggerValue: Number(event.target.value)
670
785
  })
@@ -673,7 +788,7 @@ function parsePatterns(value) {
673
788
  select: true,
674
789
  size: "small",
675
790
  label: "Frequency",
676
- value: ((_editor_popup11 = editor.popup) == null ? void 0 : _editor_popup11.oncePerSession) ? 'session' : 'days',
791
+ value: ((_editor_popup17 = editor.popup) == null ? void 0 : _editor_popup17.oncePerSession) ? 'session' : 'days',
677
792
  onChange: (event)=>patchPopup({
678
793
  oncePerSession: event.target.value === 'session'
679
794
  }),
@@ -691,11 +806,11 @@ function parsePatterns(value) {
691
806
  })
692
807
  ]
693
808
  }),
694
- ((_editor_popup12 = editor.popup) == null ? void 0 : _editor_popup12.oncePerSession) ? null : /*#__PURE__*/ _jsx(TextField, {
809
+ ((_editor_popup18 = editor.popup) == null ? void 0 : _editor_popup18.oncePerSession) ? null : /*#__PURE__*/ _jsx(TextField, {
695
810
  size: "small",
696
811
  type: "number",
697
812
  label: "Re-show after (days)",
698
- value: (_ref9 = (_editor_popup13 = editor.popup) == null ? void 0 : _editor_popup13.frequencyDays) != null ? _ref9 : 7,
813
+ value: (_ref13 = (_editor_popup19 = editor.popup) == null ? void 0 : _editor_popup19.frequencyDays) != null ? _ref13 : 7,
699
814
  onChange: (event)=>patchPopup({
700
815
  frequencyDays: Number(event.target.value)
701
816
  })
@@ -769,7 +884,7 @@ function parsePatterns(value) {
769
884
  variant: "contained",
770
885
  color: "primary",
771
886
  onClick: handleSave,
772
- disabled: copy.pending(editor == null ? void 0 : (_editor_bar6 = editor.bar) == null ? void 0 : _editor_bar6.text, editor == null ? void 0 : (_editor_popup14 = editor.popup) == null ? void 0 : _editor_popup14.headline, editor == null ? void 0 : (_editor_popup15 = editor.popup) == null ? void 0 : _editor_popup15.body),
887
+ disabled: copy.pending(editor == null ? void 0 : (_editor_bar7 = editor.bar) == null ? void 0 : _editor_bar7.text, editor == null ? void 0 : (_editor_popup20 = editor.popup) == null ? void 0 : _editor_popup20.headline, editor == null ? void 0 : (_editor_popup21 = editor.popup) == null ? void 0 : _editor_popup21.body),
773
888
  children: 'Save'
774
889
  })
775
890
  ]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/marketing/src/lib/components/host-overlays-card.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 type AglynOrgBilling,\n checkEntitlement,\n createResourceUid,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport {\n compareOverlayPrecedence,\n overlayStatus,\n type HostOverlay,\n} from '../model'\nimport { mdiChevronDown, mdiChevronUp } from '@aglyn/shared-data-mdi'\nimport {\n CardDisplay,\n MdiIcon,\n useConfirmationContext,\n} from '@aglyn/shared-ui-jsx'\nimport { ScrollTable } from '@aglyn/shared-ui-jsx/components/scroll-table.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { Timestamp } from '@aglyn/shared-util-timestamp'\nimport {\n Alert,\n Button,\n Chip,\n IconButton,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n Stack,\n Switch,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material'\nimport { collection, doc, limit, orderBy, query } from 'firebase/firestore'\nimport { useState } from 'react'\nimport {\n useFirestore,\n useFirestoreCollection,\n useHostActivityLogger,\n writeGuardedBySeed,\n useUser,\n} from '@aglyn/tenant-feature-instance'\nimport { writeSiteWideChange } from '@aglyn/tenant-feature-instance/hooks/helpers/site-wide-change'\nimport {\n overlayDisplayName,\n overlayEngagementLabel,\n overlayPagesLabel,\n overlayWindowLabel,\n} from './overlay-labels'\nimport {\n OVERLAY_COPY_HELPER_TEXT,\n shownAsTypedHelperText,\n useOverlayCopyEditor,\n} from './use-overlay-copy-editor'\n\nexport interface HostOverlaysCardProps {\n hostId: string\n /** Resolved entitlement source (AGL-395). */\n org?: Partial<AglynOrgBilling>\n}\n\ntype OverlayDraft = HostOverlay & { $id?: string }\n\n/**\n * How many overlays the card reads.\n *\n * A ceiling rather than a page size — see the query, which explains why this\n * one list is deliberately not paginated. Generous on purpose: a site runs a\n * handful of banners and popups, and the number exists to bound a pathological\n * collection rather than to bound a normal one.\n */\nconst CEILING = 50\n\nconst EMPTY_BAR: OverlayDraft = {\n kind: 'bar',\n enabled: true,\n bar: { dismissible: true },\n}\nconst EMPTY_POPUP: OverlayDraft = {\n kind: 'popup',\n enabled: true,\n popup: { trigger: 'delay', triggerValue: 3, frequencyDays: 7 },\n}\n\nfunction toDatetimeLocal(ms?: number): string {\n if (!ms) return ''\n const date = new Date(ms)\n const pad = (value: number) => String(value).padStart(2, '0')\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-` +\n `${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`\n )\n}\n\nfunction fromDatetimeLocal(value: string): number | undefined {\n if (!value) return undefined\n const ms = new Date(value).getTime()\n return Number.isFinite(ms) ? ms : undefined\n}\n\nfunction parsePatterns(value: string): string[] {\n return value\n .split(',')\n .map((pattern) => pattern.trim())\n .filter(Boolean)\n}\n\n/**\n * Marketing hub overlays manager (AGL-251): multiple announcement bars\n * and popups at `hosts/{hostId}/overlays`, each with a schedule window\n * and page targeting; the tenant render shows the first active match per\n * kind (overlay docs win over the legacy single bar/popup fields). A bar's\n * text and a popup's headline and body are edited through\n * `useOverlayCopyEditor`, like the single bar and popup cards (AGL-2885).\n */\nexport function HostOverlaysCard(props: HostOverlaysCardProps) {\n const { hostId } = props\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { org } = props\n const { enqueueSnackbar } = useSnackbar()\n const { confirm } = useConfirmationContext()\n const logActivity = useHostActivityLogger(hostId)\n const entitled = checkEntitlement(org, 'marketingOverlays')\n\n const {\n data: overlayDocs,\n status: overlaysStatus,\n /**\n * The overlay rows the editor is seeded from are unconfirmed by the\n * server (AGL-1358). Editing one spreads the whole stored row into\n * `editor` and writes it back with NO options argument at all — a full\n * document replace — so a cached seed reverts every field nobody\n * touched. Including `stats`, the lifetime impression/click/dismissal\n * counters the org beacon increments: a save here would roll live\n * engagement numbers back to whenever the snapshot was taken.\n */\n fromCache: overlaysFromCache,\n } = useFirestoreCollection<any>(\n () =>\n query(\n collection(firestore, 'hosts', hostId, 'overlays'),\n /*\n * ORDERED AND CEILINGED, deliberately not paged (AGL-2501).\n *\n * ## Why the read is ordered\n *\n * `limit(50)` alone is answered in DOCUMENT-ID order over ids from\n * `createResourceUid()`, so the window was a pseudo-random fifty that\n * the client sort below arranged into a believable precedence list.\n * `name` is the one field every overlay carries: `handleSave` writes\n * `name: (…).trim() || null` on every save, and it is the only writer\n * that CREATES one — the analytics beacon uses `update()` precisely so\n * a stale page cannot mint a stats-only stray, and `overlays` is not\n * in `IMPORTABLE_FIELDS`, so no restore path makes one either. A null\n * name still matches an `orderBy`; an ABSENT field would not.\n *\n * ## Why this list is not paged\n *\n * The row order IS the feature: the first enabled overlay of each kind\n * is the one a visitor sees (AGL-270), and the arrows reorder by\n * swapping `order` with the ADJACENT row. A page boundary separates a\n * row from the neighbor it would swap with, so the eleventh overlay\n * could never be moved into tenth place — the same reason the console's\n * screen tree and starter bundles are ceilinged rather than paged.\n *\n * `orderBy('order')` is not an option either, and that is what makes\n * the precedence sort a client-side one: `EMPTY_BAR` and `EMPTY_POPUP`\n * carry no `order`, and only `handleMove` ever writes one, so ordering\n * the query on it would hide every overlay nobody has reordered rather\n * than mis-sorting it. The client sort holds the WHOLE window, which is\n * what makes sorting it here honest.\n */\n orderBy('name'),\n // One past the ceiling, so \"there are more overlays than these\" is a\n // fact rather than a guess from `length === 50`.\n limit(CEILING + 1),\n ),\n [firestore, hostId],\n { idField: '$id' },\n )\n const truncated = (overlayDocs?.length ?? 0) > CEILING\n const overlays: OverlayDraft[] = [...(overlayDocs ?? [])]\n .slice(0, CEILING)\n .sort(compareOverlayPrecedence)\n\n const [editor, setEditor] = useState<OverlayDraft | null>(null)\n // The editor's copy is held in its stored form; the fields show it as typed.\n const copy = useOverlayCopyEditor({\n hostId,\n usesTokens:\n entitled &&\n [editor?.bar?.text, editor?.popup?.headline, editor?.popup?.body].some(\n (text) => text?.includes('{{'),\n ),\n })\n const barTextShownAsTyped = copy.shownAsTyped(editor?.bar?.text)\n const headlineShownAsTyped = copy.shownAsTyped(editor?.popup?.headline)\n const bodyShownAsTyped = copy.shownAsTyped(editor?.popup?.body)\n const patch = (partial: Partial<OverlayDraft>) =>\n setEditor((previous) => (previous ? { ...previous, ...partial } : previous))\n const patchBar = (partial: Partial<NonNullable<OverlayDraft['bar']>>) =>\n setEditor((previous) =>\n previous\n ? { ...previous, bar: { ...(previous.bar ?? {}), ...partial } }\n : previous,\n )\n const patchPopup = (partial: Partial<NonNullable<OverlayDraft['popup']>>) =>\n setEditor((previous) =>\n previous\n ? { ...previous, popup: { ...(previous.popup ?? {}), ...partial } }\n : previous,\n )\n\n const handleSave = async () => {\n if (!editor) return\n if (editor.kind === 'bar' && !editor.bar?.text?.trim()) {\n return void enqueueSnackbar('Enter the bar text', {\n variant: 'warning',\n persist: false,\n })\n }\n if (editor.kind === 'popup' && !editor.popup?.body?.trim()) {\n return void enqueueSnackbar('Enter the popup body', {\n variant: 'warning',\n persist: false,\n })\n }\n const id = editor.$id ?? createResourceUid()\n const {\n $id: _ignored,\n createdAt: _createdAt,\n updatedAt: _updatedAt,\n ...payload\n } = editor as OverlayDraft & { createdAt?: unknown; updatedAt?: unknown }\n try {\n // JSON round-trip strips undefined values Firestore rejects. The copy\n // is stored again here, for a name typed before the variables arrived.\n const cleaned = JSON.parse(\n JSON.stringify({\n ...payload,\n ...(payload.bar\n ? { bar: { ...payload.bar, text: copy.stored(payload.bar.text) } }\n : {}),\n ...(payload.popup\n ? {\n popup: {\n ...payload.popup,\n headline: copy.stored(payload.popup.headline),\n body: copy.stored(payload.popup.body),\n },\n }\n : {}),\n name: (editor.name ?? '').trim() || null,\n }),\n )\n /**\n * Refuse an EDIT whose seed the server never confirmed (AGL-1358).\n *\n * This write has no options argument, so it is a full document replace\n * of a payload copied wholesale off the listener — `merge` would not\n * have helped anyway, since every field is present. The activity log\n * is inside the guard too: a logged \"Updated overlay\" whose write never\n * happened is worse than neither, because the history then disagrees\n * with the overlay it claims to explain.\n *\n * Only the edit path. A NEW overlay starts from `EMPTY_BAR`/\n * `EMPTY_POPUP` at a fresh uid and can overwrite nothing, and the first\n * snapshot of any listener is `fromCache: true`, so guarding a create\n * would refuse a save that was never unsafe.\n *\n * The guard WRAPS the write: an early return is a shape you can keep\n * while losing the protection.\n */\n const verdict = await writeGuardedBySeed(\n {\n subject: 'overlay',\n unreadable: Boolean(editor.$id) && overlaysStatus === 'error',\n fromCache: Boolean(editor.$id) && overlaysFromCache,\n },\n async () => {\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) =>\n batch.set(doc(firestore, 'hosts', hostId, 'overlays', id), {\n ...cleaned,\n updatedAt: Timestamp.now(),\n ...(editor.$id ? {} : { createdAt: Timestamp.now() }),\n }),\n })\n logActivity(editor.$id ? 'Updated overlay' : 'Created overlay', {\n type: 'content',\n id,\n ...(editor.name ? { name: editor.name } : {}),\n })\n },\n )\n // A refusal keeps the editor open with everything that was typed.\n if (!verdict.ok) {\n return void enqueueSnackbar(verdict.message, {\n variant: 'warning',\n persist: false,\n })\n }\n enqueueSnackbar('Overlay saved', { variant: 'success', persist: false })\n setEditor(null)\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', { variant: 'error' })\n }\n }\n\n const handleDelete = async (overlay: OverlayDraft) => {\n if (!overlay.$id) return\n const confirmed = await confirm({\n title: 'Delete overlay?',\n description: `\"${overlay.name ?? overlay.$id}\" stops showing immediately.`,\n confirmationText: 'Delete',\n confirmationButtonProps: { color: 'error' },\n })\n // Resolves with no value and rejects on cancel — gating on the\n // resolved value alone made this always return (AGL-950).\n .then(() => true)\n .catch(() => false)\n if (!confirmed) return\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) =>\n batch.delete(doc(firestore, 'hosts', hostId, 'overlays', overlay.$id)),\n })\n enqueueSnackbar('Overlay deleted', { variant: 'success', persist: false })\n logActivity('Deleted overlay', {\n type: 'content',\n id: overlay.$id,\n ...(overlay.name ? { name: overlay.name } : {}),\n })\n }\n\n // Ordering (AGL-270): the first active overlay per kind wins, so the\n // list order is meaningful — swap `order` with the neighbor.\n const handleMove = async (index: number, direction: -1 | 1) => {\n const neighbor = overlays[index + direction]\n const current = overlays[index]\n if (!neighbor?.$id || !current?.$id) return\n const currentOrder = current.order ?? index\n const neighborOrder = neighbor.order ?? index + direction\n // One batch, so the swap lands whole — and the order decides which\n // overlay a visitor sees, so it carries the site's cache drop.\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) => {\n batch.set(\n doc(firestore, 'hosts', hostId, 'overlays', current.$id as string),\n { order: neighborOrder === currentOrder ? neighborOrder + direction : neighborOrder },\n { merge: true },\n )\n batch.set(\n doc(firestore, 'hosts', hostId, 'overlays', neighbor.$id as string),\n { order: currentOrder },\n { merge: true },\n )\n },\n }).catch(console.error)\n }\n\n const handleToggle = async (overlay: OverlayDraft) => {\n if (!overlay.$id) return\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) =>\n batch.set(\n doc(firestore, 'hosts', hostId, 'overlays', overlay.$id),\n { enabled: overlay.enabled === false },\n { merge: true },\n ),\n })\n }\n\n const statusChip = (overlay: OverlayDraft) => {\n const status = overlayStatus(overlay, Date.now())\n if (status === 'off') return <Chip size=\"small\" label=\"Off\" />\n if (status === 'scheduled') {\n return <Chip size=\"small\" color=\"info\" label=\"Scheduled\" />\n }\n return <Chip size=\"small\" color=\"success\" label=\"Live\" />\n }\n\n return (\n <CardDisplay\n header=\"Announcement bars & popups\"\n help={pluginDocsHelp('marketingOverlays', {\n anchor: '#frequency',\n excerpt:\n 'Every bar and popup on this site, with its schedule, page ' +\n 'targeting, and how often a visitor sees it again.',\n })}\n contentGutterX\n contentGutterY\n contentBordered=\"all\"\n >\n {!entitled ? (\n <Alert severity=\"info\">\n {'Announcement bars and popups are included from the Starter ' +\n 'plan — see Billing to upgrade.'}\n </Alert>\n ) : (\n <Stack spacing={2}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Configure as many bars and popups as you need, each with its ' +\n 'own schedule and page targeting. When several match a page, ' +\n 'the first per kind shows.'}\n </Typography>\n <Stack direction=\"row\" spacing={1}>\n <Button\n size=\"small\"\n color=\"primary\"\n variant=\"contained\"\n onClick={() => setEditor({ ...EMPTY_BAR })}\n >\n {'New bar'}\n </Button>\n <Button\n size=\"small\"\n color=\"primary\"\n variant=\"contained\"\n onClick={() => setEditor({ ...EMPTY_POPUP })}\n >\n {'New popup'}\n </Button>\n </Stack>\n {truncated ? (\n <Alert severity=\"info\">\n {`Showing ${CEILING} overlays, ordered by name. This site has ` +\n 'more than that — delete the ones you have finished with, or ' +\n 'the ones below the ceiling cannot be reordered against them.'}\n </Alert>\n ) : null}\n {overlays.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No overlays yet — the single announcement bar and popup ' +\n 'below keep working as your default surfaces.'}\n </Typography>\n ) : (\n <ScrollTable size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>{'Name'}</TableCell>\n <TableCell>{'Kind'}</TableCell>\n <TableCell>{'Status'}</TableCell>\n <TableCell>{'Window'}</TableCell>\n <TableCell>{'Pages'}</TableCell>\n <TableCell>{'Engagement'}</TableCell>\n <TableCell align=\"right\">{'Actions'}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {overlays.map((overlay) => (\n <TableRow key={overlay.$id}>\n <TableCell>{overlayDisplayName(overlay)}</TableCell>\n <TableCell>\n {overlay.kind === 'bar' ? 'Bar' : 'Popup'}\n </TableCell>\n <TableCell>{statusChip(overlay)}</TableCell>\n <TableCell>{overlayWindowLabel(overlay)}</TableCell>\n <TableCell>{overlayPagesLabel(overlay)}</TableCell>\n <TableCell>\n {/* Engagement (AGL-271): lifetime counters the org beacon increments. */}\n <Typography variant=\"caption\" color=\"text.secondary\">\n {overlayEngagementLabel(overlay.stats)}\n </Typography>\n </TableCell>\n <TableCell align=\"right\">\n <IconButton\n size=\"small\"\n aria-label=\"move up\"\n disabled={overlays.indexOf(overlay) === 0}\n onClick={() =>\n void handleMove(overlays.indexOf(overlay), -1)\n }\n >\n <MdiIcon path={mdiChevronUp.path} sx={{ fontSize: '1rem' }} />\n </IconButton>\n <IconButton\n size=\"small\"\n aria-label=\"move down\"\n disabled={\n overlays.indexOf(overlay) === overlays.length - 1\n }\n onClick={() =>\n void handleMove(overlays.indexOf(overlay), 1)\n }\n >\n <MdiIcon\n path={mdiChevronDown.path}\n sx={{ fontSize: '1rem' }}\n />\n </IconButton>\n <Switch\n size=\"small\"\n checked={overlay.enabled !== false}\n onChange={() => handleToggle(overlay)}\n slotProps={{ input: { 'aria-label': 'Enabled' } }}\n />\n <Button\n size=\"small\"\n color=\"primary\"\n onClick={() => setEditor({ ...overlay })}\n >\n {'Edit'}\n </Button>\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() => handleDelete(overlay)}\n >\n {'Delete'}\n </Button>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </ScrollTable>\n )}\n </Stack>\n )}\n\n <Dialog\n open={Boolean(editor)}\n onClose={() => setEditor(null)}\n maxWidth=\"sm\"\n fullWidth\n >\n <DialogTitle>\n {editor?.$id\n ? 'Edit overlay'\n : editor?.kind === 'bar'\n ? 'New announcement bar'\n : 'New popup'}\n </DialogTitle>\n <DialogContent>\n {editor ? (\n <Stack spacing={2} sx={{ mt: 1 }}>\n <TextField\n size=\"small\"\n label=\"Name\"\n value={editor.name ?? ''}\n onChange={(event) => patch({ name: event.target.value })}\n helperText=\"Internal label shown in this list\"\n />\n {editor.kind === 'bar' ? (\n <>\n <TextField\n size=\"small\"\n label=\"Text\"\n required\n value={copy.editable(editor.bar?.text)}\n onChange={(event) =>\n patchBar({ text: copy.stored(event.target.value) })\n }\n error={barTextShownAsTyped.length > 0}\n helperText={\n shownAsTypedHelperText(barTextShownAsTyped) ??\n OVERLAY_COPY_HELPER_TEXT\n }\n />\n <TextField\n size=\"small\"\n label=\"Link (optional)\"\n value={editor.bar?.href ?? ''}\n onChange={(event) => patchBar({ href: event.target.value })}\n />\n <Stack direction=\"row\" spacing={1}>\n <TextField\n size=\"small\"\n label=\"Background color\"\n value={editor.bar?.backgroundColor ?? ''}\n onChange={(event) =>\n patchBar({ backgroundColor: event.target.value })\n }\n />\n <TextField\n size=\"small\"\n label=\"Text color\"\n value={editor.bar?.textColor ?? ''}\n onChange={(event) =>\n patchBar({ textColor: event.target.value })\n }\n />\n </Stack>\n </>\n ) : (\n <>\n <TextField\n size=\"small\"\n label=\"Headline\"\n value={copy.editable(editor.popup?.headline)}\n onChange={(event) =>\n patchPopup({ headline: copy.stored(event.target.value) })\n }\n error={headlineShownAsTyped.length > 0}\n helperText={shownAsTypedHelperText(headlineShownAsTyped)}\n />\n <TextField\n size=\"small\"\n label=\"Body\"\n required\n multiline\n minRows={2}\n value={copy.editable(editor.popup?.body)}\n onChange={(event) =>\n patchPopup({ body: copy.stored(event.target.value) })\n }\n error={bodyShownAsTyped.length > 0}\n helperText={\n shownAsTypedHelperText(bodyShownAsTyped) ??\n OVERLAY_COPY_HELPER_TEXT\n }\n />\n <Stack direction=\"row\" spacing={1}>\n <TextField\n size=\"small\"\n label=\"CTA label\"\n value={editor.popup?.ctaLabel ?? ''}\n onChange={(event) =>\n patchPopup({ ctaLabel: event.target.value })\n }\n />\n <TextField\n size=\"small\"\n label=\"CTA link\"\n value={editor.popup?.ctaHref ?? ''}\n onChange={(event) =>\n patchPopup({ ctaHref: event.target.value })\n }\n />\n </Stack>\n <Stack direction=\"row\" spacing={1}>\n <TextField\n select\n size=\"small\"\n label=\"Trigger\"\n sx={{ minWidth: 140 }}\n value={editor.popup?.trigger ?? 'delay'}\n onChange={(event) =>\n patchPopup({\n trigger: event.target\n .value as NonNullable<\n OverlayDraft['popup']\n >['trigger'],\n })\n }\n >\n <MenuItem value=\"delay\">{'After a delay'}</MenuItem>\n <MenuItem value=\"scroll\">{'On scroll'}</MenuItem>\n <MenuItem value=\"exit\">{'On exit intent'}</MenuItem>\n </TextField>\n <TextField\n size=\"small\"\n type=\"number\"\n label={\n (editor.popup?.trigger ?? 'delay') === 'scroll'\n ? 'Scroll %'\n : 'Seconds'\n }\n value={editor.popup?.triggerValue ?? 3}\n onChange={(event) =>\n patchPopup({\n triggerValue: Number(event.target.value),\n })\n }\n />\n {/*\n `Once per session` (AGL-2174). `/product/marketing`\n sells \"per-session frequency caps\" in as many words\n and the only cap that existed was day-based — a\n visitor who dismissed a popup did not see it again\n for a week, which is a different promise. The two are\n alternatives, so the day field goes away when the\n session cap is on rather than sitting there ignored.\n */}\n <TextField\n select\n size=\"small\"\n label=\"Frequency\"\n value={editor.popup?.oncePerSession ? 'session' : 'days'}\n onChange={(event) =>\n patchPopup({\n oncePerSession: event.target.value === 'session',\n })\n }\n sx={{ minWidth: 170 }}\n >\n <MenuItem value=\"session\">\n {'Once per session'}\n </MenuItem>\n <MenuItem value=\"days\">{'Re-show after a while'}</MenuItem>\n </TextField>\n {editor.popup?.oncePerSession ? null : (\n <TextField\n size=\"small\"\n type=\"number\"\n label=\"Re-show after (days)\"\n value={editor.popup?.frequencyDays ?? 7}\n onChange={(event) =>\n patchPopup({\n frequencyDays: Number(event.target.value),\n })\n }\n />\n )}\n </Stack>\n </>\n )}\n <Stack direction=\"row\" spacing={1}>\n <TextField\n size=\"small\"\n type=\"datetime-local\"\n label=\"Show from\"\n slotProps={{ inputLabel: { shrink: true } }}\n value={toDatetimeLocal(editor.startAtMs)}\n onChange={(event) =>\n patch({ startAtMs: fromDatetimeLocal(event.target.value) })\n }\n />\n <TextField\n size=\"small\"\n type=\"datetime-local\"\n label=\"Show until\"\n slotProps={{ inputLabel: { shrink: true } }}\n value={toDatetimeLocal(editor.endAtMs)}\n onChange={(event) =>\n patch({ endAtMs: fromDatetimeLocal(event.target.value) })\n }\n />\n </Stack>\n <TextField\n size=\"small\"\n label=\"Show on pages\"\n value={(editor.pathPatterns ?? []).join(', ')}\n onChange={(event) =>\n patch({ pathPatterns: parsePatterns(event.target.value) })\n }\n helperText={\n 'Comma-separated paths; /blog/* matches a section. ' +\n 'Empty = every page.'\n }\n />\n <TextField\n size=\"small\"\n label=\"Never show on\"\n value={(editor.excludePathPatterns ?? []).join(', ')}\n onChange={(event) =>\n patch({\n excludePathPatterns: parsePatterns(event.target.value),\n })\n }\n />\n </Stack>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button color=\"inherit\" onClick={() => setEditor(null)}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={handleSave}\n disabled={copy.pending(\n editor?.bar?.text,\n editor?.popup?.headline,\n editor?.popup?.body,\n )}\n >\n {'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n </CardDisplay>\n )\n}\nHostOverlaysCard.displayName = 'HostOverlaysCard'\n\nexport default HostOverlaysCard\n"],"names":["checkEntitlement","createResourceUid","pluginDocsHelp","compareOverlayPrecedence","overlayStatus","mdiChevronDown","mdiChevronUp","CardDisplay","MdiIcon","useConfirmationContext","ScrollTable","useSnackbar","Timestamp","Alert","Button","Chip","IconButton","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","Stack","Switch","TableBody","TableCell","TableHead","TableRow","TextField","Typography","collection","doc","limit","orderBy","query","useState","useFirestore","useFirestoreCollection","useHostActivityLogger","writeGuardedBySeed","useUser","writeSiteWideChange","overlayDisplayName","overlayEngagementLabel","overlayPagesLabel","overlayWindowLabel","OVERLAY_COPY_HELPER_TEXT","shownAsTypedHelperText","useOverlayCopyEditor","CEILING","EMPTY_BAR","kind","enabled","bar","dismissible","EMPTY_POPUP","popup","trigger","triggerValue","frequencyDays","toDatetimeLocal","ms","date","Date","pad","value","String","padStart","getFullYear","getMonth","getDate","getHours","getMinutes","fromDatetimeLocal","undefined","getTime","Number","isFinite","parsePatterns","split","map","pattern","trim","filter","Boolean","HostOverlaysCard","props","editor","hostId","firestore","data","user","org","enqueueSnackbar","confirm","logActivity","entitled","overlayDocs","status","overlaysStatus","fromCache","overlaysFromCache","idField","truncated","length","overlays","slice","sort","setEditor","copy","usesTokens","text","headline","body","some","includes","barTextShownAsTyped","shownAsTyped","headlineShownAsTyped","bodyShownAsTyped","patch","partial","previous","patchBar","patchPopup","handleSave","variant","persist","id","$id","_ignored","createdAt","_createdAt","updatedAt","_updatedAt","payload","cleaned","JSON","parse","stringify","stored","name","verdict","subject","unreadable","write","batch","set","now","type","ok","message","error","console","handleDelete","overlay","confirmed","title","description","confirmationText","confirmationButtonProps","color","then","catch","delete","handleMove","index","direction","current","neighbor","currentOrder","order","neighborOrder","merge","handleToggle","statusChip","size","label","header","help","anchor","excerpt","contentGutterX","contentGutterY","contentBordered","severity","spacing","onClick","align","stats","aria-label","disabled","indexOf","path","sx","fontSize","checked","onChange","slotProps","input","open","onClose","maxWidth","fullWidth","mt","event","target","helperText","required","editable","href","backgroundColor","textColor","multiline","minRows","ctaLabel","ctaHref","select","minWidth","oncePerSession","inputLabel","shrink","startAtMs","endAtMs","pathPatterns","join","excludePathPatterns","pending","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketing/src/lib/components/host-overlays-card.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 type AglynOrgBilling,\n checkEntitlement,\n createResourceUid,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport {\n compareOverlayPrecedence,\n OVERLAY_COPY_LIMITS,\n OVERLAY_LIST_CEILING,\n OVERLAY_POPUP_TRIGGERS,\n overlayCopyFromProposal,\n overlayDraftFromProposal,\n overlayStatus,\n type HostOverlay,\n type OverlayCopyProposal,\n} from '../model'\nimport { mdiChevronDown, mdiChevronUp } from '@aglyn/shared-data-mdi'\nimport {\n CardDisplay,\n MdiIcon,\n useConfirmationContext,\n} from '@aglyn/shared-ui-jsx'\nimport { ScrollTable } from '@aglyn/shared-ui-jsx/components/scroll-table.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { Timestamp } from '@aglyn/shared-util-timestamp'\nimport {\n Alert,\n Button,\n Chip,\n IconButton,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n Stack,\n Switch,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material'\nimport { collection, doc, limit, orderBy, query } from 'firebase/firestore'\nimport { useState } from 'react'\nimport {\n useFirestore,\n useFirestoreCollection,\n useHostActivityLogger,\n writeGuardedBySeed,\n useUser,\n} from '@aglyn/tenant-feature-instance'\nimport { writeSiteWideChange } from '@aglyn/tenant-feature-instance/hooks/helpers/site-wide-change'\nimport {\n overlayDisplayName,\n overlayEngagementLabel,\n overlayPagesLabel,\n overlayWindowLabel,\n} from './overlay-labels'\nimport {\n OVERLAY_COPY_HELPER_TEXT,\n shownAsTypedHelperText,\n useOverlayCopyEditor,\n} from './use-overlay-copy-editor'\nimport {\n HostOverlaysZone,\n OverlayEditorZone,\n type MarketingOverlayDraftResult,\n} from './overlay-zones'\n\nexport interface HostOverlaysCardProps {\n hostId: string\n /** Resolved entitlement source (AGL-395). */\n org?: Partial<AglynOrgBilling>\n}\n\ntype OverlayDraft = HostOverlay & { $id?: string }\n\n/**\n * How many overlays the card reads.\n *\n * A ceiling rather than a page size — see the query, which explains why this\n * one list is deliberately not paginated. Generous on purpose: a site runs a\n * handful of banners and popups, and the number exists to bound a pathological\n * collection rather than to bound a normal one.\n */\nconst CEILING = OVERLAY_LIST_CEILING\n\nconst EMPTY_BAR: OverlayDraft = {\n kind: 'bar',\n enabled: true,\n bar: { dismissible: true },\n}\nconst EMPTY_POPUP: OverlayDraft = {\n kind: 'popup',\n enabled: true,\n popup: { trigger: 'delay', triggerValue: 3, frequencyDays: 7 },\n}\n\nfunction toDatetimeLocal(ms?: number): string {\n if (!ms) return ''\n const date = new Date(ms)\n const pad = (value: number) => String(value).padStart(2, '0')\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-` +\n `${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`\n )\n}\n\nfunction fromDatetimeLocal(value: string): number | undefined {\n if (!value) return undefined\n const ms = new Date(value).getTime()\n return Number.isFinite(ms) ? ms : undefined\n}\n\nfunction parsePatterns(value: string): string[] {\n return value\n .split(',')\n .map((pattern) => pattern.trim())\n .filter(Boolean)\n}\n\n/**\n * Marketing hub overlays manager (AGL-251): multiple announcement bars\n * and popups at `hosts/{hostId}/overlays`, each with a schedule window\n * and page targeting; the tenant render shows the first active match per\n * kind (overlay docs win over the legacy single bar/popup fields). A bar's\n * text and a popup's headline and body are edited through\n * `useOverlayCopyEditor`, like the single bar and popup cards (AGL-2885).\n */\nexport function HostOverlaysCard(props: HostOverlaysCardProps) {\n const { hostId } = props\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { org } = props\n const { enqueueSnackbar } = useSnackbar()\n const { confirm } = useConfirmationContext()\n const logActivity = useHostActivityLogger(hostId)\n const entitled = checkEntitlement(org, 'marketingOverlays')\n\n const {\n data: overlayDocs,\n status: overlaysStatus,\n /**\n * The overlay rows the editor is seeded from are unconfirmed by the\n * server (AGL-1358). Editing one spreads the whole stored row into\n * `editor` and writes it back with NO options argument at all — a full\n * document replace — so a cached seed reverts every field nobody\n * touched. Including `stats`, the lifetime impression/click/dismissal\n * counters the org beacon increments: a save here would roll live\n * engagement numbers back to whenever the snapshot was taken.\n */\n fromCache: overlaysFromCache,\n } = useFirestoreCollection<any>(\n () =>\n query(\n collection(firestore, 'hosts', hostId, 'overlays'),\n /*\n * ORDERED AND CEILINGED, deliberately not paged (AGL-2501).\n *\n * ## Why the read is ordered\n *\n * `limit(50)` alone is answered in DOCUMENT-ID order over ids from\n * `createResourceUid()`, so the window was a pseudo-random fifty that\n * the client sort below arranged into a believable precedence list.\n * `name` is the one field every overlay carries: `handleSave` writes\n * `name: (…).trim() || null` on every save, and it is the only writer\n * that CREATES one — the analytics beacon uses `update()` precisely so\n * a stale page cannot mint a stats-only stray, and `overlays` is not\n * in `IMPORTABLE_FIELDS`, so no restore path makes one either. A null\n * name still matches an `orderBy`; an ABSENT field would not.\n *\n * ## Why this list is not paged\n *\n * The row order IS the feature: the first enabled overlay of each kind\n * is the one a visitor sees (AGL-270), and the arrows reorder by\n * swapping `order` with the ADJACENT row. A page boundary separates a\n * row from the neighbor it would swap with, so the eleventh overlay\n * could never be moved into tenth place — the same reason the console's\n * screen tree and starter bundles are ceilinged rather than paged.\n *\n * `orderBy('order')` is not an option either, and that is what makes\n * the precedence sort a client-side one: `EMPTY_BAR` and `EMPTY_POPUP`\n * carry no `order`, and only `handleMove` ever writes one, so ordering\n * the query on it would hide every overlay nobody has reordered rather\n * than mis-sorting it. The client sort holds the WHOLE window, which is\n * what makes sorting it here honest.\n */\n orderBy('name'),\n // One past the ceiling, so \"there are more overlays than these\" is a\n // fact rather than a guess from `length === 50`.\n limit(CEILING + 1),\n ),\n [firestore, hostId],\n { idField: '$id' },\n )\n const truncated = (overlayDocs?.length ?? 0) > CEILING\n const overlays: OverlayDraft[] = [...(overlayDocs ?? [])]\n .slice(0, CEILING)\n .sort(compareOverlayPrecedence)\n\n const [editor, setEditor] = useState<OverlayDraft | null>(null)\n // The editor's copy is held in its stored form; the fields show it as typed.\n const copy = useOverlayCopyEditor({\n hostId,\n usesTokens:\n entitled &&\n [editor?.bar?.text, editor?.popup?.headline, editor?.popup?.body].some(\n (text) => text?.includes('{{'),\n ),\n })\n const barTextShownAsTyped = copy.shownAsTyped(editor?.bar?.text)\n const headlineShownAsTyped = copy.shownAsTyped(editor?.popup?.headline)\n const bodyShownAsTyped = copy.shownAsTyped(editor?.popup?.body)\n const patch = (partial: Partial<OverlayDraft>) =>\n setEditor((previous) => (previous ? { ...previous, ...partial } : previous))\n const patchBar = (partial: Partial<NonNullable<OverlayDraft['bar']>>) =>\n setEditor((previous) =>\n previous\n ? { ...previous, bar: { ...(previous.bar ?? {}), ...partial } }\n : previous,\n )\n const patchPopup = (partial: Partial<NonNullable<OverlayDraft['popup']>>) =>\n setEditor((previous) =>\n previous\n ? { ...previous, popup: { ...(previous.popup ?? {}), ...partial } }\n : previous,\n )\n\n const handleSave = async () => {\n if (!editor) return\n if (editor.kind === 'bar' && !editor.bar?.text?.trim()) {\n return void enqueueSnackbar('Enter the bar text', {\n variant: 'warning',\n persist: false,\n })\n }\n if (editor.kind === 'popup' && !editor.popup?.body?.trim()) {\n return void enqueueSnackbar('Enter the popup body', {\n variant: 'warning',\n persist: false,\n })\n }\n const id = editor.$id ?? createResourceUid()\n const {\n $id: _ignored,\n createdAt: _createdAt,\n updatedAt: _updatedAt,\n ...payload\n } = editor as OverlayDraft & { createdAt?: unknown; updatedAt?: unknown }\n try {\n // JSON round-trip strips undefined values Firestore rejects. The copy\n // is stored again here, for a name typed before the variables arrived.\n const cleaned = JSON.parse(\n JSON.stringify({\n ...payload,\n ...(payload.bar\n ? { bar: { ...payload.bar, text: copy.stored(payload.bar.text) } }\n : {}),\n ...(payload.popup\n ? {\n popup: {\n ...payload.popup,\n headline: copy.stored(payload.popup.headline),\n body: copy.stored(payload.popup.body),\n },\n }\n : {}),\n name: (editor.name ?? '').trim() || null,\n }),\n )\n /**\n * Refuse an EDIT whose seed the server never confirmed (AGL-1358).\n *\n * This write has no options argument, so it is a full document replace\n * of a payload copied wholesale off the listener — `merge` would not\n * have helped anyway, since every field is present. The activity log\n * is inside the guard too: a logged \"Updated overlay\" whose write never\n * happened is worse than neither, because the history then disagrees\n * with the overlay it claims to explain.\n *\n * Only the edit path. A NEW overlay starts from `EMPTY_BAR`/\n * `EMPTY_POPUP` at a fresh uid and can overwrite nothing, and the first\n * snapshot of any listener is `fromCache: true`, so guarding a create\n * would refuse a save that was never unsafe.\n *\n * The guard WRAPS the write: an early return is a shape you can keep\n * while losing the protection.\n */\n const verdict = await writeGuardedBySeed(\n {\n subject: 'overlay',\n unreadable: Boolean(editor.$id) && overlaysStatus === 'error',\n fromCache: Boolean(editor.$id) && overlaysFromCache,\n },\n async () => {\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) =>\n batch.set(doc(firestore, 'hosts', hostId, 'overlays', id), {\n ...cleaned,\n updatedAt: Timestamp.now(),\n ...(editor.$id ? {} : { createdAt: Timestamp.now() }),\n }),\n })\n logActivity(editor.$id ? 'Updated overlay' : 'Created overlay', {\n type: 'content',\n id,\n ...(editor.name ? { name: editor.name } : {}),\n })\n },\n )\n // A refusal keeps the editor open with everything that was typed.\n if (!verdict.ok) {\n return void enqueueSnackbar(verdict.message, {\n variant: 'warning',\n persist: false,\n })\n }\n enqueueSnackbar('Overlay saved', { variant: 'success', persist: false })\n setEditor(null)\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', { variant: 'error' })\n }\n }\n\n /*\n * What a widget in the list's zone asks for (AGL-3603): a new overlay from\n * proposed copy, cut to the overlay's limits and written SWITCHED OFF —\n * through the same site-wide write a typed overlay takes — then opened in\n * the editor, where a person reads it, changes it and turns it on.\n */\n const createOverlayDraft = async (\n kind: HostOverlay['kind'],\n proposal: OverlayCopyProposal,\n ): Promise<MarketingOverlayDraftResult> => {\n const draft = overlayDraftFromProposal(kind, proposal)\n if (!draft) {\n return {\n ok: false,\n error:\n kind === 'bar'\n ? 'There was no bar text to save.'\n : 'There was no popup body to save.',\n }\n }\n const id = createResourceUid()\n // The list orders on `name`, which every overlay carries, null or not.\n const stored = { ...draft, name: draft.name ?? null }\n try {\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) =>\n batch.set(doc(firestore, 'hosts', hostId, 'overlays', id), {\n ...stored,\n createdAt: Timestamp.now(),\n updatedAt: Timestamp.now(),\n }),\n })\n } catch (error) {\n console.error(error)\n return { ok: false, error: 'The overlay could not be saved. Try again.' }\n }\n logActivity('Created overlay', {\n type: 'content',\n id,\n ...(draft.name ? { name: draft.name } : {}),\n })\n setEditor({ ...draft, $id: id })\n return { ok: true, id }\n }\n\n /*\n * What a widget in the editor's zone proposes (AGL-3603), put into the\n * editor's own fields unsaved. Copy is stored as the editor stores typed\n * copy, so a proposed variable name is kept the way a typed one is.\n */\n const proposeOverlayCopy = (proposal: OverlayCopyProposal) => {\n if (!editor) return\n const values = overlayCopyFromProposal(editor.kind, proposal)\n if (values.name) patch({ name: values.name })\n if (editor.kind === 'bar') {\n if (values.text) patchBar({ text: copy.stored(values.text) })\n return\n }\n patchPopup({\n ...(values.headline ? { headline: copy.stored(values.headline) } : {}),\n ...(values.body ? { body: copy.stored(values.body) } : {}),\n ...(values.ctaLabel ? { ctaLabel: values.ctaLabel } : {}),\n ...(values.trigger ? { trigger: values.trigger } : {}),\n ...(values.triggerValue !== undefined ? { triggerValue: values.triggerValue } : {}),\n })\n }\n\n const overlayRules = { limits: OVERLAY_COPY_LIMITS, triggers: OVERLAY_POPUP_TRIGGERS }\n\n const handleDelete = async (overlay: OverlayDraft) => {\n if (!overlay.$id) return\n const confirmed = await confirm({\n title: 'Delete overlay?',\n description: `\"${overlay.name ?? overlay.$id}\" stops showing immediately.`,\n confirmationText: 'Delete',\n confirmationButtonProps: { color: 'error' },\n })\n // Resolves with no value and rejects on cancel — gating on the\n // resolved value alone made this always return (AGL-950).\n .then(() => true)\n .catch(() => false)\n if (!confirmed) return\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) =>\n batch.delete(doc(firestore, 'hosts', hostId, 'overlays', overlay.$id)),\n })\n enqueueSnackbar('Overlay deleted', { variant: 'success', persist: false })\n logActivity('Deleted overlay', {\n type: 'content',\n id: overlay.$id,\n ...(overlay.name ? { name: overlay.name } : {}),\n })\n }\n\n // Ordering (AGL-270): the first active overlay per kind wins, so the\n // list order is meaningful — swap `order` with the neighbor.\n const handleMove = async (index: number, direction: -1 | 1) => {\n const neighbor = overlays[index + direction]\n const current = overlays[index]\n if (!neighbor?.$id || !current?.$id) return\n const currentOrder = current.order ?? index\n const neighborOrder = neighbor.order ?? index + direction\n // One batch, so the swap lands whole — and the order decides which\n // overlay a visitor sees, so it carries the site's cache drop.\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) => {\n batch.set(\n doc(firestore, 'hosts', hostId, 'overlays', current.$id as string),\n { order: neighborOrder === currentOrder ? neighborOrder + direction : neighborOrder },\n { merge: true },\n )\n batch.set(\n doc(firestore, 'hosts', hostId, 'overlays', neighbor.$id as string),\n { order: currentOrder },\n { merge: true },\n )\n },\n }).catch(console.error)\n }\n\n const handleToggle = async (overlay: OverlayDraft) => {\n if (!overlay.$id) return\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) =>\n batch.set(\n doc(firestore, 'hosts', hostId, 'overlays', overlay.$id),\n { enabled: overlay.enabled === false },\n { merge: true },\n ),\n })\n }\n\n const statusChip = (overlay: OverlayDraft) => {\n const status = overlayStatus(overlay, Date.now())\n if (status === 'off') return <Chip size=\"small\" label=\"Off\" />\n if (status === 'scheduled') {\n return <Chip size=\"small\" color=\"info\" label=\"Scheduled\" />\n }\n return <Chip size=\"small\" color=\"success\" label=\"Live\" />\n }\n\n return (\n <CardDisplay\n header=\"Announcement bars & popups\"\n help={pluginDocsHelp('marketingOverlays', {\n anchor: '#frequency',\n excerpt:\n 'Every bar and popup on this site, with its schedule, page ' +\n 'targeting, and how often a visitor sees it again.',\n })}\n contentGutterX\n contentGutterY\n contentBordered=\"all\"\n >\n {!entitled ? (\n <Alert severity=\"info\">\n {'Announcement bars and popups are included from the Starter ' +\n 'plan — see Billing to upgrade.'}\n </Alert>\n ) : (\n <Stack spacing={2}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Configure as many bars and popups as you need, each with its ' +\n 'own schedule and page targeting. When several match a page, ' +\n 'the first per kind shows.'}\n </Typography>\n <Stack direction=\"row\" spacing={1}>\n <Button\n size=\"small\"\n color=\"primary\"\n variant=\"contained\"\n onClick={() => setEditor({ ...EMPTY_BAR })}\n >\n {'New bar'}\n </Button>\n <Button\n size=\"small\"\n color=\"primary\"\n variant=\"contained\"\n onClick={() => setEditor({ ...EMPTY_POPUP })}\n >\n {'New popup'}\n </Button>\n {/*\n Other ways to start an overlay, from plugins (AGL-3603): the\n `hostOverlays` zone this plugin declares, drawn through the\n shell's own gated slot.\n */}\n <HostOverlaysZone\n hostId={hostId}\n createOverlayDraft={createOverlayDraft}\n {...overlayRules}\n />\n </Stack>\n {truncated ? (\n <Alert severity=\"info\">\n {`Showing ${CEILING} overlays, ordered by name. This site has ` +\n 'more than that — delete the ones you have finished with, or ' +\n 'the ones below the ceiling cannot be reordered against them.'}\n </Alert>\n ) : null}\n {overlays.length === 0 ? (\n <Stack spacing={1} sx={{ alignItems: 'flex-start' }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No overlays yet — the single announcement bar and popup ' +\n 'below keep working as your default surfaces.'}\n </Typography>\n {/* Other ways to start an overlay, the row's zone again. */}\n <HostOverlaysZone\n hostId={hostId}\n createOverlayDraft={createOverlayDraft}\n {...overlayRules}\n />\n </Stack>\n ) : (\n <ScrollTable size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>{'Name'}</TableCell>\n <TableCell>{'Kind'}</TableCell>\n <TableCell>{'Status'}</TableCell>\n <TableCell>{'Window'}</TableCell>\n <TableCell>{'Pages'}</TableCell>\n <TableCell>{'Engagement'}</TableCell>\n <TableCell align=\"right\">{'Actions'}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {overlays.map((overlay) => (\n <TableRow key={overlay.$id}>\n <TableCell>{overlayDisplayName(overlay)}</TableCell>\n <TableCell>\n {overlay.kind === 'bar' ? 'Bar' : 'Popup'}\n </TableCell>\n <TableCell>{statusChip(overlay)}</TableCell>\n <TableCell>{overlayWindowLabel(overlay)}</TableCell>\n <TableCell>{overlayPagesLabel(overlay)}</TableCell>\n <TableCell>\n {/* Engagement (AGL-271): lifetime counters the org beacon increments. */}\n <Typography variant=\"caption\" color=\"text.secondary\">\n {overlayEngagementLabel(overlay.stats)}\n </Typography>\n </TableCell>\n <TableCell align=\"right\">\n <IconButton\n size=\"small\"\n aria-label=\"move up\"\n disabled={overlays.indexOf(overlay) === 0}\n onClick={() =>\n void handleMove(overlays.indexOf(overlay), -1)\n }\n >\n <MdiIcon path={mdiChevronUp.path} sx={{ fontSize: '1rem' }} />\n </IconButton>\n <IconButton\n size=\"small\"\n aria-label=\"move down\"\n disabled={\n overlays.indexOf(overlay) === overlays.length - 1\n }\n onClick={() =>\n void handleMove(overlays.indexOf(overlay), 1)\n }\n >\n <MdiIcon\n path={mdiChevronDown.path}\n sx={{ fontSize: '1rem' }}\n />\n </IconButton>\n <Switch\n size=\"small\"\n checked={overlay.enabled !== false}\n onChange={() => handleToggle(overlay)}\n slotProps={{ input: { 'aria-label': 'Enabled' } }}\n />\n <Button\n size=\"small\"\n color=\"primary\"\n onClick={() => setEditor({ ...overlay })}\n >\n {'Edit'}\n </Button>\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() => handleDelete(overlay)}\n >\n {'Delete'}\n </Button>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </ScrollTable>\n )}\n </Stack>\n )}\n\n <Dialog\n open={Boolean(editor)}\n onClose={() => setEditor(null)}\n maxWidth=\"sm\"\n fullWidth\n >\n <DialogTitle>\n {editor?.$id\n ? 'Edit overlay'\n : editor?.kind === 'bar'\n ? 'New announcement bar'\n : 'New popup'}\n </DialogTitle>\n <DialogContent>\n {editor ? (\n <Stack spacing={2} sx={{ mt: 1 }}>\n <TextField\n size=\"small\"\n label=\"Name\"\n value={editor.name ?? ''}\n onChange={(event) => patch({ name: event.target.value })}\n helperText=\"Internal label shown in this list\"\n />\n {/*\n Copy proposed by a plugin (AGL-3603): the `overlayEditor`\n zone this plugin declares. A widget fills these fields\n unsaved; Save below is the only write.\n */}\n <OverlayEditorZone\n hostId={hostId}\n overlayId={editor.$id ?? ''}\n kind={editor.kind}\n copy={{\n name: editor.name ?? '',\n text: copy.editable(editor.bar?.text),\n headline: copy.editable(editor.popup?.headline),\n body: copy.editable(editor.popup?.body),\n ctaLabel: editor.popup?.ctaLabel ?? '',\n ctaHref: editor.popup?.ctaHref ?? '',\n trigger: editor.popup?.trigger ?? 'delay',\n triggerValue: editor.popup?.triggerValue ?? null,\n }}\n proposeValues={proposeOverlayCopy}\n {...overlayRules}\n />\n {editor.kind === 'bar' ? (\n <>\n <TextField\n size=\"small\"\n label=\"Text\"\n required\n value={copy.editable(editor.bar?.text)}\n onChange={(event) =>\n patchBar({ text: copy.stored(event.target.value) })\n }\n error={barTextShownAsTyped.length > 0}\n helperText={\n shownAsTypedHelperText(barTextShownAsTyped) ??\n OVERLAY_COPY_HELPER_TEXT\n }\n />\n <TextField\n size=\"small\"\n label=\"Link (optional)\"\n value={editor.bar?.href ?? ''}\n onChange={(event) => patchBar({ href: event.target.value })}\n />\n <Stack direction=\"row\" spacing={1}>\n <TextField\n size=\"small\"\n label=\"Background color\"\n value={editor.bar?.backgroundColor ?? ''}\n onChange={(event) =>\n patchBar({ backgroundColor: event.target.value })\n }\n />\n <TextField\n size=\"small\"\n label=\"Text color\"\n value={editor.bar?.textColor ?? ''}\n onChange={(event) =>\n patchBar({ textColor: event.target.value })\n }\n />\n </Stack>\n </>\n ) : (\n <>\n <TextField\n size=\"small\"\n label=\"Headline\"\n value={copy.editable(editor.popup?.headline)}\n onChange={(event) =>\n patchPopup({ headline: copy.stored(event.target.value) })\n }\n error={headlineShownAsTyped.length > 0}\n helperText={shownAsTypedHelperText(headlineShownAsTyped)}\n />\n <TextField\n size=\"small\"\n label=\"Body\"\n required\n multiline\n minRows={2}\n value={copy.editable(editor.popup?.body)}\n onChange={(event) =>\n patchPopup({ body: copy.stored(event.target.value) })\n }\n error={bodyShownAsTyped.length > 0}\n helperText={\n shownAsTypedHelperText(bodyShownAsTyped) ??\n OVERLAY_COPY_HELPER_TEXT\n }\n />\n <Stack direction=\"row\" spacing={1}>\n <TextField\n size=\"small\"\n label=\"CTA label\"\n value={editor.popup?.ctaLabel ?? ''}\n onChange={(event) =>\n patchPopup({ ctaLabel: event.target.value })\n }\n />\n <TextField\n size=\"small\"\n label=\"CTA link\"\n value={editor.popup?.ctaHref ?? ''}\n onChange={(event) =>\n patchPopup({ ctaHref: event.target.value })\n }\n />\n </Stack>\n <Stack direction=\"row\" spacing={1}>\n <TextField\n select\n size=\"small\"\n label=\"Trigger\"\n sx={{ minWidth: 140 }}\n value={editor.popup?.trigger ?? 'delay'}\n onChange={(event) =>\n patchPopup({\n trigger: event.target\n .value as NonNullable<\n OverlayDraft['popup']\n >['trigger'],\n })\n }\n >\n <MenuItem value=\"delay\">{'After a delay'}</MenuItem>\n <MenuItem value=\"scroll\">{'On scroll'}</MenuItem>\n <MenuItem value=\"exit\">{'On exit intent'}</MenuItem>\n </TextField>\n <TextField\n size=\"small\"\n type=\"number\"\n label={\n (editor.popup?.trigger ?? 'delay') === 'scroll'\n ? 'Scroll %'\n : 'Seconds'\n }\n value={editor.popup?.triggerValue ?? 3}\n onChange={(event) =>\n patchPopup({\n triggerValue: Number(event.target.value),\n })\n }\n />\n {/*\n `Once per session` (AGL-2174). `/product/marketing`\n sells \"per-session frequency caps\" in as many words\n and the only cap that existed was day-based — a\n visitor who dismissed a popup did not see it again\n for a week, which is a different promise. The two are\n alternatives, so the day field goes away when the\n session cap is on rather than sitting there ignored.\n */}\n <TextField\n select\n size=\"small\"\n label=\"Frequency\"\n value={editor.popup?.oncePerSession ? 'session' : 'days'}\n onChange={(event) =>\n patchPopup({\n oncePerSession: event.target.value === 'session',\n })\n }\n sx={{ minWidth: 170 }}\n >\n <MenuItem value=\"session\">\n {'Once per session'}\n </MenuItem>\n <MenuItem value=\"days\">{'Re-show after a while'}</MenuItem>\n </TextField>\n {editor.popup?.oncePerSession ? null : (\n <TextField\n size=\"small\"\n type=\"number\"\n label=\"Re-show after (days)\"\n value={editor.popup?.frequencyDays ?? 7}\n onChange={(event) =>\n patchPopup({\n frequencyDays: Number(event.target.value),\n })\n }\n />\n )}\n </Stack>\n </>\n )}\n <Stack direction=\"row\" spacing={1}>\n <TextField\n size=\"small\"\n type=\"datetime-local\"\n label=\"Show from\"\n slotProps={{ inputLabel: { shrink: true } }}\n value={toDatetimeLocal(editor.startAtMs)}\n onChange={(event) =>\n patch({ startAtMs: fromDatetimeLocal(event.target.value) })\n }\n />\n <TextField\n size=\"small\"\n type=\"datetime-local\"\n label=\"Show until\"\n slotProps={{ inputLabel: { shrink: true } }}\n value={toDatetimeLocal(editor.endAtMs)}\n onChange={(event) =>\n patch({ endAtMs: fromDatetimeLocal(event.target.value) })\n }\n />\n </Stack>\n <TextField\n size=\"small\"\n label=\"Show on pages\"\n value={(editor.pathPatterns ?? []).join(', ')}\n onChange={(event) =>\n patch({ pathPatterns: parsePatterns(event.target.value) })\n }\n helperText={\n 'Comma-separated paths; /blog/* matches a section. ' +\n 'Empty = every page.'\n }\n />\n <TextField\n size=\"small\"\n label=\"Never show on\"\n value={(editor.excludePathPatterns ?? []).join(', ')}\n onChange={(event) =>\n patch({\n excludePathPatterns: parsePatterns(event.target.value),\n })\n }\n />\n </Stack>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button color=\"inherit\" onClick={() => setEditor(null)}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={handleSave}\n disabled={copy.pending(\n editor?.bar?.text,\n editor?.popup?.headline,\n editor?.popup?.body,\n )}\n >\n {'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n </CardDisplay>\n )\n}\nHostOverlaysCard.displayName = 'HostOverlaysCard'\n\nexport default HostOverlaysCard\n"],"names":["checkEntitlement","createResourceUid","pluginDocsHelp","compareOverlayPrecedence","OVERLAY_COPY_LIMITS","OVERLAY_LIST_CEILING","OVERLAY_POPUP_TRIGGERS","overlayCopyFromProposal","overlayDraftFromProposal","overlayStatus","mdiChevronDown","mdiChevronUp","CardDisplay","MdiIcon","useConfirmationContext","ScrollTable","useSnackbar","Timestamp","Alert","Button","Chip","IconButton","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","Stack","Switch","TableBody","TableCell","TableHead","TableRow","TextField","Typography","collection","doc","limit","orderBy","query","useState","useFirestore","useFirestoreCollection","useHostActivityLogger","writeGuardedBySeed","useUser","writeSiteWideChange","overlayDisplayName","overlayEngagementLabel","overlayPagesLabel","overlayWindowLabel","OVERLAY_COPY_HELPER_TEXT","shownAsTypedHelperText","useOverlayCopyEditor","HostOverlaysZone","OverlayEditorZone","CEILING","EMPTY_BAR","kind","enabled","bar","dismissible","EMPTY_POPUP","popup","trigger","triggerValue","frequencyDays","toDatetimeLocal","ms","date","Date","pad","value","String","padStart","getFullYear","getMonth","getDate","getHours","getMinutes","fromDatetimeLocal","undefined","getTime","Number","isFinite","parsePatterns","split","map","pattern","trim","filter","Boolean","HostOverlaysCard","props","editor","hostId","firestore","data","user","org","enqueueSnackbar","confirm","logActivity","entitled","overlayDocs","status","overlaysStatus","fromCache","overlaysFromCache","idField","truncated","length","overlays","slice","sort","setEditor","copy","usesTokens","text","headline","body","some","includes","barTextShownAsTyped","shownAsTyped","headlineShownAsTyped","bodyShownAsTyped","patch","partial","previous","patchBar","patchPopup","handleSave","variant","persist","id","$id","_ignored","createdAt","_createdAt","updatedAt","_updatedAt","payload","cleaned","JSON","parse","stringify","stored","name","verdict","subject","unreadable","write","batch","set","now","type","ok","message","error","console","createOverlayDraft","proposal","draft","proposeOverlayCopy","values","ctaLabel","overlayRules","limits","triggers","handleDelete","overlay","confirmed","title","description","confirmationText","confirmationButtonProps","color","then","catch","delete","handleMove","index","direction","current","neighbor","currentOrder","order","neighborOrder","merge","handleToggle","statusChip","size","label","header","help","anchor","excerpt","contentGutterX","contentGutterY","contentBordered","severity","spacing","onClick","sx","alignItems","align","stats","aria-label","disabled","indexOf","path","fontSize","checked","onChange","slotProps","input","open","onClose","maxWidth","fullWidth","mt","event","target","helperText","overlayId","editable","ctaHref","proposeValues","required","href","backgroundColor","textColor","multiline","minRows","select","minWidth","oncePerSession","inputLabel","shrink","startAtMs","endAtMs","pathPatterns","join","excludePathPatterns","pending","displayName"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The zone a marketing report hosts in its header (AGL-3603): the
3
+ * Conversions section and one campaign's report.
4
+ *
5
+ * A widget here explains the figures the page shows, in words. It is handed
6
+ * the site the figures are one site's — the site picked on the
7
+ * organization's Conversions section, the site a campaign email was sent as —
8
+ * and what the page is about, and nothing else: the figures it reads are the
9
+ * ones this plugin publishes to other plugins as figure readers
10
+ * (`server/marketing-figures.ts`), never this page's documents. There is
11
+ * nothing to apply and nothing a widget may write.
12
+ */
13
+ /** What the report a widget sits on is about. */
14
+ export type MarketingInsightSubject = 'conversions' | 'campaign';
15
+ /** What {@link MARKETING_INSIGHTS_ZONE} hands each widget. */
16
+ export interface MarketingInsightsZoneProps {
17
+ /** The site the figures are one site's; `null` when the page has none to name yet. */
18
+ hostId: string | null;
19
+ subject: MarketingInsightSubject;
20
+ /** One campaign's report: the subject line it is known by. `null` elsewhere. */
21
+ campaign: string | null;
22
+ }
23
+ export declare const MARKETING_INSIGHTS_ZONE: import("@aglyn/aglyn/plugin-manager/plugin-zones").PluginZone<MarketingInsightsZoneProps>;
24
+ /** The report's zone, drawn through the shell's renderer, or nothing outside the shell. */
25
+ export declare function MarketingInsightsZone(props: MarketingInsightsZoneProps): import("react").JSX.Element;
26
+ export declare namespace MarketingInsightsZone {
27
+ var displayName: string;
28
+ }