@burdenoff/microfe-theculturepost 2026.830.1 → 2026.1030.1
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/theculturepost/TheCulturePostRoutes.d.ts.map +1 -1
- package/dist/theculturepost/TheCulturePostRoutes.js +18 -14
- package/dist/theculturepost/TheCulturePostRoutes.js.map +1 -1
- package/dist/theculturepost/components/AddCitationDialog.d.ts +12 -2
- package/dist/theculturepost/components/AddCitationDialog.d.ts.map +1 -1
- package/dist/theculturepost/components/AddCitationDialog.js +114 -92
- package/dist/theculturepost/components/AddCitationDialog.js.map +1 -1
- package/dist/theculturepost/components/AddClaimDialog.d.ts +14 -0
- package/dist/theculturepost/components/AddClaimDialog.d.ts.map +1 -0
- package/dist/theculturepost/components/AddClaimDialog.js +108 -0
- package/dist/theculturepost/components/AddClaimDialog.js.map +1 -0
- package/dist/theculturepost/components/CitationList.d.ts +10 -1
- package/dist/theculturepost/components/CitationList.d.ts.map +1 -1
- package/dist/theculturepost/components/CitationList.js +89 -85
- package/dist/theculturepost/components/CitationList.js.map +1 -1
- package/dist/theculturepost/hooks/useTcpApi.d.ts +17 -1
- package/dist/theculturepost/hooks/useTcpApi.d.ts.map +1 -1
- package/dist/theculturepost/hooks/useTcpApi.js +117 -62
- package/dist/theculturepost/hooks/useTcpApi.js.map +1 -1
- package/dist/theculturepost/pages/stories/StoryCitationsPage.d.ts +19 -0
- package/dist/theculturepost/pages/stories/StoryCitationsPage.d.ts.map +1 -0
- package/dist/theculturepost/pages/stories/StoryCitationsPage.js +319 -0
- package/dist/theculturepost/pages/stories/StoryCitationsPage.js.map +1 -0
- package/dist/theculturepost/pages/stories/StoryDetailPage.d.ts.map +1 -1
- package/dist/theculturepost/pages/stories/StoryDetailPage.js +327 -271
- package/dist/theculturepost/pages/stories/StoryDetailPage.js.map +1 -1
- package/dist/theculturepost/types/index.d.ts +34 -0
- package/dist/theculturepost/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TheCulturePostRoutes.d.ts","sourceRoot":"","sources":["../../src/theculturepost/TheCulturePostRoutes.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAqC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"TheCulturePostRoutes.d.ts","sourceRoot":"","sources":["../../src/theculturepost/TheCulturePostRoutes.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAqC,MAAM,OAAO,CAAC;AAmGnE,eAAO,MAAM,oBAAoB,EAAE,EA6DlC,CAAC"}
|
|
@@ -37,17 +37,17 @@ function h(e, t) {
|
|
|
37
37
|
children: e
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
|
-
var g = i(() => import("./pages/stories/StoriesPage.js").then((e) => ({ default: e.StoriesPage }))), _ = i(() => import("./pages/stories/StoryDetailPage.js").then((e) => ({ default: e.StoryDetailPage }))), v = i(() => import("./pages/stories/SavedStoriesPage.js").then((e) => ({ default: e.SavedStoriesPage }))),
|
|
40
|
+
var g = i(() => import("./pages/stories/StoriesPage.js").then((e) => ({ default: e.StoriesPage }))), _ = i(() => import("./pages/stories/StoryDetailPage.js").then((e) => ({ default: e.StoryDetailPage }))), v = i(() => import("./pages/stories/StoryCitationsPage.js").then((e) => ({ default: e.StoryCitationsPage }))), y = i(() => import("./pages/stories/SavedStoriesPage.js").then((e) => ({ default: e.SavedStoriesPage }))), b = i(() => import("./pages/topics/TopicsPage.js").then((e) => ({ default: e.TopicsPage }))), x = i(() => import("./pages/topics/TopicDetailPage.js").then((e) => ({ default: e.TopicDetailPage }))), S = i(() => import("./pages/discussions/DiscussionsPage.js").then((e) => ({ default: e.DiscussionsPage }))), C = i(() => import("./pages/discussions/DiscussionDetailPage.js").then((e) => ({ default: e.DiscussionDetailPage }))), w = i(() => import("./pages/timeline/TimelinePage.js").then((e) => ({ default: e.TimelinePage }))), T = i(() => import("./pages/governance/GovernancePage.js").then((e) => ({ default: e.GovernancePage }))), E = i(() => import("./pages/archive/ArchivePage.js").then((e) => ({ default: e.ArchivePage }))), D = i(() => import("./pages/archive/CollectionDetailPage.js").then((e) => ({ default: e.CollectionDetailPage }))), O = i(() => import("./pages/archive/ArchiveItemDetailPage.js").then((e) => ({ default: e.ArchiveItemDetailPage }))), k = () => /* @__PURE__ */ u("div", {
|
|
41
41
|
className: "flex min-h-[400px] items-center justify-center",
|
|
42
42
|
children: /* @__PURE__ */ u(f, { size: "lg" })
|
|
43
|
-
}),
|
|
43
|
+
}), A = () => {
|
|
44
44
|
let { basePath: i, isStandalone: a } = e(), f = l();
|
|
45
45
|
t();
|
|
46
46
|
let m = i === "/" ? "" : (i ?? "").replace(/\/$/, "");
|
|
47
47
|
return m && !a && !(f.pathname === m || f.pathname.startsWith(m + "/")) ? null : /* @__PURE__ */ u("div", {
|
|
48
48
|
className: "flex min-h-full flex-col",
|
|
49
49
|
children: /* @__PURE__ */ u(r, {
|
|
50
|
-
fallback: /* @__PURE__ */ u(
|
|
50
|
+
fallback: /* @__PURE__ */ u(k, {}),
|
|
51
51
|
children: /* @__PURE__ */ d(c, { children: [
|
|
52
52
|
/* @__PURE__ */ u(s, {
|
|
53
53
|
index: !0,
|
|
@@ -55,7 +55,7 @@ var g = i(() => import("./pages/stories/StoriesPage.js").then((e) => ({ default:
|
|
|
55
55
|
}),
|
|
56
56
|
/* @__PURE__ */ u(s, {
|
|
57
57
|
path: "overview",
|
|
58
|
-
element: h(/* @__PURE__ */ u(
|
|
58
|
+
element: h(/* @__PURE__ */ u(T, {}), p.overview)
|
|
59
59
|
}),
|
|
60
60
|
/* @__PURE__ */ u(s, {
|
|
61
61
|
path: "stories",
|
|
@@ -65,41 +65,45 @@ var g = i(() => import("./pages/stories/StoriesPage.js").then((e) => ({ default:
|
|
|
65
65
|
path: "stories/:id",
|
|
66
66
|
element: h(/* @__PURE__ */ u(_, {}), p.stories)
|
|
67
67
|
}),
|
|
68
|
+
/* @__PURE__ */ u(s, {
|
|
69
|
+
path: "stories/:id/citations",
|
|
70
|
+
element: h(/* @__PURE__ */ u(v, {}), p.stories)
|
|
71
|
+
}),
|
|
68
72
|
/* @__PURE__ */ u(s, {
|
|
69
73
|
path: "saved",
|
|
70
|
-
element: h(/* @__PURE__ */ u(
|
|
74
|
+
element: h(/* @__PURE__ */ u(y, {}), p.saved)
|
|
71
75
|
}),
|
|
72
76
|
/* @__PURE__ */ u(s, {
|
|
73
77
|
path: "topics",
|
|
74
|
-
element: h(/* @__PURE__ */ u(
|
|
78
|
+
element: h(/* @__PURE__ */ u(b, {}), p.topics)
|
|
75
79
|
}),
|
|
76
80
|
/* @__PURE__ */ u(s, {
|
|
77
81
|
path: "topics/:id",
|
|
78
|
-
element: h(/* @__PURE__ */ u(
|
|
82
|
+
element: h(/* @__PURE__ */ u(x, {}), p.topics)
|
|
79
83
|
}),
|
|
80
84
|
/* @__PURE__ */ u(s, {
|
|
81
85
|
path: "timeline",
|
|
82
|
-
element: h(/* @__PURE__ */ u(
|
|
86
|
+
element: h(/* @__PURE__ */ u(w, {}), p.timeline)
|
|
83
87
|
}),
|
|
84
88
|
/* @__PURE__ */ u(s, {
|
|
85
89
|
path: "discussions",
|
|
86
|
-
element: h(/* @__PURE__ */ u(
|
|
90
|
+
element: h(/* @__PURE__ */ u(S, {}), p.discussions)
|
|
87
91
|
}),
|
|
88
92
|
/* @__PURE__ */ u(s, {
|
|
89
93
|
path: "discussions/:id",
|
|
90
|
-
element: h(/* @__PURE__ */ u(
|
|
94
|
+
element: h(/* @__PURE__ */ u(C, {}), p.discussions)
|
|
91
95
|
}),
|
|
92
96
|
/* @__PURE__ */ u(s, {
|
|
93
97
|
path: "archive",
|
|
94
|
-
element: h(/* @__PURE__ */ u(
|
|
98
|
+
element: h(/* @__PURE__ */ u(E, {}), p.archive)
|
|
95
99
|
}),
|
|
96
100
|
/* @__PURE__ */ u(s, {
|
|
97
101
|
path: "archive/collections/:id",
|
|
98
|
-
element: h(/* @__PURE__ */ u(
|
|
102
|
+
element: h(/* @__PURE__ */ u(D, {}), p.archive)
|
|
99
103
|
}),
|
|
100
104
|
/* @__PURE__ */ u(s, {
|
|
101
105
|
path: "archive/items/:id",
|
|
102
|
-
element: h(/* @__PURE__ */ u(
|
|
106
|
+
element: h(/* @__PURE__ */ u(O, {}), p.archive)
|
|
103
107
|
}),
|
|
104
108
|
/* @__PURE__ */ u(s, {
|
|
105
109
|
path: "*",
|
|
@@ -113,6 +117,6 @@ var g = i(() => import("./pages/stories/StoriesPage.js").then((e) => ({ default:
|
|
|
113
117
|
});
|
|
114
118
|
};
|
|
115
119
|
//#endregion
|
|
116
|
-
export {
|
|
120
|
+
export { A as TheCulturePostRoutes };
|
|
117
121
|
|
|
118
122
|
//# sourceMappingURL=TheCulturePostRoutes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TheCulturePostRoutes.js","names":[],"sources":["../../src/theculturepost/TheCulturePostRoutes.tsx"],"sourcesContent":["/**\n * TheCulturePost Routes\n * @module theculturepost\n *\n * Domain routes. The editorial home page is eager-loaded (primary landing); all\n * other pages are lazy-loaded. Every route maps to a real `tcp*` backend\n * capability.\n */\n\nimport { type FC, lazy, Suspense, type ReactElement } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useTheCulturePost } from './context/TheCulturePostContext';\nimport { usePageAnalytics } from './hooks/usePageAnalytics';\n\nconst FEATURE = {\n home: 'theculturepost.home',\n overview: 'theculturepost.overview',\n stories: 'theculturepost.stories',\n topics: 'theculturepost.topics',\n timeline: 'theculturepost.timeline',\n discussions: 'theculturepost.discussions',\n archive: 'theculturepost.archive',\n saved: 'theculturepost.saved',\n} as const;\n\nfunction FeatureDisabledFallback(): ReactElement {\n return (\n <div className=\"flex min-h-[400px] flex-col items-center justify-center gap-3 text-text-secondary\">\n <span className=\"text-lg font-semibold text-text-primary\">Feature unavailable</span>\n <span className=\"text-sm\">This page is disabled in your workspace.</span>\n </div>\n );\n}\n\nfunction gated(element: ReactElement, flag: string): ReactElement {\n return (\n <FeatureGate flag={flag} defaultValue fallback={<FeatureDisabledFallback />}>\n {element}\n </FeatureGate>\n );\n}\n\n// Eager — primary landing\nimport { HomePage } from './pages/HomePage';\n\n// Stories\nconst StoriesPage = lazy(() =>\n import('./pages/stories/StoriesPage').then((m) => ({ default: m.StoriesPage }))\n);\nconst StoryDetailPage = lazy(() =>\n import('./pages/stories/StoryDetailPage').then((m) => ({ default: m.StoryDetailPage }))\n);\nconst SavedStoriesPage = lazy(() =>\n import('./pages/stories/SavedStoriesPage').then((m) => ({ default: m.SavedStoriesPage }))\n);\n\n// Topics\nconst TopicsPage = lazy(() =>\n import('./pages/topics/TopicsPage').then((m) => ({ default: m.TopicsPage }))\n);\nconst TopicDetailPage = lazy(() =>\n import('./pages/topics/TopicDetailPage').then((m) => ({ default: m.TopicDetailPage }))\n);\n\n// Discussions\nconst DiscussionsPage = lazy(() =>\n import('./pages/discussions/DiscussionsPage').then((m) => ({ default: m.DiscussionsPage }))\n);\nconst DiscussionDetailPage = lazy(() =>\n import('./pages/discussions/DiscussionDetailPage').then((m) => ({\n default: m.DiscussionDetailPage,\n }))\n);\n\n// Timeline\nconst TimelinePage = lazy(() =>\n import('./pages/timeline/TimelinePage').then((m) => ({ default: m.TimelinePage }))\n);\n\n// Governance / Overview\nconst GovernancePage = lazy(() =>\n import('./pages/governance/GovernancePage').then((m) => ({ default: m.GovernancePage }))\n);\n\n// Archive\nconst ArchivePage = lazy(() =>\n import('./pages/archive/ArchivePage').then((m) => ({ default: m.ArchivePage }))\n);\nconst CollectionDetailPage = lazy(() =>\n import('./pages/archive/CollectionDetailPage').then((m) => ({ default: m.CollectionDetailPage }))\n);\nconst ArchiveItemDetailPage = lazy(() =>\n import('./pages/archive/ArchiveItemDetailPage').then((m) => ({\n default: m.ArchiveItemDetailPage,\n }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nexport const TheCulturePostRoutes: FC = () => {\n const { basePath, isStandalone } = useTheCulturePost();\n const location = useLocation();\n\n usePageAnalytics();\n\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n <Route index element={gated(<HomePage />, FEATURE.home)} />\n\n <Route path=\"overview\" element={gated(<GovernancePage />, FEATURE.overview)} />\n\n <Route path=\"stories\" element={gated(<StoriesPage />, FEATURE.stories)} />\n <Route path=\"stories/:id\" element={gated(<StoryDetailPage />, FEATURE.stories)} />\n\n <Route path=\"saved\" element={gated(<SavedStoriesPage />, FEATURE.saved)} />\n\n <Route path=\"topics\" element={gated(<TopicsPage />, FEATURE.topics)} />\n <Route path=\"topics/:id\" element={gated(<TopicDetailPage />, FEATURE.topics)} />\n\n <Route path=\"timeline\" element={gated(<TimelinePage />, FEATURE.timeline)} />\n\n <Route path=\"discussions\" element={gated(<DiscussionsPage />, FEATURE.discussions)} />\n <Route\n path=\"discussions/:id\"\n element={gated(<DiscussionDetailPage />, FEATURE.discussions)}\n />\n\n <Route path=\"archive\" element={gated(<ArchivePage />, FEATURE.archive)} />\n <Route\n path=\"archive/collections/:id\"\n element={gated(<CollectionDetailPage />, FEATURE.archive)}\n />\n <Route\n path=\"archive/items/:id\"\n element={gated(<ArchiveItemDetailPage />, FEATURE.archive)}\n />\n\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;AAgBA,IAAM,IAAU;CACd,MAAM;CACN,UAAU;CACV,SAAS;CACT,QAAQ;CACR,UAAU;CACV,aAAa;CACb,SAAS;CACT,OAAO;CACR;AAED,SAAS,IAAwC;AAC/C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,QAAD;GAAM,WAAU;aAA0C;GAA0B,CAAA,EACpF,kBAAC,QAAD;GAAM,WAAU;aAAU;GAA+C,CAAA,CACrE;;;AAIV,SAAS,EAAM,GAAuB,GAA4B;AAChE,QACE,kBAAC,GAAD;EAAmB;EAAM,cAAA;EAAa,UAAU,kBAAC,GAAD,EAA2B,CAAA;YACxE;EACW,CAAA;;AAQlB,IAAM,IAAc,QAClB,OAAO,kCAA+B,MAAM,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CAChF,EACK,IAAkB,QACtB,OAAO,sCAAmC,MAAM,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,CACxF,EACK,IAAmB,QACvB,OAAO,uCAAoC,MAAM,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAC1F,EAGK,IAAa,QACjB,OAAO,gCAA6B,MAAM,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,CAC7E,EACK,IAAkB,QACtB,OAAO,qCAAkC,MAAM,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,CACvF,EAGK,IAAkB,QACtB,OAAO,0CAAuC,MAAM,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAC5F,EACK,IAAuB,QAC3B,OAAO,+CAA4C,MAAM,OAAO,EAC9D,SAAS,EAAE,sBACZ,EAAE,CACJ,EAGK,IAAe,QACnB,OAAO,oCAAiC,MAAM,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CACnF,EAGK,IAAiB,QACrB,OAAO,wCAAqC,MAAM,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,CACzF,EAGK,IAAc,QAClB,OAAO,kCAA+B,MAAM,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CAChF,EACK,IAAuB,QAC3B,OAAO,2CAAwC,MAAM,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,CAClG,EACK,IAAwB,QAC5B,OAAO,4CAAyC,MAAM,OAAO,EAC3D,SAAS,EAAE,uBACZ,EAAE,CACJ,EAEK,UACJ,kBAAC,OAAD;CAAK,WAAU;WACb,kBAAC,GAAD,EAAS,MAAK,MAAO,CAAA;CACjB,CAAA,EAGK,UAAiC;CAC5C,IAAM,EAAE,aAAU,oBAAiB,GAAmB,EAChD,IAAW,GAAa;AAE9B,IAAkB;CAElB,IAAM,IAAqB,MAAa,MAAM,MAAM,KAAY,IAAI,QAAQ,OAAO,GAAG;AAYtF,QATI,KAAsB,CAAC,KAIrB,EAFF,EAAS,aAAa,KACtB,EAAS,SAAS,WAAW,IAAqB,IAAI,IAE/C,OAKT,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD;GAAU,UAAU,kBAAC,GAAD,EAAc,CAAA;aAChC,kBAAC,GAAD,EAAA,UAAA;IACE,kBAAC,GAAD;KAAO,OAAA;KAAM,SAAS,EAAM,kBAAC,GAAD,EAAY,CAAA,EAAE,EAAQ,KAAK;KAAI,CAAA;IAE3D,kBAAC,GAAD;KAAO,MAAK;KAAW,SAAS,EAAM,kBAAC,GAAD,EAAkB,CAAA,EAAE,EAAQ,SAAS;KAAI,CAAA;IAE/E,kBAAC,GAAD;KAAO,MAAK;KAAU,SAAS,EAAM,kBAAC,GAAD,EAAe,CAAA,EAAE,EAAQ,QAAQ;KAAI,CAAA;IAC1E,kBAAC,GAAD;KAAO,MAAK;KAAc,SAAS,EAAM,kBAAC,GAAD,EAAmB,CAAA,EAAE,EAAQ,QAAQ;KAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"TheCulturePostRoutes.js","names":[],"sources":["../../src/theculturepost/TheCulturePostRoutes.tsx"],"sourcesContent":["/**\n * TheCulturePost Routes\n * @module theculturepost\n *\n * Domain routes. The editorial home page is eager-loaded (primary landing); all\n * other pages are lazy-loaded. Every route maps to a real `tcp*` backend\n * capability.\n */\n\nimport { type FC, lazy, Suspense, type ReactElement } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useTheCulturePost } from './context/TheCulturePostContext';\nimport { usePageAnalytics } from './hooks/usePageAnalytics';\n\nconst FEATURE = {\n home: 'theculturepost.home',\n overview: 'theculturepost.overview',\n stories: 'theculturepost.stories',\n topics: 'theculturepost.topics',\n timeline: 'theculturepost.timeline',\n discussions: 'theculturepost.discussions',\n archive: 'theculturepost.archive',\n saved: 'theculturepost.saved',\n} as const;\n\nfunction FeatureDisabledFallback(): ReactElement {\n return (\n <div className=\"flex min-h-[400px] flex-col items-center justify-center gap-3 text-text-secondary\">\n <span className=\"text-lg font-semibold text-text-primary\">Feature unavailable</span>\n <span className=\"text-sm\">This page is disabled in your workspace.</span>\n </div>\n );\n}\n\nfunction gated(element: ReactElement, flag: string): ReactElement {\n return (\n <FeatureGate flag={flag} defaultValue fallback={<FeatureDisabledFallback />}>\n {element}\n </FeatureGate>\n );\n}\n\n// Eager — primary landing\nimport { HomePage } from './pages/HomePage';\n\n// Stories\nconst StoriesPage = lazy(() =>\n import('./pages/stories/StoriesPage').then((m) => ({ default: m.StoriesPage }))\n);\nconst StoryDetailPage = lazy(() =>\n import('./pages/stories/StoryDetailPage').then((m) => ({ default: m.StoryDetailPage }))\n);\nconst StoryCitationsPage = lazy(() =>\n import('./pages/stories/StoryCitationsPage').then((m) => ({ default: m.StoryCitationsPage }))\n);\nconst SavedStoriesPage = lazy(() =>\n import('./pages/stories/SavedStoriesPage').then((m) => ({ default: m.SavedStoriesPage }))\n);\n\n// Topics\nconst TopicsPage = lazy(() =>\n import('./pages/topics/TopicsPage').then((m) => ({ default: m.TopicsPage }))\n);\nconst TopicDetailPage = lazy(() =>\n import('./pages/topics/TopicDetailPage').then((m) => ({ default: m.TopicDetailPage }))\n);\n\n// Discussions\nconst DiscussionsPage = lazy(() =>\n import('./pages/discussions/DiscussionsPage').then((m) => ({ default: m.DiscussionsPage }))\n);\nconst DiscussionDetailPage = lazy(() =>\n import('./pages/discussions/DiscussionDetailPage').then((m) => ({\n default: m.DiscussionDetailPage,\n }))\n);\n\n// Timeline\nconst TimelinePage = lazy(() =>\n import('./pages/timeline/TimelinePage').then((m) => ({ default: m.TimelinePage }))\n);\n\n// Governance / Overview\nconst GovernancePage = lazy(() =>\n import('./pages/governance/GovernancePage').then((m) => ({ default: m.GovernancePage }))\n);\n\n// Archive\nconst ArchivePage = lazy(() =>\n import('./pages/archive/ArchivePage').then((m) => ({ default: m.ArchivePage }))\n);\nconst CollectionDetailPage = lazy(() =>\n import('./pages/archive/CollectionDetailPage').then((m) => ({ default: m.CollectionDetailPage }))\n);\nconst ArchiveItemDetailPage = lazy(() =>\n import('./pages/archive/ArchiveItemDetailPage').then((m) => ({\n default: m.ArchiveItemDetailPage,\n }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nexport const TheCulturePostRoutes: FC = () => {\n const { basePath, isStandalone } = useTheCulturePost();\n const location = useLocation();\n\n usePageAnalytics();\n\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n <Route index element={gated(<HomePage />, FEATURE.home)} />\n\n <Route path=\"overview\" element={gated(<GovernancePage />, FEATURE.overview)} />\n\n <Route path=\"stories\" element={gated(<StoriesPage />, FEATURE.stories)} />\n <Route path=\"stories/:id\" element={gated(<StoryDetailPage />, FEATURE.stories)} />\n <Route\n path=\"stories/:id/citations\"\n element={gated(<StoryCitationsPage />, FEATURE.stories)}\n />\n\n <Route path=\"saved\" element={gated(<SavedStoriesPage />, FEATURE.saved)} />\n\n <Route path=\"topics\" element={gated(<TopicsPage />, FEATURE.topics)} />\n <Route path=\"topics/:id\" element={gated(<TopicDetailPage />, FEATURE.topics)} />\n\n <Route path=\"timeline\" element={gated(<TimelinePage />, FEATURE.timeline)} />\n\n <Route path=\"discussions\" element={gated(<DiscussionsPage />, FEATURE.discussions)} />\n <Route\n path=\"discussions/:id\"\n element={gated(<DiscussionDetailPage />, FEATURE.discussions)}\n />\n\n <Route path=\"archive\" element={gated(<ArchivePage />, FEATURE.archive)} />\n <Route\n path=\"archive/collections/:id\"\n element={gated(<CollectionDetailPage />, FEATURE.archive)}\n />\n <Route\n path=\"archive/items/:id\"\n element={gated(<ArchiveItemDetailPage />, FEATURE.archive)}\n />\n\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
import { TcpCitation } from '../types';
|
|
1
|
+
import { TcpCitation, TcpStoryClaim } from '../types';
|
|
2
2
|
|
|
3
3
|
interface AddCitationDialogProps {
|
|
4
4
|
open: boolean;
|
|
5
5
|
onOpenChange: (open: boolean) => void;
|
|
6
6
|
storyId: string;
|
|
7
7
|
onCreated?: (citation: TcpCitation) => void;
|
|
8
|
+
/**
|
|
9
|
+
* The story's evidence-trail claims. When supplied, the dialog offers a
|
|
10
|
+
* "Supports claim" picker so the new source is linked as it is created.
|
|
11
|
+
*/
|
|
12
|
+
claims?: TcpStoryClaim[];
|
|
13
|
+
/**
|
|
14
|
+
* Claim preselected in the picker (e.g. "Add citation" on a claim row).
|
|
15
|
+
* Read on mount only — callers re-key the dialog when it changes.
|
|
16
|
+
*/
|
|
17
|
+
defaultClaimId?: string | null;
|
|
8
18
|
}
|
|
9
|
-
export declare function AddCitationDialog({ open, onOpenChange, storyId, onCreated, }: AddCitationDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare function AddCitationDialog({ open, onOpenChange, storyId, onCreated, claims, defaultClaimId, }: AddCitationDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
10
20
|
export {};
|
|
11
21
|
//# sourceMappingURL=AddCitationDialog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddCitationDialog.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/components/AddCitationDialog.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA0BH,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"AddCitationDialog.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/components/AddCitationDialog.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA0BH,OAAO,KAAK,EAAE,WAAW,EAAiB,aAAa,EAAE,MAAM,UAAU,CAAC;AAyB1E,UAAU,sBAAsB;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;IAC5C;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,SAAS,EACT,MAAM,EACN,cAAqB,GACtB,EAAE,sBAAsB,2CAyNxB"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { FILE_FOLDERS as e } from "../hooks/useFiles.js";
|
|
2
2
|
import { formatEnumLabel as t } from "../utils/formatters.js";
|
|
3
|
-
import { useTcpAddCitation as
|
|
4
|
-
import { describeError as
|
|
3
|
+
import { useTcpAddCitation as ee } from "../hooks/useTcpApi.js";
|
|
4
|
+
import { describeError as n, notify as r } from "../lib/toast.js";
|
|
5
5
|
import "../hooks/index.js";
|
|
6
|
-
import { FileUploadField as
|
|
7
|
-
import { sourceTypeIcon as
|
|
8
|
-
import { createElement as
|
|
9
|
-
import { ShieldCheck as
|
|
10
|
-
import { jsx as
|
|
11
|
-
import { Button as
|
|
6
|
+
import { FileUploadField as te } from "./FileUploadField.js";
|
|
7
|
+
import { sourceTypeIcon as ne } from "./CitationList.js";
|
|
8
|
+
import { createElement as i, useState as a } from "react";
|
|
9
|
+
import { ShieldCheck as o } from "lucide-react";
|
|
10
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
11
|
+
import { Button as l, Input as u, Label as d, ResponsiveDialog as re, ResponsiveDialogContent as f, ResponsiveDialogDescription as p, ResponsiveDialogFooter as m, ResponsiveDialogHeader as ie, ResponsiveDialogTitle as h, Select as g, SelectContent as _, SelectItem as v, SelectTrigger as y, SelectValue as b, Textarea as x } from "@burdenoff/fe-libs/ui";
|
|
12
12
|
//#region src/theculturepost/components/AddCitationDialog.tsx
|
|
13
|
-
var
|
|
13
|
+
var S = "__none__", ae = [
|
|
14
14
|
"WEB",
|
|
15
15
|
"BOOK",
|
|
16
16
|
"ACADEMIC",
|
|
@@ -19,155 +19,176 @@ var D = [
|
|
|
19
19
|
"PRIMARY_DOCUMENT",
|
|
20
20
|
"ARCHIVAL_RECORD",
|
|
21
21
|
"ARTIFACT"
|
|
22
|
-
],
|
|
22
|
+
], C = (e, t) => e.length > t ? `${e.slice(0, t - 1)}…` : e, w = (e) => {
|
|
23
23
|
if (!e) return null;
|
|
24
24
|
let t = new Date(e);
|
|
25
25
|
return Number.isNaN(t.getTime()) ? null : t.toISOString();
|
|
26
26
|
};
|
|
27
|
-
function
|
|
28
|
-
let N =
|
|
29
|
-
F(""), L(""), z(""), V(""), U(""), G(""), q(""), Y(
|
|
27
|
+
function T({ open: T, onOpenChange: E, storyId: D, onCreated: O, claims: k, defaultClaimId: A = null }) {
|
|
28
|
+
let j = ee(), [M, N] = a(""), [P, F] = a(""), [I, L] = a(""), [R, z] = a(""), [B, V] = a(""), [H, U] = a(""), [W, G] = a(""), [K, q] = a("WEB"), [J, Y] = a(null), [X, Z] = a(A ?? S), [Q, $] = a(null), oe = () => {
|
|
29
|
+
N(""), F(""), L(""), z(""), V(""), U(""), G(""), q("WEB"), Y(null), Z(A ?? S), $(null);
|
|
30
30
|
};
|
|
31
|
-
return /* @__PURE__ */
|
|
32
|
-
open:
|
|
33
|
-
onOpenChange:
|
|
34
|
-
children: /* @__PURE__ */
|
|
31
|
+
return /* @__PURE__ */ s(re, {
|
|
32
|
+
open: T,
|
|
33
|
+
onOpenChange: E,
|
|
34
|
+
children: /* @__PURE__ */ c(f, {
|
|
35
35
|
className: "sm:max-w-lg",
|
|
36
36
|
children: [
|
|
37
|
-
/* @__PURE__ */
|
|
38
|
-
/* @__PURE__ */
|
|
37
|
+
/* @__PURE__ */ c(ie, { children: [/* @__PURE__ */ s(h, { children: "Add a citation" }), /* @__PURE__ */ s(p, { children: "Ground this story in the record with a verifiable source." })] }),
|
|
38
|
+
/* @__PURE__ */ c("div", {
|
|
39
39
|
className: "flex max-h-[62vh] flex-col gap-5 overflow-y-auto py-2",
|
|
40
40
|
children: [
|
|
41
|
-
/* @__PURE__ */
|
|
41
|
+
/* @__PURE__ */ c("div", {
|
|
42
42
|
className: "grid gap-1.5",
|
|
43
|
-
children: [/* @__PURE__ */ d
|
|
43
|
+
children: [/* @__PURE__ */ c(d, {
|
|
44
44
|
htmlFor: "cite-title",
|
|
45
|
-
children: ["Title ", /* @__PURE__ */
|
|
45
|
+
children: ["Title ", /* @__PURE__ */ s("span", {
|
|
46
46
|
className: "text-status-error-text",
|
|
47
47
|
children: "*"
|
|
48
48
|
})]
|
|
49
|
-
}), /* @__PURE__ */ u
|
|
49
|
+
}), /* @__PURE__ */ s(u, {
|
|
50
50
|
id: "cite-title",
|
|
51
|
-
value:
|
|
52
|
-
onChange: (e) =>
|
|
51
|
+
value: M,
|
|
52
|
+
onChange: (e) => N(e.target.value),
|
|
53
53
|
placeholder: "e.g. The Penguin History of Early India"
|
|
54
54
|
})]
|
|
55
55
|
}),
|
|
56
|
-
/* @__PURE__ */
|
|
56
|
+
/* @__PURE__ */ c("div", {
|
|
57
57
|
className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
|
|
58
|
-
children: [/* @__PURE__ */
|
|
58
|
+
children: [/* @__PURE__ */ c("div", {
|
|
59
59
|
className: "grid gap-1.5",
|
|
60
|
-
children: [/* @__PURE__ */
|
|
61
|
-
value:
|
|
62
|
-
onValueChange: (e) =>
|
|
63
|
-
children: [/* @__PURE__ */
|
|
60
|
+
children: [/* @__PURE__ */ s(d, { children: "Source type" }), /* @__PURE__ */ c(g, {
|
|
61
|
+
value: K,
|
|
62
|
+
onValueChange: (e) => q(e),
|
|
63
|
+
children: [/* @__PURE__ */ s(y, { children: /* @__PURE__ */ s(b, {}) }), /* @__PURE__ */ s(_, { children: ae.map((e) => /* @__PURE__ */ s(v, {
|
|
64
64
|
value: e,
|
|
65
|
-
children: /* @__PURE__ */
|
|
65
|
+
children: /* @__PURE__ */ c("span", {
|
|
66
66
|
className: "inline-flex items-center gap-2",
|
|
67
|
-
children: [
|
|
67
|
+
children: [i(ne(e), { className: "h-3.5 w-3.5 text-text-tertiary" }), t(e)]
|
|
68
68
|
})
|
|
69
69
|
}, e)) })]
|
|
70
70
|
})]
|
|
71
|
-
}), /* @__PURE__ */
|
|
71
|
+
}), /* @__PURE__ */ c("div", {
|
|
72
72
|
className: "grid gap-1.5",
|
|
73
|
-
children: [/* @__PURE__ */
|
|
73
|
+
children: [/* @__PURE__ */ s(d, {
|
|
74
74
|
htmlFor: "cite-published",
|
|
75
75
|
children: "Published on"
|
|
76
|
-
}), /* @__PURE__ */ u
|
|
76
|
+
}), /* @__PURE__ */ s(u, {
|
|
77
77
|
id: "cite-published",
|
|
78
78
|
type: "date",
|
|
79
|
-
value:
|
|
80
|
-
onChange: (e) =>
|
|
79
|
+
value: R,
|
|
80
|
+
onChange: (e) => z(e.target.value)
|
|
81
81
|
})]
|
|
82
82
|
})]
|
|
83
83
|
}),
|
|
84
|
-
/* @__PURE__ */
|
|
84
|
+
/* @__PURE__ */ c("div", {
|
|
85
85
|
className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
|
|
86
|
-
children: [/* @__PURE__ */
|
|
86
|
+
children: [/* @__PURE__ */ c("div", {
|
|
87
87
|
className: "grid gap-1.5",
|
|
88
|
-
children: [/* @__PURE__ */
|
|
88
|
+
children: [/* @__PURE__ */ s(d, {
|
|
89
89
|
htmlFor: "cite-author",
|
|
90
90
|
children: "Author"
|
|
91
|
-
}), /* @__PURE__ */ u
|
|
91
|
+
}), /* @__PURE__ */ s(u, {
|
|
92
92
|
id: "cite-author",
|
|
93
|
-
value:
|
|
94
|
-
onChange: (e) =>
|
|
93
|
+
value: P,
|
|
94
|
+
onChange: (e) => F(e.target.value),
|
|
95
95
|
placeholder: "e.g. Romila Thapar"
|
|
96
96
|
})]
|
|
97
|
-
}), /* @__PURE__ */
|
|
97
|
+
}), /* @__PURE__ */ c("div", {
|
|
98
98
|
className: "grid gap-1.5",
|
|
99
|
-
children: [/* @__PURE__ */
|
|
99
|
+
children: [/* @__PURE__ */ s(d, {
|
|
100
100
|
htmlFor: "cite-publisher",
|
|
101
101
|
children: "Publisher"
|
|
102
|
-
}), /* @__PURE__ */ u
|
|
102
|
+
}), /* @__PURE__ */ s(u, {
|
|
103
103
|
id: "cite-publisher",
|
|
104
|
-
value:
|
|
105
|
-
onChange: (e) =>
|
|
104
|
+
value: I,
|
|
105
|
+
onChange: (e) => L(e.target.value),
|
|
106
106
|
placeholder: "e.g. Penguin Books"
|
|
107
107
|
})]
|
|
108
108
|
})]
|
|
109
109
|
}),
|
|
110
|
-
/* @__PURE__ */
|
|
110
|
+
/* @__PURE__ */ c("div", {
|
|
111
111
|
className: "grid gap-1.5",
|
|
112
|
-
children: [/* @__PURE__ */
|
|
112
|
+
children: [/* @__PURE__ */ s(d, {
|
|
113
113
|
htmlFor: "cite-url",
|
|
114
114
|
children: "URL"
|
|
115
|
-
}), /* @__PURE__ */ u
|
|
115
|
+
}), /* @__PURE__ */ s(u, {
|
|
116
116
|
id: "cite-url",
|
|
117
117
|
type: "url",
|
|
118
118
|
inputMode: "url",
|
|
119
|
-
value:
|
|
120
|
-
onChange: (e) =>
|
|
119
|
+
value: B,
|
|
120
|
+
onChange: (e) => V(e.target.value),
|
|
121
121
|
placeholder: "https://…"
|
|
122
122
|
})]
|
|
123
123
|
}),
|
|
124
|
-
/* @__PURE__ */
|
|
124
|
+
k && k.length > 0 && /* @__PURE__ */ c("div", {
|
|
125
125
|
className: "grid gap-1.5",
|
|
126
|
-
children: [/* @__PURE__ */
|
|
126
|
+
children: [/* @__PURE__ */ s(d, { children: "Supports claim" }), /* @__PURE__ */ c(g, {
|
|
127
|
+
value: X,
|
|
128
|
+
onValueChange: Z,
|
|
129
|
+
children: [/* @__PURE__ */ s(y, {
|
|
130
|
+
"aria-label": "Supports claim",
|
|
131
|
+
children: /* @__PURE__ */ s(b, {})
|
|
132
|
+
}), /* @__PURE__ */ c(_, { children: [/* @__PURE__ */ s(v, {
|
|
133
|
+
value: S,
|
|
134
|
+
children: "General source (no specific claim)"
|
|
135
|
+
}), k.map((e) => /* @__PURE__ */ c(v, {
|
|
136
|
+
value: e.id,
|
|
137
|
+
children: [
|
|
138
|
+
e.position,
|
|
139
|
+
". ",
|
|
140
|
+
C(e.text, 70)
|
|
141
|
+
]
|
|
142
|
+
}, e.id))] })]
|
|
143
|
+
})]
|
|
144
|
+
}),
|
|
145
|
+
/* @__PURE__ */ c("div", {
|
|
146
|
+
className: "grid gap-1.5",
|
|
147
|
+
children: [/* @__PURE__ */ s(d, {
|
|
127
148
|
htmlFor: "cite-excerpt",
|
|
128
149
|
children: "Excerpt"
|
|
129
|
-
}), /* @__PURE__ */
|
|
150
|
+
}), /* @__PURE__ */ s(x, {
|
|
130
151
|
id: "cite-excerpt",
|
|
131
|
-
value:
|
|
132
|
-
onChange: (e) =>
|
|
152
|
+
value: H,
|
|
153
|
+
onChange: (e) => U(e.target.value),
|
|
133
154
|
placeholder: "A short quoted passage that supports the story.",
|
|
134
155
|
rows: 2
|
|
135
156
|
})]
|
|
136
157
|
}),
|
|
137
|
-
/* @__PURE__ */
|
|
158
|
+
/* @__PURE__ */ c("div", {
|
|
138
159
|
className: "grid gap-1.5",
|
|
139
|
-
children: [/* @__PURE__ */
|
|
160
|
+
children: [/* @__PURE__ */ s(d, {
|
|
140
161
|
htmlFor: "cite-provenance",
|
|
141
162
|
children: "Provenance"
|
|
142
|
-
}), /* @__PURE__ */
|
|
163
|
+
}), /* @__PURE__ */ s(x, {
|
|
143
164
|
id: "cite-provenance",
|
|
144
|
-
value:
|
|
145
|
-
onChange: (e) =>
|
|
165
|
+
value: W,
|
|
166
|
+
onChange: (e) => G(e.target.value),
|
|
146
167
|
placeholder: "Where the source is held, reference numbers, chain of custody…",
|
|
147
168
|
rows: 2
|
|
148
169
|
})]
|
|
149
170
|
}),
|
|
150
|
-
/* @__PURE__ */
|
|
171
|
+
/* @__PURE__ */ c("div", {
|
|
151
172
|
className: "grid gap-1.5",
|
|
152
|
-
children: [/* @__PURE__ */
|
|
173
|
+
children: [/* @__PURE__ */ s(d, { children: "Source scan" }), /* @__PURE__ */ s(te, {
|
|
153
174
|
folder: e.artifacts,
|
|
154
175
|
accept: "image/*,application/pdf",
|
|
155
176
|
label: "Upload source scan",
|
|
156
177
|
hint: "A scan of the primary source (optional).",
|
|
157
|
-
fileId:
|
|
158
|
-
onUploaded:
|
|
159
|
-
onCleared: () =>
|
|
178
|
+
fileId: J,
|
|
179
|
+
onUploaded: Y,
|
|
180
|
+
onCleared: () => Y(null)
|
|
160
181
|
})]
|
|
161
182
|
}),
|
|
162
|
-
/* @__PURE__ */
|
|
183
|
+
/* @__PURE__ */ c("p", {
|
|
163
184
|
className: "flex items-start gap-2 rounded-lg bg-bg-sunken/60 px-3 py-2 text-xs text-text-tertiary",
|
|
164
185
|
children: [
|
|
165
|
-
/* @__PURE__ */
|
|
186
|
+
/* @__PURE__ */ s(o, {
|
|
166
187
|
className: "mt-0.5 h-3.5 w-3.5 shrink-0",
|
|
167
188
|
"aria-hidden": "true"
|
|
168
189
|
}),
|
|
169
190
|
"New sources start as ",
|
|
170
|
-
/* @__PURE__ */
|
|
191
|
+
/* @__PURE__ */ s("span", {
|
|
171
192
|
className: "font-medium text-text-secondary",
|
|
172
193
|
children: "Unverified"
|
|
173
194
|
}),
|
|
@@ -175,41 +196,42 @@ function k({ open: k, onOpenChange: A, storyId: j, onCreated: M }) {
|
|
|
175
196
|
"and are reviewed for accuracy, relevance, and cultural sensitivity before verification."
|
|
176
197
|
]
|
|
177
198
|
}),
|
|
178
|
-
Q && /* @__PURE__ */
|
|
199
|
+
Q && /* @__PURE__ */ s("p", {
|
|
179
200
|
className: "text-sm text-status-error-text",
|
|
180
201
|
children: Q
|
|
181
202
|
})
|
|
182
203
|
]
|
|
183
204
|
}),
|
|
184
|
-
/* @__PURE__ */
|
|
205
|
+
/* @__PURE__ */ c(m, { children: [/* @__PURE__ */ s(l, {
|
|
185
206
|
variant: "outline",
|
|
186
|
-
onClick: () =>
|
|
207
|
+
onClick: () => E(!1),
|
|
187
208
|
children: "Cancel"
|
|
188
|
-
}), /* @__PURE__ */
|
|
209
|
+
}), /* @__PURE__ */ s(l, {
|
|
189
210
|
onClick: async () => {
|
|
190
|
-
if (!
|
|
211
|
+
if (!M.trim()) {
|
|
191
212
|
$("A citation title is required.");
|
|
192
213
|
return;
|
|
193
214
|
}
|
|
194
215
|
try {
|
|
195
|
-
let e = await
|
|
196
|
-
storyId:
|
|
197
|
-
title:
|
|
198
|
-
author:
|
|
199
|
-
publisher:
|
|
200
|
-
publishedOn:
|
|
201
|
-
url:
|
|
202
|
-
excerpt:
|
|
203
|
-
provenance:
|
|
204
|
-
sourceType:
|
|
205
|
-
sourceFileId:
|
|
216
|
+
let e = await j.mutateAsync({
|
|
217
|
+
storyId: D,
|
|
218
|
+
title: M.trim(),
|
|
219
|
+
author: P.trim() || null,
|
|
220
|
+
publisher: I.trim() || null,
|
|
221
|
+
publishedOn: w(R),
|
|
222
|
+
url: B.trim() || null,
|
|
223
|
+
excerpt: H.trim() || null,
|
|
224
|
+
provenance: W.trim() || null,
|
|
225
|
+
sourceType: K,
|
|
226
|
+
sourceFileId: J,
|
|
227
|
+
...X === S ? {} : { claimId: X }
|
|
206
228
|
});
|
|
207
|
-
|
|
229
|
+
r.success("Citation added", e.title), E(!1), oe(), O?.(e);
|
|
208
230
|
} catch (e) {
|
|
209
|
-
$(
|
|
231
|
+
$(n(e));
|
|
210
232
|
}
|
|
211
233
|
},
|
|
212
|
-
disabled:
|
|
234
|
+
disabled: j.isPending,
|
|
213
235
|
children: "Add citation"
|
|
214
236
|
})] })
|
|
215
237
|
]
|
|
@@ -217,6 +239,6 @@ function k({ open: k, onOpenChange: A, storyId: j, onCreated: M }) {
|
|
|
217
239
|
});
|
|
218
240
|
}
|
|
219
241
|
//#endregion
|
|
220
|
-
export {
|
|
242
|
+
export { T as AddCitationDialog };
|
|
221
243
|
|
|
222
244
|
//# sourceMappingURL=AddCitationDialog.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddCitationDialog.js","names":[],"sources":["../../../src/theculturepost/components/AddCitationDialog.tsx"],"sourcesContent":["/**\n * AddCitationDialog — attach a verifiable source to a story.\n * @module theculturepost/components\n *\n * Writes `tcpAddCitation`. An optional source scan is uploaded to\n * wspace-files-svc (only the id is stored).\n */\n\nimport { createElement, useState } from 'react';\nimport { ShieldCheck } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { FileUploadField } from './FileUploadField';\nimport { sourceTypeIcon } from './CitationList';\nimport { useTcpAddCitation, FILE_FOLDERS } from '../hooks';\nimport { formatEnumLabel } from '../utils/formatters';\nimport { notify, describeError } from '../lib/toast';\nimport type { TcpCitation, TcpSourceType } from '../types';\n\nconst SOURCE_TYPES: TcpSourceType[] = [\n 'WEB',\n 'BOOK',\n 'ACADEMIC',\n 'PERIODICAL',\n 'INTERVIEW',\n 'PRIMARY_DOCUMENT',\n 'ARCHIVAL_RECORD',\n 'ARTIFACT',\n];\n\nconst dateToIso = (value: string): string | null => {\n if (!value) return null;\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d.toISOString();\n};\n\ninterface AddCitationDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n storyId: string;\n onCreated?: (citation: TcpCitation) => void;\n}\n\nexport function AddCitationDialog({\n open,\n onOpenChange,\n storyId,\n onCreated,\n}: AddCitationDialogProps) {\n const addCitation = useTcpAddCitation();\n const [title, setTitle] = useState('');\n const [author, setAuthor] = useState('');\n const [publisher, setPublisher] = useState('');\n const [publishedOn, setPublishedOn] = useState('');\n const [url, setUrl] = useState('');\n const [excerpt, setExcerpt] = useState('');\n const [provenance, setProvenance] = useState('');\n const [sourceType, setSourceType] = useState<TcpSourceType>('WEB');\n const [sourceFileId, setSourceFileId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const reset = () => {\n setTitle('');\n setAuthor('');\n setPublisher('');\n setPublishedOn('');\n setUrl('');\n setExcerpt('');\n setProvenance('');\n setSourceType('WEB');\n setSourceFileId(null);\n setError(null);\n };\n\n const submit = async () => {\n if (!title.trim()) {\n setError('A citation title is required.');\n return;\n }\n try {\n const created = await addCitation.mutateAsync({\n storyId,\n title: title.trim(),\n author: author.trim() || null,\n publisher: publisher.trim() || null,\n publishedOn: dateToIso(publishedOn),\n url: url.trim() || null,\n excerpt: excerpt.trim() || null,\n provenance: provenance.trim() || null,\n sourceType,\n sourceFileId,\n });\n notify.success('Citation added', created.title);\n onOpenChange(false);\n reset();\n onCreated?.(created);\n } catch (err) {\n setError(describeError(err));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add a citation</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Ground this story in the record with a verifiable source.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex max-h-[62vh] flex-col gap-5 overflow-y-auto py-2\">\n {/* Source identity */}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-title\">\n Title <span className=\"text-status-error-text\">*</span>\n </Label>\n <Input\n id=\"cite-title\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. The Penguin History of Early India\"\n />\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label>Source type</Label>\n <Select value={sourceType} onValueChange={(v) => setSourceType(v as TcpSourceType)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SOURCE_TYPES.map((s) => (\n <SelectItem key={s} value={s}>\n <span className=\"inline-flex items-center gap-2\">\n {createElement(sourceTypeIcon(s), {\n className: 'h-3.5 w-3.5 text-text-tertiary',\n })}\n {formatEnumLabel(s)}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-published\">Published on</Label>\n <Input\n id=\"cite-published\"\n type=\"date\"\n value={publishedOn}\n onChange={(e) => setPublishedOn(e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-author\">Author</Label>\n <Input\n id=\"cite-author\"\n value={author}\n onChange={(e) => setAuthor(e.target.value)}\n placeholder=\"e.g. Romila Thapar\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-publisher\">Publisher</Label>\n <Input\n id=\"cite-publisher\"\n value={publisher}\n onChange={(e) => setPublisher(e.target.value)}\n placeholder=\"e.g. Penguin Books\"\n />\n </div>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-url\">URL</Label>\n <Input\n id=\"cite-url\"\n type=\"url\"\n inputMode=\"url\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://…\"\n />\n </div>\n\n {/* Grounding detail */}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-excerpt\">Excerpt</Label>\n <Textarea\n id=\"cite-excerpt\"\n value={excerpt}\n onChange={(e) => setExcerpt(e.target.value)}\n placeholder=\"A short quoted passage that supports the story.\"\n rows={2}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-provenance\">Provenance</Label>\n <Textarea\n id=\"cite-provenance\"\n value={provenance}\n onChange={(e) => setProvenance(e.target.value)}\n placeholder=\"Where the source is held, reference numbers, chain of custody…\"\n rows={2}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label>Source scan</Label>\n <FileUploadField\n folder={FILE_FOLDERS.artifacts}\n accept=\"image/*,application/pdf\"\n label=\"Upload source scan\"\n hint=\"A scan of the primary source (optional).\"\n fileId={sourceFileId}\n onUploaded={setSourceFileId}\n onCleared={() => setSourceFileId(null)}\n />\n </div>\n\n <p className=\"flex items-start gap-2 rounded-lg bg-bg-sunken/60 px-3 py-2 text-xs text-text-tertiary\">\n <ShieldCheck className=\"mt-0.5 h-3.5 w-3.5 shrink-0\" aria-hidden=\"true\" />\n New sources start as <span className=\"font-medium text-text-secondary\">\n Unverified\n </span>{' '}\n and are reviewed for accuracy, relevance, and cultural sensitivity before verification.\n </p>\n\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={addCitation.isPending}>\n Add citation\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AddCitationDialog.js","names":[],"sources":["../../../src/theculturepost/components/AddCitationDialog.tsx"],"sourcesContent":["/**\n * AddCitationDialog — attach a verifiable source to a story.\n * @module theculturepost/components\n *\n * Writes `tcpAddCitation`. An optional source scan is uploaded to\n * wspace-files-svc (only the id is stored).\n */\n\nimport { createElement, useState } from 'react';\nimport { ShieldCheck } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { FileUploadField } from './FileUploadField';\nimport { sourceTypeIcon } from './CitationList';\nimport { useTcpAddCitation, FILE_FOLDERS } from '../hooks';\nimport { formatEnumLabel } from '../utils/formatters';\nimport { notify, describeError } from '../lib/toast';\nimport type { TcpCitation, TcpSourceType, TcpStoryClaim } from '../types';\n\n/** Sentinel Select value for \"not tied to a specific claim\". */\nconst NO_CLAIM = '__none__';\n\nconst SOURCE_TYPES: TcpSourceType[] = [\n 'WEB',\n 'BOOK',\n 'ACADEMIC',\n 'PERIODICAL',\n 'INTERVIEW',\n 'PRIMARY_DOCUMENT',\n 'ARCHIVAL_RECORD',\n 'ARTIFACT',\n];\n\nconst truncate = (text: string, max: number): string =>\n text.length > max ? `${text.slice(0, max - 1)}…` : text;\n\nconst dateToIso = (value: string): string | null => {\n if (!value) return null;\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d.toISOString();\n};\n\ninterface AddCitationDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n storyId: string;\n onCreated?: (citation: TcpCitation) => void;\n /**\n * The story's evidence-trail claims. When supplied, the dialog offers a\n * \"Supports claim\" picker so the new source is linked as it is created.\n */\n claims?: TcpStoryClaim[];\n /**\n * Claim preselected in the picker (e.g. \"Add citation\" on a claim row).\n * Read on mount only — callers re-key the dialog when it changes.\n */\n defaultClaimId?: string | null;\n}\n\nexport function AddCitationDialog({\n open,\n onOpenChange,\n storyId,\n onCreated,\n claims,\n defaultClaimId = null,\n}: AddCitationDialogProps) {\n const addCitation = useTcpAddCitation();\n const [title, setTitle] = useState('');\n const [author, setAuthor] = useState('');\n const [publisher, setPublisher] = useState('');\n const [publishedOn, setPublishedOn] = useState('');\n const [url, setUrl] = useState('');\n const [excerpt, setExcerpt] = useState('');\n const [provenance, setProvenance] = useState('');\n const [sourceType, setSourceType] = useState<TcpSourceType>('WEB');\n const [sourceFileId, setSourceFileId] = useState<string | null>(null);\n const [claimId, setClaimId] = useState<string>(defaultClaimId ?? NO_CLAIM);\n const [error, setError] = useState<string | null>(null);\n\n const reset = () => {\n setTitle('');\n setAuthor('');\n setPublisher('');\n setPublishedOn('');\n setUrl('');\n setExcerpt('');\n setProvenance('');\n setSourceType('WEB');\n setSourceFileId(null);\n setClaimId(defaultClaimId ?? NO_CLAIM);\n setError(null);\n };\n\n const submit = async () => {\n if (!title.trim()) {\n setError('A citation title is required.');\n return;\n }\n try {\n const created = await addCitation.mutateAsync({\n storyId,\n title: title.trim(),\n author: author.trim() || null,\n publisher: publisher.trim() || null,\n publishedOn: dateToIso(publishedOn),\n url: url.trim() || null,\n excerpt: excerpt.trim() || null,\n provenance: provenance.trim() || null,\n sourceType,\n sourceFileId,\n ...(claimId !== NO_CLAIM ? { claimId } : {}),\n });\n notify.success('Citation added', created.title);\n onOpenChange(false);\n reset();\n onCreated?.(created);\n } catch (err) {\n setError(describeError(err));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add a citation</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Ground this story in the record with a verifiable source.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex max-h-[62vh] flex-col gap-5 overflow-y-auto py-2\">\n {/* Source identity */}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-title\">\n Title <span className=\"text-status-error-text\">*</span>\n </Label>\n <Input\n id=\"cite-title\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. The Penguin History of Early India\"\n />\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label>Source type</Label>\n <Select value={sourceType} onValueChange={(v) => setSourceType(v as TcpSourceType)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SOURCE_TYPES.map((s) => (\n <SelectItem key={s} value={s}>\n <span className=\"inline-flex items-center gap-2\">\n {createElement(sourceTypeIcon(s), {\n className: 'h-3.5 w-3.5 text-text-tertiary',\n })}\n {formatEnumLabel(s)}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-published\">Published on</Label>\n <Input\n id=\"cite-published\"\n type=\"date\"\n value={publishedOn}\n onChange={(e) => setPublishedOn(e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-author\">Author</Label>\n <Input\n id=\"cite-author\"\n value={author}\n onChange={(e) => setAuthor(e.target.value)}\n placeholder=\"e.g. Romila Thapar\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-publisher\">Publisher</Label>\n <Input\n id=\"cite-publisher\"\n value={publisher}\n onChange={(e) => setPublisher(e.target.value)}\n placeholder=\"e.g. Penguin Books\"\n />\n </div>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-url\">URL</Label>\n <Input\n id=\"cite-url\"\n type=\"url\"\n inputMode=\"url\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://…\"\n />\n </div>\n\n {claims && claims.length > 0 && (\n <div className=\"grid gap-1.5\">\n <Label>Supports claim</Label>\n <Select value={claimId} onValueChange={setClaimId}>\n <SelectTrigger aria-label=\"Supports claim\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NO_CLAIM}>General source (no specific claim)</SelectItem>\n {claims.map((claim) => (\n <SelectItem key={claim.id} value={claim.id}>\n {claim.position}. {truncate(claim.text, 70)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n\n {/* Grounding detail */}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-excerpt\">Excerpt</Label>\n <Textarea\n id=\"cite-excerpt\"\n value={excerpt}\n onChange={(e) => setExcerpt(e.target.value)}\n placeholder=\"A short quoted passage that supports the story.\"\n rows={2}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-provenance\">Provenance</Label>\n <Textarea\n id=\"cite-provenance\"\n value={provenance}\n onChange={(e) => setProvenance(e.target.value)}\n placeholder=\"Where the source is held, reference numbers, chain of custody…\"\n rows={2}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label>Source scan</Label>\n <FileUploadField\n folder={FILE_FOLDERS.artifacts}\n accept=\"image/*,application/pdf\"\n label=\"Upload source scan\"\n hint=\"A scan of the primary source (optional).\"\n fileId={sourceFileId}\n onUploaded={setSourceFileId}\n onCleared={() => setSourceFileId(null)}\n />\n </div>\n\n <p className=\"flex items-start gap-2 rounded-lg bg-bg-sunken/60 px-3 py-2 text-xs text-text-tertiary\">\n <ShieldCheck className=\"mt-0.5 h-3.5 w-3.5 shrink-0\" aria-hidden=\"true\" />\n New sources start as <span className=\"font-medium text-text-secondary\">\n Unverified\n </span>{' '}\n and are reviewed for accuracy, relevance, and cultural sensitivity before verification.\n </p>\n\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={addCitation.isPending}>\n Add citation\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TcpStoryClaim } from '../types';
|
|
2
|
+
|
|
3
|
+
/** Split a story body into its sentences (trimmed, de-duplicated, bounded). */
|
|
4
|
+
export declare function bodySentences(body: string | null | undefined): string[];
|
|
5
|
+
interface AddClaimDialogProps {
|
|
6
|
+
open: boolean;
|
|
7
|
+
onOpenChange: (open: boolean) => void;
|
|
8
|
+
storyId: string;
|
|
9
|
+
storyBody?: string | null;
|
|
10
|
+
onCreated?: (claim: TcpStoryClaim) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function AddClaimDialog({ open, onOpenChange, storyId, storyBody, onCreated, }: AddClaimDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=AddClaimDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddClaimDialog.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/components/AddClaimDialog.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAsBH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAM9C,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAWvE;AAKD,UAAU,mBAAmB;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC5C;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,SAAS,EACT,SAAS,GACV,EAAE,mBAAmB,2CAgGrB"}
|