@byline/admin 4.18.0 → 5.0.0

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.
@@ -1,3 +1,4 @@
1
+ import type { StructuralMutationReceipt } from '@byline/core';
1
2
  /**
2
3
  * This Source Code is subject to the terms of the Mozilla Public
3
4
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -64,6 +65,7 @@ export interface TreeAncestor {
64
65
  path?: string;
65
66
  }
66
67
  export interface PlaceTreeNodeInput {
68
+ expectedRevision: number;
67
69
  collection: string;
68
70
  documentId: string;
69
71
  /** The new parent; `null` makes the document a root node. */
@@ -75,12 +77,13 @@ export interface PlaceTreeNodeInput {
75
77
  /** Place / move a document within its collection's tree. */
76
78
  export type PlaceTreeNodeFn = (input: PlaceTreeNodeInput) => Promise<{
77
79
  orderKey: string;
78
- }>;
80
+ } & StructuralMutationReceipt>;
79
81
  /** Remove a document from the tree (back to the unplaced state). */
80
82
  export type RemoveFromTreeFn = (input: {
81
83
  collection: string;
82
84
  documentId: string;
83
- }) => Promise<void>;
85
+ expectedRevision: number;
86
+ }) => Promise<StructuralMutationReceipt>;
84
87
  /** Resolve a document's ancestor chain, root-first, hydrated with titles. */
85
88
  export type GetTreeAncestorsFn = (input: {
86
89
  collection: string;
@@ -5,6 +5,7 @@ export interface AvailableLocalesWidgetLocale {
5
5
  label: string;
6
6
  }
7
7
  export interface AvailableLocalesWidgetProps {
8
+ disabled?: boolean;
8
9
  /** All configured content locales — one checkbox each (code + display label). */
9
10
  contentLocales: ReadonlyArray<AvailableLocalesWidgetLocale>;
10
11
  /**
@@ -26,4 +27,4 @@ export interface AvailableLocalesWidgetProps {
26
27
  * Stable override handles: `.byline-form-available-locales`,
27
28
  * `.byline-form-available-locales-list`.
28
29
  */
29
- export declare const AvailableLocalesWidget: ({ contentLocales, availableVersionLocales, }: AvailableLocalesWidgetProps) => import("react").JSX.Element | null;
30
+ export declare const AvailableLocalesWidget: ({ disabled: mutationsBlocked, contentLocales, availableVersionLocales, }: AvailableLocalesWidgetProps) => import("react").JSX.Element | null;
@@ -7,7 +7,7 @@ import clsx from "clsx";
7
7
  import { reconcileLocaleState } from "./available-locales-reconcile.js";
8
8
  import available_locales_widget_module from "./available-locales-widget.module.js";
9
9
  import { useFormContext, useSystemAvailableLocales } from "./form-context.js";
10
- const AvailableLocalesWidget = ({ contentLocales, availableVersionLocales })=>{
10
+ const AvailableLocalesWidget = ({ disabled: mutationsBlocked = false, contentLocales, availableVersionLocales })=>{
11
11
  const { t } = useTranslation('byline-admin');
12
12
  const { setSystemAvailableLocales } = useFormContext();
13
13
  const advertised = useSystemAvailableLocales();
@@ -18,6 +18,7 @@ const AvailableLocalesWidget = ({ contentLocales, availableVersionLocales })=>{
18
18
  availableVersionLocales
19
19
  ]);
20
20
  const toggle = useCallback((code, checked)=>{
21
+ if (mutationsBlocked) return;
21
22
  const next = new Set(advertised);
22
23
  if (checked) next.add(code);
23
24
  else next.delete(code);
@@ -25,6 +26,7 @@ const AvailableLocalesWidget = ({ contentLocales, availableVersionLocales })=>{
25
26
  ...next
26
27
  ]);
27
28
  }, [
29
+ mutationsBlocked,
28
30
  advertised,
29
31
  setSystemAvailableLocales
30
32
  ]);
@@ -52,7 +54,7 @@ const AvailableLocalesWidget = ({ contentLocales, availableVersionLocales })=>{
52
54
  label: label,
53
55
  intent: intent,
54
56
  checked: checked,
55
- disabled: disabled,
57
+ disabled: mutationsBlocked || disabled,
56
58
  onCheckedChange: (value)=>toggle(code, true === value)
57
59
  }, code);
58
60
  })
@@ -9,7 +9,8 @@ export interface DocumentActionsLocaleOption {
9
9
  code: string;
10
10
  label: string;
11
11
  }
12
- export declare function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate, sourceTitle, onCopyToLocale, sourceLocale, contentLocales, hasUnsavedChanges, onUnsavedChanges, onDeleteLocale, defaultLocale, availableLocales, scheduledPublicationState, onSchedulePublication, onConfirmScheduledPublication, onCancelScheduledPublication, }: {
12
+ export declare function DocumentActions({ disabled, publishedVersion, onUnpublish, onDelete, onDuplicate, sourceTitle, onCopyToLocale, sourceLocale, contentLocales, hasUnsavedChanges, onUnsavedChanges, onDeleteLocale, defaultLocale, availableLocales, scheduledPublicationState, onSchedulePublication, onConfirmScheduledPublication, onCancelScheduledPublication, }: {
13
+ disabled?: boolean;
13
14
  publishedVersion?: PublishedVersionInfo | null;
14
15
  onUnpublish?: () => Promise<void>;
15
16
  onDelete?: () => Promise<void>;
@@ -6,7 +6,7 @@ import { Button, Checkbox, CloseIcon, DeleteIcon, Dropdown, EllipsisIcon, IconBu
6
6
  import clsx from "clsx";
7
7
  import document_actions_module from "./document-actions.module.js";
8
8
  const DUPLICATE_TITLE_SUFFIX = ' (copy)';
9
- function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate, sourceTitle, onCopyToLocale, sourceLocale, contentLocales, hasUnsavedChanges, onUnsavedChanges, onDeleteLocale, defaultLocale, availableLocales, scheduledPublicationState, onSchedulePublication, onConfirmScheduledPublication, onCancelScheduledPublication }) {
9
+ function DocumentActions({ disabled = false, publishedVersion, onUnpublish, onDelete, onDuplicate, sourceTitle, onCopyToLocale, sourceLocale, contentLocales, hasUnsavedChanges, onUnsavedChanges, onDeleteLocale, defaultLocale, availableLocales, scheduledPublicationState, onSchedulePublication, onConfirmScheduledPublication, onCancelScheduledPublication }) {
10
10
  const { t } = useTranslation('byline-admin');
11
11
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
12
12
  const [showDuplicateConfirm, setShowDuplicateConfirm] = useState(false);
@@ -51,30 +51,35 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
51
51
  }
52
52
  const hasAnyAction = schedulingActions.length > 0 || copyToLocaleAvailable || deleteLocaleAvailable || null != onDuplicate || null != onDelete;
53
53
  const handleOnDelete = ()=>{
54
+ if (disabled) return;
54
55
  setShowDeleteConfirm(false);
55
- if (onDelete) onDelete();
56
+ if (onDelete) onDelete().catch(()=>{});
56
57
  };
57
58
  const handleOnDuplicate = async ()=>{
59
+ if (disabled) return;
58
60
  if (!onDuplicate) return;
59
61
  setDuplicateBusy(true);
60
62
  try {
61
63
  await onDuplicate();
62
64
  setShowDuplicateConfirm(false);
63
- } finally{
65
+ } catch {} finally{
64
66
  setDuplicateBusy(false);
65
67
  }
66
68
  };
67
69
  const handleOpenDuplicate = ()=>{
70
+ if (disabled) return;
68
71
  if (hasUnsavedChanges) return void onUnsavedChanges?.();
69
72
  setShowDuplicateConfirm(true);
70
73
  };
71
74
  const handleOpenCopyToLocale = ()=>{
75
+ if (disabled) return;
72
76
  if (hasUnsavedChanges) return void onUnsavedChanges?.();
73
77
  setCopyTargetLocale(availableTargetLocales[0]?.code ?? '');
74
78
  setCopyOverwrite(false);
75
79
  setShowCopyToLocaleConfirm(true);
76
80
  };
77
81
  const handleOnCopyToLocale = async ()=>{
82
+ if (disabled) return;
78
83
  if (!onCopyToLocale || !copyTargetLocale) return;
79
84
  setCopyToLocaleBusy(true);
80
85
  try {
@@ -83,17 +88,19 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
83
88
  overwrite: copyOverwrite
84
89
  });
85
90
  setShowCopyToLocaleConfirm(false);
86
- } finally{
91
+ } catch {} finally{
87
92
  setCopyToLocaleBusy(false);
88
93
  }
89
94
  };
90
95
  const handleOpenDeleteLocale = ()=>{
96
+ if (disabled) return;
91
97
  if (hasUnsavedChanges) return void onUnsavedChanges?.();
92
98
  const preferred = deletableLocales.find((loc)=>loc.code === sourceLocale)?.code;
93
99
  setDeleteTargetLocale(preferred ?? deletableLocales[0]?.code ?? '');
94
100
  setShowDeleteLocaleConfirm(true);
95
101
  };
96
102
  const handleOnDeleteLocale = async ()=>{
103
+ if (disabled) return;
97
104
  if (!onDeleteLocale || !deleteTargetLocale) return;
98
105
  setDeleteLocaleBusy(true);
99
106
  try {
@@ -101,7 +108,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
101
108
  targetLocale: deleteTargetLocale
102
109
  });
103
110
  setShowDeleteLocaleConfirm(false);
104
- } finally{
111
+ } catch {} finally{
105
112
  setDeleteLocaleBusy(false);
106
113
  }
107
114
  };
@@ -113,6 +120,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
113
120
  hasAnyAction && /*#__PURE__*/ jsxs(Dropdown.Root, {
114
121
  children: [
115
122
  /*#__PURE__*/ jsx(Dropdown.Trigger, {
123
+ disabled: disabled,
116
124
  render: /*#__PURE__*/ jsx(IconButton, {
117
125
  variant: "text",
118
126
  intent: "noeffect",
@@ -134,6 +142,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
134
142
  schedulingActions.length > 0 && /*#__PURE__*/ jsxs(Fragment, {
135
143
  children: [
136
144
  schedulingActions.map((action)=>/*#__PURE__*/ jsx(Dropdown.Item, {
145
+ disabled: disabled,
137
146
  onClick: action.onSelect,
138
147
  children: /*#__PURE__*/ jsx("div", {
139
148
  className: clsx('byline-form-actions-item', document_actions_module.item),
@@ -141,6 +150,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
141
150
  className: clsx('byline-form-actions-item-text', document_actions_module["item-text"]),
142
151
  children: /*#__PURE__*/ jsx("button", {
143
152
  type: "button",
153
+ disabled: disabled,
144
154
  children: action.label
145
155
  })
146
156
  })
@@ -150,6 +160,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
150
160
  ]
151
161
  }),
152
162
  copyToLocaleAvailable && /*#__PURE__*/ jsx(Dropdown.Item, {
163
+ disabled: disabled,
153
164
  onClick: handleOpenCopyToLocale,
154
165
  children: /*#__PURE__*/ jsx("div", {
155
166
  className: clsx('byline-form-actions-item', document_actions_module.item),
@@ -157,12 +168,14 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
157
168
  className: clsx('byline-form-actions-item-text', document_actions_module["item-text"]),
158
169
  children: /*#__PURE__*/ jsx("button", {
159
170
  type: "button",
171
+ disabled: disabled,
160
172
  children: t('documentActions.copyToLocaleMenuItem')
161
173
  })
162
174
  })
163
175
  })
164
176
  }),
165
177
  deleteLocaleAvailable && /*#__PURE__*/ jsx(Dropdown.Item, {
178
+ disabled: disabled,
166
179
  onClick: handleOpenDeleteLocale,
167
180
  children: /*#__PURE__*/ jsx("div", {
168
181
  className: clsx('byline-form-actions-item', document_actions_module.item),
@@ -170,12 +183,14 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
170
183
  className: clsx('byline-form-actions-item-text', document_actions_module["item-text"]),
171
184
  children: /*#__PURE__*/ jsx("button", {
172
185
  type: "button",
186
+ disabled: disabled,
173
187
  children: t('documentActions.deleteLocale.menuItem')
174
188
  })
175
189
  })
176
190
  })
177
191
  }),
178
192
  onDuplicate && /*#__PURE__*/ jsx(Dropdown.Item, {
193
+ disabled: disabled,
179
194
  onClick: handleOpenDuplicate,
180
195
  children: /*#__PURE__*/ jsx("div", {
181
196
  className: clsx('byline-form-actions-item', document_actions_module.item),
@@ -183,6 +198,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
183
198
  className: clsx('byline-form-actions-item-text', document_actions_module["item-text"]),
184
199
  children: /*#__PURE__*/ jsx("button", {
185
200
  type: "button",
201
+ disabled: disabled,
186
202
  children: t('common.actions.duplicate')
187
203
  })
188
204
  })
@@ -192,6 +208,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
192
208
  children: [
193
209
  /*#__PURE__*/ jsx(Dropdown.Separator, {}),
194
210
  /*#__PURE__*/ jsx(Dropdown.Item, {
211
+ disabled: disabled,
195
212
  onClick: ()=>{
196
213
  setShowDeleteConfirm(true);
197
214
  },
@@ -286,6 +303,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
286
303
  minWidth: '80px'
287
304
  },
288
305
  intent: "danger",
306
+ disabled: disabled,
289
307
  onClick: handleOnDelete,
290
308
  children: t('common.actions.delete')
291
309
  })
@@ -397,7 +415,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
397
415
  onClick: ()=>{
398
416
  if (!duplicateBusy) setShowDuplicateConfirm(false);
399
417
  },
400
- disabled: duplicateBusy,
418
+ disabled: disabled || duplicateBusy,
401
419
  children: t('common.actions.cancel')
402
420
  }),
403
421
  /*#__PURE__*/ jsx(Button, {
@@ -407,7 +425,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
407
425
  },
408
426
  intent: "primary",
409
427
  onClick: handleOnDuplicate,
410
- disabled: duplicateBusy,
428
+ disabled: disabled || duplicateBusy,
411
429
  children: duplicateBusy ? t('documentActions.duplicate.busyButton') : t('common.actions.duplicate')
412
430
  })
413
431
  ]
@@ -499,7 +517,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
499
517
  onValueChange: (value)=>{
500
518
  if (null != value) setCopyTargetLocale(value);
501
519
  },
502
- disabled: copyToLocaleBusy
520
+ disabled: disabled || copyToLocaleBusy
503
521
  })
504
522
  ]
505
523
  }),
@@ -513,7 +531,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
513
531
  name: "overwrite",
514
532
  label: t('documentActions.copyToLocale.overwriteLabel'),
515
533
  checked: copyOverwrite,
516
- disabled: copyToLocaleBusy,
534
+ disabled: disabled || copyToLocaleBusy,
517
535
  helpText: t('documentActions.copyToLocale.overwriteHelp'),
518
536
  onCheckedChange: (value)=>{
519
537
  setCopyOverwrite(true === value);
@@ -540,7 +558,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
540
558
  onClick: ()=>{
541
559
  if (!copyToLocaleBusy) setShowCopyToLocaleConfirm(false);
542
560
  },
543
- disabled: copyToLocaleBusy,
561
+ disabled: disabled || copyToLocaleBusy,
544
562
  children: t('common.actions.cancel')
545
563
  }),
546
564
  /*#__PURE__*/ jsx(Button, {
@@ -550,7 +568,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
550
568
  },
551
569
  intent: "primary",
552
570
  onClick: handleOnCopyToLocale,
553
- disabled: copyToLocaleBusy || !copyTargetLocale,
571
+ disabled: disabled || copyToLocaleBusy || !copyTargetLocale,
554
572
  children: copyToLocaleBusy ? t('documentActions.copyToLocale.busyButton') : t('documentActions.copyToLocale.confirmButton')
555
573
  })
556
574
  ]
@@ -620,7 +638,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
620
638
  onValueChange: (value)=>{
621
639
  if (null != value) setDeleteTargetLocale(value);
622
640
  },
623
- disabled: deleteLocaleBusy
641
+ disabled: disabled || deleteLocaleBusy
624
642
  })
625
643
  ]
626
644
  }),
@@ -650,7 +668,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
650
668
  onClick: ()=>{
651
669
  if (!deleteLocaleBusy) setShowDeleteLocaleConfirm(false);
652
670
  },
653
- disabled: deleteLocaleBusy,
671
+ disabled: disabled || deleteLocaleBusy,
654
672
  children: t('common.actions.cancel')
655
673
  }),
656
674
  /*#__PURE__*/ jsx(Button, {
@@ -660,7 +678,7 @@ function DocumentActions({ publishedVersion, onUnpublish, onDelete, onDuplicate,
660
678
  },
661
679
  intent: "danger",
662
680
  onClick: handleOnDeleteLocale,
663
- disabled: deleteLocaleBusy || !deleteTargetLocale,
681
+ disabled: disabled || deleteLocaleBusy || !deleteTargetLocale,
664
682
  children: deleteLocaleBusy ? t('documentActions.deleteLocale.busyButton') : t('documentActions.deleteLocale.confirmButton')
665
683
  })
666
684
  ]
@@ -37,6 +37,15 @@ export interface SystemFieldsSubmitPayload {
37
37
  }
38
38
  /** Props shared by both the public FormRenderer and its internal FormContent component. */
39
39
  export interface FormRendererProps {
40
+ mutationIssue?: 'stale' | 'reload' | 'lock' | 'unavailable' | 'committed' | null;
41
+ mutationsBlocked?: boolean;
42
+ observedRevision?: number;
43
+ onMutationError?: (error: unknown) => 'blocked' | 'committed' | null | void;
44
+ onTreeMutationCommitted?: (receipt: import('@byline/core').StructuralMutationReceipt) => void;
45
+ scheduledPublicationsNeedReconfirmation?: boolean;
46
+ scheduledPublicationsHref?: string;
47
+ /** Explicit discard action; defaults to a complete server reload. */
48
+ onReloadDocument?: () => void | Promise<void>;
40
49
  mode: 'create' | 'edit';
41
50
  fields: Field[];
42
51
  onSubmit: (data: any) => void | Promise<void>;