@strapi/admin 5.21.0 → 5.23.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 (132) 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/Context.js +23 -8
  6. package/dist/admin/admin/src/components/GuidedTour/Context.js.map +1 -1
  7. package/dist/admin/admin/src/components/GuidedTour/Context.mjs +23 -8
  8. package/dist/admin/admin/src/components/GuidedTour/Context.mjs.map +1 -1
  9. package/dist/admin/admin/src/components/GuidedTour/Overview.js +7 -5
  10. package/dist/admin/admin/src/components/GuidedTour/Overview.js.map +1 -1
  11. package/dist/admin/admin/src/components/GuidedTour/Overview.mjs +7 -5
  12. package/dist/admin/admin/src/components/GuidedTour/Overview.mjs.map +1 -1
  13. package/dist/admin/admin/src/components/GuidedTour/Steps/ApiTokensSteps.js +156 -0
  14. package/dist/admin/admin/src/components/GuidedTour/Steps/ApiTokensSteps.js.map +1 -0
  15. package/dist/admin/admin/src/components/GuidedTour/Steps/ApiTokensSteps.mjs +154 -0
  16. package/dist/admin/admin/src/components/GuidedTour/Steps/ApiTokensSteps.mjs.map +1 -0
  17. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentManagerSteps.js +221 -0
  18. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentManagerSteps.js.map +1 -0
  19. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentManagerSteps.mjs +219 -0
  20. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentManagerSteps.mjs.map +1 -0
  21. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.js +219 -0
  22. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.js.map +1 -0
  23. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.mjs +217 -0
  24. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.mjs.map +1 -0
  25. package/dist/admin/admin/src/components/GuidedTour/{Step.js → Steps/Step.js} +116 -71
  26. package/dist/admin/admin/src/components/GuidedTour/Steps/Step.js.map +1 -0
  27. package/dist/admin/admin/src/components/GuidedTour/{Step.mjs → Steps/Step.mjs} +117 -74
  28. package/dist/admin/admin/src/components/GuidedTour/Steps/Step.mjs.map +1 -0
  29. package/dist/admin/admin/src/components/GuidedTour/Tours.js +47 -322
  30. package/dist/admin/admin/src/components/GuidedTour/Tours.js.map +1 -1
  31. package/dist/admin/admin/src/components/GuidedTour/Tours.mjs +48 -324
  32. package/dist/admin/admin/src/components/GuidedTour/Tours.mjs.map +1 -1
  33. package/dist/admin/admin/src/components/GuidedTour/utils/constants.js +19 -0
  34. package/dist/admin/admin/src/components/GuidedTour/utils/constants.js.map +1 -0
  35. package/dist/admin/admin/src/components/GuidedTour/utils/constants.mjs +17 -0
  36. package/dist/admin/admin/src/components/GuidedTour/utils/constants.mjs.map +1 -0
  37. package/dist/admin/admin/src/components/GuidedTour/utils/migrations.js +31 -0
  38. package/dist/admin/admin/src/components/GuidedTour/utils/migrations.js.map +1 -0
  39. package/dist/admin/admin/src/components/GuidedTour/utils/migrations.mjs +29 -0
  40. package/dist/admin/admin/src/components/GuidedTour/utils/migrations.mjs.map +1 -0
  41. package/dist/admin/admin/src/components/SubNav.js +3 -1
  42. package/dist/admin/admin/src/components/SubNav.js.map +1 -1
  43. package/dist/admin/admin/src/components/SubNav.mjs +3 -1
  44. package/dist/admin/admin/src/components/SubNav.mjs.map +1 -1
  45. package/dist/admin/admin/src/components/Widgets.js +27 -9
  46. package/dist/admin/admin/src/components/Widgets.js.map +1 -1
  47. package/dist/admin/admin/src/components/Widgets.mjs +28 -10
  48. package/dist/admin/admin/src/components/Widgets.mjs.map +1 -1
  49. package/dist/admin/admin/src/features/Tracking.js.map +1 -1
  50. package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
  51. package/dist/admin/admin/src/pages/Home/HomePage.js +40 -33
  52. package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
  53. package/dist/admin/admin/src/pages/Home/HomePage.mjs +41 -34
  54. package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
  55. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.js +17 -14
  56. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.js.map +1 -1
  57. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.mjs +17 -14
  58. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.mjs.map +1 -1
  59. package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.js +31 -6
  60. package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.js.map +1 -1
  61. package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.mjs +12 -6
  62. package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.mjs.map +1 -1
  63. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.js +28 -24
  64. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.js.map +1 -1
  65. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.mjs +28 -24
  66. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.mjs.map +1 -1
  67. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.js.map +1 -1
  68. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.mjs.map +1 -1
  69. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.js +56 -57
  70. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.js.map +1 -1
  71. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.mjs +57 -58
  72. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.mjs.map +1 -1
  73. package/dist/admin/admin/src/services/apiTokens.js +0 -1
  74. package/dist/admin/admin/src/services/apiTokens.js.map +1 -1
  75. package/dist/admin/admin/src/services/apiTokens.mjs +0 -1
  76. package/dist/admin/admin/src/services/apiTokens.mjs.map +1 -1
  77. package/dist/admin/admin/src/translations/en.json.js +35 -21
  78. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  79. package/dist/admin/admin/src/translations/en.json.mjs +35 -21
  80. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  81. package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.js +131 -0
  82. package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.js.map +1 -0
  83. package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.mjs +129 -0
  84. package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.mjs.map +1 -0
  85. package/dist/admin/ee/admin/src/constants.js +3 -1
  86. package/dist/admin/ee/admin/src/constants.js.map +1 -1
  87. package/dist/admin/ee/admin/src/constants.mjs +3 -2
  88. package/dist/admin/ee/admin/src/constants.mjs.map +1 -1
  89. package/dist/admin/index.js +6 -2
  90. package/dist/admin/index.js.map +1 -1
  91. package/dist/admin/index.mjs +2 -0
  92. package/dist/admin/index.mjs.map +1 -1
  93. package/dist/admin/src/components/GuidedTour/Context.d.ts +26 -9
  94. package/dist/admin/src/components/GuidedTour/Steps/ApiTokensSteps.d.ts +20 -0
  95. package/dist/admin/src/components/GuidedTour/Steps/ContentManagerSteps.d.ts +21 -0
  96. package/dist/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.d.ts +30 -0
  97. package/dist/admin/src/components/GuidedTour/{Step.d.ts → Steps/Step.d.ts} +25 -6
  98. package/dist/admin/src/components/GuidedTour/Tours.d.ts +53 -14
  99. package/dist/admin/src/components/GuidedTour/utils/constants.d.ts +15 -0
  100. package/dist/admin/src/components/GuidedTour/utils/migrations.d.ts +6 -0
  101. package/dist/admin/src/features/Tracking.d.ts +20 -2
  102. package/dist/admin/src/index.d.ts +5 -0
  103. package/dist/admin/src/pages/Home/HomePage.d.ts +2 -2
  104. package/dist/ee/admin/src/components/AuditLogs/Widgets.d.ts +2 -0
  105. package/dist/ee/admin/src/constants.d.ts +1 -0
  106. package/dist/server/server/src/controllers/admin.js +2 -5
  107. package/dist/server/server/src/controllers/admin.js.map +1 -1
  108. package/dist/server/server/src/controllers/admin.mjs +2 -5
  109. package/dist/server/server/src/controllers/admin.mjs.map +1 -1
  110. package/dist/server/server/src/services/index.js +0 -2
  111. package/dist/server/server/src/services/index.js.map +1 -1
  112. package/dist/server/server/src/services/index.mjs +0 -2
  113. package/dist/server/server/src/services/index.mjs.map +1 -1
  114. package/dist/server/src/controllers/admin.d.ts +1 -1
  115. package/dist/server/src/controllers/admin.d.ts.map +1 -1
  116. package/dist/server/src/controllers/index.d.ts +1 -1
  117. package/dist/server/src/index.d.ts +1 -6
  118. package/dist/server/src/index.d.ts.map +1 -1
  119. package/dist/server/src/services/constants.d.ts +1 -0
  120. package/dist/server/src/services/guided-tour.d.ts +2 -3
  121. package/dist/server/src/services/guided-tour.d.ts.map +1 -1
  122. package/dist/server/src/services/index.d.ts +0 -5
  123. package/dist/server/src/services/index.d.ts.map +1 -1
  124. package/dist/shared/contracts/admin.d.ts +2 -2
  125. package/dist/shared/contracts/admin.d.ts.map +1 -1
  126. package/package.json +7 -7
  127. package/dist/admin/admin/src/components/GuidedTour/Step.js.map +0 -1
  128. package/dist/admin/admin/src/components/GuidedTour/Step.mjs.map +0 -1
  129. package/dist/server/server/src/services/guided-tour.js +0 -61
  130. package/dist/server/server/src/services/guided-tour.js.map +0 -1
  131. package/dist/server/server/src/services/guided-tour.mjs +0 -59
  132. package/dist/server/server/src/services/guided-tour.mjs.map +0 -1
@@ -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 | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willOpenAuditLogDetailsFromHome'\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\ninterface WillEditEntryFromHome {\n name: 'willEditEntryFromHome';\n properties: {\n entryType: 'edited' | 'published' | 'assigned';\n };\n}\n\ninterface DidOpenHomeWidgetLink {\n name: 'didOpenHomeWidgetLink';\n properties: {\n widgetUID: string;\n };\n}\n\ninterface DidOpenKeyStatisticsWidgetLink {\n name: 'didOpenKeyStatisticsWidgetLink';\n properties: {\n itemKey: string;\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 | DidOpenHomeWidgetLink\n | DidOpenKeyStatisticsWidgetLink\n | WillEditEntryFromHome;\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 +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 | 'willEditEntryFromList'\n | 'willEditReleaseFromHome'\n | 'willEditFieldOfContentType'\n | 'willEditMediaLibraryConfig'\n | 'willEditNameOfContentType'\n | 'willEditNameOfSingleType'\n | 'willEditAuthenticationProvider'\n | 'willEditFieldNameOnContentType'\n | 'willEditStage'\n | 'willFilterEntries'\n | 'willInstallPlugin'\n | 'willOpenAuditLogDetailsFromHome'\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\ninterface WillEditEntryFromHome {\n name: 'willEditEntryFromHome';\n properties: {\n entryType: 'edited' | 'published' | 'assigned';\n };\n}\n\ninterface DidOpenHomeWidgetLink {\n name: 'didOpenHomeWidgetLink';\n properties: {\n widgetUID: string;\n };\n}\n\ninterface DidOpenKeyStatisticsWidgetLink {\n name: 'didOpenKeyStatisticsWidgetLink';\n properties: {\n itemKey: string;\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 | DidOpenHomeWidgetLink\n | DidOpenKeyStatisticsWidgetLink\n | WillEditEntryFromHome;\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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"}
@@ -14,6 +14,7 @@ require('../../services/admin.js');
14
14
  var useEnterprise = require('../../hooks/useEnterprise.js');
15
15
  var Auth = require('../../features/Auth.js');
16
16
  var StrapiApp = require('../../features/StrapiApp.js');
17
+ var Tracking = require('../../features/Tracking.js');
17
18
  var FreeTrialEndedModal = require('./components/FreeTrialEndedModal.js');
18
19
  var FreeTrialWelcomeModal = require('./components/FreeTrialWelcomeModal.js');
19
20
 
@@ -36,27 +37,16 @@ function _interopNamespaceDefault(e) {
36
37
 
37
38
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
38
39
 
39
- const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], children, link })=>{
40
+ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, children, link, uid })=>{
41
+ const { trackUsage } = Tracking.useTracking();
40
42
  const { formatMessage } = reactIntl.useIntl();
41
43
  const id = React__namespace.useId();
42
44
  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
- ]);
45
+ const handleClickOnLink = ()=>{
46
+ trackUsage('didOpenHomeWidgetLink', {
47
+ widgetUID: uid
48
+ });
49
+ };
60
50
  return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
61
51
  width: "100%",
62
52
  hasRadius: true,
@@ -102,20 +92,17 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], childre
102
92
  },
103
93
  textAlign: "right",
104
94
  to: link.href,
95
+ onClick: handleClickOnLink,
105
96
  children: formatMessage(link.label)
106
97
  })
107
98
  ]
108
99
  }),
109
- /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, {
100
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
110
101
  width: "100%",
111
102
  height: "261px",
112
103
  overflow: "auto",
113
104
  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
- ]
105
+ children: children
119
106
  })
120
107
  ]
121
108
  });
@@ -146,9 +133,24 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], childre
146
133
  const user = Auth.useAuth('HomePageCE', (state)=>state.user);
147
134
  const displayName = user?.firstname ?? user?.username ?? user?.email;
148
135
  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
136
+ const checkUserHasPermissions = Auth.useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
137
+ const [filteredWidgets, setFilteredWidgets] = React__namespace.useState([]);
138
+ const [loading, setLoading] = React__namespace.useState(true);
139
+ React__namespace.useEffect(()=>{
140
+ const checkWidgetsPermissions = async ()=>{
141
+ const allWidgets = getAllWidgets();
142
+ const authorizedWidgets = await Promise.all(allWidgets.map(async (widget)=>{
143
+ if (!widget.permissions || widget.permissions.length === 0) return true;
144
+ const matchingPermissions = await checkUserHasPermissions(widget.permissions);
145
+ return matchingPermissions.length >= widget.permissions.length;
146
+ }));
147
+ setFilteredWidgets(allWidgets.filter((_, i)=>authorizedWidgets[i]));
148
+ setLoading(false);
149
+ };
150
+ checkWidgetsPermissions();
151
+ }, [
152
+ checkUserHasPermissions,
153
+ getAllWidgets
152
154
  ]);
153
155
  return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Main, {
154
156
  children: [
@@ -180,23 +182,28 @@ const WidgetRoot = ({ title, icon = icons.PuzzlePiece, permissions = [], childre
180
182
  paddingBottom: 10,
181
183
  children: [
182
184
  /*#__PURE__*/ jsxRuntime.jsx(Overview.GuidedTourHomepageOverview, {}),
183
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Root, {
185
+ loading ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
186
+ position: "absolute",
187
+ top: 0,
188
+ left: 0,
189
+ right: 0,
190
+ bottom: 0,
191
+ children: /*#__PURE__*/ jsxRuntime.jsx(PageHelpers.Page.Loading, {})
192
+ }) : /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Root, {
184
193
  gap: 5,
185
- children: filteredWidgets.map((widget)=>{
186
- return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
194
+ children: filteredWidgets.map((widget)=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
187
195
  col: 6,
188
196
  s: 12,
189
197
  children: /*#__PURE__*/ jsxRuntime.jsx(WidgetRoot, {
190
198
  title: widget.title,
191
199
  icon: widget.icon,
192
- permissions: widget.permissions,
193
200
  link: widget.link,
201
+ uid: widget.uid,
194
202
  children: /*#__PURE__*/ jsxRuntime.jsx(WidgetComponent, {
195
203
  component: widget.component
196
204
  })
197
205
  })
198
- }, widget.uid);
199
- })
206
+ }, widget.uid))
200
207
  })
201
208
  ]
202
209
  })
@@ -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';\nimport { useTracking } from '../../features/Tracking';\n\nimport { FreeTrialEndedModal } from './components/FreeTrialEndedModal';\nimport { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';\n\nimport type { WidgetWithUID } from '../../core/apis/Widgets';\nimport type { WidgetType } from '@strapi/admin/strapi-admin';\n\n/* -------------------------------------------------------------------------------------------------\n * WidgetRoot\n * -----------------------------------------------------------------------------------------------*/\n\ninterface WidgetRootProps\n extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link' | 'uid'> {\n children: React.ReactNode;\n}\n\nexport const WidgetRoot = ({ title, icon = PuzzlePiece, children, link, uid }: WidgetRootProps) => {\n const { trackUsage } = useTracking();\n const { formatMessage } = useIntl();\n const id = React.useId();\n const Icon = icon;\n\n const handleClickOnLink = () => {\n trackUsage('didOpenHomeWidgetLink', { widgetUID: uid });\n };\n\n return (\n <Flex\n width=\"100%\"\n hasRadius\n direction=\"column\"\n alignItems=\"flex-start\"\n background=\"neutral0\"\n borderColor=\"neutral150\"\n shadow=\"tableShadow\"\n tag=\"section\"\n gap={4}\n padding={6}\n aria-labelledby={id}\n >\n <Flex direction=\"row\" gap={2} justifyContent=\"space-between\" width=\"100%\" tag=\"header\">\n <Flex gap={2}>\n <Icon fill=\"neutral500\" aria-hidden />\n <Typography textColor=\"neutral500\" variant=\"sigma\" tag=\"h2\" id={id}>\n {formatMessage(title)}\n </Typography>\n </Flex>\n {link && (\n <Typography\n tag={ReactRouterLink}\n variant=\"omega\"\n textColor=\"primary600\"\n style={{ textDecoration: 'none' }}\n textAlign=\"right\"\n to={link.href}\n onClick={handleClickOnLink}\n >\n {formatMessage(link.label)}\n </Typography>\n )}\n </Flex>\n <Box width=\"100%\" height=\"261px\" overflow=\"auto\" tag=\"main\">\n {children}\n </Box>\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * UnstableHomePageCe\n * -----------------------------------------------------------------------------------------------*/\n\nconst WidgetComponent = ({ component }: { component: () => Promise<React.ComponentType> }) => {\n const [loadedComponent, setLoadedComponent] = React.useState<React.ComponentType | null>(null);\n\n React.useEffect(() => {\n const loadComponent = async () => {\n const resolvedComponent = await component();\n\n setLoadedComponent(() => resolvedComponent);\n };\n\n loadComponent();\n }, [component]);\n\n const Component = loadedComponent;\n\n if (!Component) {\n return <Widget.Loading />;\n }\n\n return <Component />;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePageCE\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePageCE = () => {\n const { formatMessage } = useIntl();\n const user = useAuth('HomePageCE', (state) => state.user);\n const displayName = user?.firstname ?? user?.username ?? user?.email;\n const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state) => state.widgets.getAll);\n const checkUserHasPermissions = useAuth('WidgetRoot', (state) => state.checkUserHasPermissions);\n const [filteredWidgets, setFilteredWidgets] = React.useState<WidgetWithUID[]>([]);\n const [loading, setLoading] = React.useState(true);\n\n React.useEffect(() => {\n const checkWidgetsPermissions = async () => {\n const allWidgets = getAllWidgets();\n const authorizedWidgets = await Promise.all(\n allWidgets.map(async (widget) => {\n if (!widget.permissions || widget.permissions.length === 0) return true;\n const matchingPermissions = await checkUserHasPermissions(widget.permissions);\n return matchingPermissions.length >= widget.permissions.length;\n })\n );\n setFilteredWidgets(allWidgets.filter((_, i) => authorizedWidgets[i]));\n setLoading(false);\n };\n\n checkWidgetsPermissions();\n }, [checkUserHasPermissions, getAllWidgets]);\n\n return (\n <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\n title={widget.title}\n icon={widget.icon}\n link={widget.link}\n uid={widget.uid}\n >\n <WidgetComponent component={widget.component} />\n </WidgetRoot>\n </Grid.Item>\n ))}\n </Grid.Root>\n )}\n </Flex>\n </Layouts.Content>\n </Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePage\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePage = () => {\n const Page = useEnterprise(\n HomePageCE,\n // eslint-disable-next-line import/no-cycle\n async () => (await import('../../../../ee/admin/src/pages/HomePage')).HomePageEE\n );\n\n // block rendering until the EE component is fully loaded\n if (!Page) {\n return null;\n }\n\n return <Page />;\n};\n\nexport { HomePage, HomePageCE };\n"],"names":["WidgetRoot","title","icon","PuzzlePiece","children","link","uid","trackUsage","useTracking","formatMessage","useIntl","id","React","useId","Icon","handleClickOnLink","widgetUID","_jsxs","Flex","width","hasRadius","direction","alignItems","background","borderColor","shadow","tag","gap","padding","aria-labelledby","justifyContent","_jsx","fill","aria-hidden","Typography","textColor","variant","ReactRouterLink","style","textDecoration","textAlign","to","href","onClick","label","Box","height","overflow","WidgetComponent","component","loadedComponent","setLoadedComponent","useState","useEffect","loadComponent","resolvedComponent","Component","Widget","Loading","HomePageCE","user","useAuth","state","displayName","firstname","username","email","getAllWidgets","useStrapiApp","widgets","getAll","checkUserHasPermissions","filteredWidgets","setFilteredWidgets","loading","setLoading","checkWidgetsPermissions","allWidgets","authorizedWidgets","Promise","all","map","widget","permissions","length","matchingPermissions","filter","_","i","Main","Page","Title","defaultMessage","Layouts","Header","name","subtitle","FreeTrialWelcomeModal","FreeTrialEndedModal","Content","paddingBottom","GuidedTourHomepageOverview","position","top","left","right","bottom","Grid","Root","Item","col","s","HomePage","useEnterprise","HomePageEE"],"mappings":"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"}
@@ -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';
@@ -12,30 +12,20 @@ import '../../services/admin.mjs';
12
12
  import { useEnterprise } from '../../hooks/useEnterprise.mjs';
13
13
  import { useAuth } from '../../features/Auth.mjs';
14
14
  import { useStrapiApp } from '../../features/StrapiApp.mjs';
15
+ import { useTracking } from '../../features/Tracking.mjs';
15
16
  import { FreeTrialEndedModal } from './components/FreeTrialEndedModal.mjs';
16
17
  import { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal.mjs';
17
18
 
18
- const WidgetRoot = ({ title, icon = PuzzlePiece, permissions = [], children, link })=>{
19
+ const WidgetRoot = ({ title, icon = PuzzlePiece, children, link, uid })=>{
20
+ const { trackUsage } = useTracking();
19
21
  const { formatMessage } = useIntl();
20
22
  const id = React.useId();
21
23
  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
- ]);
24
+ const handleClickOnLink = ()=>{
25
+ trackUsage('didOpenHomeWidgetLink', {
26
+ widgetUID: uid
27
+ });
28
+ };
39
29
  return /*#__PURE__*/ jsxs(Flex, {
40
30
  width: "100%",
41
31
  hasRadius: true,
@@ -81,20 +71,17 @@ const WidgetRoot = ({ title, icon = PuzzlePiece, permissions = [], children, lin
81
71
  },
82
72
  textAlign: "right",
83
73
  to: link.href,
74
+ onClick: handleClickOnLink,
84
75
  children: formatMessage(link.label)
85
76
  })
86
77
  ]
87
78
  }),
88
- /*#__PURE__*/ jsxs(Box, {
79
+ /*#__PURE__*/ jsx(Box, {
89
80
  width: "100%",
90
81
  height: "261px",
91
82
  overflow: "auto",
92
83
  tag: "main",
93
- children: [
94
- permissionStatus === 'loading' && /*#__PURE__*/ jsx(Widget.Loading, {}),
95
- permissionStatus === 'forbidden' && /*#__PURE__*/ jsx(Widget.NoPermissions, {}),
96
- permissionStatus === 'granted' && children
97
- ]
84
+ children: children
98
85
  })
99
86
  ]
100
87
  });
@@ -125,9 +112,24 @@ const WidgetRoot = ({ title, icon = PuzzlePiece, permissions = [], children, lin
125
112
  const user = useAuth('HomePageCE', (state)=>state.user);
126
113
  const displayName = user?.firstname ?? user?.username ?? user?.email;
127
114
  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
115
+ const checkUserHasPermissions = useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
116
+ const [filteredWidgets, setFilteredWidgets] = React.useState([]);
117
+ const [loading, setLoading] = React.useState(true);
118
+ React.useEffect(()=>{
119
+ const checkWidgetsPermissions = async ()=>{
120
+ const allWidgets = getAllWidgets();
121
+ const authorizedWidgets = await Promise.all(allWidgets.map(async (widget)=>{
122
+ if (!widget.permissions || widget.permissions.length === 0) return true;
123
+ const matchingPermissions = await checkUserHasPermissions(widget.permissions);
124
+ return matchingPermissions.length >= widget.permissions.length;
125
+ }));
126
+ setFilteredWidgets(allWidgets.filter((_, i)=>authorizedWidgets[i]));
127
+ setLoading(false);
128
+ };
129
+ checkWidgetsPermissions();
130
+ }, [
131
+ checkUserHasPermissions,
132
+ getAllWidgets
131
133
  ]);
132
134
  return /*#__PURE__*/ jsxs(Main, {
133
135
  children: [
@@ -159,23 +161,28 @@ const WidgetRoot = ({ title, icon = PuzzlePiece, permissions = [], children, lin
159
161
  paddingBottom: 10,
160
162
  children: [
161
163
  /*#__PURE__*/ jsx(GuidedTourHomepageOverview, {}),
162
- /*#__PURE__*/ jsx(Grid.Root, {
164
+ loading ? /*#__PURE__*/ jsx(Box, {
165
+ position: "absolute",
166
+ top: 0,
167
+ left: 0,
168
+ right: 0,
169
+ bottom: 0,
170
+ children: /*#__PURE__*/ jsx(Page.Loading, {})
171
+ }) : /*#__PURE__*/ jsx(Grid.Root, {
163
172
  gap: 5,
164
- children: filteredWidgets.map((widget)=>{
165
- return /*#__PURE__*/ jsx(Grid.Item, {
173
+ children: filteredWidgets.map((widget)=>/*#__PURE__*/ jsx(Grid.Item, {
166
174
  col: 6,
167
175
  s: 12,
168
176
  children: /*#__PURE__*/ jsx(WidgetRoot, {
169
177
  title: widget.title,
170
178
  icon: widget.icon,
171
- permissions: widget.permissions,
172
179
  link: widget.link,
180
+ uid: widget.uid,
173
181
  children: /*#__PURE__*/ jsx(WidgetComponent, {
174
182
  component: widget.component
175
183
  })
176
184
  })
177
- }, widget.uid);
178
- })
185
+ }, widget.uid))
179
186
  })
180
187
  ]
181
188
  })
@@ -1 +1 @@
1
- {"version":3,"file":"HomePage.mjs","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.mjs","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';\nimport { useTracking } from '../../features/Tracking';\n\nimport { FreeTrialEndedModal } from './components/FreeTrialEndedModal';\nimport { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';\n\nimport type { WidgetWithUID } from '../../core/apis/Widgets';\nimport type { WidgetType } from '@strapi/admin/strapi-admin';\n\n/* -------------------------------------------------------------------------------------------------\n * WidgetRoot\n * -----------------------------------------------------------------------------------------------*/\n\ninterface WidgetRootProps\n extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link' | 'uid'> {\n children: React.ReactNode;\n}\n\nexport const WidgetRoot = ({ title, icon = PuzzlePiece, children, link, uid }: WidgetRootProps) => {\n const { trackUsage } = useTracking();\n const { formatMessage } = useIntl();\n const id = React.useId();\n const Icon = icon;\n\n const handleClickOnLink = () => {\n trackUsage('didOpenHomeWidgetLink', { widgetUID: uid });\n };\n\n return (\n <Flex\n width=\"100%\"\n hasRadius\n direction=\"column\"\n alignItems=\"flex-start\"\n background=\"neutral0\"\n borderColor=\"neutral150\"\n shadow=\"tableShadow\"\n tag=\"section\"\n gap={4}\n padding={6}\n aria-labelledby={id}\n >\n <Flex direction=\"row\" gap={2} justifyContent=\"space-between\" width=\"100%\" tag=\"header\">\n <Flex gap={2}>\n <Icon fill=\"neutral500\" aria-hidden />\n <Typography textColor=\"neutral500\" variant=\"sigma\" tag=\"h2\" id={id}>\n {formatMessage(title)}\n </Typography>\n </Flex>\n {link && (\n <Typography\n tag={ReactRouterLink}\n variant=\"omega\"\n textColor=\"primary600\"\n style={{ textDecoration: 'none' }}\n textAlign=\"right\"\n to={link.href}\n onClick={handleClickOnLink}\n >\n {formatMessage(link.label)}\n </Typography>\n )}\n </Flex>\n <Box width=\"100%\" height=\"261px\" overflow=\"auto\" tag=\"main\">\n {children}\n </Box>\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * UnstableHomePageCe\n * -----------------------------------------------------------------------------------------------*/\n\nconst WidgetComponent = ({ component }: { component: () => Promise<React.ComponentType> }) => {\n const [loadedComponent, setLoadedComponent] = React.useState<React.ComponentType | null>(null);\n\n React.useEffect(() => {\n const loadComponent = async () => {\n const resolvedComponent = await component();\n\n setLoadedComponent(() => resolvedComponent);\n };\n\n loadComponent();\n }, [component]);\n\n const Component = loadedComponent;\n\n if (!Component) {\n return <Widget.Loading />;\n }\n\n return <Component />;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePageCE\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePageCE = () => {\n const { formatMessage } = useIntl();\n const user = useAuth('HomePageCE', (state) => state.user);\n const displayName = user?.firstname ?? user?.username ?? user?.email;\n const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state) => state.widgets.getAll);\n const checkUserHasPermissions = useAuth('WidgetRoot', (state) => state.checkUserHasPermissions);\n const [filteredWidgets, setFilteredWidgets] = React.useState<WidgetWithUID[]>([]);\n const [loading, setLoading] = React.useState(true);\n\n React.useEffect(() => {\n const checkWidgetsPermissions = async () => {\n const allWidgets = getAllWidgets();\n const authorizedWidgets = await Promise.all(\n allWidgets.map(async (widget) => {\n if (!widget.permissions || widget.permissions.length === 0) return true;\n const matchingPermissions = await checkUserHasPermissions(widget.permissions);\n return matchingPermissions.length >= widget.permissions.length;\n })\n );\n setFilteredWidgets(allWidgets.filter((_, i) => authorizedWidgets[i]));\n setLoading(false);\n };\n\n checkWidgetsPermissions();\n }, [checkUserHasPermissions, getAllWidgets]);\n\n return (\n <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\n title={widget.title}\n icon={widget.icon}\n link={widget.link}\n uid={widget.uid}\n >\n <WidgetComponent component={widget.component} />\n </WidgetRoot>\n </Grid.Item>\n ))}\n </Grid.Root>\n )}\n </Flex>\n </Layouts.Content>\n </Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePage\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePage = () => {\n const Page = useEnterprise(\n HomePageCE,\n // eslint-disable-next-line import/no-cycle\n async () => (await import('../../../../ee/admin/src/pages/HomePage')).HomePageEE\n );\n\n // block rendering until the EE component is fully loaded\n if (!Page) {\n return null;\n }\n\n return <Page />;\n};\n\nexport { HomePage, HomePageCE };\n"],"names":["WidgetRoot","title","icon","PuzzlePiece","children","link","uid","trackUsage","useTracking","formatMessage","useIntl","id","React","useId","Icon","handleClickOnLink","widgetUID","_jsxs","Flex","width","hasRadius","direction","alignItems","background","borderColor","shadow","tag","gap","padding","aria-labelledby","justifyContent","_jsx","fill","aria-hidden","Typography","textColor","variant","ReactRouterLink","style","textDecoration","textAlign","to","href","onClick","label","Box","height","overflow","WidgetComponent","component","loadedComponent","setLoadedComponent","useState","useEffect","loadComponent","resolvedComponent","Component","Widget","Loading","HomePageCE","user","useAuth","state","displayName","firstname","username","email","getAllWidgets","useStrapiApp","widgets","getAll","checkUserHasPermissions","filteredWidgets","setFilteredWidgets","loading","setLoading","checkWidgetsPermissions","allWidgets","authorizedWidgets","Promise","all","map","widget","permissions","length","matchingPermissions","filter","_","i","Main","Page","Title","defaultMessage","Layouts","Header","name","subtitle","FreeTrialWelcomeModal","FreeTrialEndedModal","Content","paddingBottom","GuidedTourHomepageOverview","position","top","left","right","bottom","Grid","Root","Item","col","s","HomePage","useEnterprise","HomePageEE"],"mappings":"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"}