@scalemule/news-publication 0.0.27 → 0.0.29

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.
@@ -64,7 +64,9 @@ var human = (s) => s.toLowerCase().replaceAll("_", " ");
64
64
  function StoryReview({
65
65
  sessionId,
66
66
  publicationName,
67
- nameplateUrl
67
+ nameplateUrl,
68
+ publicationHeader,
69
+ publicationFooter
68
70
  }) {
69
71
  const base = `/api/news/review/${encodeURIComponent(sessionId)}`;
70
72
  const [review, setReview] = useState(null), [error, setError] = useState(""), [notice, setNotice] = useState(""), [busy, setBusy] = useState(false), [panel, setPanel] = useState("article"), [verification, setVerification] = useState(false), [code, setCode] = useState("");
@@ -73,6 +75,13 @@ function StoryReview({
73
75
  const thanksRef = useRef(null);
74
76
  const [moreQuestions, setMoreQuestions] = useState(false);
75
77
  const [correctionKind, setCorrectionKind] = useState("Correct a detail");
78
+ const [replacementPhoto, setReplacementPhoto] = useState(null);
79
+ function openMedia(photo = null) {
80
+ setReplacementPhoto(photo);
81
+ setFile(null);
82
+ setRights(false);
83
+ setPanel("media");
84
+ }
76
85
  useEffect(() => {
77
86
  if (panel !== "article") {
78
87
  responseRef.current?.scrollIntoView({
@@ -193,13 +202,34 @@ function StoryReview({
193
202
  "metadata",
194
203
  JSON.stringify({ ...mediaInfo, rights_confirmed: true })
195
204
  );
196
- await request("/media", form);
205
+ const received = await request("/media", form);
206
+ let uploadNotice = "Media received privately. The newsroom will review it before publication.";
207
+ if (replacementPhoto) {
208
+ uploadNotice = "Your replacement photo has been sent to the newsroom. The current photo will stay in this preview until we prepare an updated draft.";
209
+ if (can("COMMENT")) {
210
+ try {
211
+ await request("", {
212
+ revision_id: review.revision.id,
213
+ action: "COMMENT",
214
+ message: "Please use my newly uploaded photograph in place of this photo.",
215
+ target: {
216
+ kind: "PHOTO",
217
+ reference: replacementPhoto.contribution_id,
218
+ replacement_contribution_id: received.id
219
+ }
220
+ });
221
+ } catch {
222
+ uploadNotice = "Your photo was uploaded privately, but we couldn't attach the replacement note. Please use Suggest a Change to tell the newsroom which photograph it should replace.";
223
+ }
224
+ } else {
225
+ uploadNotice = "Your photo was uploaded privately for newsroom review. The newsroom will select the photo for the next preview.";
226
+ }
227
+ }
197
228
  await load();
198
229
  setFile(null);
199
230
  setRights(false);
200
- setNotice(
201
- "Media received privately. The newsroom will review it before publication."
202
- );
231
+ setNotice(uploadNotice);
232
+ setReplacementPhoto(null);
203
233
  setPanel("article");
204
234
  } catch (e) {
205
235
  setError(e instanceof Error ? e.message : "Upload failed.");
@@ -214,639 +244,655 @@ function StoryReview({
214
244
  const selected = revisions.find((r) => r.id === compare), selectedAfter = revisions.find(
215
245
  (r) => r.id === (compareTo || review?.revision.id)
216
246
  );
217
- return /* @__PURE__ */ jsxs(
218
- "main",
219
- {
220
- className: `sm-story-review${celebration ? " sm-review-celebration" : ""}`,
221
- children: [
222
- /* @__PURE__ */ jsxs("div", { className: "sm-review-private", children: [
223
- /* @__PURE__ */ jsx("strong", { children: review?.published ? "Private review" : "Private preview \xB7 Not published" }),
224
- /* @__PURE__ */ jsx("span", { children: review?.published ? "This revision has been published. This review link remains private." : `Prepared by ${publicationName} for ${celebration ? "family " : ""}review.` })
247
+ return /* @__PURE__ */ jsxs("div", { className: `sm-review-frame${publicationHeader ? " sm-review-publication-frame" : ""}`, children: [
248
+ /* @__PURE__ */ jsx("div", { className: "sm-review-banner-wrap", children: /* @__PURE__ */ jsxs("div", { className: "sm-review-private", children: [
249
+ /* @__PURE__ */ jsx("strong", { children: review?.published ? "Private review" : "Private preview \xB7 Not published" }),
250
+ /* @__PURE__ */ jsx("span", { children: review?.published ? "This revision has been published. This review link remains private." : `Prepared by ${publicationName} for ${celebration ? "family " : ""}review.` })
251
+ ] }) }),
252
+ publicationHeader ?? /* @__PURE__ */ jsx("div", { className: "sm-review-brand-wrap", children: /* @__PURE__ */ jsxs("header", { className: "sm-review-masthead", children: [
253
+ nameplateUrl && /* @__PURE__ */ jsx("img", { src: nameplateUrl, alt: "", width: 80, height: 80 }),
254
+ /* @__PURE__ */ jsx("span", { children: review?.publication.name || publicationName })
255
+ ] }) }),
256
+ /* @__PURE__ */ jsxs("main", { className: `sm-story-review${celebration ? " sm-review-celebration" : ""}`, children: [
257
+ error && /* @__PURE__ */ jsx("p", { role: "alert", className: "sm-review-alert", children: error }),
258
+ notice && !(approved && finalEditor && notice === approvalThanks) && /* @__PURE__ */ jsx("p", { role: "status", className: "sm-review-notice", children: notice }),
259
+ verification && /* @__PURE__ */ jsxs("section", { className: "sm-review-form", children: [
260
+ /* @__PURE__ */ jsx("h2", { children: "Verify your email" }),
261
+ /* @__PURE__ */ jsx("p", { children: "The editor requires verification using the email address on your invitation. Your story remains private until verified." }),
262
+ /* @__PURE__ */ jsx(
263
+ "button",
264
+ {
265
+ disabled: busy,
266
+ onClick: async () => {
267
+ setBusy(true);
268
+ setError("");
269
+ try {
270
+ await request("/verify", {});
271
+ setNotice(
272
+ "A code was sent to the email address chosen by the editor. It expires in ten minutes."
273
+ );
274
+ } catch (e) {
275
+ setError(
276
+ e instanceof Error ? e.message : "Could not send code."
277
+ );
278
+ } finally {
279
+ setBusy(false);
280
+ }
281
+ },
282
+ children: "Email me a verification code"
283
+ }
284
+ ),
285
+ /* @__PURE__ */ jsxs(
286
+ "form",
287
+ {
288
+ onSubmit: async (e) => {
289
+ e.preventDefault();
290
+ setBusy(true);
291
+ setError("");
292
+ try {
293
+ await request("/verify", { code });
294
+ await load();
295
+ setCode("");
296
+ setNotice("Email verified.");
297
+ } catch (e2) {
298
+ setError(
299
+ e2 instanceof Error ? e2.message : "Verification failed."
300
+ );
301
+ } finally {
302
+ setBusy(false);
303
+ }
304
+ },
305
+ children: [
306
+ /* @__PURE__ */ jsxs("label", { children: [
307
+ "Eight-digit code",
308
+ /* @__PURE__ */ jsx(
309
+ "input",
310
+ {
311
+ inputMode: "numeric",
312
+ autoComplete: "one-time-code",
313
+ pattern: "[0-9]{8}",
314
+ required: true,
315
+ value: code,
316
+ onChange: (e) => setCode(e.target.value)
317
+ }
318
+ )
319
+ ] }),
320
+ /* @__PURE__ */ jsx("button", { disabled: busy, children: "Verify and open preview" })
321
+ ]
322
+ }
323
+ )
324
+ ] }),
325
+ !review && !error && !verification && /* @__PURE__ */ jsx("p", { role: "status", children: "Opening your private preview\u2026" }),
326
+ review && document && /* @__PURE__ */ jsxs(Fragment, { children: [
327
+ celebration ? /* @__PURE__ */ jsxs("div", { className: "sm-review-intro", children: [
328
+ review.revision.number > 1 ? /* @__PURE__ */ jsxs("p", { children: [
329
+ /* @__PURE__ */ jsx("strong", { children: "Updated preview" }),
330
+ " \u2014 We incorporated the information you sent us."
331
+ ] }) : /* @__PURE__ */ jsx("p", { children: "A special occasion, thoughtfully told. Read your announcement below." }),
332
+ /* @__PURE__ */ jsx("a", { href: "#review-options", children: "Review options" })
333
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "sm-review-intro", children: [
334
+ /* @__PURE__ */ jsxs("p", { children: [
335
+ "Prepared for ",
336
+ review.reviewer,
337
+ " \xB7 Version",
338
+ " ",
339
+ review.revision.number
340
+ ] }),
341
+ /* @__PURE__ */ jsx("p", { children: ["FACT_CHECK", "CONTRIBUTOR_REVIEW"].includes(
342
+ review.review_policy
343
+ ) ? "Please help us check the facts and represent your contribution accurately. The newsroom retains the final editorial decision." : "Please review this announcement. You may suggest changes or decline participation." })
225
344
  ] }),
226
- /* @__PURE__ */ jsxs("header", { className: "sm-review-masthead", children: [
227
- nameplateUrl && /* @__PURE__ */ jsx("img", { src: nameplateUrl, alt: "", width: 80, height: 80 }),
228
- /* @__PURE__ */ jsx("span", { children: review?.publication.name || publicationName })
345
+ approved && finalEditor && !review.published && /* @__PURE__ */ jsxs("section", { ref: thanksRef, tabIndex: -1, className: "sm-review-thanks", role: "status", children: [
346
+ /* @__PURE__ */ jsx("h2", { children: "Thank you." }),
347
+ /* @__PURE__ */ jsx("p", { children: "We're glad to help commemorate this special occasion." }),
348
+ /* @__PURE__ */ jsxs("p", { children: [
349
+ "This version has been sent to the ",
350
+ review.publication.name,
351
+ " ",
352
+ "newsroom for final editorial review. It has not been published yet."
353
+ ] })
229
354
  ] }),
230
- error && /* @__PURE__ */ jsx("p", { role: "alert", className: "sm-review-alert", children: error }),
231
- notice && !(approved && finalEditor && notice === approvalThanks) && /* @__PURE__ */ jsx("p", { role: "status", className: "sm-review-notice", children: notice }),
232
- verification && /* @__PURE__ */ jsxs("section", { className: "sm-review-form", children: [
233
- /* @__PURE__ */ jsx("h2", { children: "Verify your email" }),
234
- /* @__PURE__ */ jsx("p", { children: "The editor requires verification using the email address on your invitation. Your story remains private until verified." }),
355
+ /* @__PURE__ */ jsxs("article", { className: "sm-review-article", children: [
356
+ /* @__PURE__ */ jsxs("p", { className: "sm-review-category", children: [
357
+ /* @__PURE__ */ jsx("span", { children: review.revision.document.section }),
358
+ celebration && /* @__PURE__ */ jsx("span", { children: human(review.celebration_type || "") })
359
+ ] }),
360
+ /* @__PURE__ */ jsx("h1", { children: review.revision.document.title }),
361
+ /* @__PURE__ */ jsx("p", { className: "sm-review-dek", children: review.revision.document.subtitle }),
362
+ /* @__PURE__ */ jsx(EditorialNotices, { editorial: review.revision.editorial }),
363
+ review.revision.document.media.filter((m) => m.position === "hero").map((m) => /* @__PURE__ */ jsx(
364
+ PrivatePhoto,
365
+ {
366
+ media: m,
367
+ base,
368
+ onChange: can("UPLOAD_MEDIA") ? () => openMedia(m) : void 0,
369
+ disabled: busy
370
+ },
371
+ m.file_id
372
+ )),
373
+ celebration && !review.revision.document.media.some(
374
+ (m) => m.position === "hero"
375
+ ) && can("UPLOAD_MEDIA") && /* @__PURE__ */ jsxs(
376
+ "aside",
377
+ {
378
+ className: "sm-review-photo-invitation",
379
+ "aria-label": "Family photograph",
380
+ children: [
381
+ /* @__PURE__ */ jsxs("div", { children: [
382
+ /* @__PURE__ */ jsx("strong", { children: "A photograph makes it yours." }),
383
+ /* @__PURE__ */ jsx("p", { children: "Family photograph may be added before publication." })
384
+ ] }),
385
+ /* @__PURE__ */ jsx("button", { onClick: () => openMedia(), children: "+ Add a photograph" })
386
+ ]
387
+ }
388
+ ),
235
389
  /* @__PURE__ */ jsx(
390
+ "div",
391
+ {
392
+ className: "sm-review-prose",
393
+ dangerouslySetInnerHTML: { __html: review.revision.content_html }
394
+ }
395
+ ),
396
+ review.revision.document.media.filter((m) => m.position !== "hero").map((m) => /* @__PURE__ */ jsx(
397
+ PrivatePhoto,
398
+ {
399
+ media: m,
400
+ base,
401
+ onChange: m.kind !== "video" && can("UPLOAD_MEDIA") ? () => openMedia(m) : void 0,
402
+ disabled: busy
403
+ },
404
+ m.file_id
405
+ ))
406
+ ] }),
407
+ celebration && /* @__PURE__ */ jsxs("section", { id: "review-options", className: "sm-review-welcome", children: [
408
+ /* @__PURE__ */ jsx("h2", { children: "Help us make this just right" }),
409
+ /* @__PURE__ */ jsx("p", { children: "We prepared this announcement as a starting point so you don't have to write anything yourself. If everything looks right, you can simply approve it." }),
410
+ /* @__PURE__ */ jsx("p", { children: "If you'd like, you can also correct a detail, add photographs, or tell us a little more about the couple. We'll take care of turning any additional information into the next draft." }),
411
+ can("ANSWER_QUESTIONS") && review.questions.length > 0 && /* @__PURE__ */ jsx(
236
412
  "button",
237
413
  {
238
- disabled: busy,
239
- onClick: async () => {
240
- setBusy(true);
241
- setError("");
242
- try {
243
- await request("/verify", {});
244
- setNotice(
245
- "A code was sent to the email address chosen by the editor. It expires in ten minutes."
246
- );
247
- } catch (e) {
248
- setError(
249
- e instanceof Error ? e.message : "Could not send code."
250
- );
251
- } finally {
252
- setBusy(false);
253
- }
414
+ onClick: () => {
415
+ setMoreQuestions(false);
416
+ setPanel("questions");
254
417
  },
255
- children: "Email me a verification code"
418
+ children: "Tell Us More"
256
419
  }
257
420
  ),
258
- /* @__PURE__ */ jsxs(
259
- "form",
421
+ can("DECLINE") && !review.published && /* @__PURE__ */ jsx(
422
+ "button",
260
423
  {
261
- onSubmit: async (e) => {
262
- e.preventDefault();
263
- setBusy(true);
264
- setError("");
265
- try {
266
- await request("/verify", { code });
267
- await load();
268
- setCode("");
269
- setNotice("Email verified.");
270
- } catch (e2) {
271
- setError(
272
- e2 instanceof Error ? e2.message : "Verification failed."
273
- );
274
- } finally {
275
- setBusy(false);
424
+ className: "sm-review-quiet",
425
+ onClick: () => setPanel("decline"),
426
+ children: "Prefer Not to Publish"
427
+ }
428
+ ),
429
+ can("COMMENT") && /* @__PURE__ */ jsx("button", { className: "sm-review-quiet", onClick: () => setPanel("comment"), children: "Leave a Comment" })
430
+ ] }),
431
+ /* @__PURE__ */ jsxs(
432
+ "nav",
433
+ {
434
+ className: `sm-review-actions${celebration ? " sm-review-concierge-actions" : ""}${panel !== "article" ? " sm-review-actions-editing" : ""}`,
435
+ "aria-label": "Review actions",
436
+ children: [
437
+ can("APPROVE") && !review.published && /* @__PURE__ */ jsx(
438
+ "button",
439
+ {
440
+ className: "sm-review-primary",
441
+ disabled: busy || approved || review.decision === "DECLINED",
442
+ onClick: approve,
443
+ children: approved ? "Thank you \u2014 Approved" : review.review_policy === "FACT_CHECK" ? "Confirm fact check" : celebration ? "Looks Good \u2014 Approve" : "Approve draft"
276
444
  }
277
- },
278
- children: [
445
+ ),
446
+ can("REQUEST_CHANGES") && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("changes"), children: celebration ? "Suggest a Change" : "Request changes" }),
447
+ celebration && can("PROPOSE_EDITS") && !can("REQUEST_CHANGES") && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("edits"), children: "Suggest a Change" }),
448
+ can("UPLOAD_MEDIA") && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => openMedia(), children: celebration ? "Add Photos" : "Add photos" }),
449
+ !celebration && /* @__PURE__ */ jsxs(Fragment, { children: [
450
+ can("PROPOSE_EDITS") && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("edits"), children: "Suggest edits" }),
451
+ can("ANSWER_QUESTIONS") && review.questions.length > 0 && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("questions"), children: "Answer questions" }),
452
+ can("COMMENT") && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("comment"), children: "Leave a comment" })
453
+ ] })
454
+ ]
455
+ }
456
+ ),
457
+ (can("VIEW_SELECTED_HISTORY") && review.history.length > 0 || can("DOWNLOAD_PREVIEW")) && /* @__PURE__ */ jsxs("div", { className: "sm-review-utilities", children: [
458
+ can("VIEW_SELECTED_HISTORY") && review.history.length > 0 && /* @__PURE__ */ jsx("button", { onClick: () => setPanel("history"), children: "See previous previews" }),
459
+ can("DOWNLOAD_PREVIEW") && /* @__PURE__ */ jsx("button", { onClick: () => window.print(), children: "Print / save preview" })
460
+ ] }),
461
+ panel !== "article" && /* @__PURE__ */ jsxs(
462
+ "section",
463
+ {
464
+ ref: responseRef,
465
+ tabIndex: -1,
466
+ className: "sm-review-form",
467
+ "aria-label": "Your response",
468
+ children: [
469
+ /* @__PURE__ */ jsxs("div", { className: "sm-review-form-heading", children: [
470
+ /* @__PURE__ */ jsx("h2", { children: panel === "approve" ? "Approve this exact draft" : panel === "edits" ? "Propose changes" : panel === "media" ? replacementPhoto ? "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" }),
471
+ /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("article"), children: "Close" })
472
+ ] }),
473
+ panel === "edits" && /* @__PURE__ */ jsxs(Fragment, { children: [
474
+ /* @__PURE__ */ jsx("p", { children: "Your suggestions will be reviewed by an editor. They do not replace the newsroom\u2019s draft." }),
279
475
  /* @__PURE__ */ jsxs("label", { children: [
280
- "Eight-digit code",
476
+ "Headline",
281
477
  /* @__PURE__ */ jsx(
282
478
  "input",
283
479
  {
284
- inputMode: "numeric",
285
- autoComplete: "one-time-code",
286
- pattern: "[0-9]{8}",
287
- required: true,
288
- value: code,
289
- onChange: (e) => setCode(e.target.value)
480
+ value: document.title,
481
+ onChange: (e) => setDocument({ ...document, title: e.target.value })
290
482
  }
291
483
  )
292
484
  ] }),
293
- /* @__PURE__ */ jsx("button", { disabled: busy, children: "Verify and open preview" })
294
- ]
295
- }
296
- )
297
- ] }),
298
- !review && !error && !verification && /* @__PURE__ */ jsx("p", { role: "status", children: "Opening your private preview\u2026" }),
299
- review && document && /* @__PURE__ */ jsxs(Fragment, { children: [
300
- celebration ? /* @__PURE__ */ jsxs("div", { className: "sm-review-intro", children: [
301
- review.revision.number > 1 ? /* @__PURE__ */ jsxs("p", { children: [
302
- /* @__PURE__ */ jsx("strong", { children: "Updated preview" }),
303
- " \u2014 We incorporated the information you sent us."
304
- ] }) : /* @__PURE__ */ jsx("p", { children: "A special occasion, thoughtfully told. Read your announcement below." }),
305
- /* @__PURE__ */ jsx("a", { href: "#review-options", children: "Review options" })
306
- ] }) : /* @__PURE__ */ jsxs("div", { className: "sm-review-intro", children: [
307
- /* @__PURE__ */ jsxs("p", { children: [
308
- "Prepared for ",
309
- review.reviewer,
310
- " \xB7 Version",
311
- " ",
312
- review.revision.number
313
- ] }),
314
- /* @__PURE__ */ jsx("p", { children: ["FACT_CHECK", "CONTRIBUTOR_REVIEW"].includes(
315
- review.review_policy
316
- ) ? "Please help us check the facts and represent your contribution accurately. The newsroom retains the final editorial decision." : "Please review this announcement. You may suggest changes or decline participation." })
317
- ] }),
318
- approved && finalEditor && !review.published && /* @__PURE__ */ jsxs("section", { ref: thanksRef, tabIndex: -1, className: "sm-review-thanks", role: "status", children: [
319
- /* @__PURE__ */ jsx("h2", { children: "Thank you." }),
320
- /* @__PURE__ */ jsx("p", { children: "We're glad to help commemorate this special occasion." }),
321
- /* @__PURE__ */ jsxs("p", { children: [
322
- "This version has been sent to the ",
323
- review.publication.name,
324
- " ",
325
- "newsroom for final editorial review. It has not been published yet."
326
- ] })
327
- ] }),
328
- /* @__PURE__ */ jsxs("article", { className: "sm-review-article", children: [
329
- /* @__PURE__ */ jsxs("p", { className: "sm-review-category", children: [
330
- /* @__PURE__ */ jsx("span", { children: review.revision.document.section }),
331
- celebration && /* @__PURE__ */ jsx("span", { children: human(review.celebration_type || "") })
332
- ] }),
333
- /* @__PURE__ */ jsx("h1", { children: review.revision.document.title }),
334
- /* @__PURE__ */ jsx("p", { className: "sm-review-dek", children: review.revision.document.subtitle }),
335
- /* @__PURE__ */ jsx(EditorialNotices, { editorial: review.revision.editorial }),
336
- review.revision.document.media.filter((m) => m.position === "hero").map((m) => /* @__PURE__ */ jsx(PrivatePhoto, { media: m, base }, m.file_id)),
337
- celebration && !review.revision.document.media.some(
338
- (m) => m.position === "hero"
339
- ) && can("UPLOAD_MEDIA") && /* @__PURE__ */ jsxs(
340
- "aside",
341
- {
342
- className: "sm-review-photo-invitation",
343
- "aria-label": "Family photograph",
344
- children: [
345
- /* @__PURE__ */ jsxs("div", { children: [
346
- /* @__PURE__ */ jsx("strong", { children: "A photograph makes it yours." }),
347
- /* @__PURE__ */ jsx("p", { children: "Family photograph may be added before publication." })
348
- ] }),
349
- /* @__PURE__ */ jsx("button", { onClick: () => setPanel("media"), children: "+ Add a photograph" })
350
- ]
351
- }
352
- ),
353
- /* @__PURE__ */ jsx(
354
- "div",
355
- {
356
- className: "sm-review-prose",
357
- dangerouslySetInnerHTML: { __html: review.revision.content_html }
358
- }
359
- ),
360
- review.revision.document.media.filter((m) => m.position !== "hero").map((m) => /* @__PURE__ */ jsx(PrivatePhoto, { media: m, base }, m.file_id))
361
- ] }),
362
- celebration && /* @__PURE__ */ jsxs("section", { id: "review-options", className: "sm-review-welcome", children: [
363
- /* @__PURE__ */ jsx("h2", { children: "Help us make this just right" }),
364
- /* @__PURE__ */ jsx("p", { children: "We prepared this announcement as a starting point so you don't have to write anything yourself. If everything looks right, you can simply approve it." }),
365
- /* @__PURE__ */ jsx("p", { children: "If you'd like, you can also correct a detail, add photographs, or tell us a little more about the couple. We'll take care of turning any additional information into the next draft." }),
366
- can("ANSWER_QUESTIONS") && review.questions.length > 0 && /* @__PURE__ */ jsx(
367
- "button",
368
- {
369
- onClick: () => {
370
- setMoreQuestions(false);
371
- setPanel("questions");
372
- },
373
- children: "Tell Us More"
374
- }
375
- ),
376
- can("DECLINE") && !review.published && /* @__PURE__ */ jsx(
377
- "button",
378
- {
379
- className: "sm-review-quiet",
380
- onClick: () => setPanel("decline"),
381
- children: "Prefer Not to Publish"
382
- }
383
- ),
384
- can("COMMENT") && /* @__PURE__ */ jsx("button", { className: "sm-review-quiet", onClick: () => setPanel("comment"), children: "Leave a Comment" })
385
- ] }),
386
- /* @__PURE__ */ jsxs(
387
- "nav",
388
- {
389
- className: `sm-review-actions${celebration ? " sm-review-concierge-actions" : ""}${panel !== "article" ? " sm-review-actions-editing" : ""}`,
390
- "aria-label": "Review actions",
391
- children: [
392
- can("APPROVE") && !review.published && /* @__PURE__ */ jsx(
393
- "button",
394
- {
395
- className: "sm-review-primary",
396
- disabled: busy || approved || review.decision === "DECLINED",
397
- onClick: approve,
398
- children: approved ? "Thank you \u2014 Approved" : review.review_policy === "FACT_CHECK" ? "Confirm fact check" : celebration ? "Looks Good \u2014 Approve" : "Approve draft"
399
- }
400
- ),
401
- can("REQUEST_CHANGES") && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("changes"), children: celebration ? "Suggest a Change" : "Request changes" }),
402
- celebration && can("PROPOSE_EDITS") && !can("REQUEST_CHANGES") && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("edits"), children: "Suggest a Change" }),
403
- can("UPLOAD_MEDIA") && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("media"), children: celebration ? "Add Photos" : "Add photos" }),
404
- !celebration && /* @__PURE__ */ jsxs(Fragment, { children: [
405
- can("PROPOSE_EDITS") && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("edits"), children: "Suggest edits" }),
406
- can("ANSWER_QUESTIONS") && review.questions.length > 0 && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("questions"), children: "Answer questions" }),
407
- can("COMMENT") && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("comment"), children: "Leave a comment" })
408
- ] })
409
- ]
410
- }
411
- ),
412
- (can("VIEW_SELECTED_HISTORY") && review.history.length > 0 || can("DOWNLOAD_PREVIEW")) && /* @__PURE__ */ jsxs("div", { className: "sm-review-utilities", children: [
413
- can("VIEW_SELECTED_HISTORY") && review.history.length > 0 && /* @__PURE__ */ jsx("button", { onClick: () => setPanel("history"), children: "See previous previews" }),
414
- can("DOWNLOAD_PREVIEW") && /* @__PURE__ */ jsx("button", { onClick: () => window.print(), children: "Print / save preview" })
415
- ] }),
416
- panel !== "article" && /* @__PURE__ */ jsxs(
417
- "section",
418
- {
419
- ref: responseRef,
420
- tabIndex: -1,
421
- className: "sm-review-form",
422
- "aria-label": "Your response",
423
- children: [
424
- /* @__PURE__ */ jsxs("div", { className: "sm-review-form-heading", children: [
425
- /* @__PURE__ */ jsx("h2", { children: panel === "approve" ? "Approve this exact draft" : panel === "edits" ? "Propose changes" : panel === "media" ? "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" }),
426
- /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("article"), children: "Close" })
485
+ /* @__PURE__ */ jsxs("label", { children: [
486
+ "Short introduction",
487
+ /* @__PURE__ */ jsx(
488
+ "input",
489
+ {
490
+ value: document.subtitle,
491
+ onChange: (e) => setDocument({ ...document, subtitle: e.target.value })
492
+ }
493
+ )
427
494
  ] }),
428
- panel === "edits" && /* @__PURE__ */ jsxs(Fragment, { children: [
429
- /* @__PURE__ */ jsx("p", { children: "Your suggestions will be reviewed by an editor. They do not replace the newsroom\u2019s draft." }),
430
- /* @__PURE__ */ jsxs("label", { children: [
431
- "Headline",
432
- /* @__PURE__ */ jsx(
433
- "input",
434
- {
435
- value: document.title,
436
- onChange: (e) => setDocument({ ...document, title: e.target.value })
437
- }
438
- )
439
- ] }),
440
- /* @__PURE__ */ jsxs("label", { children: [
441
- "Short introduction",
442
- /* @__PURE__ */ jsx(
443
- "input",
444
- {
445
- value: document.subtitle,
446
- onChange: (e) => setDocument({ ...document, subtitle: e.target.value })
447
- }
448
- )
449
- ] }),
450
- /* @__PURE__ */ jsxs("label", { children: [
451
- "Suggested article text",
452
- /* @__PURE__ */ jsx(
453
- "textarea",
454
- {
455
- rows: 16,
456
- value: document.content_markdown,
457
- onChange: (e) => setDocument({
458
- ...document,
459
- content_markdown: e.target.value
460
- })
461
- }
462
- )
463
- ] }),
495
+ /* @__PURE__ */ jsxs("label", { children: [
496
+ "Suggested article text",
464
497
  /* @__PURE__ */ jsx(
465
- "button",
498
+ "textarea",
466
499
  {
467
- disabled: busy,
468
- onClick: () => void send(
469
- {
470
- action: "PROPOSE_EDITS",
471
- title: document.title,
472
- subtitle: document.subtitle,
473
- content_markdown: document.content_markdown,
474
- message
475
- },
476
- "Your proposed changes have been sent to the newsroom."
477
- ),
478
- children: "Send proposed changes"
500
+ rows: 16,
501
+ value: document.content_markdown,
502
+ onChange: (e) => setDocument({
503
+ ...document,
504
+ content_markdown: e.target.value
505
+ })
479
506
  }
480
507
  )
481
508
  ] }),
482
- panel === "questions" && /* @__PURE__ */ jsxs(
483
- "form",
509
+ /* @__PURE__ */ jsx(
510
+ "button",
484
511
  {
485
- onSubmit: (e) => {
486
- e.preventDefault();
487
- void send(
488
- { action: "ANSWER_QUESTIONS", answers },
489
- "Thank you for sharing. We'll take care of turning your answers into an updated draft."
490
- );
491
- },
492
- children: [
493
- /* @__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." }),
494
- review.questions.filter((q, i) => moreQuestions || i < 5 || q.required).map((q) => /* @__PURE__ */ jsxs("label", { children: [
495
- q.prompt,
496
- q.required ? " (required)" : " (optional)",
497
- /* @__PURE__ */ jsx(
498
- "textarea",
499
- {
500
- required: q.required,
501
- rows: 3,
502
- value: answers[q.id] || "",
503
- onChange: (e) => setAnswers({ ...answers, [q.id]: e.target.value })
504
- }
505
- )
506
- ] }, q.id)),
512
+ disabled: busy,
513
+ onClick: () => void send(
514
+ {
515
+ action: "PROPOSE_EDITS",
516
+ title: document.title,
517
+ subtitle: document.subtitle,
518
+ content_markdown: document.content_markdown,
519
+ message
520
+ },
521
+ "Your proposed changes have been sent to the newsroom."
522
+ ),
523
+ children: "Send proposed changes"
524
+ }
525
+ )
526
+ ] }),
527
+ panel === "questions" && /* @__PURE__ */ jsxs(
528
+ "form",
529
+ {
530
+ onSubmit: (e) => {
531
+ e.preventDefault();
532
+ void send(
533
+ { action: "ANSWER_QUESTIONS", answers },
534
+ "Thank you for sharing. We'll take care of turning your answers into an updated draft."
535
+ );
536
+ },
537
+ children: [
538
+ /* @__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." }),
539
+ review.questions.filter((q, i) => moreQuestions || i < 5 || q.required).map((q) => /* @__PURE__ */ jsxs("label", { children: [
540
+ q.prompt,
541
+ q.required ? " (required)" : " (optional)",
507
542
  /* @__PURE__ */ jsx(
508
- "button",
543
+ "textarea",
509
544
  {
510
- className: "sm-review-primary",
511
- disabled: busy || !Object.values(answers).some((a) => a.trim()),
512
- children: "Send These Answers"
513
- }
514
- ),
515
- !moreQuestions && review.questions.length > 5 && /* @__PURE__ */ jsx(
516
- "button",
517
- {
518
- type: "button",
519
- onClick: () => setMoreQuestions(true),
520
- children: "Answer More Questions"
545
+ required: q.required,
546
+ rows: 3,
547
+ value: answers[q.id] || "",
548
+ onChange: (e) => setAnswers({ ...answers, [q.id]: e.target.value })
521
549
  }
522
550
  )
523
- ]
524
- }
525
- ),
526
- panel === "metadata" && /* @__PURE__ */ jsxs(Fragment, { children: [
527
- /* @__PURE__ */ jsx("p", { children: "Caption and credit changes are proposals for the newsroom; historical captions remain intact." }),
528
- ["caption", "credit", "alt"].map((key) => /* @__PURE__ */ jsxs("label", { children: [
529
- key,
551
+ ] }, q.id)),
530
552
  /* @__PURE__ */ jsx(
531
- "input",
553
+ "button",
554
+ {
555
+ className: "sm-review-primary",
556
+ disabled: busy || !Object.values(answers).some((a) => a.trim()),
557
+ children: "Send These Answers"
558
+ }
559
+ ),
560
+ !moreQuestions && review.questions.length > 5 && /* @__PURE__ */ jsx(
561
+ "button",
532
562
  {
533
- value: mediaInfo[key],
534
- onChange: (e) => setMediaInfo({ ...mediaInfo, [key]: e.target.value })
563
+ type: "button",
564
+ onClick: () => setMoreQuestions(true),
565
+ children: "Answer More Questions"
535
566
  }
536
567
  )
537
- ] }, key)),
568
+ ]
569
+ }
570
+ ),
571
+ panel === "metadata" && /* @__PURE__ */ jsxs(Fragment, { children: [
572
+ /* @__PURE__ */ jsx("p", { children: "Caption and credit changes are proposals for the newsroom; historical captions remain intact." }),
573
+ ["caption", "credit", "alt"].map((key) => /* @__PURE__ */ jsxs("label", { children: [
574
+ key,
538
575
  /* @__PURE__ */ jsx(
539
- "button",
576
+ "input",
540
577
  {
541
- disabled: busy,
542
- onClick: () => void send(
543
- {
544
- action: "EDIT_MEDIA_METADATA",
545
- contribution_id: editingMedia,
546
- caption: mediaInfo.caption,
547
- credit: mediaInfo.credit,
548
- alt: mediaInfo.alt
549
- },
550
- "Your proposed media descriptions have been sent to the newsroom."
551
- ),
552
- children: "Propose caption / credit changes"
578
+ value: mediaInfo[key],
579
+ onChange: (e) => setMediaInfo({ ...mediaInfo, [key]: e.target.value })
553
580
  }
554
581
  )
555
- ] }),
556
- panel === "media" && /* @__PURE__ */ jsxs(
557
- "form",
582
+ ] }, key)),
583
+ /* @__PURE__ */ jsx(
584
+ "button",
558
585
  {
559
- onSubmit: (e) => {
560
- e.preventDefault();
561
- void upload();
562
- },
563
- children: [
564
- /* @__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." }),
565
- /* @__PURE__ */ jsxs("label", { children: [
566
- "Photograph or video",
567
- /* @__PURE__ */ jsx(
568
- "input",
569
- {
570
- type: "file",
571
- accept: "image/jpeg,image/png,image/webp,video/mp4,video/webm",
572
- required: true,
573
- onChange: (e) => setFile(e.target.files?.[0] || null)
574
- }
575
- )
576
- ] }),
577
- /* @__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." }),
586
+ disabled: busy,
587
+ onClick: () => void send(
588
+ {
589
+ action: "EDIT_MEDIA_METADATA",
590
+ contribution_id: editingMedia,
591
+ caption: mediaInfo.caption,
592
+ credit: mediaInfo.credit,
593
+ alt: mediaInfo.alt
594
+ },
595
+ "Your proposed media descriptions have been sent to the newsroom."
596
+ ),
597
+ children: "Propose caption / credit changes"
598
+ }
599
+ )
600
+ ] }),
601
+ panel === "media" && /* @__PURE__ */ jsxs(
602
+ "form",
603
+ {
604
+ onSubmit: (e) => {
605
+ e.preventDefault();
606
+ void upload();
607
+ },
608
+ children: [
609
+ replacementPhoto && /* @__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." }),
610
+ /* @__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." }),
611
+ /* @__PURE__ */ jsxs("label", { children: [
612
+ "Photograph or video",
613
+ /* @__PURE__ */ jsx(
614
+ "input",
615
+ {
616
+ type: "file",
617
+ accept: "image/jpeg,image/png,image/webp,video/mp4,video/webm",
618
+ required: true,
619
+ onChange: (e) => setFile(e.target.files?.[0] || null)
620
+ }
621
+ )
622
+ ] }),
623
+ /* @__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." }),
624
+ Object.entries({
625
+ caption: "Caption (optional)",
626
+ credit: "Photographer / credit (optional)"
627
+ }).map(([key, label]) => /* @__PURE__ */ jsxs("label", { children: [
628
+ label,
629
+ /* @__PURE__ */ jsx(
630
+ "input",
631
+ {
632
+ value: mediaInfo[key],
633
+ onChange: (e) => setMediaInfo({ ...mediaInfo, [key]: e.target.value })
634
+ }
635
+ )
636
+ ] }, key)),
637
+ /* @__PURE__ */ jsxs("details", { className: "sm-review-media-details", children: [
638
+ /* @__PURE__ */ jsx("summary", { children: "Add more photograph details (optional)" }),
578
639
  Object.entries({
579
- caption: "Caption (optional)",
580
- credit: "Photographer / credit (optional)"
640
+ who_is_pictured: "Who is pictured?",
641
+ creator: "Photographer / creator",
642
+ when_taken: "When was it taken?",
643
+ where_taken: "Where was it taken?",
644
+ alt: "Describe the photograph for readers who cannot see it"
581
645
  }).map(([key, label]) => /* @__PURE__ */ jsxs("label", { children: [
582
646
  label,
583
647
  /* @__PURE__ */ jsx(
584
648
  "input",
585
649
  {
586
650
  value: mediaInfo[key],
587
- onChange: (e) => setMediaInfo({ ...mediaInfo, [key]: e.target.value })
651
+ onChange: (e) => setMediaInfo({
652
+ ...mediaInfo,
653
+ [key]: e.target.value
654
+ })
588
655
  }
589
656
  )
590
- ] }, key)),
591
- /* @__PURE__ */ jsxs("details", { className: "sm-review-media-details", children: [
592
- /* @__PURE__ */ jsx("summary", { children: "Add more photograph details (optional)" }),
593
- Object.entries({
594
- who_is_pictured: "Who is pictured?",
595
- creator: "Photographer / creator",
596
- when_taken: "When was it taken?",
597
- where_taken: "Where was it taken?",
598
- alt: "Describe the photograph for readers who cannot see it"
599
- }).map(([key, label]) => /* @__PURE__ */ jsxs("label", { children: [
600
- label,
601
- /* @__PURE__ */ jsx(
602
- "input",
603
- {
604
- value: mediaInfo[key],
605
- onChange: (e) => setMediaInfo({
606
- ...mediaInfo,
607
- [key]: e.target.value
608
- })
609
- }
610
- )
611
- ] }, key))
612
- ] }),
613
- /* @__PURE__ */ jsxs("label", { className: "sm-review-check", children: [
614
- /* @__PURE__ */ jsx(
615
- "input",
616
- {
617
- type: "checkbox",
618
- required: true,
619
- checked: rights,
620
- onChange: (e) => setRights(e.target.checked)
621
- }
622
- ),
623
- "I confirm that I have the right or permission to provide this media to ",
624
- review.publication.name,
625
- " for editorial publication."
626
- ] }),
627
- /* @__PURE__ */ jsx("button", { disabled: busy || !rights || !file, children: "Upload privately" })
628
- ]
629
- }
630
- ),
631
- ["approve", "changes", "comment", "decline"].includes(panel) && /* @__PURE__ */ jsxs(Fragment, { children: [
632
- panel === "approve" && /* @__PURE__ */ jsxs("p", { children: [
633
- "You are approving version ",
634
- review.revision.number,
635
- ". Changes to the article require a new approval.",
636
- 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."
637
- ] }),
638
- panel === "decline" && /* @__PURE__ */ jsx("p", { children: ["FACT_CHECK", "CONTRIBUTOR_REVIEW"].includes(
639
- review.review_policy
640
- ) ? "You can decline this review. The newsroom may still publish its reporting." : "Declining participation prevents publication of this voluntary announcement." }),
641
- panel === "comment" && /* @__PURE__ */ jsxs("label", { children: [
642
- "Comment on",
643
- /* @__PURE__ */ jsxs(
644
- "select",
645
- {
646
- value: commentTarget,
647
- onChange: (e) => setCommentTarget(e.target.value),
648
- children: [
649
- /* @__PURE__ */ jsx("option", { value: "STORY", children: "Entire story" }),
650
- review.revision.document.content_markdown.split(/\n\s*\n/).slice(0, 200).map((_, i) => /* @__PURE__ */ jsxs("option", { value: `PARAGRAPH:${i + 1}`, children: [
651
- "Paragraph ",
652
- i + 1
653
- ] }, i)),
654
- review.revision.document.media.map((m, i) => /* @__PURE__ */ jsxs(
655
- "option",
656
- {
657
- value: `MEDIA:${m.contribution_id}`,
658
- children: [
659
- "Photo / caption ",
660
- i + 1
661
- ]
662
- },
663
- m.contribution_id
664
- )),
665
- review.questions.map((q) => /* @__PURE__ */ jsx("option", { value: `QUESTION:${q.id}`, children: q.prompt }, q.id))
666
- ]
667
- }
668
- )
669
- ] }),
670
- panel === "changes" && /* @__PURE__ */ jsxs(Fragment, { children: [
671
- /* @__PURE__ */ jsxs("label", { children: [
672
- "What would you like to change?",
657
+ ] }, key))
658
+ ] }),
659
+ /* @__PURE__ */ jsxs("label", { className: "sm-review-check", children: [
673
660
  /* @__PURE__ */ jsx(
674
- "select",
661
+ "input",
675
662
  {
676
- value: correctionKind,
677
- onChange: (e) => setCorrectionKind(e.target.value),
678
- children: [
679
- "Correct a detail",
680
- "Correct a name",
681
- "Correct a professional / education detail",
682
- "Remove something",
683
- "Rewrite something",
684
- "Add something",
685
- "General comment"
686
- ].map((kind) => /* @__PURE__ */ jsx("option", { children: kind }, kind))
663
+ type: "checkbox",
664
+ required: true,
665
+ checked: rights,
666
+ onChange: (e) => setRights(e.target.checked)
687
667
  }
688
- )
668
+ ),
669
+ "I confirm that I have the right or permission to provide this media to ",
670
+ review.publication.name,
671
+ " for editorial publication."
689
672
  ] }),
690
- /* @__PURE__ */ jsx("p", { children: "A sentence or two is enough. We'll take care of the wording." }),
691
- can("PROPOSE_EDITS") && /* @__PURE__ */ jsx("button", { onClick: () => setPanel("edits"), children: "Or edit the wording directly" })
692
- ] }),
693
- /* @__PURE__ */ jsxs("label", { children: [
694
- panel === "changes" ? "What should change?" : "Message (optional)",
695
- /* @__PURE__ */ jsx(
696
- "textarea",
697
- {
698
- rows: 5,
699
- value: message,
700
- onChange: (e) => setMessage(e.target.value)
701
- }
702
- )
703
- ] }),
704
- /* @__PURE__ */ jsx(
705
- "button",
673
+ /* @__PURE__ */ jsx("button", { disabled: busy || !rights || !file, children: "Upload privately" })
674
+ ]
675
+ }
676
+ ),
677
+ ["approve", "changes", "comment", "decline"].includes(panel) && /* @__PURE__ */ jsxs(Fragment, { children: [
678
+ panel === "approve" && /* @__PURE__ */ jsxs("p", { children: [
679
+ "You are approving version ",
680
+ review.revision.number,
681
+ ". Changes to the article require a new approval.",
682
+ 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."
683
+ ] }),
684
+ panel === "decline" && /* @__PURE__ */ jsx("p", { children: ["FACT_CHECK", "CONTRIBUTOR_REVIEW"].includes(
685
+ review.review_policy
686
+ ) ? "You can decline this review. The newsroom may still publish its reporting." : "Declining participation prevents publication of this voluntary announcement." }),
687
+ panel === "comment" && /* @__PURE__ */ jsxs("label", { children: [
688
+ "Comment on",
689
+ /* @__PURE__ */ jsxs(
690
+ "select",
706
691
  {
707
- disabled: busy || panel === "changes" && !message.trim() || panel === "comment" && !message.trim(),
708
- onClick: () => void send(
709
- {
710
- action: panel === "approve" ? "APPROVE" : panel === "changes" ? "REQUEST_CHANGES" : panel === "decline" ? "DECLINE" : "COMMENT",
711
- message: panel === "changes" ? `${correctionKind}: ${message}` : message || null,
712
- ...panel === "comment" ? {
713
- target: {
714
- kind: commentTarget.split(":")[0],
715
- reference: commentTarget.split(":")[1] || null
716
- }
717
- } : {}
718
- },
719
- 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."
720
- ),
721
- children: panel === "approve" ? `Approve version ${review.revision.number}` : panel === "changes" ? "Send change request" : panel === "decline" ? "Prefer not to publish" : "Send comment"
692
+ value: commentTarget,
693
+ onChange: (e) => setCommentTarget(e.target.value),
694
+ children: [
695
+ /* @__PURE__ */ jsx("option", { value: "STORY", children: "Entire story" }),
696
+ review.revision.document.content_markdown.split(/\n\s*\n/).slice(0, 200).map((_, i) => /* @__PURE__ */ jsxs("option", { value: `PARAGRAPH:${i + 1}`, children: [
697
+ "Paragraph ",
698
+ i + 1
699
+ ] }, i)),
700
+ review.revision.document.media.map((m, i) => /* @__PURE__ */ jsxs(
701
+ "option",
702
+ {
703
+ value: `MEDIA:${m.contribution_id}`,
704
+ children: [
705
+ "Photo / caption ",
706
+ i + 1
707
+ ]
708
+ },
709
+ m.contribution_id
710
+ )),
711
+ review.questions.map((q) => /* @__PURE__ */ jsx("option", { value: `QUESTION:${q.id}`, children: q.prompt }, q.id))
712
+ ]
722
713
  }
723
714
  )
724
715
  ] }),
725
- panel === "history" && /* @__PURE__ */ jsxs(Fragment, { children: [
726
- /* @__PURE__ */ jsx("p", { children: "Only revisions selected by the editor are visible here." }),
716
+ panel === "changes" && /* @__PURE__ */ jsxs(Fragment, { children: [
727
717
  /* @__PURE__ */ jsxs("label", { children: [
728
- "Compare from",
729
- /* @__PURE__ */ jsxs(
730
- "select",
731
- {
732
- value: compare,
733
- onChange: (e) => setCompare(e.target.value),
734
- children: [
735
- /* @__PURE__ */ jsx("option", { value: "", children: "Choose a shared revision" }),
736
- revisions.map((r) => /* @__PURE__ */ jsxs("option", { value: r.id, children: [
737
- "Version ",
738
- r.number
739
- ] }, r.id))
740
- ]
741
- }
742
- )
743
- ] }),
744
- /* @__PURE__ */ jsxs("label", { children: [
745
- "Compare to",
718
+ "What would you like to change?",
746
719
  /* @__PURE__ */ jsx(
747
720
  "select",
748
721
  {
749
- value: compareTo || review.revision.id,
750
- onChange: (e) => setCompareTo(e.target.value),
751
- children: revisions.map((r) => /* @__PURE__ */ jsxs("option", { value: r.id, children: [
752
- "Version ",
753
- r.number
754
- ] }, r.id))
722
+ value: correctionKind,
723
+ onChange: (e) => setCorrectionKind(e.target.value),
724
+ children: [
725
+ "Correct a detail",
726
+ "Correct a name",
727
+ "Correct a professional / education detail",
728
+ "Remove something",
729
+ "Rewrite something",
730
+ "Add something",
731
+ "General comment"
732
+ ].map((kind) => /* @__PURE__ */ jsx("option", { children: kind }, kind))
755
733
  }
756
734
  )
757
735
  ] }),
758
- selected && selectedAfter && /* @__PURE__ */ jsx(ReviewDiff, { before: selected, after: selectedAfter }),
759
- /* @__PURE__ */ jsxs("details", { children: [
760
- /* @__PURE__ */ jsx("summary", { children: "Read selected revision" }),
761
- /* @__PURE__ */ jsx("h3", { children: selected?.document.title }),
762
- /* @__PURE__ */ jsx("p", { children: selected?.document.subtitle }),
763
- /* @__PURE__ */ jsx(EditorialNotices, { editorial: selected?.editorial }),
764
- /* @__PURE__ */ jsx(
765
- "div",
766
- {
767
- className: "sm-review-prose",
768
- dangerouslySetInnerHTML: {
769
- __html: selected?.content_html || ""
770
- }
771
- }
772
- ),
773
- selected?.document.media.map((m) => /* @__PURE__ */ jsx(PrivatePhoto, { media: m, base }, m.file_id))
774
- ] })
775
- ] })
776
- ]
777
- }
778
- ),
779
- review.contributions.length > 0 && /* @__PURE__ */ jsxs("section", { className: "sm-review-contributions", children: [
780
- /* @__PURE__ */ jsx("h2", { children: "Your contributions and newsroom messages" }),
781
- review.contributions.map((c) => /* @__PURE__ */ jsxs("div", { children: [
782
- /* @__PURE__ */ jsxs("p", { children: [
783
- /* @__PURE__ */ jsx("strong", { children: human(c.kind) }),
784
- " \xB7 ",
785
- human(c.state)
786
- ] }),
787
- c.payload.target && /* @__PURE__ */ jsxs("p", { children: [
788
- "Regarding ",
789
- human(c.payload.target.kind),
790
- " ",
791
- c.payload.target.reference
792
- ] }),
793
- c.payload.message && /* @__PURE__ */ jsx("p", { children: c.payload.message }),
794
- c.payload.answers && Object.entries(c.payload.answers).map(([q, a]) => /* @__PURE__ */ jsx("p", { children: a }, q)),
795
- c.kind === "MEDIA" && c.payload.file_id && /* @__PURE__ */ jsxs(Fragment, { children: [
796
- /* @__PURE__ */ jsx(
797
- PrivatePhoto,
798
- {
799
- base,
800
- media: {
801
- file_id: c.payload.file_id,
802
- caption: c.payload.caption || "",
803
- credit: c.payload.credit || "",
804
- alt: c.payload.caption || "",
805
- position: "gallery",
806
- contribution_id: c.id
736
+ /* @__PURE__ */ jsx("p", { children: "A sentence or two is enough. We'll take care of the wording." }),
737
+ can("PROPOSE_EDITS") && /* @__PURE__ */ jsx("button", { onClick: () => setPanel("edits"), children: "Or edit the wording directly" })
738
+ ] }),
739
+ /* @__PURE__ */ jsxs("label", { children: [
740
+ panel === "changes" ? "What should change?" : "Message (optional)",
741
+ /* @__PURE__ */ jsx(
742
+ "textarea",
743
+ {
744
+ rows: 5,
745
+ value: message,
746
+ onChange: (e) => setMessage(e.target.value)
807
747
  }
808
- }
809
- ),
810
- c.state !== "WITHDRAWN" && can("EDIT_MEDIA_METADATA") && /* @__PURE__ */ jsx(
811
- "button",
812
- {
813
- onClick: () => {
814
- setEditingMedia(c.id);
815
- setMediaInfo({
816
- ...mediaInfo,
817
- caption: c.payload.caption || "",
818
- credit: c.payload.credit || "",
819
- alt: c.payload.caption || ""
820
- });
821
- setPanel("metadata");
822
- },
823
- children: "Suggest caption / credit changes"
824
- }
825
- ),
826
- c.state !== "WITHDRAWN" && can("UPLOAD_MEDIA") && /* @__PURE__ */ jsx(
748
+ )
749
+ ] }),
750
+ /* @__PURE__ */ jsx(
827
751
  "button",
828
752
  {
829
- disabled: busy,
753
+ disabled: busy || panel === "changes" && !message.trim() || panel === "comment" && !message.trim(),
830
754
  onClick: () => void send(
831
755
  {
832
- action: "WITHDRAW_MEDIA",
833
- contribution_id: c.id
756
+ action: panel === "approve" ? "APPROVE" : panel === "changes" ? "REQUEST_CHANGES" : panel === "decline" ? "DECLINE" : "COMMENT",
757
+ message: panel === "changes" ? `${correctionKind}: ${message}` : message || null,
758
+ ...panel === "comment" ? {
759
+ target: {
760
+ kind: commentTarget.split(":")[0],
761
+ reference: commentTarget.split(":")[1] || null
762
+ }
763
+ } : {}
834
764
  },
835
- "Your media has been withdrawn from consideration."
765
+ 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."
836
766
  ),
837
- children: "Withdraw this media"
767
+ children: panel === "approve" ? `Approve version ${review.revision.number}` : panel === "changes" ? "Send change request" : panel === "decline" ? "Prefer not to publish" : "Send comment"
838
768
  }
839
769
  )
770
+ ] }),
771
+ panel === "history" && /* @__PURE__ */ jsxs(Fragment, { children: [
772
+ /* @__PURE__ */ jsx("p", { children: "Only revisions selected by the editor are visible here." }),
773
+ /* @__PURE__ */ jsxs("label", { children: [
774
+ "Compare from",
775
+ /* @__PURE__ */ jsxs(
776
+ "select",
777
+ {
778
+ value: compare,
779
+ onChange: (e) => setCompare(e.target.value),
780
+ children: [
781
+ /* @__PURE__ */ jsx("option", { value: "", children: "Choose a shared revision" }),
782
+ revisions.map((r) => /* @__PURE__ */ jsxs("option", { value: r.id, children: [
783
+ "Version ",
784
+ r.number
785
+ ] }, r.id))
786
+ ]
787
+ }
788
+ )
789
+ ] }),
790
+ /* @__PURE__ */ jsxs("label", { children: [
791
+ "Compare to",
792
+ /* @__PURE__ */ jsx(
793
+ "select",
794
+ {
795
+ value: compareTo || review.revision.id,
796
+ onChange: (e) => setCompareTo(e.target.value),
797
+ children: revisions.map((r) => /* @__PURE__ */ jsxs("option", { value: r.id, children: [
798
+ "Version ",
799
+ r.number
800
+ ] }, r.id))
801
+ }
802
+ )
803
+ ] }),
804
+ selected && selectedAfter && /* @__PURE__ */ jsx(ReviewDiff, { before: selected, after: selectedAfter }),
805
+ /* @__PURE__ */ jsxs("details", { children: [
806
+ /* @__PURE__ */ jsx("summary", { children: "Read selected revision" }),
807
+ /* @__PURE__ */ jsx("h3", { children: selected?.document.title }),
808
+ /* @__PURE__ */ jsx("p", { children: selected?.document.subtitle }),
809
+ /* @__PURE__ */ jsx(EditorialNotices, { editorial: selected?.editorial }),
810
+ /* @__PURE__ */ jsx(
811
+ "div",
812
+ {
813
+ className: "sm-review-prose",
814
+ dangerouslySetInnerHTML: {
815
+ __html: selected?.content_html || ""
816
+ }
817
+ }
818
+ ),
819
+ selected?.document.media.map((m) => /* @__PURE__ */ jsx(PrivatePhoto, { media: m, base }, m.file_id))
820
+ ] })
840
821
  ] })
841
- ] }, c.id))
842
- ] }),
843
- !celebration && can("DECLINE") && !review.published && /* @__PURE__ */ jsx("footer", { className: "sm-review-decline", children: /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("decline"), children: "Decline participation / please don\u2019t publish this announcement" }) })
844
- ] })
845
- ]
846
- }
847
- );
822
+ ]
823
+ }
824
+ ),
825
+ review.contributions.length > 0 && /* @__PURE__ */ jsxs("section", { className: "sm-review-contributions", children: [
826
+ /* @__PURE__ */ jsx("h2", { children: "Your contributions and newsroom messages" }),
827
+ review.contributions.map((c) => /* @__PURE__ */ jsxs("div", { children: [
828
+ /* @__PURE__ */ jsxs("p", { children: [
829
+ /* @__PURE__ */ jsx("strong", { children: human(c.kind) }),
830
+ " \xB7 ",
831
+ human(c.state)
832
+ ] }),
833
+ c.payload.target && /* @__PURE__ */ jsxs("p", { children: [
834
+ "Regarding ",
835
+ human(c.payload.target.kind),
836
+ " ",
837
+ c.payload.target.reference
838
+ ] }),
839
+ c.payload.message && /* @__PURE__ */ jsx("p", { children: c.payload.message }),
840
+ c.payload.answers && Object.entries(c.payload.answers).map(([q, a]) => /* @__PURE__ */ jsx("p", { children: a }, q)),
841
+ c.kind === "MEDIA" && c.payload.file_id && /* @__PURE__ */ jsxs(Fragment, { children: [
842
+ /* @__PURE__ */ jsx(
843
+ PrivatePhoto,
844
+ {
845
+ base,
846
+ media: {
847
+ file_id: c.payload.file_id,
848
+ caption: c.payload.caption || "",
849
+ credit: c.payload.credit || "",
850
+ alt: c.payload.caption || "",
851
+ position: "gallery",
852
+ contribution_id: c.id
853
+ }
854
+ }
855
+ ),
856
+ c.state !== "WITHDRAWN" && can("EDIT_MEDIA_METADATA") && /* @__PURE__ */ jsx(
857
+ "button",
858
+ {
859
+ onClick: () => {
860
+ setEditingMedia(c.id);
861
+ setMediaInfo({
862
+ ...mediaInfo,
863
+ caption: c.payload.caption || "",
864
+ credit: c.payload.credit || "",
865
+ alt: c.payload.caption || ""
866
+ });
867
+ setPanel("metadata");
868
+ },
869
+ children: "Suggest caption / credit changes"
870
+ }
871
+ ),
872
+ c.state !== "WITHDRAWN" && can("UPLOAD_MEDIA") && /* @__PURE__ */ jsx(
873
+ "button",
874
+ {
875
+ disabled: busy,
876
+ onClick: () => void send(
877
+ {
878
+ action: "WITHDRAW_MEDIA",
879
+ contribution_id: c.id
880
+ },
881
+ "Your media has been withdrawn from consideration."
882
+ ),
883
+ children: "Withdraw this media"
884
+ }
885
+ )
886
+ ] })
887
+ ] }, c.id))
888
+ ] }),
889
+ !celebration && can("DECLINE") && !review.published && /* @__PURE__ */ jsx("footer", { className: "sm-review-decline", children: /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setPanel("decline"), children: "Decline participation / please don\u2019t publish this announcement" }) })
890
+ ] })
891
+ ] }),
892
+ publicationFooter
893
+ ] });
848
894
  }
849
- function PrivatePhoto({ base, media }) {
895
+ function PrivatePhoto({ base, media, onChange, disabled }) {
850
896
  const [url, setUrl] = useState("");
851
897
  const [video, setVideo] = useState(false);
852
898
  useEffect(() => {
@@ -880,9 +926,12 @@ function PrivatePhoto({ base, media }) {
880
926
  "aria-label": media.alt
881
927
  }
882
928
  ) : /* @__PURE__ */ jsx("img", { src: url, alt: media.alt, referrerPolicy: "no-referrer" }) : /* @__PURE__ */ jsx("p", { children: "Media unavailable." }),
883
- /* @__PURE__ */ jsxs("figcaption", { children: [
884
- media.caption,
885
- media.credit && ` Photo: ${media.credit}`
929
+ /* @__PURE__ */ jsxs("figcaption", { className: "sm-review-photo-details", children: [
930
+ (media.caption || media.credit) && /* @__PURE__ */ jsxs("span", { children: [
931
+ media.caption,
932
+ media.credit && ` Photo: ${media.credit}`
933
+ ] }),
934
+ onChange && /* @__PURE__ */ jsx("button", { className: "sm-review-change-photo", type: "button", disabled, onClick: onChange, children: "Change photo" })
886
935
  ] })
887
936
  ] });
888
937
  }