@strapi/content-manager 5.48.0 → 5.48.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/features/DocumentRBAC.js +9 -1
- package/dist/admin/features/DocumentRBAC.js.map +1 -1
- package/dist/admin/features/DocumentRBAC.mjs +9 -1
- package/dist/admin/features/DocumentRBAC.mjs.map +1 -1
- package/dist/admin/hooks/useContentTypeSchema.js +37 -17
- package/dist/admin/hooks/useContentTypeSchema.js.map +1 -1
- package/dist/admin/hooks/useContentTypeSchema.mjs +37 -17
- package/dist/admin/hooks/useContentTypeSchema.mjs.map +1 -1
- package/dist/admin/hooks/useDocumentLayout.js +43 -4
- package/dist/admin/hooks/useDocumentLayout.js.map +1 -1
- package/dist/admin/hooks/useDocumentLayout.mjs +43 -4
- package/dist/admin/hooks/useDocumentLayout.mjs.map +1 -1
- package/dist/admin/pages/ComponentConfigurationPage.js +6 -3
- package/dist/admin/pages/ComponentConfigurationPage.js.map +1 -1
- package/dist/admin/pages/ComponentConfigurationPage.mjs +6 -3
- package/dist/admin/pages/ComponentConfigurationPage.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js +5 -2
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs +5 -2
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js +11 -2
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs +11 -2
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js +9 -4
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs +9 -4
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.js +2 -26
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.mjs +2 -26
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.js +72 -0
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.js.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.mjs +70 -0
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.mjs.map +1 -0
- package/dist/admin/pages/ListConfiguration/ListConfigurationPage.js +4 -8
- package/dist/admin/pages/ListConfiguration/ListConfigurationPage.js.map +1 -1
- package/dist/admin/pages/ListConfiguration/ListConfigurationPage.mjs +5 -9
- package/dist/admin/pages/ListConfiguration/ListConfigurationPage.mjs.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.js +6 -10
- package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.js.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.mjs +6 -10
- package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/Filters.js +7 -9
- package/dist/admin/pages/ListView/components/Filters.js.map +1 -1
- package/dist/admin/pages/ListView/components/Filters.mjs +7 -9
- package/dist/admin/pages/ListView/components/Filters.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/TableCells/Media.js +5 -4
- package/dist/admin/pages/ListView/components/TableCells/Media.js.map +1 -1
- package/dist/admin/pages/ListView/components/TableCells/Media.mjs +5 -4
- package/dist/admin/pages/ListView/components/TableCells/Media.mjs.map +1 -1
- package/dist/admin/pages/formatComponentConfigurationEditLayout.js +15 -9
- package/dist/admin/pages/formatComponentConfigurationEditLayout.js.map +1 -1
- package/dist/admin/pages/formatComponentConfigurationEditLayout.mjs +15 -9
- package/dist/admin/pages/formatComponentConfigurationEditLayout.mjs.map +1 -1
- package/dist/admin/services/components.js +3 -2
- package/dist/admin/services/components.js.map +1 -1
- package/dist/admin/services/components.mjs +3 -2
- package/dist/admin/services/components.mjs.map +1 -1
- package/dist/admin/services/contentTypes.js +4 -3
- package/dist/admin/services/contentTypes.js.map +1 -1
- package/dist/admin/services/contentTypes.mjs +4 -3
- package/dist/admin/services/contentTypes.mjs.map +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.d.ts +2 -0
- package/dist/admin/src/pages/ListConfiguration/components/SortDisplayedFields.d.ts +2 -2
- package/dist/admin/src/pages/ListView/components/TableCells/Media.d.ts +2 -2
- package/dist/admin/src/pages/formatComponentConfigurationEditLayout.d.ts +3 -1
- package/dist/admin/src/utils/layouts/normalizeContentManagerLayout.d.ts +24 -0
- package/dist/admin/translations/en.json.js +1 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +1 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/admin/utils/attributes.js +17 -2
- package/dist/admin/utils/attributes.js.map +1 -1
- package/dist/admin/utils/attributes.mjs +17 -2
- package/dist/admin/utils/attributes.mjs.map +1 -1
- package/dist/admin/utils/layouts/normalizeContentManagerLayout.js +329 -0
- package/dist/admin/utils/layouts/normalizeContentManagerLayout.js.map +1 -0
- package/dist/admin/utils/layouts/normalizeContentManagerLayout.mjs +321 -0
- package/dist/admin/utils/layouts/normalizeContentManagerLayout.mjs.map +1 -0
- package/dist/server/controllers/collection-types.js +7 -2
- package/dist/server/controllers/collection-types.js.map +1 -1
- package/dist/server/controllers/collection-types.mjs +7 -2
- package/dist/server/controllers/collection-types.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Field.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n createContext,\n InputProps,\n useField,\n useForm,\n useNotification,\n} from '@strapi/admin/strapi-admin';\nimport { Box, Flex, VisuallyHidden } from '@strapi/design-system';\nimport pipe from 'lodash/fp/pipe';\nimport { useIntl } from 'react-intl';\n\nimport { useDocumentContext } from '../../../../../hooks/useDocumentContext';\nimport { type EditFieldLayout } from '../../../../../hooks/useDocumentLayout';\nimport { usePrev } from '../../../../../hooks/usePrev';\nimport { getTranslation } from '../../../../../utils/translations';\nimport { transformDocument } from '../../../utils/data';\nimport { createDefaultForm } from '../../../utils/forms';\nimport { ComponentProvider, useComponent } from '../ComponentContext';\n\nimport { AddComponentButton } from './AddComponentButton';\nimport { ComponentPicker } from './ComponentPicker';\nimport { DynamicComponent, DynamicComponentProps } from './DynamicComponent';\nimport { DynamicZoneLabel, DynamicZoneLabelProps } from './DynamicZoneLabel';\n\nimport type { InputRendererProps } from '../../InputRenderer';\nimport type { Schema } from '@strapi/types';\n\ninterface DynamicZoneContextValue {\n isInDynamicZone: boolean;\n}\n\nconst [DynamicZoneProvider, useDynamicZone] = createContext<DynamicZoneContextValue>(\n 'DynamicZone',\n {\n isInDynamicZone: false,\n }\n);\n\ninterface DynamicZoneProps\n extends Omit<Extract<EditFieldLayout, { type: 'dynamiczone' }>, 'size' | 'hint'>,\n Pick<InputProps, 'hint'>,\n Pick<DynamicZoneLabelProps, 'labelAction'> {\n children?: (props: InputRendererProps) => React.ReactNode;\n}\n\nconst DynamicZone = ({\n attribute,\n disabled: disabledProp,\n hint,\n label,\n labelAction,\n name,\n required = false,\n children,\n}: DynamicZoneProps) => {\n // We cannot use the default props here\n const { max = Infinity, min = -Infinity } = attribute ?? {};\n\n const [addComponentIsOpen, setAddComponentIsOpen] = React.useState(false);\n const [liveText, setLiveText] = React.useState('');\n const [openComponentKey, setOpenComponentKey] = React.useState<string | null>(null);\n\n const {\n currentDocument: { components, isLoading },\n } = useDocumentContext('DynamicZone');\n\n const disabled = disabledProp || isLoading;\n const addFieldRow = useForm('DynamicZone', (state) => state.addFieldRow);\n const removeFieldRow = useForm('DynamicZone', (state) => state.removeFieldRow);\n const moveFieldRow = useForm('DynamicZone', (state) => state.moveFieldRow);\n\n type DzWithTempKey =\n Schema.Attribute.GetDynamicZoneValue<Schema.Attribute.DynamicZone>[number] & {\n __temp_key__: string;\n };\n\n const { value = [], error } = useField<Array<DzWithTempKey>>(name);\n\n /**\n * Track the previous value array to detect when a new component is added.\n * When the array grows, we find the newly added item and force its accordion open.\n * This mirrors the same pattern used in RepeatableComponent.\n */\n const prevValue = usePrev(value);\n\n React.useEffect(() => {\n if (prevValue && prevValue.length < value.length) {\n const prevKeys = new Set(prevValue.map((v) => v.__temp_key__));\n const newItem = value.find((v) => !prevKeys.has(v.__temp_key__));\n if (newItem) {\n setOpenComponentKey(newItem.__temp_key__);\n }\n } else if (openComponentKey !== null) {\n // Component was removed before forceOpen was handled — clear stale key\n const currentKeys = new Set(value.map((v) => v.__temp_key__));\n if (!currentKeys.has(openComponentKey)) {\n setOpenComponentKey(null);\n }\n }\n }, [value, prevValue, openComponentKey]);\n\n const handleForceOpenHandled = React.useCallback(() => {\n setOpenComponentKey(null);\n }, []);\n\n const dynamicComponentsByCategory = React.useMemo(() => {\n return attribute.components.reduce<\n NonNullable<DynamicComponentProps['dynamicComponentsByCategory']>\n >((acc, componentUid) => {\n const { category, info } = components[componentUid] ?? { info: {} };\n\n const component = { uid: componentUid, displayName: info.displayName, icon: info.icon };\n\n if (!acc[category]) {\n acc[category] = [];\n }\n\n acc[category] = [...acc[category], component];\n\n return acc;\n }, {});\n }, [attribute.components, components]);\n\n const { formatMessage } = useIntl();\n\n const { toggleNotification } = useNotification();\n\n const dynamicDisplayedComponentsLength = value.length;\n\n const handleAddComponent = React.useCallback(\n (uid: string, position?: number) => {\n setAddComponentIsOpen(false);\n\n const schema = components[uid];\n const form = createDefaultForm(schema, components);\n const transformations = pipe(transformDocument(schema, components), (data) => ({\n ...data,\n __component: uid,\n }));\n\n const data = transformations(form);\n\n addFieldRow(name, data, position);\n },\n [addFieldRow, components, name]\n );\n\n const handleClickOpenPicker = () => {\n if (dynamicDisplayedComponentsLength < max) {\n setAddComponentIsOpen((prev) => !prev);\n } else {\n toggleNotification({\n type: 'info',\n message: formatMessage({\n id: getTranslation('components.notification.info.maximum-requirement'),\n }),\n });\n }\n };\n\n const handleMoveComponent = React.useCallback(\n (newIndex: number, currentIndex: number) => {\n setLiveText(\n formatMessage(\n {\n id: getTranslation('dnd.reorder'),\n defaultMessage: '{item}, moved. New position in list: {position}.',\n },\n {\n item: `${name}.${currentIndex}`,\n position: `${newIndex + 1} of ${value.length}`,\n }\n )\n );\n\n moveFieldRow(name, currentIndex, newIndex);\n },\n [formatMessage, moveFieldRow, name, value.length]\n );\n\n const handleCancel = React.useCallback(\n (index: number) => {\n setLiveText(\n formatMessage(\n {\n id: getTranslation('dnd.cancel-item'),\n defaultMessage: '{item}, dropped. Re-order cancelled.',\n },\n {\n item: `${name}.${index}`,\n }\n )\n );\n },\n [formatMessage, name]\n );\n\n const handleGrabItem = React.useCallback(\n (index: number) => {\n setLiveText(\n formatMessage(\n {\n id: getTranslation('dnd.grab-item'),\n defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`,\n },\n {\n item: `${name}.${index}`,\n position: `${index + 1} of ${value.length}`,\n }\n )\n );\n },\n [formatMessage, name, value.length]\n );\n\n const handleDropItem = React.useCallback(\n (index: number) => {\n setLiveText(\n formatMessage(\n {\n id: getTranslation('dnd.drop-item'),\n defaultMessage: `{item}, dropped. Final position in list: {position}.`,\n },\n {\n item: `${name}.${index}`,\n position: `${index + 1} of ${value.length}`,\n }\n )\n );\n },\n [formatMessage, name, value.length]\n );\n\n const handleRemoveComponent = React.useCallback(\n (currentIndex: number) => {\n removeFieldRow(name, currentIndex);\n },\n [name, removeFieldRow]\n );\n\n const hasError = error !== undefined;\n\n const renderButtonLabel = () => {\n if (addComponentIsOpen) {\n return formatMessage({ id: 'app.utils.close-label', defaultMessage: 'Close' });\n }\n\n if (hasError && dynamicDisplayedComponentsLength > max) {\n return formatMessage(\n {\n id: getTranslation(`components.DynamicZone.extra-components`),\n defaultMessage:\n 'There {number, plural, =0 {are # extra components} one {is # extra component} other {are # extra components}}',\n },\n {\n number: dynamicDisplayedComponentsLength - max,\n }\n );\n }\n\n if (hasError && dynamicDisplayedComponentsLength < min) {\n return formatMessage(\n {\n id: getTranslation(`components.DynamicZone.missing-components`),\n defaultMessage:\n 'There {number, plural, =0 {are # missing components} one {is # missing component} other {are # missing components}}',\n },\n { number: min - dynamicDisplayedComponentsLength }\n );\n }\n\n return formatMessage(\n {\n id: getTranslation('components.DynamicZone.add-component'),\n defaultMessage: 'Add a component to {componentName}',\n },\n { componentName: label || name }\n );\n };\n\n const level = useComponent('DynamicZone', (state) => state.level);\n\n const ariaDescriptionId = React.useId();\n\n return (\n <DynamicZoneProvider isInDynamicZone>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={{ initial: 4, medium: 6 }}>\n {dynamicDisplayedComponentsLength > 0 && (\n <Box>\n <DynamicZoneLabel\n hint={hint}\n label={label}\n labelAction={labelAction}\n name={name}\n numberOfComponents={dynamicDisplayedComponentsLength}\n required={required}\n />\n <VisuallyHidden id={ariaDescriptionId}>\n {formatMessage({\n id: getTranslation('dnd.instructions'),\n defaultMessage: `Press spacebar to grab and re-order`,\n })}\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"assertive\">{liveText}</VisuallyHidden>\n <ol aria-describedby={ariaDescriptionId}>\n {value.map((field, index) => (\n <ComponentProvider\n key={field.__temp_key__}\n level={level + 1}\n uid={field.__component}\n // id is always a number in a dynamic zone.\n id={field.id as number}\n type=\"dynamiczone\"\n >\n <DynamicComponent\n disabled={disabled}\n name={name}\n index={index}\n componentUid={field.__component}\n onMoveComponent={handleMoveComponent}\n onRemoveComponentClick={handleRemoveComponent}\n onCancel={handleCancel}\n onDropItem={handleDropItem}\n onGrabItem={handleGrabItem}\n onAddComponent={handleAddComponent}\n dynamicComponentsByCategory={dynamicComponentsByCategory}\n totalLength={dynamicDisplayedComponentsLength}\n forceOpen={openComponentKey === field.__temp_key__}\n onForceOpenHandled={handleForceOpenHandled}\n >\n {children}\n </DynamicComponent>\n </ComponentProvider>\n ))}\n </ol>\n </Box>\n )}\n <Flex justifyContent=\"center\">\n <AddComponentButton\n hasError={hasError}\n isDisabled={disabled}\n isOpen={addComponentIsOpen}\n onClick={handleClickOpenPicker}\n >\n {renderButtonLabel()}\n </AddComponentButton>\n </Flex>\n <ComponentPicker\n dynamicComponentsByCategory={dynamicComponentsByCategory}\n isOpen={addComponentIsOpen}\n onClickAddComponent={handleAddComponent}\n />\n </Flex>\n </DynamicZoneProvider>\n );\n};\n\nexport { DynamicZone, useDynamicZone };\nexport type { DynamicZoneProps };\n"],"names":["DynamicZoneProvider","useDynamicZone","createContext","isInDynamicZone","DynamicZone","attribute","disabled","disabledProp","hint","label","labelAction","name","required","children","max","Infinity","min","addComponentIsOpen","setAddComponentIsOpen","React","useState","liveText","setLiveText","openComponentKey","setOpenComponentKey","currentDocument","components","isLoading","useDocumentContext","addFieldRow","useForm","state","removeFieldRow","moveFieldRow","value","error","useField","prevValue","usePrev","useEffect","length","prevKeys","Set","map","v","__temp_key__","newItem","find","has","currentKeys","handleForceOpenHandled","useCallback","dynamicComponentsByCategory","useMemo","reduce","acc","componentUid","category","info","component","uid","displayName","icon","formatMessage","useIntl","toggleNotification","useNotification","dynamicDisplayedComponentsLength","handleAddComponent","position","schema","form","createDefaultForm","transformations","pipe","transformDocument","data","__component","handleClickOpenPicker","prev","type","message","id","getTranslation","handleMoveComponent","newIndex","currentIndex","defaultMessage","item","handleCancel","index","handleGrabItem","handleDropItem","handleRemoveComponent","hasError","undefined","renderButtonLabel","number","componentName","level","useComponent","ariaDescriptionId","useId","_jsx","_jsxs","Flex","direction","alignItems","gap","initial","medium","Box","DynamicZoneLabel","numberOfComponents","VisuallyHidden","aria-live","ol","aria-describedby","field","ComponentProvider","DynamicComponent","onMoveComponent","onRemoveComponentClick","onCancel","onDropItem","onGrabItem","onAddComponent","totalLength","forceOpen","onForceOpenHandled","justifyContent","AddComponentButton","isDisabled","isOpen","onClick","ComponentPicker","onClickAddComponent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Field.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n createContext,\n InputProps,\n useField,\n useForm,\n useNotification,\n} from '@strapi/admin/strapi-admin';\nimport { Box, Flex, VisuallyHidden } from '@strapi/design-system';\nimport pipe from 'lodash/fp/pipe';\nimport { useIntl } from 'react-intl';\n\nimport { useDocumentContext } from '../../../../../hooks/useDocumentContext';\nimport { type EditFieldLayout } from '../../../../../hooks/useDocumentLayout';\nimport { usePrev } from '../../../../../hooks/usePrev';\nimport { getTranslation } from '../../../../../utils/translations';\nimport { transformDocument } from '../../../utils/data';\nimport { createDefaultForm } from '../../../utils/forms';\nimport { ComponentProvider, useComponent } from '../ComponentContext';\n\nimport { AddComponentButton } from './AddComponentButton';\nimport { ComponentPicker } from './ComponentPicker';\nimport { DynamicComponent, DynamicComponentProps } from './DynamicComponent';\nimport { DynamicZoneLabel, DynamicZoneLabelProps } from './DynamicZoneLabel';\n\nimport type { InputRendererProps } from '../../InputRenderer';\nimport type { Schema } from '@strapi/types';\n\ninterface DynamicZoneContextValue {\n isInDynamicZone: boolean;\n}\n\nconst [DynamicZoneProvider, useDynamicZone] = createContext<DynamicZoneContextValue>(\n 'DynamicZone',\n {\n isInDynamicZone: false,\n }\n);\n\ninterface DynamicZoneProps\n extends Omit<Extract<EditFieldLayout, { type: 'dynamiczone' }>, 'size' | 'hint'>,\n Pick<InputProps, 'hint'>,\n Pick<DynamicZoneLabelProps, 'labelAction'> {\n children?: (props: InputRendererProps) => React.ReactNode;\n}\n\nconst DynamicZone = ({\n attribute,\n disabled: disabledProp,\n hint,\n label,\n labelAction,\n name,\n required = false,\n children,\n}: DynamicZoneProps) => {\n // We cannot use the default props here\n const { max = Infinity, min = -Infinity } = attribute ?? {};\n\n const [addComponentIsOpen, setAddComponentIsOpen] = React.useState(false);\n const [liveText, setLiveText] = React.useState('');\n const [openComponentKey, setOpenComponentKey] = React.useState<string | null>(null);\n\n const {\n currentDocument: { components, isLoading },\n } = useDocumentContext('DynamicZone');\n\n const disabled = disabledProp || isLoading;\n const addFieldRow = useForm('DynamicZone', (state) => state.addFieldRow);\n const removeFieldRow = useForm('DynamicZone', (state) => state.removeFieldRow);\n const moveFieldRow = useForm('DynamicZone', (state) => state.moveFieldRow);\n\n type DzWithTempKey =\n Schema.Attribute.GetDynamicZoneValue<Schema.Attribute.DynamicZone>[number] & {\n __temp_key__: string;\n };\n\n const { value = [], error } = useField<Array<DzWithTempKey>>(name);\n\n /**\n * Track the previous value array to detect when a new component is added.\n * When the array grows, we find the newly added item and force its accordion open.\n * This mirrors the same pattern used in RepeatableComponent.\n */\n const prevValue = usePrev(value);\n\n React.useEffect(() => {\n if (prevValue && prevValue.length < value.length) {\n const prevKeys = new Set(prevValue.map((v) => v.__temp_key__));\n const newItem = value.find((v) => !prevKeys.has(v.__temp_key__));\n if (newItem) {\n setOpenComponentKey(newItem.__temp_key__);\n }\n } else if (openComponentKey !== null) {\n // Component was removed before forceOpen was handled — clear stale key\n const currentKeys = new Set(value.map((v) => v.__temp_key__));\n if (!currentKeys.has(openComponentKey)) {\n setOpenComponentKey(null);\n }\n }\n }, [value, prevValue, openComponentKey]);\n\n const handleForceOpenHandled = React.useCallback(() => {\n setOpenComponentKey(null);\n }, []);\n\n const dynamicComponentsByCategory = React.useMemo(() => {\n return attribute.components.reduce<\n NonNullable<DynamicComponentProps['dynamicComponentsByCategory']>\n >((acc, componentUid) => {\n const componentSchema = components[componentUid];\n\n if (!componentSchema) {\n return acc;\n }\n\n const { category, info } = componentSchema;\n\n const component = { uid: componentUid, displayName: info.displayName, icon: info.icon };\n\n if (!acc[category]) {\n acc[category] = [];\n }\n\n acc[category] = [...acc[category], component];\n\n return acc;\n }, {});\n }, [attribute.components, components]);\n\n const { formatMessage } = useIntl();\n\n const { toggleNotification } = useNotification();\n\n const dynamicDisplayedComponentsLength = value.length;\n\n const handleAddComponent = React.useCallback(\n (uid: string, position?: number) => {\n const schema = components[uid];\n\n if (!schema) {\n return;\n }\n\n setAddComponentIsOpen(false);\n\n const form = createDefaultForm(schema, components);\n const transformations = pipe(transformDocument(schema, components), (data) => ({\n ...data,\n __component: uid,\n }));\n\n const data = transformations(form);\n\n addFieldRow(name, data, position);\n },\n [addFieldRow, components, name]\n );\n\n const handleClickOpenPicker = () => {\n if (dynamicDisplayedComponentsLength < max) {\n setAddComponentIsOpen((prev) => !prev);\n } else {\n toggleNotification({\n type: 'info',\n message: formatMessage({\n id: getTranslation('components.notification.info.maximum-requirement'),\n }),\n });\n }\n };\n\n const handleMoveComponent = React.useCallback(\n (newIndex: number, currentIndex: number) => {\n setLiveText(\n formatMessage(\n {\n id: getTranslation('dnd.reorder'),\n defaultMessage: '{item}, moved. New position in list: {position}.',\n },\n {\n item: `${name}.${currentIndex}`,\n position: `${newIndex + 1} of ${value.length}`,\n }\n )\n );\n\n moveFieldRow(name, currentIndex, newIndex);\n },\n [formatMessage, moveFieldRow, name, value.length]\n );\n\n const handleCancel = React.useCallback(\n (index: number) => {\n setLiveText(\n formatMessage(\n {\n id: getTranslation('dnd.cancel-item'),\n defaultMessage: '{item}, dropped. Re-order cancelled.',\n },\n {\n item: `${name}.${index}`,\n }\n )\n );\n },\n [formatMessage, name]\n );\n\n const handleGrabItem = React.useCallback(\n (index: number) => {\n setLiveText(\n formatMessage(\n {\n id: getTranslation('dnd.grab-item'),\n defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`,\n },\n {\n item: `${name}.${index}`,\n position: `${index + 1} of ${value.length}`,\n }\n )\n );\n },\n [formatMessage, name, value.length]\n );\n\n const handleDropItem = React.useCallback(\n (index: number) => {\n setLiveText(\n formatMessage(\n {\n id: getTranslation('dnd.drop-item'),\n defaultMessage: `{item}, dropped. Final position in list: {position}.`,\n },\n {\n item: `${name}.${index}`,\n position: `${index + 1} of ${value.length}`,\n }\n )\n );\n },\n [formatMessage, name, value.length]\n );\n\n const handleRemoveComponent = React.useCallback(\n (currentIndex: number) => {\n removeFieldRow(name, currentIndex);\n },\n [name, removeFieldRow]\n );\n\n const hasError = error !== undefined;\n\n const renderButtonLabel = () => {\n if (addComponentIsOpen) {\n return formatMessage({ id: 'app.utils.close-label', defaultMessage: 'Close' });\n }\n\n if (hasError && dynamicDisplayedComponentsLength > max) {\n return formatMessage(\n {\n id: getTranslation(`components.DynamicZone.extra-components`),\n defaultMessage:\n 'There {number, plural, =0 {are # extra components} one {is # extra component} other {are # extra components}}',\n },\n {\n number: dynamicDisplayedComponentsLength - max,\n }\n );\n }\n\n if (hasError && dynamicDisplayedComponentsLength < min) {\n return formatMessage(\n {\n id: getTranslation(`components.DynamicZone.missing-components`),\n defaultMessage:\n 'There {number, plural, =0 {are # missing components} one {is # missing component} other {are # missing components}}',\n },\n { number: min - dynamicDisplayedComponentsLength }\n );\n }\n\n return formatMessage(\n {\n id: getTranslation('components.DynamicZone.add-component'),\n defaultMessage: 'Add a component to {componentName}',\n },\n { componentName: label || name }\n );\n };\n\n const level = useComponent('DynamicZone', (state) => state.level);\n\n const ariaDescriptionId = React.useId();\n\n return (\n <DynamicZoneProvider isInDynamicZone>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={{ initial: 4, medium: 6 }}>\n {dynamicDisplayedComponentsLength > 0 && (\n <Box>\n <DynamicZoneLabel\n hint={hint}\n label={label}\n labelAction={labelAction}\n name={name}\n numberOfComponents={dynamicDisplayedComponentsLength}\n required={required}\n />\n <VisuallyHidden id={ariaDescriptionId}>\n {formatMessage({\n id: getTranslation('dnd.instructions'),\n defaultMessage: `Press spacebar to grab and re-order`,\n })}\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"assertive\">{liveText}</VisuallyHidden>\n <ol aria-describedby={ariaDescriptionId}>\n {value.map((field, index) => (\n <ComponentProvider\n key={field.__temp_key__}\n level={level + 1}\n uid={field.__component}\n // id is always a number in a dynamic zone.\n id={field.id as number}\n type=\"dynamiczone\"\n >\n <DynamicComponent\n disabled={disabled}\n name={name}\n index={index}\n componentUid={field.__component}\n onMoveComponent={handleMoveComponent}\n onRemoveComponentClick={handleRemoveComponent}\n onCancel={handleCancel}\n onDropItem={handleDropItem}\n onGrabItem={handleGrabItem}\n onAddComponent={handleAddComponent}\n dynamicComponentsByCategory={dynamicComponentsByCategory}\n totalLength={dynamicDisplayedComponentsLength}\n forceOpen={openComponentKey === field.__temp_key__}\n onForceOpenHandled={handleForceOpenHandled}\n >\n {children}\n </DynamicComponent>\n </ComponentProvider>\n ))}\n </ol>\n </Box>\n )}\n <Flex justifyContent=\"center\">\n <AddComponentButton\n hasError={hasError}\n isDisabled={disabled}\n isOpen={addComponentIsOpen}\n onClick={handleClickOpenPicker}\n >\n {renderButtonLabel()}\n </AddComponentButton>\n </Flex>\n <ComponentPicker\n dynamicComponentsByCategory={dynamicComponentsByCategory}\n isOpen={addComponentIsOpen}\n onClickAddComponent={handleAddComponent}\n />\n </Flex>\n </DynamicZoneProvider>\n );\n};\n\nexport { DynamicZone, useDynamicZone };\nexport type { DynamicZoneProps };\n"],"names":["DynamicZoneProvider","useDynamicZone","createContext","isInDynamicZone","DynamicZone","attribute","disabled","disabledProp","hint","label","labelAction","name","required","children","max","Infinity","min","addComponentIsOpen","setAddComponentIsOpen","React","useState","liveText","setLiveText","openComponentKey","setOpenComponentKey","currentDocument","components","isLoading","useDocumentContext","addFieldRow","useForm","state","removeFieldRow","moveFieldRow","value","error","useField","prevValue","usePrev","useEffect","length","prevKeys","Set","map","v","__temp_key__","newItem","find","has","currentKeys","handleForceOpenHandled","useCallback","dynamicComponentsByCategory","useMemo","reduce","acc","componentUid","componentSchema","category","info","component","uid","displayName","icon","formatMessage","useIntl","toggleNotification","useNotification","dynamicDisplayedComponentsLength","handleAddComponent","position","schema","form","createDefaultForm","transformations","pipe","transformDocument","data","__component","handleClickOpenPicker","prev","type","message","id","getTranslation","handleMoveComponent","newIndex","currentIndex","defaultMessage","item","handleCancel","index","handleGrabItem","handleDropItem","handleRemoveComponent","hasError","undefined","renderButtonLabel","number","componentName","level","useComponent","ariaDescriptionId","useId","_jsx","_jsxs","Flex","direction","alignItems","gap","initial","medium","Box","DynamicZoneLabel","numberOfComponents","VisuallyHidden","aria-live","ol","aria-describedby","field","ComponentProvider","DynamicComponent","onMoveComponent","onRemoveComponentClick","onCancel","onDropItem","onGrabItem","onAddComponent","totalLength","forceOpen","onForceOpenHandled","justifyContent","AddComponentButton","isDisabled","isOpen","onClick","ComponentPicker","onClickAddComponent"],"mappings":"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"}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var React = require('react');
|
|
5
|
-
var sanitizeHtml = require('sanitize-html');
|
|
6
5
|
var styledComponents = require('styled-components');
|
|
7
6
|
var mdRenderer = require('./utils/mdRenderer.js');
|
|
7
|
+
var sanitizer = require('./utils/sanitizer.js');
|
|
8
8
|
|
|
9
9
|
function _interopNamespaceDefault(e) {
|
|
10
10
|
var n = Object.create(null);
|
|
@@ -26,31 +26,7 @@ function _interopNamespaceDefault(e) {
|
|
|
26
26
|
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
27
27
|
|
|
28
28
|
const PreviewWysiwyg = ({ data })=>{
|
|
29
|
-
const html = React__namespace.useMemo(()=>
|
|
30
|
-
...sanitizeHtml.defaults,
|
|
31
|
-
allowedTags: false,
|
|
32
|
-
allowedAttributes: {
|
|
33
|
-
'*': [
|
|
34
|
-
'href',
|
|
35
|
-
'align',
|
|
36
|
-
'alt',
|
|
37
|
-
'center',
|
|
38
|
-
'width',
|
|
39
|
-
'height',
|
|
40
|
-
'type',
|
|
41
|
-
'controls',
|
|
42
|
-
'target'
|
|
43
|
-
],
|
|
44
|
-
img: [
|
|
45
|
-
'src',
|
|
46
|
-
'alt'
|
|
47
|
-
],
|
|
48
|
-
source: [
|
|
49
|
-
'src',
|
|
50
|
-
'type'
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
}), [
|
|
29
|
+
const html = React__namespace.useMemo(()=>sanitizer.sanitize(mdRenderer.md.render((data ?? '').replaceAll('\\n', '\n'))), [
|
|
54
30
|
data
|
|
55
31
|
]);
|
|
56
32
|
return /*#__PURE__*/ jsxRuntime.jsx(Wrapper, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PreviewWysiwyg.js","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport
|
|
1
|
+
{"version":3,"file":"PreviewWysiwyg.js","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { styled } from 'styled-components';\n\nimport { md } from './utils/mdRenderer';\nimport { sanitize } from './utils/sanitizer';\n\ninterface PreviewWysiwygProps {\n data?: string;\n}\n\nconst PreviewWysiwyg = ({ data }: PreviewWysiwygProps) => {\n const html = React.useMemo(\n () => sanitize(md.render((data ?? '').replaceAll('\\\\n', '\\n'))),\n [data]\n );\n\n return (\n <Wrapper>\n <div dangerouslySetInnerHTML={{ __html: html }} />\n </Wrapper>\n );\n};\n\nconst Wrapper = styled.div`\n position: absolute;\n top: 0;\n width: 100%;\n height: 100%;\n overflow: auto;\n padding: ${({ theme }) => `${theme.spaces[3]} ${theme.spaces[4]}`};\n font-size: 1.4rem;\n background-color: ${({ theme }) => theme.colors.neutral0};\n color: ${({ theme }) => theme.colors.neutral800};\n line-height: ${({ theme }) => theme.lineHeights[6]};\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n margin-block-start: ${({ theme }) => theme.spaces[2]};\n margin-block-end: ${({ theme }) => theme.spaces[2]};\n }\n\n p {\n margin-bottom: ${({ theme }) => theme.spaces[2]};\n }\n\n h1 {\n font-size: 2.8rem;\n ${({ theme }) => theme.breakpoints.medium} {\n font-size: 3.6rem;\n }\n font-weight: 600;\n }\n\n h2 {\n font-size: 2.2rem;\n ${({ theme }) => theme.breakpoints.medium} {\n font-size: 3rem;\n }\n font-weight: 600;\n }\n\n h3 {\n font-size: 2rem;\n ${({ theme }) => theme.breakpoints.medium} {\n font-size: 2.4rem;\n }\n font-weight: 600;\n }\n\n h4 {\n font-size: 1.8rem;\n ${({ theme }) => theme.breakpoints.medium} {\n font-size: 2.4rem;\n }\n font-weight: 600;\n }\n\n strong {\n font-weight: 800;\n }\n\n em {\n font-style: italic;\n }\n\n blockquote {\n margin-top: ${({ theme }) => theme.spaces[8]};\n margin-bottom: ${({ theme }) => theme.spaces[7]};\n font-size: 1.4rem;\n font-weight: 400;\n border-left: 4px solid ${({ theme }) => theme.colors.neutral150};\n font-style: italic;\n padding: ${({ theme }) => theme.spaces[2]} ${({ theme }) => theme.spaces[5]};\n }\n\n img {\n max-width: 100%;\n }\n\n table {\n thead {\n background: ${({ theme }) => theme.colors.neutral150};\n\n th {\n padding: ${({ theme }) => theme.spaces[4]};\n }\n }\n tr {\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n }\n th,\n td {\n padding: ${({ theme }) => theme.spaces[4]};\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-bottom: 0;\n border-top: 0;\n }\n }\n\n pre,\n code {\n font-size: 1.4rem;\n border-radius: 4px;\n /* \n Hard coded since the color is the same between themes,\n theme.colors.neutral800 changes between themes.\n\n Matches the color of the JSON Input component.\n */\n background-color: #32324d;\n max-width: 100%;\n overflow: auto;\n padding: ${({ theme }) => theme.spaces[2]};\n }\n\n /* Inline code */\n p,\n pre,\n td {\n > code {\n color: #839496;\n }\n }\n\n ol {\n list-style-type: decimal;\n margin-block-start: ${({ theme }) => theme.spaces[4]};\n margin-block-end: ${({ theme }) => theme.spaces[4]};\n margin-inline-start: 0px;\n margin-inline-end: 0px;\n padding-inline-start: ${({ theme }) => theme.spaces[4]};\n\n ol,\n ul {\n margin-block-start: 0px;\n margin-block-end: 0px;\n }\n }\n\n ul {\n list-style-type: disc;\n margin-block-start: ${({ theme }) => theme.spaces[4]};\n margin-block-end: ${({ theme }) => theme.spaces[4]};\n margin-inline-start: 0px;\n margin-inline-end: 0px;\n padding-inline-start: ${({ theme }) => theme.spaces[4]};\n\n ul,\n ol {\n margin-block-start: 0px;\n margin-block-end: 0px;\n }\n }\n`;\n\nexport { PreviewWysiwyg };\n"],"names":["PreviewWysiwyg","data","html","React","useMemo","sanitize","md","render","replaceAll","_jsx","Wrapper","div","dangerouslySetInnerHTML","__html","styled","theme","spaces","colors","neutral0","neutral800","lineHeights","breakpoints","medium","neutral150","neutral200"],"mappings":"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"}
|
|
@@ -1,35 +1,11 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import sanitizeHtml from 'sanitize-html';
|
|
4
3
|
import { styled } from 'styled-components';
|
|
5
4
|
import { md } from './utils/mdRenderer.mjs';
|
|
5
|
+
import { sanitize } from './utils/sanitizer.mjs';
|
|
6
6
|
|
|
7
7
|
const PreviewWysiwyg = ({ data })=>{
|
|
8
|
-
const html = React.useMemo(()=>
|
|
9
|
-
...sanitizeHtml.defaults,
|
|
10
|
-
allowedTags: false,
|
|
11
|
-
allowedAttributes: {
|
|
12
|
-
'*': [
|
|
13
|
-
'href',
|
|
14
|
-
'align',
|
|
15
|
-
'alt',
|
|
16
|
-
'center',
|
|
17
|
-
'width',
|
|
18
|
-
'height',
|
|
19
|
-
'type',
|
|
20
|
-
'controls',
|
|
21
|
-
'target'
|
|
22
|
-
],
|
|
23
|
-
img: [
|
|
24
|
-
'src',
|
|
25
|
-
'alt'
|
|
26
|
-
],
|
|
27
|
-
source: [
|
|
28
|
-
'src',
|
|
29
|
-
'type'
|
|
30
|
-
]
|
|
31
|
-
}
|
|
32
|
-
}), [
|
|
8
|
+
const html = React.useMemo(()=>sanitize(md.render((data ?? '').replaceAll('\\n', '\n'))), [
|
|
33
9
|
data
|
|
34
10
|
]);
|
|
35
11
|
return /*#__PURE__*/ jsx(Wrapper, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PreviewWysiwyg.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport
|
|
1
|
+
{"version":3,"file":"PreviewWysiwyg.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { styled } from 'styled-components';\n\nimport { md } from './utils/mdRenderer';\nimport { sanitize } from './utils/sanitizer';\n\ninterface PreviewWysiwygProps {\n data?: string;\n}\n\nconst PreviewWysiwyg = ({ data }: PreviewWysiwygProps) => {\n const html = React.useMemo(\n () => sanitize(md.render((data ?? '').replaceAll('\\\\n', '\\n'))),\n [data]\n );\n\n return (\n <Wrapper>\n <div dangerouslySetInnerHTML={{ __html: html }} />\n </Wrapper>\n );\n};\n\nconst Wrapper = styled.div`\n position: absolute;\n top: 0;\n width: 100%;\n height: 100%;\n overflow: auto;\n padding: ${({ theme }) => `${theme.spaces[3]} ${theme.spaces[4]}`};\n font-size: 1.4rem;\n background-color: ${({ theme }) => theme.colors.neutral0};\n color: ${({ theme }) => theme.colors.neutral800};\n line-height: ${({ theme }) => theme.lineHeights[6]};\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n margin-block-start: ${({ theme }) => theme.spaces[2]};\n margin-block-end: ${({ theme }) => theme.spaces[2]};\n }\n\n p {\n margin-bottom: ${({ theme }) => theme.spaces[2]};\n }\n\n h1 {\n font-size: 2.8rem;\n ${({ theme }) => theme.breakpoints.medium} {\n font-size: 3.6rem;\n }\n font-weight: 600;\n }\n\n h2 {\n font-size: 2.2rem;\n ${({ theme }) => theme.breakpoints.medium} {\n font-size: 3rem;\n }\n font-weight: 600;\n }\n\n h3 {\n font-size: 2rem;\n ${({ theme }) => theme.breakpoints.medium} {\n font-size: 2.4rem;\n }\n font-weight: 600;\n }\n\n h4 {\n font-size: 1.8rem;\n ${({ theme }) => theme.breakpoints.medium} {\n font-size: 2.4rem;\n }\n font-weight: 600;\n }\n\n strong {\n font-weight: 800;\n }\n\n em {\n font-style: italic;\n }\n\n blockquote {\n margin-top: ${({ theme }) => theme.spaces[8]};\n margin-bottom: ${({ theme }) => theme.spaces[7]};\n font-size: 1.4rem;\n font-weight: 400;\n border-left: 4px solid ${({ theme }) => theme.colors.neutral150};\n font-style: italic;\n padding: ${({ theme }) => theme.spaces[2]} ${({ theme }) => theme.spaces[5]};\n }\n\n img {\n max-width: 100%;\n }\n\n table {\n thead {\n background: ${({ theme }) => theme.colors.neutral150};\n\n th {\n padding: ${({ theme }) => theme.spaces[4]};\n }\n }\n tr {\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n }\n th,\n td {\n padding: ${({ theme }) => theme.spaces[4]};\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-bottom: 0;\n border-top: 0;\n }\n }\n\n pre,\n code {\n font-size: 1.4rem;\n border-radius: 4px;\n /* \n Hard coded since the color is the same between themes,\n theme.colors.neutral800 changes between themes.\n\n Matches the color of the JSON Input component.\n */\n background-color: #32324d;\n max-width: 100%;\n overflow: auto;\n padding: ${({ theme }) => theme.spaces[2]};\n }\n\n /* Inline code */\n p,\n pre,\n td {\n > code {\n color: #839496;\n }\n }\n\n ol {\n list-style-type: decimal;\n margin-block-start: ${({ theme }) => theme.spaces[4]};\n margin-block-end: ${({ theme }) => theme.spaces[4]};\n margin-inline-start: 0px;\n margin-inline-end: 0px;\n padding-inline-start: ${({ theme }) => theme.spaces[4]};\n\n ol,\n ul {\n margin-block-start: 0px;\n margin-block-end: 0px;\n }\n }\n\n ul {\n list-style-type: disc;\n margin-block-start: ${({ theme }) => theme.spaces[4]};\n margin-block-end: ${({ theme }) => theme.spaces[4]};\n margin-inline-start: 0px;\n margin-inline-end: 0px;\n padding-inline-start: ${({ theme }) => theme.spaces[4]};\n\n ul,\n ol {\n margin-block-start: 0px;\n margin-block-end: 0px;\n }\n }\n`;\n\nexport { PreviewWysiwyg };\n"],"names":["PreviewWysiwyg","data","html","React","useMemo","sanitize","md","render","replaceAll","_jsx","Wrapper","div","dangerouslySetInnerHTML","__html","styled","theme","spaces","colors","neutral0","neutral800","lineHeights","breakpoints","medium","neutral150","neutral200"],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var createDOMPurify = require('dompurify');
|
|
4
|
+
|
|
5
|
+
// Own instance, so the data: hook below stays scoped to this module instead of
|
|
6
|
+
// mutating the library-wide singleton shared with any other DOMPurify consumer.
|
|
7
|
+
const DOMPurify = createDOMPurify(window);
|
|
8
|
+
/**
|
|
9
|
+
* Attribute allowlist. Starts from the prior sanitize-html configuration:
|
|
10
|
+
* '*': href, align, alt, center, width, height, type, controls, target
|
|
11
|
+
* img: src, alt
|
|
12
|
+
* source: src, type
|
|
13
|
+
*
|
|
14
|
+
* DOMPurify's ALLOWED_ATTR is a flat list (no per-tag scoping), so the union
|
|
15
|
+
* of the original allowlist is used. Tags that the prior config never reached
|
|
16
|
+
* (script, iframe, etc.) are stripped wholesale by DOMPurify's default tag
|
|
17
|
+
* allowlist, so per-tag attribute scoping is not security-relevant here.
|
|
18
|
+
*
|
|
19
|
+
* `class` and `title` are additions over the old config (which stripped both):
|
|
20
|
+
* - class: mdRenderer.ts emits `hljs`/`language-*` on code blocks (so the
|
|
21
|
+
* highlight.js solarized-dark stylesheet applies) and `footnote-ref`/
|
|
22
|
+
* `footnote-backref` on footnotes. Stripping it left those styles dead.
|
|
23
|
+
* - title: link/image tooltips and the markdown-it abbr plugin (`<abbr title>`).
|
|
24
|
+
* Both are inert in admin-authored content behind the tag allowlist; neither
|
|
25
|
+
* can escalate.
|
|
26
|
+
*/ const ALLOWED_ATTR = [
|
|
27
|
+
'href',
|
|
28
|
+
'src',
|
|
29
|
+
'alt',
|
|
30
|
+
'align',
|
|
31
|
+
'center',
|
|
32
|
+
'width',
|
|
33
|
+
'height',
|
|
34
|
+
'type',
|
|
35
|
+
'controls',
|
|
36
|
+
'target',
|
|
37
|
+
'class',
|
|
38
|
+
'title'
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* URL scheme allowlist: http(s), ftp, mailto, tel, plus protocol-relative,
|
|
42
|
+
* fragment, and relative URLs. Mirrors sanitize-html's prior allowedSchemes.
|
|
43
|
+
*/ const ALLOWED_URI_REGEXP = /^(?:(?:https?|ftp|mailto|tel):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
|
|
44
|
+
/**
|
|
45
|
+
* DOMPurify permits `data:` URIs on media tags (img/source/video/audio)
|
|
46
|
+
* through its internal DATA_URI_TAGS allowlist, *bypassing* ALLOWED_URI_REGEXP.
|
|
47
|
+
* The prior sanitize-html config stripped every `data:` URI, so strip them here
|
|
48
|
+
* too for parity.
|
|
49
|
+
*/ const URL_ATTRIBUTES = [
|
|
50
|
+
'src',
|
|
51
|
+
'href',
|
|
52
|
+
'xlink:href'
|
|
53
|
+
];
|
|
54
|
+
DOMPurify.addHook('afterSanitizeAttributes', (node)=>{
|
|
55
|
+
if (typeof node.getAttribute !== 'function') {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
for (const attr of URL_ATTRIBUTES){
|
|
59
|
+
const value = node.getAttribute(attr);
|
|
60
|
+
if (value && /^\s*data:/i.test(value)) {
|
|
61
|
+
node.removeAttribute(attr);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
const sanitize = (html)=>DOMPurify.sanitize(html, {
|
|
66
|
+
ALLOWED_ATTR,
|
|
67
|
+
ALLOWED_URI_REGEXP,
|
|
68
|
+
ALLOW_DATA_ATTR: false
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
exports.sanitize = sanitize;
|
|
72
|
+
//# sourceMappingURL=sanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.js","sources":["../../../../../../../../admin/src/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.ts"],"sourcesContent":["import createDOMPurify from 'dompurify';\n\n// Own instance, so the data: hook below stays scoped to this module instead of\n// mutating the library-wide singleton shared with any other DOMPurify consumer.\nconst DOMPurify = createDOMPurify(window);\n\n/**\n * Attribute allowlist. Starts from the prior sanitize-html configuration:\n * '*': href, align, alt, center, width, height, type, controls, target\n * img: src, alt\n * source: src, type\n *\n * DOMPurify's ALLOWED_ATTR is a flat list (no per-tag scoping), so the union\n * of the original allowlist is used. Tags that the prior config never reached\n * (script, iframe, etc.) are stripped wholesale by DOMPurify's default tag\n * allowlist, so per-tag attribute scoping is not security-relevant here.\n *\n * `class` and `title` are additions over the old config (which stripped both):\n * - class: mdRenderer.ts emits `hljs`/`language-*` on code blocks (so the\n * highlight.js solarized-dark stylesheet applies) and `footnote-ref`/\n * `footnote-backref` on footnotes. Stripping it left those styles dead.\n * - title: link/image tooltips and the markdown-it abbr plugin (`<abbr title>`).\n * Both are inert in admin-authored content behind the tag allowlist; neither\n * can escalate.\n */\nconst ALLOWED_ATTR = [\n 'href',\n 'src',\n 'alt',\n 'align',\n 'center',\n 'width',\n 'height',\n 'type',\n 'controls',\n 'target',\n 'class',\n 'title',\n];\n\n/**\n * URL scheme allowlist: http(s), ftp, mailto, tel, plus protocol-relative,\n * fragment, and relative URLs. Mirrors sanitize-html's prior allowedSchemes.\n */\nconst ALLOWED_URI_REGEXP = /^(?:(?:https?|ftp|mailto|tel):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i;\n\n/**\n * DOMPurify permits `data:` URIs on media tags (img/source/video/audio)\n * through its internal DATA_URI_TAGS allowlist, *bypassing* ALLOWED_URI_REGEXP.\n * The prior sanitize-html config stripped every `data:` URI, so strip them here\n * too for parity.\n */\nconst URL_ATTRIBUTES = ['src', 'href', 'xlink:href'];\nDOMPurify.addHook('afterSanitizeAttributes', (node) => {\n if (typeof node.getAttribute !== 'function') {\n return;\n }\n for (const attr of URL_ATTRIBUTES) {\n const value = node.getAttribute(attr);\n if (value && /^\\s*data:/i.test(value)) {\n node.removeAttribute(attr);\n }\n }\n});\n\nconst sanitize = (html: string): string =>\n DOMPurify.sanitize(html, {\n ALLOWED_ATTR,\n ALLOWED_URI_REGEXP,\n ALLOW_DATA_ATTR: false,\n });\n\nexport { sanitize };\n"],"names":["DOMPurify","createDOMPurify","window","ALLOWED_ATTR","ALLOWED_URI_REGEXP","URL_ATTRIBUTES","addHook","node","getAttribute","attr","value","test","removeAttribute","sanitize","html","ALLOW_DATA_ATTR"],"mappings":";;;;AAEA;AACA;AACA,MAAMA,YAAYC,eAAAA,CAAgBC,MAAAA,CAAAA;AAElC;;;;;;;;;;;;;;;;;;AAkBC,IACD,MAAMC,YAAAA,GAAe;AACnB,IAAA,MAAA;AACA,IAAA,KAAA;AACA,IAAA,KAAA;AACA,IAAA,OAAA;AACA,IAAA,QAAA;AACA,IAAA,OAAA;AACA,IAAA,QAAA;AACA,IAAA,MAAA;AACA,IAAA,UAAA;AACA,IAAA,QAAA;AACA,IAAA,OAAA;AACA,IAAA;AACD,CAAA;AAED;;;AAGC,IACD,MAAMC,kBAAAA,GAAqB,qEAAA;AAE3B;;;;;AAKC,IACD,MAAMC,cAAAA,GAAiB;AAAC,IAAA,KAAA;AAAO,IAAA,MAAA;AAAQ,IAAA;AAAa,CAAA;AACpDL,SAAAA,CAAUM,OAAO,CAAC,yBAAA,EAA2B,CAACC,IAAAA,GAAAA;AAC5C,IAAA,IAAI,OAAOA,IAAAA,CAAKC,YAAY,KAAK,UAAA,EAAY;AAC3C,QAAA;AACF,IAAA;IACA,KAAK,MAAMC,QAAQJ,cAAAA,CAAgB;QACjC,MAAMK,KAAAA,GAAQH,IAAAA,CAAKC,YAAY,CAACC,IAAAA,CAAAA;AAChC,QAAA,IAAIC,KAAAA,IAAS,YAAA,CAAaC,IAAI,CAACD,KAAAA,CAAAA,EAAQ;AACrCH,YAAAA,IAAAA,CAAKK,eAAe,CAACH,IAAAA,CAAAA;AACvB,QAAA;AACF,IAAA;AACF,CAAA,CAAA;AAEA,MAAMI,WAAW,CAACC,IAAAA,GAChBd,SAAAA,CAAUa,QAAQ,CAACC,IAAAA,EAAM;AACvBX,QAAAA,YAAAA;AACAC,QAAAA,kBAAAA;QACAW,eAAAA,EAAiB;AACnB,KAAA;;;;"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import createDOMPurify from 'dompurify';
|
|
2
|
+
|
|
3
|
+
// Own instance, so the data: hook below stays scoped to this module instead of
|
|
4
|
+
// mutating the library-wide singleton shared with any other DOMPurify consumer.
|
|
5
|
+
const DOMPurify = createDOMPurify(window);
|
|
6
|
+
/**
|
|
7
|
+
* Attribute allowlist. Starts from the prior sanitize-html configuration:
|
|
8
|
+
* '*': href, align, alt, center, width, height, type, controls, target
|
|
9
|
+
* img: src, alt
|
|
10
|
+
* source: src, type
|
|
11
|
+
*
|
|
12
|
+
* DOMPurify's ALLOWED_ATTR is a flat list (no per-tag scoping), so the union
|
|
13
|
+
* of the original allowlist is used. Tags that the prior config never reached
|
|
14
|
+
* (script, iframe, etc.) are stripped wholesale by DOMPurify's default tag
|
|
15
|
+
* allowlist, so per-tag attribute scoping is not security-relevant here.
|
|
16
|
+
*
|
|
17
|
+
* `class` and `title` are additions over the old config (which stripped both):
|
|
18
|
+
* - class: mdRenderer.ts emits `hljs`/`language-*` on code blocks (so the
|
|
19
|
+
* highlight.js solarized-dark stylesheet applies) and `footnote-ref`/
|
|
20
|
+
* `footnote-backref` on footnotes. Stripping it left those styles dead.
|
|
21
|
+
* - title: link/image tooltips and the markdown-it abbr plugin (`<abbr title>`).
|
|
22
|
+
* Both are inert in admin-authored content behind the tag allowlist; neither
|
|
23
|
+
* can escalate.
|
|
24
|
+
*/ const ALLOWED_ATTR = [
|
|
25
|
+
'href',
|
|
26
|
+
'src',
|
|
27
|
+
'alt',
|
|
28
|
+
'align',
|
|
29
|
+
'center',
|
|
30
|
+
'width',
|
|
31
|
+
'height',
|
|
32
|
+
'type',
|
|
33
|
+
'controls',
|
|
34
|
+
'target',
|
|
35
|
+
'class',
|
|
36
|
+
'title'
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* URL scheme allowlist: http(s), ftp, mailto, tel, plus protocol-relative,
|
|
40
|
+
* fragment, and relative URLs. Mirrors sanitize-html's prior allowedSchemes.
|
|
41
|
+
*/ const ALLOWED_URI_REGEXP = /^(?:(?:https?|ftp|mailto|tel):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
|
|
42
|
+
/**
|
|
43
|
+
* DOMPurify permits `data:` URIs on media tags (img/source/video/audio)
|
|
44
|
+
* through its internal DATA_URI_TAGS allowlist, *bypassing* ALLOWED_URI_REGEXP.
|
|
45
|
+
* The prior sanitize-html config stripped every `data:` URI, so strip them here
|
|
46
|
+
* too for parity.
|
|
47
|
+
*/ const URL_ATTRIBUTES = [
|
|
48
|
+
'src',
|
|
49
|
+
'href',
|
|
50
|
+
'xlink:href'
|
|
51
|
+
];
|
|
52
|
+
DOMPurify.addHook('afterSanitizeAttributes', (node)=>{
|
|
53
|
+
if (typeof node.getAttribute !== 'function') {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
for (const attr of URL_ATTRIBUTES){
|
|
57
|
+
const value = node.getAttribute(attr);
|
|
58
|
+
if (value && /^\s*data:/i.test(value)) {
|
|
59
|
+
node.removeAttribute(attr);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
const sanitize = (html)=>DOMPurify.sanitize(html, {
|
|
64
|
+
ALLOWED_ATTR,
|
|
65
|
+
ALLOWED_URI_REGEXP,
|
|
66
|
+
ALLOW_DATA_ATTR: false
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export { sanitize };
|
|
70
|
+
//# sourceMappingURL=sanitizer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.mjs","sources":["../../../../../../../../admin/src/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.ts"],"sourcesContent":["import createDOMPurify from 'dompurify';\n\n// Own instance, so the data: hook below stays scoped to this module instead of\n// mutating the library-wide singleton shared with any other DOMPurify consumer.\nconst DOMPurify = createDOMPurify(window);\n\n/**\n * Attribute allowlist. Starts from the prior sanitize-html configuration:\n * '*': href, align, alt, center, width, height, type, controls, target\n * img: src, alt\n * source: src, type\n *\n * DOMPurify's ALLOWED_ATTR is a flat list (no per-tag scoping), so the union\n * of the original allowlist is used. Tags that the prior config never reached\n * (script, iframe, etc.) are stripped wholesale by DOMPurify's default tag\n * allowlist, so per-tag attribute scoping is not security-relevant here.\n *\n * `class` and `title` are additions over the old config (which stripped both):\n * - class: mdRenderer.ts emits `hljs`/`language-*` on code blocks (so the\n * highlight.js solarized-dark stylesheet applies) and `footnote-ref`/\n * `footnote-backref` on footnotes. Stripping it left those styles dead.\n * - title: link/image tooltips and the markdown-it abbr plugin (`<abbr title>`).\n * Both are inert in admin-authored content behind the tag allowlist; neither\n * can escalate.\n */\nconst ALLOWED_ATTR = [\n 'href',\n 'src',\n 'alt',\n 'align',\n 'center',\n 'width',\n 'height',\n 'type',\n 'controls',\n 'target',\n 'class',\n 'title',\n];\n\n/**\n * URL scheme allowlist: http(s), ftp, mailto, tel, plus protocol-relative,\n * fragment, and relative URLs. Mirrors sanitize-html's prior allowedSchemes.\n */\nconst ALLOWED_URI_REGEXP = /^(?:(?:https?|ftp|mailto|tel):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i;\n\n/**\n * DOMPurify permits `data:` URIs on media tags (img/source/video/audio)\n * through its internal DATA_URI_TAGS allowlist, *bypassing* ALLOWED_URI_REGEXP.\n * The prior sanitize-html config stripped every `data:` URI, so strip them here\n * too for parity.\n */\nconst URL_ATTRIBUTES = ['src', 'href', 'xlink:href'];\nDOMPurify.addHook('afterSanitizeAttributes', (node) => {\n if (typeof node.getAttribute !== 'function') {\n return;\n }\n for (const attr of URL_ATTRIBUTES) {\n const value = node.getAttribute(attr);\n if (value && /^\\s*data:/i.test(value)) {\n node.removeAttribute(attr);\n }\n }\n});\n\nconst sanitize = (html: string): string =>\n DOMPurify.sanitize(html, {\n ALLOWED_ATTR,\n ALLOWED_URI_REGEXP,\n ALLOW_DATA_ATTR: false,\n });\n\nexport { sanitize };\n"],"names":["DOMPurify","createDOMPurify","window","ALLOWED_ATTR","ALLOWED_URI_REGEXP","URL_ATTRIBUTES","addHook","node","getAttribute","attr","value","test","removeAttribute","sanitize","html","ALLOW_DATA_ATTR"],"mappings":";;AAEA;AACA;AACA,MAAMA,YAAYC,eAAAA,CAAgBC,MAAAA,CAAAA;AAElC;;;;;;;;;;;;;;;;;;AAkBC,IACD,MAAMC,YAAAA,GAAe;AACnB,IAAA,MAAA;AACA,IAAA,KAAA;AACA,IAAA,KAAA;AACA,IAAA,OAAA;AACA,IAAA,QAAA;AACA,IAAA,OAAA;AACA,IAAA,QAAA;AACA,IAAA,MAAA;AACA,IAAA,UAAA;AACA,IAAA,QAAA;AACA,IAAA,OAAA;AACA,IAAA;AACD,CAAA;AAED;;;AAGC,IACD,MAAMC,kBAAAA,GAAqB,qEAAA;AAE3B;;;;;AAKC,IACD,MAAMC,cAAAA,GAAiB;AAAC,IAAA,KAAA;AAAO,IAAA,MAAA;AAAQ,IAAA;AAAa,CAAA;AACpDL,SAAAA,CAAUM,OAAO,CAAC,yBAAA,EAA2B,CAACC,IAAAA,GAAAA;AAC5C,IAAA,IAAI,OAAOA,IAAAA,CAAKC,YAAY,KAAK,UAAA,EAAY;AAC3C,QAAA;AACF,IAAA;IACA,KAAK,MAAMC,QAAQJ,cAAAA,CAAgB;QACjC,MAAMK,KAAAA,GAAQH,IAAAA,CAAKC,YAAY,CAACC,IAAAA,CAAAA;AAChC,QAAA,IAAIC,KAAAA,IAAS,YAAA,CAAaC,IAAI,CAACD,KAAAA,CAAAA,EAAQ;AACrCH,YAAAA,IAAAA,CAAKK,eAAe,CAACH,IAAAA,CAAAA;AACvB,QAAA;AACF,IAAA;AACF,CAAA,CAAA;AAEA,MAAMI,WAAW,CAACC,IAAAA,GAChBd,SAAAA,CAAUa,QAAQ,CAACC,IAAAA,EAAM;AACvBX,QAAAA,YAAAA;AACAC,QAAAA,kBAAAA;QACAW,eAAAA,EAAiB;AACnB,KAAA;;;;"}
|
|
@@ -43,11 +43,6 @@ const ListConfiguration = ()=>{
|
|
|
43
43
|
const { model, collectionType, schema } = useDocument.useDoc();
|
|
44
44
|
const { isLoading: isLoadingLayout, list, edit, listViewConversionContext } = useDocumentLayout.useDocLayout();
|
|
45
45
|
const [displayedHeaderNames, setDisplayedHeaderNames] = strapiAdmin.useScopedPersistentState(`STRAPI_LIST_VIEW_DISPLAYED_HEADERS:${model}`, null);
|
|
46
|
-
const { metadata } = contentTypes.useGetContentTypeConfigurationQuery(model, {
|
|
47
|
-
selectFromResult: ({ data })=>({
|
|
48
|
-
metadata: data?.contentType.metadatas ?? {}
|
|
49
|
-
})
|
|
50
|
-
});
|
|
51
46
|
const [updateContentTypeConfiguration] = contentTypes.useUpdateContentTypeConfigurationMutation();
|
|
52
47
|
const handleSubmit = async (data)=>{
|
|
53
48
|
try {
|
|
@@ -112,7 +107,7 @@ const ListConfiguration = ()=>{
|
|
|
112
107
|
const initialValues = React__namespace.useMemo(()=>{
|
|
113
108
|
const headerNames = displayedHeaderNames && displayedHeaderNames.length > 0 ? displayedHeaderNames : list.layout.map((field)=>field.name);
|
|
114
109
|
const headerMetadatas = headerNames.reduce((acc, name)=>{
|
|
115
|
-
acc[name] =
|
|
110
|
+
acc[name] = list.metadatas[name] ?? {
|
|
116
111
|
label: name
|
|
117
112
|
};
|
|
118
113
|
return acc;
|
|
@@ -137,7 +132,6 @@ const ListConfiguration = ()=>{
|
|
|
137
132
|
list,
|
|
138
133
|
displayedHeaderNames,
|
|
139
134
|
schema,
|
|
140
|
-
metadata,
|
|
141
135
|
listViewConversionContext
|
|
142
136
|
]);
|
|
143
137
|
if (collectionType === collections.SINGLE_TYPES) {
|
|
@@ -180,7 +174,9 @@ const ListConfiguration = ()=>{
|
|
|
180
174
|
children: [
|
|
181
175
|
/*#__PURE__*/ jsxRuntime.jsx(Settings.Settings, {}),
|
|
182
176
|
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Divider, {}),
|
|
183
|
-
/*#__PURE__*/ jsxRuntime.jsx(SortDisplayedFields.SortDisplayedFields, {
|
|
177
|
+
/*#__PURE__*/ jsxRuntime.jsx(SortDisplayedFields.SortDisplayedFields, {
|
|
178
|
+
metadatas: list.metadatas
|
|
179
|
+
})
|
|
184
180
|
]
|
|
185
181
|
})
|
|
186
182
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListConfigurationPage.js","sources":["../../../../admin/src/pages/ListConfiguration/ListConfigurationPage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Form,\n type FormProps,\n useNotification,\n useScopedPersistentState,\n useTracking,\n useAPIErrorHandler,\n Page,\n Layouts,\n} from '@strapi/admin/strapi-admin';\nimport { Divider, Flex, Main } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { Navigate, useParams } from 'react-router-dom';\n\nimport { SINGLE_TYPES } from '../../constants/collections';\nimport { useDoc } from '../../hooks/useDocument';\nimport {\n convertListLayoutToFieldLayouts,\n type ListFieldLayout,\n type ListLayout,\n useDocLayout,\n} from '../../hooks/useDocumentLayout';\nimport { useTypedSelector } from '../../modules/hooks';\nimport {\n useGetContentTypeConfigurationQuery,\n useUpdateContentTypeConfigurationMutation,\n} from '../../services/contentTypes';\nimport { setIn } from '../../utils/objects';\n\nimport { Header } from './components/Header';\nimport { Settings } from './components/Settings';\nimport { SortDisplayedFields } from './components/SortDisplayedFields';\n\nimport type { Metadatas } from '../../../../shared/contracts/content-types';\n\ninterface FormData extends Pick<ListLayout, 'settings'> {\n layout: Array<Pick<ListFieldLayout, 'sortable' | 'name'> & { label: string }>;\n}\n\nconst ListConfiguration = () => {\n const { formatMessage } = useIntl();\n const { trackUsage } = useTracking();\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n\n const { model, collectionType, schema } = useDoc();\n\n const { isLoading: isLoadingLayout, list, edit, listViewConversionContext } = useDocLayout();\n const [displayedHeaderNames, setDisplayedHeaderNames] = useScopedPersistentState<string[] | null>(\n `STRAPI_LIST_VIEW_DISPLAYED_HEADERS:${model}`,\n null\n );\n\n const { metadata } = useGetContentTypeConfigurationQuery(model, {\n selectFromResult: ({ data }) => ({\n metadata: data?.contentType.metadatas ?? {},\n }),\n });\n\n const [updateContentTypeConfiguration] = useUpdateContentTypeConfigurationMutation();\n const handleSubmit: FormProps<FormData>['onSubmit'] = async (data) => {\n try {\n trackUsage('willSaveContentTypeLayout');\n const layoutData = data.layout ?? [];\n /**\n * We reconstruct the metadatas object by taking the existing edit metadatas\n * and re-merging that by attribute name with the current list metadatas, whilst overwriting\n * the data from the form we've built.\n */\n const meta = Object.entries(edit.metadatas).reduce<Metadatas>((acc, [name, editMeta]) => {\n const { mainField: _mainField, ...listMeta } = list.metadatas[name];\n\n const { label, sortable } = layoutData.find((field) => field.name === name) ?? {};\n\n acc[name] = {\n edit: editMeta,\n list: {\n ...listMeta,\n label: label || listMeta.label,\n sortable: sortable || listMeta.sortable,\n },\n };\n\n return acc;\n }, {});\n\n const res = await updateContentTypeConfiguration({\n layouts: {\n edit: edit.layout.flatMap((panel) =>\n panel.map((row) => row.map(({ name, size }) => ({ name, size })))\n ),\n list: layoutData.map((field) => field.name),\n },\n settings: setIn(data.settings, 'displayName', undefined),\n metadatas: meta,\n uid: model,\n });\n\n if ('data' in res) {\n setDisplayedHeaderNames(layoutData.map((field) => field.name));\n trackUsage('didEditListSettings');\n toggleNotification({\n type: 'success',\n message: formatMessage({ id: 'notification.success.saved', defaultMessage: 'Saved' }),\n });\n } else {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(res.error),\n });\n }\n } catch (err) {\n console.error(err);\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n const initialValues = React.useMemo(() => {\n const headerNames =\n displayedHeaderNames && displayedHeaderNames.length > 0\n ? displayedHeaderNames\n : list.layout.map((field) => field.name);\n\n const headerMetadatas = headerNames.reduce<ListLayout['metadatas']>((acc, name) => {\n acc[name] = metadata[name]?.list ?? list.metadatas[name] ?? { label: name };\n return acc;\n }, {});\n\n /**\n * Same context as `formatListLayout` / `ListViewPage#displayedHeaders` so `getMainField`\n * can resolve component and relation list columns (see #25509, #25872).\n */\n const listFieldLayouts = listViewConversionContext\n ? convertListLayoutToFieldLayouts(\n headerNames,\n schema?.attributes,\n headerMetadatas,\n {\n configurations: listViewConversionContext.componentConfigurations,\n schemas: listViewConversionContext.componentSchemas,\n },\n listViewConversionContext.contentTypeSchemas\n )\n : convertListLayoutToFieldLayouts(headerNames, schema?.attributes, headerMetadatas);\n\n return {\n layout: listFieldLayouts.map(({ label, sortable, name }) => ({\n label: typeof label === 'string' ? label : formatMessage(label),\n sortable,\n name,\n })),\n settings: list.settings,\n } satisfies FormData;\n }, [formatMessage, list, displayedHeaderNames, schema, metadata, listViewConversionContext]);\n\n if (collectionType === SINGLE_TYPES) {\n return <Navigate to={`/single-types/${model}`} />;\n }\n\n if (isLoadingLayout) {\n return <Page.Loading />;\n }\n\n return (\n <Layouts.Root>\n <Page.Title>{`Configure ${list.settings.displayName} List View`}</Page.Title>\n <Main>\n <Form initialValues={initialValues} onSubmit={handleSubmit} method=\"PUT\">\n <Header\n collectionType={collectionType}\n model={model}\n name={list.settings.displayName ?? ''}\n />\n <Layouts.Content>\n <Flex\n alignItems=\"stretch\"\n background=\"neutral0\"\n direction=\"column\"\n gap={6}\n hasRadius\n shadow=\"tableShadow\"\n paddingTop={6}\n paddingBottom={6}\n paddingLeft={7}\n paddingRight={7}\n position=\"relative\"\n >\n <Settings />\n <Divider />\n <SortDisplayedFields />\n </Flex>\n </Layouts.Content>\n </Form>\n </Main>\n </Layouts.Root>\n );\n};\n\nconst ProtectedListConfiguration = () => {\n const { slug = '' } = useParams<{\n slug: string;\n }>();\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions.contentManager?.collectionTypesConfigurations\n );\n\n return (\n <Page.Protect permissions={permissions}>\n <ListConfiguration key={slug} />\n </Page.Protect>\n );\n};\n\nexport { ProtectedListConfiguration, ListConfiguration };\nexport type { FormData };\n"],"names":["ListConfiguration","formatMessage","useIntl","trackUsage","useTracking","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","model","collectionType","schema","useDoc","isLoading","isLoadingLayout","list","edit","listViewConversionContext","useDocLayout","displayedHeaderNames","setDisplayedHeaderNames","useScopedPersistentState","metadata","useGetContentTypeConfigurationQuery","selectFromResult","data","contentType","metadatas","updateContentTypeConfiguration","useUpdateContentTypeConfigurationMutation","handleSubmit","layoutData","layout","meta","Object","entries","reduce","acc","name","editMeta","mainField","_mainField","listMeta","label","sortable","find","field","res","layouts","flatMap","panel","map","row","size","settings","setIn","undefined","uid","type","message","id","defaultMessage","error","err","console","initialValues","React","useMemo","headerNames","length","headerMetadatas","listFieldLayouts","convertListLayoutToFieldLayouts","attributes","configurations","componentConfigurations","schemas","componentSchemas","contentTypeSchemas","SINGLE_TYPES","_jsx","Navigate","to","Page","Loading","_jsxs","Layouts","Root","Title","displayName","Main","Form","onSubmit","method","Header","Content","Flex","alignItems","background","direction","gap","hasRadius","shadow","paddingTop","paddingBottom","paddingLeft","paddingRight","position","Settings","Divider","SortDisplayedFields","ProtectedListConfiguration","slug","useParams","permissions","useTypedSelector","state","admin_app","contentManager","collectionTypesConfigurations","Protect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ListConfigurationPage.js","sources":["../../../../admin/src/pages/ListConfiguration/ListConfigurationPage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Form,\n type FormProps,\n useNotification,\n useScopedPersistentState,\n useTracking,\n useAPIErrorHandler,\n Page,\n Layouts,\n} from '@strapi/admin/strapi-admin';\nimport { Divider, Flex, Main } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { Navigate, useParams } from 'react-router-dom';\n\nimport { SINGLE_TYPES } from '../../constants/collections';\nimport { useDoc } from '../../hooks/useDocument';\nimport {\n convertListLayoutToFieldLayouts,\n type ListFieldLayout,\n type ListLayout,\n useDocLayout,\n} from '../../hooks/useDocumentLayout';\nimport { useTypedSelector } from '../../modules/hooks';\nimport { useUpdateContentTypeConfigurationMutation } from '../../services/contentTypes';\nimport { setIn } from '../../utils/objects';\n\nimport { Header } from './components/Header';\nimport { Settings } from './components/Settings';\nimport { SortDisplayedFields } from './components/SortDisplayedFields';\n\nimport type { Metadatas } from '../../../../shared/contracts/content-types';\n\ninterface FormData extends Pick<ListLayout, 'settings'> {\n layout: Array<Pick<ListFieldLayout, 'sortable' | 'name'> & { label: string }>;\n}\n\nconst ListConfiguration = () => {\n const { formatMessage } = useIntl();\n const { trackUsage } = useTracking();\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n\n const { model, collectionType, schema } = useDoc();\n\n const { isLoading: isLoadingLayout, list, edit, listViewConversionContext } = useDocLayout();\n const [displayedHeaderNames, setDisplayedHeaderNames] = useScopedPersistentState<string[] | null>(\n `STRAPI_LIST_VIEW_DISPLAYED_HEADERS:${model}`,\n null\n );\n\n const [updateContentTypeConfiguration] = useUpdateContentTypeConfigurationMutation();\n const handleSubmit: FormProps<FormData>['onSubmit'] = async (data) => {\n try {\n trackUsage('willSaveContentTypeLayout');\n const layoutData = data.layout ?? [];\n /**\n * We reconstruct the metadatas object by taking the existing edit metadatas\n * and re-merging that by attribute name with the current list metadatas, whilst overwriting\n * the data from the form we've built.\n */\n const meta = Object.entries(edit.metadatas).reduce<Metadatas>((acc, [name, editMeta]) => {\n const { mainField: _mainField, ...listMeta } = list.metadatas[name];\n\n const { label, sortable } = layoutData.find((field) => field.name === name) ?? {};\n\n acc[name] = {\n edit: editMeta,\n list: {\n ...listMeta,\n label: label || listMeta.label,\n sortable: sortable || listMeta.sortable,\n },\n };\n\n return acc;\n }, {});\n\n const res = await updateContentTypeConfiguration({\n layouts: {\n edit: edit.layout.flatMap((panel) =>\n panel.map((row) => row.map(({ name, size }) => ({ name, size })))\n ),\n list: layoutData.map((field) => field.name),\n },\n settings: setIn(data.settings, 'displayName', undefined),\n metadatas: meta,\n uid: model,\n });\n\n if ('data' in res) {\n setDisplayedHeaderNames(layoutData.map((field) => field.name));\n trackUsage('didEditListSettings');\n toggleNotification({\n type: 'success',\n message: formatMessage({ id: 'notification.success.saved', defaultMessage: 'Saved' }),\n });\n } else {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(res.error),\n });\n }\n } catch (err) {\n console.error(err);\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n const initialValues = React.useMemo(() => {\n const headerNames =\n displayedHeaderNames && displayedHeaderNames.length > 0\n ? displayedHeaderNames\n : list.layout.map((field) => field.name);\n\n const headerMetadatas = headerNames.reduce<ListLayout['metadatas']>((acc, name) => {\n acc[name] = list.metadatas[name] ?? { label: name };\n return acc;\n }, {});\n\n /**\n * Same context as `formatListLayout` / `ListViewPage#displayedHeaders` so `getMainField`\n * can resolve component and relation list columns (see #25509, #25872).\n */\n const listFieldLayouts = listViewConversionContext\n ? convertListLayoutToFieldLayouts(\n headerNames,\n schema?.attributes,\n headerMetadatas,\n {\n configurations: listViewConversionContext.componentConfigurations,\n schemas: listViewConversionContext.componentSchemas,\n },\n listViewConversionContext.contentTypeSchemas\n )\n : convertListLayoutToFieldLayouts(headerNames, schema?.attributes, headerMetadatas);\n\n return {\n layout: listFieldLayouts.map(({ label, sortable, name }) => ({\n label: typeof label === 'string' ? label : formatMessage(label),\n sortable,\n name,\n })),\n settings: list.settings,\n } satisfies FormData;\n }, [formatMessage, list, displayedHeaderNames, schema, listViewConversionContext]);\n\n if (collectionType === SINGLE_TYPES) {\n return <Navigate to={`/single-types/${model}`} />;\n }\n\n if (isLoadingLayout) {\n return <Page.Loading />;\n }\n\n return (\n <Layouts.Root>\n <Page.Title>{`Configure ${list.settings.displayName} List View`}</Page.Title>\n <Main>\n <Form initialValues={initialValues} onSubmit={handleSubmit} method=\"PUT\">\n <Header\n collectionType={collectionType}\n model={model}\n name={list.settings.displayName ?? ''}\n />\n <Layouts.Content>\n <Flex\n alignItems=\"stretch\"\n background=\"neutral0\"\n direction=\"column\"\n gap={6}\n hasRadius\n shadow=\"tableShadow\"\n paddingTop={6}\n paddingBottom={6}\n paddingLeft={7}\n paddingRight={7}\n position=\"relative\"\n >\n <Settings />\n <Divider />\n <SortDisplayedFields metadatas={list.metadatas} />\n </Flex>\n </Layouts.Content>\n </Form>\n </Main>\n </Layouts.Root>\n );\n};\n\nconst ProtectedListConfiguration = () => {\n const { slug = '' } = useParams<{\n slug: string;\n }>();\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions.contentManager?.collectionTypesConfigurations\n );\n\n return (\n <Page.Protect permissions={permissions}>\n <ListConfiguration key={slug} />\n </Page.Protect>\n );\n};\n\nexport { ProtectedListConfiguration, ListConfiguration };\nexport type { FormData };\n"],"names":["ListConfiguration","formatMessage","useIntl","trackUsage","useTracking","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","model","collectionType","schema","useDoc","isLoading","isLoadingLayout","list","edit","listViewConversionContext","useDocLayout","displayedHeaderNames","setDisplayedHeaderNames","useScopedPersistentState","updateContentTypeConfiguration","useUpdateContentTypeConfigurationMutation","handleSubmit","data","layoutData","layout","meta","Object","entries","metadatas","reduce","acc","name","editMeta","mainField","_mainField","listMeta","label","sortable","find","field","res","layouts","flatMap","panel","map","row","size","settings","setIn","undefined","uid","type","message","id","defaultMessage","error","err","console","initialValues","React","useMemo","headerNames","length","headerMetadatas","listFieldLayouts","convertListLayoutToFieldLayouts","attributes","configurations","componentConfigurations","schemas","componentSchemas","contentTypeSchemas","SINGLE_TYPES","_jsx","Navigate","to","Page","Loading","_jsxs","Layouts","Root","Title","displayName","Main","Form","onSubmit","method","Header","Content","Flex","alignItems","background","direction","gap","hasRadius","shadow","paddingTop","paddingBottom","paddingLeft","paddingRight","position","Settings","Divider","SortDisplayedFields","ProtectedListConfiguration","slug","useParams","permissions","useTypedSelector","state","admin_app","contentManager","collectionTypesConfigurations","Protect"],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ import { SINGLE_TYPES } from '../../constants/collections.mjs';
|
|
|
8
8
|
import { useDoc } from '../../hooks/useDocument.mjs';
|
|
9
9
|
import { useDocLayout, convertListLayoutToFieldLayouts } from '../../hooks/useDocumentLayout.mjs';
|
|
10
10
|
import { useTypedSelector } from '../../modules/hooks.mjs';
|
|
11
|
-
import {
|
|
11
|
+
import { useUpdateContentTypeConfigurationMutation } from '../../services/contentTypes.mjs';
|
|
12
12
|
import { setIn } from '../../utils/objects.mjs';
|
|
13
13
|
import { Header } from './components/Header.mjs';
|
|
14
14
|
import { Settings } from './components/Settings.mjs';
|
|
@@ -22,11 +22,6 @@ const ListConfiguration = ()=>{
|
|
|
22
22
|
const { model, collectionType, schema } = useDoc();
|
|
23
23
|
const { isLoading: isLoadingLayout, list, edit, listViewConversionContext } = useDocLayout();
|
|
24
24
|
const [displayedHeaderNames, setDisplayedHeaderNames] = useScopedPersistentState(`STRAPI_LIST_VIEW_DISPLAYED_HEADERS:${model}`, null);
|
|
25
|
-
const { metadata } = useGetContentTypeConfigurationQuery(model, {
|
|
26
|
-
selectFromResult: ({ data })=>({
|
|
27
|
-
metadata: data?.contentType.metadatas ?? {}
|
|
28
|
-
})
|
|
29
|
-
});
|
|
30
25
|
const [updateContentTypeConfiguration] = useUpdateContentTypeConfigurationMutation();
|
|
31
26
|
const handleSubmit = async (data)=>{
|
|
32
27
|
try {
|
|
@@ -91,7 +86,7 @@ const ListConfiguration = ()=>{
|
|
|
91
86
|
const initialValues = React.useMemo(()=>{
|
|
92
87
|
const headerNames = displayedHeaderNames && displayedHeaderNames.length > 0 ? displayedHeaderNames : list.layout.map((field)=>field.name);
|
|
93
88
|
const headerMetadatas = headerNames.reduce((acc, name)=>{
|
|
94
|
-
acc[name] =
|
|
89
|
+
acc[name] = list.metadatas[name] ?? {
|
|
95
90
|
label: name
|
|
96
91
|
};
|
|
97
92
|
return acc;
|
|
@@ -116,7 +111,6 @@ const ListConfiguration = ()=>{
|
|
|
116
111
|
list,
|
|
117
112
|
displayedHeaderNames,
|
|
118
113
|
schema,
|
|
119
|
-
metadata,
|
|
120
114
|
listViewConversionContext
|
|
121
115
|
]);
|
|
122
116
|
if (collectionType === SINGLE_TYPES) {
|
|
@@ -159,7 +153,9 @@ const ListConfiguration = ()=>{
|
|
|
159
153
|
children: [
|
|
160
154
|
/*#__PURE__*/ jsx(Settings, {}),
|
|
161
155
|
/*#__PURE__*/ jsx(Divider, {}),
|
|
162
|
-
/*#__PURE__*/ jsx(SortDisplayedFields, {
|
|
156
|
+
/*#__PURE__*/ jsx(SortDisplayedFields, {
|
|
157
|
+
metadatas: list.metadatas
|
|
158
|
+
})
|
|
163
159
|
]
|
|
164
160
|
})
|
|
165
161
|
})
|