@byline/admin 6.0.3 → 6.1.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.
- package/dist/exports-parity.test.node.js +37 -0
- package/dist/fields/array/array-field.jsx +209 -0
- package/dist/fields/blocks/blocks-field.jsx +248 -0
- package/dist/fields/checkbox/checkbox-field.jsx +24 -0
- package/dist/fields/code/code-editor.jsx +211 -0
- package/dist/fields/code/code-field.jsx +109 -0
- package/dist/fields/column-formatter.jsx +25 -0
- package/dist/fields/date-time-formatter.jsx +18 -0
- package/dist/fields/datetime/datetime-field.jsx +22 -0
- package/dist/fields/draggable-context-menu.jsx +50 -0
- package/dist/fields/field-admin.test.node.js +40 -0
- package/dist/fields/field-renderer.jsx +136 -0
- package/dist/fields/field-services-context.jsx +17 -0
- package/dist/fields/file/file-field.jsx +176 -0
- package/dist/fields/file/file-upload-field.jsx +89 -0
- package/dist/fields/group/group-field.jsx +46 -0
- package/dist/fields/image/image-field.jsx +183 -0
- package/dist/fields/image/image-upload-field.jsx +157 -0
- package/dist/fields/local-date-time.jsx +69 -0
- package/dist/fields/locale-badge.jsx +19 -0
- package/dist/fields/numerical/numerical-field.jsx +93 -0
- package/dist/fields/relation/relation-column-formatter.jsx +74 -0
- package/dist/fields/relation/relation-display.jsx +118 -0
- package/dist/fields/relation/relation-field.jsx +108 -0
- package/dist/fields/relation/relation-many-field.jsx +142 -0
- package/dist/fields/relation/relation-picker.jsx +240 -0
- package/dist/fields/relation/relation-summary.jsx +45 -0
- package/dist/fields/select/select-field.jsx +27 -0
- package/dist/fields/sortable-item.jsx +54 -0
- package/dist/fields/text/text-field.jsx +79 -0
- package/dist/fields/text-area/text-area-field.jsx +79 -0
- package/dist/forms/available-locales-reconcile.test.node.js +43 -0
- package/dist/forms/available-locales-widget.jsx +63 -0
- package/dist/forms/document-actions.jsx +486 -0
- package/dist/forms/form-context.jsx +598 -0
- package/dist/forms/form-modals.jsx +128 -0
- package/dist/forms/form-renderer.d.ts +8 -2
- package/dist/forms/form-renderer.js +3 -2
- package/dist/forms/form-renderer.jsx +532 -0
- package/dist/forms/form-status-display.jsx +69 -0
- package/dist/forms/navigation-guard.jsx +68 -0
- package/dist/forms/nested-path.test.node.js +115 -0
- package/dist/forms/path-widget.d.ts +9 -1
- package/dist/forms/path-widget.js +8 -5
- package/dist/forms/path-widget.jsx +125 -0
- package/dist/forms/pending-uploads.test.node.js +19 -0
- package/dist/forms/repeating-items.test.node.js +29 -0
- package/dist/forms/scheduled-publication-control.jsx +389 -0
- package/dist/forms/scheduled-publication-state.test.node.js +121 -0
- package/dist/forms/scheduled-publication-time.test.node.js +70 -0
- package/dist/forms/status-transitions.test.node.js +76 -0
- package/dist/forms/tree-placement-widget.jsx +160 -0
- package/dist/forms/upload-executor.test.node.js +368 -0
- package/dist/forms/use-form-layout.test.node.js +69 -0
- package/dist/modules/admin-account/components/change-password.jsx +169 -0
- package/dist/modules/admin-account/components/container.jsx +164 -0
- package/dist/modules/admin-account/components/preferences.jsx +148 -0
- package/dist/modules/admin-account/components/theme-switch.jsx +52 -0
- package/dist/modules/admin-account/components/update.jsx +186 -0
- package/dist/modules/admin-permissions/components/inspector.jsx +200 -0
- package/dist/modules/admin-preferences/schemas.test.node.js +48 -0
- package/dist/modules/admin-roles/components/create.jsx +155 -0
- package/dist/modules/admin-roles/components/permissions.jsx +239 -0
- package/dist/modules/admin-roles/components/update.jsx +148 -0
- package/dist/modules/admin-users/components/create.jsx +206 -0
- package/dist/modules/admin-users/components/roles.jsx +126 -0
- package/dist/modules/admin-users/components/set-password.jsx +133 -0
- package/dist/modules/admin-users/components/update.jsx +215 -0
- package/dist/modules/analytics/components/dashboard.jsx +208 -0
- package/dist/modules/analytics/components/dashboard.test.node.js +162 -0
- package/dist/modules/analytics/components/timeseries.jsx +193 -0
- package/dist/modules/auth/components/sign-in-form.jsx +89 -0
- package/dist/modules/auth/safe-redirect.test.node.js +40 -0
- package/dist/modules/auth/sign-in-form-props.test.node.js +7 -0
- package/dist/presentation/group.jsx +26 -0
- package/dist/presentation/row.jsx +23 -0
- package/dist/presentation/tabs.jsx +39 -0
- package/dist/services/admin-services-context.jsx +17 -0
- package/dist/widgets/diff-viewer/diff-modal.jsx +110 -0
- package/dist/widgets/source-locale-badge/source-locale-badge.jsx +28 -0
- package/dist/widgets/status-badge/status-badge.jsx +46 -0
- package/package.json +7 -7
- package/src/forms/form-renderer-capabilities.test.tsx +72 -2
- package/src/forms/form-renderer.tsx +14 -2
- package/src/forms/path-widget.test.tsx +96 -2
- package/src/forms/path-widget.tsx +31 -11
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
/**
|
|
3
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) Infonomic Company Limited
|
|
8
|
+
*/
|
|
9
|
+
import { useTranslation } from '@byline/i18n/react';
|
|
10
|
+
import { Button, CloseIcon, IconButton, Modal } from '@byline/ui/react';
|
|
11
|
+
import cx from 'clsx';
|
|
12
|
+
import styles from './form-renderer.module.css';
|
|
13
|
+
/**
|
|
14
|
+
* Shown when the editor triggers a guarded action (status change, duplicate,
|
|
15
|
+
* copy-to-locale) while the form is dirty. Those actions operate on the saved
|
|
16
|
+
* version, so the editor must save first.
|
|
17
|
+
*/
|
|
18
|
+
export const UnsavedChangesModal = ({ onClose }) => {
|
|
19
|
+
const { t } = useTranslation('byline-admin');
|
|
20
|
+
return (<Modal isOpen={true} closeOnOverlayClick={true} onDismiss={onClose}>
|
|
21
|
+
<Modal.Container style={{ maxWidth: '460px' }}>
|
|
22
|
+
<Modal.Header className={cx('byline-form-guard-modal-head', styles['guard-modal-head'])}>
|
|
23
|
+
<h3 className={cx('byline-form-guard-modal-title', styles['guard-modal-title'])}>
|
|
24
|
+
{t('forms.unsavedChanges.title')}
|
|
25
|
+
</h3>
|
|
26
|
+
</Modal.Header>
|
|
27
|
+
<Modal.Content>
|
|
28
|
+
<p className={cx('byline-form-guard-modal-text', styles['guard-modal-text'])}>
|
|
29
|
+
{t('forms.unsavedChanges.message')}
|
|
30
|
+
</p>
|
|
31
|
+
</Modal.Content>
|
|
32
|
+
<Modal.Actions>
|
|
33
|
+
<Button size="sm" style={{ minWidth: '60px' }} intent="primary" type="button" onClick={onClose}>
|
|
34
|
+
{t('forms.unsavedChanges.okButton')}
|
|
35
|
+
</Button>
|
|
36
|
+
</Modal.Actions>
|
|
37
|
+
</Modal.Container>
|
|
38
|
+
</Modal>);
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Confirms an immediate, non-versioned write of the document-grain system
|
|
42
|
+
* fields (path / advertised locales) — which does NOT reset workflow status.
|
|
43
|
+
* When content is also dirty, the copy reassures that content edits still
|
|
44
|
+
* follow the normal revision + publish workflow. See docs/08-internationalization/index.md.
|
|
45
|
+
*/
|
|
46
|
+
export const SystemFieldsConfirmModal = ({ contentDirty, pathDirty, availableLocalesDirty, onCancel, onConfirm, }) => {
|
|
47
|
+
const { t } = useTranslation('byline-admin');
|
|
48
|
+
return (<Modal isOpen={true} closeOnOverlayClick={true} onDismiss={onCancel}>
|
|
49
|
+
<Modal.Container style={{ maxWidth: '520px' }}>
|
|
50
|
+
<Modal.Header className={cx('byline-form-guard-modal-head', styles['guard-modal-head'])}>
|
|
51
|
+
<h3 className={cx('byline-form-guard-modal-title', styles['guard-modal-title'])}>
|
|
52
|
+
{contentDirty
|
|
53
|
+
? t('forms.systemFieldsConfirm.bothTitle')
|
|
54
|
+
: t('forms.systemFieldsConfirm.title')}
|
|
55
|
+
</h3>
|
|
56
|
+
<IconButton aria-label={t('common.actions.close')} size="xs" onClick={onCancel}>
|
|
57
|
+
<CloseIcon width="16px" height="16px" svgClassName="white-icon"/>
|
|
58
|
+
</IconButton>
|
|
59
|
+
</Modal.Header>
|
|
60
|
+
<Modal.Content className="prose">
|
|
61
|
+
{/* Lead with reassurance: content edits follow the normal
|
|
62
|
+
revision + publish workflow. The immediate, document-level
|
|
63
|
+
system-field write is explained below the divider. */}
|
|
64
|
+
{contentDirty && (<p className={cx('byline-form-system-fields-content-note', 'm-0 mt-2')}>
|
|
65
|
+
{t('forms.systemFieldsConfirm.contentNote')}
|
|
66
|
+
</p>)}
|
|
67
|
+
<p className="m-0 mt-2" style={contentDirty
|
|
68
|
+
? {
|
|
69
|
+
marginTop: 'var(--spacing-8)',
|
|
70
|
+
paddingTop: 'var(--spacing-12)',
|
|
71
|
+
borderTop: '1px solid var(--border-color)',
|
|
72
|
+
}
|
|
73
|
+
: undefined}>
|
|
74
|
+
{t('forms.systemFieldsConfirm.intro')}
|
|
75
|
+
</p>
|
|
76
|
+
<ul className={cx('byline-form-system-fields-list', styles['guard-modal-text'], 'm-0')}>
|
|
77
|
+
{pathDirty && <li>{t('forms.systemFieldsConfirm.bulletPath')}</li>}
|
|
78
|
+
{availableLocalesDirty && <li>{t('forms.systemFieldsConfirm.bulletLocales')}</li>}
|
|
79
|
+
</ul>
|
|
80
|
+
<p className={cx('byline-form-system-fields-effect', styles['guard-modal-text'])} style={{
|
|
81
|
+
marginTop: 'var(--spacing-4)',
|
|
82
|
+
marginBottom: 0,
|
|
83
|
+
color: 'var(--text-subtle)',
|
|
84
|
+
}}>
|
|
85
|
+
{t('forms.systemFieldsConfirm.effectLine')}
|
|
86
|
+
</p>
|
|
87
|
+
</Modal.Content>
|
|
88
|
+
<Modal.Actions>
|
|
89
|
+
<Button size="sm" style={{ minWidth: '80px' }} intent="noeffect" type="button" onClick={onCancel}>
|
|
90
|
+
{t('common.actions.cancel')}
|
|
91
|
+
</Button>
|
|
92
|
+
<Button size="sm" style={{ minWidth: '80px' }} intent="primary" type="button" onClick={onConfirm}>
|
|
93
|
+
{t('forms.systemFieldsConfirm.confirmButton')}
|
|
94
|
+
</Button>
|
|
95
|
+
</Modal.Actions>
|
|
96
|
+
</Modal.Container>
|
|
97
|
+
</Modal>);
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Blocks router navigation / browser unload while the form is dirty. Driven by
|
|
101
|
+
* the navigation-guard adapter's `isBlocked` state; `onStay` keeps the editor
|
|
102
|
+
* on the page, `onProceed` discards and continues.
|
|
103
|
+
*/
|
|
104
|
+
export const NavigationGuardModal = ({ onStay, onProceed, }) => {
|
|
105
|
+
const { t } = useTranslation('byline-admin');
|
|
106
|
+
return (<Modal isOpen={true} closeOnOverlayClick={false} onDismiss={onStay}>
|
|
107
|
+
<Modal.Container style={{ maxWidth: '460px' }}>
|
|
108
|
+
<Modal.Header className={cx('byline-form-guard-modal-head', styles['guard-modal-head'])}>
|
|
109
|
+
<h3 className={cx('byline-form-guard-modal-title', styles['guard-modal-title'])}>
|
|
110
|
+
{t('forms.navigationGuard.title')}
|
|
111
|
+
</h3>
|
|
112
|
+
</Modal.Header>
|
|
113
|
+
<Modal.Content>
|
|
114
|
+
<p className={cx('byline-form-guard-modal-text', styles['guard-modal-text'])}>
|
|
115
|
+
{t('forms.navigationGuard.message')}
|
|
116
|
+
</p>
|
|
117
|
+
</Modal.Content>
|
|
118
|
+
<Modal.Actions>
|
|
119
|
+
<Button size="sm" intent="noeffect" type="button" onClick={onStay}>
|
|
120
|
+
{t('forms.navigationGuard.stayButton')}
|
|
121
|
+
</Button>
|
|
122
|
+
<Button size="sm" intent="danger" type="button" onClick={onProceed}>
|
|
123
|
+
{t('forms.navigationGuard.leaveButton')}
|
|
124
|
+
</Button>
|
|
125
|
+
</Modal.Actions>
|
|
126
|
+
</Modal.Container>
|
|
127
|
+
</Modal>);
|
|
128
|
+
};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Copyright (c) Infonomic Company Limited
|
|
7
7
|
*/
|
|
8
8
|
import { type ReactNode } from 'react';
|
|
9
|
-
import type {
|
|
9
|
+
import type { AdminResourceConfig, Field, WorkflowStatus } from '@byline/core';
|
|
10
10
|
import type { DocumentPatch } from '@byline/core/patches';
|
|
11
11
|
import { type DocumentActionsLocaleOption } from './document-actions.js';
|
|
12
12
|
import { type ScheduledPublicationInfo, type SchedulePublicationInput } from './scheduled-publication-control.js';
|
|
@@ -95,7 +95,13 @@ export interface FormRendererProps {
|
|
|
95
95
|
workflowStatuses?: WorkflowStatus[];
|
|
96
96
|
publishedVersion?: PublishedVersionInfo | null;
|
|
97
97
|
initialData?: Record<string, any>;
|
|
98
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Presentation configuration for the resource being edited — a collection
|
|
100
|
+
* or a singleton. Typed as the union rather than the shared
|
|
101
|
+
* `FormAdminConfig` base so the renderer can read collection-only members
|
|
102
|
+
* such as `lockPath`.
|
|
103
|
+
*/
|
|
104
|
+
adminConfig?: AdminResourceConfig;
|
|
99
105
|
/**
|
|
100
106
|
* Name of the schema field to render as the live form heading.
|
|
101
107
|
* Sourced from `CollectionDefinition.useAsTitle` by the caller.
|
|
@@ -533,7 +533,7 @@ const FormContent = ({ mode, mutationIssue, mutationsBlocked = false, observedRe
|
|
|
533
533
|
/*#__PURE__*/ jsxs("div", {
|
|
534
534
|
className: clsx('byline-form-sidebar', form_renderer_module.sidebar),
|
|
535
535
|
children: [
|
|
536
|
-
showPath && (useAsPath || 'string' == typeof initialData?.path && initialData.path.length > 0) && /*#__PURE__*/ jsx(PathWidget, {
|
|
536
|
+
showPath && (useAsPath || adminConfig?.lockPath === true || 'string' == typeof initialData?.path && initialData.path.length > 0) && /*#__PURE__*/ jsx(PathWidget, {
|
|
537
537
|
disabled: mutationsBlocked || discarding,
|
|
538
538
|
useAsPath: useAsPath,
|
|
539
539
|
collectionPath: collectionPath ?? '',
|
|
@@ -541,7 +541,8 @@ const FormContent = ({ mode, mutationIssue, mutationsBlocked = false, observedRe
|
|
|
541
541
|
activeLocale: contentLocale,
|
|
542
542
|
mode: mode,
|
|
543
543
|
slugifier: pathSlugifier,
|
|
544
|
-
sourceLocked: pathSourceLocked
|
|
544
|
+
sourceLocked: pathSourceLocked,
|
|
545
|
+
lockPath: adminConfig?.lockPath
|
|
545
546
|
}),
|
|
546
547
|
tree && 'edit' === mode && 'string' == typeof initialData?.id && /*#__PURE__*/ jsx(TreePlacementWidget, {
|
|
547
548
|
disabled: mutationsBlocked || discarding,
|