@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.
- package/dist/admin/admin/src/StrapiApp.js +38 -8
- package/dist/admin/admin/src/StrapiApp.js.map +1 -1
- package/dist/admin/admin/src/StrapiApp.mjs +36 -6
- package/dist/admin/admin/src/StrapiApp.mjs.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Context.js +23 -8
- package/dist/admin/admin/src/components/GuidedTour/Context.js.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Context.mjs +23 -8
- package/dist/admin/admin/src/components/GuidedTour/Context.mjs.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Overview.js +7 -5
- package/dist/admin/admin/src/components/GuidedTour/Overview.js.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Overview.mjs +7 -5
- package/dist/admin/admin/src/components/GuidedTour/Overview.mjs.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Steps/ApiTokensSteps.js +156 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ApiTokensSteps.js.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ApiTokensSteps.mjs +154 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ApiTokensSteps.mjs.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ContentManagerSteps.js +221 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ContentManagerSteps.js.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ContentManagerSteps.mjs +219 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ContentManagerSteps.mjs.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.js +219 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.js.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.mjs +217 -0
- package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.mjs.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/{Step.js → Steps/Step.js} +116 -71
- package/dist/admin/admin/src/components/GuidedTour/Steps/Step.js.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/{Step.mjs → Steps/Step.mjs} +117 -74
- package/dist/admin/admin/src/components/GuidedTour/Steps/Step.mjs.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/Tours.js +47 -322
- package/dist/admin/admin/src/components/GuidedTour/Tours.js.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Tours.mjs +48 -324
- package/dist/admin/admin/src/components/GuidedTour/Tours.mjs.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/utils/constants.js +19 -0
- package/dist/admin/admin/src/components/GuidedTour/utils/constants.js.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/utils/constants.mjs +17 -0
- package/dist/admin/admin/src/components/GuidedTour/utils/constants.mjs.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/utils/migrations.js +31 -0
- package/dist/admin/admin/src/components/GuidedTour/utils/migrations.js.map +1 -0
- package/dist/admin/admin/src/components/GuidedTour/utils/migrations.mjs +29 -0
- package/dist/admin/admin/src/components/GuidedTour/utils/migrations.mjs.map +1 -0
- package/dist/admin/admin/src/components/SubNav.js +3 -1
- package/dist/admin/admin/src/components/SubNav.js.map +1 -1
- package/dist/admin/admin/src/components/SubNav.mjs +3 -1
- package/dist/admin/admin/src/components/SubNav.mjs.map +1 -1
- package/dist/admin/admin/src/components/Widgets.js +27 -9
- package/dist/admin/admin/src/components/Widgets.js.map +1 -1
- package/dist/admin/admin/src/components/Widgets.mjs +28 -10
- package/dist/admin/admin/src/components/Widgets.mjs.map +1 -1
- package/dist/admin/admin/src/features/Tracking.js.map +1 -1
- package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Home/HomePage.js +40 -33
- package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
- package/dist/admin/admin/src/pages/Home/HomePage.mjs +41 -34
- package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.js +17 -14
- package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.mjs +17 -14
- package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.js +31 -6
- package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.mjs +12 -6
- package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.js +28 -24
- package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.mjs +28 -24
- package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.js +56 -57
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.mjs +57 -58
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.mjs.map +1 -1
- package/dist/admin/admin/src/services/apiTokens.js +0 -1
- package/dist/admin/admin/src/services/apiTokens.js.map +1 -1
- package/dist/admin/admin/src/services/apiTokens.mjs +0 -1
- package/dist/admin/admin/src/services/apiTokens.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +35 -21
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +35 -21
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.js +131 -0
- package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.js.map +1 -0
- package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.mjs +129 -0
- package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.mjs.map +1 -0
- package/dist/admin/ee/admin/src/constants.js +3 -1
- package/dist/admin/ee/admin/src/constants.js.map +1 -1
- package/dist/admin/ee/admin/src/constants.mjs +3 -2
- package/dist/admin/ee/admin/src/constants.mjs.map +1 -1
- package/dist/admin/index.js +6 -2
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +2 -0
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/src/components/GuidedTour/Context.d.ts +26 -9
- package/dist/admin/src/components/GuidedTour/Steps/ApiTokensSteps.d.ts +20 -0
- package/dist/admin/src/components/GuidedTour/Steps/ContentManagerSteps.d.ts +21 -0
- package/dist/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.d.ts +30 -0
- package/dist/admin/src/components/GuidedTour/{Step.d.ts → Steps/Step.d.ts} +25 -6
- package/dist/admin/src/components/GuidedTour/Tours.d.ts +53 -14
- package/dist/admin/src/components/GuidedTour/utils/constants.d.ts +15 -0
- package/dist/admin/src/components/GuidedTour/utils/migrations.d.ts +6 -0
- package/dist/admin/src/features/Tracking.d.ts +20 -2
- package/dist/admin/src/index.d.ts +5 -0
- package/dist/admin/src/pages/Home/HomePage.d.ts +2 -2
- package/dist/ee/admin/src/components/AuditLogs/Widgets.d.ts +2 -0
- package/dist/ee/admin/src/constants.d.ts +1 -0
- package/dist/server/server/src/controllers/admin.js +2 -5
- package/dist/server/server/src/controllers/admin.js.map +1 -1
- package/dist/server/server/src/controllers/admin.mjs +2 -5
- package/dist/server/server/src/controllers/admin.mjs.map +1 -1
- package/dist/server/server/src/services/index.js +0 -2
- package/dist/server/server/src/services/index.js.map +1 -1
- package/dist/server/server/src/services/index.mjs +0 -2
- package/dist/server/server/src/services/index.mjs.map +1 -1
- package/dist/server/src/controllers/admin.d.ts +1 -1
- package/dist/server/src/controllers/admin.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +1 -1
- package/dist/server/src/index.d.ts +1 -6
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/constants.d.ts +1 -0
- package/dist/server/src/services/guided-tour.d.ts +2 -3
- package/dist/server/src/services/guided-tour.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +0 -5
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/shared/contracts/admin.d.ts +2 -2
- package/dist/shared/contracts/admin.d.ts.map +1 -1
- package/package.json +7 -7
- package/dist/admin/admin/src/components/GuidedTour/Step.js.map +0 -1
- package/dist/admin/admin/src/components/GuidedTour/Step.mjs.map +0 -1
- package/dist/server/server/src/services/guided-tour.js +0 -61
- package/dist/server/server/src/services/guided-tour.js.map +0 -1
- package/dist/server/server/src/services/guided-tour.mjs +0 -59
- 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,
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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.
|
|
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
|
|
150
|
-
|
|
151
|
-
|
|
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.
|
|
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
|
|
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,
|
|
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
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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__*/
|
|
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
|
|
129
|
-
|
|
130
|
-
|
|
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(
|
|
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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"}
|