@strapi/content-manager 5.47.1 → 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/Blocks/Code.js +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.mjs +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.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/Component/Input.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Input.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/Component/Input.d.ts +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/homepage/services/homepage-query-utils.js +56 -0
- package/dist/server/homepage/services/homepage-query-utils.js.map +1 -0
- package/dist/server/homepage/services/homepage-query-utils.mjs +50 -0
- package/dist/server/homepage/services/homepage-query-utils.mjs.map +1 -0
- package/dist/server/homepage/services/homepage.js +29 -29
- package/dist/server/homepage/services/homepage.js.map +1 -1
- package/dist/server/homepage/services/homepage.mjs +29 -29
- package/dist/server/homepage/services/homepage.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/homepage/services/homepage-query-utils.d.ts +28 -0
- package/dist/server/src/homepage/services/homepage-query-utils.d.ts.map +1 -0
- package/dist/server/src/homepage/services/homepage.d.ts.map +1 -1
- package/package.json +8 -8
|
@@ -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
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListConfigurationPage.mjs","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.mjs","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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"}
|
|
@@ -7,7 +7,6 @@ var designSystem = require('@strapi/design-system');
|
|
|
7
7
|
var Icons = require('@strapi/icons');
|
|
8
8
|
var reactIntl = require('react-intl');
|
|
9
9
|
var useDocument = require('../../../hooks/useDocument.js');
|
|
10
|
-
var contentTypes = require('../../../services/contentTypes.js');
|
|
11
10
|
var attributes = require('../../../utils/attributes.js');
|
|
12
11
|
var translations = require('../../../utils/translations.js');
|
|
13
12
|
var DraggableCard = require('./DraggableCard.js');
|
|
@@ -31,9 +30,9 @@ function _interopNamespaceDefault(e) {
|
|
|
31
30
|
|
|
32
31
|
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
33
32
|
|
|
34
|
-
const SortDisplayedFields = ()=>{
|
|
33
|
+
const SortDisplayedFields = ({ metadatas })=>{
|
|
35
34
|
const { formatMessage } = reactIntl.useIntl();
|
|
36
|
-
const {
|
|
35
|
+
const { schema } = useDocument.useDoc();
|
|
37
36
|
const [isDraggingSibling, setIsDraggingSibling] = React__namespace.useState(false);
|
|
38
37
|
const [lastAction, setLastAction] = React__namespace.useState(null);
|
|
39
38
|
const scrollableContainerRef = React__namespace.useRef(null);
|
|
@@ -41,11 +40,6 @@ const SortDisplayedFields = ()=>{
|
|
|
41
40
|
const addFieldRow = strapiAdmin.useForm('SortDisplayedFields', (state)=>state.addFieldRow);
|
|
42
41
|
const removeFieldRow = strapiAdmin.useForm('SortDisplayedFields', (state)=>state.removeFieldRow);
|
|
43
42
|
const moveFieldRow = strapiAdmin.useForm('SortDisplayedFields', (state)=>state.moveFieldRow);
|
|
44
|
-
const { metadata: allMetadata } = contentTypes.useGetContentTypeConfigurationQuery(model, {
|
|
45
|
-
selectFromResult: ({ data })=>({
|
|
46
|
-
metadata: data?.contentType.metadatas ?? {}
|
|
47
|
-
})
|
|
48
|
-
});
|
|
49
43
|
/**
|
|
50
44
|
* This is our list of fields that are not displayed in the current layout
|
|
51
45
|
* so we create their default state to be added to the layout.
|
|
@@ -56,7 +50,9 @@ const SortDisplayedFields = ()=>{
|
|
|
56
50
|
const displayedFieldNames = values.map((field)=>field.name);
|
|
57
51
|
return Object.entries(schema.attributes).reduce((acc, [name, attribute])=>{
|
|
58
52
|
if (!displayedFieldNames.includes(name) && attributes.checkIfAttributeIsDisplayable(attribute)) {
|
|
59
|
-
const
|
|
53
|
+
const metadata = metadatas[name] || {
|
|
54
|
+
label: name
|
|
55
|
+
};
|
|
60
56
|
acc.push({
|
|
61
57
|
name,
|
|
62
58
|
label: metadata.label || name,
|
|
@@ -66,7 +62,7 @@ const SortDisplayedFields = ()=>{
|
|
|
66
62
|
return acc;
|
|
67
63
|
}, []);
|
|
68
64
|
}, [
|
|
69
|
-
|
|
65
|
+
metadatas,
|
|
70
66
|
values,
|
|
71
67
|
schema
|
|
72
68
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SortDisplayedFields.js","sources":["../../../../../admin/src/pages/ListConfiguration/components/SortDisplayedFields.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useForm } from '@strapi/admin/strapi-admin';\nimport { Box, Flex, VisuallyHidden, Typography, Menu } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useDoc } from '../../../hooks/useDocument';\nimport { useGetContentTypeConfigurationQuery } from '../../../services/contentTypes';\nimport { checkIfAttributeIsDisplayable } from '../../../utils/attributes';\nimport { getTranslation } from '../../../utils/translations';\n\nimport { DraggableCard, DraggableCardProps } from './DraggableCard';\n\nimport type { ListLayout } from '../../../hooks/useDocumentLayout';\nimport type { FormData } from '../ListConfigurationPage';\n\ninterface SortDisplayedFieldsProps extends Pick<ListLayout, 'layout'> {}\n\nconst SortDisplayedFields = () => {\n const { formatMessage } = useIntl();\n const { model, schema } = useDoc();\n const [isDraggingSibling, setIsDraggingSibling] = React.useState(false);\n const [lastAction, setLastAction] = React.useState<string | null>(null);\n const scrollableContainerRef = React.useRef<HTMLDivElement>(null);\n\n const values = useForm<FormData['layout']>(\n 'SortDisplayedFields',\n (state) => state.values.layout ?? []\n );\n const addFieldRow = useForm('SortDisplayedFields', (state) => state.addFieldRow);\n const removeFieldRow = useForm('SortDisplayedFields', (state) => state.removeFieldRow);\n const moveFieldRow = useForm('SortDisplayedFields', (state) => state.moveFieldRow);\n\n const { metadata: allMetadata } = useGetContentTypeConfigurationQuery(model, {\n selectFromResult: ({ data }) => ({ metadata: data?.contentType.metadatas ?? {} }),\n });\n\n /**\n * This is our list of fields that are not displayed in the current layout\n * so we create their default state to be added to the layout.\n */\n const nonDisplayedFields = React.useMemo(() => {\n if (!schema) {\n return [];\n }\n\n const displayedFieldNames = values.map((field) => field.name);\n\n return Object.entries(schema.attributes).reduce<Array<FormData['layout'][number]>>(\n (acc, [name, attribute]) => {\n if (!displayedFieldNames.includes(name) && checkIfAttributeIsDisplayable(attribute)) {\n const { list: metadata } = allMetadata[name];\n\n acc.push({\n name,\n label: metadata.label || name,\n sortable: metadata.sortable,\n });\n }\n\n return acc;\n },\n []\n );\n }, [allMetadata, values, schema]);\n\n const handleAddField = (field: FormData['layout'][number]) => {\n setLastAction('add');\n addFieldRow('layout', field);\n };\n\n const handleRemoveField = (index: number) => {\n setLastAction('remove');\n removeFieldRow('layout', index);\n };\n\n const handleMoveField: DraggableCardProps['onMoveField'] = (dragIndex, hoverIndex) => {\n moveFieldRow('layout', dragIndex, hoverIndex);\n };\n\n React.useEffect(() => {\n if (lastAction === 'add' && scrollableContainerRef?.current) {\n scrollableContainerRef.current.scrollLeft = scrollableContainerRef.current.scrollWidth;\n }\n }, [lastAction]);\n\n return (\n <Flex alignItems=\"stretch\" direction=\"column\" gap={4}>\n <Typography variant=\"delta\" tag=\"h2\">\n {formatMessage({\n id: getTranslation('containers.SettingPage.view'),\n defaultMessage: 'View',\n })}\n </Typography>\n\n <Flex padding={4} borderColor=\"neutral300\" borderStyle=\"dashed\" borderWidth=\"1px\" hasRadius>\n <Box flex=\"1\" overflow=\"auto hidden\" ref={scrollableContainerRef}>\n <Flex gap={3}>\n {values.map((field, index) => (\n <DraggableCard\n key={field.name}\n index={index}\n isDraggingSibling={isDraggingSibling}\n onMoveField={handleMoveField}\n onRemoveField={() => handleRemoveField(index)}\n setIsDraggingSibling={setIsDraggingSibling}\n {...field}\n attribute={schema!.attributes[field.name]}\n label={typeof field.label === 'object' ? formatMessage(field.label) : field.label}\n />\n ))}\n </Flex>\n </Box>\n\n <Menu.Root>\n <Menu.Trigger\n paddingLeft={2}\n paddingRight={2}\n justifyContent=\"center\"\n endIcon={null}\n disabled={nonDisplayedFields.length === 0}\n variant=\"tertiary\"\n >\n <VisuallyHidden tag=\"span\">\n {formatMessage({\n id: getTranslation('components.FieldSelect.label'),\n defaultMessage: 'Add a field',\n })}\n </VisuallyHidden>\n <Plus aria-hidden focusable={false} style={{ position: 'relative', top: 2 }} />\n </Menu.Trigger>\n <Menu.Content>\n {nonDisplayedFields.map((field) => (\n <Menu.Item key={field.name} onSelect={() => handleAddField(field)}>\n {typeof field.label === 'object' ? formatMessage(field.label) : field.label}\n </Menu.Item>\n ))}\n </Menu.Content>\n </Menu.Root>\n </Flex>\n </Flex>\n );\n};\n\nexport { SortDisplayedFields };\nexport type { SortDisplayedFieldsProps };\n"],"names":["SortDisplayedFields","formatMessage","useIntl","model","schema","useDoc","isDraggingSibling","setIsDraggingSibling","React","useState","lastAction","setLastAction","scrollableContainerRef","useRef","values","useForm","state","layout","addFieldRow","removeFieldRow","moveFieldRow","metadata","allMetadata","useGetContentTypeConfigurationQuery","selectFromResult","data","contentType","metadatas","nonDisplayedFields","useMemo","displayedFieldNames","map","field","name","Object","entries","attributes","reduce","acc","attribute","includes","checkIfAttributeIsDisplayable","list","push","label","sortable","handleAddField","handleRemoveField","index","handleMoveField","dragIndex","hoverIndex","useEffect","current","scrollLeft","scrollWidth","_jsxs","Flex","alignItems","direction","gap","_jsx","Typography","variant","tag","id","getTranslation","defaultMessage","padding","borderColor","borderStyle","borderWidth","hasRadius","Box","flex","overflow","ref","DraggableCard","onMoveField","onRemoveField","Menu","Root","Trigger","paddingLeft","paddingRight","justifyContent","endIcon","disabled","length","VisuallyHidden","Plus","aria-hidden","focusable","style","position","top","Content","Item","onSelect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SortDisplayedFields.js","sources":["../../../../../admin/src/pages/ListConfiguration/components/SortDisplayedFields.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useForm } from '@strapi/admin/strapi-admin';\nimport { Box, Flex, VisuallyHidden, Typography, Menu } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useDoc } from '../../../hooks/useDocument';\nimport { checkIfAttributeIsDisplayable } from '../../../utils/attributes';\nimport { getTranslation } from '../../../utils/translations';\n\nimport { DraggableCard, DraggableCardProps } from './DraggableCard';\n\nimport type { ListLayout } from '../../../hooks/useDocumentLayout';\nimport type { FormData } from '../ListConfigurationPage';\n\ninterface SortDisplayedFieldsProps extends Pick<ListLayout, 'metadatas'> {}\n\nconst SortDisplayedFields = ({ metadatas }: SortDisplayedFieldsProps) => {\n const { formatMessage } = useIntl();\n const { schema } = useDoc();\n const [isDraggingSibling, setIsDraggingSibling] = React.useState(false);\n const [lastAction, setLastAction] = React.useState<string | null>(null);\n const scrollableContainerRef = React.useRef<HTMLDivElement>(null);\n\n const values = useForm<FormData['layout']>(\n 'SortDisplayedFields',\n (state) => state.values.layout ?? []\n );\n const addFieldRow = useForm('SortDisplayedFields', (state) => state.addFieldRow);\n const removeFieldRow = useForm('SortDisplayedFields', (state) => state.removeFieldRow);\n const moveFieldRow = useForm('SortDisplayedFields', (state) => state.moveFieldRow);\n\n /**\n * This is our list of fields that are not displayed in the current layout\n * so we create their default state to be added to the layout.\n */\n const nonDisplayedFields = React.useMemo(() => {\n if (!schema) {\n return [];\n }\n\n const displayedFieldNames = values.map((field) => field.name);\n\n return Object.entries(schema.attributes).reduce<Array<FormData['layout'][number]>>(\n (acc, [name, attribute]) => {\n if (!displayedFieldNames.includes(name) && checkIfAttributeIsDisplayable(attribute)) {\n const metadata = metadatas[name] || { label: name };\n\n acc.push({\n name,\n label: metadata.label || name,\n sortable: metadata.sortable,\n });\n }\n\n return acc;\n },\n []\n );\n }, [metadatas, values, schema]);\n\n const handleAddField = (field: FormData['layout'][number]) => {\n setLastAction('add');\n addFieldRow('layout', field);\n };\n\n const handleRemoveField = (index: number) => {\n setLastAction('remove');\n removeFieldRow('layout', index);\n };\n\n const handleMoveField: DraggableCardProps['onMoveField'] = (dragIndex, hoverIndex) => {\n moveFieldRow('layout', dragIndex, hoverIndex);\n };\n\n React.useEffect(() => {\n if (lastAction === 'add' && scrollableContainerRef?.current) {\n scrollableContainerRef.current.scrollLeft = scrollableContainerRef.current.scrollWidth;\n }\n }, [lastAction]);\n\n return (\n <Flex alignItems=\"stretch\" direction=\"column\" gap={4}>\n <Typography variant=\"delta\" tag=\"h2\">\n {formatMessage({\n id: getTranslation('containers.SettingPage.view'),\n defaultMessage: 'View',\n })}\n </Typography>\n\n <Flex padding={4} borderColor=\"neutral300\" borderStyle=\"dashed\" borderWidth=\"1px\" hasRadius>\n <Box flex=\"1\" overflow=\"auto hidden\" ref={scrollableContainerRef}>\n <Flex gap={3}>\n {values.map((field, index) => (\n <DraggableCard\n key={field.name}\n index={index}\n isDraggingSibling={isDraggingSibling}\n onMoveField={handleMoveField}\n onRemoveField={() => handleRemoveField(index)}\n setIsDraggingSibling={setIsDraggingSibling}\n {...field}\n attribute={schema!.attributes[field.name]}\n label={typeof field.label === 'object' ? formatMessage(field.label) : field.label}\n />\n ))}\n </Flex>\n </Box>\n\n <Menu.Root>\n <Menu.Trigger\n paddingLeft={2}\n paddingRight={2}\n justifyContent=\"center\"\n endIcon={null}\n disabled={nonDisplayedFields.length === 0}\n variant=\"tertiary\"\n >\n <VisuallyHidden tag=\"span\">\n {formatMessage({\n id: getTranslation('components.FieldSelect.label'),\n defaultMessage: 'Add a field',\n })}\n </VisuallyHidden>\n <Plus aria-hidden focusable={false} style={{ position: 'relative', top: 2 }} />\n </Menu.Trigger>\n <Menu.Content>\n {nonDisplayedFields.map((field) => (\n <Menu.Item key={field.name} onSelect={() => handleAddField(field)}>\n {typeof field.label === 'object' ? formatMessage(field.label) : field.label}\n </Menu.Item>\n ))}\n </Menu.Content>\n </Menu.Root>\n </Flex>\n </Flex>\n );\n};\n\nexport { SortDisplayedFields };\nexport type { SortDisplayedFieldsProps };\n"],"names":["SortDisplayedFields","metadatas","formatMessage","useIntl","schema","useDoc","isDraggingSibling","setIsDraggingSibling","React","useState","lastAction","setLastAction","scrollableContainerRef","useRef","values","useForm","state","layout","addFieldRow","removeFieldRow","moveFieldRow","nonDisplayedFields","useMemo","displayedFieldNames","map","field","name","Object","entries","attributes","reduce","acc","attribute","includes","checkIfAttributeIsDisplayable","metadata","label","push","sortable","handleAddField","handleRemoveField","index","handleMoveField","dragIndex","hoverIndex","useEffect","current","scrollLeft","scrollWidth","_jsxs","Flex","alignItems","direction","gap","_jsx","Typography","variant","tag","id","getTranslation","defaultMessage","padding","borderColor","borderStyle","borderWidth","hasRadius","Box","flex","overflow","ref","DraggableCard","onMoveField","onRemoveField","Menu","Root","Trigger","paddingLeft","paddingRight","justifyContent","endIcon","disabled","length","VisuallyHidden","Plus","aria-hidden","focusable","style","position","top","Content","Item","onSelect"],"mappings":"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"}
|
|
@@ -5,14 +5,13 @@ import { Flex, Typography, Box, Menu, VisuallyHidden } from '@strapi/design-syst
|
|
|
5
5
|
import { Plus } from '@strapi/icons';
|
|
6
6
|
import { useIntl } from 'react-intl';
|
|
7
7
|
import { useDoc } from '../../../hooks/useDocument.mjs';
|
|
8
|
-
import { useGetContentTypeConfigurationQuery } from '../../../services/contentTypes.mjs';
|
|
9
8
|
import { checkIfAttributeIsDisplayable } from '../../../utils/attributes.mjs';
|
|
10
9
|
import { getTranslation } from '../../../utils/translations.mjs';
|
|
11
10
|
import { DraggableCard } from './DraggableCard.mjs';
|
|
12
11
|
|
|
13
|
-
const SortDisplayedFields = ()=>{
|
|
12
|
+
const SortDisplayedFields = ({ metadatas })=>{
|
|
14
13
|
const { formatMessage } = useIntl();
|
|
15
|
-
const {
|
|
14
|
+
const { schema } = useDoc();
|
|
16
15
|
const [isDraggingSibling, setIsDraggingSibling] = React.useState(false);
|
|
17
16
|
const [lastAction, setLastAction] = React.useState(null);
|
|
18
17
|
const scrollableContainerRef = React.useRef(null);
|
|
@@ -20,11 +19,6 @@ const SortDisplayedFields = ()=>{
|
|
|
20
19
|
const addFieldRow = useForm('SortDisplayedFields', (state)=>state.addFieldRow);
|
|
21
20
|
const removeFieldRow = useForm('SortDisplayedFields', (state)=>state.removeFieldRow);
|
|
22
21
|
const moveFieldRow = useForm('SortDisplayedFields', (state)=>state.moveFieldRow);
|
|
23
|
-
const { metadata: allMetadata } = useGetContentTypeConfigurationQuery(model, {
|
|
24
|
-
selectFromResult: ({ data })=>({
|
|
25
|
-
metadata: data?.contentType.metadatas ?? {}
|
|
26
|
-
})
|
|
27
|
-
});
|
|
28
22
|
/**
|
|
29
23
|
* This is our list of fields that are not displayed in the current layout
|
|
30
24
|
* so we create their default state to be added to the layout.
|
|
@@ -35,7 +29,9 @@ const SortDisplayedFields = ()=>{
|
|
|
35
29
|
const displayedFieldNames = values.map((field)=>field.name);
|
|
36
30
|
return Object.entries(schema.attributes).reduce((acc, [name, attribute])=>{
|
|
37
31
|
if (!displayedFieldNames.includes(name) && checkIfAttributeIsDisplayable(attribute)) {
|
|
38
|
-
const
|
|
32
|
+
const metadata = metadatas[name] || {
|
|
33
|
+
label: name
|
|
34
|
+
};
|
|
39
35
|
acc.push({
|
|
40
36
|
name,
|
|
41
37
|
label: metadata.label || name,
|
|
@@ -45,7 +41,7 @@ const SortDisplayedFields = ()=>{
|
|
|
45
41
|
return acc;
|
|
46
42
|
}, []);
|
|
47
43
|
}, [
|
|
48
|
-
|
|
44
|
+
metadatas,
|
|
49
45
|
values,
|
|
50
46
|
schema
|
|
51
47
|
]);
|