@strapi/admin 5.27.0 → 5.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/admin/src/components/DragLayer.js +67 -0
- package/dist/admin/admin/src/components/DragLayer.js.map +1 -0
- package/dist/admin/admin/src/components/DragLayer.mjs +64 -0
- package/dist/admin/admin/src/components/DragLayer.mjs.map +1 -0
- package/dist/admin/admin/src/components/GapDropZone.js +292 -0
- package/dist/admin/admin/src/components/GapDropZone.js.map +1 -0
- package/dist/admin/admin/src/components/GapDropZone.mjs +268 -0
- package/dist/admin/admin/src/components/GapDropZone.mjs.map +1 -0
- package/dist/admin/admin/src/components/ResizeIndicator.js +353 -0
- package/dist/admin/admin/src/components/ResizeIndicator.js.map +1 -0
- package/dist/admin/admin/src/components/ResizeIndicator.mjs +332 -0
- package/dist/admin/admin/src/components/ResizeIndicator.mjs.map +1 -0
- package/dist/admin/admin/src/components/WidgetRoot.js +216 -0
- package/dist/admin/admin/src/components/WidgetRoot.js.map +1 -0
- package/dist/admin/admin/src/components/WidgetRoot.mjs +195 -0
- package/dist/admin/admin/src/components/WidgetRoot.mjs.map +1 -0
- package/dist/admin/admin/src/features/Tracking.js.map +1 -1
- package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
- package/dist/admin/admin/src/features/Widgets.js +276 -0
- package/dist/admin/admin/src/features/Widgets.js.map +1 -0
- package/dist/admin/admin/src/features/Widgets.mjs +255 -0
- package/dist/admin/admin/src/features/Widgets.mjs.map +1 -0
- package/dist/admin/admin/src/hooks/useAPIErrorHandler.js +1 -1
- package/dist/admin/admin/src/hooks/useAPIErrorHandler.js.map +1 -1
- package/dist/admin/admin/src/hooks/useAPIErrorHandler.mjs +1 -1
- package/dist/admin/admin/src/hooks/useAPIErrorHandler.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Home/HomePage.js +160 -91
- package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
- package/dist/admin/admin/src/pages/Home/HomePage.mjs +162 -93
- package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.js +189 -0
- package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.js.map +1 -0
- package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.mjs +168 -0
- package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.mjs.map +1 -0
- package/dist/admin/admin/src/services/homepage.js +11 -4
- package/dist/admin/admin/src/services/homepage.js.map +1 -1
- package/dist/admin/admin/src/services/homepage.mjs +11 -4
- package/dist/admin/admin/src/services/homepage.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +6 -1
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +6 -1
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/uk.json.js +9 -9
- package/dist/admin/admin/src/translations/uk.json.mjs +9 -9
- package/dist/admin/admin/src/utils/resizeHandlers.js +109 -0
- package/dist/admin/admin/src/utils/resizeHandlers.js.map +1 -0
- package/dist/admin/admin/src/utils/resizeHandlers.mjs +100 -0
- package/dist/admin/admin/src/utils/resizeHandlers.mjs.map +1 -0
- package/dist/admin/admin/src/utils/widgetLayout.js +293 -0
- package/dist/admin/admin/src/utils/widgetLayout.js.map +1 -0
- package/dist/admin/admin/src/utils/widgetLayout.mjs +273 -0
- package/dist/admin/admin/src/utils/widgetLayout.mjs.map +1 -0
- package/dist/admin/src/components/DragLayer.d.ts +8 -4
- package/dist/admin/src/components/GapDropZone.d.ts +36 -0
- package/dist/admin/src/components/ResizeIndicator.d.ts +12 -0
- package/dist/admin/src/components/WidgetRoot.d.ts +14 -0
- package/dist/admin/src/features/Tracking.d.ts +1 -1
- package/dist/admin/src/features/Widgets.d.ts +29 -0
- package/dist/admin/src/pages/Home/HomePage.d.ts +4 -5
- package/dist/admin/src/pages/Home/components/AddWidgetModal.d.ts +10 -0
- package/dist/admin/src/services/homepage.d.ts +3 -3
- package/dist/admin/src/utils/resizeHandlers.d.ts +58 -0
- package/dist/admin/src/utils/widgetLayout.d.ts +78 -0
- package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js +4 -2
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs +4 -2
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs.map +1 -1
- package/dist/server/server/src/bootstrap.js +5 -0
- package/dist/server/server/src/bootstrap.js.map +1 -1
- package/dist/server/server/src/bootstrap.mjs +5 -0
- package/dist/server/server/src/bootstrap.mjs.map +1 -1
- package/dist/server/shared/utils/session-auth.js +4 -2
- package/dist/server/shared/utils/session-auth.js.map +1 -1
- package/dist/server/shared/utils/session-auth.mjs +4 -2
- package/dist/server/shared/utils/session-auth.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/shared/contracts/homepage.d.ts +8 -4
- package/dist/shared/contracts/homepage.d.ts.map +1 -1
- package/dist/shared/utils/session-auth.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAPIErrorHandler.js","sources":["../../../../../admin/src/hooks/useAPIErrorHandler.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { IntlFormatters, useIntl } from 'react-intl';\n\nimport { FetchError, ApiError } from '../utils/getFetchClient';\nimport { getPrefixedId } from '../utils/getPrefixedId';\nimport { NormalizeErrorOptions, normalizeAPIError } from '../utils/normalizeAPIError';\nimport { setIn } from '../utils/objects';\n\ninterface UnknownApiError {\n /**\n * The name of the ApiError, is always a static value.\n */\n name: 'UnknownError';\n /**\n * The error message.\n */\n message: string;\n /**\n * The error details.\n */\n details?: unknown;\n /**\n * The HTTP status code of the error.\n */\n status?: number;\n}\n\n/**\n * The last item is the fallback error SerializedError which\n * typically comes from redux-toolkit itself.\n */\ninterface SerializedError {\n /**\n * The name of the error.\n */\n name?: string;\n /**\n * The error message that explains what went wrong.\n */\n message?: string;\n /**\n * The stack trace of the error.\n */\n stack?: string;\n /**\n * A specific error code associated with the error.\n */\n code?: string;\n}\n\n/**\n * These are the types or errors we return\n * from the redux-toolkit data-fetching setup.\n */\ntype BaseQueryError = ApiError | UnknownApiError | SerializedError;\n\ninterface YupFormattedError {\n /**\n * An array representing the path to the field where the validation error occurred.\n */\n path: string[];\n /**\n * The error message describing the validation failure.\n */\n message: string;\n /**\n * The name of the error, typically identifies the type of validation error that occurred.\n */\n name: string;\n\n value: string;\n}\n\n/**\n * @public\n * @description The purpose of this hook is to offer a unified way to handle errors thrown by API endpoints, regardless of the type of error (`ValidationError`, `ApplicationErrror` ...)\nthat has been thrown.\n * @example\n * ```tsx\n * import * as React from 'react';\n * import { useFetchClient, useAPIErrorHandler, useNotification } from '@strapi/admin/admin';\n *\n * const MyComponent = () => {\n * const { get } = useFetchClient();\n * const { formatAPIError } = useAPIErrorHandler(getTrad);\n * const { toggleNotification } = useNotification();\n *\n * const handleDeleteItem = async () => {\n * try {\n * return await get('/admin');\n * } catch (error) {\n * toggleNotification({\n * type: 'danger',\n * message: formatAPIError(error),\n * });\n * }\n * };\n * return <button onClick={handleDeleteItem}>Delete item</button>;\n * };\n * ```\n */\nexport function useAPIErrorHandler(\n intlMessagePrefixCallback?: FormatAPIErrorOptions['intlMessagePrefixCallback']\n) {\n const { formatMessage } = useIntl();\n\n /**\n * @description This method try to normalize the passed error\n * and then call formatAPIError to stringify the ResponseObject\n * into a string. If it fails it will call formatFetchError and\n * return the error message.\n */\n const formatError = React.useCallback(\n (error: FetchError) => {\n // Try to normalize the passed error first. This will fail for e.g. network\n // errors which are thrown by fetchClient directly.\n try {\n const formattedErr = formatAPIError(error, { intlMessagePrefixCallback, formatMessage });\n\n if (!formattedErr) {\n return formatFetchError(error, { intlMessagePrefixCallback, formatMessage });\n }\n\n return formattedErr;\n } catch (_) {\n throw new Error('formatAPIError: Unknown error:', error);\n }\n },\n [formatMessage, intlMessagePrefixCallback]\n );\n\n return {\n /**\n * @alpha\n * Convert ValidationErrors from the API into an object that can be used by forms.\n */\n _unstableFormatValidationErrors: React.useCallback(\n (error: Extract<BaseQueryError, { name: 'ValidationError' }>): Record<string, string> => {\n if (typeof error.details === 'object' && error.details !== null) {\n if ('errors' in error.details && Array.isArray(error.details.errors)) {\n const validationErrors = error.details.errors as YupFormattedError[];\n\n return validationErrors.reduce((acc, err) => {\n const { path, message } = err;\n\n return setIn(acc, path.join('.'), message);\n }, {});\n } else {\n const details = error.details as Record<string, string[]>;\n\n return Object.keys(details).reduce((acc, key) => {\n const messages = details[key];\n\n return {\n ...acc,\n [key]: messages.join(', '),\n };\n }, {});\n }\n } else {\n return {};\n }\n },\n []\n ),\n /**\n * @alpha\n * This handles the errors given from `redux-toolkit`'s axios based baseQuery function.\n */\n _unstableFormatAPIError: React.useCallback(\n (error: BaseQueryError) => {\n const err = {\n response: {\n data: {\n error,\n },\n },\n } as FetchError;\n\n /**\n * There's a chance with SerializedErrors that the message is not set.\n * In that case we return a generic error message.\n */\n if (!error.message) {\n return 'Unknown error occured.';\n }\n\n return formatError(err);\n },\n [formatError]\n ),\n formatAPIError: formatError,\n };\n}\n\nfunction formatFetchError(\n error: FetchError,\n { intlMessagePrefixCallback, formatMessage }: FormatAPIErrorOptions\n) {\n const { code, message } = error;\n\n return formatMessage(\n {\n id: getPrefixedId(message, intlMessagePrefixCallback),\n defaultMessage: message,\n },\n {\n code,\n }\n );\n}\n\ntype FormatAPIErrorOptions = Partial<Pick<NormalizeErrorOptions, 'intlMessagePrefixCallback'>> &\n Pick<IntlFormatters, 'formatMessage'>;\n\n/**\n * @description This method stringifies the `ResponseObject` into\n * a string. If multiple errors are thrown by the API, which\n * happens e.g.in the case of a `ValidationError`, all errors\n * will bo concatenated into a single string.\n */\nfunction formatAPIError(\n error: FetchError,\n { formatMessage, intlMessagePrefixCallback }: FormatAPIErrorOptions\n) {\n if (!formatMessage) {\n throw new Error('The formatMessage callback is a mandatory argument.');\n }\n\n const normalizedError = normalizeAPIError(error, intlMessagePrefixCallback);\n\n if (!normalizedError) {\n return null;\n }\n\n if ('message' in normalizedError && normalizedError.message !== null) {\n return normalizedError.message;\n }\n\n // stringify multiple errors\n if ('errors' in normalizedError) {\n return normalizedError.errors\n .map(({ id, defaultMessage, values }) => formatMessage({ id, defaultMessage }, values))\n .join('\\n');\n }\n\n return formatMessage(normalizedError);\n}\n\nexport type { ApiError };\n"],"names":["useAPIErrorHandler","intlMessagePrefixCallback","formatMessage","useIntl","formatError","React","useCallback","error","formattedErr","formatAPIError","formatFetchError","_","Error","_unstableFormatValidationErrors","details","Array","isArray","errors","validationErrors","reduce","acc","err","path","message","setIn","join","Object","keys","key","messages","_unstableFormatAPIError","response","data","code","id","getPrefixedId","defaultMessage","normalizedError","normalizeAPIError","map","values"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAPIErrorHandler.js","sources":["../../../../../admin/src/hooks/useAPIErrorHandler.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { IntlFormatters, useIntl } from 'react-intl';\n\nimport { FetchError, ApiError } from '../utils/getFetchClient';\nimport { getPrefixedId } from '../utils/getPrefixedId';\nimport { NormalizeErrorOptions, normalizeAPIError } from '../utils/normalizeAPIError';\nimport { setIn } from '../utils/objects';\n\ninterface UnknownApiError {\n /**\n * The name of the ApiError, is always a static value.\n */\n name: 'UnknownError';\n /**\n * The error message.\n */\n message: string;\n /**\n * The error details.\n */\n details?: unknown;\n /**\n * The HTTP status code of the error.\n */\n status?: number;\n}\n\n/**\n * The last item is the fallback error SerializedError which\n * typically comes from redux-toolkit itself.\n */\ninterface SerializedError {\n /**\n * The name of the error.\n */\n name?: string;\n /**\n * The error message that explains what went wrong.\n */\n message?: string;\n /**\n * The stack trace of the error.\n */\n stack?: string;\n /**\n * A specific error code associated with the error.\n */\n code?: string;\n}\n\n/**\n * These are the types or errors we return\n * from the redux-toolkit data-fetching setup.\n */\ntype BaseQueryError = ApiError | UnknownApiError | SerializedError;\n\ninterface YupFormattedError {\n /**\n * An array representing the path to the field where the validation error occurred.\n */\n path: string[];\n /**\n * The error message describing the validation failure.\n */\n message: string;\n /**\n * The name of the error, typically identifies the type of validation error that occurred.\n */\n name: string;\n\n value: string;\n}\n\n/**\n * @public\n * @description The purpose of this hook is to offer a unified way to handle errors thrown by API endpoints, regardless of the type of error (`ValidationError`, `ApplicationErrror` ...)\nthat has been thrown.\n * @example\n * ```tsx\n * import * as React from 'react';\n * import { useFetchClient, useAPIErrorHandler, useNotification } from '@strapi/admin/admin';\n *\n * const MyComponent = () => {\n * const { get } = useFetchClient();\n * const { formatAPIError } = useAPIErrorHandler(getTrad);\n * const { toggleNotification } = useNotification();\n *\n * const handleDeleteItem = async () => {\n * try {\n * return await get('/admin');\n * } catch (error) {\n * toggleNotification({\n * type: 'danger',\n * message: formatAPIError(error),\n * });\n * }\n * };\n * return <button onClick={handleDeleteItem}>Delete item</button>;\n * };\n * ```\n */\nexport function useAPIErrorHandler(\n intlMessagePrefixCallback?: FormatAPIErrorOptions['intlMessagePrefixCallback']\n) {\n const { formatMessage } = useIntl();\n\n /**\n * @description This method try to normalize the passed error\n * and then call formatAPIError to stringify the ResponseObject\n * into a string. If it fails it will call formatFetchError and\n * return the error message.\n */\n const formatError = React.useCallback(\n (error: FetchError) => {\n // Try to normalize the passed error first. This will fail for e.g. network\n // errors which are thrown by fetchClient directly.\n try {\n const formattedErr = formatAPIError(error, { intlMessagePrefixCallback, formatMessage });\n\n if (!formattedErr) {\n return formatFetchError(error, { intlMessagePrefixCallback, formatMessage });\n }\n\n return formattedErr;\n } catch (_) {\n throw new Error('formatAPIError: Unknown error:', error);\n }\n },\n [formatMessage, intlMessagePrefixCallback]\n );\n\n return {\n /**\n * @alpha\n * Convert ValidationErrors from the API into an object that can be used by forms.\n */\n _unstableFormatValidationErrors: React.useCallback(\n (error: Extract<BaseQueryError, { name: 'ValidationError' }>): Record<string, string> => {\n if (typeof error.details === 'object' && error.details !== null) {\n if ('errors' in error.details && Array.isArray(error.details.errors)) {\n const validationErrors = error.details.errors as YupFormattedError[];\n\n return validationErrors.reduce((acc, err) => {\n const { path, message } = err;\n\n return setIn(acc, path.join('.'), message);\n }, {});\n } else {\n const details = error.details as Record<string, string[]>;\n\n return Object.keys(details).reduce((acc, key) => {\n const messages = details[key];\n\n return {\n ...acc,\n [key]: messages.join(', '),\n };\n }, {});\n }\n } else {\n return {};\n }\n },\n []\n ),\n /**\n * @alpha\n * This handles the errors given from `redux-toolkit`'s axios based baseQuery function.\n */\n _unstableFormatAPIError: React.useCallback(\n (error: BaseQueryError) => {\n const err = {\n response: {\n data: {\n error,\n },\n },\n } as FetchError;\n\n /**\n * There's a chance with SerializedErrors that the message is not set.\n * In that case we return a generic error message.\n */\n if (!error.message) {\n return 'Unknown error occurred.';\n }\n\n return formatError(err);\n },\n [formatError]\n ),\n formatAPIError: formatError,\n };\n}\n\nfunction formatFetchError(\n error: FetchError,\n { intlMessagePrefixCallback, formatMessage }: FormatAPIErrorOptions\n) {\n const { code, message } = error;\n\n return formatMessage(\n {\n id: getPrefixedId(message, intlMessagePrefixCallback),\n defaultMessage: message,\n },\n {\n code,\n }\n );\n}\n\ntype FormatAPIErrorOptions = Partial<Pick<NormalizeErrorOptions, 'intlMessagePrefixCallback'>> &\n Pick<IntlFormatters, 'formatMessage'>;\n\n/**\n * @description This method stringifies the `ResponseObject` into\n * a string. If multiple errors are thrown by the API, which\n * happens e.g.in the case of a `ValidationError`, all errors\n * will bo concatenated into a single string.\n */\nfunction formatAPIError(\n error: FetchError,\n { formatMessage, intlMessagePrefixCallback }: FormatAPIErrorOptions\n) {\n if (!formatMessage) {\n throw new Error('The formatMessage callback is a mandatory argument.');\n }\n\n const normalizedError = normalizeAPIError(error, intlMessagePrefixCallback);\n\n if (!normalizedError) {\n return null;\n }\n\n if ('message' in normalizedError && normalizedError.message !== null) {\n return normalizedError.message;\n }\n\n // stringify multiple errors\n if ('errors' in normalizedError) {\n return normalizedError.errors\n .map(({ id, defaultMessage, values }) => formatMessage({ id, defaultMessage }, values))\n .join('\\n');\n }\n\n return formatMessage(normalizedError);\n}\n\nexport type { ApiError };\n"],"names":["useAPIErrorHandler","intlMessagePrefixCallback","formatMessage","useIntl","formatError","React","useCallback","error","formattedErr","formatAPIError","formatFetchError","_","Error","_unstableFormatValidationErrors","details","Array","isArray","errors","validationErrors","reduce","acc","err","path","message","setIn","join","Object","keys","key","messages","_unstableFormatAPIError","response","data","code","id","getPrefixedId","defaultMessage","normalizedError","normalizeAPIError","map","values"],"mappings":"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"}
|
|
@@ -101,7 +101,7 @@ that has been thrown.
|
|
|
101
101
|
* There's a chance with SerializedErrors that the message is not set.
|
|
102
102
|
* In that case we return a generic error message.
|
|
103
103
|
*/ if (!error.message) {
|
|
104
|
-
return 'Unknown error
|
|
104
|
+
return 'Unknown error occurred.';
|
|
105
105
|
}
|
|
106
106
|
return formatError(err);
|
|
107
107
|
}, [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAPIErrorHandler.mjs","sources":["../../../../../admin/src/hooks/useAPIErrorHandler.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { IntlFormatters, useIntl } from 'react-intl';\n\nimport { FetchError, ApiError } from '../utils/getFetchClient';\nimport { getPrefixedId } from '../utils/getPrefixedId';\nimport { NormalizeErrorOptions, normalizeAPIError } from '../utils/normalizeAPIError';\nimport { setIn } from '../utils/objects';\n\ninterface UnknownApiError {\n /**\n * The name of the ApiError, is always a static value.\n */\n name: 'UnknownError';\n /**\n * The error message.\n */\n message: string;\n /**\n * The error details.\n */\n details?: unknown;\n /**\n * The HTTP status code of the error.\n */\n status?: number;\n}\n\n/**\n * The last item is the fallback error SerializedError which\n * typically comes from redux-toolkit itself.\n */\ninterface SerializedError {\n /**\n * The name of the error.\n */\n name?: string;\n /**\n * The error message that explains what went wrong.\n */\n message?: string;\n /**\n * The stack trace of the error.\n */\n stack?: string;\n /**\n * A specific error code associated with the error.\n */\n code?: string;\n}\n\n/**\n * These are the types or errors we return\n * from the redux-toolkit data-fetching setup.\n */\ntype BaseQueryError = ApiError | UnknownApiError | SerializedError;\n\ninterface YupFormattedError {\n /**\n * An array representing the path to the field where the validation error occurred.\n */\n path: string[];\n /**\n * The error message describing the validation failure.\n */\n message: string;\n /**\n * The name of the error, typically identifies the type of validation error that occurred.\n */\n name: string;\n\n value: string;\n}\n\n/**\n * @public\n * @description The purpose of this hook is to offer a unified way to handle errors thrown by API endpoints, regardless of the type of error (`ValidationError`, `ApplicationErrror` ...)\nthat has been thrown.\n * @example\n * ```tsx\n * import * as React from 'react';\n * import { useFetchClient, useAPIErrorHandler, useNotification } from '@strapi/admin/admin';\n *\n * const MyComponent = () => {\n * const { get } = useFetchClient();\n * const { formatAPIError } = useAPIErrorHandler(getTrad);\n * const { toggleNotification } = useNotification();\n *\n * const handleDeleteItem = async () => {\n * try {\n * return await get('/admin');\n * } catch (error) {\n * toggleNotification({\n * type: 'danger',\n * message: formatAPIError(error),\n * });\n * }\n * };\n * return <button onClick={handleDeleteItem}>Delete item</button>;\n * };\n * ```\n */\nexport function useAPIErrorHandler(\n intlMessagePrefixCallback?: FormatAPIErrorOptions['intlMessagePrefixCallback']\n) {\n const { formatMessage } = useIntl();\n\n /**\n * @description This method try to normalize the passed error\n * and then call formatAPIError to stringify the ResponseObject\n * into a string. If it fails it will call formatFetchError and\n * return the error message.\n */\n const formatError = React.useCallback(\n (error: FetchError) => {\n // Try to normalize the passed error first. This will fail for e.g. network\n // errors which are thrown by fetchClient directly.\n try {\n const formattedErr = formatAPIError(error, { intlMessagePrefixCallback, formatMessage });\n\n if (!formattedErr) {\n return formatFetchError(error, { intlMessagePrefixCallback, formatMessage });\n }\n\n return formattedErr;\n } catch (_) {\n throw new Error('formatAPIError: Unknown error:', error);\n }\n },\n [formatMessage, intlMessagePrefixCallback]\n );\n\n return {\n /**\n * @alpha\n * Convert ValidationErrors from the API into an object that can be used by forms.\n */\n _unstableFormatValidationErrors: React.useCallback(\n (error: Extract<BaseQueryError, { name: 'ValidationError' }>): Record<string, string> => {\n if (typeof error.details === 'object' && error.details !== null) {\n if ('errors' in error.details && Array.isArray(error.details.errors)) {\n const validationErrors = error.details.errors as YupFormattedError[];\n\n return validationErrors.reduce((acc, err) => {\n const { path, message } = err;\n\n return setIn(acc, path.join('.'), message);\n }, {});\n } else {\n const details = error.details as Record<string, string[]>;\n\n return Object.keys(details).reduce((acc, key) => {\n const messages = details[key];\n\n return {\n ...acc,\n [key]: messages.join(', '),\n };\n }, {});\n }\n } else {\n return {};\n }\n },\n []\n ),\n /**\n * @alpha\n * This handles the errors given from `redux-toolkit`'s axios based baseQuery function.\n */\n _unstableFormatAPIError: React.useCallback(\n (error: BaseQueryError) => {\n const err = {\n response: {\n data: {\n error,\n },\n },\n } as FetchError;\n\n /**\n * There's a chance with SerializedErrors that the message is not set.\n * In that case we return a generic error message.\n */\n if (!error.message) {\n return 'Unknown error occured.';\n }\n\n return formatError(err);\n },\n [formatError]\n ),\n formatAPIError: formatError,\n };\n}\n\nfunction formatFetchError(\n error: FetchError,\n { intlMessagePrefixCallback, formatMessage }: FormatAPIErrorOptions\n) {\n const { code, message } = error;\n\n return formatMessage(\n {\n id: getPrefixedId(message, intlMessagePrefixCallback),\n defaultMessage: message,\n },\n {\n code,\n }\n );\n}\n\ntype FormatAPIErrorOptions = Partial<Pick<NormalizeErrorOptions, 'intlMessagePrefixCallback'>> &\n Pick<IntlFormatters, 'formatMessage'>;\n\n/**\n * @description This method stringifies the `ResponseObject` into\n * a string. If multiple errors are thrown by the API, which\n * happens e.g.in the case of a `ValidationError`, all errors\n * will bo concatenated into a single string.\n */\nfunction formatAPIError(\n error: FetchError,\n { formatMessage, intlMessagePrefixCallback }: FormatAPIErrorOptions\n) {\n if (!formatMessage) {\n throw new Error('The formatMessage callback is a mandatory argument.');\n }\n\n const normalizedError = normalizeAPIError(error, intlMessagePrefixCallback);\n\n if (!normalizedError) {\n return null;\n }\n\n if ('message' in normalizedError && normalizedError.message !== null) {\n return normalizedError.message;\n }\n\n // stringify multiple errors\n if ('errors' in normalizedError) {\n return normalizedError.errors\n .map(({ id, defaultMessage, values }) => formatMessage({ id, defaultMessage }, values))\n .join('\\n');\n }\n\n return formatMessage(normalizedError);\n}\n\nexport type { ApiError };\n"],"names":["useAPIErrorHandler","intlMessagePrefixCallback","formatMessage","useIntl","formatError","React","useCallback","error","formattedErr","formatAPIError","formatFetchError","_","Error","_unstableFormatValidationErrors","details","Array","isArray","errors","validationErrors","reduce","acc","err","path","message","setIn","join","Object","keys","key","messages","_unstableFormatAPIError","response","data","code","id","getPrefixedId","defaultMessage","normalizedError","normalizeAPIError","map","values"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAPIErrorHandler.mjs","sources":["../../../../../admin/src/hooks/useAPIErrorHandler.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { IntlFormatters, useIntl } from 'react-intl';\n\nimport { FetchError, ApiError } from '../utils/getFetchClient';\nimport { getPrefixedId } from '../utils/getPrefixedId';\nimport { NormalizeErrorOptions, normalizeAPIError } from '../utils/normalizeAPIError';\nimport { setIn } from '../utils/objects';\n\ninterface UnknownApiError {\n /**\n * The name of the ApiError, is always a static value.\n */\n name: 'UnknownError';\n /**\n * The error message.\n */\n message: string;\n /**\n * The error details.\n */\n details?: unknown;\n /**\n * The HTTP status code of the error.\n */\n status?: number;\n}\n\n/**\n * The last item is the fallback error SerializedError which\n * typically comes from redux-toolkit itself.\n */\ninterface SerializedError {\n /**\n * The name of the error.\n */\n name?: string;\n /**\n * The error message that explains what went wrong.\n */\n message?: string;\n /**\n * The stack trace of the error.\n */\n stack?: string;\n /**\n * A specific error code associated with the error.\n */\n code?: string;\n}\n\n/**\n * These are the types or errors we return\n * from the redux-toolkit data-fetching setup.\n */\ntype BaseQueryError = ApiError | UnknownApiError | SerializedError;\n\ninterface YupFormattedError {\n /**\n * An array representing the path to the field where the validation error occurred.\n */\n path: string[];\n /**\n * The error message describing the validation failure.\n */\n message: string;\n /**\n * The name of the error, typically identifies the type of validation error that occurred.\n */\n name: string;\n\n value: string;\n}\n\n/**\n * @public\n * @description The purpose of this hook is to offer a unified way to handle errors thrown by API endpoints, regardless of the type of error (`ValidationError`, `ApplicationErrror` ...)\nthat has been thrown.\n * @example\n * ```tsx\n * import * as React from 'react';\n * import { useFetchClient, useAPIErrorHandler, useNotification } from '@strapi/admin/admin';\n *\n * const MyComponent = () => {\n * const { get } = useFetchClient();\n * const { formatAPIError } = useAPIErrorHandler(getTrad);\n * const { toggleNotification } = useNotification();\n *\n * const handleDeleteItem = async () => {\n * try {\n * return await get('/admin');\n * } catch (error) {\n * toggleNotification({\n * type: 'danger',\n * message: formatAPIError(error),\n * });\n * }\n * };\n * return <button onClick={handleDeleteItem}>Delete item</button>;\n * };\n * ```\n */\nexport function useAPIErrorHandler(\n intlMessagePrefixCallback?: FormatAPIErrorOptions['intlMessagePrefixCallback']\n) {\n const { formatMessage } = useIntl();\n\n /**\n * @description This method try to normalize the passed error\n * and then call formatAPIError to stringify the ResponseObject\n * into a string. If it fails it will call formatFetchError and\n * return the error message.\n */\n const formatError = React.useCallback(\n (error: FetchError) => {\n // Try to normalize the passed error first. This will fail for e.g. network\n // errors which are thrown by fetchClient directly.\n try {\n const formattedErr = formatAPIError(error, { intlMessagePrefixCallback, formatMessage });\n\n if (!formattedErr) {\n return formatFetchError(error, { intlMessagePrefixCallback, formatMessage });\n }\n\n return formattedErr;\n } catch (_) {\n throw new Error('formatAPIError: Unknown error:', error);\n }\n },\n [formatMessage, intlMessagePrefixCallback]\n );\n\n return {\n /**\n * @alpha\n * Convert ValidationErrors from the API into an object that can be used by forms.\n */\n _unstableFormatValidationErrors: React.useCallback(\n (error: Extract<BaseQueryError, { name: 'ValidationError' }>): Record<string, string> => {\n if (typeof error.details === 'object' && error.details !== null) {\n if ('errors' in error.details && Array.isArray(error.details.errors)) {\n const validationErrors = error.details.errors as YupFormattedError[];\n\n return validationErrors.reduce((acc, err) => {\n const { path, message } = err;\n\n return setIn(acc, path.join('.'), message);\n }, {});\n } else {\n const details = error.details as Record<string, string[]>;\n\n return Object.keys(details).reduce((acc, key) => {\n const messages = details[key];\n\n return {\n ...acc,\n [key]: messages.join(', '),\n };\n }, {});\n }\n } else {\n return {};\n }\n },\n []\n ),\n /**\n * @alpha\n * This handles the errors given from `redux-toolkit`'s axios based baseQuery function.\n */\n _unstableFormatAPIError: React.useCallback(\n (error: BaseQueryError) => {\n const err = {\n response: {\n data: {\n error,\n },\n },\n } as FetchError;\n\n /**\n * There's a chance with SerializedErrors that the message is not set.\n * In that case we return a generic error message.\n */\n if (!error.message) {\n return 'Unknown error occurred.';\n }\n\n return formatError(err);\n },\n [formatError]\n ),\n formatAPIError: formatError,\n };\n}\n\nfunction formatFetchError(\n error: FetchError,\n { intlMessagePrefixCallback, formatMessage }: FormatAPIErrorOptions\n) {\n const { code, message } = error;\n\n return formatMessage(\n {\n id: getPrefixedId(message, intlMessagePrefixCallback),\n defaultMessage: message,\n },\n {\n code,\n }\n );\n}\n\ntype FormatAPIErrorOptions = Partial<Pick<NormalizeErrorOptions, 'intlMessagePrefixCallback'>> &\n Pick<IntlFormatters, 'formatMessage'>;\n\n/**\n * @description This method stringifies the `ResponseObject` into\n * a string. If multiple errors are thrown by the API, which\n * happens e.g.in the case of a `ValidationError`, all errors\n * will bo concatenated into a single string.\n */\nfunction formatAPIError(\n error: FetchError,\n { formatMessage, intlMessagePrefixCallback }: FormatAPIErrorOptions\n) {\n if (!formatMessage) {\n throw new Error('The formatMessage callback is a mandatory argument.');\n }\n\n const normalizedError = normalizeAPIError(error, intlMessagePrefixCallback);\n\n if (!normalizedError) {\n return null;\n }\n\n if ('message' in normalizedError && normalizedError.message !== null) {\n return normalizedError.message;\n }\n\n // stringify multiple errors\n if ('errors' in normalizedError) {\n return normalizedError.errors\n .map(({ id, defaultMessage, values }) => formatMessage({ id, defaultMessage }, values))\n .join('\\n');\n }\n\n return formatMessage(normalizedError);\n}\n\nexport type { ApiError };\n"],"names":["useAPIErrorHandler","intlMessagePrefixCallback","formatMessage","useIntl","formatError","React","useCallback","error","formattedErr","formatAPIError","formatFetchError","_","Error","_unstableFormatValidationErrors","details","Array","isArray","errors","validationErrors","reduce","acc","err","path","message","setIn","join","Object","keys","key","messages","_unstableFormatAPIError","response","data","code","id","getPrefixedId","defaultMessage","normalizedError","normalizeAPIError","map","values"],"mappings":";;;;;;AA0EA;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4BO,SAASA,kBAAAA,CACdC,yBAA8E,EAAA;IAE9E,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1B;;;;;AAKC,MACD,MAAMC,WAAAA,GAAcC,KAAMC,CAAAA,WAAW,CACnC,CAACC,KAAAA,GAAAA;;;QAGC,IAAI;YACF,MAAMC,YAAAA,GAAeC,eAAeF,KAAO,EAAA;AAAEN,gBAAAA,yBAAAA;AAA2BC,gBAAAA;AAAc,aAAA,CAAA;AAEtF,YAAA,IAAI,CAACM,YAAc,EAAA;AACjB,gBAAA,OAAOE,iBAAiBH,KAAO,EAAA;AAAEN,oBAAAA,yBAAAA;AAA2BC,oBAAAA;AAAc,iBAAA,CAAA;AAC5E;YAEA,OAAOM,YAAAA;AACT,SAAA,CAAE,OAAOG,CAAG,EAAA;YACV,MAAM,IAAIC,MAAM,gCAAkCL,EAAAA,KAAAA,CAAAA;AACpD;KAEF,EAAA;AAACL,QAAAA,aAAAA;AAAeD,QAAAA;AAA0B,KAAA,CAAA;IAG5C,OAAO;AACL;;;AAGC,QACDY,+BAAiCR,EAAAA,KAAAA,CAAMC,WAAW,CAChD,CAACC,KAAAA,GAAAA;YACC,IAAI,OAAOA,MAAMO,OAAO,KAAK,YAAYP,KAAMO,CAAAA,OAAO,KAAK,IAAM,EAAA;gBAC/D,IAAI,QAAA,IAAYP,KAAMO,CAAAA,OAAO,IAAIC,KAAAA,CAAMC,OAAO,CAACT,KAAMO,CAAAA,OAAO,CAACG,MAAM,CAAG,EAAA;AACpE,oBAAA,MAAMC,gBAAmBX,GAAAA,KAAAA,CAAMO,OAAO,CAACG,MAAM;AAE7C,oBAAA,OAAOC,gBAAiBC,CAAAA,MAAM,CAAC,CAACC,GAAKC,EAAAA,GAAAA,GAAAA;AACnC,wBAAA,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAE,GAAGF,GAAAA;AAE1B,wBAAA,OAAOG,KAAMJ,CAAAA,GAAAA,EAAKE,IAAKG,CAAAA,IAAI,CAAC,GAAMF,CAAAA,EAAAA,OAAAA,CAAAA;AACpC,qBAAA,EAAG,EAAC,CAAA;iBACC,MAAA;oBACL,MAAMT,OAAAA,GAAUP,MAAMO,OAAO;AAE7B,oBAAA,OAAOY,OAAOC,IAAI,CAACb,SAASK,MAAM,CAAC,CAACC,GAAKQ,EAAAA,GAAAA,GAAAA;wBACvC,MAAMC,QAAAA,GAAWf,OAAO,CAACc,GAAI,CAAA;wBAE7B,OAAO;AACL,4BAAA,GAAGR,GAAG;AACN,4BAAA,CAACQ,GAAI,GAAEC,QAASJ,CAAAA,IAAI,CAAC,IAAA;AACvB,yBAAA;AACF,qBAAA,EAAG,EAAC,CAAA;AACN;aACK,MAAA;AACL,gBAAA,OAAO,EAAC;AACV;AACF,SAAA,EACA,EAAE,CAAA;AAEJ;;;AAGC,QACDK,uBAAyBzB,EAAAA,KAAAA,CAAMC,WAAW,CACxC,CAACC,KAAAA,GAAAA;AACC,YAAA,MAAMc,GAAM,GAAA;gBACVU,QAAU,EAAA;oBACRC,IAAM,EAAA;AACJzB,wBAAAA;AACF;AACF;AACF,aAAA;AAEA;;;AAGC,YACD,IAAI,CAACA,KAAMgB,CAAAA,OAAO,EAAE;gBAClB,OAAO,yBAAA;AACT;AAEA,YAAA,OAAOnB,WAAYiB,CAAAA,GAAAA,CAAAA;SAErB,EAAA;AAACjB,YAAAA;AAAY,SAAA,CAAA;QAEfK,cAAgBL,EAAAA;AAClB,KAAA;AACF;AAEA,SAASM,iBACPH,KAAiB,EACjB,EAAEN,yBAAyB,EAAEC,aAAa,EAAyB,EAAA;AAEnE,IAAA,MAAM,EAAE+B,IAAI,EAAEV,OAAO,EAAE,GAAGhB,KAAAA;AAE1B,IAAA,OAAOL,aACL,CAAA;AACEgC,QAAAA,EAAAA,EAAIC,cAAcZ,OAAStB,EAAAA,yBAAAA,CAAAA;QAC3BmC,cAAgBb,EAAAA;KAElB,EAAA;AACEU,QAAAA;AACF,KAAA,CAAA;AAEJ;AAKA;;;;;IAMA,SAASxB,eACPF,KAAiB,EACjB,EAAEL,aAAa,EAAED,yBAAyB,EAAyB,EAAA;AAEnE,IAAA,IAAI,CAACC,aAAe,EAAA;AAClB,QAAA,MAAM,IAAIU,KAAM,CAAA,qDAAA,CAAA;AAClB;IAEA,MAAMyB,eAAAA,GAAkBC,kBAAkB/B,KAAON,EAAAA,yBAAAA,CAAAA;AAEjD,IAAA,IAAI,CAACoC,eAAiB,EAAA;QACpB,OAAO,IAAA;AACT;AAEA,IAAA,IAAI,SAAaA,IAAAA,eAAAA,IAAmBA,eAAgBd,CAAAA,OAAO,KAAK,IAAM,EAAA;AACpE,QAAA,OAAOc,gBAAgBd,OAAO;AAChC;;AAGA,IAAA,IAAI,YAAYc,eAAiB,EAAA;AAC/B,QAAA,OAAOA,eAAgBpB,CAAAA,MAAM,CAC1BsB,GAAG,CAAC,CAAC,EAAEL,EAAE,EAAEE,cAAc,EAAEI,MAAM,EAAE,GAAKtC,aAAc,CAAA;AAAEgC,gBAAAA,EAAAA;AAAIE,gBAAAA;aAAkBI,EAAAA,MAAAA,CAAAA,CAAAA,CAC9Ef,IAAI,CAAC,IAAA,CAAA;AACV;AAEA,IAAA,OAAOvB,aAAcmC,CAAAA,eAAAA,CAAAA;AACvB;;;;"}
|
|
@@ -5,17 +5,24 @@ var React = require('react');
|
|
|
5
5
|
var designSystem = require('@strapi/design-system');
|
|
6
6
|
var icons = require('@strapi/icons');
|
|
7
7
|
var reactIntl = require('react-intl');
|
|
8
|
-
var
|
|
8
|
+
var styled = require('styled-components');
|
|
9
|
+
var DragLayer = require('../../components/DragLayer.js');
|
|
10
|
+
var GapDropZone = require('../../components/GapDropZone.js');
|
|
9
11
|
var Overview = require('../../components/GuidedTour/Overview.js');
|
|
10
12
|
var Layout = require('../../components/Layouts/Layout.js');
|
|
11
13
|
var PageHelpers = require('../../components/PageHelpers.js');
|
|
14
|
+
var ResizeIndicator = require('../../components/ResizeIndicator.js');
|
|
12
15
|
var WidgetHelpers = require('../../components/WidgetHelpers.js');
|
|
16
|
+
var WidgetRoot = require('../../components/WidgetRoot.js');
|
|
13
17
|
require('../../services/admin.js');
|
|
14
18
|
var useEnterprise = require('../../hooks/useEnterprise.js');
|
|
15
19
|
require('../../../../ee/admin/src/services/ai.js');
|
|
16
20
|
var Auth = require('../../features/Auth.js');
|
|
17
21
|
var StrapiApp = require('../../features/StrapiApp.js');
|
|
18
|
-
var
|
|
22
|
+
var Widgets = require('../../features/Widgets.js');
|
|
23
|
+
var homepage = require('../../services/homepage.js');
|
|
24
|
+
var widgetLayout = require('../../utils/widgetLayout.js');
|
|
25
|
+
var AddWidgetModal = require('./components/AddWidgetModal.js');
|
|
19
26
|
var FreeTrialEndedModal = require('./components/FreeTrialEndedModal.js');
|
|
20
27
|
var FreeTrialWelcomeModal = require('./components/FreeTrialWelcomeModal.js');
|
|
21
28
|
|
|
@@ -38,79 +45,18 @@ function _interopNamespaceDefault(e) {
|
|
|
38
45
|
|
|
39
46
|
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
};
|
|
51
|
-
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
52
|
-
width: "100%",
|
|
53
|
-
hasRadius: true,
|
|
54
|
-
direction: "column",
|
|
55
|
-
alignItems: "flex-start",
|
|
56
|
-
background: "neutral0",
|
|
57
|
-
borderColor: "neutral150",
|
|
58
|
-
shadow: "tableShadow",
|
|
59
|
-
tag: "section",
|
|
60
|
-
gap: 4,
|
|
61
|
-
padding: 6,
|
|
62
|
-
"aria-labelledby": id,
|
|
63
|
-
children: [
|
|
64
|
-
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
65
|
-
direction: "row",
|
|
66
|
-
gap: 2,
|
|
67
|
-
justifyContent: "space-between",
|
|
68
|
-
width: "100%",
|
|
69
|
-
tag: "header",
|
|
70
|
-
children: [
|
|
71
|
-
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
72
|
-
gap: 2,
|
|
73
|
-
children: [
|
|
74
|
-
/*#__PURE__*/ jsxRuntime.jsx(Icon, {
|
|
75
|
-
fill: "neutral500",
|
|
76
|
-
"aria-hidden": true
|
|
77
|
-
}),
|
|
78
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
79
|
-
textColor: "neutral500",
|
|
80
|
-
variant: "sigma",
|
|
81
|
-
tag: "h2",
|
|
82
|
-
id: id,
|
|
83
|
-
children: formatMessage(title)
|
|
84
|
-
})
|
|
85
|
-
]
|
|
86
|
-
}),
|
|
87
|
-
link && /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
88
|
-
tag: reactRouterDom.Link,
|
|
89
|
-
variant: "omega",
|
|
90
|
-
textColor: "primary600",
|
|
91
|
-
style: {
|
|
92
|
-
textDecoration: 'none'
|
|
93
|
-
},
|
|
94
|
-
textAlign: "right",
|
|
95
|
-
to: link.href,
|
|
96
|
-
onClick: handleClickOnLink,
|
|
97
|
-
children: formatMessage(link.label)
|
|
98
|
-
})
|
|
99
|
-
]
|
|
100
|
-
}),
|
|
101
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
|
102
|
-
width: "100%",
|
|
103
|
-
height: "261px",
|
|
104
|
-
overflow: "auto",
|
|
105
|
-
tag: "main",
|
|
106
|
-
children: children
|
|
107
|
-
})
|
|
108
|
-
]
|
|
109
|
-
});
|
|
110
|
-
};
|
|
48
|
+
// Styled wrapper for the drag preview
|
|
49
|
+
const DragPreviewWrapper = styled.styled.div`
|
|
50
|
+
max-width: ${(props)=>props.$maxWidth};
|
|
51
|
+
overflow: hidden;
|
|
52
|
+
opacity: 0.9;
|
|
53
|
+
border: 2px solid ${({ theme })=>theme.colors.primary500};
|
|
54
|
+
border-radius: ${({ theme })=>theme.borderRadius};
|
|
55
|
+
pointer-events: none;
|
|
56
|
+
`;
|
|
111
57
|
/* -------------------------------------------------------------------------------------------------
|
|
112
58
|
* UnstableHomePageCe
|
|
113
|
-
* -----------------------------------------------------------------------------------------------*/ const WidgetComponent = ({ component })=>{
|
|
59
|
+
* -----------------------------------------------------------------------------------------------*/ const WidgetComponent = ({ component, columnWidth })=>{
|
|
114
60
|
const [loadedComponent, setLoadedComponent] = React__namespace.useState(null);
|
|
115
61
|
React__namespace.useEffect(()=>{
|
|
116
62
|
const loadComponent = async ()=>{
|
|
@@ -125,7 +71,11 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children, link, uid })=>{
|
|
|
125
71
|
if (!Component) {
|
|
126
72
|
return /*#__PURE__*/ jsxRuntime.jsx(WidgetHelpers.Widget.Loading, {});
|
|
127
73
|
}
|
|
128
|
-
return /*#__PURE__*/ jsxRuntime.jsx(Component, {
|
|
74
|
+
return /*#__PURE__*/ jsxRuntime.jsx(Component, {
|
|
75
|
+
...{
|
|
76
|
+
columnWidth
|
|
77
|
+
}
|
|
78
|
+
});
|
|
129
79
|
};
|
|
130
80
|
/* -------------------------------------------------------------------------------------------------
|
|
131
81
|
* HomePageCE
|
|
@@ -135,8 +85,16 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children, link, uid })=>{
|
|
|
135
85
|
const displayName = user?.firstname ?? user?.username ?? user?.email;
|
|
136
86
|
const getAllWidgets = StrapiApp.useStrapiApp('UnstableHomepageCe', (state)=>state.widgets.getAll);
|
|
137
87
|
const checkUserHasPermissions = Auth.useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
|
|
88
|
+
const { data: homepageLayout, isLoading: _isLoadingLayout } = homepage.useGetHomepageLayoutQuery();
|
|
138
89
|
const [filteredWidgets, setFilteredWidgets] = React__namespace.useState([]);
|
|
90
|
+
const [allAvailableWidgets, setAllAvailableWidgets] = React__namespace.useState([]);
|
|
139
91
|
const [loading, setLoading] = React__namespace.useState(true);
|
|
92
|
+
const [isAddWidgetModalOpen, setIsAddWidgetModalOpen] = React__namespace.useState(false);
|
|
93
|
+
// Use custom hook for widget management
|
|
94
|
+
const { findWidget, deleteWidget, addWidget, moveWidget, columnWidths, setColumnWidths, handleWidgetResize, saveLayout, isDraggingWidget, draggedWidgetId, handleDragStart, handleDragEnd } = Widgets.useWidgets({
|
|
95
|
+
filteredWidgets,
|
|
96
|
+
setFilteredWidgets
|
|
97
|
+
});
|
|
140
98
|
React__namespace.useEffect(()=>{
|
|
141
99
|
const checkWidgetsPermissions = async ()=>{
|
|
142
100
|
const allWidgets = getAllWidgets();
|
|
@@ -145,7 +103,8 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children, link, uid })=>{
|
|
|
145
103
|
const matchingPermissions = await checkUserHasPermissions(widget.permissions);
|
|
146
104
|
return matchingPermissions.length >= widget.permissions.length;
|
|
147
105
|
}));
|
|
148
|
-
|
|
106
|
+
const authorizedWidgetsList = allWidgets.filter((_, i)=>authorizedWidgets[i]);
|
|
107
|
+
setAllAvailableWidgets(authorizedWidgetsList);
|
|
149
108
|
setLoading(false);
|
|
150
109
|
};
|
|
151
110
|
checkWidgetsPermissions();
|
|
@@ -153,6 +112,42 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children, link, uid })=>{
|
|
|
153
112
|
checkUserHasPermissions,
|
|
154
113
|
getAllWidgets
|
|
155
114
|
]);
|
|
115
|
+
React__namespace.useEffect(()=>{
|
|
116
|
+
if (allAvailableWidgets.length === 0) return;
|
|
117
|
+
// If user has customized the homepage layout, apply it
|
|
118
|
+
if (homepageLayout && homepageLayout.widgets) {
|
|
119
|
+
const { filteredWidgets, widths: homepageWidths } = widgetLayout.applyHomepageLayout(allAvailableWidgets, homepageLayout);
|
|
120
|
+
setFilteredWidgets(filteredWidgets);
|
|
121
|
+
setColumnWidths(homepageWidths);
|
|
122
|
+
} else {
|
|
123
|
+
// Set default layout when no custom layout exists
|
|
124
|
+
setFilteredWidgets(allAvailableWidgets);
|
|
125
|
+
setColumnWidths(widgetLayout.createDefaultWidgetWidths(allAvailableWidgets));
|
|
126
|
+
}
|
|
127
|
+
}, [
|
|
128
|
+
homepageLayout,
|
|
129
|
+
allAvailableWidgets,
|
|
130
|
+
setColumnWidths
|
|
131
|
+
]);
|
|
132
|
+
const widgetLayout$1 = React__namespace.useMemo(()=>{
|
|
133
|
+
return filteredWidgets.map((widget, index)=>{
|
|
134
|
+
const rightWidgetId = filteredWidgets[index + 1]?.uid;
|
|
135
|
+
const widgetWidth = widgetLayout.getWidgetWidth(columnWidths, widget.uid);
|
|
136
|
+
const rightWidgetWidth = widgetLayout.getWidgetWidth(columnWidths, rightWidgetId);
|
|
137
|
+
return {
|
|
138
|
+
widget,
|
|
139
|
+
index,
|
|
140
|
+
isLastInRow: widgetLayout.isLastWidgetInRow(index, filteredWidgets, columnWidths),
|
|
141
|
+
rightWidgetId,
|
|
142
|
+
widgetWidth,
|
|
143
|
+
rightWidgetWidth,
|
|
144
|
+
canResize: rightWidgetId && widgetLayout.canResizeBetweenWidgets(widget.uid, rightWidgetId, columnWidths, filteredWidgets)
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
}, [
|
|
148
|
+
filteredWidgets,
|
|
149
|
+
columnWidths
|
|
150
|
+
]);
|
|
156
151
|
return /*#__PURE__*/ jsxRuntime.jsx(Layout.Layouts.Root, {
|
|
157
152
|
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Main, {
|
|
158
153
|
children: [
|
|
@@ -172,15 +167,33 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children, link, uid })=>{
|
|
|
172
167
|
subtitle: formatMessage({
|
|
173
168
|
id: 'HomePage.header.subtitle',
|
|
174
169
|
defaultMessage: 'Welcome to your administration panel'
|
|
170
|
+
}),
|
|
171
|
+
primaryAction: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
|
|
172
|
+
variant: "tertiary",
|
|
173
|
+
size: "S",
|
|
174
|
+
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Plus, {}),
|
|
175
|
+
onClick: ()=>setIsAddWidgetModalOpen(true),
|
|
176
|
+
children: formatMessage({
|
|
177
|
+
id: 'HomePage.addWidget.button',
|
|
178
|
+
defaultMessage: 'Add Widget'
|
|
179
|
+
})
|
|
175
180
|
})
|
|
176
181
|
}),
|
|
177
182
|
/*#__PURE__*/ jsxRuntime.jsx(FreeTrialWelcomeModal.FreeTrialWelcomeModal, {}),
|
|
178
183
|
/*#__PURE__*/ jsxRuntime.jsx(FreeTrialEndedModal.FreeTrialEndedModal, {}),
|
|
184
|
+
/*#__PURE__*/ jsxRuntime.jsx(AddWidgetModal.AddWidgetModal, {
|
|
185
|
+
isOpen: isAddWidgetModalOpen,
|
|
186
|
+
onClose: ()=>setIsAddWidgetModalOpen(false),
|
|
187
|
+
onAddWidget: addWidget,
|
|
188
|
+
currentWidgets: filteredWidgets,
|
|
189
|
+
availableWidgets: allAvailableWidgets
|
|
190
|
+
}),
|
|
179
191
|
/*#__PURE__*/ jsxRuntime.jsx(Layout.Layouts.Content, {
|
|
180
192
|
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
181
193
|
direction: "column",
|
|
182
194
|
alignItems: "stretch",
|
|
183
195
|
gap: 8,
|
|
196
|
+
paddingBottom: 10,
|
|
184
197
|
children: [
|
|
185
198
|
/*#__PURE__*/ jsxRuntime.jsx(Overview.GuidedTourHomepageOverview, {}),
|
|
186
199
|
loading ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
|
@@ -190,24 +203,80 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children, link, uid })=>{
|
|
|
190
203
|
right: 0,
|
|
191
204
|
bottom: 0,
|
|
192
205
|
children: /*#__PURE__*/ jsxRuntime.jsx(PageHelpers.Page.Loading, {})
|
|
193
|
-
}) : /*#__PURE__*/ jsxRuntime.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
206
|
+
}) : /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, {
|
|
207
|
+
position: "relative",
|
|
208
|
+
[widgetLayout.WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER]: true,
|
|
209
|
+
children: [
|
|
210
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Root, {
|
|
211
|
+
gap: 5,
|
|
212
|
+
children: widgetLayout$1.map(({ widget, isLastInRow, rightWidgetId, widgetWidth, rightWidgetWidth, canResize })=>/*#__PURE__*/ jsxRuntime.jsxs(React__namespace.Fragment, {
|
|
213
|
+
children: [
|
|
214
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
|
|
215
|
+
col: widgetWidth,
|
|
216
|
+
s: 12,
|
|
217
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(WidgetRoot.WidgetRoot, {
|
|
218
|
+
uid: widget.uid,
|
|
219
|
+
title: widget.title,
|
|
220
|
+
icon: widget.icon,
|
|
221
|
+
link: widget.link,
|
|
222
|
+
findWidget: findWidget,
|
|
223
|
+
deleteWidget: deleteWidget,
|
|
224
|
+
onDragStart: handleDragStart,
|
|
225
|
+
onDragEnd: handleDragEnd,
|
|
226
|
+
component: widget.component,
|
|
227
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(WidgetComponent, {
|
|
228
|
+
component: widget.component,
|
|
229
|
+
columnWidth: widgetWidth
|
|
230
|
+
})
|
|
231
|
+
})
|
|
232
|
+
}),
|
|
233
|
+
!isLastInRow && canResize && rightWidgetId && /*#__PURE__*/ jsxRuntime.jsx(ResizeIndicator.WidgetResizeHandle, {
|
|
234
|
+
leftWidgetId: widget.uid,
|
|
235
|
+
rightWidgetId: rightWidgetId,
|
|
236
|
+
leftWidgetWidth: widgetWidth,
|
|
237
|
+
rightWidgetWidth: rightWidgetWidth,
|
|
238
|
+
onResize: handleWidgetResize,
|
|
239
|
+
saveLayout: saveLayout,
|
|
240
|
+
filteredWidgets: filteredWidgets
|
|
241
|
+
}, `resize-${widget.uid}`)
|
|
242
|
+
]
|
|
243
|
+
}, widget.uid))
|
|
244
|
+
}),
|
|
245
|
+
isDraggingWidget && /*#__PURE__*/ jsxRuntime.jsx(GapDropZone.GapDropZoneManager, {
|
|
246
|
+
filteredWidgets: filteredWidgets,
|
|
247
|
+
columnWidths: columnWidths,
|
|
248
|
+
draggedWidgetId: draggedWidgetId,
|
|
249
|
+
moveWidget: moveWidget
|
|
250
|
+
})
|
|
251
|
+
]
|
|
208
252
|
})
|
|
209
253
|
]
|
|
210
254
|
})
|
|
255
|
+
}),
|
|
256
|
+
/*#__PURE__*/ jsxRuntime.jsx(DragLayer.DragLayer, {
|
|
257
|
+
renderItem: ({ type, item })=>{
|
|
258
|
+
if (!DragLayer.isWidgetDragItem(item)) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const widgetElement = widgetLayout.getWidgetElement(item.id);
|
|
262
|
+
const maxWidth = `${widgetElement?.clientWidth}px`;
|
|
263
|
+
return /*#__PURE__*/ jsxRuntime.jsx(DragPreviewWrapper, {
|
|
264
|
+
$maxWidth: maxWidth,
|
|
265
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(WidgetRoot.WidgetRoot, {
|
|
266
|
+
uid: item.id,
|
|
267
|
+
title: item.title || {
|
|
268
|
+
id: `${item.id}`,
|
|
269
|
+
defaultMessage: item.id
|
|
270
|
+
},
|
|
271
|
+
icon: item.icon,
|
|
272
|
+
link: item.link,
|
|
273
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(WidgetComponent, {
|
|
274
|
+
component: item.component,
|
|
275
|
+
columnWidth: 4
|
|
276
|
+
})
|
|
277
|
+
})
|
|
278
|
+
});
|
|
279
|
+
}
|
|
211
280
|
})
|
|
212
281
|
]
|
|
213
282
|
})
|
|
@@ -227,5 +296,5 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children, link, uid })=>{
|
|
|
227
296
|
|
|
228
297
|
exports.HomePage = HomePage;
|
|
229
298
|
exports.HomePageCE = HomePageCE;
|
|
230
|
-
exports.
|
|
299
|
+
exports.WidgetComponent = WidgetComponent;
|
|
231
300
|
//# 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 { Box, Flex, Grid, Typography, Main } from '@strapi/design-system';\nimport { PuzzlePiece } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { Link as ReactRouterLink } from 'react-router-dom';\n\nimport { GuidedTourHomepageOverview } from '../../components/GuidedTour/Overview';\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';\nimport { useTracking } from '../../features/Tracking';\n\nimport { FreeTrialEndedModal } from './components/FreeTrialEndedModal';\nimport { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';\n\nimport type { WidgetWithUID } from '../../core/apis/Widgets';\nimport type { WidgetType } from '@strapi/admin/strapi-admin';\n\n/* -------------------------------------------------------------------------------------------------\n * WidgetRoot\n * -----------------------------------------------------------------------------------------------*/\n\ninterface WidgetRootProps\n extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link' | 'uid'> {\n children: React.ReactNode;\n}\n\nexport const WidgetRoot = ({ title, icon = PuzzlePiece, children, link, uid }: WidgetRootProps) => {\n const { trackUsage } = useTracking();\n const { formatMessage } = useIntl();\n const id = React.useId();\n const Icon = icon;\n\n const handleClickOnLink = () => {\n trackUsage('didOpenHomeWidgetLink', { widgetUID: uid });\n };\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\" gap={2} justifyContent=\"space-between\" width=\"100%\" tag=\"header\">\n <Flex gap={2}>\n <Icon fill=\"neutral500\" aria-hidden />\n <Typography textColor=\"neutral500\" variant=\"sigma\" tag=\"h2\" id={id}>\n {formatMessage(title)}\n </Typography>\n </Flex>\n {link && (\n <Typography\n tag={ReactRouterLink}\n variant=\"omega\"\n textColor=\"primary600\"\n style={{ textDecoration: 'none' }}\n textAlign=\"right\"\n to={link.href}\n onClick={handleClickOnLink}\n >\n {formatMessage(link.label)}\n </Typography>\n )}\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\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 const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state) => state.widgets.getAll);\n const checkUserHasPermissions = useAuth('WidgetRoot', (state) => state.checkUserHasPermissions);\n const [filteredWidgets, setFilteredWidgets] = React.useState<WidgetWithUID[]>([]);\n const [loading, setLoading] = React.useState(true);\n\n React.useEffect(() => {\n const checkWidgetsPermissions = async () => {\n const allWidgets = getAllWidgets();\n const authorizedWidgets = await Promise.all(\n allWidgets.map(async (widget) => {\n if (!widget.permissions || widget.permissions.length === 0) return true;\n const matchingPermissions = await checkUserHasPermissions(widget.permissions);\n return matchingPermissions.length >= widget.permissions.length;\n })\n );\n setFilteredWidgets(allWidgets.filter((_, i) => authorizedWidgets[i]));\n setLoading(false);\n };\n\n checkWidgetsPermissions();\n }, [checkUserHasPermissions, getAllWidgets]);\n\n return (\n <Layouts.Root>\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 <FreeTrialWelcomeModal />\n <FreeTrialEndedModal />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={8}>\n <GuidedTourHomepageOverview />\n {loading ? (\n <Box position=\"absolute\" top={0} left={0} right={0} bottom={0}>\n <Page.Loading />\n </Box>\n ) : (\n <Grid.Root gap={5}>\n {filteredWidgets.map((widget) => (\n <Grid.Item col={6} s={12} key={widget.uid}>\n <WidgetRoot\n title={widget.title}\n icon={widget.icon}\n link={widget.link}\n uid={widget.uid}\n >\n <WidgetComponent component={widget.component} />\n </WidgetRoot>\n </Grid.Item>\n ))}\n </Grid.Root>\n )}\n </Flex>\n </Layouts.Content>\n </Main>\n </Layouts.Root>\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","link","uid","trackUsage","useTracking","formatMessage","useIntl","id","React","useId","Icon","handleClickOnLink","widgetUID","_jsxs","Flex","width","hasRadius","direction","alignItems","background","borderColor","shadow","tag","gap","padding","aria-labelledby","justifyContent","_jsx","fill","aria-hidden","Typography","textColor","variant","ReactRouterLink","style","textDecoration","textAlign","to","href","onClick","label","Box","height","overflow","WidgetComponent","component","loadedComponent","setLoadedComponent","useState","useEffect","loadComponent","resolvedComponent","Component","Widget","Loading","HomePageCE","user","useAuth","state","displayName","firstname","username","email","getAllWidgets","useStrapiApp","widgets","getAll","checkUserHasPermissions","filteredWidgets","setFilteredWidgets","loading","setLoading","checkWidgetsPermissions","allWidgets","authorizedWidgets","Promise","all","map","widget","permissions","length","matchingPermissions","filter","_","i","Layouts","Root","Main","Page","Title","defaultMessage","Header","name","subtitle","FreeTrialWelcomeModal","FreeTrialEndedModal","Content","GuidedTourHomepageOverview","position","top","left","right","bottom","Grid","Item","col","s","HomePage","useEnterprise","HomePageEE"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HomePage.js","sources":["../../../../../../admin/src/pages/Home/HomePage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Button, Flex, Grid, Main } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { DragLayer, isWidgetDragItem } from '../../components/DragLayer';\nimport { GapDropZoneManager } from '../../components/GapDropZone';\nimport { GuidedTourHomepageOverview } from '../../components/GuidedTour/Overview';\nimport { Layouts } from '../../components/Layouts/Layout';\nimport { Page } from '../../components/PageHelpers';\nimport { WidgetResizeHandle } from '../../components/ResizeIndicator';\nimport { Widget } from '../../components/WidgetHelpers';\nimport { WidgetRoot } from '../../components/WidgetRoot';\nimport { useEnterprise } from '../../ee';\nimport { useAuth } from '../../features/Auth';\nimport { useStrapiApp } from '../../features/StrapiApp';\nimport { useWidgets } from '../../features/Widgets';\nimport { useGetHomepageLayoutQuery } from '../../services/homepage';\nimport { getWidgetElement, WIDGET_DATA_ATTRIBUTES } from '../../utils/widgetLayout';\nimport {\n applyHomepageLayout,\n createDefaultWidgetWidths,\n isLastWidgetInRow,\n canResizeBetweenWidgets,\n getWidgetWidth,\n} from '../../utils/widgetLayout';\n\nimport { AddWidgetModal } from './components/AddWidgetModal';\nimport { FreeTrialEndedModal } from './components/FreeTrialEndedModal';\nimport { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';\n\nimport type { WidgetWithUID } from '../../core/apis/Widgets';\n\n// Styled wrapper for the drag preview\nconst DragPreviewWrapper = styled.div<{ $maxWidth: string }>`\n max-width: ${(props) => props.$maxWidth};\n overflow: hidden;\n opacity: 0.9;\n border: 2px solid ${({ theme }) => theme.colors.primary500};\n border-radius: ${({ theme }) => theme.borderRadius};\n pointer-events: none;\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * UnstableHomePageCe\n * -----------------------------------------------------------------------------------------------*/\n\nexport const WidgetComponent = ({\n component,\n columnWidth,\n}: {\n component: () => Promise<React.ComponentType>;\n columnWidth: number;\n}) => {\n const [loadedComponent, setLoadedComponent] = React.useState<React.ComponentType<{\n columnWidth?: number;\n }> | 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 {...({ columnWidth } as Record<string, unknown>)} />;\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 const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state) => state.widgets.getAll);\n const checkUserHasPermissions = useAuth('WidgetRoot', (state) => state.checkUserHasPermissions);\n const { data: homepageLayout, isLoading: _isLoadingLayout } = useGetHomepageLayoutQuery();\n const [filteredWidgets, setFilteredWidgets] = React.useState<WidgetWithUID[]>([]);\n const [allAvailableWidgets, setAllAvailableWidgets] = React.useState<WidgetWithUID[]>([]);\n const [loading, setLoading] = React.useState(true);\n const [isAddWidgetModalOpen, setIsAddWidgetModalOpen] = React.useState(false);\n\n // Use custom hook for widget management\n const {\n findWidget,\n deleteWidget,\n addWidget,\n moveWidget,\n columnWidths,\n setColumnWidths,\n handleWidgetResize,\n saveLayout,\n isDraggingWidget,\n draggedWidgetId,\n handleDragStart,\n handleDragEnd,\n } = useWidgets({\n filteredWidgets,\n setFilteredWidgets,\n });\n\n React.useEffect(() => {\n const checkWidgetsPermissions = async () => {\n const allWidgets = getAllWidgets();\n const authorizedWidgets = await Promise.all(\n allWidgets.map(async (widget) => {\n if (!widget.permissions || widget.permissions.length === 0) return true;\n const matchingPermissions = await checkUserHasPermissions(widget.permissions);\n return matchingPermissions.length >= widget.permissions.length;\n })\n );\n const authorizedWidgetsList = allWidgets.filter((_, i) => authorizedWidgets[i]);\n\n setAllAvailableWidgets(authorizedWidgetsList);\n setLoading(false);\n };\n\n checkWidgetsPermissions();\n }, [checkUserHasPermissions, getAllWidgets]);\n\n React.useEffect(() => {\n if (allAvailableWidgets.length === 0) return;\n\n // If user has customized the homepage layout, apply it\n if (homepageLayout && homepageLayout.widgets) {\n const { filteredWidgets, widths: homepageWidths } = applyHomepageLayout(\n allAvailableWidgets,\n homepageLayout\n );\n\n setFilteredWidgets(filteredWidgets);\n setColumnWidths(homepageWidths);\n } else {\n // Set default layout when no custom layout exists\n setFilteredWidgets(allAvailableWidgets);\n setColumnWidths(createDefaultWidgetWidths(allAvailableWidgets));\n }\n }, [homepageLayout, allAvailableWidgets, setColumnWidths]);\n\n const widgetLayout = React.useMemo(() => {\n return filteredWidgets.map((widget, index) => {\n const rightWidgetId = filteredWidgets[index + 1]?.uid;\n const widgetWidth = getWidgetWidth(columnWidths, widget.uid);\n const rightWidgetWidth = getWidgetWidth(columnWidths, rightWidgetId);\n\n return {\n widget,\n index,\n isLastInRow: isLastWidgetInRow(index, filteredWidgets, columnWidths),\n rightWidgetId,\n widgetWidth,\n rightWidgetWidth,\n canResize:\n rightWidgetId &&\n canResizeBetweenWidgets(widget.uid, rightWidgetId, columnWidths, filteredWidgets),\n };\n });\n }, [filteredWidgets, columnWidths]);\n\n return (\n <Layouts.Root>\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 primaryAction={\n <Button\n variant=\"tertiary\"\n size=\"S\"\n startIcon={<Plus />}\n onClick={() => setIsAddWidgetModalOpen(true)}\n >\n {formatMessage({\n id: 'HomePage.addWidget.button',\n defaultMessage: 'Add Widget',\n })}\n </Button>\n }\n />\n <FreeTrialWelcomeModal />\n <FreeTrialEndedModal />\n <AddWidgetModal\n isOpen={isAddWidgetModalOpen}\n onClose={() => setIsAddWidgetModalOpen(false)}\n onAddWidget={addWidget}\n currentWidgets={filteredWidgets}\n availableWidgets={allAvailableWidgets}\n />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={8} paddingBottom={10}>\n <GuidedTourHomepageOverview />\n {loading ? (\n <Box position=\"absolute\" top={0} left={0} right={0} bottom={0}>\n <Page.Loading />\n </Box>\n ) : (\n <Box position=\"relative\" {...{ [WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER]: true }}>\n <Grid.Root gap={5}>\n {widgetLayout.map(\n ({\n widget,\n isLastInRow,\n rightWidgetId,\n widgetWidth,\n rightWidgetWidth,\n canResize,\n }) => (\n <React.Fragment key={widget.uid}>\n <Grid.Item col={widgetWidth} s={12}>\n <WidgetRoot\n uid={widget.uid}\n title={widget.title}\n icon={widget.icon}\n link={widget.link}\n findWidget={findWidget}\n deleteWidget={deleteWidget}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n component={widget.component}\n >\n <WidgetComponent\n component={widget.component}\n columnWidth={widgetWidth}\n />\n </WidgetRoot>\n </Grid.Item>\n\n {!isLastInRow && canResize && rightWidgetId && (\n <WidgetResizeHandle\n key={`resize-${widget.uid}`}\n leftWidgetId={widget.uid}\n rightWidgetId={rightWidgetId}\n leftWidgetWidth={widgetWidth}\n rightWidgetWidth={rightWidgetWidth}\n onResize={handleWidgetResize}\n saveLayout={saveLayout}\n filteredWidgets={filteredWidgets}\n />\n )}\n </React.Fragment>\n )\n )}\n </Grid.Root>\n\n {isDraggingWidget && (\n <GapDropZoneManager\n filteredWidgets={filteredWidgets}\n columnWidths={columnWidths}\n draggedWidgetId={draggedWidgetId}\n moveWidget={moveWidget}\n />\n )}\n </Box>\n )}\n </Flex>\n </Layouts.Content>\n\n {/* Add the DragLayer to handle custom drag previews */}\n <DragLayer\n renderItem={({ type, item }) => {\n if (!isWidgetDragItem(item)) {\n return null;\n }\n\n const widgetElement = getWidgetElement(item.id);\n const maxWidth = `${widgetElement?.clientWidth}px`;\n\n return (\n <DragPreviewWrapper $maxWidth={maxWidth}>\n <WidgetRoot\n uid={item.id as WidgetWithUID['uid']}\n title={item.title || { id: `${item.id}`, defaultMessage: item.id }}\n icon={item.icon}\n link={item.link}\n >\n <WidgetComponent component={item.component} columnWidth={4} />\n </WidgetRoot>\n </DragPreviewWrapper>\n );\n }}\n />\n </Main>\n </Layouts.Root>\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":["DragPreviewWrapper","styled","div","props","$maxWidth","theme","colors","primary500","borderRadius","WidgetComponent","component","columnWidth","loadedComponent","setLoadedComponent","React","useState","useEffect","loadComponent","resolvedComponent","Component","_jsx","Widget","Loading","HomePageCE","formatMessage","useIntl","user","useAuth","state","displayName","firstname","username","email","getAllWidgets","useStrapiApp","widgets","getAll","checkUserHasPermissions","data","homepageLayout","isLoading","_isLoadingLayout","useGetHomepageLayoutQuery","filteredWidgets","setFilteredWidgets","allAvailableWidgets","setAllAvailableWidgets","loading","setLoading","isAddWidgetModalOpen","setIsAddWidgetModalOpen","findWidget","deleteWidget","addWidget","moveWidget","columnWidths","setColumnWidths","handleWidgetResize","saveLayout","isDraggingWidget","draggedWidgetId","handleDragStart","handleDragEnd","useWidgets","checkWidgetsPermissions","allWidgets","authorizedWidgets","Promise","all","map","widget","permissions","length","matchingPermissions","authorizedWidgetsList","filter","_","i","widths","homepageWidths","applyHomepageLayout","createDefaultWidgetWidths","widgetLayout","useMemo","index","rightWidgetId","uid","widgetWidth","getWidgetWidth","rightWidgetWidth","isLastInRow","isLastWidgetInRow","canResize","canResizeBetweenWidgets","Layouts","Root","_jsxs","Main","Page","Title","id","defaultMessage","Header","title","name","subtitle","primaryAction","Button","variant","size","startIcon","Plus","onClick","FreeTrialWelcomeModal","FreeTrialEndedModal","AddWidgetModal","isOpen","onClose","onAddWidget","currentWidgets","availableWidgets","Content","Flex","direction","alignItems","gap","paddingBottom","GuidedTourHomepageOverview","Box","position","top","left","right","bottom","WIDGET_DATA_ATTRIBUTES","GRID_CONTAINER","Grid","Fragment","Item","col","s","WidgetRoot","icon","link","onDragStart","onDragEnd","WidgetResizeHandle","leftWidgetId","leftWidgetWidth","onResize","GapDropZoneManager","DragLayer","renderItem","type","item","isWidgetDragItem","widgetElement","getWidgetElement","maxWidth","clientWidth","HomePage","useEnterprise","HomePageEE"],"mappings":"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"}
|