@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.
- package/dist/api/index.js +3 -3
- package/dist/app/index.d.ts +28 -2
- package/dist/app/index.js +8 -8
- package/dist/auth/index.js +4 -4
- package/dist/charts/index.js +4 -4
- package/dist/{chunk-GZADST64.js → chunk-2454MK7P.js} +7 -7
- package/dist/{chunk-26BTE3Z4.js → chunk-753MKWFV.js} +1 -1
- package/dist/{chunk-LWYLZUUV.js → chunk-7ESZKTQG.js} +3 -3
- package/dist/{chunk-SMH6SQQE.js → chunk-A3JHFZDP.js} +1 -1
- package/dist/{chunk-MFCV4JMQ.js → chunk-AFBFSXP3.js} +4 -4
- package/dist/{chunk-TJMZUL6E.js → chunk-DJWIIPKW.js} +3 -3
- package/dist/{chunk-QDMIFD6F.js → chunk-DKVGO6RJ.js} +1 -1
- package/dist/{chunk-LY3IKYTZ.js → chunk-IMZTRDY2.js} +2 -2
- package/dist/{chunk-JA2XDMAE.js → chunk-IXBRUIYI.js} +1 -1
- package/dist/{chunk-6TT3FQEZ.js → chunk-KIDZXZM5.js} +149 -17
- package/dist/{chunk-CCZJ4OWY.js → chunk-LCHL5SM2.js} +1 -1
- package/dist/{chunk-5C62IRKS.js → chunk-LEQGGX2U.js} +4 -4
- package/dist/{chunk-NM4A63KJ.js → chunk-Q3O3WY7Q.js} +23 -7
- package/dist/{chunk-GJQF3S2Q.js → chunk-RRS2QR3W.js} +1 -1
- package/dist/{chunk-DUEGHF7A.js → chunk-SV4M2BUI.js} +4 -4
- package/dist/{chunk-AGX2CY2O.js → chunk-UZ5JO5TK.js} +1 -1
- package/dist/{chunk-C75XWBYZ.js → chunk-XZIOCB5D.js} +1 -1
- package/dist/{chunk-VDX6DL7Z.js → chunk-Z2W5VNN3.js} +1 -1
- package/dist/{chunk-XKUEO4HG.js → chunk-ZBXCEWKF.js} +3 -3
- package/dist/components/index.d.ts +61 -5
- package/dist/components/index.js +23 -23
- package/dist/components/navigation/index.js +5 -5
- package/dist/features/auth/index.d.ts +26 -0
- package/dist/features/auth/index.js +6 -6
- package/dist/features/clients/index.js +5 -5
- package/dist/features/content/index.d.ts +187 -113
- package/dist/features/content/index.js +200 -303
- package/dist/features/crm/index.d.ts +29 -2
- package/dist/features/crm/index.js +6 -6
- package/dist/features/dashboard/index.d.ts +1 -1
- package/dist/features/dashboard/index.js +6 -6
- package/dist/features/delivery/index.d.ts +26 -0
- package/dist/features/delivery/index.js +5 -5
- package/dist/features/knowledge/index.js +4 -4
- package/dist/features/lead-gen/index.d.ts +3 -2
- package/dist/features/lead-gen/index.js +6 -6
- package/dist/features/monitoring/index.d.ts +33 -3
- package/dist/features/monitoring/index.js +7 -7
- package/dist/features/monitoring/requests/index.js +5 -5
- package/dist/features/operations/index.d.ts +2 -2
- package/dist/features/operations/index.js +9 -9
- package/dist/features/settings/index.d.ts +26 -0
- package/dist/features/settings/index.js +6 -6
- package/dist/hooks/access/index.js +4 -4
- package/dist/hooks/delivery/index.d.ts +26 -0
- package/dist/hooks/delivery/index.js +2 -2
- package/dist/hooks/index.d.ts +310 -14
- package/dist/hooks/index.js +4 -4
- package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +1 -1
- package/dist/hooks/published.d.ts +310 -14
- package/dist/hooks/published.js +4 -4
- package/dist/initialization/index.d.ts +26 -0
- package/dist/knowledge/index.d.ts +2 -2
- package/dist/knowledge/index.js +18 -18
- package/dist/{knowledge-search-index-LP2WVSQX.js → knowledge-search-index-RZLIVWPJ.js} +5 -5
- package/dist/layout/index.js +7 -7
- package/dist/profile/index.d.ts +26 -0
- package/dist/provider/index.d.ts +28 -2
- package/dist/provider/index.js +4 -4
- package/dist/provider/published.d.ts +28 -2
- package/dist/provider/published.js +4 -4
- package/dist/supabase/index.d.ts +50 -0
- package/dist/test-utils/index.js +3 -3
- package/dist/types/index.d.ts +60 -4
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- 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,
|
|
5
|
-
export { CONTENT_ITEMS, ContentSidebar, ContentSidebarMiddle, DEFAULT_CONTENT_VOCABULARY, MyReviewQueuePanel, contentManifest, deriveContentBoard, getContentItemIdentity, resolveContentStepResource, resolveContentVocabulary, useContentConfig } from '../../chunk-
|
|
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-
|
|
9
|
+
import '../../chunk-Z2W5VNN3.js';
|
|
10
10
|
import '../../chunk-L7BZZ4SI.js';
|
|
11
|
-
import { showSuccessNotification } from '../../chunk-
|
|
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-
|
|
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,
|
|
33
|
-
import { IconAlertTriangle, IconShieldCheck, IconShieldX, IconArticle, IconArrowRight, IconClock, IconSend, IconSearch, IconFileText, IconListDetails, IconAlertCircle, IconLayoutGrid, IconShare, IconPlayerPlay,
|
|
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
|
-
|
|
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.
|
|
794
|
-
{
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
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
|
-
|
|
841
|
-
|
|
842
|
-
|
|
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 ?
|
|
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
|
|
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({
|
|
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
|
|
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 = (
|
|
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
|
|
1575
|
-
function
|
|
1576
|
-
return typeof value === "string" &&
|
|
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
|
|
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 =
|
|
1661
|
+
const activeTab = isPipelineBoardTab(rawSearch.tab) ? rawSearch.tab : "board";
|
|
1586
1662
|
const handleTabChange = useCallback(
|
|
1587
1663
|
(value) => {
|
|
1588
|
-
if (!
|
|
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
|
|
1888
|
-
const
|
|
1889
|
-
|
|
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, {
|
|
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
|
-
|
|
2078
|
+
dist.platformUrl ? /* @__PURE__ */ jsx(
|
|
2079
|
+
Anchor,
|
|
2007
2080
|
{
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
style: {
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
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__ */
|
|
2056
|
-
|
|
2057
|
-
{
|
|
2058
|
-
|
|
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__ */
|
|
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 };
|