@strapi/admin 5.21.0 → 5.22.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.
Files changed (35) hide show
  1. package/dist/admin/admin/src/StrapiApp.js +38 -8
  2. package/dist/admin/admin/src/StrapiApp.js.map +1 -1
  3. package/dist/admin/admin/src/StrapiApp.mjs +36 -6
  4. package/dist/admin/admin/src/StrapiApp.mjs.map +1 -1
  5. package/dist/admin/admin/src/components/GuidedTour/Tours.js +2 -0
  6. package/dist/admin/admin/src/components/GuidedTour/Tours.js.map +1 -1
  7. package/dist/admin/admin/src/components/GuidedTour/Tours.mjs +2 -0
  8. package/dist/admin/admin/src/components/GuidedTour/Tours.mjs.map +1 -1
  9. package/dist/admin/admin/src/components/Widgets.js +23 -9
  10. package/dist/admin/admin/src/components/Widgets.js.map +1 -1
  11. package/dist/admin/admin/src/components/Widgets.mjs +23 -9
  12. package/dist/admin/admin/src/components/Widgets.mjs.map +1 -1
  13. package/dist/admin/admin/src/features/Tracking.js.map +1 -1
  14. package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
  15. package/dist/admin/admin/src/pages/Home/HomePage.js +31 -33
  16. package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
  17. package/dist/admin/admin/src/pages/Home/HomePage.mjs +32 -34
  18. package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
  19. package/dist/admin/admin/src/translations/en.json.js +3 -0
  20. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  21. package/dist/admin/admin/src/translations/en.json.mjs +3 -0
  22. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  23. package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.js +131 -0
  24. package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.js.map +1 -0
  25. package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.mjs +129 -0
  26. package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.mjs.map +1 -0
  27. package/dist/admin/ee/admin/src/constants.js +3 -1
  28. package/dist/admin/ee/admin/src/constants.js.map +1 -1
  29. package/dist/admin/ee/admin/src/constants.mjs +3 -2
  30. package/dist/admin/ee/admin/src/constants.mjs.map +1 -1
  31. package/dist/admin/src/features/Tracking.d.ts +1 -1
  32. package/dist/admin/src/pages/Home/HomePage.d.ts +1 -1
  33. package/dist/ee/admin/src/components/AuditLogs/Widgets.d.ts +2 -0
  34. package/dist/ee/admin/src/constants.d.ts +1 -0
  35. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"Widgets.mjs","sources":["../../../../../admin/src/components/Widgets.tsx"],"sourcesContent":["import { useAuth } from '@strapi/admin/strapi-admin';\nimport { Avatar, Badge, Box, Flex, Typography } from '@strapi/design-system';\nimport { Earth, Images, User, Key, Files, Layout, Graph, Webhooks } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useGetCountDocumentsQuery, useGetKeyStatisticsQuery } from '../services/homepage';\nimport { getDisplayName, getInitials } from '../utils/users';\n\nimport { Widget } from './WidgetHelpers';\n\n/* -------------------------------------------------------------------------------------------------\n * ProfileWidget\n * -----------------------------------------------------------------------------------------------*/\n\nconst DisplayNameTypography = styled(Typography)`\n font-size: 2.4rem;\n`;\n\nconst ProfileWidget = () => {\n const user = useAuth('User', (state) => state.user);\n const userDisplayName = getDisplayName(user);\n const initials = getInitials(user);\n\n return (\n <Flex direction=\"column\" gap={3} height=\"100%\" justifyContent=\"center\">\n <Avatar.Item delayMs={0} fallback={initials} />\n {userDisplayName && (\n <DisplayNameTypography fontWeight=\"bold\" textTransform=\"none\" textAlign=\"center\">\n {userDisplayName}\n </DisplayNameTypography>\n )}\n {user?.email && (\n <Typography variant=\"omega\" textColor=\"neutral600\">\n {user?.email}\n </Typography>\n )}\n {user?.roles?.length && (\n <Flex marginTop={2} gap={1} wrap=\"wrap\">\n {user?.roles?.map((role) => <Badge key={role.id}>{role.name}</Badge>)}\n </Flex>\n )}\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Key Statistics\n * -----------------------------------------------------------------------------------------------*/\nconst Grid = styled(Box)`\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 0;\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-radius: ${({ theme }) => theme.borderRadius};\n overflow: hidden;\n`;\n\nconst GridCell = styled(Box)`\n border-bottom: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-right: 1px solid ${({ theme }) => theme.colors.neutral200};\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n\n &:nth-child(2n) {\n border-right: none;\n }\n &:nth-last-child(-n + 2) {\n border-bottom: none;\n }\n`;\n\nconst formatNumber = ({ locale, number }: { locale: string; number: number }) => {\n return new Intl.NumberFormat(locale, {\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(number);\n};\n\nconst KeyStatisticsWidget = () => {\n const { formatMessage, locale } = useIntl();\n const { data: countDocuments, isLoading: isLoadingCountDocuments } = useGetCountDocumentsQuery();\n const { data: countKeyStatistics, isLoading: isLoadingKeyStatistics } =\n useGetKeyStatisticsQuery();\n\n if (isLoadingKeyStatistics || isLoadingCountDocuments) {\n return <Widget.Loading />;\n }\n\n if (!countKeyStatistics || !countDocuments) {\n return <Widget.Error />;\n }\n\n const keyStatisticsList = {\n entries: {\n label: {\n id: 'widget.key-statistics.list.entries',\n defaultMessage: 'Entries',\n },\n icon: {\n component: <Files />,\n background: 'primary100',\n color: 'primary600',\n },\n },\n assets: {\n label: {\n id: 'widget.key-statistics.list.assets',\n defaultMessage: 'Assets',\n },\n icon: {\n component: <Images />,\n background: 'warning100',\n color: 'warning600',\n },\n },\n contentTypes: {\n label: {\n id: 'widget.key-statistics.list.contentTypes',\n defaultMessage: 'Content-Types',\n },\n icon: {\n component: <Layout />,\n background: 'secondary100',\n color: 'secondary600',\n },\n },\n components: {\n label: {\n id: 'widget.key-statistics.list.components',\n defaultMessage: 'Components',\n },\n icon: {\n component: <Graph />,\n background: 'alternative100',\n color: 'alternative600',\n },\n },\n locales: {\n label: {\n id: 'widget.key-statistics.list.locales',\n defaultMessage: 'Locales',\n },\n icon: {\n component: <Earth />,\n background: 'success100',\n color: 'success600',\n },\n },\n admins: {\n label: {\n id: 'widget.key-statistics.list.admins',\n defaultMessage: 'Admins',\n },\n icon: {\n component: <User />,\n background: 'danger100',\n color: 'danger600',\n },\n },\n webhooks: {\n label: {\n id: 'widget.key-statistics.list.webhooks',\n defaultMessage: 'Webhooks',\n },\n icon: {\n component: <Webhooks />,\n background: 'alternative100',\n color: 'alternative600',\n },\n },\n apiTokens: {\n label: {\n id: 'widget.key-statistics.list.apiTokens',\n defaultMessage: 'API Tokens',\n },\n icon: {\n component: <Key />,\n background: 'neutral100',\n color: 'neutral600',\n },\n },\n };\n\n const { draft, published, modified } = countDocuments ?? {\n draft: 0,\n published: 0,\n modified: 0,\n };\n\n const totalCountEntries = draft + published + modified;\n\n return (\n <Grid>\n {Object.entries(keyStatisticsList).map(([key, item]) => {\n const value = countKeyStatistics?.[key as keyof typeof countKeyStatistics];\n return (\n value !== null && (\n <GridCell key={`key-statistics-${key}`} padding={3} data-testid={`stat-${key}`}>\n <Flex alignItems=\"center\" gap={2}>\n <Flex\n padding={2}\n borderRadius={1}\n background={item.icon.background}\n color={item.icon.color}\n >\n {item.icon.component}\n </Flex>\n <Flex direction=\"column\" alignItems=\"flex-start\">\n <Typography variant=\"pi\" fontWeight=\"bold\" textColor=\"neutral500\">\n {formatMessage(item.label)}\n </Typography>\n <Typography variant=\"omega\" fontWeight=\"bold\" textColor=\"neutral800\">\n {formatNumber({\n locale,\n number: key === 'entries' ? totalCountEntries : value,\n })}\n </Typography>\n </Flex>\n </Flex>\n </GridCell>\n )\n );\n })}\n </Grid>\n );\n};\n\nexport { ProfileWidget, KeyStatisticsWidget };\n"],"names":["DisplayNameTypography","styled","Typography","ProfileWidget","user","useAuth","state","userDisplayName","getDisplayName","initials","getInitials","_jsxs","Flex","direction","gap","height","justifyContent","_jsx","Avatar","Item","delayMs","fallback","fontWeight","textTransform","textAlign","email","variant","textColor","roles","length","marginTop","wrap","map","role","Badge","name","id","Grid","Box","theme","colors","neutral200","borderRadius","GridCell","formatNumber","locale","number","Intl","NumberFormat","notation","maximumFractionDigits","format","KeyStatisticsWidget","formatMessage","useIntl","data","countDocuments","isLoading","isLoadingCountDocuments","useGetCountDocumentsQuery","countKeyStatistics","isLoadingKeyStatistics","useGetKeyStatisticsQuery","Widget","Loading","Error","keyStatisticsList","entries","label","defaultMessage","icon","component","Files","background","color","assets","Images","contentTypes","Layout","components","Graph","locales","Earth","admins","User","webhooks","Webhooks","apiTokens","Key","draft","published","modified","totalCountEntries","Object","key","item","value","padding","data-testid","alignItems"],"mappings":"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"}
1
+ {"version":3,"file":"Widgets.mjs","sources":["../../../../../admin/src/components/Widgets.tsx"],"sourcesContent":["import { useAuth } from '@strapi/admin/strapi-admin';\nimport { Avatar, Badge, Box, Flex, Typography } from '@strapi/design-system';\nimport { Earth, Images, User, Key, Files, Layout, Graph, Webhooks } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { Link } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { useGetCountDocumentsQuery, useGetKeyStatisticsQuery } from '../services/homepage';\nimport { getDisplayName, getInitials } from '../utils/users';\n\nimport { Widget } from './WidgetHelpers';\n\n/* -------------------------------------------------------------------------------------------------\n * ProfileWidget\n * -----------------------------------------------------------------------------------------------*/\n\nconst DisplayNameTypography = styled(Typography)`\n font-size: 2.4rem;\n`;\n\nconst ProfileWidget = () => {\n const user = useAuth('User', (state) => state.user);\n const userDisplayName = getDisplayName(user);\n const initials = getInitials(user);\n\n return (\n <Flex direction=\"column\" gap={3} height=\"100%\" justifyContent=\"center\">\n <Avatar.Item delayMs={0} fallback={initials} />\n {userDisplayName && (\n <DisplayNameTypography fontWeight=\"bold\" textTransform=\"none\" textAlign=\"center\">\n {userDisplayName}\n </DisplayNameTypography>\n )}\n {user?.email && (\n <Typography variant=\"omega\" textColor=\"neutral600\">\n {user?.email}\n </Typography>\n )}\n {user?.roles?.length && (\n <Flex marginTop={2} gap={1} wrap=\"wrap\">\n {user?.roles?.map((role) => <Badge key={role.id}>{role.name}</Badge>)}\n </Flex>\n )}\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Key Statistics\n * -----------------------------------------------------------------------------------------------*/\nconst Grid = styled(Box)`\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 0;\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-radius: ${({ theme }) => theme.borderRadius};\n overflow: hidden;\n`;\n\nconst GridCell = styled(Box)`\n border-bottom: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-right: 1px solid ${({ theme }) => theme.colors.neutral200};\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n\n &:nth-child(2n) {\n border-right: none;\n }\n &:nth-last-child(-n + 2) {\n border-bottom: none;\n }\n`;\n\nconst formatNumber = ({ locale, number }: { locale: string; number: number }) => {\n return new Intl.NumberFormat(locale, {\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(number);\n};\n\nconst LinkCell = styled(Link)`\n text-decoration: none;\n padding: ${({ theme }) => theme.spaces[3]};\n`;\n\nconst KeyStatisticsWidget = () => {\n const { formatMessage, locale } = useIntl();\n const { data: countDocuments, isLoading: isLoadingCountDocuments } = useGetCountDocumentsQuery();\n const { data: countKeyStatistics, isLoading: isLoadingKeyStatistics } =\n useGetKeyStatisticsQuery();\n\n if (isLoadingKeyStatistics || isLoadingCountDocuments) {\n return <Widget.Loading />;\n }\n\n if (!countKeyStatistics || !countDocuments) {\n return <Widget.Error />;\n }\n\n const keyStatisticsList = {\n entries: {\n label: {\n id: 'widget.key-statistics.list.entries',\n defaultMessage: 'Entries',\n },\n icon: {\n component: <Files />,\n background: 'primary100',\n color: 'primary600',\n },\n link: '/content-manager',\n },\n assets: {\n label: {\n id: 'widget.key-statistics.list.assets',\n defaultMessage: 'Assets',\n },\n icon: {\n component: <Images />,\n background: 'warning100',\n color: 'warning600',\n },\n link: '/plugins/upload',\n },\n contentTypes: {\n label: {\n id: 'widget.key-statistics.list.contentTypes',\n defaultMessage: 'Content-Types',\n },\n icon: {\n component: <Layout />,\n background: 'secondary100',\n color: 'secondary600',\n },\n link: '/plugins/content-type-builder',\n },\n components: {\n label: {\n id: 'widget.key-statistics.list.components',\n defaultMessage: 'Components',\n },\n icon: {\n component: <Graph />,\n background: 'alternative100',\n color: 'alternative600',\n },\n link: '/plugins/content-type-builder',\n },\n locales: {\n label: {\n id: 'widget.key-statistics.list.locales',\n defaultMessage: 'Locales',\n },\n icon: {\n component: <Earth />,\n background: 'success100',\n color: 'success600',\n },\n link: '/settings/internationalization',\n },\n admins: {\n label: {\n id: 'widget.key-statistics.list.admins',\n defaultMessage: 'Admins',\n },\n icon: {\n component: <User />,\n background: 'danger100',\n color: 'danger600',\n },\n link: '/settings/users?pageSize=10&page=1&sort=firstname',\n },\n webhooks: {\n label: {\n id: 'widget.key-statistics.list.webhooks',\n defaultMessage: 'Webhooks',\n },\n icon: {\n component: <Webhooks />,\n background: 'alternative100',\n color: 'alternative600',\n },\n link: '/settings/webhooks',\n },\n apiTokens: {\n label: {\n id: 'widget.key-statistics.list.apiTokens',\n defaultMessage: 'API Tokens',\n },\n icon: {\n component: <Key />,\n background: 'neutral100',\n color: 'neutral600',\n },\n link: '/settings/api-tokens?sort=name:ASC',\n },\n };\n\n const { draft, published, modified } = countDocuments ?? {\n draft: 0,\n published: 0,\n modified: 0,\n };\n\n const totalCountEntries = draft + published + modified;\n\n return (\n <Grid>\n {Object.entries(keyStatisticsList).map(([key, item]) => {\n const value = countKeyStatistics?.[key as keyof typeof countKeyStatistics];\n return (\n value !== null && (\n <GridCell\n as={LinkCell}\n to={item.link}\n key={`key-statistics-${key}`}\n data-testid={`stat-${key}`}\n >\n <Flex alignItems=\"center\" gap={2}>\n <Flex\n padding={2}\n borderRadius={1}\n background={item.icon.background}\n color={item.icon.color}\n >\n {item.icon.component}\n </Flex>\n <Flex direction=\"column\" alignItems=\"flex-start\">\n <Typography variant=\"pi\" fontWeight=\"bold\" textColor=\"neutral500\">\n {formatMessage(item.label)}\n </Typography>\n <Typography variant=\"omega\" fontWeight=\"bold\" textColor=\"neutral800\">\n {formatNumber({\n locale,\n number: key === 'entries' ? totalCountEntries : value,\n })}\n </Typography>\n </Flex>\n </Flex>\n </GridCell>\n )\n );\n })}\n </Grid>\n );\n};\n\nexport { ProfileWidget, KeyStatisticsWidget };\n"],"names":["DisplayNameTypography","styled","Typography","ProfileWidget","user","useAuth","state","userDisplayName","getDisplayName","initials","getInitials","_jsxs","Flex","direction","gap","height","justifyContent","_jsx","Avatar","Item","delayMs","fallback","fontWeight","textTransform","textAlign","email","variant","textColor","roles","length","marginTop","wrap","map","role","Badge","name","id","Grid","Box","theme","colors","neutral200","borderRadius","GridCell","formatNumber","locale","number","Intl","NumberFormat","notation","maximumFractionDigits","format","LinkCell","Link","spaces","KeyStatisticsWidget","formatMessage","useIntl","data","countDocuments","isLoading","isLoadingCountDocuments","useGetCountDocumentsQuery","countKeyStatistics","isLoadingKeyStatistics","useGetKeyStatisticsQuery","Widget","Loading","Error","keyStatisticsList","entries","label","defaultMessage","icon","component","Files","background","color","link","assets","Images","contentTypes","Layout","components","Graph","locales","Earth","admins","User","webhooks","Webhooks","apiTokens","Key","draft","published","modified","totalCountEntries","Object","key","item","value","as","to","data-testid","alignItems","padding"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tracking.js","sources":["../../../../../admin/src/features/Tracking.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport axios, { AxiosResponse } from 'axios';\n\nimport { Tours } from '../components/GuidedTour/Tours';\nimport { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin';\n\nimport { useAppInfo } from './AppInfo';\nimport { useAuth } from './Auth';\nimport { useStrapiApp } from './StrapiApp';\n\nexport interface TelemetryProperties {\n useTypescriptOnServer?: boolean;\n useTypescriptOnAdmin?: boolean;\n isHostedOnStrapiCloud?: boolean;\n numberOfAllContentTypes?: number;\n numberOfComponents?: number;\n numberOfDynamicZones?: number;\n}\n\nexport interface TrackingContextValue {\n uuid?: string | boolean;\n telemetryProperties?: TelemetryProperties;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\nconst TrackingContext = React.createContext<TrackingContextValue>({\n uuid: false,\n});\n\n/* -------------------------------------------------------------------------------------------------\n * Provider\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface TrackingProviderProps {\n children: React.ReactNode;\n}\n\nconst TrackingProvider = ({ children }: TrackingProviderProps) => {\n const token = useAuth('App', (state) => state.token);\n const { data: initData } = useInitQuery();\n const { uuid } = initData ?? {};\n const getAllWidgets = useStrapiApp('TrackingProvider', (state) => state.widgets.getAll);\n\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\n React.useEffect(() => {\n if (uuid && data) {\n const event = 'didInitializeAdministration';\n try {\n fetch(`${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`, {\n method: 'POST',\n body: JSON.stringify({\n // This event is anonymous\n event,\n userId: '',\n eventPropeties: {},\n groupProperties: {\n ...data,\n projectId: uuid,\n registeredWidgets: getAllWidgets().map((widget) => widget.uid),\n },\n }),\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n });\n } catch {\n // silence is golden\n }\n }\n }, [data, uuid, getAllWidgets]);\n const value = React.useMemo(\n () => ({\n uuid,\n telemetryProperties: data,\n }),\n [uuid, data]\n );\n\n return <TrackingContext.Provider value={value}>{children}</TrackingContext.Provider>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hook\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * We can group these events together because none have properties so there's no benefit\n * to having them as separate types.\n *\n * Meanwhile those with properties have different property shapes corresponding to the specific\n * event so understanding which properties go with which event is very helpful.\n */\nexport interface EventWithoutProperties {\n name:\n | 'changeComponentsOrder'\n | 'didAddComponentToDynamicZone'\n | 'didBulkDeleteEntries'\n | 'didNotBulkDeleteEntries'\n | 'didChangeDisplayedFields'\n | 'didCheckDraftRelations'\n | 'didClickGuidedTourHomepageApiTokens'\n | 'didClickGuidedTourHomepageContentManager'\n | 'didClickGuidedTourHomepageContentTypeBuilder'\n | 'didClickGuidedTourStep1CollectionType'\n | 'didClickGuidedTourStep2ContentManager'\n | 'didClickGuidedTourStep3ApiTokens'\n | 'didClickonBlogSection'\n | 'didClickonCodeExampleSection'\n | 'didClickonReadTheDocumentationSection'\n | 'didClickOnTryStrapiCloudSection'\n | 'didClickonTutorialSection'\n | 'didCreateGuidedTourCollectionType'\n | 'didCreateGuidedTourEntry'\n | 'didCreateNewRole'\n | 'didCreateRole'\n | 'didDeleteToken'\n | 'didDuplicateRole'\n | 'didEditEditSettings'\n | 'didEditEmailTemplates'\n | 'didEditFieldNameOnContentType'\n | 'didEditListSettings'\n | 'didEditMediaLibraryConfig'\n | 'didEditNameOfContentType'\n | 'didGenerateGuidedTourApiTokens'\n | 'didGoToMarketplace'\n | 'didLaunchGuidedtour'\n | 'didMissMarketplacePlugin'\n | 'didNotCreateFirstAdmin'\n | 'didNotSaveComponent'\n | 'didPluginLearnMore'\n | 'didBulkPublishEntries'\n | 'didNotBulkPublishEntries'\n | 'didUnpublishEntry'\n | 'didBulkUnpublishEntries'\n | 'didNotBulkUnpublishEntries'\n | 'didSaveComponent'\n | 'didSaveContentType'\n | 'didSearch'\n | 'didSkipGuidedtour'\n | 'didSubmitPlugin'\n | 'didSubmitProvider'\n | 'didUpdateConditions'\n | 'didSelectAllMediaLibraryElements'\n | 'didSelectContentTypeFieldSettings'\n | 'didSelectContentTypeSettings'\n | 'didEditAuthenticationProvider'\n | 'didRestoreHistoryVersion'\n | 'hasClickedCTBAddFieldBanner'\n | 'removeComponentFromDynamicZone'\n | 'willAddMoreFieldToContentType'\n | 'willBulkDeleteEntries'\n | 'willBulkPublishEntries'\n | 'willBulkUnpublishEntries'\n | 'willChangeNumberOfEntriesPerPage'\n | 'willCheckDraftRelations'\n | 'willCreateComponent'\n | 'willCreateComponentFromAttributesModal'\n | 'willCreateContentType'\n | 'willCreateFirstAdmin'\n | 'willCreateNewRole'\n | 'willCreateRole'\n | 'willCreateSingleType'\n | 'willCreateStage'\n | 'willCreateWorkflow'\n | 'willDeleteEntryFromList'\n | 'willDeleteFieldOfContentType'\n | 'willDuplicateRole'\n | 'willEditEditLayout'\n | 'willEditEmailTemplates'\n | 'willEditEntryFromButton'\n | 'willEditEntryFromHome'\n | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\n | 'didLaunchGuidedtour';\n properties?: never;\n}\n\ninterface DidAccessAuthenticatedAdministrationEvent {\n name: 'didAccessAuthenticatedAdministration';\n properties: {\n registeredWidgets: string[];\n projectId: string;\n };\n}\n\ninterface DidFilterMediaLibraryElementsEvent {\n name: 'didFilterMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n filter: string;\n };\n}\n\ninterface DidSortMediaLibraryElementsEvent {\n name: 'didSortMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n sort: string;\n };\n}\n\ninterface DidCropFileEvent {\n name: 'didCropFile';\n properties: MediaEvents['properties'] & {\n duplicatedFile: null | boolean;\n };\n}\n\ninterface DidSelectFile {\n name: 'didSelectFile';\n properties: MediaEvents['properties'] & {\n source: 'url' | 'computer';\n };\n}\n\ninterface DidEditMediaLibraryElementsEvent {\n name: 'didEditMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n type: string;\n changeLocation: string | boolean;\n };\n}\n\ninterface MediaEvents {\n name:\n | 'didSearchMediaLibraryElements'\n | 'didReplaceMedia'\n | 'didAddMediaLibraryFolders'\n | 'willAddMediaLibraryAssets';\n properties: {\n location: string;\n };\n}\n\ninterface DidSelectContentTypeFieldTypeEvent {\n name: 'didSelectContentTypeFieldType';\n properties: {\n type?: string;\n };\n}\n\ninterface DidChangeModeEvent {\n name: 'didChangeMode';\n properties: {\n newMode: string;\n };\n}\ninterface DidSubmitWithErrorsFirstAdminEvent {\n name: 'didSubmitWithErrorsFirstAdmin';\n properties: {\n count: string;\n };\n}\n\ninterface WillNavigateEvent {\n name: 'willNavigate';\n properties: {\n from: string;\n to: string;\n };\n}\n\ninterface DidAccessTokenListEvent {\n name: 'didAccessTokenList';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n number: number;\n };\n}\ninterface LogoEvent {\n name: 'didChangeLogo' | 'didClickResetLogo';\n properties: {\n logo: 'menu' | 'auth';\n };\n}\n\ninterface TokenEvents {\n name:\n | 'didCopyTokenKey'\n | 'didAddTokenFromList'\n | 'didEditTokenFromList'\n | 'willAccessTokenList'\n | 'willAddTokenFromList'\n | 'willCreateToken'\n | 'willDeleteToken'\n | 'willEditToken'\n | 'willEditTokenFromList';\n properties: {\n tokenType: 'api-token' | 'transfer-token';\n };\n}\n\ninterface WillModifyTokenEvent {\n name: 'didCreateToken' | 'didEditToken';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n type: 'custom' | 'full-access' | 'read-only' | Array<'push' | 'pull' | 'push-pull'>;\n };\n}\n\ninterface DeleteEntryEvents {\n name: 'willDeleteEntry' | 'didDeleteEntry' | 'didNotDeleteEntry';\n properties: {\n status?: string;\n error?: unknown;\n };\n}\n\ninterface CreateEntryEvents {\n name: 'willCreateEntry' | 'didCreateEntry' | 'didNotCreateEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface PublishEntryEvents {\n name: 'willPublishEntry' | 'didPublishEntry';\n properties: {\n documentId?: string;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface UpdateEntryEvents {\n name: 'willEditEntry' | 'didEditEntry' | 'didNotEditEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface DidFilterEntriesEvent {\n name: 'didFilterEntries';\n properties: {\n useRelation: boolean;\n };\n}\n\ninterface DidPublishRelease {\n name: 'didPublishRelease';\n properties: {\n totalEntries: number;\n totalPublishedEntries: number;\n totalUnpublishedEntries: number;\n };\n}\n\ninterface DidUpdateCTBSchema {\n name: 'didUpdateCTBSchema';\n properties: {\n success: boolean;\n newContentTypes: number;\n editedContentTypes: number;\n deletedContentTypes: number;\n newComponents: number;\n editedComponents: number;\n deletedComponents: number;\n newFields: number;\n editedFields: number;\n deletedFields: number;\n };\n}\n\ninterface DidSkipGuidedTour {\n name: 'didSkipGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidCompleteGuidedTour {\n name: 'didCompleteGuidedTour';\n properties: {\n name: keyof Tours;\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTourFromHomepage';\n properties: {\n name: keyof Tours;\n };\n}\n\ntype EventsWithProperties =\n | CreateEntryEvents\n | PublishEntryEvents\n | DidAccessAuthenticatedAdministrationEvent\n | DidAccessTokenListEvent\n | DidChangeModeEvent\n | DidCropFileEvent\n | DeleteEntryEvents\n | DidEditMediaLibraryElementsEvent\n | DidFilterMediaLibraryElementsEvent\n | DidFilterEntriesEvent\n | DidSelectContentTypeFieldTypeEvent\n | DidSelectFile\n | DidSortMediaLibraryElementsEvent\n | DidSubmitWithErrorsFirstAdminEvent\n | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour;\n\nexport type TrackingEvent = EventWithoutProperties | EventsWithProperties;\nexport interface UseTrackingReturn {\n /**\n * This type helps show all the available event names before you start typing,\n * however autocomplete isn't great.\n */\n trackUsage<TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n trackUsage<TEvent extends Extract<TrackingEvent, { properties?: never }>>(\n event: TEvent['name'],\n properties?: never\n ): Promise<null | AxiosResponse<string>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n trackUsage<TEvent extends Extract<TrackingEvent, { properties: object }>>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n}\n\n/**\n * @description Used to send amplitude events to the Strapi Tracking hub.\n *\n * @example\n * ```tsx\n * import { useTracking } from '@strapi/strapi/admin';\n *\n * const MyComponent = () => {\n * const { trackUsage } = useTracking();\n *\n * const handleClick = () => {\n * trackUsage('my-event', { myProperty: 'myValue' });\n * }\n *\n * return <button onClick={handleClick}>Send Event</button>\n * }\n * ```\n */\nconst useTracking = (): UseTrackingReturn => {\n const { uuid, telemetryProperties } = React.useContext(TrackingContext);\n const userId = useAppInfo('useTracking', (state) => state.userId);\n const trackUsage = React.useCallback(\n async <TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties?: TEvent['properties']\n ) => {\n try {\n if (uuid && !window.strapi.telemetryDisabled) {\n const res = await axios.post<string>(\n `${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`,\n {\n event,\n userId,\n eventProperties: { ...properties },\n userProperties: {},\n groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\n },\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n }\n );\n\n return res;\n }\n } catch (err) {\n // Silence is golden\n }\n\n return null;\n },\n [telemetryProperties, userId, uuid]\n );\n\n return { trackUsage };\n};\n\nexport { TrackingProvider, useTracking };\n"],"names":["TrackingContext","React","createContext","uuid","TrackingProvider","children","token","useAuth","state","data","initData","useInitQuery","getAllWidgets","useStrapiApp","widgets","getAll","useTelemetryPropertiesQuery","undefined","skip","useEffect","event","fetch","process","env","STRAPI_ANALYTICS_URL","method","body","JSON","stringify","userId","eventPropeties","groupProperties","projectId","registeredWidgets","map","widget","uid","headers","value","useMemo","telemetryProperties","_jsx","Provider","useTracking","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","err"],"mappings":"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"}
1
+ {"version":3,"file":"Tracking.js","sources":["../../../../../admin/src/features/Tracking.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport axios, { AxiosResponse } from 'axios';\n\nimport { Tours } from '../components/GuidedTour/Tours';\nimport { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin';\n\nimport { useAppInfo } from './AppInfo';\nimport { useAuth } from './Auth';\nimport { useStrapiApp } from './StrapiApp';\n\nexport interface TelemetryProperties {\n useTypescriptOnServer?: boolean;\n useTypescriptOnAdmin?: boolean;\n isHostedOnStrapiCloud?: boolean;\n numberOfAllContentTypes?: number;\n numberOfComponents?: number;\n numberOfDynamicZones?: number;\n}\n\nexport interface TrackingContextValue {\n uuid?: string | boolean;\n telemetryProperties?: TelemetryProperties;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\nconst TrackingContext = React.createContext<TrackingContextValue>({\n uuid: false,\n});\n\n/* -------------------------------------------------------------------------------------------------\n * Provider\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface TrackingProviderProps {\n children: React.ReactNode;\n}\n\nconst TrackingProvider = ({ children }: TrackingProviderProps) => {\n const token = useAuth('App', (state) => state.token);\n const { data: initData } = useInitQuery();\n const { uuid } = initData ?? {};\n const getAllWidgets = useStrapiApp('TrackingProvider', (state) => state.widgets.getAll);\n\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\n React.useEffect(() => {\n if (uuid && data) {\n const event = 'didInitializeAdministration';\n try {\n fetch(`${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`, {\n method: 'POST',\n body: JSON.stringify({\n // This event is anonymous\n event,\n userId: '',\n eventPropeties: {},\n groupProperties: {\n ...data,\n projectId: uuid,\n registeredWidgets: getAllWidgets().map((widget) => widget.uid),\n },\n }),\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n });\n } catch {\n // silence is golden\n }\n }\n }, [data, uuid, getAllWidgets]);\n const value = React.useMemo(\n () => ({\n uuid,\n telemetryProperties: data,\n }),\n [uuid, data]\n );\n\n return <TrackingContext.Provider value={value}>{children}</TrackingContext.Provider>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hook\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * We can group these events together because none have properties so there's no benefit\n * to having them as separate types.\n *\n * Meanwhile those with properties have different property shapes corresponding to the specific\n * event so understanding which properties go with which event is very helpful.\n */\nexport interface EventWithoutProperties {\n name:\n | 'changeComponentsOrder'\n | 'didAddComponentToDynamicZone'\n | 'didBulkDeleteEntries'\n | 'didNotBulkDeleteEntries'\n | 'didChangeDisplayedFields'\n | 'didCheckDraftRelations'\n | 'didClickGuidedTourHomepageApiTokens'\n | 'didClickGuidedTourHomepageContentManager'\n | 'didClickGuidedTourHomepageContentTypeBuilder'\n | 'didClickGuidedTourStep1CollectionType'\n | 'didClickGuidedTourStep2ContentManager'\n | 'didClickGuidedTourStep3ApiTokens'\n | 'didClickonBlogSection'\n | 'didClickonCodeExampleSection'\n | 'didClickonReadTheDocumentationSection'\n | 'didClickOnTryStrapiCloudSection'\n | 'didClickonTutorialSection'\n | 'didCreateGuidedTourCollectionType'\n | 'didCreateGuidedTourEntry'\n | 'didCreateNewRole'\n | 'didCreateRole'\n | 'didDeleteToken'\n | 'didDuplicateRole'\n | 'didEditEditSettings'\n | 'didEditEmailTemplates'\n | 'didEditFieldNameOnContentType'\n | 'didEditListSettings'\n | 'didEditMediaLibraryConfig'\n | 'didEditNameOfContentType'\n | 'didGenerateGuidedTourApiTokens'\n | 'didGoToMarketplace'\n | 'didLaunchGuidedtour'\n | 'didMissMarketplacePlugin'\n | 'didNotCreateFirstAdmin'\n | 'didNotSaveComponent'\n | 'didPluginLearnMore'\n | 'didBulkPublishEntries'\n | 'didNotBulkPublishEntries'\n | 'didUnpublishEntry'\n | 'didBulkUnpublishEntries'\n | 'didNotBulkUnpublishEntries'\n | 'didSaveComponent'\n | 'didSaveContentType'\n | 'didSearch'\n | 'didSkipGuidedtour'\n | 'didSubmitPlugin'\n | 'didSubmitProvider'\n | 'didUpdateConditions'\n | 'didSelectAllMediaLibraryElements'\n | 'didSelectContentTypeFieldSettings'\n | 'didSelectContentTypeSettings'\n | 'didEditAuthenticationProvider'\n | 'didRestoreHistoryVersion'\n | 'hasClickedCTBAddFieldBanner'\n | 'removeComponentFromDynamicZone'\n | 'willAddMoreFieldToContentType'\n | 'willBulkDeleteEntries'\n | 'willBulkPublishEntries'\n | 'willBulkUnpublishEntries'\n | 'willChangeNumberOfEntriesPerPage'\n | 'willCheckDraftRelations'\n | 'willCreateComponent'\n | 'willCreateComponentFromAttributesModal'\n | 'willCreateContentType'\n | 'willCreateFirstAdmin'\n | 'willCreateNewRole'\n | 'willCreateRole'\n | 'willCreateSingleType'\n | 'willCreateStage'\n | 'willCreateWorkflow'\n | 'willDeleteEntryFromList'\n | 'willDeleteFieldOfContentType'\n | 'willDuplicateRole'\n | 'willEditEditLayout'\n | 'willEditEmailTemplates'\n | 'willEditEntryFromButton'\n | 'willEditEntryFromHome'\n | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willOpenAuditLogDetails'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\n | 'didLaunchGuidedtour';\n properties?: never;\n}\n\ninterface DidAccessAuthenticatedAdministrationEvent {\n name: 'didAccessAuthenticatedAdministration';\n properties: {\n registeredWidgets: string[];\n projectId: string;\n };\n}\n\ninterface DidFilterMediaLibraryElementsEvent {\n name: 'didFilterMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n filter: string;\n };\n}\n\ninterface DidSortMediaLibraryElementsEvent {\n name: 'didSortMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n sort: string;\n };\n}\n\ninterface DidCropFileEvent {\n name: 'didCropFile';\n properties: MediaEvents['properties'] & {\n duplicatedFile: null | boolean;\n };\n}\n\ninterface DidSelectFile {\n name: 'didSelectFile';\n properties: MediaEvents['properties'] & {\n source: 'url' | 'computer';\n };\n}\n\ninterface DidEditMediaLibraryElementsEvent {\n name: 'didEditMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n type: string;\n changeLocation: string | boolean;\n };\n}\n\ninterface MediaEvents {\n name:\n | 'didSearchMediaLibraryElements'\n | 'didReplaceMedia'\n | 'didAddMediaLibraryFolders'\n | 'willAddMediaLibraryAssets';\n properties: {\n location: string;\n };\n}\n\ninterface DidSelectContentTypeFieldTypeEvent {\n name: 'didSelectContentTypeFieldType';\n properties: {\n type?: string;\n };\n}\n\ninterface DidChangeModeEvent {\n name: 'didChangeMode';\n properties: {\n newMode: string;\n };\n}\ninterface DidSubmitWithErrorsFirstAdminEvent {\n name: 'didSubmitWithErrorsFirstAdmin';\n properties: {\n count: string;\n };\n}\n\ninterface WillNavigateEvent {\n name: 'willNavigate';\n properties: {\n from: string;\n to: string;\n };\n}\n\ninterface DidAccessTokenListEvent {\n name: 'didAccessTokenList';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n number: number;\n };\n}\ninterface LogoEvent {\n name: 'didChangeLogo' | 'didClickResetLogo';\n properties: {\n logo: 'menu' | 'auth';\n };\n}\n\ninterface TokenEvents {\n name:\n | 'didCopyTokenKey'\n | 'didAddTokenFromList'\n | 'didEditTokenFromList'\n | 'willAccessTokenList'\n | 'willAddTokenFromList'\n | 'willCreateToken'\n | 'willDeleteToken'\n | 'willEditToken'\n | 'willEditTokenFromList';\n properties: {\n tokenType: 'api-token' | 'transfer-token';\n };\n}\n\ninterface WillModifyTokenEvent {\n name: 'didCreateToken' | 'didEditToken';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n type: 'custom' | 'full-access' | 'read-only' | Array<'push' | 'pull' | 'push-pull'>;\n };\n}\n\ninterface DeleteEntryEvents {\n name: 'willDeleteEntry' | 'didDeleteEntry' | 'didNotDeleteEntry';\n properties: {\n status?: string;\n error?: unknown;\n };\n}\n\ninterface CreateEntryEvents {\n name: 'willCreateEntry' | 'didCreateEntry' | 'didNotCreateEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface PublishEntryEvents {\n name: 'willPublishEntry' | 'didPublishEntry';\n properties: {\n documentId?: string;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface UpdateEntryEvents {\n name: 'willEditEntry' | 'didEditEntry' | 'didNotEditEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface DidFilterEntriesEvent {\n name: 'didFilterEntries';\n properties: {\n useRelation: boolean;\n };\n}\n\ninterface DidPublishRelease {\n name: 'didPublishRelease';\n properties: {\n totalEntries: number;\n totalPublishedEntries: number;\n totalUnpublishedEntries: number;\n };\n}\n\ninterface DidUpdateCTBSchema {\n name: 'didUpdateCTBSchema';\n properties: {\n success: boolean;\n newContentTypes: number;\n editedContentTypes: number;\n deletedContentTypes: number;\n newComponents: number;\n editedComponents: number;\n deletedComponents: number;\n newFields: number;\n editedFields: number;\n deletedFields: number;\n };\n}\n\ninterface DidSkipGuidedTour {\n name: 'didSkipGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidCompleteGuidedTour {\n name: 'didCompleteGuidedTour';\n properties: {\n name: keyof Tours;\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTourFromHomepage';\n properties: {\n name: keyof Tours;\n };\n}\n\ntype EventsWithProperties =\n | CreateEntryEvents\n | PublishEntryEvents\n | DidAccessAuthenticatedAdministrationEvent\n | DidAccessTokenListEvent\n | DidChangeModeEvent\n | DidCropFileEvent\n | DeleteEntryEvents\n | DidEditMediaLibraryElementsEvent\n | DidFilterMediaLibraryElementsEvent\n | DidFilterEntriesEvent\n | DidSelectContentTypeFieldTypeEvent\n | DidSelectFile\n | DidSortMediaLibraryElementsEvent\n | DidSubmitWithErrorsFirstAdminEvent\n | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour;\n\nexport type TrackingEvent = EventWithoutProperties | EventsWithProperties;\nexport interface UseTrackingReturn {\n /**\n * This type helps show all the available event names before you start typing,\n * however autocomplete isn't great.\n */\n trackUsage<TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n trackUsage<TEvent extends Extract<TrackingEvent, { properties?: never }>>(\n event: TEvent['name'],\n properties?: never\n ): Promise<null | AxiosResponse<string>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n trackUsage<TEvent extends Extract<TrackingEvent, { properties: object }>>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n}\n\n/**\n * @description Used to send amplitude events to the Strapi Tracking hub.\n *\n * @example\n * ```tsx\n * import { useTracking } from '@strapi/strapi/admin';\n *\n * const MyComponent = () => {\n * const { trackUsage } = useTracking();\n *\n * const handleClick = () => {\n * trackUsage('my-event', { myProperty: 'myValue' });\n * }\n *\n * return <button onClick={handleClick}>Send Event</button>\n * }\n * ```\n */\nconst useTracking = (): UseTrackingReturn => {\n const { uuid, telemetryProperties } = React.useContext(TrackingContext);\n const userId = useAppInfo('useTracking', (state) => state.userId);\n const trackUsage = React.useCallback(\n async <TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties?: TEvent['properties']\n ) => {\n try {\n if (uuid && !window.strapi.telemetryDisabled) {\n const res = await axios.post<string>(\n `${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`,\n {\n event,\n userId,\n eventProperties: { ...properties },\n userProperties: {},\n groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\n },\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n }\n );\n\n return res;\n }\n } catch (err) {\n // Silence is golden\n }\n\n return null;\n },\n [telemetryProperties, userId, uuid]\n );\n\n return { trackUsage };\n};\n\nexport { TrackingProvider, useTracking };\n"],"names":["TrackingContext","React","createContext","uuid","TrackingProvider","children","token","useAuth","state","data","initData","useInitQuery","getAllWidgets","useStrapiApp","widgets","getAll","useTelemetryPropertiesQuery","undefined","skip","useEffect","event","fetch","process","env","STRAPI_ANALYTICS_URL","method","body","JSON","stringify","userId","eventPropeties","groupProperties","projectId","registeredWidgets","map","widget","uid","headers","value","useMemo","telemetryProperties","_jsx","Provider","useTracking","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","err"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA;;AAEkG,qGAElG,MAAMA,eAAAA,iBAAkBC,gBAAMC,CAAAA,aAAa,CAAuB;IAChEC,IAAM,EAAA;AACR,CAAA,CAAA;AAUA,MAAMC,gBAAmB,GAAA,CAAC,EAAEC,QAAQ,EAAyB,GAAA;AAC3D,IAAA,MAAMC,QAAQC,YAAQ,CAAA,KAAA,EAAO,CAACC,KAAAA,GAAUA,MAAMF,KAAK,CAAA;AACnD,IAAA,MAAM,EAAEG,IAAAA,EAAMC,QAAQ,EAAE,GAAGC,kBAAAA,EAAAA;AAC3B,IAAA,MAAM,EAAER,IAAI,EAAE,GAAGO,YAAY,EAAC;IAC9B,MAAME,aAAAA,GAAgBC,uBAAa,kBAAoB,EAAA,CAACL,QAAUA,KAAMM,CAAAA,OAAO,CAACC,MAAM,CAAA;AAEtF,IAAA,MAAM,EAAEN,IAAI,EAAE,GAAGO,kCAA4BC,SAAW,EAAA;QACtDC,IAAM,EAAA,CAACR,QAAUP,EAAAA,IAAAA,IAAQ,CAACG;AAC5B,KAAA,CAAA;AACAL,IAAAA,gBAAAA,CAAMkB,SAAS,CAAC,IAAA;AACd,QAAA,IAAIhB,QAAQM,IAAM,EAAA;AAChB,YAAA,MAAMW,KAAQ,GAAA,6BAAA;YACd,IAAI;gBACFC,KAAM,CAAA,CAAC,EAAEC,OAAAA,CAAQC,GAAG,CAACC,oBAAoB,IAAI,6BAAA,CAA8B,aAAa,CAAC,EAAE;oBACzFC,MAAQ,EAAA,MAAA;oBACRC,IAAMC,EAAAA,IAAAA,CAAKC,SAAS,CAAC;;AAEnBR,wBAAAA,KAAAA;wBACAS,MAAQ,EAAA,EAAA;AACRC,wBAAAA,cAAAA,EAAgB,EAAC;wBACjBC,eAAiB,EAAA;AACf,4BAAA,GAAGtB,IAAI;4BACPuB,SAAW7B,EAAAA,IAAAA;AACX8B,4BAAAA,iBAAAA,EAAmBrB,gBAAgBsB,GAAG,CAAC,CAACC,MAAAA,GAAWA,OAAOC,GAAG;AAC/D;AACF,qBAAA,CAAA;oBACAC,OAAS,EAAA;wBACP,cAAgB,EAAA,kBAAA;wBAChB,gBAAkBjB,EAAAA;AACpB;AACF,iBAAA,CAAA;AACF,aAAA,CAAE,OAAM;;AAER;AACF;KACC,EAAA;AAACX,QAAAA,IAAAA;AAAMN,QAAAA,IAAAA;AAAMS,QAAAA;AAAc,KAAA,CAAA;AAC9B,IAAA,MAAM0B,KAAQrC,GAAAA,gBAAAA,CAAMsC,OAAO,CACzB,KAAO;AACLpC,YAAAA,IAAAA;YACAqC,mBAAqB/B,EAAAA;AACvB,SAAA,CACA,EAAA;AAACN,QAAAA,IAAAA;AAAMM,QAAAA;AAAK,KAAA,CAAA;IAGd,qBAAOgC,cAAA,CAACzC,gBAAgB0C,QAAQ,EAAA;QAACJ,KAAOA,EAAAA,KAAAA;AAAQjC,QAAAA,QAAAA,EAAAA;;AAClD;AAuXA;;;;;;;;;;;;;;;;;AAiBC,UACKsC,WAAc,GAAA,IAAA;IAClB,MAAM,EAAExC,IAAI,EAAEqC,mBAAmB,EAAE,GAAGvC,gBAAAA,CAAM2C,UAAU,CAAC5C,eAAAA,CAAAA;AACvD,IAAA,MAAM6B,SAASgB,kBAAW,CAAA,aAAA,EAAe,CAACrC,KAAAA,GAAUA,MAAMqB,MAAM,CAAA;AAChE,IAAA,MAAMiB,UAAa7C,GAAAA,gBAAAA,CAAM8C,WAAW,CAClC,OACE3B,KACA4B,EAAAA,UAAAA,GAAAA;QAEA,IAAI;AACF,YAAA,IAAI7C,QAAQ,CAAC8C,MAAAA,CAAOC,MAAM,CAACC,iBAAiB,EAAE;AAC5C,gBAAA,MAAMC,GAAM,GAAA,MAAMC,KAAMC,CAAAA,IAAI,CAC1B,CAAC,EAAEhC,OAAQC,CAAAA,GAAG,CAACC,oBAAoB,IAAI,6BAA8B,CAAA,aAAa,CAAC,EACnF;AACEJ,oBAAAA,KAAAA;AACAS,oBAAAA,MAAAA;oBACA0B,eAAiB,EAAA;AAAE,wBAAA,GAAGP;AAAW,qBAAA;AACjCQ,oBAAAA,cAAAA,EAAgB,EAAC;oBACjBzB,eAAiB,EAAA;AACf,wBAAA,GAAGS,mBAAmB;wBACtBR,SAAW7B,EAAAA,IAAAA;wBACXsD,WAAaR,EAAAA,MAAAA,CAAOC,MAAM,CAACO;AAC7B;iBAEF,EAAA;oBACEpB,OAAS,EAAA;wBACP,cAAgB,EAAA,kBAAA;wBAChB,gBAAkBjB,EAAAA;AACpB;AACF,iBAAA,CAAA;gBAGF,OAAOgC,GAAAA;AACT;AACF,SAAA,CAAE,OAAOM,GAAK,EAAA;;AAEd;QAEA,OAAO,IAAA;KAET,EAAA;AAAClB,QAAAA,mBAAAA;AAAqBX,QAAAA,MAAAA;AAAQ1B,QAAAA;AAAK,KAAA,CAAA;IAGrC,OAAO;AAAE2C,QAAAA;AAAW,KAAA;AACtB;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tracking.mjs","sources":["../../../../../admin/src/features/Tracking.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport axios, { AxiosResponse } from 'axios';\n\nimport { Tours } from '../components/GuidedTour/Tours';\nimport { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin';\n\nimport { useAppInfo } from './AppInfo';\nimport { useAuth } from './Auth';\nimport { useStrapiApp } from './StrapiApp';\n\nexport interface TelemetryProperties {\n useTypescriptOnServer?: boolean;\n useTypescriptOnAdmin?: boolean;\n isHostedOnStrapiCloud?: boolean;\n numberOfAllContentTypes?: number;\n numberOfComponents?: number;\n numberOfDynamicZones?: number;\n}\n\nexport interface TrackingContextValue {\n uuid?: string | boolean;\n telemetryProperties?: TelemetryProperties;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\nconst TrackingContext = React.createContext<TrackingContextValue>({\n uuid: false,\n});\n\n/* -------------------------------------------------------------------------------------------------\n * Provider\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface TrackingProviderProps {\n children: React.ReactNode;\n}\n\nconst TrackingProvider = ({ children }: TrackingProviderProps) => {\n const token = useAuth('App', (state) => state.token);\n const { data: initData } = useInitQuery();\n const { uuid } = initData ?? {};\n const getAllWidgets = useStrapiApp('TrackingProvider', (state) => state.widgets.getAll);\n\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\n React.useEffect(() => {\n if (uuid && data) {\n const event = 'didInitializeAdministration';\n try {\n fetch(`${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`, {\n method: 'POST',\n body: JSON.stringify({\n // This event is anonymous\n event,\n userId: '',\n eventPropeties: {},\n groupProperties: {\n ...data,\n projectId: uuid,\n registeredWidgets: getAllWidgets().map((widget) => widget.uid),\n },\n }),\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n });\n } catch {\n // silence is golden\n }\n }\n }, [data, uuid, getAllWidgets]);\n const value = React.useMemo(\n () => ({\n uuid,\n telemetryProperties: data,\n }),\n [uuid, data]\n );\n\n return <TrackingContext.Provider value={value}>{children}</TrackingContext.Provider>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hook\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * We can group these events together because none have properties so there's no benefit\n * to having them as separate types.\n *\n * Meanwhile those with properties have different property shapes corresponding to the specific\n * event so understanding which properties go with which event is very helpful.\n */\nexport interface EventWithoutProperties {\n name:\n | 'changeComponentsOrder'\n | 'didAddComponentToDynamicZone'\n | 'didBulkDeleteEntries'\n | 'didNotBulkDeleteEntries'\n | 'didChangeDisplayedFields'\n | 'didCheckDraftRelations'\n | 'didClickGuidedTourHomepageApiTokens'\n | 'didClickGuidedTourHomepageContentManager'\n | 'didClickGuidedTourHomepageContentTypeBuilder'\n | 'didClickGuidedTourStep1CollectionType'\n | 'didClickGuidedTourStep2ContentManager'\n | 'didClickGuidedTourStep3ApiTokens'\n | 'didClickonBlogSection'\n | 'didClickonCodeExampleSection'\n | 'didClickonReadTheDocumentationSection'\n | 'didClickOnTryStrapiCloudSection'\n | 'didClickonTutorialSection'\n | 'didCreateGuidedTourCollectionType'\n | 'didCreateGuidedTourEntry'\n | 'didCreateNewRole'\n | 'didCreateRole'\n | 'didDeleteToken'\n | 'didDuplicateRole'\n | 'didEditEditSettings'\n | 'didEditEmailTemplates'\n | 'didEditFieldNameOnContentType'\n | 'didEditListSettings'\n | 'didEditMediaLibraryConfig'\n | 'didEditNameOfContentType'\n | 'didGenerateGuidedTourApiTokens'\n | 'didGoToMarketplace'\n | 'didLaunchGuidedtour'\n | 'didMissMarketplacePlugin'\n | 'didNotCreateFirstAdmin'\n | 'didNotSaveComponent'\n | 'didPluginLearnMore'\n | 'didBulkPublishEntries'\n | 'didNotBulkPublishEntries'\n | 'didUnpublishEntry'\n | 'didBulkUnpublishEntries'\n | 'didNotBulkUnpublishEntries'\n | 'didSaveComponent'\n | 'didSaveContentType'\n | 'didSearch'\n | 'didSkipGuidedtour'\n | 'didSubmitPlugin'\n | 'didSubmitProvider'\n | 'didUpdateConditions'\n | 'didSelectAllMediaLibraryElements'\n | 'didSelectContentTypeFieldSettings'\n | 'didSelectContentTypeSettings'\n | 'didEditAuthenticationProvider'\n | 'didRestoreHistoryVersion'\n | 'hasClickedCTBAddFieldBanner'\n | 'removeComponentFromDynamicZone'\n | 'willAddMoreFieldToContentType'\n | 'willBulkDeleteEntries'\n | 'willBulkPublishEntries'\n | 'willBulkUnpublishEntries'\n | 'willChangeNumberOfEntriesPerPage'\n | 'willCheckDraftRelations'\n | 'willCreateComponent'\n | 'willCreateComponentFromAttributesModal'\n | 'willCreateContentType'\n | 'willCreateFirstAdmin'\n | 'willCreateNewRole'\n | 'willCreateRole'\n | 'willCreateSingleType'\n | 'willCreateStage'\n | 'willCreateWorkflow'\n | 'willDeleteEntryFromList'\n | 'willDeleteFieldOfContentType'\n | 'willDuplicateRole'\n | 'willEditEditLayout'\n | 'willEditEmailTemplates'\n | 'willEditEntryFromButton'\n | 'willEditEntryFromHome'\n | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\n | 'didLaunchGuidedtour';\n properties?: never;\n}\n\ninterface DidAccessAuthenticatedAdministrationEvent {\n name: 'didAccessAuthenticatedAdministration';\n properties: {\n registeredWidgets: string[];\n projectId: string;\n };\n}\n\ninterface DidFilterMediaLibraryElementsEvent {\n name: 'didFilterMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n filter: string;\n };\n}\n\ninterface DidSortMediaLibraryElementsEvent {\n name: 'didSortMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n sort: string;\n };\n}\n\ninterface DidCropFileEvent {\n name: 'didCropFile';\n properties: MediaEvents['properties'] & {\n duplicatedFile: null | boolean;\n };\n}\n\ninterface DidSelectFile {\n name: 'didSelectFile';\n properties: MediaEvents['properties'] & {\n source: 'url' | 'computer';\n };\n}\n\ninterface DidEditMediaLibraryElementsEvent {\n name: 'didEditMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n type: string;\n changeLocation: string | boolean;\n };\n}\n\ninterface MediaEvents {\n name:\n | 'didSearchMediaLibraryElements'\n | 'didReplaceMedia'\n | 'didAddMediaLibraryFolders'\n | 'willAddMediaLibraryAssets';\n properties: {\n location: string;\n };\n}\n\ninterface DidSelectContentTypeFieldTypeEvent {\n name: 'didSelectContentTypeFieldType';\n properties: {\n type?: string;\n };\n}\n\ninterface DidChangeModeEvent {\n name: 'didChangeMode';\n properties: {\n newMode: string;\n };\n}\ninterface DidSubmitWithErrorsFirstAdminEvent {\n name: 'didSubmitWithErrorsFirstAdmin';\n properties: {\n count: string;\n };\n}\n\ninterface WillNavigateEvent {\n name: 'willNavigate';\n properties: {\n from: string;\n to: string;\n };\n}\n\ninterface DidAccessTokenListEvent {\n name: 'didAccessTokenList';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n number: number;\n };\n}\ninterface LogoEvent {\n name: 'didChangeLogo' | 'didClickResetLogo';\n properties: {\n logo: 'menu' | 'auth';\n };\n}\n\ninterface TokenEvents {\n name:\n | 'didCopyTokenKey'\n | 'didAddTokenFromList'\n | 'didEditTokenFromList'\n | 'willAccessTokenList'\n | 'willAddTokenFromList'\n | 'willCreateToken'\n | 'willDeleteToken'\n | 'willEditToken'\n | 'willEditTokenFromList';\n properties: {\n tokenType: 'api-token' | 'transfer-token';\n };\n}\n\ninterface WillModifyTokenEvent {\n name: 'didCreateToken' | 'didEditToken';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n type: 'custom' | 'full-access' | 'read-only' | Array<'push' | 'pull' | 'push-pull'>;\n };\n}\n\ninterface DeleteEntryEvents {\n name: 'willDeleteEntry' | 'didDeleteEntry' | 'didNotDeleteEntry';\n properties: {\n status?: string;\n error?: unknown;\n };\n}\n\ninterface CreateEntryEvents {\n name: 'willCreateEntry' | 'didCreateEntry' | 'didNotCreateEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface PublishEntryEvents {\n name: 'willPublishEntry' | 'didPublishEntry';\n properties: {\n documentId?: string;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface UpdateEntryEvents {\n name: 'willEditEntry' | 'didEditEntry' | 'didNotEditEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface DidFilterEntriesEvent {\n name: 'didFilterEntries';\n properties: {\n useRelation: boolean;\n };\n}\n\ninterface DidPublishRelease {\n name: 'didPublishRelease';\n properties: {\n totalEntries: number;\n totalPublishedEntries: number;\n totalUnpublishedEntries: number;\n };\n}\n\ninterface DidUpdateCTBSchema {\n name: 'didUpdateCTBSchema';\n properties: {\n success: boolean;\n newContentTypes: number;\n editedContentTypes: number;\n deletedContentTypes: number;\n newComponents: number;\n editedComponents: number;\n deletedComponents: number;\n newFields: number;\n editedFields: number;\n deletedFields: number;\n };\n}\n\ninterface DidSkipGuidedTour {\n name: 'didSkipGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidCompleteGuidedTour {\n name: 'didCompleteGuidedTour';\n properties: {\n name: keyof Tours;\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTourFromHomepage';\n properties: {\n name: keyof Tours;\n };\n}\n\ntype EventsWithProperties =\n | CreateEntryEvents\n | PublishEntryEvents\n | DidAccessAuthenticatedAdministrationEvent\n | DidAccessTokenListEvent\n | DidChangeModeEvent\n | DidCropFileEvent\n | DeleteEntryEvents\n | DidEditMediaLibraryElementsEvent\n | DidFilterMediaLibraryElementsEvent\n | DidFilterEntriesEvent\n | DidSelectContentTypeFieldTypeEvent\n | DidSelectFile\n | DidSortMediaLibraryElementsEvent\n | DidSubmitWithErrorsFirstAdminEvent\n | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour;\n\nexport type TrackingEvent = EventWithoutProperties | EventsWithProperties;\nexport interface UseTrackingReturn {\n /**\n * This type helps show all the available event names before you start typing,\n * however autocomplete isn't great.\n */\n trackUsage<TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n trackUsage<TEvent extends Extract<TrackingEvent, { properties?: never }>>(\n event: TEvent['name'],\n properties?: never\n ): Promise<null | AxiosResponse<string>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n trackUsage<TEvent extends Extract<TrackingEvent, { properties: object }>>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n}\n\n/**\n * @description Used to send amplitude events to the Strapi Tracking hub.\n *\n * @example\n * ```tsx\n * import { useTracking } from '@strapi/strapi/admin';\n *\n * const MyComponent = () => {\n * const { trackUsage } = useTracking();\n *\n * const handleClick = () => {\n * trackUsage('my-event', { myProperty: 'myValue' });\n * }\n *\n * return <button onClick={handleClick}>Send Event</button>\n * }\n * ```\n */\nconst useTracking = (): UseTrackingReturn => {\n const { uuid, telemetryProperties } = React.useContext(TrackingContext);\n const userId = useAppInfo('useTracking', (state) => state.userId);\n const trackUsage = React.useCallback(\n async <TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties?: TEvent['properties']\n ) => {\n try {\n if (uuid && !window.strapi.telemetryDisabled) {\n const res = await axios.post<string>(\n `${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`,\n {\n event,\n userId,\n eventProperties: { ...properties },\n userProperties: {},\n groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\n },\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n }\n );\n\n return res;\n }\n } catch (err) {\n // Silence is golden\n }\n\n return null;\n },\n [telemetryProperties, userId, uuid]\n );\n\n return { trackUsage };\n};\n\nexport { TrackingProvider, useTracking };\n"],"names":["TrackingContext","React","createContext","uuid","TrackingProvider","children","token","useAuth","state","data","initData","useInitQuery","getAllWidgets","useStrapiApp","widgets","getAll","useTelemetryPropertiesQuery","undefined","skip","useEffect","event","fetch","process","env","STRAPI_ANALYTICS_URL","method","body","JSON","stringify","userId","eventPropeties","groupProperties","projectId","registeredWidgets","map","widget","uid","headers","value","useMemo","telemetryProperties","_jsx","Provider","useTracking","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","err"],"mappings":"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"}
1
+ {"version":3,"file":"Tracking.mjs","sources":["../../../../../admin/src/features/Tracking.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport axios, { AxiosResponse } from 'axios';\n\nimport { Tours } from '../components/GuidedTour/Tours';\nimport { useInitQuery, useTelemetryPropertiesQuery } from '../services/admin';\n\nimport { useAppInfo } from './AppInfo';\nimport { useAuth } from './Auth';\nimport { useStrapiApp } from './StrapiApp';\n\nexport interface TelemetryProperties {\n useTypescriptOnServer?: boolean;\n useTypescriptOnAdmin?: boolean;\n isHostedOnStrapiCloud?: boolean;\n numberOfAllContentTypes?: number;\n numberOfComponents?: number;\n numberOfDynamicZones?: number;\n}\n\nexport interface TrackingContextValue {\n uuid?: string | boolean;\n telemetryProperties?: TelemetryProperties;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\nconst TrackingContext = React.createContext<TrackingContextValue>({\n uuid: false,\n});\n\n/* -------------------------------------------------------------------------------------------------\n * Provider\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface TrackingProviderProps {\n children: React.ReactNode;\n}\n\nconst TrackingProvider = ({ children }: TrackingProviderProps) => {\n const token = useAuth('App', (state) => state.token);\n const { data: initData } = useInitQuery();\n const { uuid } = initData ?? {};\n const getAllWidgets = useStrapiApp('TrackingProvider', (state) => state.widgets.getAll);\n\n const { data } = useTelemetryPropertiesQuery(undefined, {\n skip: !initData?.uuid || !token,\n });\n React.useEffect(() => {\n if (uuid && data) {\n const event = 'didInitializeAdministration';\n try {\n fetch(`${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`, {\n method: 'POST',\n body: JSON.stringify({\n // This event is anonymous\n event,\n userId: '',\n eventPropeties: {},\n groupProperties: {\n ...data,\n projectId: uuid,\n registeredWidgets: getAllWidgets().map((widget) => widget.uid),\n },\n }),\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n });\n } catch {\n // silence is golden\n }\n }\n }, [data, uuid, getAllWidgets]);\n const value = React.useMemo(\n () => ({\n uuid,\n telemetryProperties: data,\n }),\n [uuid, data]\n );\n\n return <TrackingContext.Provider value={value}>{children}</TrackingContext.Provider>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hook\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * We can group these events together because none have properties so there's no benefit\n * to having them as separate types.\n *\n * Meanwhile those with properties have different property shapes corresponding to the specific\n * event so understanding which properties go with which event is very helpful.\n */\nexport interface EventWithoutProperties {\n name:\n | 'changeComponentsOrder'\n | 'didAddComponentToDynamicZone'\n | 'didBulkDeleteEntries'\n | 'didNotBulkDeleteEntries'\n | 'didChangeDisplayedFields'\n | 'didCheckDraftRelations'\n | 'didClickGuidedTourHomepageApiTokens'\n | 'didClickGuidedTourHomepageContentManager'\n | 'didClickGuidedTourHomepageContentTypeBuilder'\n | 'didClickGuidedTourStep1CollectionType'\n | 'didClickGuidedTourStep2ContentManager'\n | 'didClickGuidedTourStep3ApiTokens'\n | 'didClickonBlogSection'\n | 'didClickonCodeExampleSection'\n | 'didClickonReadTheDocumentationSection'\n | 'didClickOnTryStrapiCloudSection'\n | 'didClickonTutorialSection'\n | 'didCreateGuidedTourCollectionType'\n | 'didCreateGuidedTourEntry'\n | 'didCreateNewRole'\n | 'didCreateRole'\n | 'didDeleteToken'\n | 'didDuplicateRole'\n | 'didEditEditSettings'\n | 'didEditEmailTemplates'\n | 'didEditFieldNameOnContentType'\n | 'didEditListSettings'\n | 'didEditMediaLibraryConfig'\n | 'didEditNameOfContentType'\n | 'didGenerateGuidedTourApiTokens'\n | 'didGoToMarketplace'\n | 'didLaunchGuidedtour'\n | 'didMissMarketplacePlugin'\n | 'didNotCreateFirstAdmin'\n | 'didNotSaveComponent'\n | 'didPluginLearnMore'\n | 'didBulkPublishEntries'\n | 'didNotBulkPublishEntries'\n | 'didUnpublishEntry'\n | 'didBulkUnpublishEntries'\n | 'didNotBulkUnpublishEntries'\n | 'didSaveComponent'\n | 'didSaveContentType'\n | 'didSearch'\n | 'didSkipGuidedtour'\n | 'didSubmitPlugin'\n | 'didSubmitProvider'\n | 'didUpdateConditions'\n | 'didSelectAllMediaLibraryElements'\n | 'didSelectContentTypeFieldSettings'\n | 'didSelectContentTypeSettings'\n | 'didEditAuthenticationProvider'\n | 'didRestoreHistoryVersion'\n | 'hasClickedCTBAddFieldBanner'\n | 'removeComponentFromDynamicZone'\n | 'willAddMoreFieldToContentType'\n | 'willBulkDeleteEntries'\n | 'willBulkPublishEntries'\n | 'willBulkUnpublishEntries'\n | 'willChangeNumberOfEntriesPerPage'\n | 'willCheckDraftRelations'\n | 'willCreateComponent'\n | 'willCreateComponentFromAttributesModal'\n | 'willCreateContentType'\n | 'willCreateFirstAdmin'\n | 'willCreateNewRole'\n | 'willCreateRole'\n | 'willCreateSingleType'\n | 'willCreateStage'\n | 'willCreateWorkflow'\n | 'willDeleteEntryFromList'\n | 'willDeleteFieldOfContentType'\n | 'willDuplicateRole'\n | 'willEditEditLayout'\n | 'willEditEmailTemplates'\n | 'willEditEntryFromButton'\n | 'willEditEntryFromHome'\n | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willOpenAuditLogDetails'\n | 'willUnpublishEntry'\n | 'willSaveComponent'\n | 'willSaveContentType'\n | 'willSaveContentTypeLayout'\n | 'didEditFieldNameOnContentType'\n | 'didCreateRelease'\n | 'didLaunchGuidedtour';\n properties?: never;\n}\n\ninterface DidAccessAuthenticatedAdministrationEvent {\n name: 'didAccessAuthenticatedAdministration';\n properties: {\n registeredWidgets: string[];\n projectId: string;\n };\n}\n\ninterface DidFilterMediaLibraryElementsEvent {\n name: 'didFilterMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n filter: string;\n };\n}\n\ninterface DidSortMediaLibraryElementsEvent {\n name: 'didSortMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n sort: string;\n };\n}\n\ninterface DidCropFileEvent {\n name: 'didCropFile';\n properties: MediaEvents['properties'] & {\n duplicatedFile: null | boolean;\n };\n}\n\ninterface DidSelectFile {\n name: 'didSelectFile';\n properties: MediaEvents['properties'] & {\n source: 'url' | 'computer';\n };\n}\n\ninterface DidEditMediaLibraryElementsEvent {\n name: 'didEditMediaLibraryElements';\n properties: MediaEvents['properties'] & {\n type: string;\n changeLocation: string | boolean;\n };\n}\n\ninterface MediaEvents {\n name:\n | 'didSearchMediaLibraryElements'\n | 'didReplaceMedia'\n | 'didAddMediaLibraryFolders'\n | 'willAddMediaLibraryAssets';\n properties: {\n location: string;\n };\n}\n\ninterface DidSelectContentTypeFieldTypeEvent {\n name: 'didSelectContentTypeFieldType';\n properties: {\n type?: string;\n };\n}\n\ninterface DidChangeModeEvent {\n name: 'didChangeMode';\n properties: {\n newMode: string;\n };\n}\ninterface DidSubmitWithErrorsFirstAdminEvent {\n name: 'didSubmitWithErrorsFirstAdmin';\n properties: {\n count: string;\n };\n}\n\ninterface WillNavigateEvent {\n name: 'willNavigate';\n properties: {\n from: string;\n to: string;\n };\n}\n\ninterface DidAccessTokenListEvent {\n name: 'didAccessTokenList';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n number: number;\n };\n}\ninterface LogoEvent {\n name: 'didChangeLogo' | 'didClickResetLogo';\n properties: {\n logo: 'menu' | 'auth';\n };\n}\n\ninterface TokenEvents {\n name:\n | 'didCopyTokenKey'\n | 'didAddTokenFromList'\n | 'didEditTokenFromList'\n | 'willAccessTokenList'\n | 'willAddTokenFromList'\n | 'willCreateToken'\n | 'willDeleteToken'\n | 'willEditToken'\n | 'willEditTokenFromList';\n properties: {\n tokenType: 'api-token' | 'transfer-token';\n };\n}\n\ninterface WillModifyTokenEvent {\n name: 'didCreateToken' | 'didEditToken';\n properties: {\n tokenType: TokenEvents['properties']['tokenType'];\n type: 'custom' | 'full-access' | 'read-only' | Array<'push' | 'pull' | 'push-pull'>;\n };\n}\n\ninterface DeleteEntryEvents {\n name: 'willDeleteEntry' | 'didDeleteEntry' | 'didNotDeleteEntry';\n properties: {\n status?: string;\n error?: unknown;\n };\n}\n\ninterface CreateEntryEvents {\n name: 'willCreateEntry' | 'didCreateEntry' | 'didNotCreateEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface PublishEntryEvents {\n name: 'willPublishEntry' | 'didPublishEntry';\n properties: {\n documentId?: string;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface UpdateEntryEvents {\n name: 'willEditEntry' | 'didEditEntry' | 'didNotEditEntry';\n properties: {\n documentId?: string;\n status?: string;\n error?: unknown;\n fromPreview?: boolean;\n fromRelationModal?: boolean;\n };\n}\n\ninterface DidFilterEntriesEvent {\n name: 'didFilterEntries';\n properties: {\n useRelation: boolean;\n };\n}\n\ninterface DidPublishRelease {\n name: 'didPublishRelease';\n properties: {\n totalEntries: number;\n totalPublishedEntries: number;\n totalUnpublishedEntries: number;\n };\n}\n\ninterface DidUpdateCTBSchema {\n name: 'didUpdateCTBSchema';\n properties: {\n success: boolean;\n newContentTypes: number;\n editedContentTypes: number;\n deletedContentTypes: number;\n newComponents: number;\n editedComponents: number;\n deletedComponents: number;\n newFields: number;\n editedFields: number;\n deletedFields: number;\n };\n}\n\ninterface DidSkipGuidedTour {\n name: 'didSkipGuidedTour';\n properties: {\n name: keyof Tours | 'all';\n };\n}\n\ninterface DidCompleteGuidedTour {\n name: 'didCompleteGuidedTour';\n properties: {\n name: keyof Tours;\n };\n}\n\ninterface DidStartGuidedTour {\n name: 'didStartGuidedTourFromHomepage';\n properties: {\n name: keyof Tours;\n };\n}\n\ntype EventsWithProperties =\n | CreateEntryEvents\n | PublishEntryEvents\n | DidAccessAuthenticatedAdministrationEvent\n | DidAccessTokenListEvent\n | DidChangeModeEvent\n | DidCropFileEvent\n | DeleteEntryEvents\n | DidEditMediaLibraryElementsEvent\n | DidFilterMediaLibraryElementsEvent\n | DidFilterEntriesEvent\n | DidSelectContentTypeFieldTypeEvent\n | DidSelectFile\n | DidSortMediaLibraryElementsEvent\n | DidSubmitWithErrorsFirstAdminEvent\n | LogoEvent\n | TokenEvents\n | UpdateEntryEvents\n | WillModifyTokenEvent\n | WillNavigateEvent\n | DidPublishRelease\n | MediaEvents\n | DidUpdateCTBSchema\n | DidSkipGuidedTour\n | DidCompleteGuidedTour\n | DidStartGuidedTour;\n\nexport type TrackingEvent = EventWithoutProperties | EventsWithProperties;\nexport interface UseTrackingReturn {\n /**\n * This type helps show all the available event names before you start typing,\n * however autocomplete isn't great.\n */\n trackUsage<TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n trackUsage<TEvent extends Extract<TrackingEvent, { properties?: never }>>(\n event: TEvent['name'],\n properties?: never\n ): Promise<null | AxiosResponse<string>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n trackUsage<TEvent extends Extract<TrackingEvent, { properties: object }>>(\n event: TEvent['name'],\n properties: TEvent['properties']\n ): Promise<null | AxiosResponse<string>>;\n}\n\n/**\n * @description Used to send amplitude events to the Strapi Tracking hub.\n *\n * @example\n * ```tsx\n * import { useTracking } from '@strapi/strapi/admin';\n *\n * const MyComponent = () => {\n * const { trackUsage } = useTracking();\n *\n * const handleClick = () => {\n * trackUsage('my-event', { myProperty: 'myValue' });\n * }\n *\n * return <button onClick={handleClick}>Send Event</button>\n * }\n * ```\n */\nconst useTracking = (): UseTrackingReturn => {\n const { uuid, telemetryProperties } = React.useContext(TrackingContext);\n const userId = useAppInfo('useTracking', (state) => state.userId);\n const trackUsage = React.useCallback(\n async <TEvent extends TrackingEvent>(\n event: TEvent['name'],\n properties?: TEvent['properties']\n ) => {\n try {\n if (uuid && !window.strapi.telemetryDisabled) {\n const res = await axios.post<string>(\n `${process.env.STRAPI_ANALYTICS_URL || 'https://analytics.strapi.io'}/api/v2/track`,\n {\n event,\n userId,\n eventProperties: { ...properties },\n userProperties: {},\n groupProperties: {\n ...telemetryProperties,\n projectId: uuid,\n projectType: window.strapi.projectType,\n },\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'X-Strapi-Event': event,\n },\n }\n );\n\n return res;\n }\n } catch (err) {\n // Silence is golden\n }\n\n return null;\n },\n [telemetryProperties, userId, uuid]\n );\n\n return { trackUsage };\n};\n\nexport { TrackingProvider, useTracking };\n"],"names":["TrackingContext","React","createContext","uuid","TrackingProvider","children","token","useAuth","state","data","initData","useInitQuery","getAllWidgets","useStrapiApp","widgets","getAll","useTelemetryPropertiesQuery","undefined","skip","useEffect","event","fetch","process","env","STRAPI_ANALYTICS_URL","method","body","JSON","stringify","userId","eventPropeties","groupProperties","projectId","registeredWidgets","map","widget","uid","headers","value","useMemo","telemetryProperties","_jsx","Provider","useTracking","useContext","useAppInfo","trackUsage","useCallback","properties","window","strapi","telemetryDisabled","res","axios","post","eventProperties","userProperties","projectType","err"],"mappings":"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"}
@@ -36,27 +36,10 @@ function _interopNamespaceDefault(e) {
36
36
 
37
37
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
38
38
 
39
- const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], children, link })=>{
39
+ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children, link })=>{
40
40
  const { formatMessage } = reactIntl.useIntl();
41
41
  const id = React__namespace.useId();
42
42
  const Icon = icon;
43
- const [permissionStatus, setPermissionStatus] = React__namespace.useState('loading');
44
- const checkUserHasPermissions = Auth.useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
45
- React__namespace.useEffect(()=>{
46
- const checkPermissions = async ()=>{
47
- const matchingPermissions = await checkUserHasPermissions(permissions);
48
- const shouldGrant = matchingPermissions.length >= permissions.length;
49
- setPermissionStatus(shouldGrant ? 'granted' : 'forbidden');
50
- };
51
- if (!permissions || permissions.length === 0) {
52
- setPermissionStatus('granted');
53
- } else {
54
- checkPermissions();
55
- }
56
- }, [
57
- checkUserHasPermissions,
58
- permissions
59
- ]);
60
43
  return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
61
44
  width: "100%",
62
45
  hasRadius: true,
@@ -106,16 +89,12 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], childre
106
89
  })
107
90
  ]
108
91
  }),
109
- /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, {
92
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
110
93
  width: "100%",
111
94
  height: "261px",
112
95
  overflow: "auto",
113
96
  tag: "main",
114
- children: [
115
- permissionStatus === 'loading' && /*#__PURE__*/ jsxRuntime.jsx(WidgetHelpers.Widget.Loading, {}),
116
- permissionStatus === 'forbidden' && /*#__PURE__*/ jsxRuntime.jsx(WidgetHelpers.Widget.NoPermissions, {}),
117
- permissionStatus === 'granted' && children
118
- ]
97
+ children: children
119
98
  })
120
99
  ]
121
100
  });
@@ -146,9 +125,24 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], childre
146
125
  const user = Auth.useAuth('HomePageCE', (state)=>state.user);
147
126
  const displayName = user?.firstname ?? user?.username ?? user?.email;
148
127
  const getAllWidgets = StrapiApp.useStrapiApp('UnstableHomepageCe', (state)=>state.widgets.getAll);
149
- const filteredWidgets = React__namespace.useMemo(()=>getAllWidgets().filter((widget)=>!widget.roles || user?.roles?.some((userRole)=>widget.roles?.find((role)=>userRole.code === role))), [
150
- getAllWidgets,
151
- user?.roles
128
+ const checkUserHasPermissions = Auth.useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
129
+ const [filteredWidgets, setFilteredWidgets] = React__namespace.useState([]);
130
+ const [loading, setLoading] = React__namespace.useState(true);
131
+ React__namespace.useEffect(()=>{
132
+ const checkWidgetsPermissions = async ()=>{
133
+ const allWidgets = getAllWidgets();
134
+ const authorizedWidgets = await Promise.all(allWidgets.map(async (widget)=>{
135
+ if (!widget.permissions || widget.permissions.length === 0) return true;
136
+ const matchingPermissions = await checkUserHasPermissions(widget.permissions);
137
+ return matchingPermissions.length >= widget.permissions.length;
138
+ }));
139
+ setFilteredWidgets(allWidgets.filter((_, i)=>authorizedWidgets[i]));
140
+ setLoading(false);
141
+ };
142
+ checkWidgetsPermissions();
143
+ }, [
144
+ checkUserHasPermissions,
145
+ getAllWidgets
152
146
  ]);
153
147
  return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Main, {
154
148
  children: [
@@ -180,23 +174,27 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], childre
180
174
  paddingBottom: 10,
181
175
  children: [
182
176
  /*#__PURE__*/ jsxRuntime.jsx(Overview.GuidedTourHomepageOverview, {}),
183
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Root, {
177
+ loading ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
178
+ position: "absolute",
179
+ top: 0,
180
+ left: 0,
181
+ right: 0,
182
+ bottom: 0,
183
+ children: /*#__PURE__*/ jsxRuntime.jsx(PageHelpers.Page.Loading, {})
184
+ }) : /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Root, {
184
185
  gap: 5,
185
- children: filteredWidgets.map((widget)=>{
186
- return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
186
+ children: filteredWidgets.map((widget)=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
187
187
  col: 6,
188
188
  s: 12,
189
189
  children: /*#__PURE__*/ jsxRuntime.jsx(WidgetRoot, {
190
190
  title: widget.title,
191
191
  icon: widget.icon,
192
- permissions: widget.permissions,
193
192
  link: widget.link,
194
193
  children: /*#__PURE__*/ jsxRuntime.jsx(WidgetComponent, {
195
194
  component: widget.component
196
195
  })
197
196
  })
198
- }, widget.uid);
199
- })
197
+ }, widget.uid))
200
198
  })
201
199
  ]
202
200
  })
@@ -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, Main, Typography } 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';\n\nimport { FreeTrialEndedModal } from './components/FreeTrialEndedModal';\nimport { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';\n\nimport type { WidgetType } from '@strapi/admin/strapi-admin';\n\n/* -------------------------------------------------------------------------------------------------\n * WidgetRoot\n * -----------------------------------------------------------------------------------------------*/\n\ninterface WidgetRootProps extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link'> {\n children: React.ReactNode;\n}\n\nexport const WidgetRoot = ({\n title,\n icon = PuzzlePiece,\n permissions = [],\n children,\n link,\n}: WidgetRootProps) => {\n const { formatMessage } = useIntl();\n const id = React.useId();\n const Icon = icon;\n\n const [permissionStatus, setPermissionStatus] = React.useState<\n 'loading' | 'granted' | 'forbidden'\n >('loading');\n const checkUserHasPermissions = useAuth('WidgetRoot', (state) => state.checkUserHasPermissions);\n React.useEffect(() => {\n const checkPermissions = async () => {\n const matchingPermissions = await checkUserHasPermissions(permissions);\n const shouldGrant = matchingPermissions.length >= permissions.length;\n setPermissionStatus(shouldGrant ? 'granted' : 'forbidden');\n };\n\n if (!permissions || permissions.length === 0) {\n setPermissionStatus('granted');\n } else {\n checkPermissions();\n }\n }, [checkUserHasPermissions, permissions]);\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 >\n {formatMessage(link.label)}\n </Typography>\n )}\n </Flex>\n <Box width=\"100%\" height=\"261px\" overflow=\"auto\" tag=\"main\">\n {permissionStatus === 'loading' && <Widget.Loading />}\n {permissionStatus === 'forbidden' && <Widget.NoPermissions />}\n {permissionStatus === 'granted' && 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\n const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state) => state.widgets.getAll);\n const filteredWidgets = React.useMemo(\n () =>\n getAllWidgets().filter(\n (widget) =>\n !widget.roles ||\n user?.roles?.some((userRole) => widget.roles?.find((role) => userRole.code === role))\n ),\n [getAllWidgets, user?.roles]\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 <FreeTrialWelcomeModal />\n <FreeTrialEndedModal />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={8} paddingBottom={10}>\n <GuidedTourHomepageOverview />\n <Grid.Root gap={5}>\n {filteredWidgets.map((widget) => {\n return (\n <Grid.Item col={6} s={12} key={widget.uid}>\n <WidgetRoot\n title={widget.title}\n icon={widget.icon}\n permissions={widget.permissions}\n link={widget.link}\n >\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 * 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","permissions","children","link","formatMessage","useIntl","id","React","useId","Icon","permissionStatus","setPermissionStatus","useState","checkUserHasPermissions","useAuth","state","useEffect","checkPermissions","matchingPermissions","shouldGrant","length","_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","label","Box","height","overflow","Widget","Loading","NoPermissions","WidgetComponent","component","loadedComponent","setLoadedComponent","loadComponent","resolvedComponent","Component","HomePageCE","user","displayName","firstname","username","email","getAllWidgets","useStrapiApp","widgets","getAll","filteredWidgets","useMemo","filter","widget","roles","some","userRole","find","role","code","Main","Page","Title","defaultMessage","Layouts","Header","name","subtitle","FreeTrialWelcomeModal","FreeTrialEndedModal","Content","paddingBottom","GuidedTourHomepageOverview","Grid","Root","map","Item","col","s","uid","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, Flex, Grid, Main, Typography } 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';\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 extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link'> {\n children: React.ReactNode;\n}\n\nexport const WidgetRoot = ({ title, icon = PuzzlePiece, children, link }: WidgetRootProps) => {\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\" 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 >\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 <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} 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 <Grid.Root gap={5}>\n {filteredWidgets.map((widget) => (\n <Grid.Item col={6} s={12} key={widget.uid}>\n <WidgetRoot title={widget.title} icon={widget.icon} link={widget.link}>\n <WidgetComponent component={widget.component} />\n </WidgetRoot>\n </Grid.Item>\n ))}\n </Grid.Root>\n )}\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","link","formatMessage","useIntl","id","React","useId","Icon","_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","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","Main","Page","Title","defaultMessage","Layouts","Header","name","subtitle","FreeTrialWelcomeModal","FreeTrialEndedModal","Content","paddingBottom","GuidedTourHomepageOverview","position","top","left","right","bottom","Grid","Root","Item","col","s","uid","HomePage","useEnterprise","HomePageEE"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BaA,MAAAA,UAAAA,GAAa,CAAC,EAAEC,KAAK,EAAEC,IAAOC,GAAAA,iBAAW,EAAEC,QAAQ,EAAEC,IAAI,EAAmB,GAAA;IACvF,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;IAC1B,MAAMC,EAAAA,GAAKC,iBAAMC,KAAK,EAAA;AACtB,IAAA,MAAMC,IAAOT,GAAAA,IAAAA;AAEb,IAAA,qBACEU,eAACC,CAAAA,iBAAAA,EAAAA;QACCC,KAAM,EAAA,MAAA;QACNC,SAAS,EAAA,IAAA;QACTC,SAAU,EAAA,QAAA;QACVC,UAAW,EAAA,YAAA;QACXC,UAAW,EAAA,UAAA;QACXC,WAAY,EAAA,YAAA;QACZC,MAAO,EAAA,aAAA;QACPC,GAAI,EAAA,SAAA;QACJC,GAAK,EAAA,CAAA;QACLC,OAAS,EAAA,CAAA;QACTC,iBAAiBhB,EAAAA,EAAAA;;0BAEjBI,eAACC,CAAAA,iBAAAA,EAAAA;gBAAKG,SAAU,EAAA,KAAA;gBAAMM,GAAK,EAAA,CAAA;gBAAGG,cAAe,EAAA,eAAA;gBAAgBX,KAAM,EAAA,MAAA;gBAAOO,GAAI,EAAA,QAAA;;kCAC5ET,eAACC,CAAAA,iBAAAA,EAAAA;wBAAKS,GAAK,EAAA,CAAA;;0CACTI,cAACf,CAAAA,IAAAA,EAAAA;gCAAKgB,IAAK,EAAA,YAAA;gCAAaC,aAAW,EAAA;;0CACnCF,cAACG,CAAAA,uBAAAA,EAAAA;gCAAWC,SAAU,EAAA,YAAA;gCAAaC,OAAQ,EAAA,OAAA;gCAAQV,GAAI,EAAA,IAAA;gCAAKb,EAAIA,EAAAA,EAAAA;0CAC7DF,aAAcL,CAAAA,KAAAA;;;;AAGlBI,oBAAAA,IAAAA,kBACCqB,cAACG,CAAAA,uBAAAA,EAAAA;wBACCR,GAAKW,EAAAA,mBAAAA;wBACLD,OAAQ,EAAA,OAAA;wBACRD,SAAU,EAAA,YAAA;wBACVG,KAAO,EAAA;4BAAEC,cAAgB,EAAA;AAAO,yBAAA;wBAChCC,SAAU,EAAA,OAAA;AACVC,wBAAAA,EAAAA,EAAI/B,KAAKgC,IAAI;AAEZ/B,wBAAAA,QAAAA,EAAAA,aAAAA,CAAcD,KAAKiC,KAAK;;;;0BAI/BZ,cAACa,CAAAA,gBAAAA,EAAAA;gBAAIzB,KAAM,EAAA,MAAA;gBAAO0B,MAAO,EAAA,OAAA;gBAAQC,QAAS,EAAA,MAAA;gBAAOpB,GAAI,EAAA,MAAA;AAClDjB,gBAAAA,QAAAA,EAAAA;;;;AAIT;AAEA;;AAEkG,qGAElG,MAAMsC,eAAAA,GAAkB,CAAC,EAAEC,SAAS,EAAqD,GAAA;AACvF,IAAA,MAAM,CAACC,eAAiBC,EAAAA,kBAAAA,CAAmB,GAAGpC,gBAAAA,CAAMqC,QAAQ,CAA6B,IAAA,CAAA;AAEzFrC,IAAAA,gBAAAA,CAAMsC,SAAS,CAAC,IAAA;AACd,QAAA,MAAMC,aAAgB,GAAA,UAAA;AACpB,YAAA,MAAMC,oBAAoB,MAAMN,SAAAA,EAAAA;AAEhCE,YAAAA,kBAAAA,CAAmB,IAAMI,iBAAAA,CAAAA;AAC3B,SAAA;AAEAD,QAAAA,aAAAA,EAAAA;KACC,EAAA;AAACL,QAAAA;AAAU,KAAA,CAAA;AAEd,IAAA,MAAMO,SAAYN,GAAAA,eAAAA;AAElB,IAAA,IAAI,CAACM,SAAW,EAAA;QACd,qBAAOxB,cAAA,CAACyB,qBAAOC,OAAO,EAAA,EAAA,CAAA;AACxB;AAEA,IAAA,qBAAO1B,cAACwB,CAAAA,SAAAA,EAAAA,EAAAA,CAAAA;AACV,CAAA;AAEA;;AAEkG,2GAE5FG,UAAa,GAAA,IAAA;IACjB,MAAM,EAAE/C,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAC1B,IAAA,MAAM+C,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;IAC/D,MAAMC,aAAAA,GAAgBC,uBAAa,oBAAsB,EAAA,CAACN,QAAUA,KAAMO,CAAAA,OAAO,CAACC,MAAM,CAAA;AACxF,IAAA,MAAMC,0BAA0BV,YAAQ,CAAA,YAAA,EAAc,CAACC,KAAAA,GAAUA,MAAMS,uBAAuB,CAAA;AAC9F,IAAA,MAAM,CAACC,eAAiBC,EAAAA,kBAAAA,CAAmB,GAAG1D,gBAAMqC,CAAAA,QAAQ,CAAkB,EAAE,CAAA;AAChF,IAAA,MAAM,CAACsB,OAASC,EAAAA,UAAAA,CAAW,GAAG5D,gBAAAA,CAAMqC,QAAQ,CAAC,IAAA,CAAA;AAE7CrC,IAAAA,gBAAAA,CAAMsC,SAAS,CAAC,IAAA;AACd,QAAA,MAAMuB,uBAA0B,GAAA,UAAA;AAC9B,YAAA,MAAMC,UAAaV,GAAAA,aAAAA,EAAAA;YACnB,MAAMW,iBAAAA,GAAoB,MAAMC,OAAQC,CAAAA,GAAG,CACzCH,UAAWI,CAAAA,GAAG,CAAC,OAAOC,MAAAA,GAAAA;gBACpB,IAAI,CAACA,MAAOC,CAAAA,WAAW,IAAID,MAAAA,CAAOC,WAAW,CAACC,MAAM,KAAK,CAAA,EAAG,OAAO,IAAA;AACnE,gBAAA,MAAMC,mBAAsB,GAAA,MAAMd,uBAAwBW,CAAAA,MAAAA,CAAOC,WAAW,CAAA;AAC5E,gBAAA,OAAOE,oBAAoBD,MAAM,IAAIF,MAAOC,CAAAA,WAAW,CAACC,MAAM;AAChE,aAAA,CAAA,CAAA;YAEFX,kBAAmBI,CAAAA,UAAAA,CAAWS,MAAM,CAAC,CAACC,GAAGC,CAAMV,GAAAA,iBAAiB,CAACU,CAAE,CAAA,CAAA,CAAA;YACnEb,UAAW,CAAA,KAAA,CAAA;AACb,SAAA;AAEAC,QAAAA,uBAAAA,EAAAA;KACC,EAAA;AAACL,QAAAA,uBAAAA;AAAyBJ,QAAAA;AAAc,KAAA,CAAA;AAE3C,IAAA,qBACEjD,eAACuE,CAAAA,iBAAAA,EAAAA;;AACC,0BAAAzD,cAAA,CAAC0D,iBAAKC,KAAK,EAAA;0BACR/E,aAAc,CAAA;oBAAEE,EAAI,EAAA,qBAAA;oBAAuB8E,cAAgB,EAAA;AAAW,iBAAA;;AAEzE,0BAAA5D,cAAA,CAAC6D,eAAQC,MAAM,EAAA;AACbvF,gBAAAA,KAAAA,EAAOK,aACL,CAAA;oBAAEE,EAAI,EAAA,uBAAA;oBAAyB8E,cAAgB,EAAA;iBAC/C,EAAA;oBAAEG,IAAMhC,EAAAA;AAAY,iBAAA,CAAA;AAEtBiC,gBAAAA,QAAAA,EAAUpF,aAAc,CAAA;oBACtBE,EAAI,EAAA,0BAAA;oBACJ8E,cAAgB,EAAA;AAClB,iBAAA;;0BAEF5D,cAACiE,CAAAA,2CAAAA,EAAAA,EAAAA,CAAAA;0BACDjE,cAACkE,CAAAA,uCAAAA,EAAAA,EAAAA,CAAAA;AACD,0BAAAlE,cAAA,CAAC6D,eAAQM,OAAO,EAAA;AACd,gBAAA,QAAA,gBAAAjF,eAACC,CAAAA,iBAAAA,EAAAA;oBAAKG,SAAU,EAAA,QAAA;oBAASC,UAAW,EAAA,SAAA;oBAAUK,GAAK,EAAA,CAAA;oBAAGwE,aAAe,EAAA,EAAA;;sCACnEpE,cAACqE,CAAAA,mCAAAA,EAAAA,EAAAA,CAAAA;AACA3B,wBAAAA,OAAAA,iBACC1C,cAACa,CAAAA,gBAAAA,EAAAA;4BAAIyD,QAAS,EAAA,UAAA;4BAAWC,GAAK,EAAA,CAAA;4BAAGC,IAAM,EAAA,CAAA;4BAAGC,KAAO,EAAA,CAAA;4BAAGC,MAAQ,EAAA,CAAA;oDAC1D1E,cAAA,CAAC0D,iBAAKhC,OAAO,EAAA,EAAA;AAGf,yBAAA,CAAA,iBAAA1B,cAAA,CAAC2E,kBAAKC,IAAI,EAAA;4BAAChF,GAAK,EAAA,CAAA;AACb4C,4BAAAA,QAAAA,EAAAA,eAAAA,CAAgBS,GAAG,CAAC,CAACC,MACpB,iBAAAlD,cAAA,CAAC2E,kBAAKE,IAAI,EAAA;oCAACC,GAAK,EAAA,CAAA;oCAAGC,CAAG,EAAA,EAAA;AACpB,oCAAA,QAAA,gBAAA/E,cAAC1B,CAAAA,UAAAA,EAAAA;AAAWC,wCAAAA,KAAAA,EAAO2E,OAAO3E,KAAK;AAAEC,wCAAAA,IAAAA,EAAM0E,OAAO1E,IAAI;AAAEG,wCAAAA,IAAAA,EAAMuE,OAAOvE,IAAI;AACnE,wCAAA,QAAA,gBAAAqB,cAACgB,CAAAA,eAAAA,EAAAA;AAAgBC,4CAAAA,SAAAA,EAAWiC,OAAOjC;;;AAFRiC,iCAAAA,EAAAA,MAAAA,CAAO8B,GAAG,CAAA;;;;;;;AAYzD;AAEA;;AAEkG,2GAE5FC,QAAW,GAAA,IAAA;IACf,MAAMvB,IAAAA,GAAOwB,2BACXvD,CAAAA,UAAAA;AAEA,IAAA,UAAY,CAAC,MAAM,oDAAO,4CAAA,KAAyC,EAAGwD,UAAU,CAAA;;AAIlF,IAAA,IAAI,CAACzB,IAAM,EAAA;QACT,OAAO,IAAA;AACT;AAEA,IAAA,qBAAO1D,cAAC0D,CAAAA,IAAAA,EAAAA,EAAAA,CAAAA;AACV;;;;;;"}
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import { Main, Flex, Grid, Typography, Box } from '@strapi/design-system';
3
+ import { Main, Flex, Box, Grid, Typography } from '@strapi/design-system';
4
4
  import { PuzzlePiece } from '@strapi/icons';
5
5
  import { useIntl } from 'react-intl';
6
6
  import { Link } from 'react-router-dom';
@@ -15,27 +15,10 @@ import { useStrapiApp } from '../../features/StrapiApp.mjs';
15
15
  import { FreeTrialEndedModal } from './components/FreeTrialEndedModal.mjs';
16
16
  import { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal.mjs';
17
17
 
18
- const WidgetRoot = ({ title, icon = PuzzlePiece, permissions = [], children, link })=>{
18
+ const WidgetRoot = ({ title, icon = PuzzlePiece, children, link })=>{
19
19
  const { formatMessage } = useIntl();
20
20
  const id = React.useId();
21
21
  const Icon = icon;
22
- const [permissionStatus, setPermissionStatus] = React.useState('loading');
23
- const checkUserHasPermissions = useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
24
- React.useEffect(()=>{
25
- const checkPermissions = async ()=>{
26
- const matchingPermissions = await checkUserHasPermissions(permissions);
27
- const shouldGrant = matchingPermissions.length >= permissions.length;
28
- setPermissionStatus(shouldGrant ? 'granted' : 'forbidden');
29
- };
30
- if (!permissions || permissions.length === 0) {
31
- setPermissionStatus('granted');
32
- } else {
33
- checkPermissions();
34
- }
35
- }, [
36
- checkUserHasPermissions,
37
- permissions
38
- ]);
39
22
  return /*#__PURE__*/ jsxs(Flex, {
40
23
  width: "100%",
41
24
  hasRadius: true,
@@ -85,16 +68,12 @@ const WidgetRoot = ({ title, icon = PuzzlePiece, permissions = [], children, lin
85
68
  })
86
69
  ]
87
70
  }),
88
- /*#__PURE__*/ jsxs(Box, {
71
+ /*#__PURE__*/ jsx(Box, {
89
72
  width: "100%",
90
73
  height: "261px",
91
74
  overflow: "auto",
92
75
  tag: "main",
93
- children: [
94
- permissionStatus === 'loading' && /*#__PURE__*/ jsx(Widget.Loading, {}),
95
- permissionStatus === 'forbidden' && /*#__PURE__*/ jsx(Widget.NoPermissions, {}),
96
- permissionStatus === 'granted' && children
97
- ]
76
+ children: children
98
77
  })
99
78
  ]
100
79
  });
@@ -125,9 +104,24 @@ const WidgetRoot = ({ title, icon = PuzzlePiece, permissions = [], children, lin
125
104
  const user = useAuth('HomePageCE', (state)=>state.user);
126
105
  const displayName = user?.firstname ?? user?.username ?? user?.email;
127
106
  const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state)=>state.widgets.getAll);
128
- const filteredWidgets = React.useMemo(()=>getAllWidgets().filter((widget)=>!widget.roles || user?.roles?.some((userRole)=>widget.roles?.find((role)=>userRole.code === role))), [
129
- getAllWidgets,
130
- user?.roles
107
+ const checkUserHasPermissions = useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
108
+ const [filteredWidgets, setFilteredWidgets] = React.useState([]);
109
+ const [loading, setLoading] = React.useState(true);
110
+ React.useEffect(()=>{
111
+ const checkWidgetsPermissions = async ()=>{
112
+ const allWidgets = getAllWidgets();
113
+ const authorizedWidgets = await Promise.all(allWidgets.map(async (widget)=>{
114
+ if (!widget.permissions || widget.permissions.length === 0) return true;
115
+ const matchingPermissions = await checkUserHasPermissions(widget.permissions);
116
+ return matchingPermissions.length >= widget.permissions.length;
117
+ }));
118
+ setFilteredWidgets(allWidgets.filter((_, i)=>authorizedWidgets[i]));
119
+ setLoading(false);
120
+ };
121
+ checkWidgetsPermissions();
122
+ }, [
123
+ checkUserHasPermissions,
124
+ getAllWidgets
131
125
  ]);
132
126
  return /*#__PURE__*/ jsxs(Main, {
133
127
  children: [
@@ -159,23 +153,27 @@ const WidgetRoot = ({ title, icon = PuzzlePiece, permissions = [], children, lin
159
153
  paddingBottom: 10,
160
154
  children: [
161
155
  /*#__PURE__*/ jsx(GuidedTourHomepageOverview, {}),
162
- /*#__PURE__*/ jsx(Grid.Root, {
156
+ loading ? /*#__PURE__*/ jsx(Box, {
157
+ position: "absolute",
158
+ top: 0,
159
+ left: 0,
160
+ right: 0,
161
+ bottom: 0,
162
+ children: /*#__PURE__*/ jsx(Page.Loading, {})
163
+ }) : /*#__PURE__*/ jsx(Grid.Root, {
163
164
  gap: 5,
164
- children: filteredWidgets.map((widget)=>{
165
- return /*#__PURE__*/ jsx(Grid.Item, {
165
+ children: filteredWidgets.map((widget)=>/*#__PURE__*/ jsx(Grid.Item, {
166
166
  col: 6,
167
167
  s: 12,
168
168
  children: /*#__PURE__*/ jsx(WidgetRoot, {
169
169
  title: widget.title,
170
170
  icon: widget.icon,
171
- permissions: widget.permissions,
172
171
  link: widget.link,
173
172
  children: /*#__PURE__*/ jsx(WidgetComponent, {
174
173
  component: widget.component
175
174
  })
176
175
  })
177
- }, widget.uid);
178
- })
176
+ }, widget.uid))
179
177
  })
180
178
  ]
181
179
  })