@scalemule/news-publication 0.0.43 → 0.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/article-blocks-DsabIDmH.d.cts +91 -0
- package/dist/article-blocks-DsabIDmH.d.ts +91 -0
- package/dist/{chunk-DC6RMIYL.js → chunk-2IYKWGVM.js} +1 -1
- package/dist/{chunk-C7JTEHTH.js → chunk-57YVL6BD.js} +1 -1
- package/dist/{chunk-XDGBMMLD.js → chunk-72PKW2HM.js} +1 -1
- package/dist/{chunk-VRDUSIVG.js → chunk-GVLJ3HAI.js} +4 -2
- package/dist/{chunk-EVAGI7C5.js → chunk-OIEO2YVG.js} +1 -1
- package/dist/chunk-OISLCYER.js +235 -0
- package/dist/chunk-UTBV6JJX.js +387 -0
- package/dist/cookie-consent-banner.cjs +38 -16
- package/dist/cookie-consent-banner.js +2 -2
- package/dist/cookie-settings-view.cjs +38 -16
- package/dist/cookie-settings-view.js +2 -2
- package/dist/index.cjs +382 -21
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +11 -9
- package/dist/network-bar.cjs +38 -16
- package/dist/network-bar.js +2 -2
- package/dist/network-copyright.cjs +43 -20
- package/dist/network-copyright.js +2 -2
- package/dist/network.cjs +138 -18
- package/dist/network.d.cts +20 -1
- package/dist/network.d.ts +20 -1
- package/dist/network.js +1 -1
- package/dist/snapshot-file.cjs +1 -1
- package/dist/snapshot-file.js +1 -1
- package/dist/story-review.cjs +890 -537
- package/dist/story-review.d.cts +11 -2
- package/dist/story-review.d.ts +11 -2
- package/dist/story-review.js +703 -537
- package/package.json +1 -1
- package/story-review.css +174 -0
- package/dist/chunk-56TU57OO.js +0 -268
package/dist/story-review.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { parseDocumentBlocks, formatArtworkCaption } from './chunk-OISLCYER.js';
|
|
2
3
|
import { useState, useRef, useEffect } from 'react';
|
|
3
4
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
5
|
|
|
@@ -397,15 +398,27 @@ function StoryReview({
|
|
|
397
398
|
setRights(false);
|
|
398
399
|
setPanel("media");
|
|
399
400
|
}
|
|
401
|
+
function openCorrection(photo) {
|
|
402
|
+
const title = photo.artwork_title || photo.caption || "Photograph";
|
|
403
|
+
setPanel("changes");
|
|
404
|
+
drafts.set("changes", {
|
|
405
|
+
...drafts.entries.changes?.data,
|
|
406
|
+
correctionKind: "Correct a detail",
|
|
407
|
+
message: drafts.entries.changes?.data.message || `Correction regarding \u201C${title}\u201D: `
|
|
408
|
+
});
|
|
409
|
+
}
|
|
400
410
|
useEffect(() => {
|
|
401
411
|
if (panel !== "article") {
|
|
402
|
-
responseRef.current?.
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
412
|
+
responseRef.current?.focus();
|
|
413
|
+
const handleKeyDown = (e) => {
|
|
414
|
+
if (e.key === "Escape" && !busy) {
|
|
415
|
+
setPanel("article");
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
419
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
407
420
|
}
|
|
408
|
-
}, [panel]);
|
|
421
|
+
}, [panel, busy]);
|
|
409
422
|
const emptyMediaInfo = { caption: "", who_is_pictured: "", creator: "", when_taken: "", where_taken: "", credit: "", alt: "" };
|
|
410
423
|
const drafts = useReviewDrafts(identity, review?.identity_required ? void 0 : review?.revision.id, review?.response_drafts, request);
|
|
411
424
|
const currentDraft = drafts.entries[panel];
|
|
@@ -774,11 +787,25 @@ function StoryReview({
|
|
|
774
787
|
] }),
|
|
775
788
|
/* @__PURE__ */ jsx("button", { disabled: busy || pending.length > 0 || !!file, onClick: async () => {
|
|
776
789
|
setBusy(true);
|
|
790
|
+
setError("");
|
|
777
791
|
try {
|
|
792
|
+
const prevReviewer = review.reviewer;
|
|
778
793
|
await request("/leave", {});
|
|
794
|
+
setReader(null);
|
|
779
795
|
setPanelState("article");
|
|
780
796
|
setIdentityStep("name");
|
|
781
797
|
await load();
|
|
798
|
+
if (readerAccountUrl) {
|
|
799
|
+
void fetch(readerAccountUrl, { credentials: "same-origin", cache: "no-store" }).then(async (res) => {
|
|
800
|
+
if (res.ok) {
|
|
801
|
+
const d = await res.json();
|
|
802
|
+
setReader(d.user || null);
|
|
803
|
+
} else {
|
|
804
|
+
setReader(null);
|
|
805
|
+
}
|
|
806
|
+
}).catch(() => setReader(null));
|
|
807
|
+
}
|
|
808
|
+
setNotice(`You are no longer contributing as ${prevReviewer}. You can review the draft or sign in with another account.`);
|
|
782
809
|
} catch (e) {
|
|
783
810
|
setError(e.message);
|
|
784
811
|
} finally {
|
|
@@ -828,6 +855,7 @@ function StoryReview({
|
|
|
828
855
|
media: m,
|
|
829
856
|
base,
|
|
830
857
|
onChange: can("UPLOAD_MEDIA") ? () => openMedia(m) : void 0,
|
|
858
|
+
onSuggestCorrection: can("REQUEST_CHANGES") ? () => openCorrection(m) : void 0,
|
|
831
859
|
disabled: busy
|
|
832
860
|
},
|
|
833
861
|
m.file_id
|
|
@@ -848,19 +876,77 @@ function StoryReview({
|
|
|
848
876
|
]
|
|
849
877
|
}
|
|
850
878
|
),
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
879
|
+
(() => {
|
|
880
|
+
const blocks = parseDocumentBlocks({
|
|
881
|
+
content_markdown: review.revision.document.content_markdown,
|
|
882
|
+
media: review.revision.document.media,
|
|
883
|
+
blocks: review.revision.document.blocks
|
|
884
|
+
});
|
|
885
|
+
const mediaMap = /* @__PURE__ */ new Map();
|
|
886
|
+
for (const m of review.revision.document.media) {
|
|
887
|
+
mediaMap.set(m.file_id, m);
|
|
888
|
+
if (m.contribution_id) mediaMap.set(m.contribution_id, m);
|
|
856
889
|
}
|
|
857
|
-
|
|
858
|
-
|
|
890
|
+
return /* @__PURE__ */ jsx("div", { className: "sm-review-prose", children: blocks.length === 0 && review.revision.content_html ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: review.revision.content_html } }) : blocks.map((block, idx) => {
|
|
891
|
+
switch (block.type) {
|
|
892
|
+
case "paragraph":
|
|
893
|
+
return /* @__PURE__ */ jsx(
|
|
894
|
+
"p",
|
|
895
|
+
{
|
|
896
|
+
dangerouslySetInnerHTML: { __html: block.html }
|
|
897
|
+
},
|
|
898
|
+
idx
|
|
899
|
+
);
|
|
900
|
+
case "heading": {
|
|
901
|
+
if (block.level === 1)
|
|
902
|
+
return /* @__PURE__ */ jsx("h1", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
903
|
+
if (block.level === 2)
|
|
904
|
+
return /* @__PURE__ */ jsx("h2", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
905
|
+
if (block.level === 3)
|
|
906
|
+
return /* @__PURE__ */ jsx("h3", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
907
|
+
if (block.level === 4)
|
|
908
|
+
return /* @__PURE__ */ jsx("h4", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
909
|
+
if (block.level === 5)
|
|
910
|
+
return /* @__PURE__ */ jsx("h5", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
911
|
+
return /* @__PURE__ */ jsx("h6", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
912
|
+
}
|
|
913
|
+
case "quote":
|
|
914
|
+
return /* @__PURE__ */ jsxs("blockquote", { children: [
|
|
915
|
+
/* @__PURE__ */ jsx("p", { dangerouslySetInnerHTML: { __html: block.html } }),
|
|
916
|
+
block.attribution && /* @__PURE__ */ jsx("cite", { children: block.attribution })
|
|
917
|
+
] }, idx);
|
|
918
|
+
case "list":
|
|
919
|
+
return block.ordered ? /* @__PURE__ */ jsx("ol", { children: block.items.map((it, i) => /* @__PURE__ */ jsx("li", { dangerouslySetInnerHTML: { __html: it } }, i)) }, idx) : /* @__PURE__ */ jsx("ul", { children: block.items.map((it, i) => /* @__PURE__ */ jsx("li", { dangerouslySetInnerHTML: { __html: it } }, i)) }, idx);
|
|
920
|
+
case "divider":
|
|
921
|
+
return /* @__PURE__ */ jsx("hr", {}, idx);
|
|
922
|
+
case "inline_media": {
|
|
923
|
+
const m = mediaMap.get(block.media_id);
|
|
924
|
+
if (!m) return null;
|
|
925
|
+
return /* @__PURE__ */ jsx(
|
|
926
|
+
PrivatePhoto,
|
|
927
|
+
{
|
|
928
|
+
media: m,
|
|
929
|
+
base,
|
|
930
|
+
onChange: m.kind !== "video" && can("UPLOAD_MEDIA") ? () => openMedia(m) : void 0,
|
|
931
|
+
onSuggestCorrection: can("REQUEST_CHANGES") ? () => openCorrection(m) : void 0,
|
|
932
|
+
disabled: busy,
|
|
933
|
+
isInline: true
|
|
934
|
+
},
|
|
935
|
+
m.file_id
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
default:
|
|
939
|
+
return null;
|
|
940
|
+
}
|
|
941
|
+
}) });
|
|
942
|
+
})(),
|
|
943
|
+
review.revision.document.media.filter((m) => m.position === "gallery").map((m) => /* @__PURE__ */ jsx(
|
|
859
944
|
PrivatePhoto,
|
|
860
945
|
{
|
|
861
946
|
media: m,
|
|
862
947
|
base,
|
|
863
948
|
onChange: m.kind !== "video" && can("UPLOAD_MEDIA") ? () => openMedia(m) : void 0,
|
|
949
|
+
onSuggestCorrection: can("REQUEST_CHANGES") ? () => openCorrection(m) : void 0,
|
|
864
950
|
disabled: busy
|
|
865
951
|
},
|
|
866
952
|
m.file_id
|
|
@@ -934,544 +1020,573 @@ function StoryReview({
|
|
|
934
1020
|
] }, name)),
|
|
935
1021
|
file && !pending.some(([name]) => name === "media") && /* @__PURE__ */ jsx("button", { onClick: () => setPanel("media"), children: "Continue your photo upload" })
|
|
936
1022
|
] }),
|
|
937
|
-
panel
|
|
938
|
-
|
|
939
|
-
errorMessage,
|
|
940
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
941
|
-
"Anyone with this link can read the private preview. ",
|
|
942
|
-
renderSignIn ? "To contribute, they can continue with Google or use an email code." : "To send feedback or photos, they will enter their own name and verify their email. No account is needed."
|
|
943
|
-
] }),
|
|
944
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "review-share-url", children: "Private preview link" }),
|
|
945
|
-
/* @__PURE__ */ jsx("input", { id: "review-share-url", readOnly: true, value: shareUrl, onFocus: (e) => e.currentTarget.select() }),
|
|
946
|
-
/* @__PURE__ */ jsx("button", { onClick: async () => {
|
|
947
|
-
try {
|
|
948
|
-
await navigator.clipboard.writeText(shareUrl);
|
|
949
|
-
setNotice("Private link copied. Paste it into your message to family.");
|
|
950
|
-
} catch {
|
|
951
|
-
setNotice("Select the link above, then choose Copy on your device.");
|
|
952
|
-
}
|
|
953
|
-
}, children: "Copy private link" }),
|
|
954
|
-
/* @__PURE__ */ jsx("button", { onClick: () => setPanel("article"), children: "Back to the story" })
|
|
955
|
-
] }),
|
|
956
|
-
panel === "question-list" && /* @__PURE__ */ jsxs("section", { ref: responseRef, tabIndex: -1, className: "sm-review-form", "aria-label": "Optional story questions", children: [
|
|
957
|
-
/* @__PURE__ */ jsxs("div", { className: "sm-review-form-heading", children: [
|
|
958
|
-
/* @__PURE__ */ jsx("h2", { children: "Tell us a little more" }),
|
|
959
|
-
/* @__PURE__ */ jsx("button", { onClick: () => setPanel("article"), children: "Close" })
|
|
960
|
-
] }),
|
|
961
|
-
/* @__PURE__ */ jsx("p", { children: "Completely optional. Read the questions first, then answer online or copy them into an email. Even one answer helps." }),
|
|
962
|
-
/* @__PURE__ */ jsx("ol", { className: "sm-review-question-list", children: review.questions.filter((q, i) => moreQuestions || i < 5 || q.required).map((q) => /* @__PURE__ */ jsx("li", { children: q.prompt }, q.id)) }),
|
|
963
|
-
!moreQuestions && review.questions.length > 5 && /* @__PURE__ */ jsx("button", { onClick: () => setMoreQuestions(true), children: "See all questions" }),
|
|
964
|
-
/* @__PURE__ */ jsx("button", { className: "sm-review-primary", onClick: () => setPanel("questions"), children: "Answer online" }),
|
|
965
|
-
/* @__PURE__ */ jsx("p", { children: "Sign in to save your answers as you go. You can return whenever it suits you." }),
|
|
966
|
-
/* @__PURE__ */ jsx("button", { onClick: async () => {
|
|
967
|
-
try {
|
|
968
|
-
await navigator.clipboard.writeText(questionText);
|
|
969
|
-
setNotice("Questions copied. Paste them into an email and answer as many as you like.");
|
|
970
|
-
} catch {
|
|
971
|
-
setCopiedQuestions(true);
|
|
972
|
-
}
|
|
973
|
-
}, children: "Copy all questions" }),
|
|
974
|
-
copiedQuestions && /* @__PURE__ */ jsxs("label", { children: [
|
|
975
|
-
"Copy these questions",
|
|
976
|
-
/* @__PURE__ */ jsx("textarea", { readOnly: true, rows: 10, value: questionText, onFocus: (e) => e.currentTarget.select() })
|
|
977
|
-
] }),
|
|
978
|
-
questionsEmail && /* @__PURE__ */ jsxs("p", { children: [
|
|
979
|
-
/* @__PURE__ */ jsx("a", { href: questionsEmail, children: "Answer by email" }),
|
|
980
|
-
" \u2014 opens your email app with the questions ready."
|
|
981
|
-
] })
|
|
982
|
-
] }),
|
|
983
|
-
panel === "identity" && /* @__PURE__ */ jsxs("section", { ref: responseRef, tabIndex: -1, className: "sm-review-form", "aria-label": "Introduce yourself", children: [
|
|
984
|
-
/* @__PURE__ */ jsx("h2", { children: identityStep === "code" ? "Check your email" : "Continue to help with the story" }),
|
|
985
|
-
errorMessage,
|
|
986
|
-
/* @__PURE__ */ jsx("p", { children: "Your name accompanies your feedback. Your email stays private." }),
|
|
987
|
-
identityStep === "name" && renderSignIn && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
988
|
-
readerLoading ? /* @__PURE__ */ jsx("p", { role: "status", children: "Checking your sign-in\u2026" }) : reader?.email_verified ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
989
|
-
/* @__PURE__ */ jsxs("button", { className: "sm-review-primary", disabled: busy, onClick: () => void connectReader(), children: [
|
|
990
|
-
"Continue as ",
|
|
991
|
-
reader.full_name || reader.email
|
|
992
|
-
] }),
|
|
993
|
-
/* @__PURE__ */ jsx("p", { children: "Your reader account is ready. No email code is needed." })
|
|
994
|
-
] }) : renderSignIn(signInReturn),
|
|
995
|
-
!useEmailCode && /* @__PURE__ */ jsx("button", { className: "sm-review-quiet", onClick: () => setUseEmailCode(true), children: "Use an email code instead" })
|
|
996
|
-
] }),
|
|
997
|
-
identityStep === "name" && useEmailCode && /* @__PURE__ */ jsxs("form", { onSubmit: async (e) => {
|
|
998
|
-
e.preventDefault();
|
|
999
|
-
setBusy(true);
|
|
1000
|
-
setError("");
|
|
1001
|
-
try {
|
|
1002
|
-
await request("/join", { name: contributorName, email: contributorEmail });
|
|
1003
|
-
await request("/verify", {});
|
|
1004
|
-
setIdentityStep("code");
|
|
1005
|
-
setCode("");
|
|
1006
|
-
} catch (e2) {
|
|
1007
|
-
setError(e2.message);
|
|
1008
|
-
} finally {
|
|
1009
|
-
setBusy(false);
|
|
1010
|
-
}
|
|
1011
|
-
}, children: [
|
|
1012
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "contributor-name", children: "Your name" }),
|
|
1013
|
-
/* @__PURE__ */ jsx("input", { id: "contributor-name", autoComplete: "name", value: contributorName, maxLength: 150, required: true, onChange: (e) => setContributorName(e.target.value) }),
|
|
1014
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "contributor-email", children: "Your email" }),
|
|
1015
|
-
/* @__PURE__ */ jsx("input", { id: "contributor-email", type: "email", autoComplete: "email", value: contributorEmail, maxLength: 320, required: true, onChange: (e) => setContributorEmail(e.target.value) }),
|
|
1016
|
-
/* @__PURE__ */ jsx("p", { children: "We'll email you a code to confirm it's you." }),
|
|
1017
|
-
/* @__PURE__ */ jsx("p", { children: "No password or account is needed for this option." }),
|
|
1018
|
-
/* @__PURE__ */ jsx("button", { disabled: busy, children: busy ? "Sending your code\u2026" : "Email me a code" })
|
|
1019
|
-
] }),
|
|
1020
|
-
identityStep === "code" && /* @__PURE__ */ jsxs("form", { onSubmit: async (e) => {
|
|
1021
|
-
e.preventDefault();
|
|
1022
|
-
setBusy(true);
|
|
1023
|
-
setError("");
|
|
1024
|
-
try {
|
|
1025
|
-
await request("/verify", { code });
|
|
1026
|
-
await load();
|
|
1027
|
-
setCode("");
|
|
1028
|
-
setPanelState(requestedPanel);
|
|
1029
|
-
} catch (e2) {
|
|
1030
|
-
setError(e2.message);
|
|
1031
|
-
} finally {
|
|
1032
|
-
setBusy(false);
|
|
1033
|
-
}
|
|
1034
|
-
}, children: [
|
|
1035
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
1036
|
-
"Enter the eight-digit code sent to ",
|
|
1037
|
-
/* @__PURE__ */ jsx("strong", { children: contributorEmail }),
|
|
1038
|
-
". It expires in ten minutes."
|
|
1039
|
-
] }),
|
|
1040
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "contributor-code", children: "Email verification code" }),
|
|
1041
|
-
/* @__PURE__ */ jsx("input", { id: "contributor-code", inputMode: "numeric", autoComplete: "one-time-code", pattern: "[0-9]{8}", maxLength: 8, value: code, required: true, onChange: (e) => setCode(e.target.value.replace(/\s/g, "")) }),
|
|
1042
|
-
/* @__PURE__ */ jsx("button", { disabled: busy, children: busy ? "Verifying\u2026" : "Verify and continue" }),
|
|
1043
|
-
/* @__PURE__ */ jsx("button", { type: "button", disabled: busy, onClick: async () => {
|
|
1044
|
-
setBusy(true);
|
|
1045
|
-
try {
|
|
1046
|
-
await request("/verify", {});
|
|
1047
|
-
setNotice("A new code was sent. Check your inbox and spam folder.");
|
|
1048
|
-
} catch (e) {
|
|
1049
|
-
setError(e.message);
|
|
1050
|
-
} finally {
|
|
1051
|
-
setBusy(false);
|
|
1052
|
-
}
|
|
1053
|
-
}, children: "Send a new code" }),
|
|
1054
|
-
/* @__PURE__ */ jsx("button", { type: "button", disabled: busy, onClick: () => setIdentityStep("name"), children: "Use a different email" })
|
|
1055
|
-
] }),
|
|
1056
|
-
emailAlternative,
|
|
1057
|
-
/* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("article"), children: "Just read the story" })
|
|
1058
|
-
] }),
|
|
1059
|
-
panel === "feedback" && /* @__PURE__ */ jsxs("section", { ref: responseRef, tabIndex: -1, className: "sm-review-form", "aria-label": "Family feedback", children: [
|
|
1060
|
-
/* @__PURE__ */ jsx("h2", { children: "Looks good to you?" }),
|
|
1061
|
-
errorMessage,
|
|
1062
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
1063
|
-
"We'll send your feedback as ",
|
|
1064
|
-
review.reviewer,
|
|
1065
|
-
". The newsroom will request approval from the designated family reviewer separately. This will not publish the story."
|
|
1066
|
-
] }),
|
|
1067
|
-
/* @__PURE__ */ jsx("button", { className: "sm-review-primary", disabled: busy, onClick: () => void send({ action: "COMMENT", message: "This draft looks good to me.", target: { kind: "STORY" } }, "Thank you. Your feedback has been sent to the newsroom. The story is still private.", false), children: "Send my feedback" }),
|
|
1068
|
-
/* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("article"), children: "Back to the story" })
|
|
1069
|
-
] }),
|
|
1070
|
-
!["article", "identity", "share", "feedback", "question-list"].includes(panel) && /* @__PURE__ */ jsxs(
|
|
1071
|
-
"section",
|
|
1023
|
+
panel !== "article" && /* @__PURE__ */ jsx(
|
|
1024
|
+
"div",
|
|
1072
1025
|
{
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1026
|
+
className: "sm-review-modal-backdrop",
|
|
1027
|
+
role: "dialog",
|
|
1028
|
+
"aria-modal": "true",
|
|
1029
|
+
onClick: (e) => {
|
|
1030
|
+
if (e.target === e.currentTarget && !busy) setPanel("article");
|
|
1031
|
+
},
|
|
1032
|
+
children: /* @__PURE__ */ jsxs("div", { className: "sm-review-modal-container", children: [
|
|
1033
|
+
panel === "share" && /* @__PURE__ */ jsxs("section", { ref: responseRef, tabIndex: -1, className: "sm-review-form", "aria-label": "Share private preview", children: [
|
|
1034
|
+
/* @__PURE__ */ jsxs("div", { className: "sm-review-form-heading", children: [
|
|
1035
|
+
/* @__PURE__ */ jsx("h2", { children: "Share with your family" }),
|
|
1036
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, type: "button", onClick: () => setPanel("article"), "aria-label": "Close", children: "Close" })
|
|
1037
|
+
] }),
|
|
1038
|
+
errorMessage,
|
|
1039
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
1040
|
+
"Anyone with this link can read the private preview. ",
|
|
1041
|
+
renderSignIn ? "To contribute, they can continue with Google or use an email code." : "To send feedback or photos, they will enter their own name and verify their email. No account is needed."
|
|
1042
|
+
] }),
|
|
1043
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "review-share-url", children: "Private preview link" }),
|
|
1044
|
+
/* @__PURE__ */ jsx("input", { id: "review-share-url", readOnly: true, value: shareUrl, onFocus: (e) => e.currentTarget.select() }),
|
|
1045
|
+
/* @__PURE__ */ jsx("button", { onClick: async () => {
|
|
1046
|
+
try {
|
|
1047
|
+
await navigator.clipboard.writeText(shareUrl);
|
|
1048
|
+
setNotice("Private link copied. Paste it into your message to family.");
|
|
1049
|
+
} catch {
|
|
1050
|
+
setNotice("Select the link above, then choose Copy on your device.");
|
|
1051
|
+
}
|
|
1052
|
+
}, children: "Copy private link" }),
|
|
1053
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setPanel("article"), children: "Back to the story" })
|
|
1081
1054
|
] }),
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
/* @__PURE__ */ jsx("
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1055
|
+
panel === "question-list" && /* @__PURE__ */ jsxs("section", { ref: responseRef, tabIndex: -1, className: "sm-review-form", "aria-label": "Optional story questions", children: [
|
|
1056
|
+
/* @__PURE__ */ jsxs("div", { className: "sm-review-form-heading", children: [
|
|
1057
|
+
/* @__PURE__ */ jsx("h2", { children: "Tell us a little more" }),
|
|
1058
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setPanel("article"), children: "Close" })
|
|
1059
|
+
] }),
|
|
1060
|
+
/* @__PURE__ */ jsx("p", { children: "Completely optional. Read the questions first, then answer online or copy them into an email. Even one answer helps." }),
|
|
1061
|
+
/* @__PURE__ */ jsx("ol", { className: "sm-review-question-list", children: review.questions.filter((q, i) => moreQuestions || i < 5 || q.required).map((q) => /* @__PURE__ */ jsx("li", { children: q.prompt }, q.id)) }),
|
|
1062
|
+
!moreQuestions && review.questions.length > 5 && /* @__PURE__ */ jsx("button", { onClick: () => setMoreQuestions(true), children: "See all questions" }),
|
|
1063
|
+
/* @__PURE__ */ jsx("button", { className: "sm-review-primary", onClick: () => setPanel("questions"), children: "Answer online" }),
|
|
1064
|
+
/* @__PURE__ */ jsx("p", { children: "Sign in to save your answers as you go. You can return whenever it suits you." }),
|
|
1065
|
+
/* @__PURE__ */ jsx("button", { onClick: async () => {
|
|
1066
|
+
try {
|
|
1067
|
+
await navigator.clipboard.writeText(questionText);
|
|
1068
|
+
setNotice("Questions copied. Paste them into an email and answer as many as you like.");
|
|
1069
|
+
} catch {
|
|
1070
|
+
setCopiedQuestions(true);
|
|
1071
|
+
}
|
|
1072
|
+
}, children: "Copy all questions" }),
|
|
1073
|
+
copiedQuestions && /* @__PURE__ */ jsxs("label", { children: [
|
|
1074
|
+
"Copy these questions",
|
|
1075
|
+
/* @__PURE__ */ jsx("textarea", { readOnly: true, rows: 10, value: questionText, onFocus: (e) => e.currentTarget.select() })
|
|
1076
|
+
] }),
|
|
1077
|
+
questionsEmail && /* @__PURE__ */ jsxs("p", { children: [
|
|
1078
|
+
/* @__PURE__ */ jsx("a", { href: questionsEmail, children: "Answer by email" }),
|
|
1079
|
+
" \u2014 opens your email app with the questions ready."
|
|
1080
|
+
] })
|
|
1095
1081
|
] }),
|
|
1096
|
-
/* @__PURE__ */ jsxs("
|
|
1097
|
-
|
|
1098
|
-
/* @__PURE__ */ jsx("
|
|
1099
|
-
/* @__PURE__ */
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
/* @__PURE__ */
|
|
1110
|
-
"
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1082
|
+
panel === "identity" && /* @__PURE__ */ jsxs("section", { ref: responseRef, tabIndex: -1, className: "sm-review-form", "aria-label": "Introduce yourself", children: [
|
|
1083
|
+
/* @__PURE__ */ jsxs("div", { className: "sm-review-form-heading", children: [
|
|
1084
|
+
/* @__PURE__ */ jsx("h2", { children: identityStep === "code" ? "Check your email" : requestedPanel === "media" ? photoToReplace ? "Change photo" : "Contribute a photograph" : requestedPanel === "changes" ? "Suggest a change" : requestedPanel === "edits" ? "Propose changes" : requestedPanel === "comment" ? "Leave a comment" : "Continue to help with the story" }),
|
|
1085
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, type: "button", onClick: () => setPanel("article"), "aria-label": "Close", children: "Close" })
|
|
1086
|
+
] }),
|
|
1087
|
+
errorMessage,
|
|
1088
|
+
photoToReplace && /* @__PURE__ */ jsx("div", { className: "sm-review-target-preview", style: { padding: "10px 14px", background: "#f8fafc", borderRadius: "8px", border: "1px solid #e2e8f0", margin: "10px 0 16px" }, children: /* @__PURE__ */ jsxs("div", { style: { fontSize: "13px", color: "#334155" }, children: [
|
|
1089
|
+
/* @__PURE__ */ jsx("strong", { children: "Replacing:" }),
|
|
1090
|
+
" ",
|
|
1091
|
+
photoToReplace.artwork_title ? `\u201C${photoToReplace.artwork_title}\u201D` : photoToReplace.caption || "Header photograph"
|
|
1092
|
+
] }) }),
|
|
1093
|
+
/* @__PURE__ */ jsx("p", { children: "Your name accompanies your feedback. Your email stays private." }),
|
|
1094
|
+
identityStep === "name" && renderSignIn && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1095
|
+
readerLoading ? /* @__PURE__ */ jsx("p", { role: "status", children: "Checking your sign-in\u2026" }) : reader?.email_verified ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1096
|
+
/* @__PURE__ */ jsxs("button", { className: "sm-review-primary", disabled: busy, onClick: () => void connectReader(), children: [
|
|
1097
|
+
"Continue as ",
|
|
1098
|
+
reader.full_name || reader.email
|
|
1099
|
+
] }),
|
|
1100
|
+
/* @__PURE__ */ jsx("p", { children: "Your reader account is ready. No email code is needed." })
|
|
1101
|
+
] }) : renderSignIn(signInReturn),
|
|
1102
|
+
!useEmailCode && /* @__PURE__ */ jsx("button", { className: "sm-review-quiet", onClick: () => setUseEmailCode(true), children: "Use an email code instead" })
|
|
1103
|
+
] }),
|
|
1104
|
+
identityStep === "name" && useEmailCode && /* @__PURE__ */ jsxs("form", { onSubmit: async (e) => {
|
|
1105
|
+
e.preventDefault();
|
|
1106
|
+
setBusy(true);
|
|
1107
|
+
setError("");
|
|
1108
|
+
try {
|
|
1109
|
+
await request("/join", { name: contributorName, email: contributorEmail });
|
|
1110
|
+
await request("/verify", {});
|
|
1111
|
+
setIdentityStep("code");
|
|
1112
|
+
setCode("");
|
|
1113
|
+
} catch (e2) {
|
|
1114
|
+
setError(e2.message);
|
|
1115
|
+
} finally {
|
|
1116
|
+
setBusy(false);
|
|
1117
|
+
}
|
|
1118
|
+
}, children: [
|
|
1119
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "contributor-name", children: "Your name" }),
|
|
1120
|
+
/* @__PURE__ */ jsx("input", { id: "contributor-name", autoComplete: "name", value: contributorName, maxLength: 150, required: true, onChange: (e) => setContributorName(e.target.value) }),
|
|
1121
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "contributor-email", children: "Your email" }),
|
|
1122
|
+
/* @__PURE__ */ jsx("input", { id: "contributor-email", type: "email", autoComplete: "email", value: contributorEmail, maxLength: 320, required: true, onChange: (e) => setContributorEmail(e.target.value) }),
|
|
1123
|
+
/* @__PURE__ */ jsx("p", { children: "We'll email you a code to confirm it's you." }),
|
|
1124
|
+
/* @__PURE__ */ jsx("p", { children: "No password or account is needed for this option." }),
|
|
1125
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, children: busy ? "Sending your code\u2026" : "Email me a code" })
|
|
1126
|
+
] }),
|
|
1127
|
+
identityStep === "code" && /* @__PURE__ */ jsxs("form", { onSubmit: async (e) => {
|
|
1128
|
+
e.preventDefault();
|
|
1129
|
+
setBusy(true);
|
|
1130
|
+
setError("");
|
|
1131
|
+
try {
|
|
1132
|
+
await request("/verify", { code });
|
|
1133
|
+
await load();
|
|
1134
|
+
setCode("");
|
|
1135
|
+
setPanelState(requestedPanel);
|
|
1136
|
+
} catch (e2) {
|
|
1137
|
+
setError(e2.message);
|
|
1138
|
+
} finally {
|
|
1139
|
+
setBusy(false);
|
|
1140
|
+
}
|
|
1141
|
+
}, children: [
|
|
1142
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
1143
|
+
"Enter the eight-digit code sent to ",
|
|
1144
|
+
/* @__PURE__ */ jsx("strong", { children: contributorEmail }),
|
|
1145
|
+
". It expires in ten minutes."
|
|
1132
1146
|
] }),
|
|
1133
|
-
/* @__PURE__ */ jsx(
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
"Your proposed changes have been sent to the newsroom."
|
|
1146
|
-
),
|
|
1147
|
-
children: "Send proposed changes"
|
|
1147
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "contributor-code", children: "Email verification code" }),
|
|
1148
|
+
/* @__PURE__ */ jsx("input", { id: "contributor-code", inputMode: "numeric", autoComplete: "one-time-code", pattern: "[0-9]{8}", maxLength: 8, value: code, required: true, onChange: (e) => setCode(e.target.value.replace(/\s/g, "")) }),
|
|
1149
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, children: busy ? "Verifying\u2026" : "Verify and continue" }),
|
|
1150
|
+
/* @__PURE__ */ jsx("button", { type: "button", disabled: busy, onClick: async () => {
|
|
1151
|
+
setBusy(true);
|
|
1152
|
+
try {
|
|
1153
|
+
await request("/verify", {});
|
|
1154
|
+
setNotice("A new code was sent. Check your inbox and spam folder.");
|
|
1155
|
+
} catch (e) {
|
|
1156
|
+
setError(e.message);
|
|
1157
|
+
} finally {
|
|
1158
|
+
setBusy(false);
|
|
1148
1159
|
}
|
|
1149
|
-
)
|
|
1160
|
+
}, children: "Send a new code" }),
|
|
1161
|
+
/* @__PURE__ */ jsx("button", { type: "button", disabled: busy, onClick: () => setIdentityStep("name"), children: "Use a different email" })
|
|
1150
1162
|
] }),
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1163
|
+
emailAlternative,
|
|
1164
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("article"), children: "Just read the story" })
|
|
1165
|
+
] }),
|
|
1166
|
+
panel === "feedback" && /* @__PURE__ */ jsxs("section", { ref: responseRef, tabIndex: -1, className: "sm-review-form", "aria-label": "Family feedback", children: [
|
|
1167
|
+
/* @__PURE__ */ jsx("h2", { children: "Looks good to you?" }),
|
|
1168
|
+
errorMessage,
|
|
1169
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
1170
|
+
"We'll send your feedback as ",
|
|
1171
|
+
review.reviewer,
|
|
1172
|
+
". The newsroom will request approval from the designated family reviewer separately. This will not publish the story."
|
|
1173
|
+
] }),
|
|
1174
|
+
/* @__PURE__ */ jsx("button", { className: "sm-review-primary", disabled: busy, onClick: () => void send({ action: "COMMENT", message: "This draft looks good to me.", target: { kind: "STORY" } }, "Thank you. Your feedback has been sent to the newsroom. The story is still private.", false), children: "Send my feedback" }),
|
|
1175
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("article"), children: "Back to the story" })
|
|
1176
|
+
] }),
|
|
1177
|
+
!["article", "identity", "share", "feedback", "question-list"].includes(panel) && /* @__PURE__ */ jsxs(
|
|
1178
|
+
"section",
|
|
1179
|
+
{
|
|
1180
|
+
ref: responseRef,
|
|
1181
|
+
tabIndex: -1,
|
|
1182
|
+
className: "sm-review-form",
|
|
1183
|
+
"aria-label": "Your response",
|
|
1184
|
+
children: [
|
|
1185
|
+
/* @__PURE__ */ jsxs("div", { className: "sm-review-form-heading", children: [
|
|
1186
|
+
/* @__PURE__ */ jsx("h2", { children: panel === "approve" ? "Approve this exact draft" : panel === "edits" ? "Propose changes" : panel === "media" ? photoToReplace ? "Change photo" : "Contribute a photograph" : panel === "questions" ? "Tell us a little more" : panel === "history" ? "Selected revision history" : panel === "decline" ? "Prefer not to publish" : panel === "changes" ? "Suggest a change" : "Message the newsroom" }),
|
|
1187
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("article"), children: "Close" })
|
|
1188
|
+
] }),
|
|
1189
|
+
errorMessage,
|
|
1190
|
+
panel !== "history" && /* @__PURE__ */ jsxs("div", { className: "sm-review-save-state", role: "status", "aria-live": "polite", children: [
|
|
1191
|
+
currentDraft?.status === "conflict" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1192
|
+
/* @__PURE__ */ jsx("p", { children: "A response was saved in another tab or device. Your writing here is still available. Choose which version to keep." }),
|
|
1193
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => void drafts.resolve(panel, true).catch((e) => setError(e.message)), children: "Keep what I wrote here" }),
|
|
1194
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => void drafts.resolve(panel, false).catch((e) => setError(e.message)), children: "Use the saved response" })
|
|
1195
|
+
] }) : currentDraft?.status === "offline" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1196
|
+
/* @__PURE__ */ jsx("p", { children: currentDraft.local ? "Saved on this device. Waiting for a connection to save online." : "Not saved yet. Keep this page open and try again." }),
|
|
1197
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => void drafts.flush(panel).catch((e) => setError(e.message)), children: "Try saving again" })
|
|
1198
|
+
] }) : /* @__PURE__ */ jsx("p", { children: currentDraft?.status === "saving" ? "Saving your writing\u2026" : hasDraft(currentDraft?.data) ? "Saved \u2014 not sent yet. You can safely come back later." : "Your writing saves automatically. Use the Send button below when you're ready to share it with the newsroom." }),
|
|
1199
|
+
hasDraft(currentDraft?.data) && /* @__PURE__ */ jsx("button", { className: "sm-review-quiet", disabled: busy, onClick: () => {
|
|
1200
|
+
if (window.confirm("Discard this unsent response? Responses already sent will be kept.")) void drafts.discard(panel).catch((e) => setError(e.message));
|
|
1201
|
+
}, children: "Discard this unsent response" })
|
|
1202
|
+
] }),
|
|
1203
|
+
/* @__PURE__ */ jsxs("fieldset", { disabled: busy, className: "sm-review-response-fields", children: [
|
|
1204
|
+
panel === "edits" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1205
|
+
/* @__PURE__ */ jsx("p", { children: "Your suggestions will be reviewed by an editor. They do not replace the newsroom\u2019s draft." }),
|
|
1206
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
1207
|
+
"Headline",
|
|
1208
|
+
/* @__PURE__ */ jsx(
|
|
1209
|
+
"input",
|
|
1210
|
+
{
|
|
1211
|
+
value: document.title,
|
|
1212
|
+
onChange: (e) => setDocument({ ...document, title: e.target.value })
|
|
1213
|
+
}
|
|
1214
|
+
)
|
|
1215
|
+
] }),
|
|
1216
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
1217
|
+
"Short introduction",
|
|
1218
|
+
/* @__PURE__ */ jsx(
|
|
1219
|
+
"input",
|
|
1220
|
+
{
|
|
1221
|
+
value: document.subtitle,
|
|
1222
|
+
onChange: (e) => setDocument({ ...document, subtitle: e.target.value })
|
|
1223
|
+
}
|
|
1224
|
+
)
|
|
1225
|
+
] }),
|
|
1226
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
1227
|
+
"Suggested article text",
|
|
1228
|
+
/* @__PURE__ */ jsx(
|
|
1229
|
+
"textarea",
|
|
1230
|
+
{
|
|
1231
|
+
rows: 16,
|
|
1232
|
+
value: document.content_markdown,
|
|
1233
|
+
onChange: (e) => setDocument({
|
|
1234
|
+
...document,
|
|
1235
|
+
content_markdown: e.target.value
|
|
1236
|
+
})
|
|
1237
|
+
}
|
|
1238
|
+
)
|
|
1239
|
+
] }),
|
|
1166
1240
|
/* @__PURE__ */ jsx(
|
|
1167
|
-
"
|
|
1241
|
+
"button",
|
|
1168
1242
|
{
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1243
|
+
disabled: busy,
|
|
1244
|
+
onClick: () => void send(
|
|
1245
|
+
{
|
|
1246
|
+
action: "PROPOSE_EDITS",
|
|
1247
|
+
title: document.title,
|
|
1248
|
+
subtitle: document.subtitle,
|
|
1249
|
+
content_markdown: document.content_markdown,
|
|
1250
|
+
message
|
|
1251
|
+
},
|
|
1252
|
+
"Your proposed changes have been sent to the newsroom."
|
|
1253
|
+
),
|
|
1254
|
+
children: "Send proposed changes"
|
|
1173
1255
|
}
|
|
1174
1256
|
)
|
|
1175
|
-
] }
|
|
1176
|
-
/* @__PURE__ */
|
|
1177
|
-
"
|
|
1178
|
-
{
|
|
1179
|
-
className: "sm-review-primary",
|
|
1180
|
-
disabled: busy || !Object.values(answers).some((a) => a.trim()),
|
|
1181
|
-
children: "Send These Answers"
|
|
1182
|
-
}
|
|
1183
|
-
),
|
|
1184
|
-
!moreQuestions && review.questions.length > 5 && /* @__PURE__ */ jsx(
|
|
1185
|
-
"button",
|
|
1257
|
+
] }),
|
|
1258
|
+
panel === "questions" && /* @__PURE__ */ jsxs(
|
|
1259
|
+
"form",
|
|
1186
1260
|
{
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1261
|
+
onSubmit: (e) => {
|
|
1262
|
+
e.preventDefault();
|
|
1263
|
+
void send(
|
|
1264
|
+
{ action: "ANSWER_QUESTIONS", answers },
|
|
1265
|
+
"Thank you for sharing. We'll take care of turning your answers into an updated draft."
|
|
1266
|
+
);
|
|
1267
|
+
},
|
|
1268
|
+
children: [
|
|
1269
|
+
/* @__PURE__ */ jsx("p", { children: review.questions.some((q) => q.required) ? "Only questions marked required must be answered. Share what you would like considered for publication." : "Completely optional. Even one answer can help us make the announcement more personal." }),
|
|
1270
|
+
review.questions.filter((q, i) => moreQuestions || i < 5 || q.required).map((q) => /* @__PURE__ */ jsxs("label", { children: [
|
|
1271
|
+
q.prompt,
|
|
1272
|
+
q.required ? " (required)" : " (optional)",
|
|
1273
|
+
/* @__PURE__ */ jsx(
|
|
1274
|
+
"textarea",
|
|
1275
|
+
{
|
|
1276
|
+
required: q.required,
|
|
1277
|
+
rows: 3,
|
|
1278
|
+
value: answers[q.id] || "",
|
|
1279
|
+
onChange: (e) => setAnswers({ ...answers, [q.id]: e.target.value })
|
|
1280
|
+
}
|
|
1281
|
+
)
|
|
1282
|
+
] }, q.id)),
|
|
1283
|
+
/* @__PURE__ */ jsx(
|
|
1284
|
+
"button",
|
|
1285
|
+
{
|
|
1286
|
+
className: "sm-review-primary",
|
|
1287
|
+
disabled: busy || !Object.values(answers).some((a) => a.trim()),
|
|
1288
|
+
children: "Send These Answers"
|
|
1289
|
+
}
|
|
1290
|
+
),
|
|
1291
|
+
!moreQuestions && review.questions.length > 5 && /* @__PURE__ */ jsx(
|
|
1292
|
+
"button",
|
|
1293
|
+
{
|
|
1294
|
+
type: "button",
|
|
1295
|
+
onClick: () => setMoreQuestions(true),
|
|
1296
|
+
children: "Answer More Questions"
|
|
1297
|
+
}
|
|
1298
|
+
),
|
|
1299
|
+
questionsEmail && /* @__PURE__ */ jsxs("p", { children: [
|
|
1300
|
+
/* @__PURE__ */ jsx("a", { href: questionsEmail, children: "Email these answers instead" }),
|
|
1301
|
+
". Send them from your email app; your online draft stays saved."
|
|
1302
|
+
] })
|
|
1303
|
+
]
|
|
1190
1304
|
}
|
|
1191
1305
|
),
|
|
1192
|
-
|
|
1193
|
-
/* @__PURE__ */ jsx("
|
|
1194
|
-
"
|
|
1195
|
-
|
|
1196
|
-
]
|
|
1197
|
-
}
|
|
1198
|
-
),
|
|
1199
|
-
panel === "metadata" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1200
|
-
/* @__PURE__ */ jsx("p", { children: "Caption and credit changes are proposals for the newsroom; historical captions remain intact." }),
|
|
1201
|
-
["caption", "credit", "alt"].map((key) => /* @__PURE__ */ jsxs("label", { children: [
|
|
1202
|
-
key,
|
|
1203
|
-
/* @__PURE__ */ jsx(
|
|
1204
|
-
"input",
|
|
1205
|
-
{
|
|
1206
|
-
value: mediaInfo[key],
|
|
1207
|
-
onChange: (e) => setMediaInfo({ ...mediaInfo, [key]: e.target.value })
|
|
1208
|
-
}
|
|
1209
|
-
)
|
|
1210
|
-
] }, key)),
|
|
1211
|
-
/* @__PURE__ */ jsx(
|
|
1212
|
-
"button",
|
|
1213
|
-
{
|
|
1214
|
-
disabled: busy,
|
|
1215
|
-
onClick: () => void send(
|
|
1216
|
-
{
|
|
1217
|
-
action: "EDIT_MEDIA_METADATA",
|
|
1218
|
-
contribution_id: drafts.entries.metadata?.data.editingMedia || editingMedia,
|
|
1219
|
-
caption: mediaInfo.caption,
|
|
1220
|
-
credit: mediaInfo.credit,
|
|
1221
|
-
alt: mediaInfo.alt
|
|
1222
|
-
},
|
|
1223
|
-
"Your proposed media descriptions have been sent to the newsroom."
|
|
1224
|
-
),
|
|
1225
|
-
children: "Propose caption / credit changes"
|
|
1226
|
-
}
|
|
1227
|
-
)
|
|
1228
|
-
] }),
|
|
1229
|
-
panel === "media" && /* @__PURE__ */ jsxs(
|
|
1230
|
-
"form",
|
|
1231
|
-
{
|
|
1232
|
-
onSubmit: (e) => {
|
|
1233
|
-
e.preventDefault();
|
|
1234
|
-
void upload();
|
|
1235
|
-
},
|
|
1236
|
-
children: [
|
|
1237
|
-
photoToReplace && /* @__PURE__ */ jsx("p", { children: "Choose the photograph you'd like us to use instead. We'll review it and prepare an updated preview; the current photo stays in place until then." }),
|
|
1238
|
-
/* @__PURE__ */ jsx("p", { children: "JPEG, PNG or WebP photos up to 12 MB; MP4 or WebM videos up to 25 MB. Media remain private until selected and approved by the newsroom." }),
|
|
1239
|
-
/* @__PURE__ */ jsxs("div", { className: "sm-review-photo-picker", children: [
|
|
1240
|
-
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: "1. Choose a photo" }) }),
|
|
1241
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => galleryRef.current?.click(), children: "Choose from my photos" }),
|
|
1242
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => cameraRef.current?.click(), children: "Take a photo" }),
|
|
1243
|
-
/* @__PURE__ */ jsx("input", { ref: cameraRef, "aria-label": "Take a photo", type: "file", accept: "image/jpeg,image/png,image/webp", capture: "environment", hidden: true, onChange: (e) => choosePhoto(e.target.files?.[0] || null) }),
|
|
1244
|
-
/* @__PURE__ */ jsxs("label", { className: "sm-review-native-file", children: [
|
|
1245
|
-
"Photograph or video",
|
|
1306
|
+
panel === "metadata" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1307
|
+
/* @__PURE__ */ jsx("p", { children: "Caption and credit changes are proposals for the newsroom; historical captions remain intact." }),
|
|
1308
|
+
["caption", "credit", "alt"].map((key) => /* @__PURE__ */ jsxs("label", { children: [
|
|
1309
|
+
key,
|
|
1246
1310
|
/* @__PURE__ */ jsx(
|
|
1247
1311
|
"input",
|
|
1248
1312
|
{
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
accept: "image/jpeg,image/png,image/webp,video/mp4,video/webm",
|
|
1252
|
-
onChange: (e) => choosePhoto(e.target.files?.[0] || null)
|
|
1313
|
+
value: mediaInfo[key],
|
|
1314
|
+
onChange: (e) => setMediaInfo({ ...mediaInfo, [key]: e.target.value })
|
|
1253
1315
|
}
|
|
1254
1316
|
)
|
|
1255
|
-
] })
|
|
1256
|
-
] }),
|
|
1257
|
-
file && /* @__PURE__ */ jsxs("div", { className: "sm-review-selected-photo", children: [
|
|
1258
|
-
pendingPhoto.preview && /* @__PURE__ */ jsx("img", { src: pendingPhoto.preview, alt: "Your selected photograph" }),
|
|
1259
|
-
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: file.name }) }),
|
|
1260
|
-
/* @__PURE__ */ jsx("p", { role: "status", children: pendingPhoto.saved ? "Photo kept on this device \u2014 not uploaded yet." : "Photo selected \u2014 not uploaded yet. Keep this page open." }),
|
|
1261
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => {
|
|
1262
|
-
void pendingPhoto.select(null);
|
|
1263
|
-
setRights(false);
|
|
1264
|
-
}, children: "Remove selected photo" })
|
|
1265
|
-
] }),
|
|
1266
|
-
/* @__PURE__ */ jsx("p", { className: "sm-review-help", children: "Choose a photograph and confirm permission below. All descriptions are optional; we can help with the caption." }),
|
|
1267
|
-
Object.entries({
|
|
1268
|
-
caption: "Caption (optional)",
|
|
1269
|
-
credit: "Photographer / credit (optional)"
|
|
1270
|
-
}).map(([key, label]) => /* @__PURE__ */ jsxs("label", { children: [
|
|
1271
|
-
label,
|
|
1317
|
+
] }, key)),
|
|
1272
1318
|
/* @__PURE__ */ jsx(
|
|
1273
|
-
"
|
|
1319
|
+
"button",
|
|
1274
1320
|
{
|
|
1275
|
-
|
|
1276
|
-
|
|
1321
|
+
disabled: busy,
|
|
1322
|
+
onClick: () => void send(
|
|
1323
|
+
{
|
|
1324
|
+
action: "EDIT_MEDIA_METADATA",
|
|
1325
|
+
contribution_id: drafts.entries.metadata?.data.editingMedia || editingMedia,
|
|
1326
|
+
caption: mediaInfo.caption,
|
|
1327
|
+
credit: mediaInfo.credit,
|
|
1328
|
+
alt: mediaInfo.alt
|
|
1329
|
+
},
|
|
1330
|
+
"Your proposed media descriptions have been sent to the newsroom."
|
|
1331
|
+
),
|
|
1332
|
+
children: "Propose caption / credit changes"
|
|
1277
1333
|
}
|
|
1278
1334
|
)
|
|
1279
|
-
] }
|
|
1280
|
-
/* @__PURE__ */ jsxs(
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1335
|
+
] }),
|
|
1336
|
+
panel === "media" && /* @__PURE__ */ jsxs(
|
|
1337
|
+
"form",
|
|
1338
|
+
{
|
|
1339
|
+
onSubmit: (e) => {
|
|
1340
|
+
e.preventDefault();
|
|
1341
|
+
void upload();
|
|
1342
|
+
},
|
|
1343
|
+
children: [
|
|
1344
|
+
photoToReplace && /* @__PURE__ */ jsx("div", { className: "sm-review-target-preview", children: /* @__PURE__ */ jsxs("div", { className: "sm-review-target-preview-title", children: [
|
|
1345
|
+
/* @__PURE__ */ jsx("strong", { children: "Replacing:" }),
|
|
1346
|
+
" ",
|
|
1347
|
+
photoToReplace.artwork_title ? `\u201C${photoToReplace.artwork_title}\u201D` : photoToReplace.caption || "Header photograph"
|
|
1348
|
+
] }) }),
|
|
1349
|
+
photoToReplace && /* @__PURE__ */ jsx("p", { children: "Choose the photograph you'd like us to use instead. We'll review it and prepare an updated preview; the current photo stays in place until then." }),
|
|
1350
|
+
/* @__PURE__ */ jsx("p", { children: "JPEG, PNG or WebP photos up to 12 MB; MP4 or WebM videos up to 25 MB. Media remain private until selected and approved by the newsroom." }),
|
|
1351
|
+
/* @__PURE__ */ jsxs("div", { className: "sm-review-photo-picker", children: [
|
|
1352
|
+
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: "1. Choose a photo" }) }),
|
|
1353
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => galleryRef.current?.click(), children: "Choose from my photos" }),
|
|
1354
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => cameraRef.current?.click(), children: "Take a photo" }),
|
|
1355
|
+
/* @__PURE__ */ jsx("input", { ref: cameraRef, "aria-label": "Take a photo", type: "file", accept: "image/jpeg,image/png,image/webp", capture: "environment", hidden: true, onChange: (e) => choosePhoto(e.target.files?.[0] || null) }),
|
|
1356
|
+
/* @__PURE__ */ jsxs("label", { className: "sm-review-native-file", children: [
|
|
1357
|
+
"Photograph or video",
|
|
1358
|
+
/* @__PURE__ */ jsx(
|
|
1359
|
+
"input",
|
|
1360
|
+
{
|
|
1361
|
+
ref: galleryRef,
|
|
1362
|
+
type: "file",
|
|
1363
|
+
accept: "image/jpeg,image/png,image/webp,video/mp4,video/webm",
|
|
1364
|
+
onChange: (e) => choosePhoto(e.target.files?.[0] || null)
|
|
1365
|
+
}
|
|
1366
|
+
)
|
|
1367
|
+
] })
|
|
1368
|
+
] }),
|
|
1369
|
+
file && /* @__PURE__ */ jsxs("div", { className: "sm-review-selected-photo", children: [
|
|
1370
|
+
pendingPhoto.preview && /* @__PURE__ */ jsx("img", { src: pendingPhoto.preview, alt: "Your selected photograph" }),
|
|
1371
|
+
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: file.name }) }),
|
|
1372
|
+
/* @__PURE__ */ jsx("p", { role: "status", children: pendingPhoto.saved ? "Photo kept on this device \u2014 not uploaded yet." : "Photo selected \u2014 not uploaded yet. Keep this page open." }),
|
|
1373
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => {
|
|
1374
|
+
void pendingPhoto.select(null);
|
|
1375
|
+
setRights(false);
|
|
1376
|
+
}, children: "Remove selected photo" })
|
|
1377
|
+
] }),
|
|
1378
|
+
/* @__PURE__ */ jsx("p", { className: "sm-review-help", children: "Choose a photograph and confirm permission below. All descriptions are optional; we can help with the caption." }),
|
|
1379
|
+
Object.entries({
|
|
1380
|
+
caption: "Caption (optional)",
|
|
1381
|
+
credit: "Photographer / credit (optional)"
|
|
1382
|
+
}).map(([key, label]) => /* @__PURE__ */ jsxs("label", { children: [
|
|
1383
|
+
label,
|
|
1384
|
+
/* @__PURE__ */ jsx(
|
|
1385
|
+
"input",
|
|
1386
|
+
{
|
|
1387
|
+
value: mediaInfo[key],
|
|
1388
|
+
onChange: (e) => setMediaInfo({ ...mediaInfo, [key]: e.target.value })
|
|
1389
|
+
}
|
|
1390
|
+
)
|
|
1391
|
+
] }, key)),
|
|
1392
|
+
/* @__PURE__ */ jsxs("details", { className: "sm-review-media-details", children: [
|
|
1393
|
+
/* @__PURE__ */ jsx("summary", { children: "Add more photograph details (optional)" }),
|
|
1394
|
+
Object.entries({
|
|
1395
|
+
who_is_pictured: "Who is pictured?",
|
|
1396
|
+
creator: "Photographer / creator",
|
|
1397
|
+
when_taken: "When was it taken?",
|
|
1398
|
+
where_taken: "Where was it taken?",
|
|
1399
|
+
alt: "Describe the photograph for readers who cannot see it"
|
|
1400
|
+
}).map(([key, label]) => /* @__PURE__ */ jsxs("label", { children: [
|
|
1401
|
+
label,
|
|
1402
|
+
/* @__PURE__ */ jsx(
|
|
1403
|
+
"input",
|
|
1404
|
+
{
|
|
1405
|
+
value: mediaInfo[key],
|
|
1406
|
+
onChange: (e) => setMediaInfo({
|
|
1407
|
+
...mediaInfo,
|
|
1408
|
+
[key]: e.target.value
|
|
1409
|
+
})
|
|
1410
|
+
}
|
|
1411
|
+
)
|
|
1412
|
+
] }, key))
|
|
1413
|
+
] }),
|
|
1414
|
+
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: "2. Confirm permission" }) }),
|
|
1415
|
+
/* @__PURE__ */ jsxs("label", { className: "sm-review-check", children: [
|
|
1416
|
+
/* @__PURE__ */ jsx(
|
|
1417
|
+
"input",
|
|
1418
|
+
{
|
|
1419
|
+
type: "checkbox",
|
|
1420
|
+
required: true,
|
|
1421
|
+
checked: rights,
|
|
1422
|
+
onChange: (e) => setRights(e.target.checked)
|
|
1423
|
+
}
|
|
1424
|
+
),
|
|
1425
|
+
"I confirm that I have the right or permission to provide this media to ",
|
|
1426
|
+
review.publication.name,
|
|
1427
|
+
" for editorial publication."
|
|
1428
|
+
] }),
|
|
1429
|
+
/* @__PURE__ */ jsxs("div", { className: `sm-review-send-bar${rights && file ? " is-ready" : ""}`, children: [
|
|
1430
|
+
/* @__PURE__ */ jsx("p", { children: busy ? "Uploading your photo. Please keep this page open\u2026" : !file ? "Choose a photo above to continue." : !rights ? "Tick the permission box above, then upload your photo." : "Ready. Tap Upload privately to send this photo to the newsroom." }),
|
|
1431
|
+
busy && /* @__PURE__ */ jsx("progress", { "aria-label": "Uploading photo" }),
|
|
1432
|
+
/* @__PURE__ */ jsx("button", { className: "sm-review-primary", disabled: busy || !rights || !file, children: busy ? "Uploading\u2026" : "Upload privately" })
|
|
1433
|
+
] })
|
|
1434
|
+
]
|
|
1435
|
+
}
|
|
1436
|
+
),
|
|
1437
|
+
["approve", "changes", "comment", "decline"].includes(panel) && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1438
|
+
panel === "approve" && /* @__PURE__ */ jsxs("p", { children: [
|
|
1439
|
+
"You are approving version ",
|
|
1440
|
+
review.revision.number,
|
|
1441
|
+
". Changes to the article require a new approval.",
|
|
1442
|
+
review.review_policy === "SUBJECT_APPROVAL_AUTO_PUBLISH" ? " The editor has configured this version to publish or schedule after the required approvals are received." : " The newsroom will complete its editorial workflow before publication."
|
|
1443
|
+
] }),
|
|
1444
|
+
panel === "decline" && /* @__PURE__ */ jsx("p", { children: ["FACT_CHECK", "CONTRIBUTOR_REVIEW"].includes(
|
|
1445
|
+
review.review_policy
|
|
1446
|
+
) ? "You can decline this review. The newsroom may still publish its reporting." : "Declining participation prevents publication of this voluntary announcement." }),
|
|
1447
|
+
panel === "comment" && /* @__PURE__ */ jsxs("label", { children: [
|
|
1448
|
+
"Comment on",
|
|
1449
|
+
/* @__PURE__ */ jsxs(
|
|
1450
|
+
"select",
|
|
1451
|
+
{
|
|
1452
|
+
value: currentDraft?.data.commentTarget || commentTarget,
|
|
1453
|
+
onChange: (e) => {
|
|
1454
|
+
setCommentTarget(e.target.value);
|
|
1455
|
+
if (message) drafts.set("comment", { ...currentDraft?.data, commentTarget: e.target.value });
|
|
1456
|
+
},
|
|
1457
|
+
children: [
|
|
1458
|
+
/* @__PURE__ */ jsx("option", { value: "STORY", children: "Entire story" }),
|
|
1459
|
+
review.revision.document.content_markdown.split(/\n\s*\n/).slice(0, 200).map((_, i) => /* @__PURE__ */ jsxs("option", { value: `PARAGRAPH:${i + 1}`, children: [
|
|
1460
|
+
"Paragraph ",
|
|
1461
|
+
i + 1
|
|
1462
|
+
] }, i)),
|
|
1463
|
+
review.revision.document.media.map((m, i) => /* @__PURE__ */ jsxs(
|
|
1464
|
+
"option",
|
|
1465
|
+
{
|
|
1466
|
+
value: `MEDIA:${m.contribution_id}`,
|
|
1467
|
+
children: [
|
|
1468
|
+
"Photo / caption ",
|
|
1469
|
+
i + 1
|
|
1470
|
+
]
|
|
1471
|
+
},
|
|
1472
|
+
m.contribution_id
|
|
1473
|
+
)),
|
|
1474
|
+
review.questions.map((q) => /* @__PURE__ */ jsx("option", { value: `QUESTION:${q.id}`, children: q.prompt }, q.id))
|
|
1475
|
+
]
|
|
1476
|
+
}
|
|
1477
|
+
)
|
|
1478
|
+
] }),
|
|
1479
|
+
panel === "changes" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1480
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
1481
|
+
"What would you like to change?",
|
|
1482
|
+
/* @__PURE__ */ jsx(
|
|
1483
|
+
"select",
|
|
1484
|
+
{
|
|
1485
|
+
value: correctionKind,
|
|
1486
|
+
onChange: (e) => setCorrectionKind(e.target.value),
|
|
1487
|
+
children: [
|
|
1488
|
+
"Correct a detail",
|
|
1489
|
+
"Correct a name",
|
|
1490
|
+
"Correct a professional / education detail",
|
|
1491
|
+
"Remove something",
|
|
1492
|
+
"Rewrite something",
|
|
1493
|
+
"Add something",
|
|
1494
|
+
"General comment"
|
|
1495
|
+
].map((kind) => /* @__PURE__ */ jsx("option", { children: kind }, kind))
|
|
1496
|
+
}
|
|
1497
|
+
)
|
|
1498
|
+
] }),
|
|
1499
|
+
/* @__PURE__ */ jsx("p", { children: "A sentence or two is enough. We'll take care of the wording." }),
|
|
1500
|
+
can("PROPOSE_EDITS") && /* @__PURE__ */ jsx("button", { onClick: () => setPanel("edits"), children: "Or edit the wording directly" })
|
|
1501
|
+
] }),
|
|
1502
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
1503
|
+
panel === "changes" ? "What should change?" : "Message (optional)",
|
|
1290
1504
|
/* @__PURE__ */ jsx(
|
|
1291
|
-
"
|
|
1505
|
+
"textarea",
|
|
1292
1506
|
{
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
[key]: e.target.value
|
|
1297
|
-
})
|
|
1507
|
+
rows: 5,
|
|
1508
|
+
value: message,
|
|
1509
|
+
onChange: (e) => setMessage(e.target.value)
|
|
1298
1510
|
}
|
|
1299
1511
|
)
|
|
1300
|
-
] },
|
|
1301
|
-
] }),
|
|
1302
|
-
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: "2. Confirm permission" }) }),
|
|
1303
|
-
/* @__PURE__ */ jsxs("label", { className: "sm-review-check", children: [
|
|
1512
|
+
] }),
|
|
1304
1513
|
/* @__PURE__ */ jsx(
|
|
1305
|
-
"
|
|
1514
|
+
"button",
|
|
1306
1515
|
{
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1516
|
+
disabled: busy || panel === "changes" && !message.trim() || panel === "comment" && !message.trim(),
|
|
1517
|
+
onClick: () => void send(
|
|
1518
|
+
{
|
|
1519
|
+
action: panel === "approve" ? "APPROVE" : panel === "changes" ? "REQUEST_CHANGES" : panel === "decline" ? "DECLINE" : "COMMENT",
|
|
1520
|
+
message: panel === "changes" ? `${correctionKind}: ${message}` : message || null,
|
|
1521
|
+
...panel === "comment" ? {
|
|
1522
|
+
target: {
|
|
1523
|
+
kind: (currentDraft?.data.commentTarget || commentTarget).split(":")[0],
|
|
1524
|
+
reference: (currentDraft?.data.commentTarget || commentTarget).split(":")[1] || null
|
|
1525
|
+
}
|
|
1526
|
+
} : {}
|
|
1527
|
+
},
|
|
1528
|
+
panel === "approve" ? celebration && finalEditor ? approvalThanks : "Your approval has been recorded for this version." : panel === "decline" ? "Thank you for letting us know. The newsroom has received your decision." : "Your message has been sent to the newsroom."
|
|
1529
|
+
),
|
|
1530
|
+
children: panel === "approve" ? `Approve version ${review.revision.number}` : panel === "changes" ? "Send change request" : panel === "decline" ? "Prefer not to publish" : "Send comment"
|
|
1311
1531
|
}
|
|
1312
|
-
)
|
|
1313
|
-
"I confirm that I have the right or permission to provide this media to ",
|
|
1314
|
-
review.publication.name,
|
|
1315
|
-
" for editorial publication."
|
|
1532
|
+
)
|
|
1316
1533
|
] }),
|
|
1317
|
-
/* @__PURE__ */ jsxs(
|
|
1318
|
-
/* @__PURE__ */ jsx("p", { children:
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
}
|
|
1324
|
-
),
|
|
1325
|
-
["approve", "changes", "comment", "decline"].includes(panel) && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1326
|
-
panel === "approve" && /* @__PURE__ */ jsxs("p", { children: [
|
|
1327
|
-
"You are approving version ",
|
|
1328
|
-
review.revision.number,
|
|
1329
|
-
". Changes to the article require a new approval.",
|
|
1330
|
-
review.review_policy === "SUBJECT_APPROVAL_AUTO_PUBLISH" ? " The editor has configured this version to publish or schedule after the required approvals are received." : " The newsroom will complete its editorial workflow before publication."
|
|
1331
|
-
] }),
|
|
1332
|
-
panel === "decline" && /* @__PURE__ */ jsx("p", { children: ["FACT_CHECK", "CONTRIBUTOR_REVIEW"].includes(
|
|
1333
|
-
review.review_policy
|
|
1334
|
-
) ? "You can decline this review. The newsroom may still publish its reporting." : "Declining participation prevents publication of this voluntary announcement." }),
|
|
1335
|
-
panel === "comment" && /* @__PURE__ */ jsxs("label", { children: [
|
|
1336
|
-
"Comment on",
|
|
1337
|
-
/* @__PURE__ */ jsxs(
|
|
1338
|
-
"select",
|
|
1339
|
-
{
|
|
1340
|
-
value: currentDraft?.data.commentTarget || commentTarget,
|
|
1341
|
-
onChange: (e) => {
|
|
1342
|
-
setCommentTarget(e.target.value);
|
|
1343
|
-
if (message) drafts.set("comment", { ...currentDraft?.data, commentTarget: e.target.value });
|
|
1344
|
-
},
|
|
1345
|
-
children: [
|
|
1346
|
-
/* @__PURE__ */ jsx("option", { value: "STORY", children: "Entire story" }),
|
|
1347
|
-
review.revision.document.content_markdown.split(/\n\s*\n/).slice(0, 200).map((_, i) => /* @__PURE__ */ jsxs("option", { value: `PARAGRAPH:${i + 1}`, children: [
|
|
1348
|
-
"Paragraph ",
|
|
1349
|
-
i + 1
|
|
1350
|
-
] }, i)),
|
|
1351
|
-
review.revision.document.media.map((m, i) => /* @__PURE__ */ jsxs(
|
|
1352
|
-
"option",
|
|
1534
|
+
panel === "history" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1535
|
+
/* @__PURE__ */ jsx("p", { children: "Only revisions selected by the editor are visible here." }),
|
|
1536
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
1537
|
+
"Compare from",
|
|
1538
|
+
/* @__PURE__ */ jsxs(
|
|
1539
|
+
"select",
|
|
1353
1540
|
{
|
|
1354
|
-
value:
|
|
1541
|
+
value: compare,
|
|
1542
|
+
onChange: (e) => setCompare(e.target.value),
|
|
1355
1543
|
children: [
|
|
1356
|
-
"
|
|
1357
|
-
|
|
1544
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Choose a shared revision" }),
|
|
1545
|
+
revisions.map((r) => /* @__PURE__ */ jsxs("option", { value: r.id, children: [
|
|
1546
|
+
"Version ",
|
|
1547
|
+
r.number
|
|
1548
|
+
] }, r.id))
|
|
1358
1549
|
]
|
|
1359
|
-
},
|
|
1360
|
-
m.contribution_id
|
|
1361
|
-
)),
|
|
1362
|
-
review.questions.map((q) => /* @__PURE__ */ jsx("option", { value: `QUESTION:${q.id}`, children: q.prompt }, q.id))
|
|
1363
|
-
]
|
|
1364
|
-
}
|
|
1365
|
-
)
|
|
1366
|
-
] }),
|
|
1367
|
-
panel === "changes" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1368
|
-
/* @__PURE__ */ jsxs("label", { children: [
|
|
1369
|
-
"What would you like to change?",
|
|
1370
|
-
/* @__PURE__ */ jsx(
|
|
1371
|
-
"select",
|
|
1372
|
-
{
|
|
1373
|
-
value: correctionKind,
|
|
1374
|
-
onChange: (e) => setCorrectionKind(e.target.value),
|
|
1375
|
-
children: [
|
|
1376
|
-
"Correct a detail",
|
|
1377
|
-
"Correct a name",
|
|
1378
|
-
"Correct a professional / education detail",
|
|
1379
|
-
"Remove something",
|
|
1380
|
-
"Rewrite something",
|
|
1381
|
-
"Add something",
|
|
1382
|
-
"General comment"
|
|
1383
|
-
].map((kind) => /* @__PURE__ */ jsx("option", { children: kind }, kind))
|
|
1384
|
-
}
|
|
1385
|
-
)
|
|
1386
|
-
] }),
|
|
1387
|
-
/* @__PURE__ */ jsx("p", { children: "A sentence or two is enough. We'll take care of the wording." }),
|
|
1388
|
-
can("PROPOSE_EDITS") && /* @__PURE__ */ jsx("button", { onClick: () => setPanel("edits"), children: "Or edit the wording directly" })
|
|
1389
|
-
] }),
|
|
1390
|
-
/* @__PURE__ */ jsxs("label", { children: [
|
|
1391
|
-
panel === "changes" ? "What should change?" : "Message (optional)",
|
|
1392
|
-
/* @__PURE__ */ jsx(
|
|
1393
|
-
"textarea",
|
|
1394
|
-
{
|
|
1395
|
-
rows: 5,
|
|
1396
|
-
value: message,
|
|
1397
|
-
onChange: (e) => setMessage(e.target.value)
|
|
1398
|
-
}
|
|
1399
|
-
)
|
|
1400
|
-
] }),
|
|
1401
|
-
/* @__PURE__ */ jsx(
|
|
1402
|
-
"button",
|
|
1403
|
-
{
|
|
1404
|
-
disabled: busy || panel === "changes" && !message.trim() || panel === "comment" && !message.trim(),
|
|
1405
|
-
onClick: () => void send(
|
|
1406
|
-
{
|
|
1407
|
-
action: panel === "approve" ? "APPROVE" : panel === "changes" ? "REQUEST_CHANGES" : panel === "decline" ? "DECLINE" : "COMMENT",
|
|
1408
|
-
message: panel === "changes" ? `${correctionKind}: ${message}` : message || null,
|
|
1409
|
-
...panel === "comment" ? {
|
|
1410
|
-
target: {
|
|
1411
|
-
kind: (currentDraft?.data.commentTarget || commentTarget).split(":")[0],
|
|
1412
|
-
reference: (currentDraft?.data.commentTarget || commentTarget).split(":")[1] || null
|
|
1413
1550
|
}
|
|
1414
|
-
|
|
1415
|
-
},
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
children: [
|
|
1432
|
-
/* @__PURE__ */ jsx("
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
)
|
|
1454
|
-
] }),
|
|
1455
|
-
selected && selectedAfter && /* @__PURE__ */ jsx(ReviewDiff, { before: selected, after: selectedAfter }),
|
|
1456
|
-
/* @__PURE__ */ jsxs("details", { children: [
|
|
1457
|
-
/* @__PURE__ */ jsx("summary", { children: "Read selected revision" }),
|
|
1458
|
-
/* @__PURE__ */ jsx("h3", { children: selected?.document.title }),
|
|
1459
|
-
/* @__PURE__ */ jsx("p", { children: selected?.document.subtitle }),
|
|
1460
|
-
/* @__PURE__ */ jsx(EditorialNotices, { editorial: selected?.editorial }),
|
|
1461
|
-
/* @__PURE__ */ jsx(
|
|
1462
|
-
"div",
|
|
1463
|
-
{
|
|
1464
|
-
className: "sm-review-prose",
|
|
1465
|
-
dangerouslySetInnerHTML: {
|
|
1466
|
-
__html: selected?.content_html || ""
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
),
|
|
1470
|
-
selected?.document.media.map((m) => /* @__PURE__ */ jsx(PrivatePhoto, { media: m, base }, m.file_id))
|
|
1471
|
-
] })
|
|
1472
|
-
] })
|
|
1473
|
-
] })
|
|
1474
|
-
]
|
|
1551
|
+
)
|
|
1552
|
+
] }),
|
|
1553
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
1554
|
+
"Compare to",
|
|
1555
|
+
/* @__PURE__ */ jsx(
|
|
1556
|
+
"select",
|
|
1557
|
+
{
|
|
1558
|
+
value: compareTo || review.revision.id,
|
|
1559
|
+
onChange: (e) => setCompareTo(e.target.value),
|
|
1560
|
+
children: revisions.map((r) => /* @__PURE__ */ jsxs("option", { value: r.id, children: [
|
|
1561
|
+
"Version ",
|
|
1562
|
+
r.number
|
|
1563
|
+
] }, r.id))
|
|
1564
|
+
}
|
|
1565
|
+
)
|
|
1566
|
+
] }),
|
|
1567
|
+
selected && selectedAfter && /* @__PURE__ */ jsx(ReviewDiff, { before: selected, after: selectedAfter }),
|
|
1568
|
+
/* @__PURE__ */ jsxs("details", { children: [
|
|
1569
|
+
/* @__PURE__ */ jsx("summary", { children: "Read selected revision" }),
|
|
1570
|
+
/* @__PURE__ */ jsx("h3", { children: selected?.document.title }),
|
|
1571
|
+
/* @__PURE__ */ jsx("p", { children: selected?.document.subtitle }),
|
|
1572
|
+
/* @__PURE__ */ jsx(EditorialNotices, { editorial: selected?.editorial }),
|
|
1573
|
+
/* @__PURE__ */ jsx(
|
|
1574
|
+
"div",
|
|
1575
|
+
{
|
|
1576
|
+
className: "sm-review-prose",
|
|
1577
|
+
dangerouslySetInnerHTML: {
|
|
1578
|
+
__html: selected?.content_html || ""
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
),
|
|
1582
|
+
selected?.document.media.map((m) => /* @__PURE__ */ jsx(PrivatePhoto, { media: m, base }, m.file_id))
|
|
1583
|
+
] })
|
|
1584
|
+
] })
|
|
1585
|
+
] })
|
|
1586
|
+
]
|
|
1587
|
+
}
|
|
1588
|
+
)
|
|
1589
|
+
] })
|
|
1475
1590
|
}
|
|
1476
1591
|
),
|
|
1477
1592
|
review.contributions.length > 0 && /* @__PURE__ */ jsxs("section", { className: "sm-review-contributions", children: [
|
|
@@ -1539,7 +1654,14 @@ function StoryReview({
|
|
|
1539
1654
|
publicationFooter
|
|
1540
1655
|
] });
|
|
1541
1656
|
}
|
|
1542
|
-
function PrivatePhoto({
|
|
1657
|
+
function PrivatePhoto({
|
|
1658
|
+
base,
|
|
1659
|
+
media,
|
|
1660
|
+
onChange,
|
|
1661
|
+
onSuggestCorrection,
|
|
1662
|
+
disabled,
|
|
1663
|
+
isInline
|
|
1664
|
+
}) {
|
|
1543
1665
|
const [url, setUrl] = useState("");
|
|
1544
1666
|
const [video, setVideo] = useState(false);
|
|
1545
1667
|
useEffect(() => {
|
|
@@ -1562,25 +1684,69 @@ function PrivatePhoto({ base, media, onChange, disabled }) {
|
|
|
1562
1684
|
if (object) URL.revokeObjectURL(object);
|
|
1563
1685
|
};
|
|
1564
1686
|
}, [base, media.file_id]);
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1687
|
+
const captionInfo = formatArtworkCaption(media);
|
|
1688
|
+
return /* @__PURE__ */ jsxs(
|
|
1689
|
+
"figure",
|
|
1690
|
+
{
|
|
1691
|
+
className: `sm-review-photo-figure ${isInline ? "sm-review-inline-figure" : "sm-review-hero-figure"}`,
|
|
1692
|
+
"data-media-id": media.file_id,
|
|
1693
|
+
children: [
|
|
1694
|
+
url ? video ? /* @__PURE__ */ jsx(
|
|
1695
|
+
"video",
|
|
1696
|
+
{
|
|
1697
|
+
src: url,
|
|
1698
|
+
controls: true,
|
|
1699
|
+
playsInline: true,
|
|
1700
|
+
preload: "metadata",
|
|
1701
|
+
"aria-label": media.alt || captionInfo.title || "Story video"
|
|
1702
|
+
}
|
|
1703
|
+
) : /* @__PURE__ */ jsx(
|
|
1704
|
+
"img",
|
|
1705
|
+
{
|
|
1706
|
+
src: url,
|
|
1707
|
+
alt: media.alt || captionInfo.title || "Story photograph",
|
|
1708
|
+
referrerPolicy: "no-referrer"
|
|
1709
|
+
}
|
|
1710
|
+
) : /* @__PURE__ */ jsx("p", { children: "Media unavailable." }),
|
|
1711
|
+
/* @__PURE__ */ jsxs("figcaption", { className: "sm-review-photo-details", children: [
|
|
1712
|
+
/* @__PURE__ */ jsxs("div", { className: "sm-review-caption-text", children: [
|
|
1713
|
+
captionInfo.title && /* @__PURE__ */ jsx("div", { className: "sm-review-artwork-title", children: /* @__PURE__ */ jsxs("strong", { children: [
|
|
1714
|
+
"\u201C",
|
|
1715
|
+
captionInfo.title,
|
|
1716
|
+
"\u201D"
|
|
1717
|
+
] }) }),
|
|
1718
|
+
captionInfo.artist && /* @__PURE__ */ jsx("div", { className: "sm-review-artist-name", children: captionInfo.artist }),
|
|
1719
|
+
captionInfo.mediumAndDate && /* @__PURE__ */ jsx("div", { className: "sm-review-artwork-medium", children: captionInfo.mediumAndDate }),
|
|
1720
|
+
captionInfo.captionText && /* @__PURE__ */ jsx("div", { className: "sm-review-photo-caption", children: captionInfo.captionText }),
|
|
1721
|
+
captionInfo.credit && /* @__PURE__ */ jsx("div", { className: "sm-review-photo-credit", children: captionInfo.credit }),
|
|
1722
|
+
captionInfo.source && /* @__PURE__ */ jsx("div", { className: "sm-review-photo-source", children: captionInfo.source })
|
|
1723
|
+
] }),
|
|
1724
|
+
/* @__PURE__ */ jsxs("div", { className: "sm-review-photo-controls", children: [
|
|
1725
|
+
onChange && /* @__PURE__ */ jsx(
|
|
1726
|
+
"button",
|
|
1727
|
+
{
|
|
1728
|
+
className: "sm-review-change-photo",
|
|
1729
|
+
type: "button",
|
|
1730
|
+
disabled,
|
|
1731
|
+
onClick: onChange,
|
|
1732
|
+
children: "Change photo"
|
|
1733
|
+
}
|
|
1734
|
+
),
|
|
1735
|
+
onSuggestCorrection && /* @__PURE__ */ jsx(
|
|
1736
|
+
"button",
|
|
1737
|
+
{
|
|
1738
|
+
className: "sm-review-suggest-correction",
|
|
1739
|
+
type: "button",
|
|
1740
|
+
disabled,
|
|
1741
|
+
onClick: onSuggestCorrection,
|
|
1742
|
+
children: "Suggest correction"
|
|
1743
|
+
}
|
|
1744
|
+
)
|
|
1745
|
+
] })
|
|
1746
|
+
] })
|
|
1747
|
+
]
|
|
1748
|
+
}
|
|
1749
|
+
);
|
|
1584
1750
|
}
|
|
1585
1751
|
function ReviewDiff({
|
|
1586
1752
|
before,
|