@strapi/admin 4.15.0-alpha.0 → 4.15.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/.eslintrc.js +4 -1
- package/admin/.eslintrc.js +28 -0
- package/admin/custom.d.ts +28 -0
- package/admin/src/StrapiApp.js +27 -28
- package/admin/src/components/AuthenticatedApp.tsx +187 -0
- package/admin/src/components/ConfigurationProvider.tsx +68 -0
- package/admin/src/components/{DragLayer/DragLayer.js → DragLayer.tsx} +18 -10
- package/admin/src/components/GuidedTour/Homepage.tsx +111 -0
- package/admin/src/components/GuidedTour/Modal.tsx +303 -0
- package/admin/src/components/GuidedTour/Ornaments.tsx +74 -0
- package/admin/src/components/GuidedTour/Provider.tsx +253 -0
- package/admin/src/components/GuidedTour/{layout.js → constants.ts} +13 -3
- package/admin/src/components/LanguageProvider.tsx +130 -0
- package/admin/src/components/{LeftMenu/index.js → LeftMenu.tsx} +23 -18
- package/admin/src/components/{NpsSurvey/index.js → NpsSurvey.tsx} +68 -21
- package/admin/src/components/PluginsInitializer.tsx +124 -0
- package/admin/src/components/PrivateRoute.tsx +42 -0
- package/admin/src/components/Providers.tsx +125 -0
- package/admin/src/components/RBACProvider.tsx +124 -0
- package/admin/src/components/Theme.tsx +41 -0
- package/admin/src/components/ThemeToggleProvider.tsx +64 -0
- package/admin/src/components/{UnauthenticatedLogo/index.js → UnauthenticatedLogo.tsx} +3 -5
- package/admin/src/components/{LocalesProvider/__mocks__/useLocalesProvider.js → __mocks__/LanguageProvider.ts} +3 -1
- package/admin/src/{constants.js → constants.ts} +48 -0
- package/admin/src/content-manager/components/BlocksEditor/BlocksInput/index.js +68 -9
- package/admin/src/content-manager/components/BlocksEditor/Toolbar/index.js +433 -202
- package/admin/src/content-manager/components/BlocksEditor/hooks/useBlocksStore.js +463 -135
- package/admin/src/content-manager/components/BlocksEditor/hooks/useModifiersStore.js +23 -6
- package/admin/src/content-manager/components/BlocksEditor/index.js +97 -20
- package/admin/src/content-manager/components/BlocksEditor/plugins/index.js +4 -0
- package/admin/src/content-manager/components/BlocksEditor/plugins/withLinks.js +61 -0
- package/admin/src/content-manager/components/BlocksEditor/plugins/withStrapiSchema.js +33 -0
- package/admin/src/content-manager/components/BlocksEditor/utils/links.js +90 -0
- package/admin/src/content-manager/components/InputUID/index.js +1 -1
- package/admin/src/content-manager/hooks/useAllowedAttributes.js +9 -1
- package/admin/src/content-manager/pages/App/selectors.js +1 -1
- package/admin/src/content-manager/pages/App/useContentManagerInitData.js +3 -1
- package/admin/src/content-manager/pages/EditSettingsView/index.js +1 -0
- package/admin/src/content-manager/pages/EditSettingsView/utils/createPossibleMainFieldsForModelsAndComponents.js +1 -0
- package/admin/src/content-manager/pages/EditView/selectors.js +1 -1
- package/admin/src/content-manager/pages/EditViewLayoutManager/index.js +3 -1
- package/admin/src/content-manager/pages/ListSettingsView/constants.js +1 -0
- package/admin/src/content-manager/pages/ListView/components/Body/index.js +53 -56
- package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +5 -3
- package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +1 -1
- package/admin/src/content-manager/pages/ListView/index.js +35 -51
- package/admin/src/content-manager/pages/ListView/selectors.js +1 -1
- package/admin/src/content-manager/utils/checkIfAttributeIsDisplayable.js +1 -1
- package/admin/src/content-manager/utils/schema.js +2 -2
- package/admin/src/contexts/admin.ts +19 -0
- package/admin/src/contexts/apiTokenPermissions.tsx +64 -0
- package/admin/src/contexts/configuration.ts +25 -0
- package/admin/src/contexts/themeToggle.ts +18 -0
- package/admin/src/core/store/configure.ts +91 -0
- package/admin/src/core/store/hooks.ts +15 -0
- package/admin/src/hooks/{useConfigurations/__mocks__/index.js → __mocks__/useConfigurations.ts} +4 -2
- package/admin/src/hooks/index.js +0 -8
- package/admin/src/hooks/{useAdminRoles/index.js → useAdminRoles.ts} +26 -10
- package/admin/src/hooks/useAdminUsers.ts +64 -0
- package/admin/src/hooks/useConfiguration.ts +5 -0
- package/admin/src/hooks/{useContentTypes/useContentTypes.js → useContentTypes.ts} +39 -16
- package/admin/src/hooks/useDebounce.ts +17 -0
- package/admin/src/hooks/{useEnterprise/useEnterprise.js → useEnterprise.ts} +15 -5
- package/admin/src/hooks/useLicenseLimitNotification.ts +3 -0
- package/admin/src/hooks/useMenu.ts +153 -0
- package/admin/src/hooks/useSettingsForm/index.js +14 -2
- package/admin/src/hooks/useSettingsMenu/constants.js +39 -0
- package/admin/src/hooks/useThemeToggle.ts +9 -0
- package/admin/src/index.js +7 -6
- package/admin/src/layouts/{AppLayout/index.js → AppLayout.tsx} +7 -10
- package/admin/src/layouts/UnauthenticatedLayout.tsx +77 -0
- package/admin/src/pages/Admin/index.js +15 -8
- package/admin/src/pages/App/index.js +13 -8
- package/admin/src/pages/App/selectors.js +1 -1
- package/admin/src/pages/AuthPage/components/ForgotPassword/index.js +3 -2
- package/admin/src/pages/AuthPage/components/ForgotPasswordSuccess/index.js +3 -2
- package/admin/src/pages/AuthPage/components/Login/BaseLogin.js +1 -1
- package/admin/src/pages/AuthPage/components/Login/index.js +1 -1
- package/admin/src/pages/AuthPage/components/Oops/index.js +3 -2
- package/admin/src/pages/AuthPage/components/Register/index.js +30 -35
- package/admin/src/pages/AuthPage/components/ResetPassword/index.js +3 -2
- package/admin/src/pages/AuthPage/index.js +4 -5
- package/admin/src/pages/HomePage/index.js +6 -3
- package/admin/src/pages/{InternalErrorPage/index.js → InternalErrorPage.tsx} +10 -6
- package/admin/src/pages/MarketplacePage/components/NpmPackageCard/index.js +0 -2
- package/admin/src/pages/MarketplacePage/hooks/__mocks__/useNavigatorOnline.ts +1 -0
- package/admin/src/{hooks/useNavigatorOnLine/index.js → pages/MarketplacePage/hooks/useNavigatorOnline.ts} +4 -6
- package/admin/src/pages/MarketplacePage/index.js +3 -3
- package/admin/src/pages/{NotFoundPage/index.js → NotFoundPage.tsx} +9 -7
- package/admin/src/pages/ProfilePage/components/Preferences/index.js +23 -9
- package/admin/src/pages/ProfilePage/index.js +4 -4
- package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +20 -0
- package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +1 -1
- package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +119 -87
- package/admin/src/pages/SettingsPage/constants.js +33 -0
- package/admin/src/{hooks/useRegenerate/index.js → pages/SettingsPage/hooks/useRegenerate.ts} +13 -7
- package/admin/src/pages/SettingsPage/index.js +2 -2
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ActionBoundRoutes/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Permissions/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +2 -2
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/CustomizationInfos/index.js +2 -2
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +2 -2
- package/admin/src/pages/SettingsPage/pages/AuditLogs/SalesPage.js +50 -0
- package/admin/src/pages/SettingsPage/pages/ReviewWorkflows/SalesPage.js +53 -0
- package/admin/src/pages/SettingsPage/pages/Roles/CreatePage/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/ActionRow/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/SubActionRow/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/GlobalActions/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PermissionsDataManagerProvider/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PluginsAndSettings/SubCategory/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/hooks/usePermissionsDataManager.ts +28 -0
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js +1 -1
- package/admin/src/{hooks/useAdminRolePermissions/index.js → pages/SettingsPage/pages/Roles/hooks/useAdminRolePermissions.ts} +13 -6
- package/admin/src/pages/SettingsPage/pages/SingleSignOn/SalesPage.js +53 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +3 -5
- package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +2 -1
- package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
- package/admin/src/pages/{UseCasePage/index.js → UseCasePage.tsx} +10 -12
- package/admin/src/shared/hooks/index.js +0 -1
- package/admin/src/shared/hooks/useInjectionZone/index.js +2 -2
- package/admin/src/translations/en.json +13 -0
- package/admin/src/types/adminAPI.ts +29 -0
- package/admin/src/utils/createRoute.tsx +54 -0
- package/admin/src/utils/formatAPIErrors.ts +18 -0
- package/admin/src/utils/getFullName.ts +3 -0
- package/admin/src/utils/{uniqueAdminHash.js → hashAdminUserEmail.ts} +6 -3
- package/admin/src/utils/makeUniqueRoutes.ts +11 -0
- package/admin/tsconfig.build.json +4 -0
- package/admin/tsconfig.json +11 -0
- package/build/0cd5f8915b265d5b1856.png +0 -0
- package/build/1049.ecc10c97.chunk.js +1 -0
- package/build/1217.96155682.chunk.js +35 -0
- package/build/1227.947ceaf9.chunk.js +1 -0
- package/build/1306.2699df52.chunk.js +79 -0
- package/build/135.ad267b59.chunk.js +1 -0
- package/build/1386.eabd8a1e.chunk.js +7 -0
- package/build/1727.b49f0713.chunk.js +1 -0
- package/build/1835.eaa696ba.chunk.js +1 -0
- package/build/19eb2dfcf2603eb55733.png +0 -0
- package/build/2325.d705b39a.chunk.js +1 -0
- package/build/2379.7ce8e110.chunk.js +1 -0
- package/build/2395.acb961a8.chunk.js +26 -0
- package/build/2421.79e5b3d0.chunk.js +1 -0
- package/build/267.073a3bcb.chunk.js +1 -0
- package/build/27d16aefee06412db90a.png +0 -0
- package/build/2801.4711ea5a.chunk.js +1 -0
- package/build/2878.145ebf7c.chunk.js +1 -0
- package/build/2950.216f2e89.chunk.js +1 -0
- package/build/2953.284a63c0.chunk.js +1 -0
- package/build/3019.fde2e1be.chunk.js +181 -0
- package/build/3100.2ba4df95.chunk.js +1 -0
- package/build/311.cb0884bb.chunk.js +1 -0
- package/build/3460.8644e608.chunk.js +146 -0
- package/build/3483.db8c1520.chunk.js +1 -0
- package/build/3911.488fbde3.chunk.js +95 -0
- package/build/4174.49cedb6a.chunk.js +1 -0
- package/build/4429.7f044dc7.chunk.js +1 -0
- package/build/4555.c883d697.chunk.js +1 -0
- package/build/4663.b906cc10.chunk.js +1 -0
- package/build/4732.149f5f8f.chunk.js +1 -0
- package/build/4916.480053a6.chunk.js +1 -0
- package/build/4996.d285c30b.chunk.js +1 -0
- package/build/502.f536f78b.chunk.js +1 -0
- package/build/570.2f3b4c56.chunk.js +1 -0
- package/build/5858.493b31ec.chunk.js +1 -0
- package/build/6158.c3c13c20.chunk.js +1 -0
- package/build/6345.334e7678.chunk.js +1 -0
- package/build/6453.4160b5b7.chunk.js +1 -0
- package/build/7030.b98dcedf.chunk.js +1 -0
- package/build/70674f63fc3904c20de0.svg +7 -0
- package/build/7448.6fd14dd3.chunk.js +1 -0
- package/build/7464.579564ac.chunk.js +1 -0
- package/build/7735.9e7c9fdd.chunk.js +10 -0
- package/build/78.dcc6df5c.chunk.js +1 -0
- package/build/7811.fdbe09af.chunk.js +103 -0
- package/build/782.7243b183.chunk.js +1 -0
- package/build/7849.2a500ed8.chunk.js +1 -0
- package/build/7897.63ba0a00.chunk.js +6 -0
- package/build/7e9af4fb7e723fcebf1f.svg +48 -0
- package/build/8162.7d1100a0.chunk.js +1 -0
- package/build/8276.9abe4679.chunk.js +26 -0
- package/build/8773.ee67141c.chunk.js +48 -0
- package/build/8980.f0045cc1.chunk.js +1 -0
- package/build/9077.2cc01ac8.chunk.js +105 -0
- package/build/9153.42c1428a.chunk.js +1 -0
- package/build/918.54414509.chunk.js +1 -0
- package/build/9218.b2d367f8.chunk.js +1 -0
- package/build/9285.5f174057.chunk.js +1 -0
- package/build/9547.62987774.chunk.js +1 -0
- package/build/9754.b4e73779.chunk.js +1 -0
- package/build/9d5d788027e86620c234.svg +5 -0
- package/build/Admin-authenticatedApp.059dc48f.chunk.js +79 -0
- package/build/Admin_InternalErrorPage.06eeef20.chunk.js +1 -0
- package/build/Admin_homePage.56b9eb3f.chunk.js +81 -0
- package/build/Admin_marketplace.d693a435.chunk.js +44 -0
- package/build/Admin_pluginsPage.ae2c872a.chunk.js +6 -0
- package/build/Admin_profilePage.89099d5b.chunk.js +13 -0
- package/build/Admin_settingsPage.88c45586.chunk.js +12 -0
- package/build/Upload_ConfigureTheView.44f28145.chunk.js +1 -0
- package/build/admin-app.990e112f.chunk.js +69 -0
- package/build/admin-edit-roles-page.4e1eb4a9.chunk.js +267 -0
- package/build/admin-edit-users.5b91404e.chunk.js +10 -0
- package/build/admin-roles-list.89dd94fe.chunk.js +22 -0
- package/build/admin-users.7be4fc5f.chunk.js +11 -0
- package/build/api-tokens-create-page.571920e5.chunk.js +1 -0
- package/build/api-tokens-edit-page.cbdc81b1.chunk.js +1 -0
- package/build/api-tokens-list-page.de0c49e8.chunk.js +16 -0
- package/build/ar-json.74e40bc7.chunk.js +1 -0
- package/build/audit-logs-sales-page.2955db88.chunk.js +1 -0
- package/build/audit-logs-settings-page.b0cb5164.chunk.js +1 -0
- package/build/bb3108f7fd1e6179bde1.svg +1 -0
- package/build/bb4d0d527bdfb161bc5a.svg +1 -0
- package/build/ca-json.fc6001d3.chunk.js +1 -0
- package/build/content-manager.de7ae330.chunk.js +1241 -0
- package/build/content-type-builder-list-view.6c8d3213.chunk.js +211 -0
- package/build/content-type-builder-translation-ar-json.3e808e2f.chunk.js +1 -0
- package/build/content-type-builder-translation-cs-json.1ef9e106.chunk.js +1 -0
- package/build/content-type-builder-translation-de-json.63fcff7b.chunk.js +1 -0
- package/build/content-type-builder-translation-dk-json.fd626b67.chunk.js +1 -0
- package/build/content-type-builder-translation-en-json.74d80f18.chunk.js +1 -0
- package/build/content-type-builder-translation-es-json.a4a361a9.chunk.js +1 -0
- package/build/content-type-builder-translation-fr-json.499c3a46.chunk.js +1 -0
- package/build/content-type-builder-translation-id-json.65255f93.chunk.js +1 -0
- package/build/content-type-builder-translation-it-json.e268ab74.chunk.js +1 -0
- package/build/content-type-builder-translation-ja-json.9be0d5b2.chunk.js +1 -0
- package/build/content-type-builder-translation-ko-json.04cb309d.chunk.js +1 -0
- package/build/content-type-builder-translation-ms-json.f6b743b9.chunk.js +1 -0
- package/build/content-type-builder-translation-nl-json.997fe8cc.chunk.js +1 -0
- package/build/content-type-builder-translation-pl-json.634f638b.chunk.js +1 -0
- package/build/content-type-builder-translation-pt-BR-json.6a95dc71.chunk.js +1 -0
- package/build/content-type-builder-translation-pt-json.ddb44f8c.chunk.js +1 -0
- package/build/content-type-builder-translation-ru-json.3af65503.chunk.js +1 -0
- package/build/content-type-builder-translation-sk-json.c6078082.chunk.js +1 -0
- package/build/content-type-builder-translation-sv-json.a6df2462.chunk.js +1 -0
- package/build/content-type-builder-translation-th-json.122277cc.chunk.js +1 -0
- package/build/content-type-builder-translation-tr-json.41f44f77.chunk.js +1 -0
- package/build/content-type-builder-translation-uk-json.e1315acd.chunk.js +1 -0
- package/build/content-type-builder-translation-zh-Hans-json.6ff57db6.chunk.js +1 -0
- package/build/content-type-builder-translation-zh-json.3532b962.chunk.js +1 -0
- package/build/content-type-builder.0bc97051.chunk.js +136 -0
- package/build/cs-json.4b44411c.chunk.js +1 -0
- package/build/de-json.e72545cf.chunk.js +1 -0
- package/build/dk-json.e77140ef.chunk.js +1 -0
- package/build/email-settings-page.07712efc.chunk.js +11 -0
- package/build/en-json.5b907f67.chunk.js +1 -0
- package/build/es-json.b1f2284b.chunk.js +1 -0
- package/build/eu-json.63d0a898.chunk.js +1 -0
- package/build/fr-json.33c6428b.chunk.js +1 -0
- package/build/gu-json.7efe8cc2.chunk.js +1 -0
- package/build/he-json.3cf0b48a.chunk.js +1 -0
- package/build/hi-json.0d633692.chunk.js +1 -0
- package/build/highlight.js.28a1547e.chunk.js +85 -0
- package/build/hu-json.c74b6a1e.chunk.js +1 -0
- package/build/i18n-settings-page.5c34f012.chunk.js +9 -0
- package/build/i18n-translation-de-json.362384a6.chunk.js +1 -0
- package/build/i18n-translation-dk-json.89401417.chunk.js +1 -0
- package/build/i18n-translation-en-json.1ec7becf.chunk.js +1 -0
- package/build/i18n-translation-es-json.87b494d1.chunk.js +1 -0
- package/build/i18n-translation-fr-json.57ddc77e.chunk.js +1 -0
- package/build/i18n-translation-ko-json.ef4f9471.chunk.js +1 -0
- package/build/i18n-translation-pl-json.dfac513d.chunk.js +1 -0
- package/build/i18n-translation-ru-json.a3dbc125.chunk.js +1 -0
- package/build/i18n-translation-tr-json.3bfc812f.chunk.js +1 -0
- package/build/i18n-translation-zh-Hans-json.757ce62d.chunk.js +1 -0
- package/build/i18n-translation-zh-json.bef2dc07.chunk.js +1 -0
- package/build/id-json.41e07c46.chunk.js +1 -0
- package/build/index.html +1 -0
- package/build/it-json.bfe27ed8.chunk.js +1 -0
- package/build/ja-json.e1959a1c.chunk.js +1 -0
- package/build/ko-json.ce5d6d94.chunk.js +1 -0
- package/build/main.f84563f1.js +2665 -0
- package/build/ml-json.940d7ace.chunk.js +1 -0
- package/build/ms-json.0eddffd9.chunk.js +1 -0
- package/build/nl-json.fe38f0fb.chunk.js +1 -0
- package/build/no-json.19a2dbfa.chunk.js +1 -0
- package/build/pl-json.d55e8e78.chunk.js +1 -0
- package/build/pt-BR-json.ae0a0d2e.chunk.js +1 -0
- package/build/pt-json.ee554a41.chunk.js +1 -0
- package/build/review-workflows-sales-page.f46a8f00.chunk.js +1 -0
- package/build/review-workflows-settings-create-view.d0544fb0.chunk.js +1 -0
- package/build/review-workflows-settings-edit-view.aabf49ef.chunk.js +1 -0
- package/build/review-workflows-settings-list-view.8b0525ab.chunk.js +56 -0
- package/build/ru-json.1c976644.chunk.js +1 -0
- package/build/runtime~main.270fd45f.js +2 -0
- package/build/sa-json.2c03ef4e.chunk.js +1 -0
- package/build/sk-json.b41847e8.chunk.js +1 -0
- package/build/sso-sales-page.ef22e469.chunk.js +1 -0
- package/build/sso-settings-page.21e16ae4.chunk.js +1 -0
- package/build/sv-json.568cb7ae.chunk.js +1 -0
- package/build/th-json.5f659396.chunk.js +1 -0
- package/build/tr-json.c9f22432.chunk.js +1 -0
- package/build/transfer-tokens-create-page.3366204d.chunk.js +1 -0
- package/build/transfer-tokens-edit-page.15cf0f73.chunk.js +1 -0
- package/build/transfer-tokens-list-page.0bc0e682.chunk.js +16 -0
- package/build/uk-json.b7e38370.chunk.js +1 -0
- package/build/upload-settings.1319dca0.chunk.js +14 -0
- package/build/upload-translation-ca-json.57954414.chunk.js +1 -0
- package/build/upload-translation-de-json.420c943b.chunk.js +1 -0
- package/build/upload-translation-dk-json.bbb2fa05.chunk.js +1 -0
- package/build/upload-translation-en-json.8b7573ce.chunk.js +1 -0
- package/build/upload-translation-es-json.ba2eb03a.chunk.js +1 -0
- package/build/upload-translation-fr-json.baab9911.chunk.js +1 -0
- package/build/upload-translation-he-json.0a830937.chunk.js +1 -0
- package/build/upload-translation-it-json.e87d7966.chunk.js +1 -0
- package/build/upload-translation-ja-json.44b88e7a.chunk.js +1 -0
- package/build/upload-translation-ko-json.a52eab64.chunk.js +1 -0
- package/build/upload-translation-ms-json.74f6d746.chunk.js +1 -0
- package/build/upload-translation-pl-json.426f31c9.chunk.js +1 -0
- package/build/upload-translation-pt-BR-json.d1704f0b.chunk.js +1 -0
- package/build/upload-translation-pt-json.6b937fdf.chunk.js +1 -0
- package/build/upload-translation-ru-json.675f6b93.chunk.js +1 -0
- package/build/upload-translation-sk-json.483a18f6.chunk.js +1 -0
- package/build/upload-translation-th-json.98d35574.chunk.js +1 -0
- package/build/upload-translation-tr-json.74117e5c.chunk.js +1 -0
- package/build/upload-translation-uk-json.9950466a.chunk.js +1 -0
- package/build/upload-translation-zh-Hans-json.db163b6b.chunk.js +1 -0
- package/build/upload-translation-zh-json.e1dd6eb2.chunk.js +1 -0
- package/build/upload.1ced11be.chunk.js +58 -0
- package/build/users-advanced-settings-page.8e657084.chunk.js +9 -0
- package/build/users-email-settings-page.e57745e5.chunk.js +9 -0
- package/build/users-permissions-translation-ar-json.7d87d54d.chunk.js +1 -0
- package/build/users-permissions-translation-cs-json.7e23424a.chunk.js +1 -0
- package/build/users-permissions-translation-de-json.a6fb670f.chunk.js +1 -0
- package/build/users-permissions-translation-dk-json.60e50f48.chunk.js +1 -0
- package/build/users-permissions-translation-en-json.4b302272.chunk.js +1 -0
- package/build/users-permissions-translation-es-json.35007573.chunk.js +1 -0
- package/build/users-permissions-translation-fr-json.7e55bbbb.chunk.js +1 -0
- package/build/users-permissions-translation-id-json.a5a0fb59.chunk.js +1 -0
- package/build/users-permissions-translation-it-json.0705465d.chunk.js +1 -0
- package/build/users-permissions-translation-ja-json.891fe76e.chunk.js +1 -0
- package/build/users-permissions-translation-ko-json.357d7a33.chunk.js +1 -0
- package/build/users-permissions-translation-ms-json.c83f87c4.chunk.js +1 -0
- package/build/users-permissions-translation-nl-json.c9f92a3c.chunk.js +1 -0
- package/build/users-permissions-translation-pl-json.0a7287d1.chunk.js +1 -0
- package/build/users-permissions-translation-pt-BR-json.1b6d2920.chunk.js +1 -0
- package/build/users-permissions-translation-pt-json.a7eda429.chunk.js +1 -0
- package/build/users-permissions-translation-ru-json.8e883c67.chunk.js +1 -0
- package/build/users-permissions-translation-sk-json.7f37180f.chunk.js +1 -0
- package/build/users-permissions-translation-sv-json.17187818.chunk.js +1 -0
- package/build/users-permissions-translation-th-json.1e9c0247.chunk.js +1 -0
- package/build/users-permissions-translation-tr-json.2bd7ff98.chunk.js +1 -0
- package/build/users-permissions-translation-uk-json.6a0a1572.chunk.js +1 -0
- package/build/users-permissions-translation-vi-json.6722a8a2.chunk.js +1 -0
- package/build/users-permissions-translation-zh-Hans-json.8d82c809.chunk.js +1 -0
- package/build/users-permissions-translation-zh-json.7978eaa6.chunk.js +1 -0
- package/build/users-providers-settings-page.55796d13.chunk.js +14 -0
- package/build/users-roles-settings-page.57079245.chunk.js +55 -0
- package/build/vi-json.ee4c5537.chunk.js +1 -0
- package/build/webhook-edit-page.3a28b2e7.chunk.js +33 -0
- package/build/webhook-list-page.ee80767b.chunk.js +63 -0
- package/build/zh-Hans-json.97efd015.chunk.js +1 -0
- package/build/zh-json.bfc2e036.chunk.js +1 -0
- package/ee/admin/hooks/{useLicenseLimitNotification.js → useLicenseLimitNotification.ts} +4 -4
- package/ee/admin/pages/AuthPage/components/Login/index.js +1 -1
- package/ee/admin/pages/AuthPage/components/Providers/index.js +3 -2
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/selectors.js +1 -1
- package/ee/admin/pages/SettingsPage/pages/Users/ListPage/index.js +1 -3
- package/ee/server/bootstrap.js +1 -1
- package/ee/server/controllers/admin.js +1 -1
- package/ee/server/controllers/user.js +1 -1
- package/ee/server/destroy.js +1 -1
- package/ee/server/register.js +1 -1
- package/ee/server/routes/utils.js +1 -1
- package/ee/server/services/audit-logs.js +1 -1
- package/ee/server/services/passport/sso.js +1 -1
- package/ee/server/services/passport.js +1 -1
- package/ee/server/services/seat-enforcement.js +1 -1
- package/ee/server/utils/sso-lock.js +1 -1
- package/ee/server/validation/role.js +1 -1
- package/ee/server/validation/user.js +1 -1
- package/jest.config.front.js +4 -0
- package/package.json +28 -22
- package/scripts/build.js +6 -2
- package/server/controllers/admin.js +4 -3
- package/shared/entities.ts +33 -0
- package/shared/permissions.ts +52 -0
- package/shared/schema.ts +9 -0
- package/webpack.config.js +1 -0
- package/admin/src/components/AuthenticatedApp/index.js +0 -120
- package/admin/src/components/AuthenticatedApp/utils/api.js +0 -85
- package/admin/src/components/AuthenticatedApp/utils/checkLatestStrapiVersion.js +0 -11
- package/admin/src/components/ConfigurationsProvider/index.js +0 -66
- package/admin/src/components/ConfigurationsProvider/reducer.js +0 -29
- package/admin/src/components/DragLayer/index.js +0 -1
- package/admin/src/components/GlobalStyle/index.js +0 -9
- package/admin/src/components/GuidedTour/Homepage/components/Step.js +0 -61
- package/admin/src/components/GuidedTour/Homepage/components/Stepper.js +0 -61
- package/admin/src/components/GuidedTour/Homepage/index.js +0 -71
- package/admin/src/components/GuidedTour/Modal/components/Content.js +0 -66
- package/admin/src/components/GuidedTour/Modal/components/Modal.js +0 -72
- package/admin/src/components/GuidedTour/Modal/components/StepNumberWithPadding.js +0 -26
- package/admin/src/components/GuidedTour/Modal/components/Stepper.js +0 -118
- package/admin/src/components/GuidedTour/Modal/index.js +0 -94
- package/admin/src/components/GuidedTour/Modal/reducer.js +0 -29
- package/admin/src/components/GuidedTour/Stepper/StepLine.js +0 -29
- package/admin/src/components/GuidedTour/Stepper/StepNumber.js +0 -71
- package/admin/src/components/GuidedTour/constants.js +0 -3
- package/admin/src/components/GuidedTour/index.js +0 -102
- package/admin/src/components/GuidedTour/init.js +0 -37
- package/admin/src/components/GuidedTour/reducer.js +0 -50
- package/admin/src/components/GuidedTour/utils/arePreviousSectionsDone.js +0 -13
- package/admin/src/components/GuidedTour/utils/arePreviousStepsDone.js +0 -12
- package/admin/src/components/GuidedTour/utils/isGuidedTourCompleted.js +0 -6
- package/admin/src/components/GuidedTour/utils/persistStateToLocaleStorage.js +0 -34
- package/admin/src/components/LanguageProvider/index.js +0 -54
- package/admin/src/components/LanguageProvider/init.js +0 -13
- package/admin/src/components/LanguageProvider/reducer.js +0 -30
- package/admin/src/components/LanguageProvider/utils/localStorageKey.js +0 -3
- package/admin/src/components/LocalesProvider/context.js +0 -5
- package/admin/src/components/LocalesProvider/index.js +0 -21
- package/admin/src/components/LocalesProvider/useLocalesProvider.js +0 -11
- package/admin/src/components/NpsSurvey/hooks/useNpsSurveySettings.js +0 -17
- package/admin/src/components/PluginsInitializer/index.js +0 -68
- package/admin/src/components/PluginsInitializer/init.js +0 -11
- package/admin/src/components/PluginsInitializer/reducer.js +0 -22
- package/admin/src/components/PrivateRoute/index.js +0 -46
- package/admin/src/components/Providers/index.js +0 -156
- package/admin/src/components/RBACProvider/actions.js +0 -10
- package/admin/src/components/RBACProvider/constants.js +0 -2
- package/admin/src/components/RBACProvider/index.js +0 -39
- package/admin/src/components/RBACProvider/reducer.js +0 -51
- package/admin/src/components/Theme/index.js +0 -26
- package/admin/src/components/ThemeToggleProvider/index.js +0 -79
- package/admin/src/contexts/Admin/index.js +0 -5
- package/admin/src/contexts/ApiTokenPermissions/index.js +0 -25
- package/admin/src/contexts/Configurations/index.js +0 -5
- package/admin/src/contexts/MarketPlace/index.js +0 -18
- package/admin/src/contexts/PermisssionsDataManagerContext/index.js +0 -5
- package/admin/src/contexts/ThemeToggle/index.js +0 -5
- package/admin/src/contexts/index.js +0 -4
- package/admin/src/core/store/configureStore.js +0 -47
- package/admin/src/exposedHooks.js +0 -27
- package/admin/src/hooks/useAdminRoles/__mocks__/index.js +0 -5
- package/admin/src/hooks/useAdminUsers/index.js +0 -1
- package/admin/src/hooks/useAdminUsers/useAdminUsers.js +0 -47
- package/admin/src/hooks/useConfigurations/index.js +0 -11
- package/admin/src/hooks/useContentTypes/index.js +0 -1
- package/admin/src/hooks/useDebounce/index.js +0 -19
- package/admin/src/hooks/useEnterprise/index.js +0 -1
- package/admin/src/hooks/useLicenseLimitNotification/index.js +0 -5
- package/admin/src/hooks/useMenu/index.js +0 -86
- package/admin/src/hooks/useMenu/utils/checkPermissions.js +0 -13
- package/admin/src/hooks/useMenu/utils/getGeneralLinks.js +0 -31
- package/admin/src/hooks/useMenu/utils/getPluginSectionLinks.js +0 -17
- package/admin/src/hooks/usePermissionsDataManager/index.js +0 -7
- package/admin/src/hooks/useReleaseNotification/index.js +0 -31
- package/admin/src/hooks/useReleaseNotification/utils/api.js +0 -20
- package/admin/src/hooks/useReleaseNotification/utils/checkLatestStrapiVersion.js +0 -11
- package/admin/src/hooks/useThemeToggle/index.js +0 -11
- package/admin/src/injectionZones.js +0 -25
- package/admin/src/layouts/UnauthenticatedLayout/LocaleToggle/index.js +0 -29
- package/admin/src/layouts/UnauthenticatedLayout/index.js +0 -55
- package/admin/src/reducers.js +0 -23
- package/admin/src/shared/hooks/useAdminProvider/index.js +0 -11
- package/admin/src/tsconfig.json +0 -10
- package/admin/src/utils/checkFormValidity.js +0 -15
- package/admin/src/utils/createRoute.js +0 -47
- package/admin/src/utils/formatAPIErrors.js +0 -17
- package/admin/src/utils/getAttributesToDisplay.js +0 -19
- package/admin/src/utils/getExistingActions.js +0 -32
- package/admin/src/utils/getFullName.js +0 -9
- package/admin/src/utils/index.js +0 -9
- package/admin/src/utils/makeUniqueRoutes.js +0 -6
- package/admin/src/utils/sortLinks.js +0 -5
- /package/admin/src/hooks/{useAdminUsers/__mocks__/index.js → __mocks__/useAdminUsers.ts} +0 -0
- /package/admin/src/hooks/{useContentTypes/__mocks__/index.js → __mocks__/useContentTypes.ts} +0 -0
- /package/admin/src/{hooks/useAdminRolePermissions/__mocks__/index.js → pages/SettingsPage/pages/Roles/hooks/__mocks__/useAdminRolePermissions.ts} +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* LanguageProvider
|
|
4
|
+
*
|
|
5
|
+
* this component connects the redux state language locale to the
|
|
6
|
+
* IntlProvider component and i18n messages (loaded from `app/translations`)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as React from 'react';
|
|
10
|
+
|
|
11
|
+
import defaultsDeep from 'lodash/defaultsDeep';
|
|
12
|
+
import { IntlProvider } from 'react-intl';
|
|
13
|
+
|
|
14
|
+
/* -------------------------------------------------------------------------------------------------
|
|
15
|
+
* LocalesContext
|
|
16
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
17
|
+
|
|
18
|
+
interface LocalesContextValue {
|
|
19
|
+
changeLocale: (locale: keyof State['localeNames']) => void;
|
|
20
|
+
localeNames: Record<string, string>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const LocalesContext = React.createContext<LocalesContextValue>({
|
|
24
|
+
changeLocale: () => {
|
|
25
|
+
throw new Error('LocalesContext: changeLocale() is not implemented');
|
|
26
|
+
},
|
|
27
|
+
localeNames: {},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const useLocales = () => React.useContext(LocalesContext);
|
|
31
|
+
|
|
32
|
+
/* -------------------------------------------------------------------------------------------------
|
|
33
|
+
* LanguageProvider
|
|
34
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
35
|
+
|
|
36
|
+
const LANGUAGE_LOCAL_STORAGE_KEY = 'strapi-admin-language';
|
|
37
|
+
|
|
38
|
+
interface LanguageProviderProps {
|
|
39
|
+
children: React.ReactNode;
|
|
40
|
+
localeNames: Record<string, string>;
|
|
41
|
+
messages: Record<string, Record<string, string>>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const LanguageProvider = ({ children, localeNames, messages }: LanguageProviderProps) => {
|
|
45
|
+
const [{ locale }, dispatch] = React.useReducer<React.Reducer<State, Action>, State>(
|
|
46
|
+
reducer,
|
|
47
|
+
initialState,
|
|
48
|
+
() => {
|
|
49
|
+
const languageFromLocaleStorage = window.localStorage.getItem(LANGUAGE_LOCAL_STORAGE_KEY);
|
|
50
|
+
if (languageFromLocaleStorage && localeNames[languageFromLocaleStorage]) {
|
|
51
|
+
return {
|
|
52
|
+
locale: languageFromLocaleStorage,
|
|
53
|
+
localeNames,
|
|
54
|
+
};
|
|
55
|
+
} else {
|
|
56
|
+
return {
|
|
57
|
+
locale: 'en',
|
|
58
|
+
localeNames,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
React.useEffect(() => {
|
|
65
|
+
// Set user language in local storage.
|
|
66
|
+
window.localStorage.setItem(LANGUAGE_LOCAL_STORAGE_KEY, locale);
|
|
67
|
+
document.documentElement.setAttribute('lang', locale);
|
|
68
|
+
}, [locale]);
|
|
69
|
+
|
|
70
|
+
const changeLocale = React.useCallback((locale: keyof State['localeNames']) => {
|
|
71
|
+
dispatch({
|
|
72
|
+
type: 'CHANGE_LOCALE',
|
|
73
|
+
locale,
|
|
74
|
+
});
|
|
75
|
+
}, []);
|
|
76
|
+
|
|
77
|
+
const appMessages = defaultsDeep(messages[locale], messages.en);
|
|
78
|
+
|
|
79
|
+
const contextValue = React.useMemo(
|
|
80
|
+
() => ({ changeLocale, localeNames }),
|
|
81
|
+
[changeLocale, localeNames]
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<IntlProvider locale={locale} defaultLocale="en" messages={appMessages} textComponent="span">
|
|
86
|
+
<LocalesContext.Provider value={contextValue}>{children}</LocalesContext.Provider>
|
|
87
|
+
</IntlProvider>
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/* -------------------------------------------------------------------------------------------------
|
|
92
|
+
* Reducer
|
|
93
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
94
|
+
|
|
95
|
+
interface State {
|
|
96
|
+
localeNames: Record<string, string>;
|
|
97
|
+
locale: keyof State['localeNames'];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const initialState: State = {
|
|
101
|
+
localeNames: { en: 'English' },
|
|
102
|
+
locale: 'en',
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
interface ChangeLocaleAction {
|
|
106
|
+
type: 'CHANGE_LOCALE';
|
|
107
|
+
locale: keyof State['localeNames'];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
type Action = ChangeLocaleAction;
|
|
111
|
+
|
|
112
|
+
const reducer = (state = initialState, action: Action) => {
|
|
113
|
+
switch (action.type) {
|
|
114
|
+
case 'CHANGE_LOCALE': {
|
|
115
|
+
const { locale } = action;
|
|
116
|
+
|
|
117
|
+
if (!state.localeNames[locale]) {
|
|
118
|
+
return state;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return { ...state, locale };
|
|
122
|
+
}
|
|
123
|
+
default: {
|
|
124
|
+
return state;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export { LanguageProvider, useLocales, LANGUAGE_LOCAL_STORAGE_KEY };
|
|
130
|
+
export type { LanguageProviderProps, LocalesContextValue };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
|
|
3
3
|
import { Box, Divider, Flex, FocusTrap, Typography } from '@strapi/design-system';
|
|
4
4
|
import {
|
|
@@ -19,12 +19,12 @@ import {
|
|
|
19
19
|
useTracking,
|
|
20
20
|
} from '@strapi/helper-plugin';
|
|
21
21
|
import { Exit, Write } from '@strapi/icons';
|
|
22
|
-
import PropTypes from 'prop-types';
|
|
23
22
|
import { useIntl } from 'react-intl';
|
|
24
23
|
import { NavLink as RouterNavLink, useHistory, useLocation } from 'react-router-dom';
|
|
25
24
|
import styled from 'styled-components';
|
|
26
25
|
|
|
27
|
-
import {
|
|
26
|
+
import { useConfiguration } from '../hooks/useConfiguration';
|
|
27
|
+
import { Menu } from '../hooks/useMenu';
|
|
28
28
|
|
|
29
29
|
const LinkUserWrapper = styled(Box)`
|
|
30
30
|
width: ${150 / 16}rem;
|
|
@@ -33,7 +33,7 @@ const LinkUserWrapper = styled(Box)`
|
|
|
33
33
|
left: ${({ theme }) => theme.spaces[5]};
|
|
34
34
|
`;
|
|
35
35
|
|
|
36
|
-
const LinkUser = styled(RouterNavLink)
|
|
36
|
+
const LinkUser = styled(RouterNavLink)<{ logout?: boolean }>`
|
|
37
37
|
display: flex;
|
|
38
38
|
justify-content: space-between;
|
|
39
39
|
align-items: center;
|
|
@@ -54,12 +54,14 @@ const LinkUser = styled(RouterNavLink)`
|
|
|
54
54
|
}
|
|
55
55
|
`;
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
interface LeftMenuProps extends Pick<Menu, 'generalSectionLinks' | 'pluginsSectionLinks'> {}
|
|
58
|
+
|
|
59
|
+
const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }: LeftMenuProps) => {
|
|
60
|
+
const navUserRef = React.useRef<HTMLDivElement>(null!);
|
|
61
|
+
const [userLinksVisible, setUserLinksVisible] = React.useState(false);
|
|
60
62
|
const {
|
|
61
63
|
logos: { menu },
|
|
62
|
-
} =
|
|
64
|
+
} = useConfiguration();
|
|
63
65
|
const [condensed, setCondensed] = usePersistentState('navbar-condensed', false);
|
|
64
66
|
const { userDisplayName } = useAppInfo();
|
|
65
67
|
const { formatMessage } = useIntl();
|
|
@@ -83,16 +85,19 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
|
|
|
83
85
|
history.push('/auth/login');
|
|
84
86
|
};
|
|
85
87
|
|
|
86
|
-
const handleBlur = (e) => {
|
|
88
|
+
const handleBlur: React.FocusEventHandler = (e) => {
|
|
87
89
|
if (
|
|
88
90
|
!e.currentTarget.contains(e.relatedTarget) &&
|
|
91
|
+
/**
|
|
92
|
+
* TODO: can we replace this by just using the navUserRef?
|
|
93
|
+
*/
|
|
89
94
|
e.relatedTarget?.parentElement?.id !== 'main-nav-user-button'
|
|
90
95
|
) {
|
|
91
96
|
setUserLinksVisible(false);
|
|
92
97
|
}
|
|
93
98
|
};
|
|
94
99
|
|
|
95
|
-
const handleClickOnLink = (destination
|
|
100
|
+
const handleClickOnLink = (destination: string) => {
|
|
96
101
|
trackUsage('willNavigate', { from: pathname, to: destination });
|
|
97
102
|
};
|
|
98
103
|
|
|
@@ -126,6 +131,7 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
|
|
|
126
131
|
<NavSections>
|
|
127
132
|
<NavLink
|
|
128
133
|
as={RouterNavLink}
|
|
134
|
+
// @ts-expect-error the props from the passed as prop are not inferred // joined together
|
|
129
135
|
to="/content-manager"
|
|
130
136
|
icon={<Write />}
|
|
131
137
|
onClick={() => handleClickOnLink('/content-manager')}
|
|
@@ -146,6 +152,7 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
|
|
|
146
152
|
return (
|
|
147
153
|
<NavLink
|
|
148
154
|
as={RouterNavLink}
|
|
155
|
+
// @ts-expect-error the props from the passed as prop are not inferred // joined together
|
|
149
156
|
to={link.to}
|
|
150
157
|
key={link.to}
|
|
151
158
|
icon={<Icon />}
|
|
@@ -172,8 +179,11 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
|
|
|
172
179
|
<NavLink
|
|
173
180
|
as={RouterNavLink}
|
|
174
181
|
badgeContent={
|
|
175
|
-
|
|
182
|
+
link.notificationsCount && link.notificationsCount > 0
|
|
183
|
+
? link.notificationsCount.toString()
|
|
184
|
+
: undefined
|
|
176
185
|
}
|
|
186
|
+
// @ts-expect-error the props from the passed as prop are not inferred // joined together
|
|
177
187
|
to={link.to}
|
|
178
188
|
key={link.to}
|
|
179
189
|
icon={<LinkIcon />}
|
|
@@ -190,7 +200,7 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
|
|
|
190
200
|
<NavFooter>
|
|
191
201
|
<NavUser
|
|
192
202
|
id="main-nav-user-button"
|
|
193
|
-
ref={
|
|
203
|
+
ref={navUserRef}
|
|
194
204
|
onClick={handleToggleUserLinks}
|
|
195
205
|
initials={initials}
|
|
196
206
|
>
|
|
@@ -244,9 +254,4 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
|
|
|
244
254
|
);
|
|
245
255
|
};
|
|
246
256
|
|
|
247
|
-
LeftMenu
|
|
248
|
-
generalSectionLinks: PropTypes.array.isRequired,
|
|
249
|
-
pluginsSectionLinks: PropTypes.array.isRequired,
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
export default LeftMenu;
|
|
257
|
+
export { LeftMenu };
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
FieldInput,
|
|
14
14
|
VisuallyHidden,
|
|
15
15
|
} from '@strapi/design-system';
|
|
16
|
-
import { auth, useNotification, useAppInfo } from '@strapi/helper-plugin';
|
|
16
|
+
import { auth, useNotification, useAppInfo, usePersistentState } from '@strapi/helper-plugin';
|
|
17
17
|
import { Cross } from '@strapi/icons';
|
|
18
18
|
import { Formik, Form } from 'formik';
|
|
19
19
|
import { useIntl } from 'react-intl';
|
|
@@ -21,8 +21,6 @@ import { useMutation } from 'react-query';
|
|
|
21
21
|
import styled, { useTheme } from 'styled-components';
|
|
22
22
|
import * as yup from 'yup';
|
|
23
23
|
|
|
24
|
-
import { useNpsSurveySettings } from './hooks/useNpsSurveySettings';
|
|
25
|
-
|
|
26
24
|
const FieldWrapper = styled(Field)`
|
|
27
25
|
height: ${32 / 16}rem;
|
|
28
26
|
width: ${32 / 16}rem;
|
|
@@ -67,21 +65,27 @@ const delays = {
|
|
|
67
65
|
|
|
68
66
|
const ratingArray = [...Array(11).keys()];
|
|
69
67
|
|
|
70
|
-
const checkIfShouldShowSurvey = (settings) => {
|
|
68
|
+
const checkIfShouldShowSurvey = (settings: NpsSurveySettings) => {
|
|
71
69
|
const { enabled, lastResponseDate, firstDismissalDate, lastDismissalDate } = settings;
|
|
72
70
|
|
|
73
71
|
// This function goes through all the cases where we'd want to not show the survey:
|
|
74
|
-
// 1. If the survey is disabled, abort mission, don't bother checking the other settings.
|
|
75
|
-
// 2. If the
|
|
76
|
-
// 3. If the user has
|
|
77
|
-
// 4. If the user has
|
|
72
|
+
// 1. If the survey is disabled by strapi, abort mission, don't bother checking the other settings.
|
|
73
|
+
// 2. If the survey is disabled by user, abort mission, don't bother checking the other settings.
|
|
74
|
+
// 3. If the user has already responded to the survey, check if enough time has passed since the last response.
|
|
75
|
+
// 4. If the user has dismissed the survey twice or more before, check if enough time has passed since the last dismissal.
|
|
76
|
+
// 5. If the user has only dismissed the survey once before, check if enough time has passed since the first dismissal.
|
|
78
77
|
// If none of these cases check out, then we show the survey.
|
|
79
78
|
// Note that submitting a response resets the dismissal counts.
|
|
80
|
-
// Checks
|
|
79
|
+
// Checks 4 and 5 should not be reversed, since the first dismissal will also exist if the user has dismissed the survey twice or more before.
|
|
81
80
|
|
|
82
81
|
// For users who had created an account before the NPS feature was introduced,
|
|
83
82
|
// we assume that they would have enabled the NPS feature if they had the chance.
|
|
84
83
|
|
|
84
|
+
// Global strapi disable for NSP.
|
|
85
|
+
if (window.strapi.flags.nps === false) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
85
89
|
// User chose not to enable the NPS feature when signing up
|
|
86
90
|
if (enabled === false) {
|
|
87
91
|
return false;
|
|
@@ -132,7 +136,16 @@ const NpsSurvey = () => {
|
|
|
132
136
|
const toggleNotification = useNotification();
|
|
133
137
|
const { currentEnvironment, strapiVersion } = useAppInfo();
|
|
134
138
|
|
|
135
|
-
|
|
139
|
+
interface NpsSurveyMutationBody {
|
|
140
|
+
email: string;
|
|
141
|
+
rating: number | null;
|
|
142
|
+
comment: string;
|
|
143
|
+
environment?: string;
|
|
144
|
+
version?: string;
|
|
145
|
+
license: 'Enterprise' | 'Community';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const { mutate, isLoading } = useMutation<unknown, unknown, NpsSurveyMutationBody>(
|
|
136
149
|
async (form) => {
|
|
137
150
|
const res = await fetch('https://analytics.strapi.io/submit-nps', {
|
|
138
151
|
method: 'POST',
|
|
@@ -152,7 +165,7 @@ const NpsSurvey = () => {
|
|
|
152
165
|
onSuccess() {
|
|
153
166
|
setNpsSurveySettings((settings) => ({
|
|
154
167
|
...settings,
|
|
155
|
-
lastResponseDate: new Date(),
|
|
168
|
+
lastResponseDate: new Date().toString(),
|
|
156
169
|
firstDismissalDate: null,
|
|
157
170
|
lastDismissalDate: null,
|
|
158
171
|
}));
|
|
@@ -165,7 +178,7 @@ const NpsSurvey = () => {
|
|
|
165
178
|
onError() {
|
|
166
179
|
toggleNotification({
|
|
167
180
|
type: 'warning',
|
|
168
|
-
message: formatMessage({ id: 'notification.error' }),
|
|
181
|
+
message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),
|
|
169
182
|
});
|
|
170
183
|
},
|
|
171
184
|
}
|
|
@@ -197,12 +210,18 @@ const NpsSurvey = () => {
|
|
|
197
210
|
return null;
|
|
198
211
|
}
|
|
199
212
|
|
|
200
|
-
const handleSubmitResponse = ({
|
|
201
|
-
|
|
213
|
+
const handleSubmitResponse = ({
|
|
214
|
+
npsSurveyRating,
|
|
215
|
+
npsSurveyFeedback,
|
|
216
|
+
}: {
|
|
217
|
+
npsSurveyRating: NpsSurveyMutationBody['rating'];
|
|
218
|
+
npsSurveyFeedback: NpsSurveyMutationBody['comment'];
|
|
219
|
+
}) => {
|
|
220
|
+
const userInfo = auth.getUserInfo();
|
|
202
221
|
mutate({
|
|
203
|
-
email,
|
|
204
|
-
rating,
|
|
205
|
-
comment,
|
|
222
|
+
email: typeof userInfo === 'object' && userInfo !== null ? userInfo.email : '',
|
|
223
|
+
rating: npsSurveyRating,
|
|
224
|
+
comment: npsSurveyFeedback,
|
|
206
225
|
environment: currentEnvironment,
|
|
207
226
|
version: strapiVersion,
|
|
208
227
|
license: window.strapi.projectType,
|
|
@@ -218,10 +237,10 @@ const NpsSurvey = () => {
|
|
|
218
237
|
|
|
219
238
|
if (settings.firstDismissalDate) {
|
|
220
239
|
// If the user dismisses the survey for the second time
|
|
221
|
-
nextSettings.lastDismissalDate = new Date();
|
|
240
|
+
nextSettings.lastDismissalDate = new Date().toString();
|
|
222
241
|
} else {
|
|
223
242
|
// If the user dismisses the survey for the first time
|
|
224
|
-
nextSettings.firstDismissalDate = new Date();
|
|
243
|
+
nextSettings.firstDismissalDate = new Date().toString();
|
|
225
244
|
}
|
|
226
245
|
|
|
227
246
|
return nextSettings;
|
|
@@ -295,7 +314,7 @@ const NpsSurvey = () => {
|
|
|
295
314
|
return (
|
|
296
315
|
<FieldWrapper
|
|
297
316
|
key={number}
|
|
298
|
-
className={values.npsSurveyRating === number ? 'selected' :
|
|
317
|
+
className={values.npsSurveyRating === number ? 'selected' : undefined} // "selected" class added when child radio button is checked
|
|
299
318
|
hasRadius
|
|
300
319
|
background="primary100"
|
|
301
320
|
borderColor="primary200"
|
|
@@ -365,4 +384,32 @@ const NpsSurvey = () => {
|
|
|
365
384
|
);
|
|
366
385
|
};
|
|
367
386
|
|
|
368
|
-
|
|
387
|
+
interface NpsSurveySettings {
|
|
388
|
+
enabled: boolean;
|
|
389
|
+
lastResponseDate: string | null;
|
|
390
|
+
firstDismissalDate: string | null;
|
|
391
|
+
lastDismissalDate: string | null;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* We exported to make it available during admin user registration.
|
|
396
|
+
* Because we only enable the NPS for users who subscribe to the newsletter when signing up
|
|
397
|
+
*/
|
|
398
|
+
function useNpsSurveySettings() {
|
|
399
|
+
const [npsSurveySettings, setNpsSurveySettings] = usePersistentState<NpsSurveySettings>(
|
|
400
|
+
'STRAPI_NPS_SURVEY_SETTINGS',
|
|
401
|
+
{
|
|
402
|
+
enabled: true,
|
|
403
|
+
lastResponseDate: null,
|
|
404
|
+
firstDismissalDate: null,
|
|
405
|
+
lastDismissalDate: null,
|
|
406
|
+
}
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* TODO: should this just be an array so we can alias the `usePersistentState` hook?
|
|
411
|
+
*/
|
|
412
|
+
return { npsSurveySettings, setNpsSurveySettings };
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export { NpsSurvey, useNpsSurveySettings };
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
LoadingIndicatorPage,
|
|
5
|
+
useStrapiApp,
|
|
6
|
+
type StrapiAppContextValue,
|
|
7
|
+
} from '@strapi/helper-plugin';
|
|
8
|
+
import produce from 'immer';
|
|
9
|
+
import set from 'lodash/set';
|
|
10
|
+
|
|
11
|
+
// @ts-expect-error pages/Admin has not been converted yet.
|
|
12
|
+
import Admin from '../pages/Admin';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* TODO: this isn't great, and we really should focus on fixing this.
|
|
16
|
+
*/
|
|
17
|
+
const PluginsInitializer = () => {
|
|
18
|
+
const { plugins: appPlugins } = useStrapiApp();
|
|
19
|
+
const [{ plugins }, dispatch] = React.useReducer<React.Reducer<State, Action>, State>(
|
|
20
|
+
reducer,
|
|
21
|
+
initialState,
|
|
22
|
+
() => init(appPlugins)
|
|
23
|
+
);
|
|
24
|
+
const setPlugin = React.useRef((pluginId: string) => {
|
|
25
|
+
dispatch({ type: 'SET_PLUGIN_READY', pluginId });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const hasApluginNotReady = Object.keys(plugins).some(
|
|
29
|
+
(plugin) => plugins[plugin].isReady === false
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* I have spent some time trying to understand what is happening here, and wanted to
|
|
35
|
+
* leave that knowledge for my future me:
|
|
36
|
+
*
|
|
37
|
+
* `initializer` is an undocumented property of the `registerPlugin` API. At the time
|
|
38
|
+
* of writing it seems only to be used by the i18n plugin.
|
|
39
|
+
*
|
|
40
|
+
* How does it work?
|
|
41
|
+
*
|
|
42
|
+
* Every plugin that has an `initializer` component defined, receives the
|
|
43
|
+
* `setPlugin` function as a component prop. In the case of i18n the plugin fetches locales
|
|
44
|
+
* first and calls `setPlugin` with `pluginId` once they are loaded, which then triggers the
|
|
45
|
+
* reducer of the admin app defined above.
|
|
46
|
+
*
|
|
47
|
+
* Once all plugins are set to `isReady: true` the app renders.
|
|
48
|
+
*
|
|
49
|
+
* This API is used to block rendering of the admin app. We should remove that in v5 completely
|
|
50
|
+
* and make sure plugins can inject data into the global store before they are initialized, to avoid
|
|
51
|
+
* having a new prop-callback based communication channel between plugins and the core admin app.
|
|
52
|
+
*
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
if (hasApluginNotReady) {
|
|
56
|
+
const initializers = Object.keys(plugins).reduce((acc, current) => {
|
|
57
|
+
const InitializerComponent = plugins[current].initializer;
|
|
58
|
+
|
|
59
|
+
if (InitializerComponent) {
|
|
60
|
+
const key = plugins[current].pluginId;
|
|
61
|
+
|
|
62
|
+
acc.push(<InitializerComponent key={key} setPlugin={setPlugin.current} />);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return acc;
|
|
66
|
+
}, [] as React.ReactNode[]);
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<>
|
|
70
|
+
{initializers}
|
|
71
|
+
<LoadingIndicatorPage />
|
|
72
|
+
</>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return <Admin />;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/* -------------------------------------------------------------------------------------------------
|
|
80
|
+
* Reducer
|
|
81
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
82
|
+
|
|
83
|
+
interface State {
|
|
84
|
+
plugins: StrapiAppContextValue['plugins'];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const initialState: State = {
|
|
88
|
+
plugins: {},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
type SetPluginReadyAction = {
|
|
92
|
+
type: 'SET_PLUGIN_READY';
|
|
93
|
+
pluginId: string;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
type Action = SetPluginReadyAction;
|
|
97
|
+
|
|
98
|
+
const reducer: React.Reducer<State, Action> = (state = initialState, action: Action): State =>
|
|
99
|
+
produce(state, (draftState) => {
|
|
100
|
+
switch (action.type) {
|
|
101
|
+
case 'SET_PLUGIN_READY': {
|
|
102
|
+
set(draftState, ['plugins', action.pluginId, 'isReady'], true);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
default:
|
|
106
|
+
return draftState;
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
/* -------------------------------------------------------------------------------------------------
|
|
111
|
+
* Init state
|
|
112
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
113
|
+
|
|
114
|
+
const init = (plugins: State['plugins']): State => {
|
|
115
|
+
return {
|
|
116
|
+
plugins: Object.keys(plugins).reduce<State['plugins']>((acc, current) => {
|
|
117
|
+
acc[current] = { ...plugins[current] };
|
|
118
|
+
|
|
119
|
+
return acc;
|
|
120
|
+
}, {}),
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export { PluginsInitializer };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import { auth } from '@strapi/helper-plugin';
|
|
4
|
+
import { Redirect, Route, useLocation } from 'react-router-dom';
|
|
5
|
+
|
|
6
|
+
type PropsOf<T> = T extends React.ComponentType<infer P> ? P : object;
|
|
7
|
+
|
|
8
|
+
type PrivateRouteProps<TComponent extends React.ElementType> = {
|
|
9
|
+
component: TComponent;
|
|
10
|
+
path: string;
|
|
11
|
+
} & PropsOf<TComponent>;
|
|
12
|
+
|
|
13
|
+
const PrivateRoute = <TComponent extends React.ElementType>({
|
|
14
|
+
component: Component,
|
|
15
|
+
path,
|
|
16
|
+
...rest
|
|
17
|
+
}: PrivateRouteProps<TComponent>) => {
|
|
18
|
+
const { pathname, search } = useLocation();
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Route
|
|
22
|
+
path={path}
|
|
23
|
+
render={(props) =>
|
|
24
|
+
auth.getToken() !== null ? (
|
|
25
|
+
<Component {...rest} {...props} />
|
|
26
|
+
) : (
|
|
27
|
+
<Redirect
|
|
28
|
+
to={{
|
|
29
|
+
pathname: '/auth/login',
|
|
30
|
+
search:
|
|
31
|
+
pathname !== '/'
|
|
32
|
+
? `?redirectTo=${encodeURIComponent(`${pathname}${search}`)}`
|
|
33
|
+
: undefined,
|
|
34
|
+
}}
|
|
35
|
+
/>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { PrivateRoute };
|