diff --git a/packages/strapi-admin/admin/src/containers/Admin/index.js b/packages/strapi-admin/admin/src/containers/Admin/index.js
index 807be32aee..6696983a68 100644
--- a/packages/strapi-admin/admin/src/containers/Admin/index.js
+++ b/packages/strapi-admin/admin/src/containers/Admin/index.js
@@ -31,7 +31,7 @@ import Header from '../../components/Header/index';
import NavTopRightWrapper from '../../components/NavTopRightWrapper';
import LeftMenu from '../LeftMenu';
import InstalledPluginsPage from '../InstalledPluginsPage';
-import LocaleToggle from '../LocaleToggle';
+
import HomePage from '../HomePage';
import MarketplacePage from '../MarketplacePage';
import NotFoundPage from '../NotFoundPage';
@@ -292,7 +292,6 @@ export class Admin extends React.Component {
{/* Injection zone not ready yet */}
-
diff --git a/packages/strapi-admin/admin/src/containers/LanguageProvider/hooks/useLanguages.js b/packages/strapi-admin/admin/src/containers/LanguageProvider/hooks/useLanguages.js
new file mode 100644
index 0000000000..8bcbe775a9
--- /dev/null
+++ b/packages/strapi-admin/admin/src/containers/LanguageProvider/hooks/useLanguages.js
@@ -0,0 +1,15 @@
+import { useSelector, useDispatch } from 'react-redux';
+import { changeLocale } from '../actions';
+
+const languageSelector = state => state.get('language').toJS();
+
+const useLanguages = () => {
+ const { locale } = useSelector(languageSelector);
+ const dispatch = useDispatch();
+
+ const selectLanguage = nextLocale => dispatch(changeLocale(nextLocale));
+
+ return { currentLanguage: locale, selectLanguage };
+};
+
+export default useLanguages;
diff --git a/packages/strapi-admin/admin/src/containers/ProfilePage/components.js b/packages/strapi-admin/admin/src/containers/ProfilePage/components.js
new file mode 100644
index 0000000000..c83041daf2
--- /dev/null
+++ b/packages/strapi-admin/admin/src/containers/ProfilePage/components.js
@@ -0,0 +1,11 @@
+import styled from 'styled-components';
+import { Label, Text } from '@buffetjs/core';
+
+export const Title = styled(Text)`
+ text-transform: uppercase;
+ color: ${({ theme }) => theme.main.colors.grey};
+`;
+
+export const ProfilePageLabel = styled(Label)`
+ margin-bottom: 1rem;
+`;
diff --git a/packages/strapi-admin/admin/src/containers/ProfilePage/index.js b/packages/strapi-admin/admin/src/containers/ProfilePage/index.js
index 727072313c..d5a62ec8fa 100644
--- a/packages/strapi-admin/admin/src/containers/ProfilePage/index.js
+++ b/packages/strapi-admin/admin/src/containers/ProfilePage/index.js
@@ -1,22 +1,32 @@
import React, { useMemo } from 'react';
-import { BackHeader, BaselineAlignment, auth } from 'strapi-helper-plugin';
+import { BackHeader, BaselineAlignment, auth, Select, Option, Row } from 'strapi-helper-plugin';
+import { Padded, Text } from '@buffetjs/core';
+import { Col } from 'reactstrap';
import { useHistory } from 'react-router-dom';
import { get } from 'lodash';
+import { useIntl } from 'react-intl';
import ContainerFluid from '../../components/ContainerFluid';
-import FormBloc from '../../components/FormBloc';
+import PageTitle from '../../components/PageTitle';
import SizedInput from '../../components/SizedInput';
import { Header } from '../../components/Settings';
import { useSettingsForm } from '../../hooks';
import { form, schema } from './utils';
+import useLanguages from '../LanguageProvider/hooks/useLanguages';
+import { languages, languageNativeNames } from '../../i18n';
+import { Title, ProfilePageLabel } from './components';
+import Bloc from '../../components/Bloc';
const ProfilePage = () => {
const { goBack } = useHistory();
+ const { currentLanguage, selectLanguage } = useLanguages();
+ const { formatMessage } = useIntl();
+
const onSubmitSuccessCb = data => auth.setUserInfo(data);
const [
{ formErrors, initialData, isLoading, modifiedData, showHeaderLoader, showHeaderButtonLoader },
// eslint-disable-next-line no-unused-vars
- dispatch,
+ _,
{ handleCancel, handleChange, handleSubmit },
] = useSettingsForm('/admin/users/me', schema, onSubmitSuccessCb, [
'email',
@@ -37,9 +47,13 @@ const ProfilePage = () => {
return (
<>
+
+
+
+
>
);
diff --git a/packages/strapi-admin/admin/src/containers/ProfilePage/utils/form.js b/packages/strapi-admin/admin/src/containers/ProfilePage/utils/form.js
index 55720667bf..99c25c232e 100644
--- a/packages/strapi-admin/admin/src/containers/ProfilePage/utils/form.js
+++ b/packages/strapi-admin/admin/src/containers/ProfilePage/utils/form.js
@@ -31,17 +31,6 @@ const form = {
autoComplete: 'no',
validations: {},
},
- password: {
- label: 'Auth.form.password.label',
- type: 'password',
- autoComplete: 'new-password',
- validations: {},
- },
- confirmPassword: {
- label: 'Auth.form.confirmPassword.label',
- type: 'password',
- validations: {},
- },
};
export default form;
diff --git a/packages/strapi-admin/admin/src/containers/Users/EditPage/index.js b/packages/strapi-admin/admin/src/containers/Users/EditPage/index.js
index 430de82151..062331bb7f 100644
--- a/packages/strapi-admin/admin/src/containers/Users/EditPage/index.js
+++ b/packages/strapi-admin/admin/src/containers/Users/EditPage/index.js
@@ -99,7 +99,9 @@ const EditPage = ({ canUpdate }) => {
);
})}
+
+
{!isLoading && (
{
+ const theme = useTheme();
+
+ return (
+
+
+
+ );
+};
+
+export const Select = ({ children, onChange, selectedValue, ...props }) => {
+ const theme = useTheme();
+ const selectStyles = getStyles(theme);
+ const childrenArray = React.Children.toArray(children);
+
+ const options = childrenArray.map(child => ({
+ value: child.props.value,
+ label: child.props.children,
+ }));
+
+ const selectedOption = options.find(({ value }) => value === selectedValue);
+
+ return (
+ onChange(value)}
+ components={{ DropdownIndicator }}
+ styles={selectStyles}
+ value={selectedOption}
+ />
+ );
+};
+
+/**
+ * Do not remove this component.
+ * The Select component is a mimic of the select HTML element:
+ * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select
+ * The Select component will map over its "Option" components and verify their
+ * "value" in order to pass them down to react-select
+ */
+export const Option = () => <>>;
+
+Select.defaultProps = {
+ selectedValue: undefined,
+};
+
+Select.propTypes = {
+ children: PropTypes.node.isRequired,
+ onChange: PropTypes.func.isRequired,
+ selectedValue: PropTypes.string,
+};
diff --git a/packages/strapi-helper-plugin/lib/src/components/Select/styles.js b/packages/strapi-helper-plugin/lib/src/components/Select/styles.js
new file mode 100644
index 0000000000..f5f56f2c19
--- /dev/null
+++ b/packages/strapi-helper-plugin/lib/src/components/Select/styles.js
@@ -0,0 +1,116 @@
+/* eslint-disable indent */
+/* eslint-disable no-nested-ternary */
+
+const getStyles = theme => {
+ const { colors, fontWeights, sizes } = theme.main;
+
+ // Colors that does not exist in the theme.main.colors
+ const unknownLightGrey = `#f6f6f6`;
+ const unknownGrey = `#aaa`;
+ const unknownLightblue = `#78caff`;
+
+ // Sizes that does not exist in the theme.main.sizes
+ const unknownBorderSize1 = `1px`;
+ const optionHeight = `36px`;
+ const controlMinHeight = `34px`;
+
+ return {
+ container: base => ({
+ ...base,
+ width: '100%',
+ }),
+ control: (base, state) => {
+ const {
+ selectProps: { error, value },
+ } = state;
+
+ let border;
+ let borderBottom;
+ let backgroundColor;
+
+ if (state.isFocused) {
+ border = `${unknownBorderSize1} solid ${unknownLightblue} !important`;
+ } else if (error && !value.length) {
+ border = `${unknownBorderSize1} solid ${colors.lightOrange} !important`;
+ } else {
+ border = `${unknownBorderSize1} solid ${colors.border} !important`;
+ }
+
+ if (state.menuIsOpen === true) {
+ borderBottom = `${unknownBorderSize1} solid ${colors.border} !important`;
+ }
+
+ if (state.isDisabled) {
+ backgroundColor = `${colors.content.background} !important`;
+ }
+
+ return {
+ ...base,
+ fontSize: sizes.fonts.md,
+ minHeight: controlMinHeight,
+ border,
+ outline: 0,
+ boxShadow: 0,
+ borderRadius: `${sizes.borderRadius} !important`,
+ borderBottom,
+ backgroundColor,
+ width: '100%',
+ };
+ },
+ menu: base => ({
+ ...base,
+ width: '100%',
+ margin: '0',
+ paddingTop: 0,
+ borderRadius: `${sizes.borderRadius} !important`,
+ borderTopLeftRadius: '0 !important',
+ borderTopRightRadius: '0 !important',
+ border: `${unknownBorderSize1} solid ${unknownLightblue} !important`,
+ boxShadow: 0,
+ borderTop: '0 !important',
+ fontSize: sizes.fonts.md,
+ }),
+ menuList: base => ({
+ ...base,
+ maxHeight: '112px',
+ paddingTop: sizes.borderRadius,
+ }),
+ option: (base, state) => ({
+ ...base,
+ height: optionHeight,
+
+ backgroundColor: state.isFocused ? unknownLightGrey : colors.white,
+ ':active': {
+ ...base[':active'],
+ backgroundColor: unknownLightGrey,
+ },
+ WebkitFontSmoothing: 'antialiased',
+ color: colors.black,
+ fontWeight: state.isFocused ? fontWeights.bold : fontWeights.regular,
+ cursor: 'pointer',
+ }),
+ placeholder: base => ({
+ ...base,
+ marginTop: 0,
+ color: unknownGrey,
+ }),
+ valueContainer: base => ({
+ ...base,
+ padding: '2px 4px 4px 4px', // These value don't exist in the theme
+ fontSize: sizes.fonts.md,
+ }),
+ indicatorsContainer: base => ({
+ ...base,
+ width: '32px',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ background: colors.content.background,
+ }),
+ indicatorSeparator: () => ({
+ display: 'none',
+ }),
+ };
+};
+
+export default getStyles;
diff --git a/packages/strapi-helper-plugin/lib/src/index.js b/packages/strapi-helper-plugin/lib/src/index.js
index 74d286b69a..f10895ac0d 100644
--- a/packages/strapi-helper-plugin/lib/src/index.js
+++ b/packages/strapi-helper-plugin/lib/src/index.js
@@ -26,6 +26,7 @@ export { default as IcoContainer } from './components/IcoContainer';
export { default as InputAddon } from './components/InputAddon';
export { default as EmptyState } from './components/EmptyState';
export * from './components/Tabs';
+export * from './components/Select';
export { default as InputAddonWithErrors } from './components/InputAddonWithErrors';
export { default as InputCheckbox } from './components/InputCheckbox';