@strapi/admin 4.14.4 → 4.14.5
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/admin/.eslintrc.js +12 -0
- package/admin/custom.d.ts +20 -0
- package/admin/src/StrapiApp.js +14 -16
- package/admin/src/components/AuthenticatedApp/index.js +4 -4
- package/admin/src/components/ConfigurationProvider.tsx +67 -0
- package/admin/src/components/LanguageProvider.tsx +129 -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/Providers/index.js +6 -6
- package/admin/src/components/UnauthenticatedLogo.tsx +2 -2
- package/admin/src/components/{LocalesProvider/__mocks__/useLocalesProvider.js → __mocks__/LanguageProvider.js} +1 -1
- package/admin/src/content-manager/components/BlocksEditor/BlocksInput/index.js +48 -8
- package/admin/src/content-manager/components/BlocksEditor/Toolbar/index.js +146 -68
- package/admin/src/content-manager/components/BlocksEditor/hooks/useBlocksStore.js +50 -47
- package/admin/src/content-manager/components/BlocksEditor/hooks/useModifiersStore.js +11 -9
- package/admin/src/content-manager/components/BlocksEditor/index.js +1 -14
- package/admin/src/contexts/admin.ts +18 -0
- package/admin/src/contexts/configuration.ts +14 -4
- package/admin/src/hooks/__mocks__/useConfigurations.ts +2 -2
- package/admin/src/hooks/index.js +0 -3
- 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/{useEnterprise/useEnterprise.js → useEnterprise.ts} +15 -5
- package/admin/src/hooks/useMenu.ts +153 -0
- package/admin/src/index.js +5 -2
- package/admin/src/layouts/UnauthenticatedLayout/LocaleToggle/index.js +2 -2
- package/admin/src/pages/Admin/index.js +4 -3
- package/admin/src/pages/App/index.js +5 -3
- package/admin/src/pages/AuthPage/components/Register/index.js +28 -33
- package/admin/src/pages/AuthPage/index.js +2 -2
- package/admin/src/pages/ProfilePage/index.js +2 -2
- package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +119 -87
- 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/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/TransferTokens/ListView/index.js +3 -5
- package/admin/src/shared/hooks/index.js +0 -1
- package/admin/src/shared/hooks/useInjectionZone/index.js +2 -2
- package/admin/src/types/adminAPI.ts +29 -0
- package/admin/src/utils/createRoute.js +4 -1
- package/admin/tsconfig.build.json +4 -0
- package/admin/tsconfig.json +7 -1
- package/build/{1049.f7aed23d.chunk.js → 1049.9236e785.chunk.js} +1 -1
- package/build/1222.fe92c653.chunk.js +35 -0
- package/build/{1227.f9c74718.chunk.js → 1227.e0f7447b.chunk.js} +1 -1
- package/build/135.ad267b59.chunk.js +1 -0
- package/build/{1386.6b8819c6.chunk.js → 1386.07f2bbb3.chunk.js} +1 -1
- package/build/1835.eaa696ba.chunk.js +1 -0
- package/build/{2225.d1bcf7e3.chunk.js → 2225.a2147b8f.chunk.js} +2 -2
- package/build/2325.d705b39a.chunk.js +1 -0
- package/build/2379.b0bc4013.chunk.js +1 -0
- package/build/{2395.aca6ce66.chunk.js → 2395.d37b1025.chunk.js} +1 -1
- package/build/2421.79e5b3d0.chunk.js +1 -0
- package/build/267.073a3bcb.chunk.js +1 -0
- package/build/2801.12522720.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/{8743.31c921b1.chunk.js → 3019.0d74d080.chunk.js} +123 -139
- package/build/3021.33ad47fb.chunk.js +103 -0
- package/build/{3483.5df8e010.chunk.js → 3483.8f1b25f8.chunk.js} +1 -1
- package/build/3911.488fbde3.chunk.js +95 -0
- package/build/{4174.df9aa09a.chunk.js → 4174.2c4f958e.chunk.js} +1 -1
- 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/4916.480053a6.chunk.js +1 -0
- package/build/4996.d285c30b.chunk.js +1 -0
- package/build/502.b845473a.chunk.js +1 -0
- package/build/5858.493b31ec.chunk.js +1 -0
- package/build/6345.334e7678.chunk.js +1 -0
- package/build/6373.1a21d665.chunk.js +105 -0
- package/build/6453.4160b5b7.chunk.js +1 -0
- package/build/7448.6fd14dd3.chunk.js +1 -0
- package/build/7464.91341b4f.chunk.js +1 -0
- package/build/7735.9e7c9fdd.chunk.js +10 -0
- package/build/782.7243b183.chunk.js +1 -0
- package/build/7849.2a500ed8.chunk.js +1 -0
- package/build/7897.dffa5ad5.chunk.js +6 -0
- package/build/8162.7d1100a0.chunk.js +1 -0
- package/build/{8276.d4426fd8.chunk.js → 8276.e9698944.chunk.js} +2 -2
- package/build/8894.5ca4852a.chunk.js +26 -0
- package/build/8980.f0045cc1.chunk.js +1 -0
- package/build/9153.42c1428a.chunk.js +1 -0
- package/build/{9218.8bc01ab9.chunk.js → 9218.306ad178.chunk.js} +1 -1
- package/build/9285.5f174057.chunk.js +1 -0
- package/build/9302.550cf5b7.chunk.js +146 -0
- package/build/9547.62987774.chunk.js +1 -0
- package/build/9754.b4e73779.chunk.js +1 -0
- package/build/Admin-authenticatedApp.e897fccb.chunk.js +79 -0
- package/build/{Admin_InternalErrorPage.b66ee9c1.chunk.js → Admin_InternalErrorPage.e2431a95.chunk.js} +1 -1
- package/build/Admin_homePage.71ef8d06.chunk.js +81 -0
- package/build/{Admin_marketplace.31b962b8.chunk.js → Admin_marketplace.0db78604.chunk.js} +1 -1
- package/build/{Admin_pluginsPage.9217101d.chunk.js → Admin_pluginsPage.1083f7f0.chunk.js} +1 -1
- package/build/{Admin_profilePage.680123d9.chunk.js → Admin_profilePage.61704b7d.chunk.js} +2 -2
- package/build/Admin_settingsPage.39cb9fca.chunk.js +111 -0
- package/build/{Upload_ConfigureTheView.b40eea4d.chunk.js → Upload_ConfigureTheView.3cfeb108.chunk.js} +1 -1
- package/build/admin-app.06f5e70a.chunk.js +69 -0
- package/build/admin-edit-roles-page.556fac52.chunk.js +267 -0
- package/build/admin-edit-users.64fd1318.chunk.js +10 -0
- package/build/admin-roles-list.15918328.chunk.js +22 -0
- package/build/admin-users.74fddc87.chunk.js +11 -0
- package/build/{api-tokens-create-page.0dd63e91.chunk.js → api-tokens-create-page.c08ae118.chunk.js} +1 -1
- package/build/{api-tokens-edit-page.78d877f8.chunk.js → api-tokens-edit-page.ce18efdc.chunk.js} +1 -1
- package/build/api-tokens-list-page.783b7569.chunk.js +16 -0
- package/build/audit-logs-settings-page.12aeea8c.chunk.js +1 -0
- package/build/content-manager.2e3f660b.chunk.js +1220 -0
- package/build/{content-type-builder-list-view.3fffae65.chunk.js → content-type-builder-list-view.38ed3935.chunk.js} +7 -7
- package/build/{content-type-builder.98c71164.chunk.js → content-type-builder.758a9d23.chunk.js} +4 -4
- package/build/email-settings-page.e08a587e.chunk.js +11 -0
- package/build/{i18n-settings-page.a9708926.chunk.js → i18n-settings-page.3186e3e9.chunk.js} +1 -1
- package/build/index.html +1 -1
- package/build/main.00ea6f5a.js +2665 -0
- package/build/{review-workflows-settings-create-view.b7b0c6c5.chunk.js → review-workflows-settings-create-view.5cdc4d64.chunk.js} +1 -1
- package/build/{review-workflows-settings-edit-view.c331b3fe.chunk.js → review-workflows-settings-edit-view.53bf7865.chunk.js} +1 -1
- package/build/review-workflows-settings-list-view.b4a8aefb.chunk.js +56 -0
- package/build/runtime~main.e3bf3980.js +2 -0
- package/build/sso-settings-page.6a35d473.chunk.js +1 -0
- package/build/{transfer-tokens-create-page.e7f541d3.chunk.js → transfer-tokens-create-page.2662d519.chunk.js} +1 -1
- package/build/{transfer-tokens-edit-page.bd1276c2.chunk.js → transfer-tokens-edit-page.f64d8d8c.chunk.js} +1 -1
- package/build/transfer-tokens-list-page.e6fd5f87.chunk.js +16 -0
- package/build/{upload-settings.97ef4c92.chunk.js → upload-settings.450a1de0.chunk.js} +1 -1
- package/build/{upload.f08715a1.chunk.js → upload.0d53e7a3.chunk.js} +1 -1
- package/build/{users-advanced-settings-page.36a3c363.chunk.js → users-advanced-settings-page.4a1f1f6d.chunk.js} +1 -1
- package/build/users-email-settings-page.ea81fe82.chunk.js +9 -0
- package/build/users-providers-settings-page.10280cdb.chunk.js +14 -0
- package/build/{users-roles-settings-page.d5a8e8a1.chunk.js → users-roles-settings-page.4a7158be.chunk.js} +1 -1
- package/build/{webhook-edit-page.87456194.chunk.js → webhook-edit-page.65ac30ee.chunk.js} +2 -2
- package/build/{webhook-list-page.c88a382b.chunk.js → webhook-list-page.f57285ca.chunk.js} +1 -1
- package/jest.config.front.js +4 -0
- package/package.json +23 -17
- package/scripts/build.js +1 -1
- package/server/controllers/admin.js +3 -2
- package/shared/entities.ts +33 -0
- package/shared/permissions.ts +52 -0
- package/admin/src/components/ConfigurationsProvider/index.js +0 -66
- package/admin/src/components/ConfigurationsProvider/reducer.js +0 -29
- 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/contexts/Admin/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/index.js +0 -3
- 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.ts +0 -5
- package/admin/src/hooks/useEnterprise/index.js +0 -1
- 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/shared/hooks/useAdminProvider/index.js +0 -11
- package/build/2224.8af54440.chunk.js +0 -138
- package/build/2379.f0baf826.chunk.js +0 -1
- package/build/2421.a478ba24.chunk.js +0 -105
- package/build/2801.c49f88a1.chunk.js +0 -1
- package/build/3911.d4fada48.chunk.js +0 -95
- package/build/412.72afdf0c.chunk.js +0 -689
- package/build/502.8666bbef.chunk.js +0 -25
- package/build/5702.5b433d50.chunk.js +0 -1
- package/build/6186.c33ce082.chunk.js +0 -116
- package/build/6715.48e37308.chunk.js +0 -1
- package/build/6812.00ef5b0d.chunk.js +0 -26
- package/build/7464.43a4527c.chunk.js +0 -1
- package/build/7818.d2196a53.chunk.js +0 -29
- package/build/7897.5c03247b.chunk.js +0 -25
- package/build/8690.33243bba.chunk.js +0 -38
- package/build/Admin-authenticatedApp.27545a1b.chunk.js +0 -112
- package/build/Admin_homePage.a6281dd6.chunk.js +0 -124
- package/build/Admin_settingsPage.33378310.chunk.js +0 -111
- package/build/admin-app.e8c52c37.chunk.js +0 -36
- package/build/admin-edit-roles-page.fcf056bf.chunk.js +0 -275
- package/build/admin-edit-users.89efe3c4.chunk.js +0 -10
- package/build/admin-roles-list.8b77704a.chunk.js +0 -22
- package/build/admin-users.e3f1be14.chunk.js +0 -19
- package/build/api-tokens-list-page.ae13346c.chunk.js +0 -16
- package/build/audit-logs-settings-page.e9c92a75.chunk.js +0 -9
- package/build/content-manager.5849dbe3.chunk.js +0 -1226
- package/build/email-settings-page.ecfec9b3.chunk.js +0 -11
- package/build/email-translation-ar-json.88304564.chunk.js +0 -1
- package/build/email-translation-cs-json.6eaeec6a.chunk.js +0 -1
- package/build/email-translation-de-json.1b334230.chunk.js +0 -1
- package/build/email-translation-dk-json.85402492.chunk.js +0 -1
- package/build/email-translation-en-json.4211d4d0.chunk.js +0 -1
- package/build/email-translation-es-json.0b6b1006.chunk.js +0 -1
- package/build/email-translation-fr-json.78be2787.chunk.js +0 -1
- package/build/email-translation-id-json.c97239fe.chunk.js +0 -1
- package/build/email-translation-it-json.a2ed8c78.chunk.js +0 -1
- package/build/email-translation-ja-json.63eebd02.chunk.js +0 -1
- package/build/email-translation-ko-json.4de49b23.chunk.js +0 -1
- package/build/email-translation-ms-json.7390477e.chunk.js +0 -1
- package/build/email-translation-nl-json.377bdd9f.chunk.js +0 -1
- package/build/email-translation-pl-json.97d0db97.chunk.js +0 -1
- package/build/email-translation-pt-BR-json.81cca553.chunk.js +0 -1
- package/build/email-translation-pt-json.2a2a0643.chunk.js +0 -1
- package/build/email-translation-ru-json.6bce37dd.chunk.js +0 -1
- package/build/email-translation-sk-json.53da2fcd.chunk.js +0 -1
- package/build/email-translation-th-json.660fa9a8.chunk.js +0 -1
- package/build/email-translation-tr-json.e6c0f8fc.chunk.js +0 -1
- package/build/email-translation-uk-json.bd1fb6bf.chunk.js +0 -1
- package/build/email-translation-vi-json.9fb7e6d7.chunk.js +0 -1
- package/build/email-translation-zh-Hans-json.c6841563.chunk.js +0 -1
- package/build/email-translation-zh-json.7a2232ea.chunk.js +0 -1
- package/build/main.3abb6f34.js +0 -3278
- package/build/review-workflows-settings-list-view.70218dc1.chunk.js +0 -75
- package/build/runtime~main.450561b1.js +0 -2
- package/build/sso-settings-page.1a9e7f8f.chunk.js +0 -1
- package/build/transfer-tokens-list-page.5de6bb9f.chunk.js +0 -16
- package/build/users-email-settings-page.47b47962.chunk.js +0 -149
- package/build/users-providers-settings-page.1e0c8376.chunk.js +0 -154
- /package/admin/src/hooks/{useAdminUsers/__mocks__/index.js → __mocks__/useAdminUsers.ts} +0 -0
- /package/admin/src/{hooks/useAdminRolePermissions/__mocks__/index.js → pages/SettingsPage/pages/Roles/hooks/__mocks__/useAdminRolePermissions.ts} +0 -0
package/admin/.eslintrc.js
CHANGED
|
@@ -12,5 +12,17 @@ module.exports = {
|
|
|
12
12
|
files: ['**/*.ts', '**/*.tsx'],
|
|
13
13
|
extends: ['custom/front/typescript'],
|
|
14
14
|
},
|
|
15
|
+
{
|
|
16
|
+
files: ['./tests/*', '**/*.test.*'],
|
|
17
|
+
env: {
|
|
18
|
+
jest: true,
|
|
19
|
+
},
|
|
20
|
+
rules: {
|
|
21
|
+
/**
|
|
22
|
+
* So we can do `import { render } from '@tests/utils'`
|
|
23
|
+
*/
|
|
24
|
+
'import/no-unresolved': 'off',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
15
27
|
],
|
|
16
28
|
};
|
package/admin/custom.d.ts
CHANGED
|
@@ -6,3 +6,23 @@ declare module 'styled-components' {
|
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
7
7
|
export interface DefaultTheme extends StrapiTheme {}
|
|
8
8
|
}
|
|
9
|
+
|
|
10
|
+
declare global {
|
|
11
|
+
interface Window {
|
|
12
|
+
strapi: {
|
|
13
|
+
backendURL: string;
|
|
14
|
+
isEE: boolean;
|
|
15
|
+
features: {
|
|
16
|
+
SSO: 'sso';
|
|
17
|
+
AUDIT_LOGS: 'audit-logs';
|
|
18
|
+
REVIEW_WORKFLOWS: 'review-workflows';
|
|
19
|
+
isEnabled: (featureName?: string) => boolean;
|
|
20
|
+
};
|
|
21
|
+
flags: {
|
|
22
|
+
nps?: boolean;
|
|
23
|
+
};
|
|
24
|
+
projectType: 'Community' | 'Enterprise';
|
|
25
|
+
telemetryDisabled: boolean;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
package/admin/src/StrapiApp.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Helmet } from 'react-helmet';
|
|
|
9
9
|
import { BrowserRouter } from 'react-router-dom';
|
|
10
10
|
|
|
11
11
|
import Logo from './assets/images/logo-strapi-2022.svg';
|
|
12
|
-
import
|
|
12
|
+
import { LANGUAGE_LOCAL_STORAGE_KEY } from './components/LanguageProvider';
|
|
13
13
|
import Providers from './components/Providers';
|
|
14
14
|
import { customFields, Plugin } from './core/apis';
|
|
15
15
|
import configureStore from './core/store/configureStore';
|
|
@@ -454,21 +454,19 @@ class StrapiApp {
|
|
|
454
454
|
showReleaseNotification={this.configurations.notifications.releases}
|
|
455
455
|
store={store}
|
|
456
456
|
>
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
<
|
|
469
|
-
|
|
470
|
-
</BrowserRouter>
|
|
471
|
-
</>
|
|
457
|
+
<Helmet
|
|
458
|
+
link={[
|
|
459
|
+
{
|
|
460
|
+
rel: 'icon',
|
|
461
|
+
type: 'image/png',
|
|
462
|
+
href: this.configurations.head.favicon,
|
|
463
|
+
},
|
|
464
|
+
]}
|
|
465
|
+
htmlAttributes={{ lang: localStorage.getItem(LANGUAGE_LOCAL_STORAGE_KEY) || 'en' }}
|
|
466
|
+
/>
|
|
467
|
+
<BrowserRouter basename={basename}>
|
|
468
|
+
<App store={store} />
|
|
469
|
+
</BrowserRouter>
|
|
472
470
|
</Providers>
|
|
473
471
|
);
|
|
474
472
|
}
|
|
@@ -12,10 +12,10 @@ import { useQueries } from 'react-query';
|
|
|
12
12
|
// TODO: DS add loader
|
|
13
13
|
|
|
14
14
|
import packageJSON from '../../../../package.json';
|
|
15
|
-
import {
|
|
15
|
+
import { useConfiguration } from '../../hooks/useConfiguration';
|
|
16
16
|
import { getFullName, hashAdminUserEmail } from '../../utils';
|
|
17
|
-
import NpsSurvey from '../NpsSurvey';
|
|
18
|
-
import PluginsInitializer from '../PluginsInitializer';
|
|
17
|
+
import { NpsSurvey } from '../NpsSurvey';
|
|
18
|
+
import { PluginsInitializer } from '../PluginsInitializer';
|
|
19
19
|
import RBACProvider from '../RBACProvider';
|
|
20
20
|
|
|
21
21
|
import { fetchAppInfo, fetchCurrentUserPermissions, fetchUserRoles } from './utils/api';
|
|
@@ -31,7 +31,7 @@ const AuthenticatedApp = () => {
|
|
|
31
31
|
const userName = get(userInfo, 'username') || getFullName(userInfo.firstname, userInfo.lastname);
|
|
32
32
|
const [userDisplayName, setUserDisplayName] = useState(userName);
|
|
33
33
|
const [userId, setUserId] = useState(null);
|
|
34
|
-
const { showReleaseNotification } =
|
|
34
|
+
const { showReleaseNotification } = useConfiguration();
|
|
35
35
|
const [
|
|
36
36
|
{ data: appInfos, status },
|
|
37
37
|
{ data: tagName, isLoading },
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import { ConfigurationContext, ConfigurationContextValue } from '../contexts/configuration';
|
|
4
|
+
|
|
5
|
+
export interface ConfigurationProviderProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
authLogo: string;
|
|
8
|
+
menuLogo: string;
|
|
9
|
+
showReleaseNotification?: boolean;
|
|
10
|
+
showTutorials?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type LogoKeys = keyof ConfigurationContextValue['logos'];
|
|
14
|
+
|
|
15
|
+
const ConfigurationProvider = ({
|
|
16
|
+
children,
|
|
17
|
+
authLogo: defaultAuthLogo,
|
|
18
|
+
menuLogo: defaultMenuLogo,
|
|
19
|
+
showReleaseNotification = false,
|
|
20
|
+
showTutorials = false,
|
|
21
|
+
}: ConfigurationProviderProps) => {
|
|
22
|
+
const [{ menuLogo, authLogo }, setLogos] = React.useState<{
|
|
23
|
+
[_Key in `${LogoKeys}Logo`]?: ConfigurationContextValue['logos'][LogoKeys]['custom'];
|
|
24
|
+
}>({
|
|
25
|
+
menuLogo: null,
|
|
26
|
+
authLogo: null,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const updateProjectSettings: ConfigurationContextValue['updateProjectSettings'] =
|
|
30
|
+
React.useCallback(
|
|
31
|
+
({ menuLogo, authLogo }) => {
|
|
32
|
+
setLogos({
|
|
33
|
+
menuLogo: menuLogo || defaultMenuLogo,
|
|
34
|
+
authLogo: authLogo || defaultAuthLogo,
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
[defaultAuthLogo, defaultMenuLogo]
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const configurationValue = React.useMemo(() => {
|
|
41
|
+
return {
|
|
42
|
+
logos: {
|
|
43
|
+
menu: { custom: menuLogo, default: defaultMenuLogo },
|
|
44
|
+
auth: { custom: authLogo, default: defaultAuthLogo },
|
|
45
|
+
},
|
|
46
|
+
updateProjectSettings,
|
|
47
|
+
showReleaseNotification,
|
|
48
|
+
showTutorials,
|
|
49
|
+
};
|
|
50
|
+
}, [
|
|
51
|
+
menuLogo,
|
|
52
|
+
defaultMenuLogo,
|
|
53
|
+
authLogo,
|
|
54
|
+
defaultAuthLogo,
|
|
55
|
+
updateProjectSettings,
|
|
56
|
+
showReleaseNotification,
|
|
57
|
+
showTutorials,
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<ConfigurationContext.Provider value={configurationValue}>
|
|
62
|
+
{children}
|
|
63
|
+
</ConfigurationContext.Provider>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export { ConfigurationProvider };
|
|
@@ -0,0 +1,129 @@
|
|
|
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 };
|
|
@@ -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 };
|