Add theme toggle to user profile

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2022-02-24 11:21:37 +01:00
parent afb2c8e3fc
commit 3a74150d3a
6 changed files with 74 additions and 15 deletions

View File

@ -1,9 +1,6 @@
import darkTheme from './temp-dark-theme';
export default {
config: {
locales: ['fr'],
theme: darkTheme,
},
bootstrap() {},
};

View File

@ -5,10 +5,10 @@ import { useThemeToggle } from '../../hooks';
import GlobalStyle from '../GlobalStyle';
const Theme = ({ children }) => {
const { currentTheme } = useThemeToggle();
const { currentTheme, themes } = useThemeToggle();
return (
<ThemeProvider theme={currentTheme}>
<ThemeProvider theme={themes[currentTheme] || themes.light}>
{children}
<GlobalStyle />
</ThemeProvider>

View File

@ -9,14 +9,14 @@ import PropTypes from 'prop-types';
import { ThemeToggleContext } from '../../contexts';
const ThemeToggleProvider = ({ children, themes }) => {
const [currentTheme, setCurrentTheme] = useState(themes.light);
const [currentTheme, setCurrentTheme] = useState('light');
const handleChangeTheme = nextTheme => {
setCurrentTheme(themes[nextTheme]);
setCurrentTheme(nextTheme);
};
return (
<ThemeToggleContext.Provider value={{ currentTheme, onChangeTheme: handleChangeTheme }}>
<ThemeToggleContext.Provider value={{ currentTheme, onChangeTheme: handleChangeTheme, themes }}>
{children}
</ThemeToggleContext.Provider>
);

View File

@ -12,9 +12,9 @@ import {
} from '@strapi/helper-plugin';
import { useIntl } from 'react-intl';
import { Formik } from 'formik';
import upperFirst from 'lodash/upperFirst';
import { useQuery, useMutation, useQueryClient } from 'react-query';
import pick from 'lodash/pick';
import omit from 'lodash/omit';
import { Helmet } from 'react-helmet';
import { Main } from '@strapi/design-system/Main';
import { Typography } from '@strapi/design-system/Typography';
@ -31,6 +31,7 @@ import Eye from '@strapi/icons/Eye';
import EyeStriked from '@strapi/icons/EyeStriked';
import Check from '@strapi/icons/Check';
import useLocalesProvider from '../../components/LocalesProvider/useLocalesProvider';
import { useThemeToggle } from '../../hooks';
import { fetchUser, putUser } from './utils/api';
import schema from './utils/schema';
import { getFullName } from '../../utils';
@ -62,6 +63,7 @@ const ProfilePage = () => {
const toggleNotification = useNotification();
const { lockApp, unlockApp } = useOverlayBlocker();
const { notifyStatus } = useNotifyAT();
const { currentTheme, themes: allApplicationThemes, onChangeTheme } = useThemeToggle();
useFocusWhenNavigate();
const { status, data } = useQuery('user', () => fetchUser(), {
@ -83,14 +85,17 @@ const ProfilePage = () => {
const isLoading = status !== 'success';
const submitMutation = useMutation(body => putUser(omit(body, 'confirmPassword')), {
const submitMutation = useMutation(body => putUser(body), {
onSuccess: async data => {
await queryClient.invalidateQueries('user');
auth.setUserInfo(data);
auth.setUserInfo(
pick(data, ['email', 'firstname', 'lastname', 'username', 'preferedLanguage'])
);
const userDisplayName = data.username || getFullName(data.firstname, data.lastname);
setUserDisplayName(userDisplayName);
changeLocale(data.preferedLanguage);
onChangeTheme(data.currentTheme);
toggleNotification({
type: 'success',
@ -128,9 +133,16 @@ const ProfilePage = () => {
);
};
const fieldsToPick = ['email', 'firstname', 'lastname', 'username', 'preferedLanguage'];
const fieldsToPick = [
'currentTheme',
'email',
'firstname',
'lastname',
'username',
'preferedLanguage',
];
const initialData = pick(data, fieldsToPick);
const initialData = pick({ ...data, currentTheme }, fieldsToPick);
if (isLoading) {
return (
@ -154,6 +166,10 @@ const ProfilePage = () => {
);
}
const themesToDisplay = Object.keys(allApplicationThemes).filter(
themeName => allApplicationThemes[themeName]
);
return (
<Main aria-busy={isSubmittingForm}>
<Helmet
@ -487,6 +503,47 @@ const ProfilePage = () => {
})}
</Select>
</GridItem>
<GridItem s={12} col={6}>
<Select
label={formatMessage({
id: 'Settings.profile.form.section.experience.mode.label',
defaultMessage: 'Interface mode',
})}
placeholder={formatMessage({
id: 'components.Select.placeholder',
defaultMessage: 'Select',
})}
hint={formatMessage({
id: 'Settings.profile.form.section.experience.mode.hint',
defaultMessage: 'Displays your interface in the chosen mode.',
})}
value={values.currentTheme}
onChange={e => {
handleChange({
target: { name: 'currentTheme', value: e },
});
}}
>
{themesToDisplay.map(theme => {
const label = formatMessage(
{
id:
'Settings.profile.form.section.experience.mode.option-label',
defaultMessage: '{name} mode',
},
{
name: upperFirst(theme),
}
);
return (
<Option value={theme} key={theme}>
{label}
</Option>
);
})}
</Select>
</GridItem>
</Grid>
</Stack>
</Box>

View File

@ -1,3 +1,4 @@
import omit from 'lodash/omit';
import { axiosInstance } from '../../../core/utils';
const fetchUser = async () => {
@ -7,9 +8,10 @@ const fetchUser = async () => {
};
const putUser = async body => {
const { data } = await axiosInstance.put('/admin/users/me', body);
const dataToSend = omit(body, ['confirmPassword', 'currentTheme']);
const { data } = await axiosInstance.put('/admin/users/me', dataToSend);
return data.data;
return { ...data.data, currentTheme: body.currentTheme };
};
export { fetchUser, putUser };

View File

@ -137,6 +137,9 @@
"Settings.profile.form.section.experience.interfaceLanguage": "Interface language",
"Settings.profile.form.section.experience.interfaceLanguage.hint": "This will only display your own interface in the chosen language.",
"Settings.profile.form.section.experience.interfaceLanguageHelp": "Selection will change the interface language only for you. Please refer to this {documentation} to make other languages available for your team.",
"Settings.profile.form.section.experience.mode.label": "Interface mode",
"Settings.profile.form.section.experience.mode.hint": "Displays your interface in the chosen mode.",
"Settings.profile.form.section.experience.mode.option-label": "{name} mode",
"Settings.profile.form.section.experience.title": "Experience",
"Settings.profile.form.section.helmet.title": "User profile",
"Settings.profile.form.section.password.title": "Change password",