@elevasis/ui 2.70.0 → 2.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/api/index.js +3 -3
  2. package/dist/app/index.d.ts +28 -2
  3. package/dist/app/index.js +8 -8
  4. package/dist/auth/index.js +4 -4
  5. package/dist/charts/index.js +4 -4
  6. package/dist/{chunk-GZADST64.js → chunk-2454MK7P.js} +7 -7
  7. package/dist/{chunk-26BTE3Z4.js → chunk-753MKWFV.js} +1 -1
  8. package/dist/{chunk-LWYLZUUV.js → chunk-7ESZKTQG.js} +3 -3
  9. package/dist/{chunk-SMH6SQQE.js → chunk-A3JHFZDP.js} +1 -1
  10. package/dist/{chunk-MFCV4JMQ.js → chunk-AFBFSXP3.js} +4 -4
  11. package/dist/{chunk-TJMZUL6E.js → chunk-DJWIIPKW.js} +3 -3
  12. package/dist/{chunk-QDMIFD6F.js → chunk-DKVGO6RJ.js} +1 -1
  13. package/dist/{chunk-LY3IKYTZ.js → chunk-IMZTRDY2.js} +2 -2
  14. package/dist/{chunk-JA2XDMAE.js → chunk-IXBRUIYI.js} +1 -1
  15. package/dist/{chunk-6TT3FQEZ.js → chunk-KIDZXZM5.js} +149 -17
  16. package/dist/{chunk-CCZJ4OWY.js → chunk-LCHL5SM2.js} +1 -1
  17. package/dist/{chunk-5C62IRKS.js → chunk-LEQGGX2U.js} +4 -4
  18. package/dist/{chunk-NM4A63KJ.js → chunk-Q3O3WY7Q.js} +23 -7
  19. package/dist/{chunk-GJQF3S2Q.js → chunk-RRS2QR3W.js} +1 -1
  20. package/dist/{chunk-DUEGHF7A.js → chunk-SV4M2BUI.js} +4 -4
  21. package/dist/{chunk-AGX2CY2O.js → chunk-UZ5JO5TK.js} +1 -1
  22. package/dist/{chunk-C75XWBYZ.js → chunk-XZIOCB5D.js} +1 -1
  23. package/dist/{chunk-VDX6DL7Z.js → chunk-Z2W5VNN3.js} +1 -1
  24. package/dist/{chunk-XKUEO4HG.js → chunk-ZBXCEWKF.js} +3 -3
  25. package/dist/components/index.d.ts +61 -5
  26. package/dist/components/index.js +23 -23
  27. package/dist/components/navigation/index.js +5 -5
  28. package/dist/features/auth/index.d.ts +26 -0
  29. package/dist/features/auth/index.js +6 -6
  30. package/dist/features/clients/index.js +5 -5
  31. package/dist/features/content/index.d.ts +187 -113
  32. package/dist/features/content/index.js +200 -303
  33. package/dist/features/crm/index.d.ts +29 -2
  34. package/dist/features/crm/index.js +6 -6
  35. package/dist/features/dashboard/index.d.ts +1 -1
  36. package/dist/features/dashboard/index.js +6 -6
  37. package/dist/features/delivery/index.d.ts +26 -0
  38. package/dist/features/delivery/index.js +5 -5
  39. package/dist/features/knowledge/index.js +4 -4
  40. package/dist/features/lead-gen/index.d.ts +3 -2
  41. package/dist/features/lead-gen/index.js +6 -6
  42. package/dist/features/monitoring/index.d.ts +33 -3
  43. package/dist/features/monitoring/index.js +7 -7
  44. package/dist/features/monitoring/requests/index.js +5 -5
  45. package/dist/features/operations/index.d.ts +2 -2
  46. package/dist/features/operations/index.js +9 -9
  47. package/dist/features/settings/index.d.ts +26 -0
  48. package/dist/features/settings/index.js +6 -6
  49. package/dist/hooks/access/index.js +4 -4
  50. package/dist/hooks/delivery/index.d.ts +26 -0
  51. package/dist/hooks/delivery/index.js +2 -2
  52. package/dist/hooks/index.d.ts +310 -14
  53. package/dist/hooks/index.js +4 -4
  54. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +1 -1
  55. package/dist/hooks/published.d.ts +310 -14
  56. package/dist/hooks/published.js +4 -4
  57. package/dist/initialization/index.d.ts +26 -0
  58. package/dist/knowledge/index.d.ts +2 -2
  59. package/dist/knowledge/index.js +18 -18
  60. package/dist/{knowledge-search-index-LP2WVSQX.js → knowledge-search-index-RZLIVWPJ.js} +5 -5
  61. package/dist/layout/index.js +7 -7
  62. package/dist/profile/index.d.ts +26 -0
  63. package/dist/provider/index.d.ts +28 -2
  64. package/dist/provider/index.js +4 -4
  65. package/dist/provider/published.d.ts +28 -2
  66. package/dist/provider/published.js +4 -4
  67. package/dist/supabase/index.d.ts +50 -0
  68. package/dist/test-utils/index.js +3 -3
  69. package/dist/types/index.d.ts +60 -4
  70. package/dist/utils/index.d.ts +1 -1
  71. package/dist/utils/index.js +1 -1
  72. package/package.json +5 -5
@@ -1,14 +1,14 @@
1
1
  import { PageContainer } from '../../chunk-BZZCNLT6.js';
2
2
  import '../../chunk-TUMSNGTX.js';
3
3
  import { FilterBar } from '../../chunk-PDHTXPSF.js';
4
- import { CustomModal, useContentItems, useContentDistributions, useContentConfig, SubshellContentContainer, PageTitleCaption, CenteredErrorState, EmptyState, StatCard, getContentItemIdentity, usePaginationState, useContentItem, useContentItemAttempts, useUpdateContentItem, useReviewContentItem, useContentDistribution, useUpdateContentDistribution, useContentPipelineSummary, deriveContentBoard, useExecutions } from '../../chunk-6TT3FQEZ.js';
5
- export { CONTENT_ITEMS, ContentSidebar, ContentSidebarMiddle, DEFAULT_CONTENT_VOCABULARY, MyReviewQueuePanel, contentManifest, deriveContentBoard, getContentItemIdentity, resolveContentStepResource, resolveContentVocabulary, useContentConfig } from '../../chunk-6TT3FQEZ.js';
4
+ import { CustomModal, useContentItems, useContentDistributions, useContentConfig, SubshellContentContainer, PageTitleCaption, CenteredErrorState, EmptyState, StatCard, getContentItemIdentity, usePaginationState, useContentItem, useContentItemAttempts, useUpdateContentItem, useReviewContentItem, getOpenContentReviewGates, resolveContentWorkspaceRoute, useContentDistribution, useContentPipelineSummary, deriveContentBoard, useExecutions } from '../../chunk-KIDZXZM5.js';
5
+ export { CONTENT_ITEMS, ContentSidebar, ContentSidebarMiddle, DEFAULT_CONTENT_VOCABULARY, MyReviewQueuePanel, contentManifest, deriveContentBoard, getContentItemIdentity, resolveContentStepResource, resolveContentVocabulary, useContentConfig } from '../../chunk-KIDZXZM5.js';
6
6
  import '../../chunk-R6NMRXNO.js';
7
7
  import '../../chunk-RBGVNPA6.js';
8
8
  import '../../chunk-MKH2KOAO.js';
9
- import '../../chunk-VDX6DL7Z.js';
9
+ import '../../chunk-Z2W5VNN3.js';
10
10
  import '../../chunk-L7BZZ4SI.js';
11
- import { showSuccessNotification } from '../../chunk-C75XWBYZ.js';
11
+ import { showSuccessNotification } from '../../chunk-XZIOCB5D.js';
12
12
  import '../../chunk-MISHPEJX.js';
13
13
  import { CardHeader } from '../../chunk-62GVNH5U.js';
14
14
  import '../../chunk-P45GQ3ZW.js';
@@ -20,7 +20,7 @@ import '../../chunk-UD657ICS.js';
20
20
  import '../../chunk-DD3CCMCZ.js';
21
21
  import '../../chunk-RNP5R5I3.js';
22
22
  import '../../chunk-RT4KRGZT.js';
23
- import { formatTimeAgo, formatRelativeTime } from '../../chunk-NM4A63KJ.js';
23
+ import { formatTimeAgo, formatRelativeTime } from '../../chunk-Q3O3WY7Q.js';
24
24
  import '../../chunk-Y6I3IC45.js';
25
25
  import '../../chunk-6SSQGWK7.js';
26
26
  import '../../chunk-BI5VDO2K.js';
@@ -29,8 +29,8 @@ import '../../chunk-TVTSASST.js';
29
29
  import '../../chunk-BRJ3QZ4E.js';
30
30
  import '../../chunk-Q7DJKLEN.js';
31
31
  import '../../chunk-I2KLQ2HA.js';
32
- import { Stack, Group, Text, Badge, Button, Textarea, Box, Loader, Accordion, Card, Alert, List, Paper, Center, SimpleGrid, Table, TextInput, Select, Pagination, Title, Tabs, Anchor, Divider, Progress, Checkbox, TagsInput, Image, Tooltip, ActionIcon, UnstyledButton, ScrollArea } from '@mantine/core';
33
- import { IconAlertTriangle, IconShieldCheck, IconShieldX, IconArticle, IconArrowRight, IconClock, IconSend, IconSearch, IconFileText, IconListDetails, IconAlertCircle, IconLayoutGrid, IconShare, IconPlayerPlay, IconExternalLink, IconMaximize, IconCopy, IconDownload, IconTrash, IconArrowLeft, IconArrowsExchange, IconCheck, IconX, IconChecklist, IconRoute, IconInfoCircle, IconClockHour4 } from '@tabler/icons-react';
32
+ import { Stack, Group, Text, Badge, Button, Textarea, Box, Loader, Accordion, Tooltip, Card, Alert, List, Paper, Center, SimpleGrid, Table, TextInput, Select, Pagination, Title, Tabs, Anchor, Divider, Progress, Image, ActionIcon, UnstyledButton, ScrollArea } from '@mantine/core';
33
+ import { IconAlertTriangle, IconShieldCheck, IconShieldX, IconArticle, IconArrowRight, IconClock, IconSend, IconSearch, IconFileText, IconExternalLink, IconListDetails, IconAlertCircle, IconLayoutGrid, IconShare, IconPlayerPlay, IconCircleCheck, IconCircleDashed, IconMaximize, IconCopy, IconDownload, IconArrowLeft, IconArrowsExchange, IconCheck, IconX, IconChecklist, IconRoute, IconInfoCircle, IconClockHour4 } from '@tabler/icons-react';
34
34
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
35
35
  import { useState, useMemo, Fragment as Fragment$1, useCallback, useEffect } from 'react';
36
36
  import { useNavigate, useSearch } from '@tanstack/react-router';
@@ -335,7 +335,7 @@ function ReviewActionBar({ actions, onAction, pending = false }) {
335
335
  /* @__PURE__ */ jsx(Group, { gap: "xs", children: actions.map((action) => {
336
336
  const Icon = action.icon;
337
337
  const irreversible = isIrreversible(action);
338
- return /* @__PURE__ */ jsx(
338
+ const button = /* @__PURE__ */ jsx(
339
339
  Button,
340
340
  {
341
341
  variant: irreversible ? "filled" : "light",
@@ -343,15 +343,15 @@ function ReviewActionBar({ actions, onAction, pending = false }) {
343
343
  color: resolveActionColor(action),
344
344
  leftSection: Icon ? /* @__PURE__ */ jsx(Icon, { size: 16 }) : void 0,
345
345
  loading: pending,
346
- disabled: pending,
346
+ disabled: pending || action.disabled,
347
347
  onClick: () => openAction(action),
348
348
  size: "xs",
349
349
  radius: "xs",
350
350
  "data-testid": `content-review-action-${action.id}`,
351
351
  children: action.label
352
- },
353
- action.id
352
+ }
354
353
  );
354
+ return action.disabled && action.disabledReason ? /* @__PURE__ */ jsx(Tooltip, { label: action.disabledReason, withArrow: true, position: "top", children: /* @__PURE__ */ jsx("span", { children: button }) }, action.id) : /* @__PURE__ */ jsx("span", { children: button }, action.id);
355
355
  }) }),
356
356
  /* @__PURE__ */ jsx(CustomModal, { opened: !!confirmAction, onClose: () => setConfirmAction(null), size: "sm", children: /* @__PURE__ */ jsxs(Stack, { children: [
357
357
  /* @__PURE__ */ jsx(Text, { fw: 600, children: confirmAction?.label }),
@@ -425,7 +425,8 @@ function ContentReviewCard({
425
425
  processingSteps = [],
426
426
  actions,
427
427
  onAction,
428
- actionsPending = false
428
+ actionsPending = false,
429
+ readOnly = false
429
430
  }) {
430
431
  return /* @__PURE__ */ jsx(Card, { withBorder: true, radius: "md", padding: "xl", "data-testid": "content-review-card", children: /* @__PURE__ */ jsxs(Stack, { gap: "lg", children: [
431
432
  title || processingSteps.length > 0 ? /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", wrap: "nowrap", children: [
@@ -466,10 +467,10 @@ function ContentReviewCard({
466
467
  onReset,
467
468
  payload,
468
469
  payloadFields,
469
- disabled: actionsPending
470
+ disabled: actionsPending || readOnly
470
471
  }
471
472
  ),
472
- /* @__PURE__ */ jsx(
473
+ readOnly ? null : /* @__PURE__ */ jsx(
473
474
  AlternatesPanel,
474
475
  {
475
476
  body,
@@ -708,6 +709,16 @@ function ContentItemsPage({ headerActions } = {}) {
708
709
  const [statusFilter, setStatusFilter] = useState("");
709
710
  const [pillarFilter, setPillarFilter] = useState("");
710
711
  const pagination = usePaginationState(PAGE_SIZE, [searchQuery, statusFilter, pillarFilter, reviewFilterActive]);
712
+ const openItem = (item) => {
713
+ const pipeline = contentConfig.pipelines.find((candidate) => candidate.id === item.pipelineId);
714
+ const openGate = getOpenContentReviewGates(item.processingState ?? {}, pipeline?.steps ?? [])[0];
715
+ const workspaceRoute = openGate ? resolveContentWorkspaceRoute(pipeline, openGate.step) : void 0;
716
+ if (workspaceRoute) {
717
+ void navigate({ to: workspaceRoute });
718
+ return;
719
+ }
720
+ void navigate({ to: "/content/items/$itemId", params: { itemId: item.id } });
721
+ };
711
722
  const itemsQuery = useContentItems({
712
723
  search: searchQuery.trim() || void 0,
713
724
  status: statusFilter || void 0,
@@ -789,31 +800,23 @@ function ContentItemsPage({ headerActions } = {}) {
789
800
  const statusEntry = contentConfig.stageCatalog[item.status];
790
801
  const pillarEntry = item.pillar ? contentConfig.stageCatalog[item.pillar] : void 0;
791
802
  const statusColors = getContentStageColor(statusEntry);
792
- return /* @__PURE__ */ jsxs(
793
- Table.Tr,
794
- {
795
- style: { cursor: "pointer" },
796
- onClick: () => navigate({ to: "/content/items/$itemId", params: { itemId: item.id } }),
797
- children: [
798
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: getContentItemIdentity(item) }) }),
799
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(
800
- Badge,
801
- {
802
- size: "sm",
803
- variant: "light",
804
- styles: {
805
- root: { color: statusColors.accent, backgroundColor: statusColors.background }
806
- },
807
- children: statusEntry?.label ?? item.status
808
- }
809
- ) }),
810
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: pillarEntry?.label ?? item.pillar ?? "\u2014" }) }),
811
- /* @__PURE__ */ jsx(Table.Td, { children: item.reviewedAt ? /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "var(--color-success)", children: "Reviewed" }) : /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "var(--color-warning)", children: "Pending" }) }),
812
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: formatRelativeTime(item.updatedAt) }) })
813
- ]
814
- },
815
- item.id
816
- );
803
+ return /* @__PURE__ */ jsxs(Table.Tr, { style: { cursor: "pointer" }, onClick: () => openItem(item), children: [
804
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: getContentItemIdentity(item) }) }),
805
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(
806
+ Badge,
807
+ {
808
+ size: "sm",
809
+ variant: "light",
810
+ styles: {
811
+ root: { color: statusColors.accent, backgroundColor: statusColors.background }
812
+ },
813
+ children: statusEntry?.label ?? item.status
814
+ }
815
+ ) }),
816
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: pillarEntry?.label ?? item.pillar ?? "\u2014" }) }),
817
+ /* @__PURE__ */ jsx(Table.Td, { children: item.reviewedAt ? /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "var(--color-success)", children: "Reviewed" }) : /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "var(--color-warning)", children: "Pending" }) }),
818
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: formatRelativeTime(item.updatedAt) }) })
819
+ ] }, item.id);
817
820
  }) })
818
821
  ] }),
819
822
  total > PAGE_SIZE && /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(
@@ -832,15 +835,20 @@ function ContentItemsPage({ headerActions } = {}) {
832
835
  // src/lib/content/processing-state.ts
833
836
  function mapContentStepStatus(status) {
834
837
  if (status === void 0) return "pending";
838
+ if (status === "running") return "in_progress";
835
839
  if (status === "error") return "failed";
836
840
  return "completed";
837
841
  }
838
842
  function getContentProcessingSteps(processingState, pipelineSteps) {
839
- return pipelineSteps.map((step) => ({
840
- key: step.key,
841
- label: step.label,
842
- status: mapContentStepStatus(processingState?.[step.key]?.status)
843
- }));
843
+ return pipelineSteps.map((step) => {
844
+ const entry = processingState?.[step.key];
845
+ return {
846
+ key: step.key,
847
+ label: step.label,
848
+ status: mapContentStepStatus(entry?.status),
849
+ executionId: entry ? entry.executionId : void 0
850
+ };
851
+ });
844
852
  }
845
853
 
846
854
  // src/lib/content/payload-text.ts
@@ -873,7 +881,9 @@ function toPayloadDisplayFields(fields, payload) {
873
881
  return fields.filter((field) => field.key in payloadRecord).map((field) => ({ key: field.key, label: field.label, kind: toDisplayKind(field.type) }));
874
882
  }
875
883
  var REVIEW_QUEUE_FETCH_LIMIT = 100;
876
- function buildReviewActions(isTerminalPipeline) {
884
+ function buildReviewActions(isTerminalPipeline, gate, reason) {
885
+ const gateLabel = gate?.step.label;
886
+ const disabled = !gate;
877
887
  return [
878
888
  {
879
889
  id: "approved",
@@ -887,8 +897,10 @@ function buildReviewActions(isTerminalPipeline) {
887
897
  requiresFeedback: true,
888
898
  feedbackLabel: "Note (optional)",
889
899
  feedbackPlaceholder: "Anything the next step or a later reader should know?",
890
- confirmationMessage: isTerminalPipeline ? "Approve this item? There is no further pipeline step -- this is the last internal gate before it is published." : "Approve this item? It moves on to the next pipeline step.",
891
- consequence: isTerminalPipeline ? "irreversible" : "standard"
900
+ confirmationMessage: gateLabel ? isTerminalPipeline ? `Approve "${gateLabel}"? There is no further pipeline step -- this is the last internal gate before it is published.` : `Approve "${gateLabel}"? It moves on to the next pipeline step.` : void 0,
901
+ consequence: isTerminalPipeline ? "irreversible" : "standard",
902
+ disabled,
903
+ disabledReason: reason
892
904
  },
893
905
  {
894
906
  id: "rejected",
@@ -898,7 +910,10 @@ function buildReviewActions(isTerminalPipeline) {
898
910
  requiresFeedback: true,
899
911
  feedbackLabel: "Reason for rejection",
900
912
  feedbackPlaceholder: "What needs to change before this can go out?",
901
- feedbackRequired: true
913
+ feedbackRequired: true,
914
+ confirmationMessage: gateLabel ? `Reject "${gateLabel}"? This sends it back for changes.` : void 0,
915
+ disabled,
916
+ disabledReason: reason
902
917
  }
903
918
  ];
904
919
  }
@@ -930,7 +945,22 @@ function ContentItemReviewPage({ itemId, headerActions }) {
930
945
  const pipeline = item ? contentConfig.pipelines.find((candidate) => candidate.id === item.pipelineId) : void 0;
931
946
  const pipelineSteps = useMemo(() => pipeline?.steps ?? [], [pipeline]);
932
947
  const isTerminalPipeline = pipelineSteps.length <= 1;
933
- const reviewActions = useMemo(() => buildReviewActions(isTerminalPipeline), [isTerminalPipeline]);
948
+ const openGates = useMemo(
949
+ () => getOpenContentReviewGates(item?.processingState ?? {}, pipelineSteps),
950
+ [item?.processingState, pipelineSteps]
951
+ );
952
+ const earliestOpenGate = openGates[0];
953
+ const reviewDisabledReason = useMemo(() => {
954
+ if (earliestOpenGate) return void 0;
955
+ if (!item?.pipelineId) return "This item has no pipeline, so there is no review gate to clear.";
956
+ if (!pipeline) return `Unknown pipeline "${item.pipelineId}" -- there is no review gate to clear.`;
957
+ return "No open review gate on this item. Every queued step has already been reviewed, or the current step is still running.";
958
+ }, [earliestOpenGate, item?.pipelineId, pipeline]);
959
+ const workspaceRoute = resolveContentWorkspaceRoute(pipeline, earliestOpenGate?.step);
960
+ const reviewActions = useMemo(
961
+ () => workspaceRoute ? [] : buildReviewActions(isTerminalPipeline, earliestOpenGate, reviewDisabledReason),
962
+ [workspaceRoute, isTerminalPipeline, earliestOpenGate, reviewDisabledReason]
963
+ );
934
964
  const pipelinePayloadFields = useMemo(() => getPipelinePayloadFields(pipelineSteps), [pipelineSteps]);
935
965
  const primaryTextField = useMemo(() => getPrimaryPayloadTextField(pipelinePayloadFields), [pipelinePayloadFields]);
936
966
  const originalBody = item ? getPayloadText(item.payload, primaryTextField?.key) : "";
@@ -1039,16 +1069,21 @@ function ContentItemReviewPage({ itemId, headerActions }) {
1039
1069
  showSuccessNotification("Saved");
1040
1070
  };
1041
1071
  const handleAction = async (actionId, feedback) => {
1072
+ if (!earliestOpenGate) return;
1073
+ const stepKey = earliestOpenGate.stepKey;
1042
1074
  await persistBodyIfDirty();
1043
1075
  if (actionId === "approved") {
1044
1076
  const note = feedback?.trim();
1045
1077
  await reviewItem.mutateAsync({
1046
1078
  itemId: item.id,
1047
- review: { decision: "approved", reviewerFeedback: note ? note : void 0 }
1079
+ review: { decision: "approved", stepKey, reviewerFeedback: note ? note : void 0 }
1048
1080
  });
1049
1081
  showSuccessNotification("Item approved");
1050
1082
  } else if (actionId === "rejected") {
1051
- await reviewItem.mutateAsync({ itemId: item.id, review: { decision: "rejected", rejectReason: feedback ?? "" } });
1083
+ await reviewItem.mutateAsync({
1084
+ itemId: item.id,
1085
+ review: { decision: "rejected", stepKey, rejectReason: feedback ?? "" }
1086
+ });
1052
1087
  showSuccessNotification("Item rejected");
1053
1088
  }
1054
1089
  goToNextInQueue();
@@ -1068,7 +1103,7 @@ function ContentItemReviewPage({ itemId, headerActions }) {
1068
1103
  ] })
1069
1104
  ] }),
1070
1105
  /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
1071
- /* @__PURE__ */ jsx(
1106
+ workspaceRoute ? null : /* @__PURE__ */ jsx(
1072
1107
  Button,
1073
1108
  {
1074
1109
  size: "xs",
@@ -1082,6 +1117,38 @@ function ContentItemReviewPage({ itemId, headerActions }) {
1082
1117
  backButton
1083
1118
  ] })
1084
1119
  ] }),
1120
+ reviewDisabledReason && /* @__PURE__ */ jsx(
1121
+ Alert,
1122
+ {
1123
+ icon: /* @__PURE__ */ jsx(IconAlertTriangle, { size: 16 }),
1124
+ color: "var(--color-warning)",
1125
+ variant: "light",
1126
+ title: "Nothing to review right now",
1127
+ "data-testid": "content-review-no-open-gate",
1128
+ children: /* @__PURE__ */ jsx(Text, { size: "sm", children: reviewDisabledReason })
1129
+ }
1130
+ ),
1131
+ workspaceRoute && earliestOpenGate && /* @__PURE__ */ jsx(
1132
+ Alert,
1133
+ {
1134
+ icon: /* @__PURE__ */ jsx(IconExternalLink, { size: 16 }),
1135
+ variant: "light",
1136
+ title: "Reviewed in your workspace",
1137
+ "data-testid": "content-review-workspace-pointer",
1138
+ children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", align: "flex-start", children: [
1139
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: "This pipeline clears its gates on your own screen. Everything below is the piece as it stands." }),
1140
+ /* @__PURE__ */ jsx(
1141
+ Button,
1142
+ {
1143
+ size: "xs",
1144
+ rightSection: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 }),
1145
+ onClick: () => void navigate({ to: workspaceRoute }),
1146
+ children: "Open workspace"
1147
+ }
1148
+ )
1149
+ ] })
1150
+ }
1151
+ ),
1085
1152
  /* @__PURE__ */ jsx(
1086
1153
  ContentReviewCard,
1087
1154
  {
@@ -1095,7 +1162,8 @@ function ContentItemReviewPage({ itemId, headerActions }) {
1095
1162
  processingSteps: visibleProcessingSteps,
1096
1163
  actions: reviewActions,
1097
1164
  onAction: handleAction,
1098
- actionsPending: isSaving
1165
+ actionsPending: isSaving,
1166
+ readOnly: workspaceRoute !== void 0
1099
1167
  }
1100
1168
  ),
1101
1169
  item.reviewerFeedback && /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
@@ -1276,7 +1344,7 @@ function formatAge(ms) {
1276
1344
  return `${Math.floor(hours / 24)}d`;
1277
1345
  }
1278
1346
  function BoardItemCard({ card, onOpen }) {
1279
- return /* @__PURE__ */ jsx(Card, { withBorder: true, padding: "xs", onClick: () => onOpen(card.item.id), style: { cursor: "pointer" }, children: /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
1347
+ return /* @__PURE__ */ jsx(Card, { withBorder: true, padding: "xs", onClick: () => onOpen(card), style: { cursor: "pointer" }, children: /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
1280
1348
  /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, lineClamp: 2, children: getContentItemIdentity(card.item) }),
1281
1349
  /* @__PURE__ */ jsxs(Group, { gap: 6, justify: "space-between", wrap: "nowrap", children: [
1282
1350
  /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
@@ -1356,7 +1424,15 @@ function BoardTab({ pipeline }) {
1356
1424
  const itemsQuery = useContentItems({ pipelineId: pipeline.id, limit: BOARD_FETCH_LIMIT });
1357
1425
  const items = useMemo(() => itemsQuery.data?.data ?? [], [itemsQuery.data]);
1358
1426
  const board = useMemo(() => deriveContentBoard(items, pipeline, Date.now()), [items, pipeline]);
1359
- const openItem = (itemId) => navigate({ to: "/content/items/$itemId", params: { itemId } });
1427
+ const openItem = (card) => {
1428
+ const heldAtStep = pipeline.steps.find((step) => step.key === card.stepKey);
1429
+ const workspaceRoute = card.awaitingReview ? resolveContentWorkspaceRoute(pipeline, heldAtStep) : void 0;
1430
+ if (workspaceRoute) {
1431
+ void navigate({ to: workspaceRoute });
1432
+ return;
1433
+ }
1434
+ void navigate({ to: "/content/items/$itemId", params: { itemId: card.item.id } });
1435
+ };
1360
1436
  if (itemsQuery.isLoading) {
1361
1437
  return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) });
1362
1438
  }
@@ -1571,21 +1647,21 @@ function RunsTab({ pipeline }) {
1571
1647
  const contentConfig = useContentConfig();
1572
1648
  return /* @__PURE__ */ jsx(Stack, { gap: "md", children: pipeline.steps.map((step) => /* @__PURE__ */ jsx(StepRunsSection, { step, resourceId: contentConfig.resolveStepResource(step)?.resourceId }, step.key)) });
1573
1649
  }
1574
- var PIPELINE_WORKSPACE_TABS = ["board", "distributions", "runs"];
1575
- function isPipelineWorkspaceTab(value) {
1576
- return typeof value === "string" && PIPELINE_WORKSPACE_TABS.includes(value);
1650
+ var PIPELINE_BOARD_TABS = ["board", "distributions", "runs"];
1651
+ function isPipelineBoardTab(value) {
1652
+ return typeof value === "string" && PIPELINE_BOARD_TABS.includes(value);
1577
1653
  }
1578
- function ContentPipelineWorkspacePage({
1654
+ function ContentPipelineBoardPage({
1579
1655
  pipelineId,
1580
1656
  headerActions
1581
1657
  }) {
1582
1658
  const navigate = useNavigate();
1583
1659
  const contentConfig = useContentConfig();
1584
1660
  const rawSearch = useSearch({ strict: false });
1585
- const activeTab = isPipelineWorkspaceTab(rawSearch.tab) ? rawSearch.tab : "board";
1661
+ const activeTab = isPipelineBoardTab(rawSearch.tab) ? rawSearch.tab : "board";
1586
1662
  const handleTabChange = useCallback(
1587
1663
  (value) => {
1588
- if (!isPipelineWorkspaceTab(value) || value === activeTab) return;
1664
+ if (!isPipelineBoardTab(value) || value === activeTab) return;
1589
1665
  void navigate({
1590
1666
  to: ".",
1591
1667
  search: ((current) => ({ ...current, tab: value })),
@@ -1806,6 +1882,33 @@ function ContentDistributionsPage({ headerActions } = {}) {
1806
1882
  ] }) })
1807
1883
  ] }) }) });
1808
1884
  }
1885
+ var COMMON_PLATFORM_FIELDS = [
1886
+ { key: "title", label: "Title" },
1887
+ { key: "description", label: "Description" },
1888
+ { key: "tags", label: "Tags" }
1889
+ ];
1890
+ var PLATFORM_SPECIFIC_FIELDS = {
1891
+ youtube: [
1892
+ { key: "timestamps", label: "Timestamps" },
1893
+ { key: "endScreenVideoId", label: "End Screen Video ID" },
1894
+ { key: "pinnedComment", label: "Pinned Comment" }
1895
+ ],
1896
+ linkedin: [
1897
+ { key: "hook", label: "Hook" },
1898
+ { key: "hashtags", label: "Hashtags" },
1899
+ { key: "firstComment", label: "First Comment" }
1900
+ ],
1901
+ instagram: [
1902
+ { key: "altText", label: "Alt Text" },
1903
+ { key: "hashtags", label: "Hashtags" },
1904
+ { key: "storyLink", label: "Story Link" }
1905
+ ],
1906
+ x: [
1907
+ { key: "hookTweet", label: "Hook Tweet" },
1908
+ { key: "threadTweets", label: "Thread Tweets" },
1909
+ { key: "replyThread", label: "Reply Thread" }
1910
+ ]
1911
+ };
1809
1912
  function formatDateTime3(value) {
1810
1913
  return value ? new Date(value).toLocaleString() : "\u2014";
1811
1914
  }
@@ -1820,6 +1923,17 @@ function getChecklistProgress(checklist) {
1820
1923
  const done = checklist.filter((item) => item.done).length;
1821
1924
  return { done, total: checklist.length, pct: Math.round(done / checklist.length * 100) };
1822
1925
  }
1926
+ function hasPlatformFieldValue(value) {
1927
+ if (Array.isArray(value)) return value.length > 0;
1928
+ return typeof value === "string" && value.trim() !== "";
1929
+ }
1930
+ function PlatformContentField({ label, value }) {
1931
+ if (!hasPlatformFieldValue(value)) return null;
1932
+ return /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
1933
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: label }),
1934
+ Array.isArray(value) ? /* @__PURE__ */ jsx(Group, { gap: 4, children: value.map((entry, index) => /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", children: String(entry) }, `${String(entry)}-${index}`)) }) : /* @__PURE__ */ jsx(Text, { size: "sm", style: { whiteSpace: "pre-wrap" }, children: String(value) })
1935
+ ] });
1936
+ }
1823
1937
  function MetricsDisplay({ metrics }) {
1824
1938
  if (!metrics || typeof metrics !== "object" || Object.keys(metrics).length === 0) {
1825
1939
  return /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No metrics recorded yet." });
@@ -1843,17 +1957,8 @@ function ContentDistributionDetailPage({
1843
1957
  const distributionQuery = useContentDistribution(distributionId);
1844
1958
  const dist = distributionQuery.data;
1845
1959
  const itemQuery = useContentItem(dist?.contentItemId);
1846
- const updateDistribution = useUpdateContentDistribution();
1847
- const [platformContent, setPlatformContent] = useState({});
1848
- const [platformUrl, setPlatformUrl] = useState("");
1849
- const [status, setStatus] = useState("");
1850
1960
  const [mediaOpened, { open: openMedia, close: closeMedia }] = useDisclosure(false);
1851
1961
  const [previewUrl, setPreviewUrl] = useState(null);
1852
- useEffect(() => {
1853
- setPlatformUrl(dist?.platformUrl ?? "");
1854
- setStatus(dist?.status ?? "");
1855
- setPlatformContent(dist?.platformContent ?? {});
1856
- }, [dist?.id]);
1857
1962
  const backButton = /* @__PURE__ */ jsx(
1858
1963
  Button,
1859
1964
  {
@@ -1884,20 +1989,9 @@ function ContentDistributionDetailPage({
1884
1989
  const platformEntry = contentConfig.stageCatalog[dist.platform];
1885
1990
  const platformColors = getContentStageColor(platformEntry);
1886
1991
  const pillarEntry = contentItem?.pillar ? contentConfig.stageCatalog[contentItem.pillar] : void 0;
1887
- const isPlatformContentDirty = JSON.stringify(platformContent) !== JSON.stringify(dist.platformContent ?? {});
1888
- const patch = (updates) => {
1889
- updateDistribution.mutate({ distributionId, updates });
1890
- };
1891
- const updatePlatformField = (field, value) => {
1892
- setPlatformContent((prev) => ({ ...prev, [field]: value }));
1893
- };
1894
- const toggleChecklistItem = (key) => {
1895
- const nextChecklist = checklist.map((item) => item.key === key ? { ...item, done: !item.done } : item);
1896
- patch({ checklist: nextChecklist });
1897
- };
1898
- const deleteMedia = (url) => {
1899
- patch({ mediaUrls: mediaUrls.filter((existing) => existing !== url) });
1900
- };
1992
+ const platformContent = dist.platformContent ?? {};
1993
+ const platformFields = [...COMMON_PLATFORM_FIELDS, ...PLATFORM_SPECIFIC_FIELDS[dist.platform] ?? []];
1994
+ const hasPlatformContent = platformFields.some((field) => hasPlatformFieldValue(platformContent[field.key]));
1901
1995
  return /* @__PURE__ */ jsxs(SubshellContentContainer, { children: [
1902
1996
  /* @__PURE__ */ jsxs(PageContainer, { children: [
1903
1997
  /* @__PURE__ */ jsxs(Stack, { children: [
@@ -1955,30 +2049,9 @@ function ContentDistributionDetailPage({
1955
2049
  /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", w: 140, children: "Format" }),
1956
2050
  /* @__PURE__ */ jsx(Text, { size: "sm", children: dist.format })
1957
2051
  ] }),
1958
- /* @__PURE__ */ jsxs(Group, { wrap: "nowrap", children: [
2052
+ /* @__PURE__ */ jsxs(Group, { children: [
1959
2053
  /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", w: 140, children: "Status" }),
1960
- /* @__PURE__ */ jsx(
1961
- TextInput,
1962
- {
1963
- size: "xs",
1964
- value: status,
1965
- onChange: (event) => setStatus(event.currentTarget.value),
1966
- style: { flex: 1 },
1967
- onBlur: () => {
1968
- const value = status.trim();
1969
- if (value && value !== dist.status) {
1970
- const updates = { status: value };
1971
- if (value === "published" && !dist.publishedAt) {
1972
- updates.publishedAt = (/* @__PURE__ */ new Date()).toISOString();
1973
- }
1974
- patch(updates);
1975
- }
1976
- },
1977
- onKeyDown: (event) => {
1978
- if (event.key === "Enter") event.currentTarget.blur();
1979
- }
1980
- }
1981
- )
2054
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: dist.status })
1982
2055
  ] }),
1983
2056
  /* @__PURE__ */ jsxs(Group, { children: [
1984
2057
  /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", w: 140, children: "Publish Method" }),
@@ -2002,26 +2075,20 @@ function ContentDistributionDetailPage({
2002
2075
  ] }),
2003
2076
  /* @__PURE__ */ jsxs(Group, { wrap: "nowrap", children: [
2004
2077
  /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", w: 140, children: "URL" }),
2005
- /* @__PURE__ */ jsx(
2006
- TextInput,
2078
+ dist.platformUrl ? /* @__PURE__ */ jsx(
2079
+ Anchor,
2007
2080
  {
2008
- size: "xs",
2009
- placeholder: "https://...",
2010
- value: platformUrl,
2011
- onChange: (event) => setPlatformUrl(event.currentTarget.value),
2012
- style: { flex: 1 },
2013
- onBlur: () => {
2014
- const value = platformUrl.trim();
2015
- if (value !== (dist.platformUrl ?? "")) {
2016
- patch({ platformUrl: value || null });
2017
- }
2018
- },
2019
- onKeyDown: (event) => {
2020
- if (event.key === "Enter") event.currentTarget.blur();
2021
- },
2022
- rightSection: dist.platformUrl ? /* @__PURE__ */ jsx(Anchor, { href: dist.platformUrl, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 }) }) : void 0
2081
+ href: dist.platformUrl,
2082
+ target: "_blank",
2083
+ rel: "noopener noreferrer",
2084
+ size: "sm",
2085
+ style: { overflowWrap: "anywhere" },
2086
+ children: /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
2087
+ dist.platformUrl,
2088
+ /* @__PURE__ */ jsx(IconExternalLink, { size: 14 })
2089
+ ] })
2023
2090
  }
2024
- )
2091
+ ) : /* @__PURE__ */ jsx(Text, { size: "sm", children: "\u2014" })
2025
2092
  ] })
2026
2093
  ] })
2027
2094
  ] }) }),
@@ -2052,174 +2119,15 @@ function ContentDistributionDetailPage({
2052
2119
  ] })
2053
2120
  ] }),
2054
2121
  /* @__PURE__ */ jsx(Divider, {}),
2055
- /* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 1, sm: 2 }, spacing: "sm", verticalSpacing: "sm", children: checklist.map((item) => /* @__PURE__ */ jsx(
2056
- Checkbox,
2057
- {
2058
- label: item.label,
2059
- checked: item.done,
2060
- onChange: () => toggleChecklistItem(item.key),
2061
- disabled: updateDistribution.isPending,
2062
- size: "sm"
2063
- },
2064
- item.key
2065
- )) })
2122
+ /* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 1, sm: 2 }, spacing: "sm", verticalSpacing: "sm", children: checklist.map((item) => /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", align: "flex-start", children: [
2123
+ item.done ? /* @__PURE__ */ jsx(IconCircleCheck, { size: 16, color: "var(--color-success)" }) : /* @__PURE__ */ jsx(IconCircleDashed, { size: 16, color: "var(--mantine-color-dimmed)" }),
2124
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: item.done ? "dimmed" : void 0, children: item.label })
2125
+ ] }, item.key)) })
2066
2126
  ] }) }) : null,
2067
2127
  /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
2068
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
2069
- /* @__PURE__ */ jsx(Title, { order: 3, children: "Platform Content" }),
2070
- /* @__PURE__ */ jsx(
2071
- Button,
2072
- {
2073
- size: "xs",
2074
- disabled: !isPlatformContentDirty,
2075
- loading: updateDistribution.isPending,
2076
- onClick: () => patch({ platformContent }),
2077
- children: "Save"
2078
- }
2079
- )
2080
- ] }),
2128
+ /* @__PURE__ */ jsx(Title, { order: 3, children: "Platform Content" }),
2081
2129
  /* @__PURE__ */ jsx(Divider, {}),
2082
- /* @__PURE__ */ jsx(
2083
- TextInput,
2084
- {
2085
- label: "Title",
2086
- value: platformContent.title ?? "",
2087
- onChange: (event) => updatePlatformField("title", event.currentTarget.value)
2088
- }
2089
- ),
2090
- /* @__PURE__ */ jsx(
2091
- Textarea,
2092
- {
2093
- label: "Description",
2094
- autosize: true,
2095
- minRows: 2,
2096
- value: platformContent.description ?? "",
2097
- onChange: (event) => updatePlatformField("description", event.currentTarget.value)
2098
- }
2099
- ),
2100
- /* @__PURE__ */ jsx(
2101
- TagsInput,
2102
- {
2103
- label: "Tags",
2104
- value: platformContent.tags ?? [],
2105
- onChange: (value) => updatePlatformField("tags", value)
2106
- }
2107
- ),
2108
- dist.platform === "youtube" && /* @__PURE__ */ jsxs(Fragment, { children: [
2109
- /* @__PURE__ */ jsx(
2110
- TagsInput,
2111
- {
2112
- label: "Timestamps",
2113
- placeholder: "0:00 Intro",
2114
- value: platformContent.timestamps ?? [],
2115
- onChange: (value) => updatePlatformField("timestamps", value)
2116
- }
2117
- ),
2118
- /* @__PURE__ */ jsx(
2119
- TextInput,
2120
- {
2121
- label: "End Screen Video ID",
2122
- value: platformContent.endScreenVideoId ?? "",
2123
- onChange: (event) => updatePlatformField("endScreenVideoId", event.currentTarget.value)
2124
- }
2125
- ),
2126
- /* @__PURE__ */ jsx(
2127
- Textarea,
2128
- {
2129
- label: "Pinned Comment",
2130
- autosize: true,
2131
- minRows: 2,
2132
- value: platformContent.pinnedComment ?? "",
2133
- onChange: (event) => updatePlatformField("pinnedComment", event.currentTarget.value)
2134
- }
2135
- )
2136
- ] }),
2137
- dist.platform === "linkedin" && /* @__PURE__ */ jsxs(Fragment, { children: [
2138
- /* @__PURE__ */ jsx(
2139
- Textarea,
2140
- {
2141
- label: "Hook",
2142
- autosize: true,
2143
- minRows: 2,
2144
- value: platformContent.hook ?? "",
2145
- onChange: (event) => updatePlatformField("hook", event.currentTarget.value)
2146
- }
2147
- ),
2148
- /* @__PURE__ */ jsx(
2149
- TagsInput,
2150
- {
2151
- label: "Hashtags",
2152
- value: platformContent.hashtags ?? [],
2153
- onChange: (value) => updatePlatformField("hashtags", value)
2154
- }
2155
- ),
2156
- /* @__PURE__ */ jsx(
2157
- Textarea,
2158
- {
2159
- label: "First Comment",
2160
- autosize: true,
2161
- minRows: 2,
2162
- value: platformContent.firstComment ?? "",
2163
- onChange: (event) => updatePlatformField("firstComment", event.currentTarget.value)
2164
- }
2165
- )
2166
- ] }),
2167
- dist.platform === "instagram" && /* @__PURE__ */ jsxs(Fragment, { children: [
2168
- /* @__PURE__ */ jsx(
2169
- Textarea,
2170
- {
2171
- label: "Alt Text",
2172
- autosize: true,
2173
- minRows: 2,
2174
- value: platformContent.altText ?? "",
2175
- onChange: (event) => updatePlatformField("altText", event.currentTarget.value)
2176
- }
2177
- ),
2178
- /* @__PURE__ */ jsx(
2179
- TagsInput,
2180
- {
2181
- label: "Hashtags",
2182
- value: platformContent.hashtags ?? [],
2183
- onChange: (value) => updatePlatformField("hashtags", value)
2184
- }
2185
- ),
2186
- /* @__PURE__ */ jsx(
2187
- TextInput,
2188
- {
2189
- label: "Story Link",
2190
- value: platformContent.storyLink ?? "",
2191
- onChange: (event) => updatePlatformField("storyLink", event.currentTarget.value)
2192
- }
2193
- )
2194
- ] }),
2195
- dist.platform === "x" && /* @__PURE__ */ jsxs(Fragment, { children: [
2196
- /* @__PURE__ */ jsx(
2197
- Textarea,
2198
- {
2199
- label: "Hook Tweet",
2200
- autosize: true,
2201
- minRows: 2,
2202
- value: platformContent.hookTweet ?? "",
2203
- onChange: (event) => updatePlatformField("hookTweet", event.currentTarget.value)
2204
- }
2205
- ),
2206
- /* @__PURE__ */ jsx(
2207
- TagsInput,
2208
- {
2209
- label: "Thread Tweets",
2210
- value: platformContent.threadTweets ?? [],
2211
- onChange: (value) => updatePlatformField("threadTweets", value)
2212
- }
2213
- ),
2214
- /* @__PURE__ */ jsx(
2215
- TextInput,
2216
- {
2217
- label: "Reply Thread",
2218
- value: platformContent.replyThread ?? "",
2219
- onChange: (event) => updatePlatformField("replyThread", event.currentTarget.value)
2220
- }
2221
- )
2222
- ] })
2130
+ hasPlatformContent ? platformFields.map((field) => /* @__PURE__ */ jsx(PlatformContentField, { label: field.label, value: platformContent[field.key] }, field.key)) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No platform content recorded yet." })
2223
2131
  ] }) }),
2224
2132
  dist.adaptedBody ? /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
2225
2133
  /* @__PURE__ */ jsx(Title, { order: 3, children: "Adapted Content" }),
@@ -2289,18 +2197,7 @@ function ContentDistributionDetailPage({
2289
2197
  }
2290
2198
  ) }),
2291
2199
  /* @__PURE__ */ jsx(Tooltip, { label: "Copy URL", children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", onClick: () => navigator.clipboard.writeText(url), children: /* @__PURE__ */ jsx(IconCopy, { size: 16 }) }) }),
2292
- /* @__PURE__ */ jsx(Tooltip, { label: "Download", children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", component: "a", href: url, download: true, target: "_blank", children: /* @__PURE__ */ jsx(IconDownload, { size: 16 }) }) }),
2293
- /* @__PURE__ */ jsx(Tooltip, { label: "Delete", children: /* @__PURE__ */ jsx(
2294
- ActionIcon,
2295
- {
2296
- variant: "subtle",
2297
- color: "var(--color-error)",
2298
- size: "sm",
2299
- loading: updateDistribution.isPending,
2300
- onClick: () => deleteMedia(url),
2301
- children: /* @__PURE__ */ jsx(IconTrash, { size: 16 })
2302
- }
2303
- ) })
2200
+ /* @__PURE__ */ jsx(Tooltip, { label: "Download", children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", component: "a", href: url, download: true, target: "_blank", children: /* @__PURE__ */ jsx(IconDownload, { size: 16 }) }) })
2304
2201
  ] })
2305
2202
  ] }, url)) })
2306
2203
  ] }) })
@@ -2309,4 +2206,4 @@ function ContentDistributionDetailPage({
2309
2206
  ] });
2310
2207
  }
2311
2208
 
2312
- export { AlternatesPanel, ContentDistributionDetailPage, ContentDistributionsPage, ContentItemReviewPage, ContentItemsPage, ContentOverviewPage, ContentPipelineWorkspacePage, ContentPipelinesPage, ContentReviewCard, PayloadBody, ProcessingStateStrip, ReviewActionBar, firstLine, formatElapsed, lastLine, swapFirstLine, swapLastLine };
2209
+ export { AlternatesPanel, ContentDistributionDetailPage, ContentDistributionsPage, ContentItemReviewPage, ContentItemsPage, ContentOverviewPage, ContentPipelineBoardPage, ContentPipelineBoardPage as ContentPipelineWorkspacePage, ContentPipelinesPage, ContentReviewCard, PayloadBody, ProcessingStateStrip, ReviewActionBar, firstLine, formatElapsed, lastLine, swapFirstLine, swapLastLine };