@anthusai/papyrus 2.0.0-next.9 → 2.0.0-next.90
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 +151 -61
- package/amplify/data/resource.ts +157 -61
- package/amplify/data/schema.js +2096 -1980
- package/amplify/data/schema.ts +198 -69
- package/amplify/functions/assignment-action/data-access.js +2 -0
- package/amplify/functions/assignment-action/data-access.ts +2 -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 +61 -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/{plugins/editorial-checks/function → functions/editorial-checks}/handler.py +3 -3
- package/amplify/functions/editorial-checks/requirements.txt +1 -0
- package/amplify/{plugins/editorial-checks/function → functions/editorial-checks}/resource.js +7 -7
- package/amplify/{plugins/editorial-checks/function → functions/editorial-checks}/resource.ts +7 -7
- package/amplify/functions/editorial-checks/schema.js +122 -0
- package/amplify/{plugins → functions}/editorial-checks/schema.ts +40 -12
- package/amplify/functions/editorial-checks/wire.js +53 -0
- package/amplify/functions/editorial-checks/wire.ts +61 -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 +17 -0
- package/amplify/functions/monitoring-view/schema.ts +19 -0
- package/amplify/functions/monitoring-view/wire.js +37 -0
- package/amplify/functions/monitoring-view/wire.ts +47 -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 -2
- package/amplify/plugins/registry.ts +4 -2
- 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.ts +18 -1
- package/amplify/site-backend-names.js +4 -2
- package/amplify/site-backend-names.ts +4 -2
- package/amplify/site-backend.js +45 -3
- package/amplify/site-backend.ts +51 -3
- 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/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/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 +38 -13
- package/components/moderation-panel.tsx +248 -0
- package/components/monitoring-overview-view.tsx +241 -0
- package/components/monitoring-panel.tsx +40 -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 +11 -11
- package/components/newsroom-articles-view.tsx +6 -6
- package/components/newsroom-assignment-detail.tsx +6 -6
- package/components/newsroom-board-view.tsx +8 -3
- package/components/newsroom-curation-bootstrap.tsx +45 -0
- package/components/newsroom-ops-overview.tsx +26 -96
- package/components/newsroom-ops-shell.tsx +2 -2
- package/components/newsroom-organizer.css +33 -0
- package/components/newsroom-overview-skeleton.tsx +25 -0
- package/components/newsroom-references-view.tsx +192 -49
- package/components/notification-center.tsx +277 -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 +58 -19
- package/components/reference-cyclotron-suggestion.tsx +10 -6
- package/components/reference-priming.tsx +14 -10
- package/components/reference-relevance-review.tsx +3 -3
- package/components/reference-section-suggestion.tsx +1 -1
- package/components/topic-steering-workspace.tsx +237 -158
- package/components/use-editorial-checks.ts +12 -10
- package/infra/amplify-app-shell.js +94 -16
- package/infra/amplify-app-shell.ts +106 -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 +88 -6
- package/infra/site-config.ts +134 -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 +4 -4
- package/lib/editorial-checks-backend.ts +1 -1
- package/lib/editorial-checks-client.ts +19 -1
- package/lib/editorial-checks-demo.ts +2 -2
- package/lib/editorial-checks-settings.ts +3 -0
- package/lib/editorial-checks.ts +8 -11
- package/lib/editorial-preview.ts +5 -5
- package/lib/monitoring-client.ts +29 -0
- package/lib/monitoring-overview-fixture.ts +51 -0
- package/lib/monitoring-overview.ts +145 -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-demo-dashboard.ts +1 -1
- package/lib/newsroom-nav.ts +1 -1
- package/lib/newsroom-organizer-nav.ts +2 -1
- package/lib/prospectus-session.ts +15 -14
- package/lib/prospectus-sign-in-routes.ts +105 -20
- 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 +2 -2
- package/lib/review-client.ts +117 -0
- package/lib/review-fixture.ts +45 -0
- package/lib/review-requests.ts +244 -0
- package/lib/semantic-graph.ts +2 -0
- package/lib/site-brand-tenant.ts +11 -6
- package/lib/site-brand.ts +6 -3
- package/lib/site-origin.ts +67 -0
- package/lib/use-reference-review-data.ts +44 -0
- package/middleware.ts +14 -3
- package/package.json +56 -3
- package/routes.manifest.json +215 -2
- package/amplify/plugins/editorial-checks/function/requirements.txt +0 -1
- package/amplify/plugins/editorial-checks/papyrus.plugin.js +0 -71
- package/amplify/plugins/editorial-checks/papyrus.plugin.ts +0 -87
- package/amplify/plugins/editorial-checks/schema.js +0 -94
|
@@ -14,6 +14,10 @@ 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
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";
|
|
17
21
|
import { SignupEntriesPanel } from "./signup-entries-panel";
|
|
18
22
|
import { pluginSettings, type PluginOutputs } from "../lib/plugin-settings";
|
|
19
23
|
import { generateClient } from "aws-amplify/data";
|
|
@@ -36,6 +40,7 @@ import {
|
|
|
36
40
|
loadEditorReferencesData,
|
|
37
41
|
loadEditorProcedureData,
|
|
38
42
|
loadEditorSemanticRelationsData,
|
|
43
|
+
loadEditorReferenceReviewDetails,
|
|
39
44
|
loadEditionForumThreads,
|
|
40
45
|
loadNewsroomAssignmentPage,
|
|
41
46
|
loadNewsroomMessagePage,
|
|
@@ -89,6 +94,7 @@ import { ReferenceSourcePreview } from "./reference-source-preview";
|
|
|
89
94
|
import type { ReaderAuthSnapshot } from "./reader-auth-state";
|
|
90
95
|
import { NewsDeskAccessGate } from "./newsroom-access-gate";
|
|
91
96
|
import { NewsroomOpsOverview } from "./newsroom-ops-overview";
|
|
97
|
+
import { NewsroomCurationBootstrap } from "./newsroom-curation-bootstrap";
|
|
92
98
|
import { NewsroomReferencesView } from "./newsroom-references-view";
|
|
93
99
|
import { NewsroomAssignmentsView } from "./newsroom-assignments-view";
|
|
94
100
|
import { NewsroomTopicsView } from "./newsroom-topics-view";
|
|
@@ -162,6 +168,9 @@ import {
|
|
|
162
168
|
} from "../lib/reference-policy";
|
|
163
169
|
import { isLocalPreviewEnabled } from "../lib/local-preview";
|
|
164
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";
|
|
165
174
|
import { delegatedCurationsByReference, referencesWithHumanLatestCuration, type ShadowAgreement } from "../lib/cyclotron-suggestions";
|
|
166
175
|
import { createLocalPreviewCyclotronFixtures } from "../lib/local-preview-seed";
|
|
167
176
|
import { createLocalPreviewSectionFixtures } from "../lib/local-preview-section-fixtures";
|
|
@@ -247,7 +256,7 @@ type AssignmentAction = "claim" | "release" | "complete" | "cancel" | "reopen" |
|
|
|
247
256
|
type ReportingPacketReviewDecision = "select" | "merge" | "brief" | "hold" | "kill";
|
|
248
257
|
type AssignmentDeskViewMode = "queue" | "budget";
|
|
249
258
|
type UserRoleAction = "grant" | "revoke";
|
|
250
|
-
type AdministrationPanel = "users" | "policies" | "sections" | "procedures" | "delegations" | "signups" | "editorial-checks";
|
|
259
|
+
type AdministrationPanel = "users" | "policies" | "sections" | "procedures" | "automations" | "delegations" | "signups" | "newsletter" | "moderation" | "editorial-checks" | "monitoring";
|
|
251
260
|
export type NewsDeskTab = "overview" | "desks" | "topics" | "concepts" | "references" | "messages" | "assignments" | "administration" | "search";
|
|
252
261
|
type LexicalRuleScope = "publication" | "corpus" | "classifier" | "category";
|
|
253
262
|
type AnalysisReindexMode = "online-update" | "classifier-retrain" | "scoped-topic-rebuild" | "entity-graph-rebuild" | "generated-analysis-rebuild";
|
|
@@ -658,14 +667,14 @@ export function NewsDeskWorkspace({
|
|
|
658
667
|
editorShellReady
|
|
659
668
|
initialSelection={initialSelection}
|
|
660
669
|
initialTab={initialTab}
|
|
661
|
-
authState={{ status: "signedIn", label: "Demo
|
|
670
|
+
authState={{ status: "signedIn", label: "Demo section" }}
|
|
662
671
|
isRefreshing={false}
|
|
663
672
|
shellError={null}
|
|
664
673
|
/>
|
|
665
674
|
);
|
|
666
675
|
}
|
|
667
676
|
|
|
668
|
-
if (session && sessionDashboard) {
|
|
677
|
+
if (session && sessionDashboard && session.shell.phase !== "loadingDesk") {
|
|
669
678
|
return (
|
|
670
679
|
<NewsDeskDashboard
|
|
671
680
|
analysisProfiles={analysisProfiles}
|
|
@@ -879,7 +888,7 @@ function NewsDeskDashboard({
|
|
|
879
888
|
const [mergeSelection, setMergeSelection] = useState<MergeSelection | null>(null);
|
|
880
889
|
const [isPending, startTransition] = useTransition();
|
|
881
890
|
const controlsDisabled = isPending || !canEdit;
|
|
882
|
-
const initialAdministrationPanel = normalizeAdministrationPanel(initialSelection.panel);
|
|
891
|
+
const initialAdministrationPanel = normalizeAdministrationPanel(initialSelection.panel, Boolean(dashboard.isDemo));
|
|
883
892
|
const [administrationPanel, setAdministrationPanel] = useState<AdministrationPanel>(initialAdministrationPanel);
|
|
884
893
|
const [doctrineDrafts, setDoctrineDrafts] = useState<DoctrineEditorState>(() => buildDoctrineEditorState(dashboard.doctrineRecords));
|
|
885
894
|
const [loadedSections, setLoadedSections] = useState<Record<string, boolean>>({
|
|
@@ -897,6 +906,11 @@ function NewsDeskDashboard({
|
|
|
897
906
|
const [referencesRealtimeStatus, setReferencesRealtimeStatus] = useState<RealtimeSubscriptionStatus>("idle");
|
|
898
907
|
const [referencesRealtimeError, setReferencesRealtimeError] = useState<string | null>(null);
|
|
899
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]);
|
|
900
914
|
|
|
901
915
|
useEffect(() => {
|
|
902
916
|
referencesRef.current = references;
|
|
@@ -1120,8 +1134,8 @@ function NewsDeskDashboard({
|
|
|
1120
1134
|
}, [dashboard.procedureDefinitions, dashboard.procedureRuns, dashboard.procedureVersions]);
|
|
1121
1135
|
|
|
1122
1136
|
useEffect(() => {
|
|
1123
|
-
setAdministrationPanel(normalizeAdministrationPanel(initialSelection.panel));
|
|
1124
|
-
}, [initialSelection.panel]);
|
|
1137
|
+
setAdministrationPanel(normalizeAdministrationPanel(initialSelection.panel, Boolean(dashboard.isDemo)));
|
|
1138
|
+
}, [initialSelection.panel, dashboard.isDemo]);
|
|
1125
1139
|
|
|
1126
1140
|
useEffect(() => {
|
|
1127
1141
|
if (activeTab !== "administration") return;
|
|
@@ -1226,17 +1240,6 @@ function NewsDeskDashboard({
|
|
|
1226
1240
|
if (dashboard.isDemo) return;
|
|
1227
1241
|
let active = true;
|
|
1228
1242
|
|
|
1229
|
-
if (activeTab === "messages" && !loadedSections.messages) {
|
|
1230
|
-
setLoadedSections((current) => ({ ...current, messages: true }));
|
|
1231
|
-
void loadEditorMessagesData()
|
|
1232
|
-
.then((nextMessages) => {
|
|
1233
|
-
if (active) setMessages(nextMessages);
|
|
1234
|
-
})
|
|
1235
|
-
.catch((error) => {
|
|
1236
|
-
if (active) setActionState({ id: "messages-load", message: error instanceof Error ? error.message : "messages load failed", tone: "error" });
|
|
1237
|
-
});
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
1243
|
if (activeTab === "assignments" && !loadedSections.assignments) {
|
|
1241
1244
|
setLoadedSections((current) => ({ ...current, assignments: true }));
|
|
1242
1245
|
void loadEditorAssignmentsData()
|
|
@@ -1264,23 +1267,6 @@ function NewsDeskDashboard({
|
|
|
1264
1267
|
});
|
|
1265
1268
|
}
|
|
1266
1269
|
|
|
1267
|
-
if ((activeTab === "assignments" || activeTab === "references" || activeTab === "messages") && !loadedSections.semanticRelations) {
|
|
1268
|
-
setLoadedSections((current) => ({ ...current, semanticRelations: true }));
|
|
1269
|
-
void loadEditorSemanticRelationsData()
|
|
1270
|
-
.then((relations) => {
|
|
1271
|
-
if (active) setSemanticRelations(relations);
|
|
1272
|
-
})
|
|
1273
|
-
.catch(() => {
|
|
1274
|
-
if (active) setSemanticRelations([]);
|
|
1275
|
-
});
|
|
1276
|
-
if (!loadedSections.messages) {
|
|
1277
|
-
setLoadedSections((current) => ({ ...current, messages: true }));
|
|
1278
|
-
void loadEditorMessagesData().then((nextMessages) => {
|
|
1279
|
-
if (active) setMessages(nextMessages);
|
|
1280
|
-
}).catch(() => undefined);
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
1270
|
if ((activeTab === "topics" || activeTab === "desks" || activeTab === "concepts" || activeTab === "administration") && !loadedSections.fullDashboard) {
|
|
1285
1271
|
setLoadedSections((current) => ({ ...current, fullDashboard: true }));
|
|
1286
1272
|
void loadEditorFullNewsDeskDashboard({ isAdmin: Boolean(dashboard.canManageUsers) })
|
|
@@ -1335,6 +1321,37 @@ function NewsDeskDashboard({
|
|
|
1335
1321
|
refreshNewsroomSections,
|
|
1336
1322
|
]);
|
|
1337
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
|
+
|
|
1338
1355
|
const applyReferenceRecord = useCallback((nextReference: ReferenceRecord) => {
|
|
1339
1356
|
const { nextRecords, nextRecord, previousRecord } = upsertReferenceRecords(referencesRef.current, nextReference);
|
|
1340
1357
|
referencesRef.current = nextRecords;
|
|
@@ -1589,96 +1606,98 @@ function NewsDeskDashboard({
|
|
|
1589
1606
|
reasonCode?: ReferenceRejectionReasonCode | null,
|
|
1590
1607
|
relevance?: { decisionRelationId: string; shareable: boolean },
|
|
1591
1608
|
sectionId?: string | null,
|
|
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
|
-
|
|
1660
|
-
note: note?.trim() || undefined,
|
|
1661
|
-
reasonCode: action === "reject" ? reasonCode ?? undefined : undefined,
|
|
1662
|
-
decisionRelationId: relevance?.decisionRelationId,
|
|
1663
|
-
shareable: relevance ? relevance.shareable : undefined,
|
|
1664
|
-
sectionId: action === "accept" ? sectionId ?? undefined : undefined,
|
|
1665
|
-
},
|
|
1666
|
-
{ authMode: USER_POOL_AUTH_MODE },
|
|
1667
|
-
);
|
|
1668
|
-
const review = assertReferenceReviewMutationSucceeded(response, reference.id);
|
|
1669
|
-
const status = review.status ?? nextStatus;
|
|
1670
|
-
const now = new Date().toISOString();
|
|
1671
|
-
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,
|
|
1672
1677
|
actorLabel: authState.label,
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
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
|
+
}
|
|
1682
1701
|
});
|
|
1683
1702
|
}
|
|
1684
1703
|
|
|
@@ -2999,7 +3018,7 @@ function NewsDeskDashboard({
|
|
|
2999
3018
|
return entries;
|
|
3000
3019
|
}, [summaryStatus, tabCounts]);
|
|
3001
3020
|
const opsPageTitle = activeTab === "overview"
|
|
3002
|
-
? "
|
|
3021
|
+
? "Notification Center"
|
|
3003
3022
|
: activeTab === "administration" && administrationPanel === "sections"
|
|
3004
3023
|
? "Sections"
|
|
3005
3024
|
: formatDeskSectionHeadline(activeTab);
|
|
@@ -3057,9 +3076,11 @@ function NewsDeskDashboard({
|
|
|
3057
3076
|
|
|
3058
3077
|
{activeTab === "overview" ? (
|
|
3059
3078
|
<NewsroomOpsOverview
|
|
3079
|
+
actorLabel={authState.label}
|
|
3060
3080
|
assignments={assignments}
|
|
3081
|
+
decisions={relevanceDecisions}
|
|
3061
3082
|
demo={Boolean(dashboard.isDemo)}
|
|
3062
|
-
|
|
3083
|
+
humanCuratedReferenceLineageIds={humanCuratedReferenceLineageIds}
|
|
3063
3084
|
newsroomSections={newsroomSections}
|
|
3064
3085
|
references={references}
|
|
3065
3086
|
/>
|
|
@@ -3115,10 +3136,11 @@ function NewsDeskDashboard({
|
|
|
3115
3136
|
/>
|
|
3116
3137
|
) : null}
|
|
3117
3138
|
{activeTab === "references" ? (
|
|
3139
|
+
<NewsroomCurationBootstrap enabled={!dashboard.isDemo}>
|
|
3118
3140
|
<NewsroomReferencesView
|
|
3119
3141
|
demo={Boolean(dashboard.isDemo)}
|
|
3120
3142
|
disabled={controlsDisabled}
|
|
3121
|
-
initialReferenceLineageId={
|
|
3143
|
+
initialReferenceLineageId={selectedReviewLineageId}
|
|
3122
3144
|
cyclotronStatus={cyclotronStatus}
|
|
3123
3145
|
cyclotronPriming={{
|
|
3124
3146
|
labels: primingLabels,
|
|
@@ -3130,8 +3152,8 @@ function NewsDeskDashboard({
|
|
|
3130
3152
|
},
|
|
3131
3153
|
}}
|
|
3132
3154
|
decisions={relevanceDecisions}
|
|
3133
|
-
humanCuratedReferenceLineageIds={humanCuratedReferenceLineageIds}
|
|
3134
|
-
delegatedCurations={delegatedCurations}
|
|
3155
|
+
humanCuratedReferenceLineageIds={selectedReviewIsCurrent && predictionState !== "ready" ? undefined : humanCuratedReferenceLineageIds}
|
|
3156
|
+
delegatedCurations={selectedReviewIsCurrent && predictionState !== "ready" ? undefined : delegatedCurations}
|
|
3135
3157
|
shadowAgreement={shadowAgreement}
|
|
3136
3158
|
onRequestReviewRate={relevanceCyclotronId ? async (choice) => {
|
|
3137
3159
|
const request = buildReviewRateRequest(choice, authState.label);
|
|
@@ -3144,14 +3166,23 @@ function NewsDeskDashboard({
|
|
|
3144
3166
|
curation.note ?? undefined,
|
|
3145
3167
|
normalizeReferenceRejectionReasonCode(curation.reasonCode),
|
|
3146
3168
|
{ decisionRelationId: curation.decisionRelationId, shareable: curation.shareable },
|
|
3169
|
+
curation.sectionId,
|
|
3147
3170
|
)}
|
|
3148
3171
|
sections={sectionChoices}
|
|
3149
3172
|
sectionSuggestions={sectionSuggestions}
|
|
3150
3173
|
sectionAgreement={siteSectionAgreement}
|
|
3151
|
-
|
|
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)}
|
|
3152
3182
|
referenceAttachments={referenceAttachments}
|
|
3153
3183
|
references={references}
|
|
3154
3184
|
/>
|
|
3185
|
+
</NewsroomCurationBootstrap>
|
|
3155
3186
|
) : null}
|
|
3156
3187
|
{activeTab === "messages" ? (
|
|
3157
3188
|
<MessagesDeskView
|
|
@@ -3872,7 +3903,7 @@ function NewsroomSectionRail({
|
|
|
3872
3903
|
<aside className="newsroom-section-rail" data-newsroom-section-rail aria-labelledby="newsroom-section-rail-title" ref={railRef}>
|
|
3873
3904
|
<header className="newsroom-section-rail__header">
|
|
3874
3905
|
<p className="story-label">Sections</p>
|
|
3875
|
-
<h2 id="newsroom-section-rail-title">Section
|
|
3906
|
+
<h2 id="newsroom-section-rail-title">Section</h2>
|
|
3876
3907
|
</header>
|
|
3877
3908
|
<div className="newsroom-section-rail__body">
|
|
3878
3909
|
{canonicalSections.length ? (
|
|
@@ -4309,6 +4340,15 @@ function AdministrationDeskView({
|
|
|
4309
4340
|
<strong>Procedures</strong>
|
|
4310
4341
|
<span>Procedure registry and versioned Tactus code</span>
|
|
4311
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>
|
|
4312
4352
|
<Link
|
|
4313
4353
|
href={administrationPanelHref("delegations", isDemo)}
|
|
4314
4354
|
data-news-desk-admin-nav="delegations"
|
|
@@ -4318,17 +4358,24 @@ function AdministrationDeskView({
|
|
|
4318
4358
|
<strong>Agent delegations</strong>
|
|
4319
4359
|
<span>Let an agent curate References for you</span>
|
|
4320
4360
|
</Link>
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
>
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
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>
|
|
4332
4379
|
{signupPluginEnabled() ? (
|
|
4333
4380
|
<Link
|
|
4334
4381
|
href={administrationPanelHref("signups", isDemo)}
|
|
@@ -4340,10 +4387,36 @@ function AdministrationDeskView({
|
|
|
4340
4387
|
<span>Addresses from the site's signup forms</span>
|
|
4341
4388
|
</Link>
|
|
4342
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}
|
|
4343
4412
|
</nav>}
|
|
4344
4413
|
<div className="news-desk-settings-panel">
|
|
4345
4414
|
{administrationPanel === "signups" ? <SignupEntriesPanel /> : null}
|
|
4415
|
+
{administrationPanel === "newsletter" ? <NewsletterPanel isAdmin={canManageUsers} isDemo={isDemo} /> : null}
|
|
4416
|
+
{administrationPanel === "moderation" ? <ModerationPanel /> : null}
|
|
4346
4417
|
{administrationPanel === "editorial-checks" ? <EditorialChecksAdminPanel /> : null}
|
|
4418
|
+
{administrationPanel === "automations" ? <AutomationPanel isDemo={isDemo} /> : null}
|
|
4419
|
+
{administrationPanel === "monitoring" ? <MonitoringPanel isAdmin={canManageUsers} isDemo={isDemo} /> : null}
|
|
4347
4420
|
{administrationPanel === "delegations" ? <AdministrationDelegationsPanel disabled={disabled} /> : null}
|
|
4348
4421
|
{administrationPanel === "users" ? (
|
|
4349
4422
|
<AdministrationUsersPanel
|
|
@@ -5670,7 +5743,7 @@ function DesksDeskView({
|
|
|
5670
5743
|
<div className="news-desk-columns news-desk-columns--administration news-desk-columns--taxonomy" data-news-desk-section="desks">
|
|
5671
5744
|
<div className="news-desk-main-column">
|
|
5672
5745
|
<section className="category-steering-section category-steering-section--lead" aria-labelledby="newsroom-desks-title">
|
|
5673
|
-
<SectionHeader title="News
|
|
5746
|
+
<SectionHeader title="News sections" detail={`${roots.length} root topic sections`} />
|
|
5674
5747
|
<div className="news-desk-desk-list">
|
|
5675
5748
|
{roots.length ? roots.map((root) => {
|
|
5676
5749
|
const rootNode = root.node ?? categoryToCategoryTreeNode(root.category);
|
|
@@ -5690,11 +5763,11 @@ function DesksDeskView({
|
|
|
5690
5763
|
>
|
|
5691
5764
|
<span>{rootNode.shortTitle ?? deriveShortTitle(rootNode.displayName)}</span>
|
|
5692
5765
|
<strong>{rootNode.displayName}</strong>
|
|
5693
|
-
<p>{rootNode.description ?? "No
|
|
5766
|
+
<p>{rootNode.description ?? "No section description yet."}</p>
|
|
5694
5767
|
<small>{referenceCount} refs / {assignmentCount} assignments / {root.subcategorys.length} subtopics / {doctrineStatus.savedCount} of 2 doctrine slots</small>
|
|
5695
5768
|
</Link>
|
|
5696
5769
|
);
|
|
5697
|
-
}) : <EmptyRow label="No root topic
|
|
5770
|
+
}) : <EmptyRow label="No root topic sections are available in the canonical category set" />}
|
|
5698
5771
|
</div>
|
|
5699
5772
|
</section>
|
|
5700
5773
|
|
|
@@ -5715,18 +5788,18 @@ function DesksDeskView({
|
|
|
5715
5788
|
|
|
5716
5789
|
<aside className="news-desk-rail-column">
|
|
5717
5790
|
<section className="category-steering-section" aria-labelledby="desk-index-notes-title">
|
|
5718
|
-
<SectionHeader title="
|
|
5791
|
+
<SectionHeader title="Section rules" detail="Root topics only" />
|
|
5719
5792
|
<div className="news-desk-ledger-list">
|
|
5720
5793
|
<article className="news-desk-ledger-item">
|
|
5721
5794
|
<header>
|
|
5722
|
-
<strong>
|
|
5795
|
+
<strong>Section identity</strong>
|
|
5723
5796
|
<span>Category</span>
|
|
5724
5797
|
</header>
|
|
5725
5798
|
<p>Official name, short title, subtitle, and description stay on the accepted root Category record.</p>
|
|
5726
5799
|
</article>
|
|
5727
5800
|
<article className="news-desk-ledger-item">
|
|
5728
5801
|
<header>
|
|
5729
|
-
<strong>
|
|
5802
|
+
<strong>Section doctrine</strong>
|
|
5730
5803
|
<span>Private Item</span>
|
|
5731
5804
|
</header>
|
|
5732
5805
|
<p>Mission and policies are private doctrine Items tied to the root category lineage.</p>
|
|
@@ -5776,7 +5849,7 @@ function DeskDetailPanel({
|
|
|
5776
5849
|
<section className="category-steering-section news-desk-desk-detail" aria-labelledby="selected-desk-title">
|
|
5777
5850
|
<header className="news-desk-topic-detail__header">
|
|
5778
5851
|
<div>
|
|
5779
|
-
<p className="story-label">News
|
|
5852
|
+
<p className="story-label">News section</p>
|
|
5780
5853
|
<h3 id="selected-desk-title">{rootNode.displayName}</h3>
|
|
5781
5854
|
<span>{rootNode.shortTitle ?? deriveShortTitle(rootNode.displayName)}</span>
|
|
5782
5855
|
</div>
|
|
@@ -5859,7 +5932,7 @@ function CategoryDoctrineEditorCard({
|
|
|
5859
5932
|
<article className="news-desk-doctrine-card" data-news-desk-doctrine={definition.slug}>
|
|
5860
5933
|
<header className="news-desk-doctrine-card__header">
|
|
5861
5934
|
<div>
|
|
5862
|
-
<p className="story-label">
|
|
5935
|
+
<p className="story-label">Section doctrine</p>
|
|
5863
5936
|
<h3>{definition.label}</h3>
|
|
5864
5937
|
</div>
|
|
5865
5938
|
<span>{record ? "Saved record" : "Empty slot"}</span>
|
|
@@ -12224,7 +12297,7 @@ function AssignmentRow({
|
|
|
12224
12297
|
{context ? (
|
|
12225
12298
|
<>
|
|
12226
12299
|
<p className="news-desk-assignment-row__angle">
|
|
12227
|
-
<span>{context.deskTitle ?? context.deskKey ?? "
|
|
12300
|
+
<span>{context.deskTitle ?? context.deskKey ?? "Section"}</span>
|
|
12228
12301
|
{`${context.focusTitle ?? context.focusKey ?? "focus"} / ${context.targetSystemType ?? context.contextProfile ?? "context"}`}
|
|
12229
12302
|
</p>
|
|
12230
12303
|
{context.contextProfile || context.contextTokenBudget ? (
|
|
@@ -12339,7 +12412,7 @@ function normalizeAnalysisReindexMode(value: string | null | undefined): Analysi
|
|
|
12339
12412
|
function formatAnalysisReindexModeLabel(mode: AnalysisReindexMode): string {
|
|
12340
12413
|
if (mode === "online-update") return "Online update - new or changed accepted references";
|
|
12341
12414
|
if (mode === "classifier-retrain") return "Classifier retrain - rebuild topic classifier";
|
|
12342
|
-
if (mode === "scoped-topic-rebuild") return "Scoped topic rebuild - one
|
|
12415
|
+
if (mode === "scoped-topic-rebuild") return "Scoped topic rebuild - one section or focus";
|
|
12343
12416
|
if (mode === "entity-graph-rebuild") return "Entity graph rebuild - generated graph outputs";
|
|
12344
12417
|
return "Generated analysis rebuild - clear and rebuild targeted generated outputs";
|
|
12345
12418
|
}
|
|
@@ -12369,7 +12442,7 @@ function mergeAnalysisCorpora(configuredCorpora: CategorySteeringCorpus[], liveC
|
|
|
12369
12442
|
function analysisReindexModeHelp(mode: AnalysisReindexMode): string {
|
|
12370
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.";
|
|
12371
12444
|
if (mode === "classifier-retrain") return "Use this when authoritative labels or accepted references should retrain the semi-supervised topic classifier.";
|
|
12372
|
-
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.";
|
|
12373
12446
|
if (mode === "entity-graph-rebuild") return "Use this when generated ontology/entity graph records should be rebuilt from accepted references.";
|
|
12374
12447
|
return "Use this for incremental processing of new or changed accepted references without clearing broader generated outputs.";
|
|
12375
12448
|
}
|
|
@@ -12807,14 +12880,20 @@ function signupPluginEnabled(): boolean {
|
|
|
12807
12880
|
return pluginSettings(amplifyOutputs as PluginOutputs, "signup") !== null;
|
|
12808
12881
|
}
|
|
12809
12882
|
|
|
12810
|
-
|
|
12811
|
-
|
|
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;
|
|
12812
12890
|
}
|
|
12813
12891
|
|
|
12814
|
-
function normalizeAdministrationPanel(value: string | null | undefined): AdministrationPanel {
|
|
12815
|
-
if (value === "policies" || value === "sections" || value === "procedures" || value === "delegations") return value;
|
|
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;
|
|
12816
12894
|
if (value === "signups" && signupPluginEnabled()) return value;
|
|
12817
|
-
if (value === "
|
|
12895
|
+
if (value === "newsletter" && newsletterPluginEnabled(demo)) return value;
|
|
12896
|
+
if (value === "moderation" && readerPluginEnabled()) return value;
|
|
12818
12897
|
return "users";
|
|
12819
12898
|
}
|
|
12820
12899
|
|
|
@@ -13013,7 +13092,7 @@ function formatDeskSectionHeadline(section: NewsDeskTab): string {
|
|
|
13013
13092
|
|
|
13014
13093
|
function formatDeskSectionLede(section: NewsDeskTab): string {
|
|
13015
13094
|
if (section === "search") return "Search the newsroom knowledge base with semantic and ontology context.";
|
|
13016
|
-
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.";
|
|
13017
13096
|
if (section === "topics") return "Review suggested changes to the subject areas the newsroom covers.";
|
|
13018
13097
|
if (section === "concepts") return "Browse people, organizations, places, and ideas found in the source material.";
|
|
13019
13098
|
if (section === "references") return "Review source materials before they become usable evidence.";
|