@strapi/admin 4.2.0-alpha.5 → 4.2.0-alpha.6
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/src/StrapiApp.js +40 -42
- package/admin/src/components/GuidedTour/Modal/components/Modal.js +1 -1
- package/admin/src/components/Providers/index.js +65 -32
- package/admin/src/components/Theme/index.js +11 -12
- package/admin/src/components/ThemeToggleProvider/index.js +66 -0
- package/admin/src/content-manager/components/SelectWrapper/utils/getSelectStyles.js +3 -1
- package/admin/src/content-manager/components/Wysiwyg/EditorStylesContainer.js +4 -2
- package/admin/src/contexts/ThemeToggle/index.js +5 -0
- package/admin/src/contexts/index.js +1 -0
- package/admin/src/hooks/index.js +1 -0
- package/admin/src/hooks/useThemeToggle/index.js +10 -0
- package/admin/src/pages/Admin/Onboarding/index.js +1 -1
- package/admin/src/pages/HomePage/SocialLinks.js +0 -3
- package/admin/src/pages/ProfilePage/index.js +74 -10
- package/admin/src/pages/ProfilePage/utils/api.js +4 -2
- package/admin/src/translations/en.json +5 -2
- package/build/4362.ce36d91a.chunk.js +1 -0
- package/build/{6250.836851ca.chunk.js → 6404.3c2d0a81.chunk.js} +1 -1
- package/build/{Admin-authenticatedApp.a24ebaa0.chunk.js → Admin-authenticatedApp.13f39114.chunk.js} +1 -1
- package/build/{Admin_homePage.86604515.chunk.js → Admin_homePage.fd1fc572.chunk.js} +1 -1
- package/build/Admin_profilePage.d7192d06.chunk.js +1 -0
- package/build/{Admin_settingsPage.55ec1f30.chunk.js → Admin_settingsPage.a8c7ded5.chunk.js} +1 -1
- package/build/content-manager.f1c46a88.chunk.js +1 -0
- package/build/{content-type-builder.de5d18ad.chunk.js → content-type-builder.cda4ba3c.chunk.js} +1 -1
- package/build/{email-settings-page.27ee4a98.chunk.js → email-settings-page.40ee2bda.chunk.js} +1 -1
- package/build/en-json.98c7c4be.chunk.js +1 -0
- package/build/index.html +1 -1
- package/build/{main.4ea77c5f.js → main.f03a903a.js} +2 -2
- package/build/{main.4ea77c5f.js.LICENSE.txt → main.f03a903a.js.LICENSE.txt} +0 -0
- package/build/{runtime~main.83b9ee0b.js → runtime~main.251c8ddd.js} +1 -1
- package/build/users-email-settings-page.5abb9575.chunk.js +1 -0
- package/package.json +5 -5
- package/admin/src/themes/colors.js +0 -51
- package/admin/src/themes/fontWeights.js +0 -8
- package/admin/src/themes/index.js +0 -13
- package/admin/src/themes/sizes.js +0 -31
- package/build/4362.dbe98749.chunk.js +0 -1
- package/build/Admin_profilePage.c497b39d.chunk.js +0 -1
- package/build/content-manager.31be1448.chunk.js +0 -1
- package/build/en-json.bce44d39.chunk.js +0 -1
- package/build/users-email-settings-page.862eb51e.chunk.js +0 -1
package/admin/src/StrapiApp.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { BrowserRouter } from 'react-router-dom';
|
|
3
|
-
import { lightTheme } from '@strapi/design-system/themes';
|
|
3
|
+
import { lightTheme, darkTheme } from '@strapi/design-system/themes';
|
|
4
4
|
import merge from 'lodash/merge';
|
|
5
5
|
import pick from 'lodash/pick';
|
|
6
6
|
import isFunction from 'lodash/isFunction';
|
|
@@ -13,7 +13,6 @@ import App from './pages/App';
|
|
|
13
13
|
import AuthLogo from './assets/images/logo_strapi_auth_v4.png';
|
|
14
14
|
import MenuLogo from './assets/images/logo_strapi_menu.png';
|
|
15
15
|
import Providers from './components/Providers';
|
|
16
|
-
import Theme from './components/Theme';
|
|
17
16
|
import languageNativeNames from './translations/languageNativeNames';
|
|
18
17
|
import {
|
|
19
18
|
INJECT_COLUMN_IN_TABLE,
|
|
@@ -34,7 +33,7 @@ class StrapiApp {
|
|
|
34
33
|
locales: ['en'],
|
|
35
34
|
menuLogo: MenuLogo,
|
|
36
35
|
notifications: { releases: true },
|
|
37
|
-
|
|
36
|
+
themes: { light: lightTheme, dark: darkTheme },
|
|
38
37
|
translations: {},
|
|
39
38
|
tutorials: true,
|
|
40
39
|
};
|
|
@@ -226,7 +225,7 @@ class StrapiApp {
|
|
|
226
225
|
}
|
|
227
226
|
|
|
228
227
|
if (this.customConfigurations?.theme) {
|
|
229
|
-
|
|
228
|
+
merge(this.configurations.themes.light, this.customConfigurations.theme);
|
|
230
229
|
}
|
|
231
230
|
|
|
232
231
|
if (this.customConfigurations?.notifications?.releases !== undefined) {
|
|
@@ -427,44 +426,43 @@ class StrapiApp {
|
|
|
427
426
|
} = this.library;
|
|
428
427
|
|
|
429
428
|
return (
|
|
430
|
-
<
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
runHookWaterfall
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
</Theme>
|
|
429
|
+
<Providers
|
|
430
|
+
authLogo={this.configurations.authLogo}
|
|
431
|
+
components={components}
|
|
432
|
+
fields={fields}
|
|
433
|
+
localeNames={localeNames}
|
|
434
|
+
getAdminInjectedComponents={this.getAdminInjectedComponents}
|
|
435
|
+
getPlugin={this.getPlugin}
|
|
436
|
+
messages={this.configurations.translations}
|
|
437
|
+
menu={this.menu}
|
|
438
|
+
menuLogo={this.configurations.menuLogo}
|
|
439
|
+
plugins={this.plugins}
|
|
440
|
+
runHookParallel={this.runHookParallel}
|
|
441
|
+
runHookWaterfall={(name, initialValue, async = false) => {
|
|
442
|
+
return this.runHookWaterfall(name, initialValue, async, store);
|
|
443
|
+
}}
|
|
444
|
+
runHookSeries={this.runHookSeries}
|
|
445
|
+
themes={this.configurations.themes}
|
|
446
|
+
settings={this.settings}
|
|
447
|
+
showTutorials={this.configurations.tutorials}
|
|
448
|
+
showReleaseNotification={this.configurations.notifications.releases}
|
|
449
|
+
store={store}
|
|
450
|
+
>
|
|
451
|
+
<>
|
|
452
|
+
<Helmet
|
|
453
|
+
link={[
|
|
454
|
+
{
|
|
455
|
+
rel: 'icon',
|
|
456
|
+
type: 'image/png',
|
|
457
|
+
href: this.configurations.head.favicon,
|
|
458
|
+
},
|
|
459
|
+
]}
|
|
460
|
+
/>
|
|
461
|
+
<BrowserRouter basename={basename}>
|
|
462
|
+
<App store={store} />
|
|
463
|
+
</BrowserRouter>
|
|
464
|
+
</>
|
|
465
|
+
</Providers>
|
|
468
466
|
);
|
|
469
467
|
}
|
|
470
468
|
}
|
|
@@ -17,7 +17,7 @@ const ModalWrapper = styled(Flex)`
|
|
|
17
17
|
z-index: 4;
|
|
18
18
|
inset: 0;
|
|
19
19
|
/* this is theme.colors.neutral800 with opacity */
|
|
20
|
-
background: ${({ theme }) => `${theme.colors.neutral800}
|
|
20
|
+
background: ${({ theme }) => `${theme.colors.neutral800}1F`};
|
|
21
21
|
`;
|
|
22
22
|
|
|
23
23
|
const Modal = ({ onClose, onSkip, children, hideSkip }) => {
|
|
@@ -9,6 +9,8 @@ import GuidedTour from '../GuidedTour';
|
|
|
9
9
|
import AutoReloadOverlayBlockerProvider from '../AutoReloadOverlayBlockerProvider';
|
|
10
10
|
import Notifications from '../Notifications';
|
|
11
11
|
import OverlayBlocker from '../OverlayBlocker';
|
|
12
|
+
import ThemeToggleProvider from '../ThemeToggleProvider';
|
|
13
|
+
import Theme from '../Theme';
|
|
12
14
|
|
|
13
15
|
const queryClient = new QueryClient({
|
|
14
16
|
defaultOptions: {
|
|
@@ -36,41 +38,45 @@ const Providers = ({
|
|
|
36
38
|
settings,
|
|
37
39
|
showReleaseNotification,
|
|
38
40
|
showTutorials,
|
|
39
|
-
|
|
40
41
|
store,
|
|
42
|
+
themes,
|
|
41
43
|
}) => {
|
|
42
44
|
return (
|
|
43
|
-
<
|
|
44
|
-
<
|
|
45
|
-
<
|
|
46
|
-
<
|
|
47
|
-
value={{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
45
|
+
<ThemeToggleProvider themes={themes}>
|
|
46
|
+
<Theme>
|
|
47
|
+
<QueryClientProvider client={queryClient}>
|
|
48
|
+
<Provider store={store}>
|
|
49
|
+
<AdminContext.Provider value={{ getAdminInjectedComponents }}>
|
|
50
|
+
<ConfigurationsContext.Provider
|
|
51
|
+
value={{ authLogo, menuLogo, showReleaseNotification, showTutorials }}
|
|
52
|
+
>
|
|
53
|
+
<StrapiAppProvider
|
|
54
|
+
getPlugin={getPlugin}
|
|
55
|
+
menu={menu}
|
|
56
|
+
plugins={plugins}
|
|
57
|
+
runHookParallel={runHookParallel}
|
|
58
|
+
runHookWaterfall={runHookWaterfall}
|
|
59
|
+
runHookSeries={runHookSeries}
|
|
60
|
+
settings={settings}
|
|
61
|
+
>
|
|
62
|
+
<LibraryProvider components={components} fields={fields}>
|
|
63
|
+
<LanguageProvider messages={messages} localeNames={localeNames}>
|
|
64
|
+
<AutoReloadOverlayBlockerProvider>
|
|
65
|
+
<OverlayBlocker>
|
|
66
|
+
<GuidedTour>
|
|
67
|
+
<Notifications>{children}</Notifications>
|
|
68
|
+
</GuidedTour>
|
|
69
|
+
</OverlayBlocker>
|
|
70
|
+
</AutoReloadOverlayBlockerProvider>
|
|
71
|
+
</LanguageProvider>
|
|
72
|
+
</LibraryProvider>
|
|
73
|
+
</StrapiAppProvider>
|
|
74
|
+
</ConfigurationsContext.Provider>
|
|
75
|
+
</AdminContext.Provider>
|
|
76
|
+
</Provider>
|
|
77
|
+
</QueryClientProvider>
|
|
78
|
+
</Theme>
|
|
79
|
+
</ThemeToggleProvider>
|
|
74
80
|
);
|
|
75
81
|
};
|
|
76
82
|
|
|
@@ -104,6 +110,33 @@ Providers.propTypes = {
|
|
|
104
110
|
showReleaseNotification: PropTypes.bool.isRequired,
|
|
105
111
|
showTutorials: PropTypes.bool.isRequired,
|
|
106
112
|
store: PropTypes.object.isRequired,
|
|
113
|
+
themes: PropTypes.shape({
|
|
114
|
+
light: PropTypes.shape({
|
|
115
|
+
colors: PropTypes.object.isRequired,
|
|
116
|
+
shadows: PropTypes.object.isRequired,
|
|
117
|
+
sizes: PropTypes.object.isRequired,
|
|
118
|
+
zIndices: PropTypes.array.isRequired,
|
|
119
|
+
spaces: PropTypes.array.isRequired,
|
|
120
|
+
borderRadius: PropTypes.string.isRequired,
|
|
121
|
+
mediaQueries: PropTypes.object.isRequired,
|
|
122
|
+
fontSizes: PropTypes.array.isRequired,
|
|
123
|
+
lineHeights: PropTypes.array.isRequired,
|
|
124
|
+
fontWeights: PropTypes.object.isRequired,
|
|
125
|
+
}).isRequired,
|
|
126
|
+
dark: PropTypes.shape({
|
|
127
|
+
colors: PropTypes.object.isRequired,
|
|
128
|
+
shadows: PropTypes.object.isRequired,
|
|
129
|
+
sizes: PropTypes.object.isRequired,
|
|
130
|
+
zIndices: PropTypes.array.isRequired,
|
|
131
|
+
spaces: PropTypes.array.isRequired,
|
|
132
|
+
borderRadius: PropTypes.string.isRequired,
|
|
133
|
+
mediaQueries: PropTypes.object.isRequired,
|
|
134
|
+
fontSizes: PropTypes.array.isRequired,
|
|
135
|
+
lineHeights: PropTypes.array.isRequired,
|
|
136
|
+
fontWeights: PropTypes.object.isRequired,
|
|
137
|
+
}).isRequired,
|
|
138
|
+
custom: PropTypes.object,
|
|
139
|
+
}).isRequired,
|
|
107
140
|
};
|
|
108
141
|
|
|
109
142
|
export default Providers;
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ThemeProvider } from '@strapi/design-system/ThemeProvider';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
|
-
import {
|
|
4
|
+
import { useThemeToggle } from '../../hooks';
|
|
5
5
|
import GlobalStyle from '../GlobalStyle';
|
|
6
6
|
|
|
7
|
-
const Theme = ({ children
|
|
8
|
-
|
|
9
|
-
{children}
|
|
10
|
-
<GlobalStyle />
|
|
11
|
-
</ThemeProvider>
|
|
12
|
-
);
|
|
7
|
+
const Theme = ({ children }) => {
|
|
8
|
+
const { currentTheme, themes } = useThemeToggle();
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
return (
|
|
11
|
+
<ThemeProvider theme={themes[currentTheme] || themes.light}>
|
|
12
|
+
{children}
|
|
13
|
+
<GlobalStyle />
|
|
14
|
+
</ThemeProvider>
|
|
15
|
+
);
|
|
17
16
|
};
|
|
18
17
|
|
|
19
|
-
Theme.
|
|
20
|
-
|
|
18
|
+
Theme.propTypes = {
|
|
19
|
+
children: PropTypes.element.isRequired,
|
|
21
20
|
};
|
|
22
21
|
|
|
23
22
|
export default Theme;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* ThemeToggleProvider
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useState } from 'react';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { ThemeToggleContext } from '../../contexts';
|
|
10
|
+
|
|
11
|
+
const THEME_KEY = 'STRAPI_THEME';
|
|
12
|
+
|
|
13
|
+
const getDefaultTheme = () => {
|
|
14
|
+
const browserTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
15
|
+
const persistedTheme = localStorage.getItem(THEME_KEY);
|
|
16
|
+
|
|
17
|
+
return persistedTheme || browserTheme;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const ThemeToggleProvider = ({ children, themes }) => {
|
|
21
|
+
const [currentTheme, setCurrentTheme] = useState(getDefaultTheme());
|
|
22
|
+
|
|
23
|
+
const handleChangeTheme = nextTheme => {
|
|
24
|
+
setCurrentTheme(nextTheme);
|
|
25
|
+
localStorage.setItem(THEME_KEY, nextTheme);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<ThemeToggleContext.Provider value={{ currentTheme, onChangeTheme: handleChangeTheme, themes }}>
|
|
30
|
+
{children}
|
|
31
|
+
</ThemeToggleContext.Provider>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
ThemeToggleProvider.propTypes = {
|
|
36
|
+
children: PropTypes.node.isRequired,
|
|
37
|
+
themes: PropTypes.shape({
|
|
38
|
+
light: PropTypes.shape({
|
|
39
|
+
colors: PropTypes.object.isRequired,
|
|
40
|
+
shadows: PropTypes.object.isRequired,
|
|
41
|
+
sizes: PropTypes.object.isRequired,
|
|
42
|
+
zIndices: PropTypes.array.isRequired,
|
|
43
|
+
spaces: PropTypes.array.isRequired,
|
|
44
|
+
borderRadius: PropTypes.string.isRequired,
|
|
45
|
+
mediaQueries: PropTypes.object.isRequired,
|
|
46
|
+
fontSizes: PropTypes.array.isRequired,
|
|
47
|
+
lineHeights: PropTypes.array.isRequired,
|
|
48
|
+
fontWeights: PropTypes.object.isRequired,
|
|
49
|
+
}).isRequired,
|
|
50
|
+
dark: PropTypes.shape({
|
|
51
|
+
colors: PropTypes.object.isRequired,
|
|
52
|
+
shadows: PropTypes.object.isRequired,
|
|
53
|
+
sizes: PropTypes.object.isRequired,
|
|
54
|
+
zIndices: PropTypes.array.isRequired,
|
|
55
|
+
spaces: PropTypes.array.isRequired,
|
|
56
|
+
borderRadius: PropTypes.string.isRequired,
|
|
57
|
+
mediaQueries: PropTypes.object.isRequired,
|
|
58
|
+
fontSizes: PropTypes.array.isRequired,
|
|
59
|
+
lineHeights: PropTypes.array.isRequired,
|
|
60
|
+
fontWeights: PropTypes.object.isRequired,
|
|
61
|
+
}).isRequired,
|
|
62
|
+
custom: PropTypes.object,
|
|
63
|
+
}).isRequired,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default ThemeToggleProvider;
|
|
@@ -49,6 +49,8 @@ const getSelectStyles = theme => {
|
|
|
49
49
|
...base,
|
|
50
50
|
width: '100%',
|
|
51
51
|
marginTop: theme.spaces[1],
|
|
52
|
+
backgroundColor: theme.colors.neutral0,
|
|
53
|
+
color: theme.colors.neutral800,
|
|
52
54
|
borderRadius: '4px !important',
|
|
53
55
|
borderTopLeftRadius: '4px !important',
|
|
54
56
|
borderTopRightRadius: '4px !important',
|
|
@@ -76,7 +78,7 @@ const getSelectStyles = theme => {
|
|
|
76
78
|
return { ...base, lineHeight: theme.spaces[5], backgroundColor, borderRadius: 4 };
|
|
77
79
|
},
|
|
78
80
|
placeholder: base => ({ ...base, marginLeft: 0 }),
|
|
79
|
-
singleValue: base => ({ ...base, marginLeft: 0 }),
|
|
81
|
+
singleValue: base => ({ ...base, marginLeft: 0, color: theme.colors.neutral800 }),
|
|
80
82
|
valueContainer: base => ({
|
|
81
83
|
...base,
|
|
82
84
|
padding: 0,
|
|
@@ -29,7 +29,8 @@ export const EditorStylesContainer = styled.div`
|
|
|
29
29
|
|
|
30
30
|
.CodeMirror-scrollbar-filler,
|
|
31
31
|
.CodeMirror-gutter-filler {
|
|
32
|
-
|
|
32
|
+
/* The little square between H and V scrollbars */
|
|
33
|
+
background-color: ${({ theme }) => `${theme.colors.neutral0}`};
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
/* GUTTER */
|
|
@@ -158,7 +159,7 @@ export const EditorStylesContainer = styled.div`
|
|
|
158
159
|
.CodeMirror {
|
|
159
160
|
position: relative;
|
|
160
161
|
overflow: hidden;
|
|
161
|
-
background:
|
|
162
|
+
background: ${({ theme }) => `${theme.colors.neutral0}`};
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
.CodeMirror-scroll {
|
|
@@ -292,6 +293,7 @@ export const EditorStylesContainer = styled.div`
|
|
|
292
293
|
.CodeMirror-cursor {
|
|
293
294
|
position: absolute;
|
|
294
295
|
pointer-events: none;
|
|
296
|
+
border-color: ${({ theme }) => `${theme.colors.neutral800}`};
|
|
295
297
|
}
|
|
296
298
|
.CodeMirror-measure pre {
|
|
297
299
|
position: static;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { default as AdminContext } from './Admin';
|
|
2
2
|
export { default as ConfigurationsContext } from './Configurations';
|
|
3
3
|
export { default as PermissionsDataManagerContext } from './PermisssionsDataManagerContext';
|
|
4
|
+
export { default as ThemeToggleContext } from './ThemeToggle';
|
package/admin/src/hooks/index.js
CHANGED
|
@@ -9,3 +9,4 @@ export { default as useSettingsMenu } from './useSettingsMenu';
|
|
|
9
9
|
export { default as useSettingsForm } from './useSettingsForm';
|
|
10
10
|
export { default as usePermissionsDataManager } from './usePermissionsDataManager';
|
|
11
11
|
export { default as useReleaseNotification } from './useReleaseNotification';
|
|
12
|
+
export { default as useThemeToggle } from './useThemeToggle';
|
|
@@ -9,12 +9,13 @@ import {
|
|
|
9
9
|
useNotification,
|
|
10
10
|
useOverlayBlocker,
|
|
11
11
|
auth,
|
|
12
|
+
useTracking,
|
|
12
13
|
} from '@strapi/helper-plugin';
|
|
13
14
|
import { useIntl } from 'react-intl';
|
|
14
15
|
import { Formik } from 'formik';
|
|
16
|
+
import upperFirst from 'lodash/upperFirst';
|
|
15
17
|
import { useQuery, useMutation, useQueryClient } from 'react-query';
|
|
16
18
|
import pick from 'lodash/pick';
|
|
17
|
-
import omit from 'lodash/omit';
|
|
18
19
|
import { Helmet } from 'react-helmet';
|
|
19
20
|
import { Main } from '@strapi/design-system/Main';
|
|
20
21
|
import { Typography } from '@strapi/design-system/Typography';
|
|
@@ -31,10 +32,15 @@ import Eye from '@strapi/icons/Eye';
|
|
|
31
32
|
import EyeStriked from '@strapi/icons/EyeStriked';
|
|
32
33
|
import Check from '@strapi/icons/Check';
|
|
33
34
|
import useLocalesProvider from '../../components/LocalesProvider/useLocalesProvider';
|
|
35
|
+
import { useThemeToggle } from '../../hooks';
|
|
34
36
|
import { fetchUser, putUser } from './utils/api';
|
|
35
37
|
import schema from './utils/schema';
|
|
36
38
|
import { getFullName } from '../../utils';
|
|
37
39
|
|
|
40
|
+
const DocumentationLink = styled.a`
|
|
41
|
+
color: ${({ theme }) => theme.colors.primary600};
|
|
42
|
+
`;
|
|
43
|
+
|
|
38
44
|
const PasswordInput = styled(TextInput)`
|
|
39
45
|
::-ms-reveal {
|
|
40
46
|
display: none;
|
|
@@ -59,9 +65,11 @@ const ProfilePage = () => {
|
|
|
59
65
|
const { setUserDisplayName } = useAppInfos();
|
|
60
66
|
const queryClient = useQueryClient();
|
|
61
67
|
const { formatMessage } = useIntl();
|
|
68
|
+
const { trackUsage } = useTracking();
|
|
62
69
|
const toggleNotification = useNotification();
|
|
63
70
|
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
64
71
|
const { notifyStatus } = useNotifyAT();
|
|
72
|
+
const { currentTheme, themes: allApplicationThemes, onChangeTheme } = useThemeToggle();
|
|
65
73
|
useFocusWhenNavigate();
|
|
66
74
|
|
|
67
75
|
const { status, data } = useQuery('user', () => fetchUser(), {
|
|
@@ -83,14 +91,18 @@ const ProfilePage = () => {
|
|
|
83
91
|
|
|
84
92
|
const isLoading = status !== 'success';
|
|
85
93
|
|
|
86
|
-
const submitMutation = useMutation(body => putUser(
|
|
94
|
+
const submitMutation = useMutation(body => putUser(body), {
|
|
87
95
|
onSuccess: async data => {
|
|
88
96
|
await queryClient.invalidateQueries('user');
|
|
89
97
|
|
|
90
|
-
auth.setUserInfo(
|
|
98
|
+
auth.setUserInfo(
|
|
99
|
+
pick(data, ['email', 'firstname', 'lastname', 'username', 'preferedLanguage'])
|
|
100
|
+
);
|
|
91
101
|
const userDisplayName = data.username || getFullName(data.firstname, data.lastname);
|
|
92
102
|
setUserDisplayName(userDisplayName);
|
|
93
103
|
changeLocale(data.preferedLanguage);
|
|
104
|
+
onChangeTheme(data.currentTheme);
|
|
105
|
+
trackUsage('didChangeMode', { newMode: data.currentTheme });
|
|
94
106
|
|
|
95
107
|
toggleNotification({
|
|
96
108
|
type: 'success',
|
|
@@ -128,9 +140,16 @@ const ProfilePage = () => {
|
|
|
128
140
|
);
|
|
129
141
|
};
|
|
130
142
|
|
|
131
|
-
const fieldsToPick = [
|
|
143
|
+
const fieldsToPick = [
|
|
144
|
+
'currentTheme',
|
|
145
|
+
'email',
|
|
146
|
+
'firstname',
|
|
147
|
+
'lastname',
|
|
148
|
+
'username',
|
|
149
|
+
'preferedLanguage',
|
|
150
|
+
];
|
|
132
151
|
|
|
133
|
-
const initialData = pick(data, fieldsToPick);
|
|
152
|
+
const initialData = pick({ ...data, currentTheme }, fieldsToPick);
|
|
134
153
|
|
|
135
154
|
if (isLoading) {
|
|
136
155
|
return (
|
|
@@ -154,6 +173,10 @@ const ProfilePage = () => {
|
|
|
154
173
|
);
|
|
155
174
|
}
|
|
156
175
|
|
|
176
|
+
const themesToDisplay = Object.keys(allApplicationThemes).filter(
|
|
177
|
+
themeName => allApplicationThemes[themeName]
|
|
178
|
+
);
|
|
179
|
+
|
|
157
180
|
return (
|
|
158
181
|
<Main aria-busy={isSubmittingForm}>
|
|
159
182
|
<Helmet
|
|
@@ -424,20 +447,20 @@ const ProfilePage = () => {
|
|
|
424
447
|
id:
|
|
425
448
|
'Settings.profile.form.section.experience.interfaceLanguageHelp',
|
|
426
449
|
defaultMessage:
|
|
427
|
-
'
|
|
450
|
+
'Preference changes will apply only to you. More information is available {here}.',
|
|
428
451
|
},
|
|
429
452
|
{
|
|
430
|
-
|
|
431
|
-
<
|
|
453
|
+
here: (
|
|
454
|
+
<DocumentationLink
|
|
432
455
|
target="_blank"
|
|
433
456
|
rel="noopener noreferrer"
|
|
434
457
|
href="https://docs.strapi.io/developer-docs/latest/development/admin-customization.html#locales"
|
|
435
458
|
>
|
|
436
459
|
{formatMessage({
|
|
437
460
|
id: 'Settings.profile.form.section.experience.documentation',
|
|
438
|
-
defaultMessage: '
|
|
461
|
+
defaultMessage: 'here',
|
|
439
462
|
})}
|
|
440
|
-
</
|
|
463
|
+
</DocumentationLink>
|
|
441
464
|
),
|
|
442
465
|
}
|
|
443
466
|
)}
|
|
@@ -487,6 +510,47 @@ const ProfilePage = () => {
|
|
|
487
510
|
})}
|
|
488
511
|
</Select>
|
|
489
512
|
</GridItem>
|
|
513
|
+
<GridItem s={12} col={6}>
|
|
514
|
+
<Select
|
|
515
|
+
label={formatMessage({
|
|
516
|
+
id: 'Settings.profile.form.section.experience.mode.label',
|
|
517
|
+
defaultMessage: 'Interface mode',
|
|
518
|
+
})}
|
|
519
|
+
placeholder={formatMessage({
|
|
520
|
+
id: 'components.Select.placeholder',
|
|
521
|
+
defaultMessage: 'Select',
|
|
522
|
+
})}
|
|
523
|
+
hint={formatMessage({
|
|
524
|
+
id: 'Settings.profile.form.section.experience.mode.hint',
|
|
525
|
+
defaultMessage: 'Displays your interface in the chosen mode.',
|
|
526
|
+
})}
|
|
527
|
+
value={values.currentTheme}
|
|
528
|
+
onChange={e => {
|
|
529
|
+
handleChange({
|
|
530
|
+
target: { name: 'currentTheme', value: e },
|
|
531
|
+
});
|
|
532
|
+
}}
|
|
533
|
+
>
|
|
534
|
+
{themesToDisplay.map(theme => {
|
|
535
|
+
const label = formatMessage(
|
|
536
|
+
{
|
|
537
|
+
id:
|
|
538
|
+
'Settings.profile.form.section.experience.mode.option-label',
|
|
539
|
+
defaultMessage: '{name} mode',
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
name: upperFirst(theme),
|
|
543
|
+
}
|
|
544
|
+
);
|
|
545
|
+
|
|
546
|
+
return (
|
|
547
|
+
<Option value={theme} key={theme}>
|
|
548
|
+
{label}
|
|
549
|
+
</Option>
|
|
550
|
+
);
|
|
551
|
+
})}
|
|
552
|
+
</Select>
|
|
553
|
+
</GridItem>
|
|
490
554
|
</Grid>
|
|
491
555
|
</Stack>
|
|
492
556
|
</Box>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import omit from 'lodash/omit';
|
|
1
2
|
import { axiosInstance } from '../../../core/utils';
|
|
2
3
|
|
|
3
4
|
const fetchUser = async () => {
|
|
@@ -7,9 +8,10 @@ const fetchUser = async () => {
|
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
const putUser = async body => {
|
|
10
|
-
const
|
|
11
|
+
const dataToSend = omit(body, ['confirmPassword', 'currentTheme']);
|
|
12
|
+
const { data } = await axiosInstance.put('/admin/users/me', dataToSend);
|
|
11
13
|
|
|
12
|
-
return data.data;
|
|
14
|
+
return { ...data.data, currentTheme: body.currentTheme };
|
|
13
15
|
};
|
|
14
16
|
|
|
15
17
|
export { fetchUser, putUser };
|
|
@@ -133,10 +133,13 @@
|
|
|
133
133
|
"Settings.permissions.users.tabs.label": "Tabs Permissions",
|
|
134
134
|
"Settings.profile.form.notify.data.loaded": "Your profile data has been loaded",
|
|
135
135
|
"Settings.profile.form.section.experience.clear.select": "Clear the interface language selected",
|
|
136
|
-
"Settings.profile.form.section.experience.
|
|
136
|
+
"Settings.profile.form.section.experience.here": "here",
|
|
137
137
|
"Settings.profile.form.section.experience.interfaceLanguage": "Interface language",
|
|
138
138
|
"Settings.profile.form.section.experience.interfaceLanguage.hint": "This will only display your own interface in the chosen language.",
|
|
139
|
-
"Settings.profile.form.section.experience.interfaceLanguageHelp": "
|
|
139
|
+
"Settings.profile.form.section.experience.interfaceLanguageHelp": "Preference changes will apply only to you. More information is available {here}.",
|
|
140
|
+
"Settings.profile.form.section.experience.mode.label": "Interface mode",
|
|
141
|
+
"Settings.profile.form.section.experience.mode.hint": "Displays your interface in the chosen mode.",
|
|
142
|
+
"Settings.profile.form.section.experience.mode.option-label": "{name} mode",
|
|
140
143
|
"Settings.profile.form.section.experience.title": "Experience",
|
|
141
144
|
"Settings.profile.form.section.helmet.title": "User profile",
|
|
142
145
|
"Settings.profile.form.section.password.title": "Change password",
|