@strapi/content-manager 5.46.1 → 5.47.1
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/admin/history/components/VersionInputRenderer.js +63 -25
- package/dist/admin/history/components/VersionInputRenderer.js.map +1 -1
- package/dist/admin/history/components/VersionInputRenderer.mjs +62 -26
- package/dist/admin/history/components/VersionInputRenderer.mjs.map +1 -1
- package/dist/admin/hooks/useDocument.js +82 -2
- package/dist/admin/hooks/useDocument.js.map +1 -1
- package/dist/admin/hooks/useDocument.mjs +82 -2
- package/dist/admin/hooks/useDocument.mjs.map +1 -1
- package/dist/admin/pages/EditView/EditViewPage.js +3 -2
- package/dist/admin/pages/EditView/EditViewPage.js.map +1 -1
- package/dist/admin/pages/EditView/EditViewPage.mjs +3 -2
- package/dist/admin/pages/EditView/EditViewPage.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/DocumentActions.js +6 -3
- package/dist/admin/pages/EditView/components/DocumentActions.js.map +1 -1
- package/dist/admin/pages/EditView/components/DocumentActions.mjs +6 -3
- package/dist/admin/pages/EditView/components/DocumentActions.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js +4 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.mjs +4 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +4 -4
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +4 -4
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
- package/dist/admin/src/history/components/VersionInputRenderer.d.ts +27 -1
- package/dist/admin/translations/sk.json.js +175 -9
- package/dist/admin/translations/sk.json.js.map +1 -1
- package/dist/admin/translations/sk.json.mjs +175 -9
- package/dist/admin/translations/sk.json.mjs.map +1 -1
- package/dist/admin/utils/relations.js +4 -0
- package/dist/admin/utils/relations.js.map +1 -1
- package/dist/admin/utils/relations.mjs +4 -0
- package/dist/admin/utils/relations.mjs.map +1 -1
- package/dist/server/bootstrap.js +4 -0
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/server/bootstrap.mjs +4 -0
- package/dist/server/bootstrap.mjs.map +1 -1
- package/dist/server/controllers/collection-types.js +9 -5
- package/dist/server/controllers/collection-types.js.map +1 -1
- package/dist/server/controllers/collection-types.mjs +10 -6
- package/dist/server/controllers/collection-types.mjs.map +1 -1
- package/dist/server/homepage/services/homepage.js +21 -16
- package/dist/server/homepage/services/homepage.js.map +1 -1
- package/dist/server/homepage/services/homepage.mjs +21 -16
- package/dist/server/homepage/services/homepage.mjs.map +1 -1
- package/dist/server/mcp/derive-content-type-mcp-tools.js +524 -0
- package/dist/server/mcp/derive-content-type-mcp-tools.js.map +1 -0
- package/dist/server/mcp/derive-content-type-mcp-tools.mjs +518 -0
- package/dist/server/mcp/derive-content-type-mcp-tools.mjs.map +1 -0
- package/dist/server/mcp/handlers/collection-handlers.js +404 -0
- package/dist/server/mcp/handlers/collection-handlers.js.map +1 -0
- package/dist/server/mcp/handlers/collection-handlers.mjs +395 -0
- package/dist/server/mcp/handlers/collection-handlers.mjs.map +1 -0
- package/dist/server/mcp/handlers/constants.js +10 -0
- package/dist/server/mcp/handlers/constants.js.map +1 -0
- package/dist/server/mcp/handlers/constants.mjs +6 -0
- package/dist/server/mcp/handlers/constants.mjs.map +1 -0
- package/dist/server/mcp/handlers/single-type-handlers.js +344 -0
- package/dist/server/mcp/handlers/single-type-handlers.js.map +1 -0
- package/dist/server/mcp/handlers/single-type-handlers.mjs +336 -0
- package/dist/server/mcp/handlers/single-type-handlers.mjs.map +1 -0
- package/dist/server/mcp/permissions.js +138 -0
- package/dist/server/mcp/permissions.js.map +1 -0
- package/dist/server/mcp/permissions.mjs +131 -0
- package/dist/server/mcp/permissions.mjs.map +1 -0
- package/dist/server/mcp/register-content-manager-mcp-tools.js +30 -0
- package/dist/server/mcp/register-content-manager-mcp-tools.js.map +1 -0
- package/dist/server/mcp/register-content-manager-mcp-tools.mjs +28 -0
- package/dist/server/mcp/register-content-manager-mcp-tools.mjs.map +1 -0
- package/dist/server/mcp/schemas/blocks-schema.js +124 -0
- package/dist/server/mcp/schemas/blocks-schema.js.map +1 -0
- package/dist/server/mcp/schemas/blocks-schema.mjs +122 -0
- package/dist/server/mcp/schemas/blocks-schema.mjs.map +1 -0
- package/dist/server/mcp/schemas/data-schema.js +252 -0
- package/dist/server/mcp/schemas/data-schema.js.map +1 -0
- package/dist/server/mcp/schemas/data-schema.mjs +248 -0
- package/dist/server/mcp/schemas/data-schema.mjs.map +1 -0
- package/dist/server/mcp/schemas/filters-schema.js +111 -0
- package/dist/server/mcp/schemas/filters-schema.js.map +1 -0
- package/dist/server/mcp/schemas/filters-schema.mjs +107 -0
- package/dist/server/mcp/schemas/filters-schema.mjs.map +1 -0
- package/dist/server/mcp/schemas/input-schemas.js +18 -0
- package/dist/server/mcp/schemas/input-schemas.js.map +1 -0
- package/dist/server/mcp/schemas/input-schemas.mjs +13 -0
- package/dist/server/mcp/schemas/input-schemas.mjs.map +1 -0
- package/dist/server/mcp/schemas/output-schemas.js +48 -0
- package/dist/server/mcp/schemas/output-schemas.js.map +1 -0
- package/dist/server/mcp/schemas/output-schemas.mjs +44 -0
- package/dist/server/mcp/schemas/output-schemas.mjs.map +1 -0
- package/dist/server/mcp/schemas/sort-schema.js +80 -0
- package/dist/server/mcp/schemas/sort-schema.js.map +1 -0
- package/dist/server/mcp/schemas/sort-schema.mjs +76 -0
- package/dist/server/mcp/schemas/sort-schema.mjs.map +1 -0
- package/dist/server/mcp/utils.js +43 -0
- package/dist/server/mcp/utils.js.map +1 -0
- package/dist/server/mcp/utils.mjs +39 -0
- package/dist/server/mcp/utils.mjs.map +1 -0
- package/dist/server/services/document-metadata.js +32 -3
- package/dist/server/services/document-metadata.js.map +1 -1
- package/dist/server/services/document-metadata.mjs +32 -3
- package/dist/server/services/document-metadata.mjs.map +1 -1
- package/dist/server/services/index.js +1 -1
- package/dist/server/services/index.js.map +1 -1
- package/dist/server/services/permission-checker.js +4 -1
- package/dist/server/services/permission-checker.js.map +1 -1
- package/dist/server/services/permission-checker.mjs +1 -1
- package/dist/server/services/permission-checker.mjs.map +1 -1
- package/dist/server/services/utils/populate.js +3 -3
- package/dist/server/services/utils/populate.js.map +1 -1
- package/dist/server/services/utils/populate.mjs +3 -3
- package/dist/server/services/utils/populate.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/homepage/services/homepage.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +3 -3
- package/dist/server/src/mcp/derive-content-type-mcp-tools.d.ts +12 -0
- package/dist/server/src/mcp/derive-content-type-mcp-tools.d.ts.map +1 -0
- package/dist/server/src/mcp/handlers/collection-handlers.d.ts +69 -0
- package/dist/server/src/mcp/handlers/collection-handlers.d.ts.map +1 -0
- package/dist/server/src/mcp/handlers/constants.d.ts +4 -0
- package/dist/server/src/mcp/handlers/constants.d.ts.map +1 -0
- package/dist/server/src/mcp/handlers/index.d.ts +3 -0
- package/dist/server/src/mcp/handlers/index.d.ts.map +1 -0
- package/dist/server/src/mcp/handlers/single-type-handlers.d.ts +66 -0
- package/dist/server/src/mcp/handlers/single-type-handlers.d.ts.map +1 -0
- package/dist/server/src/mcp/permissions.d.ts +49 -0
- package/dist/server/src/mcp/permissions.d.ts.map +1 -0
- package/dist/server/src/mcp/register-content-manager-mcp-tools.d.ts +8 -0
- package/dist/server/src/mcp/register-content-manager-mcp-tools.d.ts.map +1 -0
- package/dist/server/src/mcp/schemas/blocks-schema.d.ts +8 -0
- package/dist/server/src/mcp/schemas/blocks-schema.d.ts.map +1 -0
- package/dist/server/src/mcp/schemas/data-schema.d.ts +36 -0
- package/dist/server/src/mcp/schemas/data-schema.d.ts.map +1 -0
- package/dist/server/src/mcp/schemas/filters-schema.d.ts +22 -0
- package/dist/server/src/mcp/schemas/filters-schema.d.ts.map +1 -0
- package/dist/server/src/mcp/schemas/index.d.ts +7 -0
- package/dist/server/src/mcp/schemas/index.d.ts.map +1 -0
- package/dist/server/src/mcp/schemas/input-schemas.d.ts +10 -0
- package/dist/server/src/mcp/schemas/input-schemas.d.ts.map +1 -0
- package/dist/server/src/mcp/schemas/output-schemas.d.ts +18 -0
- package/dist/server/src/mcp/schemas/output-schemas.d.ts.map +1 -0
- package/dist/server/src/mcp/schemas/sort-schema.d.ts +24 -0
- package/dist/server/src/mcp/schemas/sort-schema.d.ts.map +1 -0
- package/dist/server/src/mcp/types.d.ts +31 -0
- package/dist/server/src/mcp/types.d.ts.map +1 -0
- package/dist/server/src/mcp/utils.d.ts +21 -0
- package/dist/server/src/mcp/utils.d.ts.map +1 -0
- package/dist/server/src/services/document-metadata.d.ts +11 -1
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +3 -3
- package/dist/server/src/services/permission-checker.d.ts +13 -3
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
- package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/package.json +10 -8
|
@@ -33,6 +33,19 @@ function _interopNamespaceDefault(e) {
|
|
|
33
33
|
|
|
34
34
|
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Mirrors the server's `isLocalizedAttribute` in
|
|
38
|
+
* `packages/plugins/i18n/server/src/services/content-types.ts`: an attribute
|
|
39
|
+
* counts as localized only when `pluginOptions.i18n.localized` is explicitly
|
|
40
|
+
* `true`. Both `false` and `undefined` mean "non-localized" — important here
|
|
41
|
+
* because attributes created without the i18n plugin omit the field entirely,
|
|
42
|
+
* and we still want them inherited when creating a new locale draft.
|
|
43
|
+
*/ const isLocalizedAttribute = (attribute)=>{
|
|
44
|
+
// `pluginOptions` on the base attribute is typed as `object`, so we have to
|
|
45
|
+
// narrow it to the i18n-specific shape here.
|
|
46
|
+
const i18nOptions = attribute.pluginOptions;
|
|
47
|
+
return i18nOptions?.i18n?.localized === true;
|
|
48
|
+
};
|
|
36
49
|
/* -------------------------------------------------------------------------------------------------
|
|
37
50
|
* useDocument
|
|
38
51
|
* -----------------------------------------------------------------------------------------------*/ /**
|
|
@@ -136,6 +149,33 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
136
149
|
validationSchema
|
|
137
150
|
]);
|
|
138
151
|
/**
|
|
152
|
+
* Schema attributes that should be inherited from a sibling locale when
|
|
153
|
+
* creating a new locale draft.
|
|
154
|
+
*
|
|
155
|
+
* Scope intentionally matches what the server populates into
|
|
156
|
+
* `meta.availableLocales` (see `packages/core/content-manager/server/src/services/document-metadata.ts`):
|
|
157
|
+
* - non-localized — `isLocalizedAttribute` semantics, so attributes whose
|
|
158
|
+
* `pluginOptions.i18n.localized` is `undefined` count as non-localized
|
|
159
|
+
* (an attribute created without the i18n plugin has no i18n options at
|
|
160
|
+
* all but is still inherited at save by `copyNonLocalizedFields`).
|
|
161
|
+
* - scalar or media — `component` / `dynamiczone` / `relation` are excluded
|
|
162
|
+
* because the server doesn't populate them in `availableLocales` either,
|
|
163
|
+
* so there'd be nothing to copy from.
|
|
164
|
+
*/ const nonLocalizedScalarAndMediaFields = React__namespace.useMemo(()=>{
|
|
165
|
+
if (!schema?.attributes) {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
return Object.keys(schema.attributes).filter((name)=>{
|
|
169
|
+
const attribute = schema.attributes[name];
|
|
170
|
+
if (isLocalizedAttribute(attribute)) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
return attribute.type !== 'component' && attribute.type !== 'dynamiczone' && attribute.type !== 'relation';
|
|
174
|
+
});
|
|
175
|
+
}, [
|
|
176
|
+
schema
|
|
177
|
+
]);
|
|
178
|
+
/**
|
|
139
179
|
* Here we prepare the form for editing, we need to:
|
|
140
180
|
* - remove prohibited fields from the document (passwords | ADD YOURS WHEN THERES A NEW ONE)
|
|
141
181
|
* - swap out count objects on relations for empty arrays
|
|
@@ -143,6 +183,20 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
143
183
|
*
|
|
144
184
|
* We also prepare the form for new documents, so we need to:
|
|
145
185
|
* - set default values on fields
|
|
186
|
+
* - inherit non-localized scalar/media values from a sibling locale.
|
|
187
|
+
* Scope is intentionally limited to scalars and media — that is exactly
|
|
188
|
+
* what the server populates into `meta.availableLocales` (see
|
|
189
|
+
* `packages/core/content-manager/server/src/services/document-metadata.ts`).
|
|
190
|
+
* Components, dynamic zones, and relations are not in that payload; the
|
|
191
|
+
* server fills them at save time via `copyNonLocalizedFields` (in
|
|
192
|
+
* `packages/core/core/src/services/document-service/internationalization.ts`)
|
|
193
|
+
* when the new locale row is first created.
|
|
194
|
+
* Baking the inheritance into `initialValues` here is what lets it survive
|
|
195
|
+
* `<Form>` re-inits: the `SET_INITIAL_VALUES` effect in
|
|
196
|
+
* `packages/core/admin/admin/src/components/Form.tsx` re-applies these
|
|
197
|
+
* values whenever `initialValues` changes (e.g. after a locale switch),
|
|
198
|
+
* which the previous side-effect-based prefill in `LocalePickerAction`
|
|
199
|
+
* could not survive on revisits.
|
|
146
200
|
*/ const getInitialFormValues = React__namespace.useCallback((isCreatingDocument = false)=>{
|
|
147
201
|
if (!document && !isCreatingDocument && !isSingleType || !schema) {
|
|
148
202
|
return undefined;
|
|
@@ -150,13 +204,39 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
150
204
|
/**
|
|
151
205
|
* Check that we have an ID so we know the
|
|
152
206
|
* document has been created in some way.
|
|
153
|
-
*/
|
|
207
|
+
*/ if (document?.id) {
|
|
208
|
+
return data.transformDocument(schema, components)(document);
|
|
209
|
+
}
|
|
210
|
+
let form = forms.createDefaultForm(schema, components);
|
|
211
|
+
// Intentionally use `availableLocales[0]`:
|
|
212
|
+
// - The server sorts `getAvailableLocales` with the default locale first
|
|
213
|
+
// (see `document-metadata.ts`), so index 0 is the canonical inheritance
|
|
214
|
+
// source. Sibling locales can drift on non-localized fields because the
|
|
215
|
+
// server only syncs them at locale-creation time, not on subsequent
|
|
216
|
+
// updates — preferring the default keeps the surfaced values stable.
|
|
217
|
+
// - Avoids coupling this hook to `useGetLocalesQuery` just to find the
|
|
218
|
+
// default locale.
|
|
219
|
+
const sibling = meta?.availableLocales?.[0];
|
|
220
|
+
if (sibling && nonLocalizedScalarAndMediaFields.length > 0) {
|
|
221
|
+
const inherited = nonLocalizedScalarAndMediaFields.reduce((acc, name)=>{
|
|
222
|
+
if (name in sibling) {
|
|
223
|
+
acc[name] = sibling[name];
|
|
224
|
+
}
|
|
225
|
+
return acc;
|
|
226
|
+
}, {});
|
|
227
|
+
form = {
|
|
228
|
+
...form,
|
|
229
|
+
...inherited
|
|
230
|
+
};
|
|
231
|
+
}
|
|
154
232
|
return data.transformDocument(schema, components)(form);
|
|
155
233
|
}, [
|
|
156
234
|
document,
|
|
157
235
|
isSingleType,
|
|
158
236
|
schema,
|
|
159
|
-
components
|
|
237
|
+
components,
|
|
238
|
+
meta?.availableLocales,
|
|
239
|
+
nonLocalizedScalarAndMediaFields
|
|
160
240
|
]);
|
|
161
241
|
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
|
162
242
|
const hasError = !!error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDocument.js","sources":["../../../admin/src/hooks/useDocument.ts"],"sourcesContent":["/**\n * This hook doesn't use a context provider because we fetch directly from the server,\n * this sounds expensive but actually, it's really not. Because we have redux-toolkit-query\n * being a cache layer so if nothing invalidates the cache, we don't fetch again.\n */\n\nimport * as React from 'react';\n\nimport {\n useNotification,\n useAPIErrorHandler,\n useQueryParams,\n FormErrors,\n getYupValidationErrors,\n useForm,\n} from '@strapi/admin/strapi-admin';\nimport { useIntl } from 'react-intl';\nimport { useParams } from 'react-router-dom';\nimport { ValidationError } from 'yup';\n\nimport { SINGLE_TYPES } from '../constants/collections';\nimport { type AnyData, transformDocument } from '../pages/EditView/utils/data';\nimport { createDefaultForm } from '../pages/EditView/utils/forms';\nimport { useGetDocumentQuery } from '../services/documents';\nimport { buildValidParams } from '../utils/api';\nimport { createYupSchema } from '../utils/validation';\n\nimport { useContentTypeSchema, ComponentsDictionary } from './useContentTypeSchema';\nimport { useDocumentLayout } from './useDocumentLayout';\n\nimport type { FindOne } from '../../../shared/contracts/collection-types';\nimport type { ContentType } from '../../../shared/contracts/content-types';\nimport type { Modules } from '@strapi/types';\n\ninterface UseDocumentArgs {\n collectionType: string;\n model: string;\n documentId?: string;\n params?: object;\n}\n\ntype UseDocumentOpts = Parameters<typeof useGetDocumentQuery>[1];\n\ntype Document = FindOne.Response['data'];\n\ntype Schema = ContentType;\n\ntype UseDocument = (\n args: UseDocumentArgs,\n opts?: UseDocumentOpts\n) => {\n /**\n * These are the schemas of the components used in the content type, organised\n * by their uid.\n */\n components: ComponentsDictionary;\n document?: Document;\n meta?: FindOne.Response['meta'];\n isLoading: boolean;\n /**\n * This is the schema of the content type, it is not the same as the layout.\n */\n schema?: Schema;\n schemas?: Schema[];\n hasError?: boolean;\n refetch: () => void;\n validate: (document: Document) => null | FormErrors;\n /**\n * Get the document's title\n */\n getTitle: (mainField: string) => string;\n /**\n * Get the initial form values for the document\n */\n getInitialFormValues: (isCreatingDocument?: boolean) => AnyData | undefined;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * useDocument\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @alpha\n * @public\n * @description Returns a document based on the model, collection type & id passed as arguments.\n * Also extracts its schema from the redux cache to be used for creating a validation schema.\n * @example\n * ```tsx\n * const { id, model, collectionType } = useParams<{ id: string; model: string; collectionType: string }>();\n *\n * if(!model || !collectionType) return null;\n *\n * const { document, isLoading, validate } = useDocument({ documentId: id, model, collectionType, params: { locale: 'en-GB' } })\n * const { update } = useDocumentActions()\n *\n * const onSubmit = async (document: Document) => {\n * const errors = validate(document);\n *\n * if(errors) {\n * // handle errors\n * }\n *\n * await update({ collectionType, model, id }, document)\n * }\n * ```\n *\n */\nconst useDocument: UseDocument = (args, opts) => {\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n const { formatMessage } = useIntl();\n\n const {\n currentData: data,\n isLoading: isLoadingDocument,\n isFetching: isFetchingDocument,\n error,\n refetch,\n } = useGetDocumentQuery(args, {\n ...opts,\n skip: (!args.documentId && args.collectionType !== SINGLE_TYPES) || opts?.skip,\n });\n const document = data?.data;\n const meta = data?.meta;\n\n const {\n components,\n schema,\n schemas,\n isLoading: isLoadingSchema,\n } = useContentTypeSchema(args.model);\n const isSingleType = schema?.kind === 'singleType';\n\n const getTitle = React.useCallback(\n (mainField: string) => {\n // Always use mainField if it's not an id\n if (mainField !== 'id' && document?.[mainField]) {\n return document[mainField];\n }\n\n // When it's a singleType without a mainField, use the contentType displayName\n if (schema?.kind === 'singleType' && schema.info.displayName) {\n return formatMessage({\n id: schema.info.displayName,\n defaultMessage: schema.info.displayName,\n });\n }\n\n // Otherwise, use a fallback\n return formatMessage({\n id: 'content-manager.containers.untitled',\n defaultMessage: 'Untitled',\n });\n },\n [document, formatMessage, schema]\n );\n\n React.useEffect(() => {\n if (error) {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(error),\n });\n }\n }, [toggleNotification, error, formatAPIError, args.collectionType]);\n\n const validationSchema = React.useMemo(() => {\n if (!schema) {\n return null;\n }\n\n return createYupSchema(schema.attributes, components);\n }, [schema, components]);\n\n const validate = React.useCallback(\n (document: Modules.Documents.AnyDocument): FormErrors | null => {\n if (!validationSchema) {\n throw new Error(\n 'There is no validation schema generated, this is likely due to the schema not being loaded yet.'\n );\n }\n\n try {\n validationSchema.validateSync(document, { abortEarly: false, strict: true });\n return null;\n } catch (error) {\n if (error instanceof ValidationError) {\n return getYupValidationErrors(error);\n }\n\n throw error;\n }\n },\n [validationSchema]\n );\n\n /**\n * Here we prepare the form for editing, we need to:\n * - remove prohibited fields from the document (passwords | ADD YOURS WHEN THERES A NEW ONE)\n * - swap out count objects on relations for empty arrays\n * - set __temp_key__ on array objects for drag & drop\n *\n * We also prepare the form for new documents, so we need to:\n * - set default values on fields\n */\n const getInitialFormValues = React.useCallback(\n (isCreatingDocument: boolean = false) => {\n if ((!document && !isCreatingDocument && !isSingleType) || !schema) {\n return undefined;\n }\n\n /**\n * Check that we have an ID so we know the\n * document has been created in some way.\n */\n const form = document?.id ? document : createDefaultForm(schema, components);\n\n return transformDocument(schema, components)(form);\n },\n [document, isSingleType, schema, components]\n );\n\n const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;\n const hasError = !!error;\n\n return React.useMemo(\n () =>\n ({\n components,\n document,\n meta,\n isLoading,\n hasError,\n schema,\n schemas,\n validate,\n getTitle,\n getInitialFormValues,\n refetch,\n }) satisfies ReturnType<UseDocument>,\n [\n components,\n document,\n meta,\n isLoading,\n hasError,\n schema,\n schemas,\n validate,\n getTitle,\n getInitialFormValues,\n refetch,\n ]\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * useDoc\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @internal this hook uses the router to extract the model, collection type & id from the url.\n * therefore, it shouldn't be used outside of the content-manager because it won't work as intended.\n */\nconst useDoc = (opts?: UseDocumentOpts) => {\n const { id, slug, collectionType, origin } = useParams<{\n id: string;\n origin: string;\n slug: string;\n collectionType: string;\n }>();\n const [{ query }] = useQueryParams();\n const params = React.useMemo(() => buildValidParams(query), [query]);\n\n if (!collectionType) {\n throw new Error('Could not find collectionType in url params');\n }\n\n if (!slug) {\n throw new Error('Could not find model in url params');\n }\n\n const document = useDocument(\n { documentId: origin || id, model: slug, collectionType, params },\n {\n ...opts,\n skip: id === 'create' || (!origin && !id && collectionType !== SINGLE_TYPES) || opts?.skip,\n }\n );\n\n const returnId = origin || (id === 'create' ? undefined : id);\n\n return {\n collectionType,\n model: slug,\n id: returnId,\n ...document,\n };\n};\n\n/**\n * @public\n * @experimental\n * Content manager context hooks for plugin development.\n * Make sure to use this hook inside the content manager.\n */\nconst useContentManagerContext = () => {\n const {\n collectionType,\n model,\n id,\n components,\n isLoading: isLoadingDoc,\n schema,\n schemas,\n } = useDoc();\n\n const layout = useDocumentLayout(model);\n\n const form = useForm<unknown>('useContentManagerContext', (state) => state);\n\n const isSingleType = collectionType === SINGLE_TYPES;\n const slug = model;\n const isCreatingEntry = id === 'create';\n\n const {} = useContentTypeSchema();\n\n const isLoading = isLoadingDoc || layout.isLoading;\n const error = layout.error;\n\n return {\n error,\n isLoading,\n\n // Base metadata\n model,\n collectionType,\n id,\n slug,\n isCreatingEntry,\n isSingleType,\n hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,\n\n // All schema infos\n components,\n contentType: schema,\n contentTypes: schemas,\n\n // Form state\n form,\n\n // layout infos\n layout,\n };\n};\n\nexport { useDocument, useDoc, useContentManagerContext };\nexport type { UseDocument, UseDocumentArgs, Document, Schema, ComponentsDictionary };\n"],"names":["useDocument","args","opts","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","formatMessage","useIntl","currentData","data","isLoading","isLoadingDocument","isFetching","isFetchingDocument","error","refetch","useGetDocumentQuery","skip","documentId","collectionType","SINGLE_TYPES","document","meta","components","schema","schemas","isLoadingSchema","useContentTypeSchema","model","isSingleType","kind","getTitle","React","useCallback","mainField","info","displayName","id","defaultMessage","useEffect","type","message","validationSchema","useMemo","createYupSchema","attributes","validate","Error","validateSync","abortEarly","strict","ValidationError","getYupValidationErrors","getInitialFormValues","isCreatingDocument","undefined","form","createDefaultForm","transformDocument","hasError","useDoc","slug","origin","useParams","query","useQueryParams","params","buildValidParams","returnId","useContentManagerContext","isLoadingDoc","layout","useDocumentLayout","useForm","state","isCreatingEntry","hasDraftAndPublish","options","draftAndPublish","contentType","contentTypes"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6EA;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8BA,MAAMA,WAAAA,GAA2B,CAACC,IAAAA,EAAMC,IAAAA,GAAAA;IACtC,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,2BAAAA,EAAAA;AAC/B,IAAA,MAAM,EAAEC,uBAAAA,EAAyBC,cAAc,EAAE,GAAGC,8BAAAA,EAAAA;IACpD,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,MAAM,EACJC,WAAAA,EAAaC,MAAI,EACjBC,SAAAA,EAAWC,iBAAiB,EAC5BC,UAAAA,EAAYC,kBAAkB,EAC9BC,KAAK,EACLC,OAAO,EACR,GAAGC,8BAAoBjB,IAAAA,EAAM;AAC5B,QAAA,GAAGC,IAAI;QACPiB,IAAAA,EAAO,CAAClB,IAAAA,CAAKmB,UAAU,IAAInB,IAAAA,CAAKoB,cAAc,KAAKC,wBAAAA,IAAiBpB,IAAAA,EAAMiB;AAC5E,KAAA,CAAA;AACA,IAAA,MAAMI,WAAWZ,MAAAA,EAAMA,IAAAA;AACvB,IAAA,MAAMa,OAAOb,MAAAA,EAAMa,IAAAA;AAEnB,IAAA,MAAM,EACJC,UAAU,EACVC,MAAM,EACNC,OAAO,EACPf,SAAAA,EAAWgB,eAAe,EAC3B,GAAGC,yCAAAA,CAAqB5B,KAAK6B,KAAK,CAAA;IACnC,MAAMC,YAAAA,GAAeL,QAAQM,IAAAA,KAAS,YAAA;AAEtC,IAAA,MAAMC,QAAAA,GAAWC,gBAAAA,CAAMC,WAAW,CAChC,CAACC,SAAAA,GAAAA;;AAEC,QAAA,IAAIA,SAAAA,KAAc,IAAA,IAAQb,QAAAA,GAAWa,UAAU,EAAE;YAC/C,OAAOb,QAAQ,CAACa,SAAAA,CAAU;AAC5B,QAAA;;AAGA,QAAA,IAAIV,QAAQM,IAAAA,KAAS,YAAA,IAAgBN,OAAOW,IAAI,CAACC,WAAW,EAAE;AAC5D,YAAA,OAAO9B,aAAAA,CAAc;gBACnB+B,EAAAA,EAAIb,MAAAA,CAAOW,IAAI,CAACC,WAAW;gBAC3BE,cAAAA,EAAgBd,MAAAA,CAAOW,IAAI,CAACC;AAC9B,aAAA,CAAA;AACF,QAAA;;AAGA,QAAA,OAAO9B,aAAAA,CAAc;YACnB+B,EAAAA,EAAI,qCAAA;YACJC,cAAAA,EAAgB;AAClB,SAAA,CAAA;IACF,CAAA,EACA;AAACjB,QAAAA,QAAAA;AAAUf,QAAAA,aAAAA;AAAekB,QAAAA;AAAO,KAAA,CAAA;AAGnCQ,IAAAA,gBAAAA,CAAMO,SAAS,CAAC,IAAA;AACd,QAAA,IAAIzB,KAAAA,EAAO;YACTb,kBAAAA,CAAmB;gBACjBuC,IAAAA,EAAM,QAAA;AACNC,gBAAAA,OAAAA,EAASrC,cAAAA,CAAeU,KAAAA;AAC1B,aAAA,CAAA;AACF,QAAA;IACF,CAAA,EAAG;AAACb,QAAAA,kBAAAA;AAAoBa,QAAAA,KAAAA;AAAOV,QAAAA,cAAAA;AAAgBL,QAAAA,IAAAA,CAAKoB;AAAe,KAAA,CAAA;IAEnE,MAAMuB,gBAAAA,GAAmBV,gBAAAA,CAAMW,OAAO,CAAC,IAAA;AACrC,QAAA,IAAI,CAACnB,MAAAA,EAAQ;YACX,OAAO,IAAA;AACT,QAAA;QAEA,OAAOoB,0BAAAA,CAAgBpB,MAAAA,CAAOqB,UAAU,EAAEtB,UAAAA,CAAAA;IAC5C,CAAA,EAAG;AAACC,QAAAA,MAAAA;AAAQD,QAAAA;AAAW,KAAA,CAAA;AAEvB,IAAA,MAAMuB,QAAAA,GAAWd,gBAAAA,CAAMC,WAAW,CAChC,CAACZ,QAAAA,GAAAA;AACC,QAAA,IAAI,CAACqB,gBAAAA,EAAkB;AACrB,YAAA,MAAM,IAAIK,KAAAA,CACR,iGAAA,CAAA;AAEJ,QAAA;QAEA,IAAI;YACFL,gBAAAA,CAAiBM,YAAY,CAAC3B,QAAAA,EAAU;gBAAE4B,UAAAA,EAAY,KAAA;gBAAOC,MAAAA,EAAQ;AAAK,aAAA,CAAA;YAC1E,OAAO,IAAA;AACT,QAAA,CAAA,CAAE,OAAOpC,KAAAA,EAAO;AACd,YAAA,IAAIA,iBAAiBqC,mBAAAA,EAAiB;AACpC,gBAAA,OAAOC,kCAAAA,CAAuBtC,KAAAA,CAAAA;AAChC,YAAA;YAEA,MAAMA,KAAAA;AACR,QAAA;IACF,CAAA,EACA;AAAC4B,QAAAA;AAAiB,KAAA,CAAA;AAGpB;;;;;;;;AAQC,MACD,MAAMW,oBAAAA,GAAuBrB,gBAAAA,CAAMC,WAAW,CAC5C,CAACqB,qBAA8B,KAAK,GAAA;QAClC,IAAK,CAACjC,QAAAA,IAAY,CAACiC,sBAAsB,CAACzB,YAAAA,IAAiB,CAACL,MAAAA,EAAQ;YAClE,OAAO+B,SAAAA;AACT,QAAA;AAEA;;;AAGC,UACD,MAAMC,IAAAA,GAAOnC,QAAAA,EAAUgB,EAAAA,GAAKhB,QAAAA,GAAWoC,wBAAkBjC,MAAAA,EAAQD,UAAAA,CAAAA;QAEjE,OAAOmC,sBAAAA,CAAkBlC,QAAQD,UAAAA,CAAAA,CAAYiC,IAAAA,CAAAA;IAC/C,CAAA,EACA;AAACnC,QAAAA,QAAAA;AAAUQ,QAAAA,YAAAA;AAAcL,QAAAA,MAAAA;AAAQD,QAAAA;AAAW,KAAA,CAAA;IAG9C,MAAMb,SAAAA,GAAYC,qBAAqBE,kBAAAA,IAAsBa,eAAAA;IAC7D,MAAMiC,QAAAA,GAAW,CAAC,CAAC7C,KAAAA;AAEnB,IAAA,OAAOkB,gBAAAA,CAAMW,OAAO,CAClB,KACG;AACCpB,YAAAA,UAAAA;AACAF,YAAAA,QAAAA;AACAC,YAAAA,IAAAA;AACAZ,YAAAA,SAAAA;AACAiD,YAAAA,QAAAA;AACAnC,YAAAA,MAAAA;AACAC,YAAAA,OAAAA;AACAqB,YAAAA,QAAAA;AACAf,YAAAA,QAAAA;AACAsB,YAAAA,oBAAAA;AACAtC,YAAAA;AACF,SAAA,CAAA,EACF;AACEQ,QAAAA,UAAAA;AACAF,QAAAA,QAAAA;AACAC,QAAAA,IAAAA;AACAZ,QAAAA,SAAAA;AACAiD,QAAAA,QAAAA;AACAnC,QAAAA,MAAAA;AACAC,QAAAA,OAAAA;AACAqB,QAAAA,QAAAA;AACAf,QAAAA,QAAAA;AACAsB,QAAAA,oBAAAA;AACAtC,QAAAA;AACD,KAAA,CAAA;AAEL;AAEA;;;;;IAQA,MAAM6C,SAAS,CAAC5D,IAAAA,GAAAA;IACd,MAAM,EAAEqC,EAAE,EAAEwB,IAAI,EAAE1C,cAAc,EAAE2C,MAAM,EAAE,GAAGC,wBAAAA,EAAAA;AAM7C,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,CAAC,GAAGC,0BAAAA,EAAAA;AACpB,IAAA,MAAMC,SAASlC,gBAAAA,CAAMW,OAAO,CAAC,IAAMwB,qBAAiBH,KAAAA,CAAAA,EAAQ;AAACA,QAAAA;AAAM,KAAA,CAAA;AAEnE,IAAA,IAAI,CAAC7C,cAAAA,EAAgB;AACnB,QAAA,MAAM,IAAI4B,KAAAA,CAAM,6CAAA,CAAA;AAClB,IAAA;AAEA,IAAA,IAAI,CAACc,IAAAA,EAAM;AACT,QAAA,MAAM,IAAId,KAAAA,CAAM,oCAAA,CAAA;AAClB,IAAA;AAEA,IAAA,MAAM1B,WAAWvB,WAAAA,CACf;AAAEoB,QAAAA,UAAAA,EAAY4C,MAAAA,IAAUzB,EAAAA;QAAIT,KAAAA,EAAOiC,IAAAA;AAAM1C,QAAAA,cAAAA;AAAgB+C,QAAAA;KAAO,EAChE;AACE,QAAA,GAAGlE,IAAI;QACPiB,IAAAA,EAAMoB,EAAAA,KAAO,YAAa,CAACyB,MAAAA,IAAU,CAACzB,EAAAA,IAAMlB,cAAAA,KAAmBC,4BAAiBpB,IAAAA,EAAMiB;AACxF,KAAA,CAAA;AAGF,IAAA,MAAMmD,WAAWN,MAAAA,KAAWzB,EAAAA,KAAO,QAAA,GAAWkB,YAAYlB,EAAC,CAAA;IAE3D,OAAO;AACLlB,QAAAA,cAAAA;QACAS,KAAAA,EAAOiC,IAAAA;QACPxB,EAAAA,EAAI+B,QAAAA;AACJ,QAAA,GAAG/C;AACL,KAAA;AACF;AAEA;;;;;AAKC,UACKgD,wBAAAA,GAA2B,IAAA;AAC/B,IAAA,MAAM,EACJlD,cAAc,EACdS,KAAK,EACLS,EAAE,EACFd,UAAU,EACVb,SAAAA,EAAW4D,YAAY,EACvB9C,MAAM,EACNC,OAAO,EACR,GAAGmC,MAAAA,EAAAA;AAEJ,IAAA,MAAMW,SAASC,mCAAAA,CAAkB5C,KAAAA,CAAAA;AAEjC,IAAA,MAAM4B,IAAAA,GAAOiB,mBAAAA,CAAiB,0BAAA,EAA4B,CAACC,KAAAA,GAAUA,KAAAA,CAAAA;AAErE,IAAA,MAAM7C,eAAeV,cAAAA,KAAmBC,wBAAAA;AACxC,IAAA,MAAMyC,IAAAA,GAAOjC,KAAAA;AACb,IAAA,MAAM+C,kBAAkBtC,EAAAA,KAAO,QAAA;AAE/B,IAAWV,yCAAAA;IAEX,MAAMjB,SAAAA,GAAY4D,YAAAA,IAAgBC,MAAAA,CAAO7D,SAAS;IAClD,MAAMI,KAAAA,GAAQyD,OAAOzD,KAAK;IAE1B,OAAO;AACLA,QAAAA,KAAAA;AACAJ,QAAAA,SAAAA;;AAGAkB,QAAAA,KAAAA;AACAT,QAAAA,cAAAA;AACAkB,QAAAA,EAAAA;AACAwB,QAAAA,IAAAA;AACAc,QAAAA,eAAAA;AACA9C,QAAAA,YAAAA;QACA+C,kBAAAA,EAAoBpD,MAAAA,EAAQqD,SAASC,eAAAA,IAAmB,KAAA;;AAGxDvD,QAAAA,UAAAA;QACAwD,WAAAA,EAAavD,MAAAA;QACbwD,YAAAA,EAAcvD,OAAAA;;AAGd+B,QAAAA,IAAAA;;AAGAe,QAAAA;AACF,KAAA;AACF;;;;;;"}
|
|
1
|
+
{"version":3,"file":"useDocument.js","sources":["../../../admin/src/hooks/useDocument.ts"],"sourcesContent":["/**\n * This hook doesn't use a context provider because we fetch directly from the server,\n * this sounds expensive but actually, it's really not. Because we have redux-toolkit-query\n * being a cache layer so if nothing invalidates the cache, we don't fetch again.\n */\n\nimport * as React from 'react';\n\nimport {\n useNotification,\n useAPIErrorHandler,\n useQueryParams,\n FormErrors,\n getYupValidationErrors,\n useForm,\n} from '@strapi/admin/strapi-admin';\nimport { useIntl } from 'react-intl';\nimport { useParams } from 'react-router-dom';\nimport { ValidationError } from 'yup';\n\nimport { SINGLE_TYPES } from '../constants/collections';\nimport { type AnyData, transformDocument } from '../pages/EditView/utils/data';\nimport { createDefaultForm } from '../pages/EditView/utils/forms';\nimport { useGetDocumentQuery } from '../services/documents';\nimport { buildValidParams } from '../utils/api';\nimport { createYupSchema } from '../utils/validation';\n\nimport { useContentTypeSchema, ComponentsDictionary } from './useContentTypeSchema';\nimport { useDocumentLayout } from './useDocumentLayout';\n\nimport type { FindOne } from '../../../shared/contracts/collection-types';\nimport type { ContentType } from '../../../shared/contracts/content-types';\nimport type { Modules } from '@strapi/types';\n\ninterface UseDocumentArgs {\n collectionType: string;\n model: string;\n documentId?: string;\n params?: object;\n}\n\ntype UseDocumentOpts = Parameters<typeof useGetDocumentQuery>[1];\n\ntype Document = FindOne.Response['data'];\n\ntype Schema = ContentType;\n\ntype UseDocument = (\n args: UseDocumentArgs,\n opts?: UseDocumentOpts\n) => {\n /**\n * These are the schemas of the components used in the content type, organised\n * by their uid.\n */\n components: ComponentsDictionary;\n document?: Document;\n meta?: FindOne.Response['meta'];\n isLoading: boolean;\n /**\n * This is the schema of the content type, it is not the same as the layout.\n */\n schema?: Schema;\n schemas?: Schema[];\n hasError?: boolean;\n refetch: () => void;\n validate: (document: Document) => null | FormErrors;\n /**\n * Get the document's title\n */\n getTitle: (mainField: string) => string;\n /**\n * Get the initial form values for the document\n */\n getInitialFormValues: (isCreatingDocument?: boolean) => AnyData | undefined;\n};\n\n/**\n * Mirrors the server's `isLocalizedAttribute` in\n * `packages/plugins/i18n/server/src/services/content-types.ts`: an attribute\n * counts as localized only when `pluginOptions.i18n.localized` is explicitly\n * `true`. Both `false` and `undefined` mean \"non-localized\" — important here\n * because attributes created without the i18n plugin omit the field entirely,\n * and we still want them inherited when creating a new locale draft.\n */\nconst isLocalizedAttribute = (attribute: { pluginOptions?: object }): boolean => {\n // `pluginOptions` on the base attribute is typed as `object`, so we have to\n // narrow it to the i18n-specific shape here.\n const i18nOptions = attribute.pluginOptions as { i18n?: { localized?: boolean } } | undefined;\n return i18nOptions?.i18n?.localized === true;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * useDocument\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @alpha\n * @public\n * @description Returns a document based on the model, collection type & id passed as arguments.\n * Also extracts its schema from the redux cache to be used for creating a validation schema.\n * @example\n * ```tsx\n * const { id, model, collectionType } = useParams<{ id: string; model: string; collectionType: string }>();\n *\n * if(!model || !collectionType) return null;\n *\n * const { document, isLoading, validate } = useDocument({ documentId: id, model, collectionType, params: { locale: 'en-GB' } })\n * const { update } = useDocumentActions()\n *\n * const onSubmit = async (document: Document) => {\n * const errors = validate(document);\n *\n * if(errors) {\n * // handle errors\n * }\n *\n * await update({ collectionType, model, id }, document)\n * }\n * ```\n *\n */\nconst useDocument: UseDocument = (args, opts) => {\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n const { formatMessage } = useIntl();\n\n const {\n currentData: data,\n isLoading: isLoadingDocument,\n isFetching: isFetchingDocument,\n error,\n refetch,\n } = useGetDocumentQuery(args, {\n ...opts,\n skip: (!args.documentId && args.collectionType !== SINGLE_TYPES) || opts?.skip,\n });\n const document = data?.data;\n const meta = data?.meta;\n\n const {\n components,\n schema,\n schemas,\n isLoading: isLoadingSchema,\n } = useContentTypeSchema(args.model);\n const isSingleType = schema?.kind === 'singleType';\n\n const getTitle = React.useCallback(\n (mainField: string) => {\n // Always use mainField if it's not an id\n if (mainField !== 'id' && document?.[mainField]) {\n return document[mainField];\n }\n\n // When it's a singleType without a mainField, use the contentType displayName\n if (schema?.kind === 'singleType' && schema.info.displayName) {\n return formatMessage({\n id: schema.info.displayName,\n defaultMessage: schema.info.displayName,\n });\n }\n\n // Otherwise, use a fallback\n return formatMessage({\n id: 'content-manager.containers.untitled',\n defaultMessage: 'Untitled',\n });\n },\n [document, formatMessage, schema]\n );\n\n React.useEffect(() => {\n if (error) {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(error),\n });\n }\n }, [toggleNotification, error, formatAPIError, args.collectionType]);\n\n const validationSchema = React.useMemo(() => {\n if (!schema) {\n return null;\n }\n\n return createYupSchema(schema.attributes, components);\n }, [schema, components]);\n\n const validate = React.useCallback(\n (document: Modules.Documents.AnyDocument): FormErrors | null => {\n if (!validationSchema) {\n throw new Error(\n 'There is no validation schema generated, this is likely due to the schema not being loaded yet.'\n );\n }\n\n try {\n validationSchema.validateSync(document, { abortEarly: false, strict: true });\n return null;\n } catch (error) {\n if (error instanceof ValidationError) {\n return getYupValidationErrors(error);\n }\n\n throw error;\n }\n },\n [validationSchema]\n );\n\n /**\n * Schema attributes that should be inherited from a sibling locale when\n * creating a new locale draft.\n *\n * Scope intentionally matches what the server populates into\n * `meta.availableLocales` (see `packages/core/content-manager/server/src/services/document-metadata.ts`):\n * - non-localized — `isLocalizedAttribute` semantics, so attributes whose\n * `pluginOptions.i18n.localized` is `undefined` count as non-localized\n * (an attribute created without the i18n plugin has no i18n options at\n * all but is still inherited at save by `copyNonLocalizedFields`).\n * - scalar or media — `component` / `dynamiczone` / `relation` are excluded\n * because the server doesn't populate them in `availableLocales` either,\n * so there'd be nothing to copy from.\n */\n const nonLocalizedScalarAndMediaFields = React.useMemo(() => {\n if (!schema?.attributes) {\n return [];\n }\n\n return Object.keys(schema.attributes).filter((name) => {\n const attribute = schema.attributes[name];\n\n if (isLocalizedAttribute(attribute)) {\n return false;\n }\n\n return (\n attribute.type !== 'component' &&\n attribute.type !== 'dynamiczone' &&\n attribute.type !== 'relation'\n );\n });\n }, [schema]);\n\n /**\n * Here we prepare the form for editing, we need to:\n * - remove prohibited fields from the document (passwords | ADD YOURS WHEN THERES A NEW ONE)\n * - swap out count objects on relations for empty arrays\n * - set __temp_key__ on array objects for drag & drop\n *\n * We also prepare the form for new documents, so we need to:\n * - set default values on fields\n * - inherit non-localized scalar/media values from a sibling locale.\n * Scope is intentionally limited to scalars and media — that is exactly\n * what the server populates into `meta.availableLocales` (see\n * `packages/core/content-manager/server/src/services/document-metadata.ts`).\n * Components, dynamic zones, and relations are not in that payload; the\n * server fills them at save time via `copyNonLocalizedFields` (in\n * `packages/core/core/src/services/document-service/internationalization.ts`)\n * when the new locale row is first created.\n * Baking the inheritance into `initialValues` here is what lets it survive\n * `<Form>` re-inits: the `SET_INITIAL_VALUES` effect in\n * `packages/core/admin/admin/src/components/Form.tsx` re-applies these\n * values whenever `initialValues` changes (e.g. after a locale switch),\n * which the previous side-effect-based prefill in `LocalePickerAction`\n * could not survive on revisits.\n */\n const getInitialFormValues = React.useCallback(\n (isCreatingDocument: boolean = false) => {\n if ((!document && !isCreatingDocument && !isSingleType) || !schema) {\n return undefined;\n }\n\n /**\n * Check that we have an ID so we know the\n * document has been created in some way.\n */\n if (document?.id) {\n return transformDocument(schema, components)(document);\n }\n\n let form: AnyData = createDefaultForm(schema, components);\n\n // Intentionally use `availableLocales[0]`:\n // - The server sorts `getAvailableLocales` with the default locale first\n // (see `document-metadata.ts`), so index 0 is the canonical inheritance\n // source. Sibling locales can drift on non-localized fields because the\n // server only syncs them at locale-creation time, not on subsequent\n // updates — preferring the default keeps the surfaced values stable.\n // - Avoids coupling this hook to `useGetLocalesQuery` just to find the\n // default locale.\n const sibling = meta?.availableLocales?.[0] as Record<string, unknown> | undefined;\n if (sibling && nonLocalizedScalarAndMediaFields.length > 0) {\n const inherited = nonLocalizedScalarAndMediaFields.reduce<AnyData>((acc, name) => {\n if (name in sibling) {\n acc[name] = sibling[name];\n }\n return acc;\n }, {});\n\n form = { ...form, ...inherited };\n }\n\n return transformDocument(schema, components)(form);\n },\n [\n document,\n isSingleType,\n schema,\n components,\n meta?.availableLocales,\n nonLocalizedScalarAndMediaFields,\n ]\n );\n\n const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;\n const hasError = !!error;\n\n return React.useMemo(\n () =>\n ({\n components,\n document,\n meta,\n isLoading,\n hasError,\n schema,\n schemas,\n validate,\n getTitle,\n getInitialFormValues,\n refetch,\n }) satisfies ReturnType<UseDocument>,\n [\n components,\n document,\n meta,\n isLoading,\n hasError,\n schema,\n schemas,\n validate,\n getTitle,\n getInitialFormValues,\n refetch,\n ]\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * useDoc\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @internal this hook uses the router to extract the model, collection type & id from the url.\n * therefore, it shouldn't be used outside of the content-manager because it won't work as intended.\n */\nconst useDoc = (opts?: UseDocumentOpts) => {\n const { id, slug, collectionType, origin } = useParams<{\n id: string;\n origin: string;\n slug: string;\n collectionType: string;\n }>();\n const [{ query }] = useQueryParams();\n const params = React.useMemo(() => buildValidParams(query), [query]);\n\n if (!collectionType) {\n throw new Error('Could not find collectionType in url params');\n }\n\n if (!slug) {\n throw new Error('Could not find model in url params');\n }\n\n const document = useDocument(\n { documentId: origin || id, model: slug, collectionType, params },\n {\n ...opts,\n skip: id === 'create' || (!origin && !id && collectionType !== SINGLE_TYPES) || opts?.skip,\n }\n );\n\n const returnId = origin || (id === 'create' ? undefined : id);\n\n return {\n collectionType,\n model: slug,\n id: returnId,\n ...document,\n };\n};\n\n/**\n * @public\n * @experimental\n * Content manager context hooks for plugin development.\n * Make sure to use this hook inside the content manager.\n */\nconst useContentManagerContext = () => {\n const {\n collectionType,\n model,\n id,\n components,\n isLoading: isLoadingDoc,\n schema,\n schemas,\n } = useDoc();\n\n const layout = useDocumentLayout(model);\n\n const form = useForm<unknown>('useContentManagerContext', (state) => state);\n\n const isSingleType = collectionType === SINGLE_TYPES;\n const slug = model;\n const isCreatingEntry = id === 'create';\n\n const {} = useContentTypeSchema();\n\n const isLoading = isLoadingDoc || layout.isLoading;\n const error = layout.error;\n\n return {\n error,\n isLoading,\n\n // Base metadata\n model,\n collectionType,\n id,\n slug,\n isCreatingEntry,\n isSingleType,\n hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,\n\n // All schema infos\n components,\n contentType: schema,\n contentTypes: schemas,\n\n // Form state\n form,\n\n // layout infos\n layout,\n };\n};\n\nexport { useDocument, useDoc, useContentManagerContext };\nexport type { UseDocument, UseDocumentArgs, Document, Schema, ComponentsDictionary };\n"],"names":["isLocalizedAttribute","attribute","i18nOptions","pluginOptions","i18n","localized","useDocument","args","opts","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","formatMessage","useIntl","currentData","data","isLoading","isLoadingDocument","isFetching","isFetchingDocument","error","refetch","useGetDocumentQuery","skip","documentId","collectionType","SINGLE_TYPES","document","meta","components","schema","schemas","isLoadingSchema","useContentTypeSchema","model","isSingleType","kind","getTitle","React","useCallback","mainField","info","displayName","id","defaultMessage","useEffect","type","message","validationSchema","useMemo","createYupSchema","attributes","validate","Error","validateSync","abortEarly","strict","ValidationError","getYupValidationErrors","nonLocalizedScalarAndMediaFields","Object","keys","filter","name","getInitialFormValues","isCreatingDocument","undefined","transformDocument","form","createDefaultForm","sibling","availableLocales","length","inherited","reduce","acc","hasError","useDoc","slug","origin","useParams","query","useQueryParams","params","buildValidParams","returnId","useContentManagerContext","isLoadingDoc","layout","useDocumentLayout","useForm","state","isCreatingEntry","hasDraftAndPublish","options","draftAndPublish","contentType","contentTypes"],"mappings":"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"}
|
|
@@ -12,6 +12,19 @@ import { createYupSchema } from '../utils/validation.mjs';
|
|
|
12
12
|
import { useContentTypeSchema } from './useContentTypeSchema.mjs';
|
|
13
13
|
import { useDocumentLayout } from './useDocumentLayout.mjs';
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Mirrors the server's `isLocalizedAttribute` in
|
|
17
|
+
* `packages/plugins/i18n/server/src/services/content-types.ts`: an attribute
|
|
18
|
+
* counts as localized only when `pluginOptions.i18n.localized` is explicitly
|
|
19
|
+
* `true`. Both `false` and `undefined` mean "non-localized" — important here
|
|
20
|
+
* because attributes created without the i18n plugin omit the field entirely,
|
|
21
|
+
* and we still want them inherited when creating a new locale draft.
|
|
22
|
+
*/ const isLocalizedAttribute = (attribute)=>{
|
|
23
|
+
// `pluginOptions` on the base attribute is typed as `object`, so we have to
|
|
24
|
+
// narrow it to the i18n-specific shape here.
|
|
25
|
+
const i18nOptions = attribute.pluginOptions;
|
|
26
|
+
return i18nOptions?.i18n?.localized === true;
|
|
27
|
+
};
|
|
15
28
|
/* -------------------------------------------------------------------------------------------------
|
|
16
29
|
* useDocument
|
|
17
30
|
* -----------------------------------------------------------------------------------------------*/ /**
|
|
@@ -115,6 +128,33 @@ import { useDocumentLayout } from './useDocumentLayout.mjs';
|
|
|
115
128
|
validationSchema
|
|
116
129
|
]);
|
|
117
130
|
/**
|
|
131
|
+
* Schema attributes that should be inherited from a sibling locale when
|
|
132
|
+
* creating a new locale draft.
|
|
133
|
+
*
|
|
134
|
+
* Scope intentionally matches what the server populates into
|
|
135
|
+
* `meta.availableLocales` (see `packages/core/content-manager/server/src/services/document-metadata.ts`):
|
|
136
|
+
* - non-localized — `isLocalizedAttribute` semantics, so attributes whose
|
|
137
|
+
* `pluginOptions.i18n.localized` is `undefined` count as non-localized
|
|
138
|
+
* (an attribute created without the i18n plugin has no i18n options at
|
|
139
|
+
* all but is still inherited at save by `copyNonLocalizedFields`).
|
|
140
|
+
* - scalar or media — `component` / `dynamiczone` / `relation` are excluded
|
|
141
|
+
* because the server doesn't populate them in `availableLocales` either,
|
|
142
|
+
* so there'd be nothing to copy from.
|
|
143
|
+
*/ const nonLocalizedScalarAndMediaFields = React.useMemo(()=>{
|
|
144
|
+
if (!schema?.attributes) {
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
return Object.keys(schema.attributes).filter((name)=>{
|
|
148
|
+
const attribute = schema.attributes[name];
|
|
149
|
+
if (isLocalizedAttribute(attribute)) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
return attribute.type !== 'component' && attribute.type !== 'dynamiczone' && attribute.type !== 'relation';
|
|
153
|
+
});
|
|
154
|
+
}, [
|
|
155
|
+
schema
|
|
156
|
+
]);
|
|
157
|
+
/**
|
|
118
158
|
* Here we prepare the form for editing, we need to:
|
|
119
159
|
* - remove prohibited fields from the document (passwords | ADD YOURS WHEN THERES A NEW ONE)
|
|
120
160
|
* - swap out count objects on relations for empty arrays
|
|
@@ -122,6 +162,20 @@ import { useDocumentLayout } from './useDocumentLayout.mjs';
|
|
|
122
162
|
*
|
|
123
163
|
* We also prepare the form for new documents, so we need to:
|
|
124
164
|
* - set default values on fields
|
|
165
|
+
* - inherit non-localized scalar/media values from a sibling locale.
|
|
166
|
+
* Scope is intentionally limited to scalars and media — that is exactly
|
|
167
|
+
* what the server populates into `meta.availableLocales` (see
|
|
168
|
+
* `packages/core/content-manager/server/src/services/document-metadata.ts`).
|
|
169
|
+
* Components, dynamic zones, and relations are not in that payload; the
|
|
170
|
+
* server fills them at save time via `copyNonLocalizedFields` (in
|
|
171
|
+
* `packages/core/core/src/services/document-service/internationalization.ts`)
|
|
172
|
+
* when the new locale row is first created.
|
|
173
|
+
* Baking the inheritance into `initialValues` here is what lets it survive
|
|
174
|
+
* `<Form>` re-inits: the `SET_INITIAL_VALUES` effect in
|
|
175
|
+
* `packages/core/admin/admin/src/components/Form.tsx` re-applies these
|
|
176
|
+
* values whenever `initialValues` changes (e.g. after a locale switch),
|
|
177
|
+
* which the previous side-effect-based prefill in `LocalePickerAction`
|
|
178
|
+
* could not survive on revisits.
|
|
125
179
|
*/ const getInitialFormValues = React.useCallback((isCreatingDocument = false)=>{
|
|
126
180
|
if (!document && !isCreatingDocument && !isSingleType || !schema) {
|
|
127
181
|
return undefined;
|
|
@@ -129,13 +183,39 @@ import { useDocumentLayout } from './useDocumentLayout.mjs';
|
|
|
129
183
|
/**
|
|
130
184
|
* Check that we have an ID so we know the
|
|
131
185
|
* document has been created in some way.
|
|
132
|
-
*/
|
|
186
|
+
*/ if (document?.id) {
|
|
187
|
+
return transformDocument(schema, components)(document);
|
|
188
|
+
}
|
|
189
|
+
let form = createDefaultForm(schema, components);
|
|
190
|
+
// Intentionally use `availableLocales[0]`:
|
|
191
|
+
// - The server sorts `getAvailableLocales` with the default locale first
|
|
192
|
+
// (see `document-metadata.ts`), so index 0 is the canonical inheritance
|
|
193
|
+
// source. Sibling locales can drift on non-localized fields because the
|
|
194
|
+
// server only syncs them at locale-creation time, not on subsequent
|
|
195
|
+
// updates — preferring the default keeps the surfaced values stable.
|
|
196
|
+
// - Avoids coupling this hook to `useGetLocalesQuery` just to find the
|
|
197
|
+
// default locale.
|
|
198
|
+
const sibling = meta?.availableLocales?.[0];
|
|
199
|
+
if (sibling && nonLocalizedScalarAndMediaFields.length > 0) {
|
|
200
|
+
const inherited = nonLocalizedScalarAndMediaFields.reduce((acc, name)=>{
|
|
201
|
+
if (name in sibling) {
|
|
202
|
+
acc[name] = sibling[name];
|
|
203
|
+
}
|
|
204
|
+
return acc;
|
|
205
|
+
}, {});
|
|
206
|
+
form = {
|
|
207
|
+
...form,
|
|
208
|
+
...inherited
|
|
209
|
+
};
|
|
210
|
+
}
|
|
133
211
|
return transformDocument(schema, components)(form);
|
|
134
212
|
}, [
|
|
135
213
|
document,
|
|
136
214
|
isSingleType,
|
|
137
215
|
schema,
|
|
138
|
-
components
|
|
216
|
+
components,
|
|
217
|
+
meta?.availableLocales,
|
|
218
|
+
nonLocalizedScalarAndMediaFields
|
|
139
219
|
]);
|
|
140
220
|
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
|
141
221
|
const hasError = !!error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDocument.mjs","sources":["../../../admin/src/hooks/useDocument.ts"],"sourcesContent":["/**\n * This hook doesn't use a context provider because we fetch directly from the server,\n * this sounds expensive but actually, it's really not. Because we have redux-toolkit-query\n * being a cache layer so if nothing invalidates the cache, we don't fetch again.\n */\n\nimport * as React from 'react';\n\nimport {\n useNotification,\n useAPIErrorHandler,\n useQueryParams,\n FormErrors,\n getYupValidationErrors,\n useForm,\n} from '@strapi/admin/strapi-admin';\nimport { useIntl } from 'react-intl';\nimport { useParams } from 'react-router-dom';\nimport { ValidationError } from 'yup';\n\nimport { SINGLE_TYPES } from '../constants/collections';\nimport { type AnyData, transformDocument } from '../pages/EditView/utils/data';\nimport { createDefaultForm } from '../pages/EditView/utils/forms';\nimport { useGetDocumentQuery } from '../services/documents';\nimport { buildValidParams } from '../utils/api';\nimport { createYupSchema } from '../utils/validation';\n\nimport { useContentTypeSchema, ComponentsDictionary } from './useContentTypeSchema';\nimport { useDocumentLayout } from './useDocumentLayout';\n\nimport type { FindOne } from '../../../shared/contracts/collection-types';\nimport type { ContentType } from '../../../shared/contracts/content-types';\nimport type { Modules } from '@strapi/types';\n\ninterface UseDocumentArgs {\n collectionType: string;\n model: string;\n documentId?: string;\n params?: object;\n}\n\ntype UseDocumentOpts = Parameters<typeof useGetDocumentQuery>[1];\n\ntype Document = FindOne.Response['data'];\n\ntype Schema = ContentType;\n\ntype UseDocument = (\n args: UseDocumentArgs,\n opts?: UseDocumentOpts\n) => {\n /**\n * These are the schemas of the components used in the content type, organised\n * by their uid.\n */\n components: ComponentsDictionary;\n document?: Document;\n meta?: FindOne.Response['meta'];\n isLoading: boolean;\n /**\n * This is the schema of the content type, it is not the same as the layout.\n */\n schema?: Schema;\n schemas?: Schema[];\n hasError?: boolean;\n refetch: () => void;\n validate: (document: Document) => null | FormErrors;\n /**\n * Get the document's title\n */\n getTitle: (mainField: string) => string;\n /**\n * Get the initial form values for the document\n */\n getInitialFormValues: (isCreatingDocument?: boolean) => AnyData | undefined;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * useDocument\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @alpha\n * @public\n * @description Returns a document based on the model, collection type & id passed as arguments.\n * Also extracts its schema from the redux cache to be used for creating a validation schema.\n * @example\n * ```tsx\n * const { id, model, collectionType } = useParams<{ id: string; model: string; collectionType: string }>();\n *\n * if(!model || !collectionType) return null;\n *\n * const { document, isLoading, validate } = useDocument({ documentId: id, model, collectionType, params: { locale: 'en-GB' } })\n * const { update } = useDocumentActions()\n *\n * const onSubmit = async (document: Document) => {\n * const errors = validate(document);\n *\n * if(errors) {\n * // handle errors\n * }\n *\n * await update({ collectionType, model, id }, document)\n * }\n * ```\n *\n */\nconst useDocument: UseDocument = (args, opts) => {\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n const { formatMessage } = useIntl();\n\n const {\n currentData: data,\n isLoading: isLoadingDocument,\n isFetching: isFetchingDocument,\n error,\n refetch,\n } = useGetDocumentQuery(args, {\n ...opts,\n skip: (!args.documentId && args.collectionType !== SINGLE_TYPES) || opts?.skip,\n });\n const document = data?.data;\n const meta = data?.meta;\n\n const {\n components,\n schema,\n schemas,\n isLoading: isLoadingSchema,\n } = useContentTypeSchema(args.model);\n const isSingleType = schema?.kind === 'singleType';\n\n const getTitle = React.useCallback(\n (mainField: string) => {\n // Always use mainField if it's not an id\n if (mainField !== 'id' && document?.[mainField]) {\n return document[mainField];\n }\n\n // When it's a singleType without a mainField, use the contentType displayName\n if (schema?.kind === 'singleType' && schema.info.displayName) {\n return formatMessage({\n id: schema.info.displayName,\n defaultMessage: schema.info.displayName,\n });\n }\n\n // Otherwise, use a fallback\n return formatMessage({\n id: 'content-manager.containers.untitled',\n defaultMessage: 'Untitled',\n });\n },\n [document, formatMessage, schema]\n );\n\n React.useEffect(() => {\n if (error) {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(error),\n });\n }\n }, [toggleNotification, error, formatAPIError, args.collectionType]);\n\n const validationSchema = React.useMemo(() => {\n if (!schema) {\n return null;\n }\n\n return createYupSchema(schema.attributes, components);\n }, [schema, components]);\n\n const validate = React.useCallback(\n (document: Modules.Documents.AnyDocument): FormErrors | null => {\n if (!validationSchema) {\n throw new Error(\n 'There is no validation schema generated, this is likely due to the schema not being loaded yet.'\n );\n }\n\n try {\n validationSchema.validateSync(document, { abortEarly: false, strict: true });\n return null;\n } catch (error) {\n if (error instanceof ValidationError) {\n return getYupValidationErrors(error);\n }\n\n throw error;\n }\n },\n [validationSchema]\n );\n\n /**\n * Here we prepare the form for editing, we need to:\n * - remove prohibited fields from the document (passwords | ADD YOURS WHEN THERES A NEW ONE)\n * - swap out count objects on relations for empty arrays\n * - set __temp_key__ on array objects for drag & drop\n *\n * We also prepare the form for new documents, so we need to:\n * - set default values on fields\n */\n const getInitialFormValues = React.useCallback(\n (isCreatingDocument: boolean = false) => {\n if ((!document && !isCreatingDocument && !isSingleType) || !schema) {\n return undefined;\n }\n\n /**\n * Check that we have an ID so we know the\n * document has been created in some way.\n */\n const form = document?.id ? document : createDefaultForm(schema, components);\n\n return transformDocument(schema, components)(form);\n },\n [document, isSingleType, schema, components]\n );\n\n const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;\n const hasError = !!error;\n\n return React.useMemo(\n () =>\n ({\n components,\n document,\n meta,\n isLoading,\n hasError,\n schema,\n schemas,\n validate,\n getTitle,\n getInitialFormValues,\n refetch,\n }) satisfies ReturnType<UseDocument>,\n [\n components,\n document,\n meta,\n isLoading,\n hasError,\n schema,\n schemas,\n validate,\n getTitle,\n getInitialFormValues,\n refetch,\n ]\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * useDoc\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @internal this hook uses the router to extract the model, collection type & id from the url.\n * therefore, it shouldn't be used outside of the content-manager because it won't work as intended.\n */\nconst useDoc = (opts?: UseDocumentOpts) => {\n const { id, slug, collectionType, origin } = useParams<{\n id: string;\n origin: string;\n slug: string;\n collectionType: string;\n }>();\n const [{ query }] = useQueryParams();\n const params = React.useMemo(() => buildValidParams(query), [query]);\n\n if (!collectionType) {\n throw new Error('Could not find collectionType in url params');\n }\n\n if (!slug) {\n throw new Error('Could not find model in url params');\n }\n\n const document = useDocument(\n { documentId: origin || id, model: slug, collectionType, params },\n {\n ...opts,\n skip: id === 'create' || (!origin && !id && collectionType !== SINGLE_TYPES) || opts?.skip,\n }\n );\n\n const returnId = origin || (id === 'create' ? undefined : id);\n\n return {\n collectionType,\n model: slug,\n id: returnId,\n ...document,\n };\n};\n\n/**\n * @public\n * @experimental\n * Content manager context hooks for plugin development.\n * Make sure to use this hook inside the content manager.\n */\nconst useContentManagerContext = () => {\n const {\n collectionType,\n model,\n id,\n components,\n isLoading: isLoadingDoc,\n schema,\n schemas,\n } = useDoc();\n\n const layout = useDocumentLayout(model);\n\n const form = useForm<unknown>('useContentManagerContext', (state) => state);\n\n const isSingleType = collectionType === SINGLE_TYPES;\n const slug = model;\n const isCreatingEntry = id === 'create';\n\n const {} = useContentTypeSchema();\n\n const isLoading = isLoadingDoc || layout.isLoading;\n const error = layout.error;\n\n return {\n error,\n isLoading,\n\n // Base metadata\n model,\n collectionType,\n id,\n slug,\n isCreatingEntry,\n isSingleType,\n hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,\n\n // All schema infos\n components,\n contentType: schema,\n contentTypes: schemas,\n\n // Form state\n form,\n\n // layout infos\n layout,\n };\n};\n\nexport { useDocument, useDoc, useContentManagerContext };\nexport type { UseDocument, UseDocumentArgs, Document, Schema, ComponentsDictionary };\n"],"names":["useDocument","args","opts","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","formatMessage","useIntl","currentData","data","isLoading","isLoadingDocument","isFetching","isFetchingDocument","error","refetch","useGetDocumentQuery","skip","documentId","collectionType","SINGLE_TYPES","document","meta","components","schema","schemas","isLoadingSchema","useContentTypeSchema","model","isSingleType","kind","getTitle","React","useCallback","mainField","info","displayName","id","defaultMessage","useEffect","type","message","validationSchema","useMemo","createYupSchema","attributes","validate","Error","validateSync","abortEarly","strict","ValidationError","getYupValidationErrors","getInitialFormValues","isCreatingDocument","undefined","form","createDefaultForm","transformDocument","hasError","useDoc","slug","origin","useParams","query","useQueryParams","params","buildValidParams","returnId","useContentManagerContext","isLoadingDoc","layout","useDocumentLayout","useForm","state","isCreatingEntry","hasDraftAndPublish","options","draftAndPublish","contentType","contentTypes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useDocument.mjs","sources":["../../../admin/src/hooks/useDocument.ts"],"sourcesContent":["/**\n * This hook doesn't use a context provider because we fetch directly from the server,\n * this sounds expensive but actually, it's really not. Because we have redux-toolkit-query\n * being a cache layer so if nothing invalidates the cache, we don't fetch again.\n */\n\nimport * as React from 'react';\n\nimport {\n useNotification,\n useAPIErrorHandler,\n useQueryParams,\n FormErrors,\n getYupValidationErrors,\n useForm,\n} from '@strapi/admin/strapi-admin';\nimport { useIntl } from 'react-intl';\nimport { useParams } from 'react-router-dom';\nimport { ValidationError } from 'yup';\n\nimport { SINGLE_TYPES } from '../constants/collections';\nimport { type AnyData, transformDocument } from '../pages/EditView/utils/data';\nimport { createDefaultForm } from '../pages/EditView/utils/forms';\nimport { useGetDocumentQuery } from '../services/documents';\nimport { buildValidParams } from '../utils/api';\nimport { createYupSchema } from '../utils/validation';\n\nimport { useContentTypeSchema, ComponentsDictionary } from './useContentTypeSchema';\nimport { useDocumentLayout } from './useDocumentLayout';\n\nimport type { FindOne } from '../../../shared/contracts/collection-types';\nimport type { ContentType } from '../../../shared/contracts/content-types';\nimport type { Modules } from '@strapi/types';\n\ninterface UseDocumentArgs {\n collectionType: string;\n model: string;\n documentId?: string;\n params?: object;\n}\n\ntype UseDocumentOpts = Parameters<typeof useGetDocumentQuery>[1];\n\ntype Document = FindOne.Response['data'];\n\ntype Schema = ContentType;\n\ntype UseDocument = (\n args: UseDocumentArgs,\n opts?: UseDocumentOpts\n) => {\n /**\n * These are the schemas of the components used in the content type, organised\n * by their uid.\n */\n components: ComponentsDictionary;\n document?: Document;\n meta?: FindOne.Response['meta'];\n isLoading: boolean;\n /**\n * This is the schema of the content type, it is not the same as the layout.\n */\n schema?: Schema;\n schemas?: Schema[];\n hasError?: boolean;\n refetch: () => void;\n validate: (document: Document) => null | FormErrors;\n /**\n * Get the document's title\n */\n getTitle: (mainField: string) => string;\n /**\n * Get the initial form values for the document\n */\n getInitialFormValues: (isCreatingDocument?: boolean) => AnyData | undefined;\n};\n\n/**\n * Mirrors the server's `isLocalizedAttribute` in\n * `packages/plugins/i18n/server/src/services/content-types.ts`: an attribute\n * counts as localized only when `pluginOptions.i18n.localized` is explicitly\n * `true`. Both `false` and `undefined` mean \"non-localized\" — important here\n * because attributes created without the i18n plugin omit the field entirely,\n * and we still want them inherited when creating a new locale draft.\n */\nconst isLocalizedAttribute = (attribute: { pluginOptions?: object }): boolean => {\n // `pluginOptions` on the base attribute is typed as `object`, so we have to\n // narrow it to the i18n-specific shape here.\n const i18nOptions = attribute.pluginOptions as { i18n?: { localized?: boolean } } | undefined;\n return i18nOptions?.i18n?.localized === true;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * useDocument\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @alpha\n * @public\n * @description Returns a document based on the model, collection type & id passed as arguments.\n * Also extracts its schema from the redux cache to be used for creating a validation schema.\n * @example\n * ```tsx\n * const { id, model, collectionType } = useParams<{ id: string; model: string; collectionType: string }>();\n *\n * if(!model || !collectionType) return null;\n *\n * const { document, isLoading, validate } = useDocument({ documentId: id, model, collectionType, params: { locale: 'en-GB' } })\n * const { update } = useDocumentActions()\n *\n * const onSubmit = async (document: Document) => {\n * const errors = validate(document);\n *\n * if(errors) {\n * // handle errors\n * }\n *\n * await update({ collectionType, model, id }, document)\n * }\n * ```\n *\n */\nconst useDocument: UseDocument = (args, opts) => {\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n const { formatMessage } = useIntl();\n\n const {\n currentData: data,\n isLoading: isLoadingDocument,\n isFetching: isFetchingDocument,\n error,\n refetch,\n } = useGetDocumentQuery(args, {\n ...opts,\n skip: (!args.documentId && args.collectionType !== SINGLE_TYPES) || opts?.skip,\n });\n const document = data?.data;\n const meta = data?.meta;\n\n const {\n components,\n schema,\n schemas,\n isLoading: isLoadingSchema,\n } = useContentTypeSchema(args.model);\n const isSingleType = schema?.kind === 'singleType';\n\n const getTitle = React.useCallback(\n (mainField: string) => {\n // Always use mainField if it's not an id\n if (mainField !== 'id' && document?.[mainField]) {\n return document[mainField];\n }\n\n // When it's a singleType without a mainField, use the contentType displayName\n if (schema?.kind === 'singleType' && schema.info.displayName) {\n return formatMessage({\n id: schema.info.displayName,\n defaultMessage: schema.info.displayName,\n });\n }\n\n // Otherwise, use a fallback\n return formatMessage({\n id: 'content-manager.containers.untitled',\n defaultMessage: 'Untitled',\n });\n },\n [document, formatMessage, schema]\n );\n\n React.useEffect(() => {\n if (error) {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(error),\n });\n }\n }, [toggleNotification, error, formatAPIError, args.collectionType]);\n\n const validationSchema = React.useMemo(() => {\n if (!schema) {\n return null;\n }\n\n return createYupSchema(schema.attributes, components);\n }, [schema, components]);\n\n const validate = React.useCallback(\n (document: Modules.Documents.AnyDocument): FormErrors | null => {\n if (!validationSchema) {\n throw new Error(\n 'There is no validation schema generated, this is likely due to the schema not being loaded yet.'\n );\n }\n\n try {\n validationSchema.validateSync(document, { abortEarly: false, strict: true });\n return null;\n } catch (error) {\n if (error instanceof ValidationError) {\n return getYupValidationErrors(error);\n }\n\n throw error;\n }\n },\n [validationSchema]\n );\n\n /**\n * Schema attributes that should be inherited from a sibling locale when\n * creating a new locale draft.\n *\n * Scope intentionally matches what the server populates into\n * `meta.availableLocales` (see `packages/core/content-manager/server/src/services/document-metadata.ts`):\n * - non-localized — `isLocalizedAttribute` semantics, so attributes whose\n * `pluginOptions.i18n.localized` is `undefined` count as non-localized\n * (an attribute created without the i18n plugin has no i18n options at\n * all but is still inherited at save by `copyNonLocalizedFields`).\n * - scalar or media — `component` / `dynamiczone` / `relation` are excluded\n * because the server doesn't populate them in `availableLocales` either,\n * so there'd be nothing to copy from.\n */\n const nonLocalizedScalarAndMediaFields = React.useMemo(() => {\n if (!schema?.attributes) {\n return [];\n }\n\n return Object.keys(schema.attributes).filter((name) => {\n const attribute = schema.attributes[name];\n\n if (isLocalizedAttribute(attribute)) {\n return false;\n }\n\n return (\n attribute.type !== 'component' &&\n attribute.type !== 'dynamiczone' &&\n attribute.type !== 'relation'\n );\n });\n }, [schema]);\n\n /**\n * Here we prepare the form for editing, we need to:\n * - remove prohibited fields from the document (passwords | ADD YOURS WHEN THERES A NEW ONE)\n * - swap out count objects on relations for empty arrays\n * - set __temp_key__ on array objects for drag & drop\n *\n * We also prepare the form for new documents, so we need to:\n * - set default values on fields\n * - inherit non-localized scalar/media values from a sibling locale.\n * Scope is intentionally limited to scalars and media — that is exactly\n * what the server populates into `meta.availableLocales` (see\n * `packages/core/content-manager/server/src/services/document-metadata.ts`).\n * Components, dynamic zones, and relations are not in that payload; the\n * server fills them at save time via `copyNonLocalizedFields` (in\n * `packages/core/core/src/services/document-service/internationalization.ts`)\n * when the new locale row is first created.\n * Baking the inheritance into `initialValues` here is what lets it survive\n * `<Form>` re-inits: the `SET_INITIAL_VALUES` effect in\n * `packages/core/admin/admin/src/components/Form.tsx` re-applies these\n * values whenever `initialValues` changes (e.g. after a locale switch),\n * which the previous side-effect-based prefill in `LocalePickerAction`\n * could not survive on revisits.\n */\n const getInitialFormValues = React.useCallback(\n (isCreatingDocument: boolean = false) => {\n if ((!document && !isCreatingDocument && !isSingleType) || !schema) {\n return undefined;\n }\n\n /**\n * Check that we have an ID so we know the\n * document has been created in some way.\n */\n if (document?.id) {\n return transformDocument(schema, components)(document);\n }\n\n let form: AnyData = createDefaultForm(schema, components);\n\n // Intentionally use `availableLocales[0]`:\n // - The server sorts `getAvailableLocales` with the default locale first\n // (see `document-metadata.ts`), so index 0 is the canonical inheritance\n // source. Sibling locales can drift on non-localized fields because the\n // server only syncs them at locale-creation time, not on subsequent\n // updates — preferring the default keeps the surfaced values stable.\n // - Avoids coupling this hook to `useGetLocalesQuery` just to find the\n // default locale.\n const sibling = meta?.availableLocales?.[0] as Record<string, unknown> | undefined;\n if (sibling && nonLocalizedScalarAndMediaFields.length > 0) {\n const inherited = nonLocalizedScalarAndMediaFields.reduce<AnyData>((acc, name) => {\n if (name in sibling) {\n acc[name] = sibling[name];\n }\n return acc;\n }, {});\n\n form = { ...form, ...inherited };\n }\n\n return transformDocument(schema, components)(form);\n },\n [\n document,\n isSingleType,\n schema,\n components,\n meta?.availableLocales,\n nonLocalizedScalarAndMediaFields,\n ]\n );\n\n const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;\n const hasError = !!error;\n\n return React.useMemo(\n () =>\n ({\n components,\n document,\n meta,\n isLoading,\n hasError,\n schema,\n schemas,\n validate,\n getTitle,\n getInitialFormValues,\n refetch,\n }) satisfies ReturnType<UseDocument>,\n [\n components,\n document,\n meta,\n isLoading,\n hasError,\n schema,\n schemas,\n validate,\n getTitle,\n getInitialFormValues,\n refetch,\n ]\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * useDoc\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @internal this hook uses the router to extract the model, collection type & id from the url.\n * therefore, it shouldn't be used outside of the content-manager because it won't work as intended.\n */\nconst useDoc = (opts?: UseDocumentOpts) => {\n const { id, slug, collectionType, origin } = useParams<{\n id: string;\n origin: string;\n slug: string;\n collectionType: string;\n }>();\n const [{ query }] = useQueryParams();\n const params = React.useMemo(() => buildValidParams(query), [query]);\n\n if (!collectionType) {\n throw new Error('Could not find collectionType in url params');\n }\n\n if (!slug) {\n throw new Error('Could not find model in url params');\n }\n\n const document = useDocument(\n { documentId: origin || id, model: slug, collectionType, params },\n {\n ...opts,\n skip: id === 'create' || (!origin && !id && collectionType !== SINGLE_TYPES) || opts?.skip,\n }\n );\n\n const returnId = origin || (id === 'create' ? undefined : id);\n\n return {\n collectionType,\n model: slug,\n id: returnId,\n ...document,\n };\n};\n\n/**\n * @public\n * @experimental\n * Content manager context hooks for plugin development.\n * Make sure to use this hook inside the content manager.\n */\nconst useContentManagerContext = () => {\n const {\n collectionType,\n model,\n id,\n components,\n isLoading: isLoadingDoc,\n schema,\n schemas,\n } = useDoc();\n\n const layout = useDocumentLayout(model);\n\n const form = useForm<unknown>('useContentManagerContext', (state) => state);\n\n const isSingleType = collectionType === SINGLE_TYPES;\n const slug = model;\n const isCreatingEntry = id === 'create';\n\n const {} = useContentTypeSchema();\n\n const isLoading = isLoadingDoc || layout.isLoading;\n const error = layout.error;\n\n return {\n error,\n isLoading,\n\n // Base metadata\n model,\n collectionType,\n id,\n slug,\n isCreatingEntry,\n isSingleType,\n hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,\n\n // All schema infos\n components,\n contentType: schema,\n contentTypes: schemas,\n\n // Form state\n form,\n\n // layout infos\n layout,\n };\n};\n\nexport { useDocument, useDoc, useContentManagerContext };\nexport type { UseDocument, UseDocumentArgs, Document, Schema, ComponentsDictionary };\n"],"names":["isLocalizedAttribute","attribute","i18nOptions","pluginOptions","i18n","localized","useDocument","args","opts","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","formatMessage","useIntl","currentData","data","isLoading","isLoadingDocument","isFetching","isFetchingDocument","error","refetch","useGetDocumentQuery","skip","documentId","collectionType","SINGLE_TYPES","document","meta","components","schema","schemas","isLoadingSchema","useContentTypeSchema","model","isSingleType","kind","getTitle","React","useCallback","mainField","info","displayName","id","defaultMessage","useEffect","type","message","validationSchema","useMemo","createYupSchema","attributes","validate","Error","validateSync","abortEarly","strict","ValidationError","getYupValidationErrors","nonLocalizedScalarAndMediaFields","Object","keys","filter","name","getInitialFormValues","isCreatingDocument","undefined","transformDocument","form","createDefaultForm","sibling","availableLocales","length","inherited","reduce","acc","hasError","useDoc","slug","origin","useParams","query","useQueryParams","params","buildValidParams","returnId","useContentManagerContext","isLoadingDoc","layout","useDocumentLayout","useForm","state","isCreatingEntry","hasDraftAndPublish","options","draftAndPublish","contentType","contentTypes"],"mappings":"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"}
|
|
@@ -47,9 +47,10 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
47
47
|
* EditViewPage
|
|
48
48
|
* -----------------------------------------------------------------------------------------------*/ const EditViewPage = ()=>{
|
|
49
49
|
const location = reactRouterDom.useLocation();
|
|
50
|
-
const [{ query: { status } }, setQuery] = strapiAdmin.useQueryParams({
|
|
50
|
+
const [{ query: { status, plugins } }, setQuery] = strapiAdmin.useQueryParams({
|
|
51
51
|
status: 'draft'
|
|
52
52
|
});
|
|
53
|
+
const activeLocale = plugins?.i18n?.locale;
|
|
53
54
|
const { formatMessage } = reactIntl.useIntl();
|
|
54
55
|
const { toggleNotification } = strapiAdmin.useNotification();
|
|
55
56
|
const isDesktop = strapiAdmin.useIsDesktop();
|
|
@@ -261,7 +262,7 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
261
262
|
/*#__PURE__*/ jsxRuntime.jsx(Blocker.Blocker, {})
|
|
262
263
|
]
|
|
263
264
|
})
|
|
264
|
-
})
|
|
265
|
+
}, `${collectionType}:${model}:${id ?? 'create'}:${activeLocale ?? 'default'}`)
|
|
265
266
|
]
|
|
266
267
|
});
|
|
267
268
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditViewPage.js","sources":["../../../../admin/src/pages/EditView/EditViewPage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Page,\n Form,\n useRBAC,\n useNotification,\n useQueryParams,\n tours,\n Layouts,\n useIsDesktop,\n useIsMobile,\n} from '@strapi/admin/strapi-admin';\nimport { Grid, Tabs, Box } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { useLocation, useParams } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { ActionsDrawer } from '../../components/ActionsDrawer';\nimport { SINGLE_TYPES } from '../../constants/collections';\nimport { PERMISSIONS } from '../../constants/plugin';\nimport { DocumentRBAC, useDocumentRBAC } from '../../features/DocumentRBAC';\nimport { useDoc, type UseDocument } from '../../hooks/useDocument';\nimport { useDocumentLayout } from '../../hooks/useDocumentLayout';\nimport { useLazyComponents } from '../../hooks/useLazyComponents';\nimport { useOnce } from '../../hooks/useOnce';\nimport {\n PersistentQueryConfig,\n usePersistentPartialQueryParams,\n} from '../../hooks/usePersistentQueryParams';\nimport { getTranslation } from '../../utils/translations';\nimport { createYupSchema } from '../../utils/validation';\n\nimport { Blocker } from './components/Blocker';\nimport { FormLayout } from './components/FormLayout';\nimport { Header } from './components/Header';\nimport { Panels, PanelsProvider, usePanelsContext, ActionsPanelContent } from './components/Panels';\nimport { handleInvisibleAttributes } from './utils/data';\n\n/* -------------------------------------------------------------------------------------------------\n * EditViewPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst EditViewPage = () => {\n const location = useLocation();\n const [\n {\n query: { status },\n },\n setQuery,\n ] = useQueryParams<{ status: 'draft' | 'published' }>({\n status: 'draft',\n });\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const isDesktop = useIsDesktop();\n const isMobile = useIsMobile();\n const visiblePanels = usePanelsContext('Panels', (s) => s.visiblePanels);\n const drawerHasContent = visiblePanels.length > 0;\n\n const persistentQueryConfigs: PersistentQueryConfig = React.useMemo(\n () => ({\n STRAPI_LOCALE: {\n paths: ['plugins.i18n.locale'],\n scoped: false,\n },\n }),\n []\n );\n\n const { isHydrated } = usePersistentPartialQueryParams(persistentQueryConfigs);\n\n const doc = useDoc({ skip: !isHydrated });\n const {\n document,\n meta,\n isLoading: isLoadingDocument,\n schema,\n components,\n collectionType,\n id,\n model,\n hasError,\n getTitle,\n getInitialFormValues,\n } = doc;\n\n const hasDraftAndPublished = schema?.options?.draftAndPublish ?? false;\n\n useOnce(() => {\n /**\n * We only ever want to fire the notification once otherwise\n * whenever the app re-renders it'll pop up regardless of\n * what we do because the state comes from react-router-dom\n */\n if (location?.state && 'error' in location.state) {\n toggleNotification({\n type: 'danger',\n message: location.state.error,\n timeout: 5000,\n });\n }\n });\n\n const isLoadingActionsRBAC = useDocumentRBAC('EditViewPage', (state) => state.isLoading);\n\n const isSingleType = collectionType === SINGLE_TYPES;\n\n /**\n * single-types don't current have an id, but because they're a singleton\n * we can simply use the update operation to continuously update the same\n * document with varying params.\n */\n const isCreatingDocument = !id && !isSingleType;\n\n const {\n isLoading: isLoadingLayout,\n edit: {\n layout,\n settings: { mainField },\n },\n } = useDocumentLayout(model);\n const pageTitle = getTitle(mainField);\n\n const { isLazyLoading } = useLazyComponents([]);\n\n const isLoading =\n !isHydrated || isLoadingActionsRBAC || isLoadingDocument || isLoadingLayout || isLazyLoading;\n\n const initialValues = getInitialFormValues(isCreatingDocument);\n\n if (isLoading && !document?.documentId) {\n return <Page.Loading />;\n }\n\n if (!initialValues || hasError) {\n return <Page.Error />;\n }\n\n const handleTabChange = (status: string) => {\n if (status === 'published' || status === 'draft') {\n setQuery({ status }, 'push', true);\n }\n };\n\n const validateSync = (values: Record<string, unknown>, options: Record<string, string>) => {\n const yupSchema = createYupSchema(schema?.attributes, components, {\n status,\n ...options,\n });\n\n return yupSchema.validateSync(values, { abortEarly: false });\n };\n\n return (\n <Page.Main>\n <Page.Title>{pageTitle}</Page.Title>\n {isSingleType && (\n <tours.contentManager.Introduction>\n {/* Invisible Anchor */}\n <Box />\n </tours.contentManager.Introduction>\n )}\n <Form\n disabled={hasDraftAndPublished && status === 'published'}\n initialValues={initialValues}\n method={isCreatingDocument ? 'POST' : 'PUT'}\n validate={(values: Record<string, unknown>, options: Record<string, string>) => {\n // removes hidden fields from the validation\n // this is necessary because the yup schema doesn't know about the visibility conditions\n // and we don't want to validate fields that are not visible\n const { data: cleanedValues, removedAttributes } = handleInvisibleAttributes(values, {\n schema,\n initialValues,\n components,\n });\n\n const yupSchema = createYupSchema(schema?.attributes, components, {\n status,\n removedAttributes,\n ...options,\n });\n\n return yupSchema.validate(cleanedValues, { abortEarly: false });\n }}\n initialErrors={location?.state?.forceValidation ? validateSync(initialValues, {}) : {}}\n >\n <>\n <Header\n isCreating={isCreatingDocument}\n status={hasDraftAndPublished ? getDocumentStatus(document, meta) : undefined}\n title={pageTitle}\n />\n <Layouts.Content>\n <Tabs.Root variant=\"simple\" value={status} onValueChange={handleTabChange}>\n <Tabs.List\n aria-label={formatMessage({\n id: getTranslation('containers.edit.tabs.label'),\n defaultMessage: 'Document status',\n })}\n >\n {hasDraftAndPublished ? (\n <>\n <StatusTab value=\"draft\">\n {formatMessage({\n id: getTranslation('containers.edit.tabs.draft'),\n defaultMessage: 'draft',\n })}\n </StatusTab>\n <StatusTab\n disabled={!meta || meta.availableStatus.length === 0}\n value=\"published\"\n >\n {formatMessage({\n id: getTranslation('containers.edit.tabs.published'),\n defaultMessage: 'published',\n })}\n </StatusTab>\n </>\n ) : null}\n </Tabs.List>\n <Grid.Root\n paddingTop={{\n initial: 6,\n medium: 4,\n large: 8,\n }}\n gap={4}\n >\n <Grid.Item col={9} xs={12} direction=\"column\" alignItems=\"stretch\">\n <Tabs.Content value=\"draft\">\n <tours.contentManager.Fields>\n <Box />\n </tours.contentManager.Fields>\n <FormLayout layout={layout} document={doc} hasBackground={!isMobile} />\n </Tabs.Content>\n <Tabs.Content value=\"published\">\n <FormLayout layout={layout} document={doc} hasBackground={!isMobile} />\n </Tabs.Content>\n </Grid.Item>\n {isDesktop && (\n <Grid.Item col={3} direction=\"column\" alignItems=\"stretch\">\n <Panels />\n </Grid.Item>\n )}\n </Grid.Root>\n </Tabs.Root>\n {!isDesktop && (\n <>\n <ActionsDrawer.Root hasContent={drawerHasContent} hasSideNav>\n <ActionsDrawer.Overlay />\n <ActionsDrawer.Header>\n <ActionsPanelContent />\n </ActionsDrawer.Header>\n <ActionsDrawer.Content>\n <Panels withActions={false} />\n </ActionsDrawer.Content>\n </ActionsDrawer.Root>\n {/* Adding a fixed height to the bottom of the page to prevent \n the actions drawer from covering the content\n (40px button + 12px * 2 padding + 1px border) */}\n <Box height=\"6.5rem\" />\n </>\n )}\n </Layouts.Content>\n <Blocker />\n </>\n </Form>\n </Page.Main>\n );\n};\n\nconst StatusTab = styled(Tabs.Trigger)`\n text-transform: uppercase;\n`;\n\n/**\n * @internal\n * @description Returns the status of the document where its latest state takes priority,\n * this typically will be \"published\" unless a user has edited their draft in which we should\n * display \"modified\".\n */\nconst getDocumentStatus = (\n document: ReturnType<UseDocument>['document'],\n meta: ReturnType<UseDocument>['meta']\n): 'draft' | 'published' | 'modified' => {\n const docStatus = document?.status;\n const statuses = meta?.availableStatus ?? [];\n\n /**\n * Creating an entry\n */\n if (!docStatus) {\n return 'draft';\n }\n\n /**\n * We're viewing a draft, but the document could have a published version\n */\n if (docStatus === 'draft' && statuses.find((doc) => doc.publishedAt !== null)) {\n return 'published';\n }\n\n return docStatus;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ProtectedEditViewPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst ProtectedEditViewPage = () => {\n const { slug = '' } = useParams<{\n slug: string;\n }>();\n const {\n permissions = [],\n isLoading,\n error,\n } = useRBAC(\n PERMISSIONS.map((action) => ({\n action,\n subject: slug,\n }))\n );\n\n if (isLoading) {\n return <Page.Loading />;\n }\n\n if (error || !slug) {\n return <Page.Error />;\n }\n\n return (\n <Page.Protect permissions={permissions}>\n {({ permissions }) => (\n <DocumentRBAC permissions={permissions}>\n <PanelsProvider>\n <EditViewPage />\n </PanelsProvider>\n </DocumentRBAC>\n )}\n </Page.Protect>\n );\n};\n\nexport { EditViewPage, ProtectedEditViewPage, getDocumentStatus };\n"],"names":["EditViewPage","location","useLocation","query","status","setQuery","useQueryParams","formatMessage","useIntl","toggleNotification","useNotification","isDesktop","useIsDesktop","isMobile","useIsMobile","visiblePanels","usePanelsContext","s","drawerHasContent","length","persistentQueryConfigs","React","useMemo","STRAPI_LOCALE","paths","scoped","isHydrated","usePersistentPartialQueryParams","doc","useDoc","skip","document","meta","isLoading","isLoadingDocument","schema","components","collectionType","id","model","hasError","getTitle","getInitialFormValues","hasDraftAndPublished","options","draftAndPublish","useOnce","state","type","message","error","timeout","isLoadingActionsRBAC","useDocumentRBAC","isSingleType","SINGLE_TYPES","isCreatingDocument","isLoadingLayout","edit","layout","settings","mainField","useDocumentLayout","pageTitle","isLazyLoading","useLazyComponents","initialValues","documentId","_jsx","Page","Loading","Error","handleTabChange","validateSync","values","yupSchema","createYupSchema","attributes","abortEarly","_jsxs","Main","Title","tours","contentManager","Introduction","Box","Form","disabled","method","validate","data","cleanedValues","removedAttributes","handleInvisibleAttributes","initialErrors","forceValidation","_Fragment","Header","isCreating","getDocumentStatus","undefined","title","Layouts","Content","Tabs","Root","variant","value","onValueChange","List","aria-label","getTranslation","defaultMessage","StatusTab","availableStatus","Grid","paddingTop","initial","medium","large","gap","Item","col","xs","direction","alignItems","Fields","FormLayout","hasBackground","Panels","ActionsDrawer","hasContent","hasSideNav","Overlay","ActionsPanelContent","withActions","height","Blocker","styled","Trigger","docStatus","statuses","find","publishedAt","ProtectedEditViewPage","slug","useParams","permissions","useRBAC","PERMISSIONS","map","action","subject","Protect","DocumentRBAC","PanelsProvider"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EditViewPage.js","sources":["../../../../admin/src/pages/EditView/EditViewPage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Page,\n Form,\n useRBAC,\n useNotification,\n useQueryParams,\n tours,\n Layouts,\n useIsDesktop,\n useIsMobile,\n} from '@strapi/admin/strapi-admin';\nimport { Grid, Tabs, Box } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { useLocation, useParams } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { ActionsDrawer } from '../../components/ActionsDrawer';\nimport { SINGLE_TYPES } from '../../constants/collections';\nimport { PERMISSIONS } from '../../constants/plugin';\nimport { DocumentRBAC, useDocumentRBAC } from '../../features/DocumentRBAC';\nimport { useDoc, type UseDocument } from '../../hooks/useDocument';\nimport { useDocumentLayout } from '../../hooks/useDocumentLayout';\nimport { useLazyComponents } from '../../hooks/useLazyComponents';\nimport { useOnce } from '../../hooks/useOnce';\nimport {\n PersistentQueryConfig,\n usePersistentPartialQueryParams,\n} from '../../hooks/usePersistentQueryParams';\nimport { getTranslation } from '../../utils/translations';\nimport { createYupSchema } from '../../utils/validation';\n\nimport { Blocker } from './components/Blocker';\nimport { FormLayout } from './components/FormLayout';\nimport { Header } from './components/Header';\nimport { Panels, PanelsProvider, usePanelsContext, ActionsPanelContent } from './components/Panels';\nimport { handleInvisibleAttributes } from './utils/data';\n\n/* -------------------------------------------------------------------------------------------------\n * EditViewPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst EditViewPage = () => {\n const location = useLocation();\n const [\n {\n query: { status, plugins },\n },\n setQuery,\n ] = useQueryParams<{\n status: 'draft' | 'published';\n plugins?: { i18n?: { locale?: string } };\n }>({\n status: 'draft',\n });\n\n const activeLocale = plugins?.i18n?.locale;\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const isDesktop = useIsDesktop();\n const isMobile = useIsMobile();\n const visiblePanels = usePanelsContext('Panels', (s) => s.visiblePanels);\n const drawerHasContent = visiblePanels.length > 0;\n\n const persistentQueryConfigs: PersistentQueryConfig = React.useMemo(\n () => ({\n STRAPI_LOCALE: {\n paths: ['plugins.i18n.locale'],\n scoped: false,\n },\n }),\n []\n );\n\n const { isHydrated } = usePersistentPartialQueryParams(persistentQueryConfigs);\n\n const doc = useDoc({ skip: !isHydrated });\n const {\n document,\n meta,\n isLoading: isLoadingDocument,\n schema,\n components,\n collectionType,\n id,\n model,\n hasError,\n getTitle,\n getInitialFormValues,\n } = doc;\n\n const hasDraftAndPublished = schema?.options?.draftAndPublish ?? false;\n\n useOnce(() => {\n /**\n * We only ever want to fire the notification once otherwise\n * whenever the app re-renders it'll pop up regardless of\n * what we do because the state comes from react-router-dom\n */\n if (location?.state && 'error' in location.state) {\n toggleNotification({\n type: 'danger',\n message: location.state.error,\n timeout: 5000,\n });\n }\n });\n\n const isLoadingActionsRBAC = useDocumentRBAC('EditViewPage', (state) => state.isLoading);\n\n const isSingleType = collectionType === SINGLE_TYPES;\n\n /**\n * single-types don't current have an id, but because they're a singleton\n * we can simply use the update operation to continuously update the same\n * document with varying params.\n */\n const isCreatingDocument = !id && !isSingleType;\n\n const {\n isLoading: isLoadingLayout,\n edit: {\n layout,\n settings: { mainField },\n },\n } = useDocumentLayout(model);\n const pageTitle = getTitle(mainField);\n\n const { isLazyLoading } = useLazyComponents([]);\n\n const isLoading =\n !isHydrated || isLoadingActionsRBAC || isLoadingDocument || isLoadingLayout || isLazyLoading;\n\n const initialValues = getInitialFormValues(isCreatingDocument);\n\n if (isLoading && !document?.documentId) {\n return <Page.Loading />;\n }\n\n if (!initialValues || hasError) {\n return <Page.Error />;\n }\n\n const handleTabChange = (status: string) => {\n if (status === 'published' || status === 'draft') {\n setQuery({ status }, 'push', true);\n }\n };\n\n const validateSync = (values: Record<string, unknown>, options: Record<string, string>) => {\n const yupSchema = createYupSchema(schema?.attributes, components, {\n status,\n ...options,\n });\n\n return yupSchema.validateSync(values, { abortEarly: false });\n };\n\n return (\n <Page.Main>\n <Page.Title>{pageTitle}</Page.Title>\n {isSingleType && (\n <tours.contentManager.Introduction>\n {/* Invisible Anchor */}\n <Box />\n </tours.contentManager.Introduction>\n )}\n <Form\n key={`${collectionType}:${model}:${id ?? 'create'}:${activeLocale ?? 'default'}`}\n disabled={hasDraftAndPublished && status === 'published'}\n initialValues={initialValues}\n method={isCreatingDocument ? 'POST' : 'PUT'}\n validate={(values: Record<string, unknown>, options: Record<string, string>) => {\n // removes hidden fields from the validation\n // this is necessary because the yup schema doesn't know about the visibility conditions\n // and we don't want to validate fields that are not visible\n const { data: cleanedValues, removedAttributes } = handleInvisibleAttributes(values, {\n schema,\n initialValues,\n components,\n });\n\n const yupSchema = createYupSchema(schema?.attributes, components, {\n status,\n removedAttributes,\n ...options,\n });\n\n return yupSchema.validate(cleanedValues, { abortEarly: false });\n }}\n initialErrors={location?.state?.forceValidation ? validateSync(initialValues, {}) : {}}\n >\n <>\n <Header\n isCreating={isCreatingDocument}\n status={hasDraftAndPublished ? getDocumentStatus(document, meta) : undefined}\n title={pageTitle}\n />\n <Layouts.Content>\n <Tabs.Root variant=\"simple\" value={status} onValueChange={handleTabChange}>\n <Tabs.List\n aria-label={formatMessage({\n id: getTranslation('containers.edit.tabs.label'),\n defaultMessage: 'Document status',\n })}\n >\n {hasDraftAndPublished ? (\n <>\n <StatusTab value=\"draft\">\n {formatMessage({\n id: getTranslation('containers.edit.tabs.draft'),\n defaultMessage: 'draft',\n })}\n </StatusTab>\n <StatusTab\n disabled={!meta || meta.availableStatus.length === 0}\n value=\"published\"\n >\n {formatMessage({\n id: getTranslation('containers.edit.tabs.published'),\n defaultMessage: 'published',\n })}\n </StatusTab>\n </>\n ) : null}\n </Tabs.List>\n <Grid.Root\n paddingTop={{\n initial: 6,\n medium: 4,\n large: 8,\n }}\n gap={4}\n >\n <Grid.Item col={9} xs={12} direction=\"column\" alignItems=\"stretch\">\n <Tabs.Content value=\"draft\">\n <tours.contentManager.Fields>\n <Box />\n </tours.contentManager.Fields>\n <FormLayout layout={layout} document={doc} hasBackground={!isMobile} />\n </Tabs.Content>\n <Tabs.Content value=\"published\">\n <FormLayout layout={layout} document={doc} hasBackground={!isMobile} />\n </Tabs.Content>\n </Grid.Item>\n {isDesktop && (\n <Grid.Item col={3} direction=\"column\" alignItems=\"stretch\">\n <Panels />\n </Grid.Item>\n )}\n </Grid.Root>\n </Tabs.Root>\n {!isDesktop && (\n <>\n <ActionsDrawer.Root hasContent={drawerHasContent} hasSideNav>\n <ActionsDrawer.Overlay />\n <ActionsDrawer.Header>\n <ActionsPanelContent />\n </ActionsDrawer.Header>\n <ActionsDrawer.Content>\n <Panels withActions={false} />\n </ActionsDrawer.Content>\n </ActionsDrawer.Root>\n {/* Adding a fixed height to the bottom of the page to prevent \n the actions drawer from covering the content\n (40px button + 12px * 2 padding + 1px border) */}\n <Box height=\"6.5rem\" />\n </>\n )}\n </Layouts.Content>\n <Blocker />\n </>\n </Form>\n </Page.Main>\n );\n};\n\nconst StatusTab = styled(Tabs.Trigger)`\n text-transform: uppercase;\n`;\n\n/**\n * @internal\n * @description Returns the status of the document where its latest state takes priority,\n * this typically will be \"published\" unless a user has edited their draft in which we should\n * display \"modified\".\n */\nconst getDocumentStatus = (\n document: ReturnType<UseDocument>['document'],\n meta: ReturnType<UseDocument>['meta']\n): 'draft' | 'published' | 'modified' => {\n const docStatus = document?.status;\n const statuses = meta?.availableStatus ?? [];\n\n /**\n * Creating an entry\n */\n if (!docStatus) {\n return 'draft';\n }\n\n /**\n * We're viewing a draft, but the document could have a published version\n */\n if (docStatus === 'draft' && statuses.find((doc) => doc.publishedAt !== null)) {\n return 'published';\n }\n\n return docStatus;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ProtectedEditViewPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst ProtectedEditViewPage = () => {\n const { slug = '' } = useParams<{\n slug: string;\n }>();\n const {\n permissions = [],\n isLoading,\n error,\n } = useRBAC(\n PERMISSIONS.map((action) => ({\n action,\n subject: slug,\n }))\n );\n\n if (isLoading) {\n return <Page.Loading />;\n }\n\n if (error || !slug) {\n return <Page.Error />;\n }\n\n return (\n <Page.Protect permissions={permissions}>\n {({ permissions }) => (\n <DocumentRBAC permissions={permissions}>\n <PanelsProvider>\n <EditViewPage />\n </PanelsProvider>\n </DocumentRBAC>\n )}\n </Page.Protect>\n );\n};\n\nexport { EditViewPage, ProtectedEditViewPage, getDocumentStatus };\n"],"names":["EditViewPage","location","useLocation","query","status","plugins","setQuery","useQueryParams","activeLocale","i18n","locale","formatMessage","useIntl","toggleNotification","useNotification","isDesktop","useIsDesktop","isMobile","useIsMobile","visiblePanels","usePanelsContext","s","drawerHasContent","length","persistentQueryConfigs","React","useMemo","STRAPI_LOCALE","paths","scoped","isHydrated","usePersistentPartialQueryParams","doc","useDoc","skip","document","meta","isLoading","isLoadingDocument","schema","components","collectionType","id","model","hasError","getTitle","getInitialFormValues","hasDraftAndPublished","options","draftAndPublish","useOnce","state","type","message","error","timeout","isLoadingActionsRBAC","useDocumentRBAC","isSingleType","SINGLE_TYPES","isCreatingDocument","isLoadingLayout","edit","layout","settings","mainField","useDocumentLayout","pageTitle","isLazyLoading","useLazyComponents","initialValues","documentId","_jsx","Page","Loading","Error","handleTabChange","validateSync","values","yupSchema","createYupSchema","attributes","abortEarly","_jsxs","Main","Title","tours","contentManager","Introduction","Box","Form","disabled","method","validate","data","cleanedValues","removedAttributes","handleInvisibleAttributes","initialErrors","forceValidation","_Fragment","Header","isCreating","getDocumentStatus","undefined","title","Layouts","Content","Tabs","Root","variant","value","onValueChange","List","aria-label","getTranslation","defaultMessage","StatusTab","availableStatus","Grid","paddingTop","initial","medium","large","gap","Item","col","xs","direction","alignItems","Fields","FormLayout","hasBackground","Panels","ActionsDrawer","hasContent","hasSideNav","Overlay","ActionsPanelContent","withActions","height","Blocker","styled","Trigger","docStatus","statuses","find","publishedAt","ProtectedEditViewPage","slug","useParams","permissions","useRBAC","PERMISSIONS","map","action","subject","Protect","DocumentRBAC","PanelsProvider"],"mappings":"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"}
|
|
@@ -26,9 +26,10 @@ import { handleInvisibleAttributes } from './utils/data.mjs';
|
|
|
26
26
|
* EditViewPage
|
|
27
27
|
* -----------------------------------------------------------------------------------------------*/ const EditViewPage = ()=>{
|
|
28
28
|
const location = useLocation();
|
|
29
|
-
const [{ query: { status } }, setQuery] = useQueryParams({
|
|
29
|
+
const [{ query: { status, plugins } }, setQuery] = useQueryParams({
|
|
30
30
|
status: 'draft'
|
|
31
31
|
});
|
|
32
|
+
const activeLocale = plugins?.i18n?.locale;
|
|
32
33
|
const { formatMessage } = useIntl();
|
|
33
34
|
const { toggleNotification } = useNotification();
|
|
34
35
|
const isDesktop = useIsDesktop();
|
|
@@ -240,7 +241,7 @@ import { handleInvisibleAttributes } from './utils/data.mjs';
|
|
|
240
241
|
/*#__PURE__*/ jsx(Blocker, {})
|
|
241
242
|
]
|
|
242
243
|
})
|
|
243
|
-
})
|
|
244
|
+
}, `${collectionType}:${model}:${id ?? 'create'}:${activeLocale ?? 'default'}`)
|
|
244
245
|
]
|
|
245
246
|
});
|
|
246
247
|
};
|