@anthusai/papyrus 2.0.0-next.1 → 2.0.0-next.100
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/amplify/auth/resource.js +16 -1
- package/amplify/auth/resource.ts +19 -1
- package/amplify/data/function-handler.js +20 -0
- package/amplify/data/function-handler.ts +40 -0
- package/amplify/data/resource.js +158 -61
- package/amplify/data/resource.ts +165 -61
- package/amplify/data/schema.js +2103 -1979
- package/amplify/data/schema.ts +206 -68
- package/amplify/functions/assignment-action/data-access.js +90 -0
- package/amplify/functions/assignment-action/data-access.ts +89 -0
- package/amplify/functions/assignment-action/handler.ts +1 -1
- package/amplify/functions/automation-view/handler.py +17 -0
- package/amplify/functions/automation-view/resource.js +24 -0
- package/amplify/functions/automation-view/resource.ts +34 -0
- package/amplify/functions/automation-view/schema.js +26 -0
- package/amplify/functions/automation-view/schema.ts +28 -0
- package/amplify/functions/automation-view/wire.js +56 -0
- package/amplify/functions/automation-view/wire.ts +76 -0
- package/amplify/functions/content-actions/handler.py +70 -2
- package/amplify/functions/content-actions/requirements.txt +1 -0
- package/amplify/functions/content-actions/resource.js +1 -1
- package/amplify/functions/content-actions/resource.ts +1 -1
- package/amplify/functions/editorial-checks/handler.py +14 -0
- package/amplify/functions/editorial-checks/requirements.txt +1 -0
- package/amplify/functions/editorial-checks/resource.js +43 -0
- package/amplify/functions/editorial-checks/resource.ts +60 -0
- package/amplify/functions/editorial-checks/schema.js +122 -0
- package/amplify/functions/editorial-checks/schema.ts +124 -0
- package/amplify/functions/editorial-checks/wire.js +53 -0
- package/amplify/functions/editorial-checks/wire.ts +61 -0
- package/amplify/functions/model-attachment-upload/handler.ts +1 -0
- package/amplify/functions/monitoring-view/handler.py +11 -0
- package/amplify/functions/monitoring-view/resource.js +24 -0
- package/amplify/functions/monitoring-view/resource.ts +34 -0
- package/amplify/functions/monitoring-view/schema.js +29 -0
- package/amplify/functions/monitoring-view/schema.ts +31 -0
- package/amplify/functions/monitoring-view/wire.js +64 -0
- package/amplify/functions/monitoring-view/wire.ts +81 -0
- package/amplify/functions/public-forms/core.js +247 -0
- package/amplify/functions/public-forms/core.ts +310 -0
- package/amplify/functions/public-forms/handler.ts +41 -0
- package/amplify/functions/public-forms/origins.js +35 -0
- package/amplify/functions/public-forms/origins.ts +43 -0
- package/amplify/functions/public-forms/resource.js +9 -0
- package/amplify/functions/public-forms/resource.ts +10 -0
- package/amplify/functions/public-forms/wire.js +25 -0
- package/amplify/functions/public-forms/wire.ts +32 -0
- package/amplify/functions/shared/editorial-context.ts +63 -4
- package/amplify/functions/shared/python-bundle.js +20 -14
- package/amplify/functions/shared/python-bundle.ts +25 -18
- package/amplify/plugins/newsletter/config.js +245 -0
- package/amplify/plugins/newsletter/config.ts +305 -0
- package/amplify/plugins/newsletter/function/handler.py +6 -0
- package/amplify/plugins/newsletter/function/requirements.txt +5 -0
- package/amplify/plugins/newsletter/ops/handler.py +12 -0
- package/amplify/plugins/newsletter/ops/resource.js +27 -0
- package/amplify/plugins/newsletter/ops/resource.ts +37 -0
- package/amplify/plugins/newsletter/papyrus.plugin.js +263 -0
- package/amplify/plugins/newsletter/papyrus.plugin.ts +311 -0
- package/amplify/plugins/newsletter/schema.js +57 -0
- package/amplify/plugins/newsletter/schema.ts +62 -0
- package/amplify/plugins/newsletter/secure-string-parameter.js +107 -0
- package/amplify/plugins/newsletter/secure-string-parameter.ts +120 -0
- package/amplify/plugins/newsletter/sending.js +140 -0
- package/amplify/plugins/newsletter/sending.ts +186 -0
- package/amplify/plugins/reader-steering/config.js +182 -0
- package/amplify/plugins/reader-steering/config.ts +290 -0
- package/amplify/plugins/reader-steering/function/ai_moderation.py +246 -0
- package/amplify/plugins/reader-steering/function/handler.py +1567 -0
- package/amplify/plugins/reader-steering/function/moderation-prompt.md +27 -0
- package/amplify/plugins/reader-steering/function/moderation.py +316 -0
- package/amplify/plugins/reader-steering/function/proposals.py +458 -0
- package/amplify/plugins/reader-steering/function/resource.js +27 -0
- package/amplify/plugins/reader-steering/function/resource.ts +35 -0
- package/amplify/plugins/reader-steering/papyrus.plugin.js +186 -0
- package/amplify/plugins/reader-steering/papyrus.plugin.ts +212 -0
- package/amplify/plugins/reader-steering/schema.js +229 -0
- package/amplify/plugins/reader-steering/schema.ts +231 -0
- package/amplify/plugins/registry.js +4 -0
- package/amplify/plugins/registry.ts +4 -0
- package/amplify/plugins/signup/schema.js +2 -1
- package/amplify/plugins/signup/schema.ts +2 -1
- package/amplify/plugins/types.ts +5 -0
- package/amplify/plugins/wire.js +1 -0
- package/amplify/plugins/wire.ts +1 -0
- package/amplify/publication/projection-lease.js +30 -0
- package/amplify/publication/projection-lease.ts +39 -0
- package/amplify/publication/redirect-and-index.js +105 -0
- package/amplify/publication/redirect-rules.js +73 -0
- package/amplify/publication/redirect-rules.ts +93 -0
- package/amplify/publication/s3-projection.js +7 -1
- package/amplify/publication/s3-projection.ts +9 -1
- package/amplify/site-backend-config.js +19 -0
- package/amplify/site-backend-config.ts +45 -1
- package/amplify/site-backend-names.js +4 -2
- package/amplify/site-backend-names.ts +4 -2
- package/amplify/site-backend.js +51 -4
- package/amplify/site-backend.ts +60 -4
- package/app/api/auth/prospectus/sign-in/route.ts +4 -0
- package/app/api/newsletter/confirm/route.ts +13 -0
- package/app/api/newsletter/preferences/route.ts +13 -0
- package/app/api/newsletter/state/route.ts +9 -0
- package/app/api/newsletter/subscribe/route.ts +9 -0
- package/app/api/newsletter/unsubscribe/route.ts +13 -0
- package/app/api/newsroom/chat/[...path]/route.ts +17 -0
- package/app/api/newsroom/curation/context/route.ts +9 -0
- package/app/api/newsroom/curation/priming/route.ts +9 -0
- package/app/api/newsroom/curation/publication/route.ts +9 -0
- package/app/api/reader/comment/delete/route.ts +9 -0
- package/app/api/reader/comment/edit/route.ts +9 -0
- package/app/api/reader/comment/route.ts +9 -0
- package/app/api/reader/flag/route.ts +9 -0
- package/app/api/reader/handle/route.ts +9 -0
- package/app/api/reader/me/route.ts +9 -0
- package/app/api/reader/rating/route.ts +9 -0
- package/app/api/reader/report/route.ts +9 -0
- package/app/api/reader/retired/route.ts +9 -0
- package/app/api/reader/submit/route.ts +9 -0
- package/app/api/reader/vote/route.ts +9 -0
- package/app/layout.tsx +5 -1
- package/bin/papyrus-infra.mjs +20 -1
- package/components/automation-panel.tsx +49 -0
- package/components/automation-run-now.tsx +97 -0
- package/components/automation-view.tsx +195 -0
- package/components/editorial-checks-admin-panel.tsx +362 -0
- package/components/editorial-finding-card.tsx +162 -0
- package/components/editorial-findings-panel.tsx +91 -0
- package/components/editorial-preview-popover.tsx +103 -0
- package/components/markus-body-editor.tsx +213 -0
- package/components/markus-ir-preview.tsx +147 -6
- package/components/moderation-panel.tsx +248 -0
- package/components/monitoring-overview-view.tsx +414 -0
- package/components/monitoring-panel.tsx +60 -0
- package/components/news-desk-client-provider.tsx +18 -18
- package/components/news-desk-taxonomy-client.ts +28 -8
- package/components/newsletter-panel.tsx +474 -0
- package/components/newsletter-sections.tsx +163 -0
- package/components/newsroom-access-gate.tsx +16 -2
- package/components/newsroom-article-editor.tsx +145 -18
- package/components/newsroom-articles-view.tsx +6 -6
- package/components/newsroom-assignment-detail.tsx +6 -6
- package/components/newsroom-board-view.tsx +14 -10
- package/components/newsroom-curation-bootstrap.tsx +45 -0
- package/components/newsroom-ops-overview.tsx +26 -96
- package/components/newsroom-ops-shell.tsx +9 -5
- package/components/newsroom-organizer.css +90 -61
- package/components/newsroom-overview-skeleton.tsx +25 -0
- package/components/newsroom-references-view.tsx +192 -49
- package/components/newsroom-theme-fonts/broadsheet-green.css +10 -0
- package/components/newsroom-theme-fonts/broadsheet-green.tsx +6 -0
- package/components/newsroom-theme-fonts/newspaper-gothic.css +9 -0
- package/components/newsroom-theme-fonts/newspaper-gothic.tsx +6 -0
- package/components/newsroom-theme-fonts/night-desk.css +10 -0
- package/components/newsroom-theme-fonts/night-desk.tsx +6 -0
- package/components/newsroom-theme-fonts/refined-newsprint.css +11 -0
- package/components/newsroom-theme-fonts/refined-newsprint.tsx +6 -0
- package/components/newsroom-theme.css +39 -0
- package/components/newsroom-theme.tsx +33 -0
- package/components/notification-center.tsx +281 -0
- package/components/papyrus-console-conversation.css +14 -0
- package/components/papyrus-console-conversation.tsx +55 -0
- package/components/papyrus-console-shell.tsx +62 -420
- package/components/papyrus-private-chat-panel.tsx +134 -0
- package/components/publication-cyclotron-panel.tsx +15 -10
- package/components/reader-auth-state.ts +1 -1
- package/components/reference-add-entry.tsx +75 -0
- package/components/reference-curation-controls.tsx +31 -22
- package/components/reference-cyclotron-priming.tsx +63 -25
- package/components/reference-cyclotron-status.tsx +4 -4
- package/components/reference-cyclotron-suggestion.tsx +15 -11
- package/components/reference-live-agreement.tsx +10 -10
- package/components/reference-priming.tsx +14 -10
- package/components/reference-relevance-review.tsx +4 -4
- package/components/reference-section-suggestion.tsx +2 -2
- package/components/topic-steering-workspace.tsx +241 -144
- package/components/use-editorial-checks.ts +133 -0
- package/infra/amplify-app-shell.js +96 -16
- package/infra/amplify-app-shell.ts +108 -18
- package/infra/cloud-email-config.js +32 -0
- package/infra/cloud-email-config.ts +39 -0
- package/infra/cloud-email.js +57 -0
- package/infra/cloud-email.test.js +69 -0
- package/infra/cloud-email.test.ts +66 -0
- package/infra/cloud-email.ts +60 -0
- package/infra/index.js +1 -0
- package/infra/secure-string-parameter-handler.js +41 -0
- package/infra/secure-string-parameter-handler.ts +41 -0
- package/infra/secure-string-parameter.js +79 -0
- package/infra/secure-string-parameter.ts +91 -0
- package/infra/site-config.js +92 -6
- package/infra/site-config.ts +138 -6
- package/lib/automation-client.ts +54 -0
- package/lib/automation-fixture.ts +93 -0
- package/lib/automation-overview.ts +252 -0
- package/lib/category-repository.ts +14 -12
- package/lib/console-web-context.ts +1 -1
- package/lib/curation-routes.ts +345 -0
- package/lib/cyclotron-suggestions.ts +11 -11
- package/lib/editorial-checks-backend.ts +16 -0
- package/lib/editorial-checks-client.ts +212 -0
- package/lib/editorial-checks-demo.ts +147 -0
- package/lib/editorial-checks-settings.ts +27 -0
- package/lib/editorial-checks.ts +175 -0
- package/lib/editorial-preview.ts +228 -0
- package/lib/monitoring-client.ts +83 -0
- package/lib/monitoring-overview-fixture.ts +51 -0
- package/lib/monitoring-overview.ts +188 -0
- package/lib/news-desk-session.ts +12 -21
- package/lib/newsletter-api.ts +418 -0
- package/lib/newsletter-client.ts +46 -0
- package/lib/newsletter-fixture.ts +184 -0
- package/lib/newsletter-model.ts +202 -0
- package/lib/newsroom-board.ts +27 -2
- package/lib/newsroom-demo-dashboard.ts +1 -1
- package/lib/newsroom-nav.ts +1 -1
- package/lib/newsroom-organizer-nav.ts +2 -1
- package/lib/papyrus-chat-admission.ts +65 -0
- package/lib/papyrus-hosted-chat.ts +217 -0
- package/lib/papyrus-private-chat-client.ts +81 -0
- package/lib/prospectus-session.ts +30 -14
- package/lib/prospectus-sign-in-routes.ts +106 -31
- package/lib/prospectus-site-identity.ts +46 -6
- package/lib/reader-api.ts +145 -0
- package/lib/reader-moderation.ts +220 -0
- package/lib/reader-retirement-route.ts +89 -0
- package/lib/reader-subject.md +29 -0
- package/lib/reader-subject.ts +53 -0
- package/lib/reference-review-details.ts +71 -0
- package/lib/reference-review-request.ts +14 -0
- package/lib/relevance-decisions.ts +42 -10
- package/lib/relevance-status.ts +6 -6
- package/lib/review-client.ts +120 -0
- package/lib/review-fixture.ts +45 -0
- package/lib/review-requests.ts +246 -0
- package/lib/semantic-graph.ts +2 -0
- package/lib/shared-chat-admission.ts +182 -0
- package/lib/site-brand-tenant.ts +11 -6
- package/lib/site-brand.ts +23 -3
- package/lib/site-origin-value.ts +50 -0
- package/lib/site-origin.ts +8 -0
- package/lib/use-reference-review-data.ts +44 -0
- package/middleware.ts +14 -3
- package/package.json +98 -4
- package/routes.manifest.json +227 -2
- package/src/with-papyrus.mjs +1 -1
- package/components/newsroom-fonts/playfair-display-700.ttf +0 -0
- package/components/newsroom-fonts/playfair-display-900.ttf +0 -0
- package/components/newsroom-fonts/playfair-display-OFL.txt +0 -93
- package/components/newsroom-fonts/plus-jakarta-sans-400.ttf +0 -0
- package/components/newsroom-fonts/plus-jakarta-sans-600.ttf +0 -0
- package/components/newsroom-fonts/plus-jakarta-sans-OFL.txt +0 -93
- package/components/newsroom-newsprint-board.css +0 -7
|
@@ -13,6 +13,11 @@ import { usePathname, useRouter } from "next/navigation";
|
|
|
13
13
|
import type { ReactNode, RefObject } from "react";
|
|
14
14
|
import { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useTransition } from "react";
|
|
15
15
|
import amplifyOutputs from "papyrus-amplify-outputs";
|
|
16
|
+
import { EditorialChecksAdminPanel } from "./editorial-checks-admin-panel";
|
|
17
|
+
import { AutomationPanel } from "./automation-panel";
|
|
18
|
+
import { MonitoringPanel } from "./monitoring-panel";
|
|
19
|
+
import { ModerationPanel } from "./moderation-panel";
|
|
20
|
+
import { NewsletterPanel } from "./newsletter-panel";
|
|
16
21
|
import { SignupEntriesPanel } from "./signup-entries-panel";
|
|
17
22
|
import { pluginSettings, type PluginOutputs } from "../lib/plugin-settings";
|
|
18
23
|
import { generateClient } from "aws-amplify/data";
|
|
@@ -35,6 +40,7 @@ import {
|
|
|
35
40
|
loadEditorReferencesData,
|
|
36
41
|
loadEditorProcedureData,
|
|
37
42
|
loadEditorSemanticRelationsData,
|
|
43
|
+
loadEditorReferenceReviewDetails,
|
|
38
44
|
loadEditionForumThreads,
|
|
39
45
|
loadNewsroomAssignmentPage,
|
|
40
46
|
loadNewsroomMessagePage,
|
|
@@ -88,6 +94,7 @@ import { ReferenceSourcePreview } from "./reference-source-preview";
|
|
|
88
94
|
import type { ReaderAuthSnapshot } from "./reader-auth-state";
|
|
89
95
|
import { NewsDeskAccessGate } from "./newsroom-access-gate";
|
|
90
96
|
import { NewsroomOpsOverview } from "./newsroom-ops-overview";
|
|
97
|
+
import { NewsroomCurationBootstrap } from "./newsroom-curation-bootstrap";
|
|
91
98
|
import { NewsroomReferencesView } from "./newsroom-references-view";
|
|
92
99
|
import { NewsroomAssignmentsView } from "./newsroom-assignments-view";
|
|
93
100
|
import { NewsroomTopicsView } from "./newsroom-topics-view";
|
|
@@ -161,6 +168,9 @@ import {
|
|
|
161
168
|
} from "../lib/reference-policy";
|
|
162
169
|
import { isLocalPreviewEnabled } from "../lib/local-preview";
|
|
163
170
|
import { currentRelevanceDecisions } from "../lib/relevance-decisions";
|
|
171
|
+
import { runReferenceReviewRequest } from "../lib/reference-review-request";
|
|
172
|
+
import { useReferenceReviewData } from "../lib/use-reference-review-data";
|
|
173
|
+
import { latestReferenceReviewReasons, latestReferenceReviewSections } from "../lib/reference-review-details";
|
|
164
174
|
import { delegatedCurationsByReference, referencesWithHumanLatestCuration, type ShadowAgreement } from "../lib/cyclotron-suggestions";
|
|
165
175
|
import { createLocalPreviewCyclotronFixtures } from "../lib/local-preview-seed";
|
|
166
176
|
import { createLocalPreviewSectionFixtures } from "../lib/local-preview-section-fixtures";
|
|
@@ -246,7 +256,7 @@ type AssignmentAction = "claim" | "release" | "complete" | "cancel" | "reopen" |
|
|
|
246
256
|
type ReportingPacketReviewDecision = "select" | "merge" | "brief" | "hold" | "kill";
|
|
247
257
|
type AssignmentDeskViewMode = "queue" | "budget";
|
|
248
258
|
type UserRoleAction = "grant" | "revoke";
|
|
249
|
-
type AdministrationPanel = "users" | "policies" | "sections" | "procedures" | "delegations" | "signups";
|
|
259
|
+
type AdministrationPanel = "users" | "policies" | "sections" | "procedures" | "automations" | "delegations" | "signups" | "newsletter" | "moderation" | "editorial-checks" | "monitoring";
|
|
250
260
|
export type NewsDeskTab = "overview" | "desks" | "topics" | "concepts" | "references" | "messages" | "assignments" | "administration" | "search";
|
|
251
261
|
type LexicalRuleScope = "publication" | "corpus" | "classifier" | "category";
|
|
252
262
|
type AnalysisReindexMode = "online-update" | "classifier-retrain" | "scoped-topic-rebuild" | "entity-graph-rebuild" | "generated-analysis-rebuild";
|
|
@@ -657,14 +667,14 @@ export function NewsDeskWorkspace({
|
|
|
657
667
|
editorShellReady
|
|
658
668
|
initialSelection={initialSelection}
|
|
659
669
|
initialTab={initialTab}
|
|
660
|
-
authState={{ status: "signedIn", label: "Demo
|
|
670
|
+
authState={{ status: "signedIn", label: "Demo section" }}
|
|
661
671
|
isRefreshing={false}
|
|
662
672
|
shellError={null}
|
|
663
673
|
/>
|
|
664
674
|
);
|
|
665
675
|
}
|
|
666
676
|
|
|
667
|
-
if (session && sessionDashboard) {
|
|
677
|
+
if (session && sessionDashboard && session.shell.phase !== "loadingDesk") {
|
|
668
678
|
return (
|
|
669
679
|
<NewsDeskDashboard
|
|
670
680
|
analysisProfiles={analysisProfiles}
|
|
@@ -878,7 +888,7 @@ function NewsDeskDashboard({
|
|
|
878
888
|
const [mergeSelection, setMergeSelection] = useState<MergeSelection | null>(null);
|
|
879
889
|
const [isPending, startTransition] = useTransition();
|
|
880
890
|
const controlsDisabled = isPending || !canEdit;
|
|
881
|
-
const initialAdministrationPanel = normalizeAdministrationPanel(initialSelection.panel);
|
|
891
|
+
const initialAdministrationPanel = normalizeAdministrationPanel(initialSelection.panel, Boolean(dashboard.isDemo));
|
|
882
892
|
const [administrationPanel, setAdministrationPanel] = useState<AdministrationPanel>(initialAdministrationPanel);
|
|
883
893
|
const [doctrineDrafts, setDoctrineDrafts] = useState<DoctrineEditorState>(() => buildDoctrineEditorState(dashboard.doctrineRecords));
|
|
884
894
|
const [loadedSections, setLoadedSections] = useState<Record<string, boolean>>({
|
|
@@ -896,6 +906,11 @@ function NewsDeskDashboard({
|
|
|
896
906
|
const [referencesRealtimeStatus, setReferencesRealtimeStatus] = useState<RealtimeSubscriptionStatus>("idle");
|
|
897
907
|
const [referencesRealtimeError, setReferencesRealtimeError] = useState<string | null>(null);
|
|
898
908
|
const referencesRef = useRef(references);
|
|
909
|
+
const referenceReviewsPending = useRef(new Map<string, Promise<void>>());
|
|
910
|
+
const [selectedReviewRead, setSelectedReviewRead] = useState<{ lineageId: string; state: "loading" | "ready" | "error"; error: string | null }>({ lineageId: "", state: "ready", error: null });
|
|
911
|
+
const [selectedReviewAttempt, setSelectedReviewAttempt] = useState(0);
|
|
912
|
+
const reviewReasons = useMemo(() => latestReferenceReviewReasons(messages), [messages]);
|
|
913
|
+
const reviewSectionIds = useMemo(() => latestReferenceReviewSections(messages), [messages]);
|
|
899
914
|
|
|
900
915
|
useEffect(() => {
|
|
901
916
|
referencesRef.current = references;
|
|
@@ -1119,8 +1134,8 @@ function NewsDeskDashboard({
|
|
|
1119
1134
|
}, [dashboard.procedureDefinitions, dashboard.procedureRuns, dashboard.procedureVersions]);
|
|
1120
1135
|
|
|
1121
1136
|
useEffect(() => {
|
|
1122
|
-
setAdministrationPanel(normalizeAdministrationPanel(initialSelection.panel));
|
|
1123
|
-
}, [initialSelection.panel]);
|
|
1137
|
+
setAdministrationPanel(normalizeAdministrationPanel(initialSelection.panel, Boolean(dashboard.isDemo)));
|
|
1138
|
+
}, [initialSelection.panel, dashboard.isDemo]);
|
|
1124
1139
|
|
|
1125
1140
|
useEffect(() => {
|
|
1126
1141
|
if (activeTab !== "administration") return;
|
|
@@ -1225,17 +1240,6 @@ function NewsDeskDashboard({
|
|
|
1225
1240
|
if (dashboard.isDemo) return;
|
|
1226
1241
|
let active = true;
|
|
1227
1242
|
|
|
1228
|
-
if (activeTab === "messages" && !loadedSections.messages) {
|
|
1229
|
-
setLoadedSections((current) => ({ ...current, messages: true }));
|
|
1230
|
-
void loadEditorMessagesData()
|
|
1231
|
-
.then((nextMessages) => {
|
|
1232
|
-
if (active) setMessages(nextMessages);
|
|
1233
|
-
})
|
|
1234
|
-
.catch((error) => {
|
|
1235
|
-
if (active) setActionState({ id: "messages-load", message: error instanceof Error ? error.message : "messages load failed", tone: "error" });
|
|
1236
|
-
});
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
1243
|
if (activeTab === "assignments" && !loadedSections.assignments) {
|
|
1240
1244
|
setLoadedSections((current) => ({ ...current, assignments: true }));
|
|
1241
1245
|
void loadEditorAssignmentsData()
|
|
@@ -1263,23 +1267,6 @@ function NewsDeskDashboard({
|
|
|
1263
1267
|
});
|
|
1264
1268
|
}
|
|
1265
1269
|
|
|
1266
|
-
if ((activeTab === "assignments" || activeTab === "references" || activeTab === "messages") && !loadedSections.semanticRelations) {
|
|
1267
|
-
setLoadedSections((current) => ({ ...current, semanticRelations: true }));
|
|
1268
|
-
void loadEditorSemanticRelationsData()
|
|
1269
|
-
.then((relations) => {
|
|
1270
|
-
if (active) setSemanticRelations(relations);
|
|
1271
|
-
})
|
|
1272
|
-
.catch(() => {
|
|
1273
|
-
if (active) setSemanticRelations([]);
|
|
1274
|
-
});
|
|
1275
|
-
if (!loadedSections.messages) {
|
|
1276
|
-
setLoadedSections((current) => ({ ...current, messages: true }));
|
|
1277
|
-
void loadEditorMessagesData().then((nextMessages) => {
|
|
1278
|
-
if (active) setMessages(nextMessages);
|
|
1279
|
-
}).catch(() => undefined);
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
1270
|
if ((activeTab === "topics" || activeTab === "desks" || activeTab === "concepts" || activeTab === "administration") && !loadedSections.fullDashboard) {
|
|
1284
1271
|
setLoadedSections((current) => ({ ...current, fullDashboard: true }));
|
|
1285
1272
|
void loadEditorFullNewsDeskDashboard({ isAdmin: Boolean(dashboard.canManageUsers) })
|
|
@@ -1334,6 +1321,37 @@ function NewsDeskDashboard({
|
|
|
1334
1321
|
refreshNewsroomSections,
|
|
1335
1322
|
]);
|
|
1336
1323
|
|
|
1324
|
+
const needsReferenceReviewData = activeTab === "references" || activeTab === "assignments" || activeTab === "messages";
|
|
1325
|
+
const selectedReviewLineageId = pathname ? pathnameReferenceLineageId ?? "" : initialSelection.reference ?? "";
|
|
1326
|
+
const referenceReviewData = useReferenceReviewData({
|
|
1327
|
+
enabled: canLoadPrivateCorpus && needsReferenceReviewData && !(activeTab === "references" && selectedReviewLineageId),
|
|
1328
|
+
loadRelations: loadEditorSemanticRelationsData,
|
|
1329
|
+
loadMessages: loadEditorMessagesData,
|
|
1330
|
+
onRelations: setSemanticRelations,
|
|
1331
|
+
onMessages: setMessages,
|
|
1332
|
+
});
|
|
1333
|
+
|
|
1334
|
+
useEffect(() => {
|
|
1335
|
+
if (!canLoadPrivateCorpus || activeTab !== "references" || !selectedReviewLineageId) return;
|
|
1336
|
+
let active = true;
|
|
1337
|
+
setSelectedReviewRead({ lineageId: selectedReviewLineageId, state: "loading", error: null });
|
|
1338
|
+
void loadEditorReferenceReviewDetails(selectedReviewLineageId).then(({ relations, messages: history }) => {
|
|
1339
|
+
if (!active) return;
|
|
1340
|
+
setSemanticRelations((current) => [...current.filter((relation) => relation.subjectLineageId !== selectedReviewLineageId || relation.subjectKind !== "reference"), ...relations]);
|
|
1341
|
+
setMessages((current) => [...current.filter((message) => !history.some((entry) => entry.id === message.id)), ...history]);
|
|
1342
|
+
setSelectedReviewRead({ lineageId: selectedReviewLineageId, state: "ready", error: null });
|
|
1343
|
+
}).catch((error) => {
|
|
1344
|
+
if (active) setSelectedReviewRead({ lineageId: selectedReviewLineageId, state: "error", error: error instanceof Error ? error.message : "Reference review details could not be loaded." });
|
|
1345
|
+
});
|
|
1346
|
+
return () => { active = false; };
|
|
1347
|
+
}, [activeTab, canLoadPrivateCorpus, selectedReviewLineageId, selectedReviewAttempt]);
|
|
1348
|
+
const selectedReviewIsCurrent = selectedReviewLineageId && !dashboard.isDemo;
|
|
1349
|
+
const predictionState = selectedReviewIsCurrent
|
|
1350
|
+
? selectedReviewRead.lineageId === selectedReviewLineageId ? selectedReviewRead.state : "loading"
|
|
1351
|
+
: referenceReviewData.state;
|
|
1352
|
+
const predictionError = selectedReviewIsCurrent ? selectedReviewRead.error : referenceReviewData.error;
|
|
1353
|
+
const retryReferenceReviewData = () => { referenceReviewData.retry(); setSelectedReviewAttempt((current) => current + 1); };
|
|
1354
|
+
|
|
1337
1355
|
const applyReferenceRecord = useCallback((nextReference: ReferenceRecord) => {
|
|
1338
1356
|
const { nextRecords, nextRecord, previousRecord } = upsertReferenceRecords(referencesRef.current, nextReference);
|
|
1339
1357
|
referencesRef.current = nextRecords;
|
|
@@ -1588,96 +1606,98 @@ function NewsDeskDashboard({
|
|
|
1588
1606
|
reasonCode?: ReferenceRejectionReasonCode | null,
|
|
1589
1607
|
relevance?: { decisionRelationId: string; shareable: boolean },
|
|
1590
1608
|
sectionId?: string | null,
|
|
1591
|
-
) {
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
note: note?.trim() || undefined,
|
|
1660
|
-
reasonCode: action === "reject" ? reasonCode ?? undefined : undefined,
|
|
1661
|
-
decisionRelationId: relevance?.decisionRelationId,
|
|
1662
|
-
shareable: relevance ? relevance.shareable : undefined,
|
|
1663
|
-
sectionId: action === "accept" ? sectionId ?? undefined : undefined,
|
|
1664
|
-
},
|
|
1665
|
-
{ authMode: USER_POOL_AUTH_MODE },
|
|
1666
|
-
);
|
|
1667
|
-
const review = assertReferenceReviewMutationSucceeded(response, reference.id);
|
|
1668
|
-
const status = review.status ?? nextStatus;
|
|
1669
|
-
const now = new Date().toISOString();
|
|
1670
|
-
applyReferenceRecord(buildReviewedReferenceRecord(referencesRef.current, reference, {
|
|
1609
|
+
): Promise<void> {
|
|
1610
|
+
return runReferenceReviewRequest(referenceReviewsPending.current, reference.lineageId ?? reference.id, async () => {
|
|
1611
|
+
if (!canEdit) throw new Error("Your session does not have permission to review references.");
|
|
1612
|
+
const nextStatus = referenceCurationStatusForAction(action);
|
|
1613
|
+
setActionState({ id: reference.id, message: `${action} pending`, tone: "pending" });
|
|
1614
|
+
if (dashboard.isDemo) {
|
|
1615
|
+
const now = new Date().toISOString();
|
|
1616
|
+
const messageId = `message-demo-${reference.id}-${action}-${now.replace(/[^0-9]/g, "")}`;
|
|
1617
|
+
const relationId = `semantic-relation-demo-${messageId}`;
|
|
1618
|
+
applyReferenceRecord(buildReviewedReferenceRecord(referencesRef.current, reference, {
|
|
1619
|
+
actorLabel: authState.label,
|
|
1620
|
+
nextStatus,
|
|
1621
|
+
note: note ?? null,
|
|
1622
|
+
now,
|
|
1623
|
+
}));
|
|
1624
|
+
setMessages((current) => [{
|
|
1625
|
+
id: messageId,
|
|
1626
|
+
messageKind: "reference_curation",
|
|
1627
|
+
messageDomain: "commentary",
|
|
1628
|
+
status: "active",
|
|
1629
|
+
body: note?.trim() || `${authState.label} marked this reference ${nextStatus}.`,
|
|
1630
|
+
summary: `${reference.title ?? reference.externalItemId}: ${nextStatus}`,
|
|
1631
|
+
source: "newsroom",
|
|
1632
|
+
authorLabel: authState.label,
|
|
1633
|
+
createdAt: now,
|
|
1634
|
+
updatedAt: now,
|
|
1635
|
+
metadata: {
|
|
1636
|
+
referenceLineageId: reference.lineageId ?? reference.id,
|
|
1637
|
+
action,
|
|
1638
|
+
curationStatus: nextStatus,
|
|
1639
|
+
reasonCode: action === "reject" ? reasonCode ?? null : null,
|
|
1640
|
+
...(relevance ? { decisionRelationId: relevance.decisionRelationId, shareable: relevance.shareable } : {}),
|
|
1641
|
+
...(action === "accept" && sectionId ? { sectionId } : {}),
|
|
1642
|
+
},
|
|
1643
|
+
}, ...current]);
|
|
1644
|
+
setSemanticRelations((current) => [{
|
|
1645
|
+
id: relationId,
|
|
1646
|
+
relationState: "current",
|
|
1647
|
+
predicate: "comment",
|
|
1648
|
+
relationTypeId: "semantic-relation-type-comment",
|
|
1649
|
+
relationTypeKey: "comment",
|
|
1650
|
+
relationDomain: "commentary",
|
|
1651
|
+
subjectKind: "message",
|
|
1652
|
+
subjectId: messageId,
|
|
1653
|
+
subjectLineageId: messageId,
|
|
1654
|
+
subjectVersionNumber: 1,
|
|
1655
|
+
objectKind: "reference",
|
|
1656
|
+
objectId: reference.id,
|
|
1657
|
+
objectLineageId: reference.lineageId ?? reference.id,
|
|
1658
|
+
objectVersionNumber: reference.versionNumber ?? null,
|
|
1659
|
+
subjectStateKey: `message#${messageId}#current`,
|
|
1660
|
+
objectStateKey: `reference#${reference.lineageId ?? reference.id}#current`,
|
|
1661
|
+
objectSubjectStateKey: `reference#${reference.lineageId ?? reference.id}#current#message`,
|
|
1662
|
+
predicateObjectStateKey: `comment#reference#${reference.lineageId ?? reference.id}#current`,
|
|
1663
|
+
subjectVersionKey: `message#${messageId}`,
|
|
1664
|
+
objectVersionKey: `reference#${reference.id}`,
|
|
1665
|
+
rank: 1,
|
|
1666
|
+
reviewRecommended: false,
|
|
1667
|
+
importedAt: now,
|
|
1668
|
+
}, ...current]);
|
|
1669
|
+
setActionState({ id: reference.id, message: `${action} saved`, tone: "ok" });
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
try {
|
|
1673
|
+
const response = await dataClient.mutations.reviewReferenceCuration(
|
|
1674
|
+
{
|
|
1675
|
+
referenceId: reference.id,
|
|
1676
|
+
action,
|
|
1671
1677
|
actorLabel: authState.label,
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1678
|
+
note: note?.trim() || undefined,
|
|
1679
|
+
reasonCode: action === "reject" ? reasonCode ?? undefined : undefined,
|
|
1680
|
+
decisionRelationId: relevance?.decisionRelationId,
|
|
1681
|
+
shareable: relevance ? relevance.shareable : undefined,
|
|
1682
|
+
sectionId: action === "accept" ? sectionId ?? undefined : undefined,
|
|
1683
|
+
},
|
|
1684
|
+
{ authMode: USER_POOL_AUTH_MODE },
|
|
1685
|
+
);
|
|
1686
|
+
const review = assertReferenceReviewMutationSucceeded(response, reference.id);
|
|
1687
|
+
const status = review.status ?? nextStatus;
|
|
1688
|
+
const now = new Date().toISOString();
|
|
1689
|
+
applyReferenceRecord(buildReviewedReferenceRecord(referencesRef.current, reference, {
|
|
1690
|
+
actorLabel: authState.label,
|
|
1691
|
+
nextStatus: status,
|
|
1692
|
+
note: note?.trim() || null,
|
|
1693
|
+
now,
|
|
1694
|
+
}));
|
|
1695
|
+
setActionState({ id: reference.id, message: `${action} saved`, tone: "ok" });
|
|
1696
|
+
retryReferenceReviewData();
|
|
1697
|
+
} catch (error) {
|
|
1698
|
+
setActionState({ id: reference.id, message: error instanceof Error ? error.message : `${action} failed`, tone: "error" });
|
|
1699
|
+
throw error;
|
|
1700
|
+
}
|
|
1681
1701
|
});
|
|
1682
1702
|
}
|
|
1683
1703
|
|
|
@@ -2998,7 +3018,7 @@ function NewsDeskDashboard({
|
|
|
2998
3018
|
return entries;
|
|
2999
3019
|
}, [summaryStatus, tabCounts]);
|
|
3000
3020
|
const opsPageTitle = activeTab === "overview"
|
|
3001
|
-
? "
|
|
3021
|
+
? "Notification Center"
|
|
3002
3022
|
: activeTab === "administration" && administrationPanel === "sections"
|
|
3003
3023
|
? "Sections"
|
|
3004
3024
|
: formatDeskSectionHeadline(activeTab);
|
|
@@ -3056,9 +3076,11 @@ function NewsDeskDashboard({
|
|
|
3056
3076
|
|
|
3057
3077
|
{activeTab === "overview" ? (
|
|
3058
3078
|
<NewsroomOpsOverview
|
|
3079
|
+
actorLabel={authState.label}
|
|
3059
3080
|
assignments={assignments}
|
|
3081
|
+
decisions={relevanceDecisions}
|
|
3060
3082
|
demo={Boolean(dashboard.isDemo)}
|
|
3061
|
-
|
|
3083
|
+
humanCuratedReferenceLineageIds={humanCuratedReferenceLineageIds}
|
|
3062
3084
|
newsroomSections={newsroomSections}
|
|
3063
3085
|
references={references}
|
|
3064
3086
|
/>
|
|
@@ -3114,10 +3136,11 @@ function NewsDeskDashboard({
|
|
|
3114
3136
|
/>
|
|
3115
3137
|
) : null}
|
|
3116
3138
|
{activeTab === "references" ? (
|
|
3139
|
+
<NewsroomCurationBootstrap enabled={!dashboard.isDemo}>
|
|
3117
3140
|
<NewsroomReferencesView
|
|
3118
3141
|
demo={Boolean(dashboard.isDemo)}
|
|
3119
3142
|
disabled={controlsDisabled}
|
|
3120
|
-
initialReferenceLineageId={
|
|
3143
|
+
initialReferenceLineageId={selectedReviewLineageId}
|
|
3121
3144
|
cyclotronStatus={cyclotronStatus}
|
|
3122
3145
|
cyclotronPriming={{
|
|
3123
3146
|
labels: primingLabels,
|
|
@@ -3129,8 +3152,8 @@ function NewsDeskDashboard({
|
|
|
3129
3152
|
},
|
|
3130
3153
|
}}
|
|
3131
3154
|
decisions={relevanceDecisions}
|
|
3132
|
-
humanCuratedReferenceLineageIds={humanCuratedReferenceLineageIds}
|
|
3133
|
-
delegatedCurations={delegatedCurations}
|
|
3155
|
+
humanCuratedReferenceLineageIds={selectedReviewIsCurrent && predictionState !== "ready" ? undefined : humanCuratedReferenceLineageIds}
|
|
3156
|
+
delegatedCurations={selectedReviewIsCurrent && predictionState !== "ready" ? undefined : delegatedCurations}
|
|
3134
3157
|
shadowAgreement={shadowAgreement}
|
|
3135
3158
|
onRequestReviewRate={relevanceCyclotronId ? async (choice) => {
|
|
3136
3159
|
const request = buildReviewRateRequest(choice, authState.label);
|
|
@@ -3143,14 +3166,23 @@ function NewsDeskDashboard({
|
|
|
3143
3166
|
curation.note ?? undefined,
|
|
3144
3167
|
normalizeReferenceRejectionReasonCode(curation.reasonCode),
|
|
3145
3168
|
{ decisionRelationId: curation.decisionRelationId, shareable: curation.shareable },
|
|
3169
|
+
curation.sectionId,
|
|
3146
3170
|
)}
|
|
3147
3171
|
sections={sectionChoices}
|
|
3148
3172
|
sectionSuggestions={sectionSuggestions}
|
|
3149
3173
|
sectionAgreement={siteSectionAgreement}
|
|
3150
|
-
|
|
3174
|
+
predictionState={predictionState}
|
|
3175
|
+
predictionError={predictionError}
|
|
3176
|
+
onRetryPredictions={retryReferenceReviewData}
|
|
3177
|
+
reviewReasons={reviewReasons}
|
|
3178
|
+
reviewSectionIds={reviewSectionIds}
|
|
3179
|
+
onReview={(reference, action, options) => runReferenceCurationAction(reference, action, options?.note, options?.reasonCode,
|
|
3180
|
+
options?.decisionRelationId ? { decisionRelationId: options.decisionRelationId, shareable: options.shareable === true } : undefined,
|
|
3181
|
+
options?.sectionId)}
|
|
3151
3182
|
referenceAttachments={referenceAttachments}
|
|
3152
3183
|
references={references}
|
|
3153
3184
|
/>
|
|
3185
|
+
</NewsroomCurationBootstrap>
|
|
3154
3186
|
) : null}
|
|
3155
3187
|
{activeTab === "messages" ? (
|
|
3156
3188
|
<MessagesDeskView
|
|
@@ -3871,7 +3903,7 @@ function NewsroomSectionRail({
|
|
|
3871
3903
|
<aside className="newsroom-section-rail" data-newsroom-section-rail aria-labelledby="newsroom-section-rail-title" ref={railRef}>
|
|
3872
3904
|
<header className="newsroom-section-rail__header">
|
|
3873
3905
|
<p className="story-label">Sections</p>
|
|
3874
|
-
<h2 id="newsroom-section-rail-title">Section
|
|
3906
|
+
<h2 id="newsroom-section-rail-title">Section</h2>
|
|
3875
3907
|
</header>
|
|
3876
3908
|
<div className="newsroom-section-rail__body">
|
|
3877
3909
|
{canonicalSections.length ? (
|
|
@@ -4308,6 +4340,15 @@ function AdministrationDeskView({
|
|
|
4308
4340
|
<strong>Procedures</strong>
|
|
4309
4341
|
<span>Procedure registry and versioned Tactus code</span>
|
|
4310
4342
|
</Link>
|
|
4343
|
+
<Link
|
|
4344
|
+
href={administrationPanelHref("automations", isDemo)}
|
|
4345
|
+
data-news-desk-admin-nav="automations"
|
|
4346
|
+
data-active={administrationPanel === "automations" || undefined}
|
|
4347
|
+
onClick={() => onPanelChange("automations")}
|
|
4348
|
+
>
|
|
4349
|
+
<strong>Automation</strong>
|
|
4350
|
+
<span>Procedures that start on their own</span>
|
|
4351
|
+
</Link>
|
|
4311
4352
|
<Link
|
|
4312
4353
|
href={administrationPanelHref("delegations", isDemo)}
|
|
4313
4354
|
data-news-desk-admin-nav="delegations"
|
|
@@ -4317,6 +4358,24 @@ function AdministrationDeskView({
|
|
|
4317
4358
|
<strong>Agent delegations</strong>
|
|
4318
4359
|
<span>Let an agent curate References for you</span>
|
|
4319
4360
|
</Link>
|
|
4361
|
+
<Link
|
|
4362
|
+
href={administrationPanelHref("editorial-checks", isDemo)}
|
|
4363
|
+
data-news-desk-admin-nav="editorial-checks"
|
|
4364
|
+
data-active={administrationPanel === "editorial-checks" || undefined}
|
|
4365
|
+
onClick={() => onPanelChange("editorial-checks")}
|
|
4366
|
+
>
|
|
4367
|
+
<strong>Editorial checks</strong>
|
|
4368
|
+
<span>Policies the article editor checks drafts against</span>
|
|
4369
|
+
</Link>
|
|
4370
|
+
<Link
|
|
4371
|
+
href={administrationPanelHref("monitoring", isDemo)}
|
|
4372
|
+
data-news-desk-admin-nav="monitoring"
|
|
4373
|
+
data-active={administrationPanel === "monitoring" || undefined}
|
|
4374
|
+
onClick={() => onPanelChange("monitoring")}
|
|
4375
|
+
>
|
|
4376
|
+
<strong>Monitoring</strong>
|
|
4377
|
+
<span>The automated research pipeline, read only</span>
|
|
4378
|
+
</Link>
|
|
4320
4379
|
{signupPluginEnabled() ? (
|
|
4321
4380
|
<Link
|
|
4322
4381
|
href={administrationPanelHref("signups", isDemo)}
|
|
@@ -4328,9 +4387,36 @@ function AdministrationDeskView({
|
|
|
4328
4387
|
<span>Addresses from the site's signup forms</span>
|
|
4329
4388
|
</Link>
|
|
4330
4389
|
) : null}
|
|
4390
|
+
{newsletterPluginEnabled(isDemo) ? (
|
|
4391
|
+
<Link
|
|
4392
|
+
href={administrationPanelHref("newsletter", isDemo)}
|
|
4393
|
+
data-news-desk-admin-nav="newsletter"
|
|
4394
|
+
data-active={administrationPanel === "newsletter" || undefined}
|
|
4395
|
+
onClick={() => onPanelChange("newsletter")}
|
|
4396
|
+
>
|
|
4397
|
+
<strong>Newsletter</strong>
|
|
4398
|
+
<span>Subscribers, issues and delivery for the site's email</span>
|
|
4399
|
+
</Link>
|
|
4400
|
+
) : null}
|
|
4401
|
+
{readerPluginEnabled() ? (
|
|
4402
|
+
<Link
|
|
4403
|
+
href={administrationPanelHref("moderation", isDemo)}
|
|
4404
|
+
data-news-desk-admin-nav="moderation"
|
|
4405
|
+
data-active={administrationPanel === "moderation" || undefined}
|
|
4406
|
+
onClick={() => onPanelChange("moderation")}
|
|
4407
|
+
>
|
|
4408
|
+
<strong>Moderation</strong>
|
|
4409
|
+
<span>Reader submissions and comments</span>
|
|
4410
|
+
</Link>
|
|
4411
|
+
) : null}
|
|
4331
4412
|
</nav>}
|
|
4332
4413
|
<div className="news-desk-settings-panel">
|
|
4333
4414
|
{administrationPanel === "signups" ? <SignupEntriesPanel /> : null}
|
|
4415
|
+
{administrationPanel === "newsletter" ? <NewsletterPanel isAdmin={canManageUsers} isDemo={isDemo} /> : null}
|
|
4416
|
+
{administrationPanel === "moderation" ? <ModerationPanel /> : null}
|
|
4417
|
+
{administrationPanel === "editorial-checks" ? <EditorialChecksAdminPanel /> : null}
|
|
4418
|
+
{administrationPanel === "automations" ? <AutomationPanel isDemo={isDemo} /> : null}
|
|
4419
|
+
{administrationPanel === "monitoring" ? <MonitoringPanel isAdmin={canManageUsers} isDemo={isDemo} /> : null}
|
|
4334
4420
|
{administrationPanel === "delegations" ? <AdministrationDelegationsPanel disabled={disabled} /> : null}
|
|
4335
4421
|
{administrationPanel === "users" ? (
|
|
4336
4422
|
<AdministrationUsersPanel
|
|
@@ -5657,7 +5743,7 @@ function DesksDeskView({
|
|
|
5657
5743
|
<div className="news-desk-columns news-desk-columns--administration news-desk-columns--taxonomy" data-news-desk-section="desks">
|
|
5658
5744
|
<div className="news-desk-main-column">
|
|
5659
5745
|
<section className="category-steering-section category-steering-section--lead" aria-labelledby="newsroom-desks-title">
|
|
5660
|
-
<SectionHeader title="News
|
|
5746
|
+
<SectionHeader title="News sections" detail={`${roots.length} root topic sections`} />
|
|
5661
5747
|
<div className="news-desk-desk-list">
|
|
5662
5748
|
{roots.length ? roots.map((root) => {
|
|
5663
5749
|
const rootNode = root.node ?? categoryToCategoryTreeNode(root.category);
|
|
@@ -5677,11 +5763,11 @@ function DesksDeskView({
|
|
|
5677
5763
|
>
|
|
5678
5764
|
<span>{rootNode.shortTitle ?? deriveShortTitle(rootNode.displayName)}</span>
|
|
5679
5765
|
<strong>{rootNode.displayName}</strong>
|
|
5680
|
-
<p>{rootNode.description ?? "No
|
|
5766
|
+
<p>{rootNode.description ?? "No section description yet."}</p>
|
|
5681
5767
|
<small>{referenceCount} refs / {assignmentCount} assignments / {root.subcategorys.length} subtopics / {doctrineStatus.savedCount} of 2 doctrine slots</small>
|
|
5682
5768
|
</Link>
|
|
5683
5769
|
);
|
|
5684
|
-
}) : <EmptyRow label="No root topic
|
|
5770
|
+
}) : <EmptyRow label="No root topic sections are available in the canonical category set" />}
|
|
5685
5771
|
</div>
|
|
5686
5772
|
</section>
|
|
5687
5773
|
|
|
@@ -5702,18 +5788,18 @@ function DesksDeskView({
|
|
|
5702
5788
|
|
|
5703
5789
|
<aside className="news-desk-rail-column">
|
|
5704
5790
|
<section className="category-steering-section" aria-labelledby="desk-index-notes-title">
|
|
5705
|
-
<SectionHeader title="
|
|
5791
|
+
<SectionHeader title="Section rules" detail="Root topics only" />
|
|
5706
5792
|
<div className="news-desk-ledger-list">
|
|
5707
5793
|
<article className="news-desk-ledger-item">
|
|
5708
5794
|
<header>
|
|
5709
|
-
<strong>
|
|
5795
|
+
<strong>Section identity</strong>
|
|
5710
5796
|
<span>Category</span>
|
|
5711
5797
|
</header>
|
|
5712
5798
|
<p>Official name, short title, subtitle, and description stay on the accepted root Category record.</p>
|
|
5713
5799
|
</article>
|
|
5714
5800
|
<article className="news-desk-ledger-item">
|
|
5715
5801
|
<header>
|
|
5716
|
-
<strong>
|
|
5802
|
+
<strong>Section doctrine</strong>
|
|
5717
5803
|
<span>Private Item</span>
|
|
5718
5804
|
</header>
|
|
5719
5805
|
<p>Mission and policies are private doctrine Items tied to the root category lineage.</p>
|
|
@@ -5763,7 +5849,7 @@ function DeskDetailPanel({
|
|
|
5763
5849
|
<section className="category-steering-section news-desk-desk-detail" aria-labelledby="selected-desk-title">
|
|
5764
5850
|
<header className="news-desk-topic-detail__header">
|
|
5765
5851
|
<div>
|
|
5766
|
-
<p className="story-label">News
|
|
5852
|
+
<p className="story-label">News section</p>
|
|
5767
5853
|
<h3 id="selected-desk-title">{rootNode.displayName}</h3>
|
|
5768
5854
|
<span>{rootNode.shortTitle ?? deriveShortTitle(rootNode.displayName)}</span>
|
|
5769
5855
|
</div>
|
|
@@ -5846,7 +5932,7 @@ function CategoryDoctrineEditorCard({
|
|
|
5846
5932
|
<article className="news-desk-doctrine-card" data-news-desk-doctrine={definition.slug}>
|
|
5847
5933
|
<header className="news-desk-doctrine-card__header">
|
|
5848
5934
|
<div>
|
|
5849
|
-
<p className="story-label">
|
|
5935
|
+
<p className="story-label">Section doctrine</p>
|
|
5850
5936
|
<h3>{definition.label}</h3>
|
|
5851
5937
|
</div>
|
|
5852
5938
|
<span>{record ? "Saved record" : "Empty slot"}</span>
|
|
@@ -12211,7 +12297,7 @@ function AssignmentRow({
|
|
|
12211
12297
|
{context ? (
|
|
12212
12298
|
<>
|
|
12213
12299
|
<p className="news-desk-assignment-row__angle">
|
|
12214
|
-
<span>{context.deskTitle ?? context.deskKey ?? "
|
|
12300
|
+
<span>{context.deskTitle ?? context.deskKey ?? "Section"}</span>
|
|
12215
12301
|
{`${context.focusTitle ?? context.focusKey ?? "focus"} / ${context.targetSystemType ?? context.contextProfile ?? "context"}`}
|
|
12216
12302
|
</p>
|
|
12217
12303
|
{context.contextProfile || context.contextTokenBudget ? (
|
|
@@ -12326,7 +12412,7 @@ function normalizeAnalysisReindexMode(value: string | null | undefined): Analysi
|
|
|
12326
12412
|
function formatAnalysisReindexModeLabel(mode: AnalysisReindexMode): string {
|
|
12327
12413
|
if (mode === "online-update") return "Online update - new or changed accepted references";
|
|
12328
12414
|
if (mode === "classifier-retrain") return "Classifier retrain - rebuild topic classifier";
|
|
12329
|
-
if (mode === "scoped-topic-rebuild") return "Scoped topic rebuild - one
|
|
12415
|
+
if (mode === "scoped-topic-rebuild") return "Scoped topic rebuild - one section or focus";
|
|
12330
12416
|
if (mode === "entity-graph-rebuild") return "Entity graph rebuild - generated graph outputs";
|
|
12331
12417
|
return "Generated analysis rebuild - clear and rebuild targeted generated outputs";
|
|
12332
12418
|
}
|
|
@@ -12356,7 +12442,7 @@ function mergeAnalysisCorpora(configuredCorpora: CategorySteeringCorpus[], liveC
|
|
|
12356
12442
|
function analysisReindexModeHelp(mode: AnalysisReindexMode): string {
|
|
12357
12443
|
if (mode === "generated-analysis-rebuild") return "Use this for a full generated-output rebuild for the selected profile. It still creates an assignment only; the worker/operator executes it later.";
|
|
12358
12444
|
if (mode === "classifier-retrain") return "Use this when authoritative labels or accepted references should retrain the semi-supervised topic classifier.";
|
|
12359
|
-
if (mode === "scoped-topic-rebuild") return "Use this when proposals for a
|
|
12445
|
+
if (mode === "scoped-topic-rebuild") return "Use this when proposals for a section or focus topic should be regenerated from the accepted taxonomy plus steering feedback.";
|
|
12360
12446
|
if (mode === "entity-graph-rebuild") return "Use this when generated ontology/entity graph records should be rebuilt from accepted references.";
|
|
12361
12447
|
return "Use this for incremental processing of new or changed accepted references without clearing broader generated outputs.";
|
|
12362
12448
|
}
|
|
@@ -12794,9 +12880,20 @@ function signupPluginEnabled(): boolean {
|
|
|
12794
12880
|
return pluginSettings(amplifyOutputs as PluginOutputs, "signup") !== null;
|
|
12795
12881
|
}
|
|
12796
12882
|
|
|
12797
|
-
|
|
12798
|
-
|
|
12883
|
+
/** The Newsletter panel exists when the site enabled the plugin; `?demo=1` shows it with fixture data so it can be seen and tested. */
|
|
12884
|
+
function newsletterPluginEnabled(demo = false): boolean {
|
|
12885
|
+
return demo || pluginSettings(amplifyOutputs as PluginOutputs, "newsletter") !== null;
|
|
12886
|
+
}
|
|
12887
|
+
|
|
12888
|
+
function readerPluginEnabled(): boolean {
|
|
12889
|
+
return pluginSettings(amplifyOutputs as PluginOutputs, "reader-steering") !== null;
|
|
12890
|
+
}
|
|
12891
|
+
|
|
12892
|
+
function normalizeAdministrationPanel(value: string | null | undefined, demo = false): AdministrationPanel {
|
|
12893
|
+
if (value === "policies" || value === "sections" || value === "procedures" || value === "automations" || value === "delegations" || value === "editorial-checks" || value === "monitoring") return value;
|
|
12799
12894
|
if (value === "signups" && signupPluginEnabled()) return value;
|
|
12895
|
+
if (value === "newsletter" && newsletterPluginEnabled(demo)) return value;
|
|
12896
|
+
if (value === "moderation" && readerPluginEnabled()) return value;
|
|
12800
12897
|
return "users";
|
|
12801
12898
|
}
|
|
12802
12899
|
|
|
@@ -12995,7 +13092,7 @@ function formatDeskSectionHeadline(section: NewsDeskTab): string {
|
|
|
12995
13092
|
|
|
12996
13093
|
function formatDeskSectionLede(section: NewsDeskTab): string {
|
|
12997
13094
|
if (section === "search") return "Search the newsroom knowledge base with semantic and ontology context.";
|
|
12998
|
-
if (section === "desks") return "The
|
|
13095
|
+
if (section === "desks") return "The sections and topic categories that organize coverage, with each section's mission and policies.";
|
|
12999
13096
|
if (section === "topics") return "Review suggested changes to the subject areas the newsroom covers.";
|
|
13000
13097
|
if (section === "concepts") return "Browse people, organizations, places, and ideas found in the source material.";
|
|
13001
13098
|
if (section === "references") return "Review source materials before they become usable evidence.";
|