1
0
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:
olav 2022-02-04 12:41:59 +01:00 committed by GitHub
parent c4efaf8276
commit dfe8250c26
8 changed files with 67 additions and 28 deletions

View File

@ -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",

View File

@ -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=''>

View File

@ -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,
}; };

View File

@ -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"

View File

@ -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}
/>
);
});

View File

@ -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 {

View File

@ -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: {} });

View File

@ -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"