mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-31 13:47:02 +02:00
refactor: port UserProfile to TS/SWR (#665)
* refactor: add missing @types/react-outside-click-handler * refactor: add missing disablePasswordAuth IUiConfig field * refactor: replace NBSPs with regular spaces * refactor: port UserProfile to TS/SWR * refactor: fix interface type prefix Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
This commit is contained in:
parent
c4efaf8276
commit
dfe8250c26
@ -49,6 +49,7 @@
|
|||||||
"@types/node": "14.18.10",
|
"@types/node": "14.18.10",
|
||||||
"@types/react": "17.0.39",
|
"@types/react": "17.0.39",
|
||||||
"@types/react-dom": "17.0.11",
|
"@types/react-dom": "17.0.11",
|
||||||
|
"@types/react-outside-click-handler": "^1.3.1",
|
||||||
"@types/react-router-dom": "5.3.3",
|
"@types/react-router-dom": "5.3.3",
|
||||||
"@types/react-test-renderer": "17.0.1",
|
"@types/react-test-renderer": "17.0.1",
|
||||||
"@types/react-timeago": "4.1.3",
|
"@types/react-timeago": "4.1.3",
|
||||||
|
@ -15,8 +15,8 @@ import useToast from '../../../hooks/useToast';
|
|||||||
|
|
||||||
const PasswordAuthSettings = () => {
|
const PasswordAuthSettings = () => {
|
||||||
|
|
||||||
const { setToastData } = useToast();
|
const { setToastData } = useToast();
|
||||||
const { config } = useAuthSettings('simple');
|
const { config } = useAuthSettings('simple');
|
||||||
const [disablePasswordAuth, setDisablePasswordAuth] = useState<boolean>(false);
|
const [disablePasswordAuth, setDisablePasswordAuth] = useState<boolean>(false);
|
||||||
const { updateSettings, errors, loading } = useAuthSettingsApi<ISimpleAuthSettings>('simple')
|
const { updateSettings, errors, loading } = useAuthSettingsApi<ISimpleAuthSettings>('simple')
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
@ -24,7 +24,7 @@ const PasswordAuthSettings = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDisablePasswordAuth(!!config.disabled);
|
setDisablePasswordAuth(!!config.disabled);
|
||||||
}, [ config.disabled ]);
|
}, [ config.disabled ]);
|
||||||
|
|
||||||
if (!hasAccess(ADMIN)) {
|
if (!hasAccess(ADMIN)) {
|
||||||
return (
|
return (
|
||||||
@ -38,10 +38,10 @@ const PasswordAuthSettings = () => {
|
|||||||
setDisablePasswordAuth(!disablePasswordAuth);
|
setDisablePasswordAuth(!disablePasswordAuth);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const onSubmit = async evt => {
|
const onSubmit = async evt => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const settings: ISimpleAuthSettings = { disabled: disablePasswordAuth };
|
const settings: ISimpleAuthSettings = { disabled: disablePasswordAuth };
|
||||||
await updateSettings(settings);
|
await updateSettings(settings);
|
||||||
@ -62,7 +62,7 @@ const PasswordAuthSettings = () => {
|
|||||||
});
|
});
|
||||||
setDisablePasswordAuth(config.disabled)
|
setDisablePasswordAuth(config.disabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<PageContent headerContent=''>
|
<PageContent headerContent=''>
|
||||||
|
@ -8,15 +8,20 @@ import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
|||||||
import { useStyles } from './UserProfile.styles';
|
import { useStyles } from './UserProfile.styles';
|
||||||
import { useCommonStyles } from '../../../common.styles';
|
import { useCommonStyles } from '../../../common.styles';
|
||||||
import UserProfileContent from './UserProfileContent/UserProfileContent';
|
import UserProfileContent from './UserProfileContent/UserProfileContent';
|
||||||
|
import { IUser } from "../../../interfaces/user";
|
||||||
|
|
||||||
|
interface IUserProfileProps {
|
||||||
|
profile: IUser
|
||||||
|
updateSettingLocation: (field: 'locale', value: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
const UserProfile = ({
|
const UserProfile = ({
|
||||||
profile,
|
profile,
|
||||||
location,
|
location,
|
||||||
fetchUser,
|
|
||||||
updateSettingLocation,
|
updateSettingLocation,
|
||||||
}) => {
|
}: IUserProfileProps) => {
|
||||||
const [showProfile, setShowProfile] = useState(false);
|
const [showProfile, setShowProfile] = useState(false);
|
||||||
const [currentLocale, setCurrentLocale] = useState([]);
|
const [currentLocale, setCurrentLocale] = useState<string>();
|
||||||
|
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
const commonStyles = useCommonStyles();
|
const commonStyles = useCommonStyles();
|
||||||
@ -35,8 +40,7 @@ const UserProfile = ({
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchUser();
|
const locale = location.locale || navigator.language;
|
||||||
const locale = navigator.language || navigator.userLanguage;
|
|
||||||
let found = possibleLocales.find(l =>
|
let found = possibleLocales.find(l =>
|
||||||
l.toLowerCase().includes(locale.toLowerCase())
|
l.toLowerCase().includes(locale.toLowerCase())
|
||||||
);
|
);
|
||||||
@ -73,7 +77,6 @@ const UserProfile = ({
|
|||||||
profile={profile}
|
profile={profile}
|
||||||
updateSettingLocation={updateSettingLocation}
|
updateSettingLocation={updateSettingLocation}
|
||||||
possibleLocales={possibleLocales}
|
possibleLocales={possibleLocales}
|
||||||
location={location}
|
|
||||||
setCurrentLocale={setCurrentLocale}
|
setCurrentLocale={setCurrentLocale}
|
||||||
currentLocale={currentLocale}
|
currentLocale={currentLocale}
|
||||||
/>
|
/>
|
||||||
@ -85,7 +88,6 @@ const UserProfile = ({
|
|||||||
UserProfile.propTypes = {
|
UserProfile.propTypes = {
|
||||||
profile: PropTypes.object,
|
profile: PropTypes.object,
|
||||||
location: PropTypes.object,
|
location: PropTypes.object,
|
||||||
fetchUser: PropTypes.func.isRequired,
|
|
||||||
updateSettingLocation: PropTypes.func.isRequired,
|
updateSettingLocation: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import ConditionallyRender from '../../../common/ConditionallyRender';
|
import ConditionallyRender from '../../../common/ConditionallyRender';
|
||||||
import {
|
import {
|
||||||
Paper,
|
Paper,
|
||||||
@ -17,6 +17,17 @@ import EditProfile from '../EditProfile/EditProfile';
|
|||||||
import legacyStyles from '../../user.module.scss';
|
import legacyStyles from '../../user.module.scss';
|
||||||
import { getBasePath } from '../../../../utils/format-path';
|
import { getBasePath } from '../../../../utils/format-path';
|
||||||
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
|
import { IUser } from "../../../../interfaces/user";
|
||||||
|
|
||||||
|
interface IUserProfileContentProps {
|
||||||
|
showProfile: boolean
|
||||||
|
profile: IUser
|
||||||
|
possibleLocales: string[]
|
||||||
|
updateSettingLocation: (field: 'locale', value: string) => void
|
||||||
|
imageUrl: string
|
||||||
|
currentLocale?: string
|
||||||
|
setCurrentLocale: (value: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
const UserProfileContent = ({
|
const UserProfileContent = ({
|
||||||
showProfile,
|
showProfile,
|
||||||
@ -26,27 +37,31 @@ const UserProfileContent = ({
|
|||||||
imageUrl,
|
imageUrl,
|
||||||
currentLocale,
|
currentLocale,
|
||||||
setCurrentLocale,
|
setCurrentLocale,
|
||||||
}) => {
|
}: IUserProfileContentProps) => {
|
||||||
const commonStyles = useCommonStyles();
|
const commonStyles = useCommonStyles();
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
const [updatedPassword, setUpdatedPassword] = useState(false);
|
const [updatedPassword, setUpdatedPassword] = useState(false);
|
||||||
const [edititingProfile, setEditingProfile] = useState(false);
|
const [editingProfile, setEditingProfile] = useState(false);
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
|
||||||
const setLocale = value => {
|
const setLocale = (value: string) => {
|
||||||
updateSettingLocation('locale', value);
|
updateSettingLocation('locale', value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
const profileAvatarClasses = classnames(styles.avatar, {
|
const profileAvatarClasses = classnames(styles.avatar, {
|
||||||
[styles.editingAvatar]: edititingProfile,
|
// @ts-expect-error
|
||||||
|
[styles.editingAvatar]: editingProfile,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
const profileEmailClasses = classnames(styles.profileEmail, {
|
const profileEmailClasses = classnames(styles.profileEmail, {
|
||||||
[styles.editingEmail]: edititingProfile,
|
// @ts-expect-error
|
||||||
|
[styles.editingEmail]: editingProfile,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleChange = e => {
|
const handleChange = (e: React.ChangeEvent<{ value: unknown }>) => {
|
||||||
const { value } = e.target;
|
const value = e.target.value as string;
|
||||||
setCurrentLocale(value);
|
setCurrentLocale(value);
|
||||||
setLocale(value);
|
setLocale(value);
|
||||||
};
|
};
|
||||||
@ -57,6 +72,7 @@ const UserProfileContent = ({
|
|||||||
show={
|
show={
|
||||||
<Paper
|
<Paper
|
||||||
className={classnames(
|
className={classnames(
|
||||||
|
// @ts-expect-error
|
||||||
styles.profile,
|
styles.profile,
|
||||||
commonStyles.flexColumn,
|
commonStyles.flexColumn,
|
||||||
commonStyles.itemsCenter,
|
commonStyles.itemsCenter,
|
||||||
@ -80,7 +96,7 @@ const UserProfileContent = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={!edititingProfile}
|
condition={!editingProfile}
|
||||||
show={
|
show={
|
||||||
<>
|
<>
|
||||||
<ConditionallyRender condition={!uiConfig.disablePasswordAuth} show={
|
<ConditionallyRender condition={!uiConfig.disablePasswordAuth} show={
|
||||||
@ -133,6 +149,7 @@ const UserProfileContent = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className={commonStyles.divider} />
|
<div className={commonStyles.divider} />
|
||||||
<a
|
<a
|
||||||
|
// @ts-expect-error
|
||||||
className={styles.link}
|
className={styles.link}
|
||||||
href="https://www.getunleash.io/privacy-policy"
|
href="https://www.getunleash.io/privacy-policy"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
@ -1,16 +1,27 @@
|
|||||||
|
import useUser from '../../../hooks/api/getters/useUser/useUser';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import UserProfile from './UserProfile';
|
import UserProfile from './UserProfile';
|
||||||
import { fetchUser } from '../../../store/user/actions';
|
|
||||||
import { updateSettingForGroup } from '../../../store/settings/actions';
|
import { updateSettingForGroup } from '../../../store/settings/actions';
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
fetchUser,
|
|
||||||
updateSettingLocation: updateSettingForGroup('location'),
|
updateSettingLocation: updateSettingForGroup('location'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
profile: state.user.get('profile'),
|
|
||||||
location: state.settings ? state.settings.toJS().location : {},
|
location: state.settings ? state.settings.toJS().location : {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(UserProfile);
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(props => {
|
||||||
|
const user = useUser();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<UserProfile
|
||||||
|
location={props.location}
|
||||||
|
updateSettingLocation={props.updateSettingLocation}
|
||||||
|
profile={user.user}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
@ -8,6 +8,7 @@ export interface IUiConfig {
|
|||||||
version: string;
|
version: string;
|
||||||
versionInfo: IVersionInfo;
|
versionInfo: IVersionInfo;
|
||||||
links: ILinks[];
|
links: ILinks[];
|
||||||
|
disablePasswordAuth?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFlags {
|
export interface IFlags {
|
||||||
|
@ -2,13 +2,13 @@ import { fromJS } from 'immutable';
|
|||||||
import { UPDATE_SETTING } from './actions';
|
import { UPDATE_SETTING } from './actions';
|
||||||
import { USER_LOGOUT, USER_LOGIN } from '../user/actions';
|
import { USER_LOGOUT, USER_LOGIN } from '../user/actions';
|
||||||
|
|
||||||
import { getBasePath } from '../../utils/format-path';
|
import { getBasePath } from '../../utils/format-path';
|
||||||
|
|
||||||
const localStorage = window.localStorage || {
|
const localStorage = window.localStorage || {
|
||||||
setItem: () => {},
|
setItem: () => {},
|
||||||
getItem: () => {},
|
getItem: () => {},
|
||||||
};
|
};
|
||||||
const basePath = getBasePath();
|
const basePath = getBasePath();
|
||||||
const SETTINGS = `${basePath}:settings`;
|
const SETTINGS = `${basePath}:settings`;
|
||||||
|
|
||||||
const DEFAULT = fromJS({ location: {} });
|
const DEFAULT = fromJS({ location: {} });
|
||||||
|
@ -2129,6 +2129,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
|
"@types/react-outside-click-handler@^1.3.1":
|
||||||
|
version "1.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-outside-click-handler/-/react-outside-click-handler-1.3.1.tgz#e4772ba550e1a548468203194d2615d8f06acdf9"
|
||||||
|
integrity sha512-0BNan5zIIDyO5k9LFSG+60ZxQ/0wf+LTF9BJx3oOUdOaJlZk6RCe52jRB75mlvLLJx2YLa61+NidOwBfptWMKw==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react-redux@^7.1.20":
|
"@types/react-redux@^7.1.20":
|
||||||
version "7.1.20"
|
version "7.1.20"
|
||||||
resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz"
|
resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz"
|
||||||
|
Loading…
Reference in New Issue
Block a user