@strapi/admin 5.12.4 → 5.12.5

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.
Files changed (59) hide show
  1. package/dist/admin/admin/src/StrapiApp.js +2 -0
  2. package/dist/admin/admin/src/StrapiApp.js.map +1 -1
  3. package/dist/admin/admin/src/StrapiApp.mjs +2 -0
  4. package/dist/admin/admin/src/StrapiApp.mjs.map +1 -1
  5. package/dist/admin/admin/src/components/Providers.js +1 -0
  6. package/dist/admin/admin/src/components/Providers.js.map +1 -1
  7. package/dist/admin/admin/src/components/Providers.mjs +1 -0
  8. package/dist/admin/admin/src/components/Providers.mjs.map +1 -1
  9. package/dist/admin/admin/src/{pages/Home/components/Widget.js → components/WidgetHelpers.js} +26 -69
  10. package/dist/admin/admin/src/components/WidgetHelpers.js.map +1 -0
  11. package/dist/admin/admin/src/{pages/Home/components/Widget.mjs → components/WidgetHelpers.mjs} +30 -54
  12. package/dist/admin/admin/src/components/WidgetHelpers.mjs.map +1 -0
  13. package/dist/admin/admin/src/core/apis/CustomFields.js.map +1 -1
  14. package/dist/admin/admin/src/core/apis/CustomFields.mjs.map +1 -1
  15. package/dist/admin/admin/src/core/apis/Widgets.js +34 -0
  16. package/dist/admin/admin/src/core/apis/Widgets.js.map +1 -0
  17. package/dist/admin/admin/src/core/apis/Widgets.mjs +32 -0
  18. package/dist/admin/admin/src/core/apis/Widgets.mjs.map +1 -0
  19. package/dist/admin/admin/src/features/StrapiApp.js.map +1 -1
  20. package/dist/admin/admin/src/features/StrapiApp.mjs.map +1 -1
  21. package/dist/admin/admin/src/pages/Home/HomePage.js +163 -3
  22. package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
  23. package/dist/admin/admin/src/pages/Home/HomePage.mjs +145 -5
  24. package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
  25. package/dist/admin/admin/src/pages/Home/components/ContentManagerWidgets.js +10 -30
  26. package/dist/admin/admin/src/pages/Home/components/ContentManagerWidgets.js.map +1 -1
  27. package/dist/admin/admin/src/pages/Home/components/ContentManagerWidgets.mjs +5 -25
  28. package/dist/admin/admin/src/pages/Home/components/ContentManagerWidgets.mjs.map +1 -1
  29. package/dist/admin/admin/src/services/homepage.js +3 -2
  30. package/dist/admin/admin/src/services/homepage.js.map +1 -1
  31. package/dist/admin/admin/src/services/homepage.mjs +3 -2
  32. package/dist/admin/admin/src/services/homepage.mjs.map +1 -1
  33. package/dist/admin/admin/src/translations/en.json.js +1 -0
  34. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  35. package/dist/admin/admin/src/translations/en.json.mjs +1 -0
  36. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  37. package/dist/admin/admin/tests/utils.js +5 -0
  38. package/dist/admin/admin/tests/utils.js.map +1 -1
  39. package/dist/admin/admin/tests/utils.mjs +5 -0
  40. package/dist/admin/admin/tests/utils.mjs.map +1 -1
  41. package/dist/admin/index.js +2 -0
  42. package/dist/admin/index.js.map +1 -1
  43. package/dist/admin/index.mjs +1 -0
  44. package/dist/admin/index.mjs.map +1 -1
  45. package/dist/admin/src/StrapiApp.d.ts +2 -0
  46. package/dist/admin/src/{pages/Home/components/Widget.d.ts → components/WidgetHelpers.d.ts} +4 -8
  47. package/dist/admin/src/core/apis/Widgets.d.ts +29 -0
  48. package/dist/admin/src/features/StrapiApp.d.ts +1 -1
  49. package/dist/admin/src/index.d.ts +1 -0
  50. package/dist/admin/src/pages/Home/HomePage.d.ts +8 -0
  51. package/dist/server/server/src/services/homepage.js +3 -1
  52. package/dist/server/server/src/services/homepage.js.map +1 -1
  53. package/dist/server/server/src/services/homepage.mjs +3 -1
  54. package/dist/server/server/src/services/homepage.mjs.map +1 -1
  55. package/dist/server/src/services/homepage.d.ts +3 -0
  56. package/dist/server/src/services/homepage.d.ts.map +1 -1
  57. package/package.json +7 -7
  58. package/dist/admin/admin/src/pages/Home/components/Widget.js.map +0 -1
  59. package/dist/admin/admin/src/pages/Home/components/Widget.mjs.map +0 -1
@@ -1,56 +1,9 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
2
- import * as React from 'react';
3
- import { Flex, Typography, Box, Loader } from '@strapi/design-system';
4
- import { PuzzlePiece, WarningCircle } from '@strapi/icons';
5
- import { EmptyDocuments } from '@strapi/icons/symbols';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { Flex, Loader, Typography } from '@strapi/design-system';
3
+ import { WarningCircle } from '@strapi/icons';
4
+ import { EmptyDocuments, EmptyPermissions } from '@strapi/icons/symbols';
6
5
  import { useIntl } from 'react-intl';
7
6
 
8
- const Root = ({ title, icon = PuzzlePiece, children })=>{
9
- const { formatMessage } = useIntl();
10
- const id = React.useId();
11
- const Icon = icon;
12
- return /*#__PURE__*/ jsxs(Flex, {
13
- width: "100%",
14
- hasRadius: true,
15
- direction: "column",
16
- alignItems: "flex-start",
17
- background: "neutral0",
18
- borderColor: "neutral150",
19
- shadow: "tableShadow",
20
- tag: "section",
21
- gap: 4,
22
- padding: 6,
23
- "aria-labelledby": id,
24
- children: [
25
- /*#__PURE__*/ jsxs(Flex, {
26
- direction: "row",
27
- alignItems: "center",
28
- gap: 2,
29
- tag: "header",
30
- children: [
31
- /*#__PURE__*/ jsx(Icon, {
32
- fill: "neutral500",
33
- "aria-hidden": true
34
- }),
35
- /*#__PURE__*/ jsx(Typography, {
36
- textColor: "neutral500",
37
- variant: "sigma",
38
- tag: "h2",
39
- id: id,
40
- children: formatMessage(title)
41
- })
42
- ]
43
- }),
44
- /*#__PURE__*/ jsx(Box, {
45
- width: "100%",
46
- height: "261px",
47
- overflow: "auto",
48
- tag: "main",
49
- children: children
50
- })
51
- ]
52
- });
53
- };
54
7
  const Loading = ({ children })=>{
55
8
  const { formatMessage } = useIntl();
56
9
  return /*#__PURE__*/ jsx(Flex, {
@@ -119,12 +72,35 @@ const NoData = ({ children })=>{
119
72
  ]
120
73
  });
121
74
  };
75
+ const NoPermissions = ({ children })=>{
76
+ const { formatMessage } = useIntl();
77
+ return /*#__PURE__*/ jsxs(Flex, {
78
+ height: "100%",
79
+ direction: "column",
80
+ justifyContent: "center",
81
+ alignItems: "center",
82
+ gap: 6,
83
+ children: [
84
+ /*#__PURE__*/ jsx(EmptyPermissions, {
85
+ width: "16rem",
86
+ height: "8.8rem"
87
+ }),
88
+ /*#__PURE__*/ jsx(Typography, {
89
+ textColor: "neutral600",
90
+ children: children ?? formatMessage({
91
+ id: 'HomePage.widget.no-permissions',
92
+ defaultMessage: 'You don’t have the permission to see this widget'
93
+ })
94
+ })
95
+ ]
96
+ });
97
+ };
122
98
  const Widget = {
123
- Root,
124
99
  Loading,
125
100
  Error,
126
- NoData
101
+ NoData,
102
+ NoPermissions
127
103
  };
128
104
 
129
105
  export { Widget };
130
- //# sourceMappingURL=Widget.mjs.map
106
+ //# sourceMappingURL=WidgetHelpers.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetHelpers.mjs","sources":["../../../../../admin/src/components/WidgetHelpers.tsx"],"sourcesContent":["import { Flex, Loader, Typography } from '@strapi/design-system';\nimport { WarningCircle } from '@strapi/icons';\nimport { EmptyDocuments, EmptyPermissions } from '@strapi/icons/symbols';\nimport { useIntl } from 'react-intl';\n\n/* -------------------------------------------------------------------------------------------------\n * Loading\n * -----------------------------------------------------------------------------------------------*/\n\ninterface LoadingProps {\n children?: string;\n}\n\nconst Loading = ({ children }: LoadingProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <Flex height=\"100%\" justifyContent=\"center\" alignItems=\"center\">\n <Loader>\n {children ??\n formatMessage({\n id: 'HomePage.widget.loading',\n defaultMessage: 'Loading widget content',\n })}\n </Loader>\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Error\n * -----------------------------------------------------------------------------------------------*/\n\ninterface ErrorProps {\n children?: string;\n}\n\nconst Error = ({ children }: ErrorProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <Flex height=\"100%\" direction=\"column\" justifyContent=\"center\" alignItems=\"center\" gap={2}>\n <WarningCircle width=\"3.2rem\" height=\"3.2rem\" fill=\"danger600\" />\n <Typography variant=\"delta\">\n {formatMessage({\n id: 'global.error',\n defaultMessage: 'Something went wrong',\n })}\n </Typography>\n <Typography textColor=\"neutral600\">\n {children ??\n formatMessage({\n id: 'HomePage.widget.error',\n defaultMessage: \"Couldn't load widget content.\",\n })}\n </Typography>\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NoData\n * -----------------------------------------------------------------------------------------------*/\n\ninterface NoDataProps {\n children?: string;\n}\n\nconst NoData = ({ children }: NoDataProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <Flex height=\"100%\" direction=\"column\" justifyContent=\"center\" alignItems=\"center\" gap={6}>\n <EmptyDocuments width=\"16rem\" height=\"8.8rem\" />\n <Typography textColor=\"neutral600\">\n {children ??\n formatMessage({\n id: 'HomePage.widget.no-data',\n defaultMessage: 'No content found.',\n })}\n </Typography>\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NoPermissions\n * -----------------------------------------------------------------------------------------------*/\n\ninterface NoPermissionsProps {\n children?: string;\n}\n\nconst NoPermissions = ({ children }: NoPermissionsProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <Flex height=\"100%\" direction=\"column\" justifyContent=\"center\" alignItems=\"center\" gap={6}>\n <EmptyPermissions width=\"16rem\" height=\"8.8rem\" />\n <Typography textColor=\"neutral600\">\n {children ??\n formatMessage({\n id: 'HomePage.widget.no-permissions',\n defaultMessage: 'You don’t have the permission to see this widget',\n })}\n </Typography>\n </Flex>\n );\n};\n\nconst Widget = {\n Loading,\n Error,\n NoData,\n NoPermissions,\n};\n\nexport { Widget };\n"],"names":["Loading","children","formatMessage","useIntl","_jsx","Flex","height","justifyContent","alignItems","Loader","id","defaultMessage","Error","_jsxs","direction","gap","WarningCircle","width","fill","Typography","variant","textColor","NoData","EmptyDocuments","NoPermissions","EmptyPermissions","Widget"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CustomFields.js","sources":["../../../../../../admin/src/core/apis/CustomFields.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { ComponentType } from 'react';\n\nimport invariant from 'invariant';\n\nimport type { MessageDescriptor, PrimitiveType } from 'react-intl';\nimport type { AnySchema } from 'yup';\n\ntype CustomFieldUID = `plugin::${string}.${string}` | `global::${string}`;\n\ntype CustomFieldOptionInput =\n | 'text'\n | 'checkbox'\n | 'checkbox-with-number-field'\n | 'select-default-boolean'\n | 'date'\n | 'select'\n | 'number'\n | 'boolean-radio-group'\n | 'select-date'\n | 'text-area-enum'\n | 'select-number'\n | 'radio-group';\n\ntype CustomFieldOptionName =\n | 'min'\n | 'minLength'\n | 'max'\n | 'maxLength'\n | 'required'\n | 'regex'\n | 'enum'\n | 'unique'\n | 'private'\n | 'default';\n\ninterface CustomFieldOption {\n intlLabel: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n description: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n name: CustomFieldOptionName;\n type: CustomFieldOptionInput;\n defaultValue?: string | number | boolean | Date;\n}\n\ninterface CustomFieldOptionSection {\n sectionTitle:\n | (MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n })\n | null;\n items: CustomFieldOption[];\n}\n\ninterface CustomFieldOptions {\n base?: (CustomFieldOptionSection | CustomFieldOption)[];\n advanced?: (CustomFieldOptionSection | CustomFieldOption)[];\n validator?: () => Record<string, AnySchema>;\n}\n\ninterface CustomField {\n name: string;\n pluginId?: string;\n type: (typeof ALLOWED_TYPES)[number];\n intlLabel: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n intlDescription: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n icon?: ComponentType;\n components: {\n Input: () => Promise<{ default?: ComponentType }>;\n };\n options?: CustomFieldOptions;\n}\n\nconst ALLOWED_TYPES = [\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'decimal',\n 'email',\n 'enumeration',\n 'float',\n 'integer',\n 'json',\n 'password',\n 'richtext',\n 'string',\n 'text',\n 'time',\n 'uid',\n] as const;\n\nconst ALLOWED_ROOT_LEVEL_OPTIONS = [\n 'min',\n 'minLength',\n 'max',\n 'maxLength',\n 'required',\n 'regex',\n 'enum',\n 'unique',\n 'private',\n 'default',\n] as const;\n\nclass CustomFields {\n customFields: Record<string, CustomField>;\n\n constructor() {\n this.customFields = {};\n }\n\n register = (customFields: CustomField | CustomField[]) => {\n if (Array.isArray(customFields)) {\n // If several custom fields are passed, register them one by one\n customFields.forEach((customField) => {\n this.register(customField);\n });\n } else {\n // Handle individual custom field\n const { name, pluginId, type, intlLabel, intlDescription, components, options } =\n customFields;\n\n // Ensure required attributes are provided\n invariant(name, 'A name must be provided');\n invariant(type, 'A type must be provided');\n invariant(intlLabel, 'An intlLabel must be provided');\n invariant(intlDescription, 'An intlDescription must be provided');\n invariant(components, 'A components object must be provided');\n invariant(components.Input, 'An Input component must be provided');\n\n // Ensure the type is valid\n invariant(\n ALLOWED_TYPES.includes(type),\n `Custom field type: '${type}' is not a valid Strapi type or it can't be used with a Custom Field`\n );\n\n // Ensure name has no special characters\n const isValidObjectKey = /^(?![0-9])[a-zA-Z0-9$_-]+$/g;\n invariant(\n isValidObjectKey.test(name),\n `Custom field name: '${name}' is not a valid object key`\n );\n\n // Ensure options have valid name paths\n const allFormOptions = [...(options?.base || []), ...(options?.advanced || [])];\n\n if (allFormOptions.length) {\n const optionPathValidations = allFormOptions.reduce(optionsValidationReducer, []);\n\n optionPathValidations.forEach(({ isValidOptionPath, errorMessage }) => {\n invariant(isValidOptionPath, errorMessage);\n });\n }\n\n // When no plugin is specified, default to the global namespace\n const uid: CustomFieldUID = pluginId ? `plugin::${pluginId}.${name}` : `global::${name}`;\n\n // Ensure the uid is unique\n const uidAlreadyUsed = Object.prototype.hasOwnProperty.call(this.customFields, uid);\n invariant(!uidAlreadyUsed, `Custom field: '${uid}' has already been registered`);\n\n this.customFields[uid] = customFields;\n }\n };\n\n getAll = () => {\n return this.customFields;\n };\n\n get = (uid: string): CustomField | undefined => {\n return this.customFields[uid];\n };\n}\n\ninterface OptionValidation {\n isValidOptionPath: boolean;\n errorMessage: string;\n}\n\nconst optionsValidationReducer = (\n acc: OptionValidation[],\n option: CustomFieldOptionSection | CustomFieldOption\n): OptionValidation[] => {\n if ('items' in option) {\n return option.items.reduce(optionsValidationReducer, acc);\n }\n\n if (!option.name) {\n acc.push({\n isValidOptionPath: false,\n errorMessage: \"The 'name' property is required on an options object\",\n });\n } else {\n acc.push({\n isValidOptionPath:\n option.name.startsWith('options') || ALLOWED_ROOT_LEVEL_OPTIONS.includes(option.name),\n errorMessage: `'${option.name}' must be prefixed with 'options.'`,\n });\n }\n\n return acc;\n};\n\nexport { type CustomField, CustomFields };\n"],"names":["ALLOWED_TYPES","ALLOWED_ROOT_LEVEL_OPTIONS","CustomFields","constructor","register","customFields","Array","isArray","forEach","customField","name","pluginId","type","intlLabel","intlDescription","components","options","invariant","Input","includes","isValidObjectKey","test","allFormOptions","base","advanced","length","optionPathValidations","reduce","optionsValidationReducer","isValidOptionPath","errorMessage","uid","uidAlreadyUsed","Object","prototype","hasOwnProperty","call","getAll","get","acc","option","items","push","startsWith"],"mappings":"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"}
1
+ {"version":3,"file":"CustomFields.js","sources":["../../../../../../admin/src/core/apis/CustomFields.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { ComponentType } from 'react';\n\nimport { Internal, Utils } from '@strapi/types';\nimport invariant from 'invariant';\n\nimport type { MessageDescriptor, PrimitiveType } from 'react-intl';\nimport type { AnySchema } from 'yup';\n\ntype CustomFieldUID = Utils.String.Suffix<\n | Internal.Namespace.WithSeparator<Internal.Namespace.Plugin>\n | Internal.Namespace.WithSeparator<Internal.Namespace.Global>,\n string\n>;\n\ntype CustomFieldOptionInput =\n | 'text'\n | 'checkbox'\n | 'checkbox-with-number-field'\n | 'select-default-boolean'\n | 'date'\n | 'select'\n | 'number'\n | 'boolean-radio-group'\n | 'select-date'\n | 'text-area-enum'\n | 'select-number'\n | 'radio-group';\n\ntype CustomFieldOptionName =\n | 'min'\n | 'minLength'\n | 'max'\n | 'maxLength'\n | 'required'\n | 'regex'\n | 'enum'\n | 'unique'\n | 'private'\n | 'default';\n\ninterface CustomFieldOption {\n intlLabel: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n description: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n name: CustomFieldOptionName;\n type: CustomFieldOptionInput;\n defaultValue?: string | number | boolean | Date;\n}\n\ninterface CustomFieldOptionSection {\n sectionTitle:\n | (MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n })\n | null;\n items: CustomFieldOption[];\n}\n\ninterface CustomFieldOptions {\n base?: (CustomFieldOptionSection | CustomFieldOption)[];\n advanced?: (CustomFieldOptionSection | CustomFieldOption)[];\n validator?: () => Record<string, AnySchema>;\n}\n\ninterface CustomField {\n name: string;\n pluginId?: string;\n type: (typeof ALLOWED_TYPES)[number];\n intlLabel: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n intlDescription: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n icon?: ComponentType;\n components: {\n Input: () => Promise<{ default?: ComponentType }>;\n };\n options?: CustomFieldOptions;\n}\n\nconst ALLOWED_TYPES = [\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'decimal',\n 'email',\n 'enumeration',\n 'float',\n 'integer',\n 'json',\n 'password',\n 'richtext',\n 'string',\n 'text',\n 'time',\n 'uid',\n] as const;\n\nconst ALLOWED_ROOT_LEVEL_OPTIONS = [\n 'min',\n 'minLength',\n 'max',\n 'maxLength',\n 'required',\n 'regex',\n 'enum',\n 'unique',\n 'private',\n 'default',\n] as const;\n\nclass CustomFields {\n customFields: Record<string, CustomField>;\n\n constructor() {\n this.customFields = {};\n }\n\n register = (customFields: CustomField | CustomField[]) => {\n if (Array.isArray(customFields)) {\n // If several custom fields are passed, register them one by one\n customFields.forEach((customField) => {\n this.register(customField);\n });\n } else {\n // Handle individual custom field\n const { name, pluginId, type, intlLabel, intlDescription, components, options } =\n customFields;\n\n // Ensure required attributes are provided\n invariant(name, 'A name must be provided');\n invariant(type, 'A type must be provided');\n invariant(intlLabel, 'An intlLabel must be provided');\n invariant(intlDescription, 'An intlDescription must be provided');\n invariant(components, 'A components object must be provided');\n invariant(components.Input, 'An Input component must be provided');\n\n // Ensure the type is valid\n invariant(\n ALLOWED_TYPES.includes(type),\n `Custom field type: '${type}' is not a valid Strapi type or it can't be used with a Custom Field`\n );\n\n // Ensure name has no special characters\n const isValidObjectKey = /^(?![0-9])[a-zA-Z0-9$_-]+$/g;\n invariant(\n isValidObjectKey.test(name),\n `Custom field name: '${name}' is not a valid object key`\n );\n\n // Ensure options have valid name paths\n const allFormOptions = [...(options?.base || []), ...(options?.advanced || [])];\n\n if (allFormOptions.length) {\n const optionPathValidations = allFormOptions.reduce(optionsValidationReducer, []);\n\n optionPathValidations.forEach(({ isValidOptionPath, errorMessage }) => {\n invariant(isValidOptionPath, errorMessage);\n });\n }\n\n // When no plugin is specified, default to the global namespace\n const uid: CustomFieldUID = pluginId ? `plugin::${pluginId}.${name}` : `global::${name}`;\n\n // Ensure the uid is unique\n const uidAlreadyUsed = Object.prototype.hasOwnProperty.call(this.customFields, uid);\n invariant(!uidAlreadyUsed, `Custom field: '${uid}' has already been registered`);\n\n this.customFields[uid] = customFields;\n }\n };\n\n getAll = () => {\n return this.customFields;\n };\n\n get = (uid: string): CustomField | undefined => {\n return this.customFields[uid];\n };\n}\n\ninterface OptionValidation {\n isValidOptionPath: boolean;\n errorMessage: string;\n}\n\nconst optionsValidationReducer = (\n acc: OptionValidation[],\n option: CustomFieldOptionSection | CustomFieldOption\n): OptionValidation[] => {\n if ('items' in option) {\n return option.items.reduce(optionsValidationReducer, acc);\n }\n\n if (!option.name) {\n acc.push({\n isValidOptionPath: false,\n errorMessage: \"The 'name' property is required on an options object\",\n });\n } else {\n acc.push({\n isValidOptionPath:\n option.name.startsWith('options') || ALLOWED_ROOT_LEVEL_OPTIONS.includes(option.name),\n errorMessage: `'${option.name}' must be prefixed with 'options.'`,\n });\n }\n\n return acc;\n};\n\nexport { type CustomField, CustomFields };\n"],"names":["ALLOWED_TYPES","ALLOWED_ROOT_LEVEL_OPTIONS","CustomFields","constructor","register","customFields","Array","isArray","forEach","customField","name","pluginId","type","intlLabel","intlDescription","components","options","invariant","Input","includes","isValidObjectKey","test","allFormOptions","base","advanced","length","optionPathValidations","reduce","optionsValidationReducer","isValidOptionPath","errorMessage","uid","uidAlreadyUsed","Object","prototype","hasOwnProperty","call","getAll","get","acc","option","items","push","startsWith"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CustomFields.mjs","sources":["../../../../../../admin/src/core/apis/CustomFields.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { ComponentType } from 'react';\n\nimport invariant from 'invariant';\n\nimport type { MessageDescriptor, PrimitiveType } from 'react-intl';\nimport type { AnySchema } from 'yup';\n\ntype CustomFieldUID = `plugin::${string}.${string}` | `global::${string}`;\n\ntype CustomFieldOptionInput =\n | 'text'\n | 'checkbox'\n | 'checkbox-with-number-field'\n | 'select-default-boolean'\n | 'date'\n | 'select'\n | 'number'\n | 'boolean-radio-group'\n | 'select-date'\n | 'text-area-enum'\n | 'select-number'\n | 'radio-group';\n\ntype CustomFieldOptionName =\n | 'min'\n | 'minLength'\n | 'max'\n | 'maxLength'\n | 'required'\n | 'regex'\n | 'enum'\n | 'unique'\n | 'private'\n | 'default';\n\ninterface CustomFieldOption {\n intlLabel: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n description: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n name: CustomFieldOptionName;\n type: CustomFieldOptionInput;\n defaultValue?: string | number | boolean | Date;\n}\n\ninterface CustomFieldOptionSection {\n sectionTitle:\n | (MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n })\n | null;\n items: CustomFieldOption[];\n}\n\ninterface CustomFieldOptions {\n base?: (CustomFieldOptionSection | CustomFieldOption)[];\n advanced?: (CustomFieldOptionSection | CustomFieldOption)[];\n validator?: () => Record<string, AnySchema>;\n}\n\ninterface CustomField {\n name: string;\n pluginId?: string;\n type: (typeof ALLOWED_TYPES)[number];\n intlLabel: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n intlDescription: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n icon?: ComponentType;\n components: {\n Input: () => Promise<{ default?: ComponentType }>;\n };\n options?: CustomFieldOptions;\n}\n\nconst ALLOWED_TYPES = [\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'decimal',\n 'email',\n 'enumeration',\n 'float',\n 'integer',\n 'json',\n 'password',\n 'richtext',\n 'string',\n 'text',\n 'time',\n 'uid',\n] as const;\n\nconst ALLOWED_ROOT_LEVEL_OPTIONS = [\n 'min',\n 'minLength',\n 'max',\n 'maxLength',\n 'required',\n 'regex',\n 'enum',\n 'unique',\n 'private',\n 'default',\n] as const;\n\nclass CustomFields {\n customFields: Record<string, CustomField>;\n\n constructor() {\n this.customFields = {};\n }\n\n register = (customFields: CustomField | CustomField[]) => {\n if (Array.isArray(customFields)) {\n // If several custom fields are passed, register them one by one\n customFields.forEach((customField) => {\n this.register(customField);\n });\n } else {\n // Handle individual custom field\n const { name, pluginId, type, intlLabel, intlDescription, components, options } =\n customFields;\n\n // Ensure required attributes are provided\n invariant(name, 'A name must be provided');\n invariant(type, 'A type must be provided');\n invariant(intlLabel, 'An intlLabel must be provided');\n invariant(intlDescription, 'An intlDescription must be provided');\n invariant(components, 'A components object must be provided');\n invariant(components.Input, 'An Input component must be provided');\n\n // Ensure the type is valid\n invariant(\n ALLOWED_TYPES.includes(type),\n `Custom field type: '${type}' is not a valid Strapi type or it can't be used with a Custom Field`\n );\n\n // Ensure name has no special characters\n const isValidObjectKey = /^(?![0-9])[a-zA-Z0-9$_-]+$/g;\n invariant(\n isValidObjectKey.test(name),\n `Custom field name: '${name}' is not a valid object key`\n );\n\n // Ensure options have valid name paths\n const allFormOptions = [...(options?.base || []), ...(options?.advanced || [])];\n\n if (allFormOptions.length) {\n const optionPathValidations = allFormOptions.reduce(optionsValidationReducer, []);\n\n optionPathValidations.forEach(({ isValidOptionPath, errorMessage }) => {\n invariant(isValidOptionPath, errorMessage);\n });\n }\n\n // When no plugin is specified, default to the global namespace\n const uid: CustomFieldUID = pluginId ? `plugin::${pluginId}.${name}` : `global::${name}`;\n\n // Ensure the uid is unique\n const uidAlreadyUsed = Object.prototype.hasOwnProperty.call(this.customFields, uid);\n invariant(!uidAlreadyUsed, `Custom field: '${uid}' has already been registered`);\n\n this.customFields[uid] = customFields;\n }\n };\n\n getAll = () => {\n return this.customFields;\n };\n\n get = (uid: string): CustomField | undefined => {\n return this.customFields[uid];\n };\n}\n\ninterface OptionValidation {\n isValidOptionPath: boolean;\n errorMessage: string;\n}\n\nconst optionsValidationReducer = (\n acc: OptionValidation[],\n option: CustomFieldOptionSection | CustomFieldOption\n): OptionValidation[] => {\n if ('items' in option) {\n return option.items.reduce(optionsValidationReducer, acc);\n }\n\n if (!option.name) {\n acc.push({\n isValidOptionPath: false,\n errorMessage: \"The 'name' property is required on an options object\",\n });\n } else {\n acc.push({\n isValidOptionPath:\n option.name.startsWith('options') || ALLOWED_ROOT_LEVEL_OPTIONS.includes(option.name),\n errorMessage: `'${option.name}' must be prefixed with 'options.'`,\n });\n }\n\n return acc;\n};\n\nexport { type CustomField, CustomFields };\n"],"names":["ALLOWED_TYPES","ALLOWED_ROOT_LEVEL_OPTIONS","CustomFields","constructor","register","customFields","Array","isArray","forEach","customField","name","pluginId","type","intlLabel","intlDescription","components","options","invariant","Input","includes","isValidObjectKey","test","allFormOptions","base","advanced","length","optionPathValidations","reduce","optionsValidationReducer","isValidOptionPath","errorMessage","uid","uidAlreadyUsed","Object","prototype","hasOwnProperty","call","getAll","get","acc","option","items","push","startsWith"],"mappings":"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"}
1
+ {"version":3,"file":"CustomFields.mjs","sources":["../../../../../../admin/src/core/apis/CustomFields.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { ComponentType } from 'react';\n\nimport { Internal, Utils } from '@strapi/types';\nimport invariant from 'invariant';\n\nimport type { MessageDescriptor, PrimitiveType } from 'react-intl';\nimport type { AnySchema } from 'yup';\n\ntype CustomFieldUID = Utils.String.Suffix<\n | Internal.Namespace.WithSeparator<Internal.Namespace.Plugin>\n | Internal.Namespace.WithSeparator<Internal.Namespace.Global>,\n string\n>;\n\ntype CustomFieldOptionInput =\n | 'text'\n | 'checkbox'\n | 'checkbox-with-number-field'\n | 'select-default-boolean'\n | 'date'\n | 'select'\n | 'number'\n | 'boolean-radio-group'\n | 'select-date'\n | 'text-area-enum'\n | 'select-number'\n | 'radio-group';\n\ntype CustomFieldOptionName =\n | 'min'\n | 'minLength'\n | 'max'\n | 'maxLength'\n | 'required'\n | 'regex'\n | 'enum'\n | 'unique'\n | 'private'\n | 'default';\n\ninterface CustomFieldOption {\n intlLabel: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n description: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n name: CustomFieldOptionName;\n type: CustomFieldOptionInput;\n defaultValue?: string | number | boolean | Date;\n}\n\ninterface CustomFieldOptionSection {\n sectionTitle:\n | (MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n })\n | null;\n items: CustomFieldOption[];\n}\n\ninterface CustomFieldOptions {\n base?: (CustomFieldOptionSection | CustomFieldOption)[];\n advanced?: (CustomFieldOptionSection | CustomFieldOption)[];\n validator?: () => Record<string, AnySchema>;\n}\n\ninterface CustomField {\n name: string;\n pluginId?: string;\n type: (typeof ALLOWED_TYPES)[number];\n intlLabel: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n intlDescription: MessageDescriptor & {\n values?: Record<string, PrimitiveType>;\n };\n icon?: ComponentType;\n components: {\n Input: () => Promise<{ default?: ComponentType }>;\n };\n options?: CustomFieldOptions;\n}\n\nconst ALLOWED_TYPES = [\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'decimal',\n 'email',\n 'enumeration',\n 'float',\n 'integer',\n 'json',\n 'password',\n 'richtext',\n 'string',\n 'text',\n 'time',\n 'uid',\n] as const;\n\nconst ALLOWED_ROOT_LEVEL_OPTIONS = [\n 'min',\n 'minLength',\n 'max',\n 'maxLength',\n 'required',\n 'regex',\n 'enum',\n 'unique',\n 'private',\n 'default',\n] as const;\n\nclass CustomFields {\n customFields: Record<string, CustomField>;\n\n constructor() {\n this.customFields = {};\n }\n\n register = (customFields: CustomField | CustomField[]) => {\n if (Array.isArray(customFields)) {\n // If several custom fields are passed, register them one by one\n customFields.forEach((customField) => {\n this.register(customField);\n });\n } else {\n // Handle individual custom field\n const { name, pluginId, type, intlLabel, intlDescription, components, options } =\n customFields;\n\n // Ensure required attributes are provided\n invariant(name, 'A name must be provided');\n invariant(type, 'A type must be provided');\n invariant(intlLabel, 'An intlLabel must be provided');\n invariant(intlDescription, 'An intlDescription must be provided');\n invariant(components, 'A components object must be provided');\n invariant(components.Input, 'An Input component must be provided');\n\n // Ensure the type is valid\n invariant(\n ALLOWED_TYPES.includes(type),\n `Custom field type: '${type}' is not a valid Strapi type or it can't be used with a Custom Field`\n );\n\n // Ensure name has no special characters\n const isValidObjectKey = /^(?![0-9])[a-zA-Z0-9$_-]+$/g;\n invariant(\n isValidObjectKey.test(name),\n `Custom field name: '${name}' is not a valid object key`\n );\n\n // Ensure options have valid name paths\n const allFormOptions = [...(options?.base || []), ...(options?.advanced || [])];\n\n if (allFormOptions.length) {\n const optionPathValidations = allFormOptions.reduce(optionsValidationReducer, []);\n\n optionPathValidations.forEach(({ isValidOptionPath, errorMessage }) => {\n invariant(isValidOptionPath, errorMessage);\n });\n }\n\n // When no plugin is specified, default to the global namespace\n const uid: CustomFieldUID = pluginId ? `plugin::${pluginId}.${name}` : `global::${name}`;\n\n // Ensure the uid is unique\n const uidAlreadyUsed = Object.prototype.hasOwnProperty.call(this.customFields, uid);\n invariant(!uidAlreadyUsed, `Custom field: '${uid}' has already been registered`);\n\n this.customFields[uid] = customFields;\n }\n };\n\n getAll = () => {\n return this.customFields;\n };\n\n get = (uid: string): CustomField | undefined => {\n return this.customFields[uid];\n };\n}\n\ninterface OptionValidation {\n isValidOptionPath: boolean;\n errorMessage: string;\n}\n\nconst optionsValidationReducer = (\n acc: OptionValidation[],\n option: CustomFieldOptionSection | CustomFieldOption\n): OptionValidation[] => {\n if ('items' in option) {\n return option.items.reduce(optionsValidationReducer, acc);\n }\n\n if (!option.name) {\n acc.push({\n isValidOptionPath: false,\n errorMessage: \"The 'name' property is required on an options object\",\n });\n } else {\n acc.push({\n isValidOptionPath:\n option.name.startsWith('options') || ALLOWED_ROOT_LEVEL_OPTIONS.includes(option.name),\n errorMessage: `'${option.name}' must be prefixed with 'options.'`,\n });\n }\n\n return acc;\n};\n\nexport { type CustomField, CustomFields };\n"],"names":["ALLOWED_TYPES","ALLOWED_ROOT_LEVEL_OPTIONS","CustomFields","constructor","register","customFields","Array","isArray","forEach","customField","name","pluginId","type","intlLabel","intlDescription","components","options","invariant","Input","includes","isValidObjectKey","test","allFormOptions","base","advanced","length","optionPathValidations","reduce","optionsValidationReducer","isValidOptionPath","errorMessage","uid","uidAlreadyUsed","Object","prototype","hasOwnProperty","call","getAll","get","acc","option","items","push","startsWith"],"mappings":";;AAqFA,MAAMA,aAAgB,GAAA;AACpB,IAAA,YAAA;AACA,IAAA,SAAA;AACA,IAAA,MAAA;AACA,IAAA,UAAA;AACA,IAAA,SAAA;AACA,IAAA,OAAA;AACA,IAAA,aAAA;AACA,IAAA,OAAA;AACA,IAAA,SAAA;AACA,IAAA,MAAA;AACA,IAAA,UAAA;AACA,IAAA,UAAA;AACA,IAAA,QAAA;AACA,IAAA,MAAA;AACA,IAAA,MAAA;AACA,IAAA;AACD,CAAA;AAED,MAAMC,0BAA6B,GAAA;AACjC,IAAA,KAAA;AACA,IAAA,WAAA;AACA,IAAA,KAAA;AACA,IAAA,WAAA;AACA,IAAA,UAAA;AACA,IAAA,OAAA;AACA,IAAA,MAAA;AACA,IAAA,QAAA;AACA,IAAA,SAAA;AACA,IAAA;AACD,CAAA;AAED,MAAMC,YAAAA,CAAAA;IAGJC,WAAc,EAAA;AAIdC,QAAAA,IAAAA,CAAAA,QAAAA,GAAW,CAACC,YAAAA,GAAAA;YACV,IAAIC,KAAAA,CAAMC,OAAO,CAACF,YAAe,CAAA,EAAA;;gBAE/BA,YAAaG,CAAAA,OAAO,CAAC,CAACC,WAAAA,GAAAA;oBACpB,IAAI,CAACL,QAAQ,CAACK,WAAAA,CAAAA;AAChB,iBAAA,CAAA;aACK,MAAA;;AAEL,gBAAA,MAAM,EAAEC,IAAI,EAAEC,QAAQ,EAAEC,IAAI,EAAEC,SAAS,EAAEC,eAAe,EAAEC,UAAU,EAAEC,OAAO,EAAE,GAC7EX,YAAAA;;AAGFY,gBAAAA,SAAAA,CAAUP,IAAM,EAAA,yBAAA,CAAA;AAChBO,gBAAAA,SAAAA,CAAUL,IAAM,EAAA,yBAAA,CAAA;AAChBK,gBAAAA,SAAAA,CAAUJ,SAAW,EAAA,+BAAA,CAAA;AACrBI,gBAAAA,SAAAA,CAAUH,eAAiB,EAAA,qCAAA,CAAA;AAC3BG,gBAAAA,SAAAA,CAAUF,UAAY,EAAA,sCAAA,CAAA;gBACtBE,SAAUF,CAAAA,UAAAA,CAAWG,KAAK,EAAE,qCAAA,CAAA;;gBAG5BD,SACEjB,CAAAA,aAAAA,CAAcmB,QAAQ,CAACP,IAAAA,CAAAA,EACvB,CAAC,oBAAoB,EAAEA,IAAK,CAAA,oEAAoE,CAAC,CAAA;;AAInG,gBAAA,MAAMQ,gBAAmB,GAAA,6BAAA;gBACzBH,SACEG,CAAAA,gBAAAA,CAAiBC,IAAI,CAACX,IAAAA,CAAAA,EACtB,CAAC,oBAAoB,EAAEA,IAAK,CAAA,2BAA2B,CAAC,CAAA;;AAI1D,gBAAA,MAAMY,cAAiB,GAAA;AAAKN,oBAAAA,GAAAA,OAAAA,EAASO,QAAQ,EAAE;AAAOP,oBAAAA,GAAAA,OAAAA,EAASQ,YAAY;AAAI,iBAAA;gBAE/E,IAAIF,cAAAA,CAAeG,MAAM,EAAE;AACzB,oBAAA,MAAMC,qBAAwBJ,GAAAA,cAAAA,CAAeK,MAAM,CAACC,0BAA0B,EAAE,CAAA;AAEhFF,oBAAAA,qBAAAA,CAAsBlB,OAAO,CAAC,CAAC,EAAEqB,iBAAiB,EAAEC,YAAY,EAAE,GAAA;AAChEb,wBAAAA,SAAAA,CAAUY,iBAAmBC,EAAAA,YAAAA,CAAAA;AAC/B,qBAAA,CAAA;AACF;;AAGA,gBAAA,MAAMC,GAAsBpB,GAAAA,QAAAA,GAAW,CAAC,QAAQ,EAAEA,QAAS,CAAA,CAAC,EAAED,IAAAA,CAAK,CAAC,GAAG,CAAC,QAAQ,EAAEA,KAAK,CAAC;;gBAGxF,MAAMsB,cAAAA,GAAiBC,MAAOC,CAAAA,SAAS,CAACC,cAAc,CAACC,IAAI,CAAC,IAAI,CAAC/B,YAAY,EAAE0B,GAAAA,CAAAA;AAC/Ed,gBAAAA,SAAAA,CAAU,CAACe,cAAgB,EAAA,CAAC,eAAe,EAAED,GAAAA,CAAI,6BAA6B,CAAC,CAAA;AAE/E,gBAAA,IAAI,CAAC1B,YAAY,CAAC0B,GAAAA,CAAI,GAAG1B,YAAAA;AAC3B;AACF,SAAA;aAEAgC,MAAS,GAAA,IAAA;YACP,OAAO,IAAI,CAAChC,YAAY;AAC1B,SAAA;AAEAiC,QAAAA,IAAAA,CAAAA,GAAAA,GAAM,CAACP,GAAAA,GAAAA;AACL,YAAA,OAAO,IAAI,CAAC1B,YAAY,CAAC0B,GAAI,CAAA;AAC/B,SAAA;QA/DE,IAAI,CAAC1B,YAAY,GAAG,EAAC;AACvB;AA+DF;AAOA,MAAMuB,wBAAAA,GAA2B,CAC/BW,GACAC,EAAAA,MAAAA,GAAAA;AAEA,IAAA,IAAI,WAAWA,MAAQ,EAAA;AACrB,QAAA,OAAOA,MAAOC,CAAAA,KAAK,CAACd,MAAM,CAACC,wBAA0BW,EAAAA,GAAAA,CAAAA;AACvD;IAEA,IAAI,CAACC,MAAO9B,CAAAA,IAAI,EAAE;AAChB6B,QAAAA,GAAAA,CAAIG,IAAI,CAAC;YACPb,iBAAmB,EAAA,KAAA;YACnBC,YAAc,EAAA;AAChB,SAAA,CAAA;KACK,MAAA;AACLS,QAAAA,GAAAA,CAAIG,IAAI,CAAC;YACPb,iBACEW,EAAAA,MAAAA,CAAO9B,IAAI,CAACiC,UAAU,CAAC,cAAc1C,0BAA2BkB,CAAAA,QAAQ,CAACqB,MAAAA,CAAO9B,IAAI,CAAA;AACtFoB,YAAAA,YAAAA,EAAc,CAAC,CAAC,EAAEU,OAAO9B,IAAI,CAAC,kCAAkC;AAClE,SAAA,CAAA;AACF;IAEA,OAAO6B,GAAAA;AACT,CAAA;;;;"}
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ var invariant = require('invariant');
4
+
5
+ class Widgets {
6
+ constructor(){
7
+ this.register = (widget)=>{
8
+ if (Array.isArray(widget)) {
9
+ widget.forEach((newWidget)=>{
10
+ this.register(newWidget);
11
+ });
12
+ } else {
13
+ invariant(widget.id, 'An id must be provided');
14
+ invariant(widget.component, 'A component must be provided');
15
+ invariant(widget.title, 'A title must be provided');
16
+ invariant(widget.icon, 'An icon must be provided');
17
+ // Replace id and pluginId with computed uid
18
+ const { id, pluginId, ...widgetToStore } = widget;
19
+ const uid = pluginId ? `plugin::${pluginId}.${id}` : `global::${id}`;
20
+ this.widgets[uid] = {
21
+ ...widgetToStore,
22
+ uid
23
+ };
24
+ }
25
+ };
26
+ this.getAll = ()=>{
27
+ return Object.values(this.widgets);
28
+ };
29
+ this.widgets = {};
30
+ }
31
+ }
32
+
33
+ exports.Widgets = Widgets;
34
+ //# sourceMappingURL=Widgets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Widgets.js","sources":["../../../../../../admin/src/core/apis/Widgets.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\n\nimport invariant from 'invariant';\nimport { To } from 'react-router-dom';\n\nimport { Permission } from '../../../../shared/contracts/shared';\n\nimport type { Internal, Utils } from '@strapi/types';\nimport type { MessageDescriptor } from 'react-intl';\n\ntype WidgetUID = Utils.String.Suffix<\n | Internal.Namespace.WithSeparator<Internal.Namespace.Plugin>\n | Internal.Namespace.WithSeparator<Internal.Namespace.Global>,\n string\n>;\n\ntype WidgetArgs = {\n icon?: typeof import('@strapi/icons').PuzzlePiece;\n title: MessageDescriptor;\n link?: {\n label: MessageDescriptor;\n href: To;\n };\n component: () => Promise<React.ComponentType>;\n pluginId?: string;\n id: string;\n permissions?: Permission[];\n};\n\ntype Widget = Omit<WidgetArgs, 'id' | 'pluginId'> & { uid: WidgetUID };\n\nclass Widgets {\n widgets: Record<string, Widget>;\n\n constructor() {\n this.widgets = {};\n }\n\n register = (widget: WidgetArgs | WidgetArgs[]) => {\n if (Array.isArray(widget)) {\n widget.forEach((newWidget) => {\n this.register(newWidget);\n });\n } else {\n invariant(widget.id, 'An id must be provided');\n invariant(widget.component, 'A component must be provided');\n invariant(widget.title, 'A title must be provided');\n invariant(widget.icon, 'An icon must be provided');\n\n // Replace id and pluginId with computed uid\n const { id, pluginId, ...widgetToStore } = widget;\n const uid: WidgetUID = pluginId ? `plugin::${pluginId}.${id}` : `global::${id}`;\n\n this.widgets[uid] = { ...widgetToStore, uid };\n }\n };\n\n getAll = () => {\n return Object.values(this.widgets);\n };\n}\n\nexport { Widgets };\nexport type { WidgetArgs };\n"],"names":["Widgets","constructor","register","widget","Array","isArray","forEach","newWidget","invariant","id","component","title","icon","pluginId","widgetToStore","uid","widgets","getAll","Object","values"],"mappings":";;;;AA+BA,MAAMA,OAAAA,CAAAA;IAGJC,WAAc,EAAA;AAIdC,QAAAA,IAAAA,CAAAA,QAAAA,GAAW,CAACC,MAAAA,GAAAA;YACV,IAAIC,KAAAA,CAAMC,OAAO,CAACF,MAAS,CAAA,EAAA;gBACzBA,MAAOG,CAAAA,OAAO,CAAC,CAACC,SAAAA,GAAAA;oBACd,IAAI,CAACL,QAAQ,CAACK,SAAAA,CAAAA;AAChB,iBAAA,CAAA;aACK,MAAA;gBACLC,SAAUL,CAAAA,MAAAA,CAAOM,EAAE,EAAE,wBAAA,CAAA;gBACrBD,SAAUL,CAAAA,MAAAA,CAAOO,SAAS,EAAE,8BAAA,CAAA;gBAC5BF,SAAUL,CAAAA,MAAAA,CAAOQ,KAAK,EAAE,0BAAA,CAAA;gBACxBH,SAAUL,CAAAA,MAAAA,CAAOS,IAAI,EAAE,0BAAA,CAAA;;AAGvB,gBAAA,MAAM,EAAEH,EAAE,EAAEI,QAAQ,EAAE,GAAGC,eAAe,GAAGX,MAAAA;AAC3C,gBAAA,MAAMY,GAAiBF,GAAAA,QAAAA,GAAW,CAAC,QAAQ,EAAEA,QAAS,CAAA,CAAC,EAAEJ,EAAAA,CAAG,CAAC,GAAG,CAAC,QAAQ,EAAEA,GAAG,CAAC;AAE/E,gBAAA,IAAI,CAACO,OAAO,CAACD,GAAAA,CAAI,GAAG;AAAE,oBAAA,GAAGD,aAAa;AAAEC,oBAAAA;AAAI,iBAAA;AAC9C;AACF,SAAA;aAEAE,MAAS,GAAA,IAAA;AACP,YAAA,OAAOC,MAAOC,CAAAA,MAAM,CAAC,IAAI,CAACH,OAAO,CAAA;AACnC,SAAA;QAxBE,IAAI,CAACA,OAAO,GAAG,EAAC;AAClB;AAwBF;;;;"}
@@ -0,0 +1,32 @@
1
+ import invariant from 'invariant';
2
+
3
+ class Widgets {
4
+ constructor(){
5
+ this.register = (widget)=>{
6
+ if (Array.isArray(widget)) {
7
+ widget.forEach((newWidget)=>{
8
+ this.register(newWidget);
9
+ });
10
+ } else {
11
+ invariant(widget.id, 'An id must be provided');
12
+ invariant(widget.component, 'A component must be provided');
13
+ invariant(widget.title, 'A title must be provided');
14
+ invariant(widget.icon, 'An icon must be provided');
15
+ // Replace id and pluginId with computed uid
16
+ const { id, pluginId, ...widgetToStore } = widget;
17
+ const uid = pluginId ? `plugin::${pluginId}.${id}` : `global::${id}`;
18
+ this.widgets[uid] = {
19
+ ...widgetToStore,
20
+ uid
21
+ };
22
+ }
23
+ };
24
+ this.getAll = ()=>{
25
+ return Object.values(this.widgets);
26
+ };
27
+ this.widgets = {};
28
+ }
29
+ }
30
+
31
+ export { Widgets };
32
+ //# sourceMappingURL=Widgets.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Widgets.mjs","sources":["../../../../../../admin/src/core/apis/Widgets.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\n\nimport invariant from 'invariant';\nimport { To } from 'react-router-dom';\n\nimport { Permission } from '../../../../shared/contracts/shared';\n\nimport type { Internal, Utils } from '@strapi/types';\nimport type { MessageDescriptor } from 'react-intl';\n\ntype WidgetUID = Utils.String.Suffix<\n | Internal.Namespace.WithSeparator<Internal.Namespace.Plugin>\n | Internal.Namespace.WithSeparator<Internal.Namespace.Global>,\n string\n>;\n\ntype WidgetArgs = {\n icon?: typeof import('@strapi/icons').PuzzlePiece;\n title: MessageDescriptor;\n link?: {\n label: MessageDescriptor;\n href: To;\n };\n component: () => Promise<React.ComponentType>;\n pluginId?: string;\n id: string;\n permissions?: Permission[];\n};\n\ntype Widget = Omit<WidgetArgs, 'id' | 'pluginId'> & { uid: WidgetUID };\n\nclass Widgets {\n widgets: Record<string, Widget>;\n\n constructor() {\n this.widgets = {};\n }\n\n register = (widget: WidgetArgs | WidgetArgs[]) => {\n if (Array.isArray(widget)) {\n widget.forEach((newWidget) => {\n this.register(newWidget);\n });\n } else {\n invariant(widget.id, 'An id must be provided');\n invariant(widget.component, 'A component must be provided');\n invariant(widget.title, 'A title must be provided');\n invariant(widget.icon, 'An icon must be provided');\n\n // Replace id and pluginId with computed uid\n const { id, pluginId, ...widgetToStore } = widget;\n const uid: WidgetUID = pluginId ? `plugin::${pluginId}.${id}` : `global::${id}`;\n\n this.widgets[uid] = { ...widgetToStore, uid };\n }\n };\n\n getAll = () => {\n return Object.values(this.widgets);\n };\n}\n\nexport { Widgets };\nexport type { WidgetArgs };\n"],"names":["Widgets","constructor","register","widget","Array","isArray","forEach","newWidget","invariant","id","component","title","icon","pluginId","widgetToStore","uid","widgets","getAll","Object","values"],"mappings":";;AA+BA,MAAMA,OAAAA,CAAAA;IAGJC,WAAc,EAAA;AAIdC,QAAAA,IAAAA,CAAAA,QAAAA,GAAW,CAACC,MAAAA,GAAAA;YACV,IAAIC,KAAAA,CAAMC,OAAO,CAACF,MAAS,CAAA,EAAA;gBACzBA,MAAOG,CAAAA,OAAO,CAAC,CAACC,SAAAA,GAAAA;oBACd,IAAI,CAACL,QAAQ,CAACK,SAAAA,CAAAA;AAChB,iBAAA,CAAA;aACK,MAAA;gBACLC,SAAUL,CAAAA,MAAAA,CAAOM,EAAE,EAAE,wBAAA,CAAA;gBACrBD,SAAUL,CAAAA,MAAAA,CAAOO,SAAS,EAAE,8BAAA,CAAA;gBAC5BF,SAAUL,CAAAA,MAAAA,CAAOQ,KAAK,EAAE,0BAAA,CAAA;gBACxBH,SAAUL,CAAAA,MAAAA,CAAOS,IAAI,EAAE,0BAAA,CAAA;;AAGvB,gBAAA,MAAM,EAAEH,EAAE,EAAEI,QAAQ,EAAE,GAAGC,eAAe,GAAGX,MAAAA;AAC3C,gBAAA,MAAMY,GAAiBF,GAAAA,QAAAA,GAAW,CAAC,QAAQ,EAAEA,QAAS,CAAA,CAAC,EAAEJ,EAAAA,CAAG,CAAC,GAAG,CAAC,QAAQ,EAAEA,GAAG,CAAC;AAE/E,gBAAA,IAAI,CAACO,OAAO,CAACD,GAAAA,CAAI,GAAG;AAAE,oBAAA,GAAGD,aAAa;AAAEC,oBAAAA;AAAI,iBAAA;AAC9C;AACF,SAAA;aAEAE,MAAS,GAAA,IAAA;AACP,YAAA,OAAOC,MAAOC,CAAAA,MAAM,CAAC,IAAI,CAACH,OAAO,CAAA;AACnC,SAAA;QAxBE,IAAI,CAACA,OAAO,GAAG,EAAC;AAClB;AAwBF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"StrapiApp.js","sources":["../../../../../admin/src/features/StrapiApp.tsx"],"sourcesContent":["import { createContext } from '../components/Context';\nimport { RBAC } from '../core/apis/rbac';\nimport { Router } from '../core/apis/router';\n\nimport type { StrapiApp } from '../StrapiApp';\n\n/* -------------------------------------------------------------------------------------------------\n * StrapiApp\n * -----------------------------------------------------------------------------------------------*/\ninterface StrapiAppContextValue\n extends Pick<\n StrapiApp,\n | 'customFields'\n | 'getPlugin'\n | 'getAdminInjectedComponents'\n | 'plugins'\n | 'runHookParallel'\n | 'runHookSeries'\n >,\n Pick<Router, 'menu' | 'settings'> {\n components: StrapiApp['library']['components'];\n fields: StrapiApp['library']['fields'];\n rbac: RBAC;\n runHookWaterfall: <TData>(\n name: Parameters<StrapiApp['runHookWaterfall']>[0],\n initialValue: TData\n ) => TData;\n}\n\nconst [StrapiAppProvider, useStrapiApp] = createContext<StrapiAppContextValue>('StrapiApp');\n\nexport { StrapiAppProvider, useStrapiApp };\nexport type { StrapiAppContextValue };\n"],"names":["StrapiAppProvider","useStrapiApp","createContext"],"mappings":";;;;AA6BA,MAAM,CAACA,iBAAAA,EAAmBC,YAAa,CAAA,GAAGC,qBAAqC,CAAA,WAAA;;;;;"}
1
+ {"version":3,"file":"StrapiApp.js","sources":["../../../../../admin/src/features/StrapiApp.tsx"],"sourcesContent":["import { createContext } from '../components/Context';\nimport { RBAC } from '../core/apis/rbac';\nimport { Router } from '../core/apis/router';\n\nimport type { StrapiApp } from '../StrapiApp';\n\n/* -------------------------------------------------------------------------------------------------\n * StrapiApp\n * -----------------------------------------------------------------------------------------------*/\ninterface StrapiAppContextValue\n extends Pick<\n StrapiApp,\n | 'customFields'\n | 'getPlugin'\n | 'getAdminInjectedComponents'\n | 'plugins'\n | 'runHookParallel'\n | 'runHookSeries'\n | 'widgets'\n >,\n Pick<Router, 'menu' | 'settings'> {\n components: StrapiApp['library']['components'];\n fields: StrapiApp['library']['fields'];\n rbac: RBAC;\n runHookWaterfall: <TData>(\n name: Parameters<StrapiApp['runHookWaterfall']>[0],\n initialValue: TData\n ) => TData;\n}\n\nconst [StrapiAppProvider, useStrapiApp] = createContext<StrapiAppContextValue>('StrapiApp');\n\nexport { StrapiAppProvider, useStrapiApp };\nexport type { StrapiAppContextValue };\n"],"names":["StrapiAppProvider","useStrapiApp","createContext"],"mappings":";;;;AA8BA,MAAM,CAACA,iBAAAA,EAAmBC,YAAa,CAAA,GAAGC,qBAAqC,CAAA,WAAA;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"StrapiApp.mjs","sources":["../../../../../admin/src/features/StrapiApp.tsx"],"sourcesContent":["import { createContext } from '../components/Context';\nimport { RBAC } from '../core/apis/rbac';\nimport { Router } from '../core/apis/router';\n\nimport type { StrapiApp } from '../StrapiApp';\n\n/* -------------------------------------------------------------------------------------------------\n * StrapiApp\n * -----------------------------------------------------------------------------------------------*/\ninterface StrapiAppContextValue\n extends Pick<\n StrapiApp,\n | 'customFields'\n | 'getPlugin'\n | 'getAdminInjectedComponents'\n | 'plugins'\n | 'runHookParallel'\n | 'runHookSeries'\n >,\n Pick<Router, 'menu' | 'settings'> {\n components: StrapiApp['library']['components'];\n fields: StrapiApp['library']['fields'];\n rbac: RBAC;\n runHookWaterfall: <TData>(\n name: Parameters<StrapiApp['runHookWaterfall']>[0],\n initialValue: TData\n ) => TData;\n}\n\nconst [StrapiAppProvider, useStrapiApp] = createContext<StrapiAppContextValue>('StrapiApp');\n\nexport { StrapiAppProvider, useStrapiApp };\nexport type { StrapiAppContextValue };\n"],"names":["StrapiAppProvider","useStrapiApp","createContext"],"mappings":";;AA6BA,MAAM,CAACA,iBAAAA,EAAmBC,YAAa,CAAA,GAAGC,aAAqC,CAAA,WAAA;;;;"}
1
+ {"version":3,"file":"StrapiApp.mjs","sources":["../../../../../admin/src/features/StrapiApp.tsx"],"sourcesContent":["import { createContext } from '../components/Context';\nimport { RBAC } from '../core/apis/rbac';\nimport { Router } from '../core/apis/router';\n\nimport type { StrapiApp } from '../StrapiApp';\n\n/* -------------------------------------------------------------------------------------------------\n * StrapiApp\n * -----------------------------------------------------------------------------------------------*/\ninterface StrapiAppContextValue\n extends Pick<\n StrapiApp,\n | 'customFields'\n | 'getPlugin'\n | 'getAdminInjectedComponents'\n | 'plugins'\n | 'runHookParallel'\n | 'runHookSeries'\n | 'widgets'\n >,\n Pick<Router, 'menu' | 'settings'> {\n components: StrapiApp['library']['components'];\n fields: StrapiApp['library']['fields'];\n rbac: RBAC;\n runHookWaterfall: <TData>(\n name: Parameters<StrapiApp['runHookWaterfall']>[0],\n initialValue: TData\n ) => TData;\n}\n\nconst [StrapiAppProvider, useStrapiApp] = createContext<StrapiAppContextValue>('StrapiApp');\n\nexport { StrapiAppProvider, useStrapiApp };\nexport type { StrapiAppContextValue };\n"],"names":["StrapiAppProvider","useStrapiApp","createContext"],"mappings":";;AA8BA,MAAM,CAACA,iBAAAA,EAAmBC,YAAa,CAAA,GAAGC,aAAqC,CAAA,WAAA;;;;"}
@@ -1,23 +1,168 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- require('react');
4
+ var React = require('react');
5
5
  var designSystem = require('@strapi/design-system');
6
+ var icons = require('@strapi/icons');
6
7
  var reactIntl = require('react-intl');
7
8
  var Layout = require('../../components/Layouts/Layout.js');
8
9
  var PageHelpers = require('../../components/PageHelpers.js');
10
+ var WidgetHelpers = require('../../components/WidgetHelpers.js');
9
11
  require('../../services/admin.js');
10
12
  var useEnterprise = require('../../hooks/useEnterprise.js');
11
13
  var Auth = require('../../features/Auth.js');
14
+ var StrapiApp = require('../../features/StrapiApp.js');
12
15
  var ContentManagerWidgets = require('./components/ContentManagerWidgets.js');
13
16
  var GuidedTour = require('./components/GuidedTour.js');
14
17
 
18
+ function _interopNamespaceDefault(e) {
19
+ var n = Object.create(null);
20
+ if (e) {
21
+ Object.keys(e).forEach(function (k) {
22
+ if (k !== 'default') {
23
+ var d = Object.getOwnPropertyDescriptor(e, k);
24
+ Object.defineProperty(n, k, d.get ? d : {
25
+ enumerable: true,
26
+ get: function () { return e[k]; }
27
+ });
28
+ }
29
+ });
30
+ }
31
+ n.default = e;
32
+ return Object.freeze(n);
33
+ }
34
+
35
+ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
36
+
37
+ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children })=>{
38
+ const { formatMessage } = reactIntl.useIntl();
39
+ const id = React__namespace.useId();
40
+ const Icon = icon;
41
+ return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
42
+ width: "100%",
43
+ hasRadius: true,
44
+ direction: "column",
45
+ alignItems: "flex-start",
46
+ background: "neutral0",
47
+ borderColor: "neutral150",
48
+ shadow: "tableShadow",
49
+ tag: "section",
50
+ gap: 4,
51
+ padding: 6,
52
+ "aria-labelledby": id,
53
+ children: [
54
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
55
+ direction: "row",
56
+ alignItems: "center",
57
+ gap: 2,
58
+ tag: "header",
59
+ children: [
60
+ /*#__PURE__*/ jsxRuntime.jsx(Icon, {
61
+ fill: "neutral500",
62
+ "aria-hidden": true
63
+ }),
64
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
65
+ textColor: "neutral500",
66
+ variant: "sigma",
67
+ tag: "h2",
68
+ id: id,
69
+ children: formatMessage(title)
70
+ })
71
+ ]
72
+ }),
73
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
74
+ width: "100%",
75
+ height: "261px",
76
+ overflow: "auto",
77
+ tag: "main",
78
+ children: children
79
+ })
80
+ ]
81
+ });
82
+ };
83
+ /* -------------------------------------------------------------------------------------------------
84
+ * UnstableHomePageCe
85
+ * -----------------------------------------------------------------------------------------------*/ const WidgetComponent = ({ component })=>{
86
+ const [loadedComponent, setLoadedComponent] = React__namespace.useState(null);
87
+ React__namespace.useEffect(()=>{
88
+ const loadComponent = async ()=>{
89
+ const resolvedComponent = await component();
90
+ setLoadedComponent(()=>resolvedComponent);
91
+ };
92
+ loadComponent();
93
+ }, [
94
+ component
95
+ ]);
96
+ const Component = loadedComponent;
97
+ if (!Component) {
98
+ return /*#__PURE__*/ jsxRuntime.jsx(WidgetHelpers.Widget.Loading, {});
99
+ }
100
+ return /*#__PURE__*/ jsxRuntime.jsx(Component, {});
101
+ };
102
+ const UnstableHomePageCe = ()=>{
103
+ const { formatMessage } = reactIntl.useIntl();
104
+ const user = Auth.useAuth('HomePageCE', (state)=>state.user);
105
+ const displayName = user?.firstname ?? user?.username ?? user?.email;
106
+ const getAllWidgets = StrapiApp.useStrapiApp('UnstableHomepageCe', (state)=>state.widgets.getAll);
107
+ return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Main, {
108
+ children: [
109
+ /*#__PURE__*/ jsxRuntime.jsx(PageHelpers.Page.Title, {
110
+ children: formatMessage({
111
+ id: 'HomePage.head.title',
112
+ defaultMessage: 'Homepage'
113
+ })
114
+ }),
115
+ /*#__PURE__*/ jsxRuntime.jsx(Layout.Layouts.Header, {
116
+ title: formatMessage({
117
+ id: 'HomePage.header.title',
118
+ defaultMessage: 'Hello {name}'
119
+ }, {
120
+ name: displayName
121
+ }),
122
+ subtitle: formatMessage({
123
+ id: 'HomePage.header.subtitle',
124
+ defaultMessage: 'Welcome to your administration panel'
125
+ })
126
+ }),
127
+ /*#__PURE__*/ jsxRuntime.jsx(Layout.Layouts.Content, {
128
+ children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
129
+ direction: "column",
130
+ alignItems: "stretch",
131
+ gap: 8,
132
+ paddingBottom: 10,
133
+ children: [
134
+ /*#__PURE__*/ jsxRuntime.jsx(GuidedTour.GuidedTour, {}),
135
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Root, {
136
+ gap: 5,
137
+ children: getAllWidgets().map((widget)=>{
138
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
139
+ col: 6,
140
+ s: 12,
141
+ children: /*#__PURE__*/ jsxRuntime.jsx(WidgetRoot, {
142
+ title: widget.title,
143
+ icon: widget.icon,
144
+ children: /*#__PURE__*/ jsxRuntime.jsx(WidgetComponent, {
145
+ component: widget.component
146
+ })
147
+ })
148
+ }, widget.uid);
149
+ })
150
+ })
151
+ ]
152
+ })
153
+ })
154
+ ]
155
+ });
156
+ };
15
157
  /* -------------------------------------------------------------------------------------------------
16
158
  * HomePageCE
17
159
  * -----------------------------------------------------------------------------------------------*/ const HomePageCE = ()=>{
18
160
  const { formatMessage } = reactIntl.useIntl();
19
161
  const user = Auth.useAuth('HomePageCE', (state)=>state.user);
20
162
  const displayName = user?.firstname ?? user?.username ?? user?.email;
163
+ if (window.strapi.future.isEnabled('unstableWidgetsApi')) {
164
+ return /*#__PURE__*/ jsxRuntime.jsx(UnstableHomePageCe, {});
165
+ }
21
166
  return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Main, {
22
167
  children: [
23
168
  /*#__PURE__*/ jsxRuntime.jsx(PageHelpers.Page.Title, {
@@ -52,12 +197,26 @@ var GuidedTour = require('./components/GuidedTour.js');
52
197
  /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
53
198
  col: 6,
54
199
  s: 12,
55
- children: /*#__PURE__*/ jsxRuntime.jsx(ContentManagerWidgets.LastEditedWidget, {})
200
+ children: /*#__PURE__*/ jsxRuntime.jsx(WidgetRoot, {
201
+ title: {
202
+ id: 'content-manager.widget.last-edited.title',
203
+ defaultMessage: 'Last edited entries'
204
+ },
205
+ icon: icons.Pencil,
206
+ children: /*#__PURE__*/ jsxRuntime.jsx(ContentManagerWidgets.LastEditedWidget, {})
207
+ })
56
208
  }),
57
209
  /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
58
210
  col: 6,
59
211
  s: 12,
60
- children: /*#__PURE__*/ jsxRuntime.jsx(ContentManagerWidgets.LastPublishedWidget, {})
212
+ children: /*#__PURE__*/ jsxRuntime.jsx(WidgetRoot, {
213
+ title: {
214
+ id: 'content-manager.widget.last-published.title',
215
+ defaultMessage: 'Last published entries'
216
+ },
217
+ icon: icons.CheckCircle,
218
+ children: /*#__PURE__*/ jsxRuntime.jsx(ContentManagerWidgets.LastPublishedWidget, {})
219
+ })
61
220
  })
62
221
  ]
63
222
  })
@@ -81,4 +240,5 @@ var GuidedTour = require('./components/GuidedTour.js');
81
240
 
82
241
  exports.HomePage = HomePage;
83
242
  exports.HomePageCE = HomePageCE;
243
+ exports.WidgetRoot = WidgetRoot;
84
244
  //# sourceMappingURL=HomePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"HomePage.js","sources":["../../../../../../admin/src/pages/Home/HomePage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Flex, Grid, Main } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { Layouts } from '../../components/Layouts/Layout';\nimport { Page } from '../../components/PageHelpers';\nimport { useEnterprise } from '../../ee';\nimport { useAuth } from '../../features/Auth';\n\nimport { LastEditedWidget, LastPublishedWidget } from './components/ContentManagerWidgets';\nimport { GuidedTour } from './components/GuidedTour';\n\n/* -------------------------------------------------------------------------------------------------\n * HomePageCE\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePageCE = () => {\n const { formatMessage } = useIntl();\n const user = useAuth('HomePageCE', (state) => state.user);\n const displayName = user?.firstname ?? user?.username ?? user?.email;\n\n return (\n <Main>\n <Page.Title>\n {formatMessage({ id: 'HomePage.head.title', defaultMessage: 'Homepage' })}\n </Page.Title>\n <Layouts.Header\n title={formatMessage(\n { id: 'HomePage.header.title', defaultMessage: 'Hello {name}' },\n { name: displayName }\n )}\n subtitle={formatMessage({\n id: 'HomePage.header.subtitle',\n defaultMessage: 'Welcome to your administration panel',\n })}\n />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={8} paddingBottom={10}>\n <GuidedTour />\n <Grid.Root gap={5}>\n <Grid.Item col={6} s={12}>\n <LastEditedWidget />\n </Grid.Item>\n <Grid.Item col={6} s={12}>\n <LastPublishedWidget />\n </Grid.Item>\n </Grid.Root>\n </Flex>\n </Layouts.Content>\n </Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePage\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePage = () => {\n const Page = useEnterprise(\n HomePageCE,\n // eslint-disable-next-line import/no-cycle\n async () => (await import('../../../../ee/admin/src/pages/HomePage')).HomePageEE\n );\n\n // block rendering until the EE component is fully loaded\n if (!Page) {\n return null;\n }\n\n return <Page />;\n};\n\nexport { HomePage, HomePageCE };\n"],"names":["HomePageCE","formatMessage","useIntl","user","useAuth","state","displayName","firstname","username","email","_jsxs","Main","_jsx","Page","Title","id","defaultMessage","Layouts","Header","title","name","subtitle","Content","Flex","direction","alignItems","gap","paddingBottom","GuidedTour","Grid","Root","Item","col","s","LastEditedWidget","LastPublishedWidget","HomePage","useEnterprise","HomePageEE"],"mappings":";;;;;;;;;;;;;;AAaA;;AAEkG,2GAE5FA,UAAa,GAAA,IAAA;IACjB,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAC1B,IAAA,MAAMC,OAAOC,YAAQ,CAAA,YAAA,EAAc,CAACC,KAAAA,GAAUA,MAAMF,IAAI,CAAA;AACxD,IAAA,MAAMG,WAAcH,GAAAA,IAAAA,EAAMI,SAAaJ,IAAAA,IAAAA,EAAMK,YAAYL,IAAMM,EAAAA,KAAAA;AAE/D,IAAA,qBACEC,eAACC,CAAAA,iBAAAA,EAAAA;;AACC,0BAAAC,cAAA,CAACC,iBAAKC,KAAK,EAAA;0BACRb,aAAc,CAAA;oBAAEc,EAAI,EAAA,qBAAA;oBAAuBC,cAAgB,EAAA;AAAW,iBAAA;;AAEzE,0BAAAJ,cAAA,CAACK,eAAQC,MAAM,EAAA;AACbC,gBAAAA,KAAAA,EAAOlB,aACL,CAAA;oBAAEc,EAAI,EAAA,uBAAA;oBAAyBC,cAAgB,EAAA;iBAC/C,EAAA;oBAAEI,IAAMd,EAAAA;AAAY,iBAAA,CAAA;AAEtBe,gBAAAA,QAAAA,EAAUpB,aAAc,CAAA;oBACtBc,EAAI,EAAA,0BAAA;oBACJC,cAAgB,EAAA;AAClB,iBAAA;;AAEF,0BAAAJ,cAAA,CAACK,eAAQK,OAAO,EAAA;AACd,gBAAA,QAAA,gBAAAZ,eAACa,CAAAA,iBAAAA,EAAAA;oBAAKC,SAAU,EAAA,QAAA;oBAASC,UAAW,EAAA,SAAA;oBAAUC,GAAK,EAAA,CAAA;oBAAGC,aAAe,EAAA,EAAA;;sCACnEf,cAACgB,CAAAA,qBAAAA,EAAAA,EAAAA,CAAAA;AACD,sCAAAlB,eAAA,CAACmB,kBAAKC,IAAI,EAAA;4BAACJ,GAAK,EAAA,CAAA;;AACd,8CAAAd,cAAA,CAACiB,kBAAKE,IAAI,EAAA;oCAACC,GAAK,EAAA,CAAA;oCAAGC,CAAG,EAAA,EAAA;AACpB,oCAAA,QAAA,gBAAArB,cAACsB,CAAAA,sCAAAA,EAAAA,EAAAA;;AAEH,8CAAAtB,cAAA,CAACiB,kBAAKE,IAAI,EAAA;oCAACC,GAAK,EAAA,CAAA;oCAAGC,CAAG,EAAA,EAAA;AACpB,oCAAA,QAAA,gBAAArB,cAACuB,CAAAA,yCAAAA,EAAAA,EAAAA;;;;;;;;;AAOf;AAEA;;AAEkG,2GAE5FC,QAAW,GAAA,IAAA;IACf,MAAMvB,IAAAA,GAAOwB,2BACXrC,CAAAA,UAAAA;AAEA,IAAA,UAAY,CAAC,MAAM,oDAAO,4CAAA,KAAyC,EAAGsC,UAAU,CAAA;;AAIlF,IAAA,IAAI,CAACzB,IAAM,EAAA;QACT,OAAO,IAAA;AACT;AAEA,IAAA,qBAAOD,cAACC,CAAAA,IAAAA,EAAAA,EAAAA,CAAAA;AACV;;;;;"}
1
+ {"version":3,"file":"HomePage.js","sources":["../../../../../../admin/src/pages/Home/HomePage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Flex, Grid, Main, Typography } from '@strapi/design-system';\nimport { CheckCircle, Pencil, PuzzlePiece } from '@strapi/icons';\nimport { MessageDescriptor, useIntl } from 'react-intl';\n\nimport { Layouts } from '../../components/Layouts/Layout';\nimport { Page } from '../../components/PageHelpers';\nimport { Widget } from '../../components/WidgetHelpers';\nimport { useEnterprise } from '../../ee';\nimport { useAuth } from '../../features/Auth';\nimport { useStrapiApp } from '../../features/StrapiApp';\n\nimport { LastEditedWidget, LastPublishedWidget } from './components/ContentManagerWidgets';\nimport { GuidedTour } from './components/GuidedTour';\n\n/* -------------------------------------------------------------------------------------------------\n * WidgetRoot\n * -----------------------------------------------------------------------------------------------*/\n\ninterface RootProps {\n title: MessageDescriptor;\n icon?: typeof import('@strapi/icons').PuzzlePiece;\n children: React.ReactNode;\n}\n\nexport const WidgetRoot = ({ title, icon = PuzzlePiece, children }: RootProps) => {\n const { formatMessage } = useIntl();\n const id = React.useId();\n const Icon = icon;\n\n return (\n <Flex\n width=\"100%\"\n hasRadius\n direction=\"column\"\n alignItems=\"flex-start\"\n background=\"neutral0\"\n borderColor=\"neutral150\"\n shadow=\"tableShadow\"\n tag=\"section\"\n gap={4}\n padding={6}\n aria-labelledby={id}\n >\n <Flex direction=\"row\" alignItems=\"center\" gap={2} tag=\"header\">\n <Icon fill=\"neutral500\" aria-hidden />\n <Typography textColor=\"neutral500\" variant=\"sigma\" tag=\"h2\" id={id}>\n {formatMessage(title)}\n </Typography>\n </Flex>\n <Box width=\"100%\" height=\"261px\" overflow=\"auto\" tag=\"main\">\n {children}\n </Box>\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * UnstableHomePageCe\n * -----------------------------------------------------------------------------------------------*/\n\nconst WidgetComponent = ({ component }: { component: () => Promise<React.ComponentType> }) => {\n const [loadedComponent, setLoadedComponent] = React.useState<React.ComponentType | null>(null);\n\n React.useEffect(() => {\n const loadComponent = async () => {\n const resolvedComponent = await component();\n\n setLoadedComponent(() => resolvedComponent);\n };\n\n loadComponent();\n }, [component]);\n\n const Component = loadedComponent;\n\n if (!Component) {\n return <Widget.Loading />;\n }\n\n return <Component />;\n};\n\nconst UnstableHomePageCe = () => {\n const { formatMessage } = useIntl();\n const user = useAuth('HomePageCE', (state) => state.user);\n const displayName = user?.firstname ?? user?.username ?? user?.email;\n const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state) => state.widgets.getAll);\n\n return (\n <Main>\n <Page.Title>\n {formatMessage({ id: 'HomePage.head.title', defaultMessage: 'Homepage' })}\n </Page.Title>\n <Layouts.Header\n title={formatMessage(\n { id: 'HomePage.header.title', defaultMessage: 'Hello {name}' },\n { name: displayName }\n )}\n subtitle={formatMessage({\n id: 'HomePage.header.subtitle',\n defaultMessage: 'Welcome to your administration panel',\n })}\n />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={8} paddingBottom={10}>\n <GuidedTour />\n <Grid.Root gap={5}>\n {getAllWidgets().map((widget) => {\n return (\n <Grid.Item col={6} s={12} key={widget.uid}>\n <WidgetRoot title={widget.title} icon={widget.icon}>\n <WidgetComponent component={widget.component} />\n </WidgetRoot>\n </Grid.Item>\n );\n })}\n </Grid.Root>\n </Flex>\n </Layouts.Content>\n </Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePageCE\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePageCE = () => {\n const { formatMessage } = useIntl();\n const user = useAuth('HomePageCE', (state) => state.user);\n const displayName = user?.firstname ?? user?.username ?? user?.email;\n\n if (window.strapi.future.isEnabled('unstableWidgetsApi')) {\n return <UnstableHomePageCe />;\n }\n\n return (\n <Main>\n <Page.Title>\n {formatMessage({ id: 'HomePage.head.title', defaultMessage: 'Homepage' })}\n </Page.Title>\n <Layouts.Header\n title={formatMessage(\n { id: 'HomePage.header.title', defaultMessage: 'Hello {name}' },\n { name: displayName }\n )}\n subtitle={formatMessage({\n id: 'HomePage.header.subtitle',\n defaultMessage: 'Welcome to your administration panel',\n })}\n />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={8} paddingBottom={10}>\n <GuidedTour />\n <Grid.Root gap={5}>\n <Grid.Item col={6} s={12}>\n <WidgetRoot\n title={{\n id: 'content-manager.widget.last-edited.title',\n defaultMessage: 'Last edited entries',\n }}\n icon={Pencil}\n >\n <LastEditedWidget />\n </WidgetRoot>\n </Grid.Item>\n <Grid.Item col={6} s={12}>\n <WidgetRoot\n title={{\n id: 'content-manager.widget.last-published.title',\n defaultMessage: 'Last published entries',\n }}\n icon={CheckCircle}\n >\n <LastPublishedWidget />\n </WidgetRoot>\n </Grid.Item>\n </Grid.Root>\n </Flex>\n </Layouts.Content>\n </Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePage\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePage = () => {\n const Page = useEnterprise(\n HomePageCE,\n // eslint-disable-next-line import/no-cycle\n async () => (await import('../../../../ee/admin/src/pages/HomePage')).HomePageEE\n );\n\n // block rendering until the EE component is fully loaded\n if (!Page) {\n return null;\n }\n\n return <Page />;\n};\n\nexport { HomePage, HomePageCE };\n"],"names":["WidgetRoot","title","icon","PuzzlePiece","children","formatMessage","useIntl","id","React","useId","Icon","_jsxs","Flex","width","hasRadius","direction","alignItems","background","borderColor","shadow","tag","gap","padding","aria-labelledby","_jsx","fill","aria-hidden","Typography","textColor","variant","Box","height","overflow","WidgetComponent","component","loadedComponent","setLoadedComponent","useState","useEffect","loadComponent","resolvedComponent","Component","Widget","Loading","UnstableHomePageCe","user","useAuth","state","displayName","firstname","username","email","getAllWidgets","useStrapiApp","widgets","getAll","Main","Page","Title","defaultMessage","Layouts","Header","name","subtitle","Content","paddingBottom","GuidedTour","Grid","Root","map","widget","Item","col","s","uid","HomePageCE","window","strapi","future","isEnabled","Pencil","LastEditedWidget","CheckCircle","LastPublishedWidget","HomePage","useEnterprise","HomePageEE"],"mappings":"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"}