mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-08 01:15:49 +02:00
refactor: port global settings to TS/hooks (#679)
* refactor: add ref support to PermissionSwitch * refactor: port global settings to TS/hooks * refactor: fix file extension * refactor: format file * refactor: fix inconsistent locationSettings prop * refactor: use correct locationSettings hook * refactor: use objects for settings hooks
This commit is contained in:
parent
36f59b2290
commit
fee1894c34
@ -31,6 +31,7 @@ import Dialogue from '../../../common/Dialogue';
|
||||
import { CREATE_API_TOKEN_BUTTON } from '../../../../testIds';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { useLocationSettings } from "../../../../hooks/useLocationSettings";
|
||||
|
||||
interface IApiToken {
|
||||
createdAt: Date;
|
||||
@ -41,16 +42,13 @@ interface IApiToken {
|
||||
environment: string;
|
||||
}
|
||||
|
||||
interface IApiTokenList {
|
||||
location: any;
|
||||
}
|
||||
|
||||
const ApiTokenList = ({ location }: IApiTokenList) => {
|
||||
const ApiTokenList = () => {
|
||||
const styles = useStyles();
|
||||
const { hasAccess } = useContext(AccessContext);
|
||||
const { uiConfig } = useUiConfig();
|
||||
const [showDelete, setShowDelete] = useState(false);
|
||||
const [delToken, setDeleteToken] = useState<IApiToken>();
|
||||
const { locationSettings } = useLocationSettings()
|
||||
const { setToastData } = useToast();
|
||||
const { tokens, loading, refetch, error } = useApiTokens();
|
||||
const { deleteToken } = useApiTokensApi();
|
||||
@ -150,7 +148,7 @@ const ApiTokenList = ({ location }: IApiTokenList) => {
|
||||
>
|
||||
{formatDateWithLocale(
|
||||
item.createdAt,
|
||||
location.locale
|
||||
locationSettings.locale
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
|
@ -5,7 +5,7 @@ import AdminMenu from '../menu/AdminMenu';
|
||||
import usePermissions from '../../../hooks/usePermissions';
|
||||
import ConditionallyRender from '../../common/ConditionallyRender';
|
||||
|
||||
const ApiPage = ({ history, location }) => {
|
||||
const ApiPage = ({ history }) => {
|
||||
const { isAdmin } = usePermissions();
|
||||
|
||||
return (
|
||||
@ -14,7 +14,7 @@ const ApiPage = ({ history, location }) => {
|
||||
condition={isAdmin()}
|
||||
show={<AdminMenu history={history} />}
|
||||
/>
|
||||
<ApiTokenList location={location} />
|
||||
<ApiTokenList />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -22,7 +22,6 @@ const ApiPage = ({ history, location }) => {
|
||||
ApiPage.propTypes = {
|
||||
match: PropTypes.object.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
location: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ApiPage;
|
||||
|
@ -14,15 +14,15 @@ import HeaderTitle from '../../common/HeaderTitle';
|
||||
import ConditionallyRender from '../../common/ConditionallyRender';
|
||||
import { formatApiPath } from '../../../utils/format-path';
|
||||
import useInvoices from '../../../hooks/api/getters/useInvoices/useInvoices';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { IInvoice } from '../../../interfaces/invoice';
|
||||
import { useLocationSettings } from '../../../hooks/useLocationSettings';
|
||||
|
||||
const PORTAL_URL = formatApiPath('api/admin/invoices/portal');
|
||||
|
||||
const InvoiceList = () => {
|
||||
const { refetchInvoices, invoices } = useInvoices();
|
||||
const [isLoaded, setLoaded] = useState(false);
|
||||
const location = useLocation();
|
||||
const { locationSettings } = useLocationSettings();
|
||||
|
||||
useEffect(() => {
|
||||
refetchInvoices();
|
||||
@ -89,7 +89,7 @@ const InvoiceList = () => {
|
||||
{item.dueDate &&
|
||||
formatDateWithLocale(
|
||||
item.dueDate,
|
||||
location.locale
|
||||
locationSettings.locale
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
|
@ -14,6 +14,7 @@ import AccessContext from '../../../../../contexts/AccessContext';
|
||||
import { IUser } from '../../../../../interfaces/user';
|
||||
import { useStyles } from './UserListItem.styles';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { ILocationSettings } from "../../../../../hooks/useLocationSettings";
|
||||
|
||||
interface IUserListItemProps {
|
||||
user: IUser;
|
||||
@ -21,11 +22,7 @@ interface IUserListItemProps {
|
||||
openUpdateDialog: (user: IUser) => (e: SyntheticEvent) => void;
|
||||
openPwDialog: (user: IUser) => (e: SyntheticEvent) => void;
|
||||
openDelDialog: (user: IUser) => (e: SyntheticEvent) => void;
|
||||
location: ILocation;
|
||||
}
|
||||
|
||||
interface ILocation {
|
||||
locale: string;
|
||||
locationSettings: ILocationSettings;
|
||||
}
|
||||
|
||||
const UserListItem = ({
|
||||
@ -34,7 +31,7 @@ const UserListItem = ({
|
||||
openDelDialog,
|
||||
openPwDialog,
|
||||
openUpdateDialog,
|
||||
location,
|
||||
locationSettings,
|
||||
}: IUserListItemProps) => {
|
||||
const { hasAccess } = useContext(AccessContext);
|
||||
const history = useHistory()
|
||||
@ -54,7 +51,7 @@ const UserListItem = ({
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<span data-loading>
|
||||
{formatDateWithLocale(user.createdAt, location.locale)}
|
||||
{formatDateWithLocale(user.createdAt, locationSettings.locale)}
|
||||
</span>
|
||||
</TableCell>
|
||||
<TableCell className={styles.leftTableCell}>
|
||||
|
@ -20,10 +20,10 @@ import loadingData from './loadingData';
|
||||
import useLoading from '../../../../hooks/useLoading';
|
||||
import usePagination from '../../../../hooks/usePagination';
|
||||
import PaginateUI from '../../../common/PaginateUI/PaginateUI';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { IUser } from '../../../../interfaces/user';
|
||||
import IRole from '../../../../interfaces/role';
|
||||
import useToast from '../../../../hooks/useToast';
|
||||
import { useLocationSettings } from "../../../../hooks/useLocationSettings";
|
||||
|
||||
const UsersList = () => {
|
||||
const { users, roles, refetch, loading } = useUsers();
|
||||
@ -35,9 +35,8 @@ const UsersList = () => {
|
||||
userLoading,
|
||||
userApiErrors,
|
||||
} = useAdminUsersApi();
|
||||
const history = useHistory();
|
||||
const { location } = history;
|
||||
const { hasAccess } = useContext(AccessContext);
|
||||
const { locationSettings } = useLocationSettings()
|
||||
const [pwDialog, setPwDialog] = useState<{ open: boolean; user?: IUser }>({
|
||||
open: false,
|
||||
});
|
||||
@ -104,7 +103,7 @@ const UsersList = () => {
|
||||
user={user}
|
||||
openPwDialog={openPwDialog}
|
||||
openDelDialog={openDelDialog}
|
||||
location={location}
|
||||
locationSettings={locationSettings}
|
||||
renderRole={renderRole}
|
||||
/>
|
||||
));
|
||||
@ -117,7 +116,7 @@ const UsersList = () => {
|
||||
user={user}
|
||||
openPwDialog={openPwDialog}
|
||||
openDelDialog={openDelDialog}
|
||||
location={location}
|
||||
locationSettings={locationSettings}
|
||||
renderRole={renderRole}
|
||||
/>
|
||||
);
|
||||
|
@ -19,6 +19,7 @@ test('renders correctly if no application', () => {
|
||||
storeApplicationMetaData={jest.fn()}
|
||||
deleteApplication={jest.fn()}
|
||||
history={{}}
|
||||
locationSettings={{ locale: 'en-GB' }}
|
||||
/>
|
||||
</AccessProvider>
|
||||
)
|
||||
@ -77,7 +78,7 @@ test('renders correctly without permission', () => {
|
||||
url: 'http://example.org',
|
||||
description: 'app description',
|
||||
}}
|
||||
location={{ locale: 'en-GB' }}
|
||||
locationSettings={{ locale: 'en-GB' }}
|
||||
/>
|
||||
</AccessProvider>
|
||||
</ThemeProvider>
|
||||
@ -140,7 +141,7 @@ test('renders correctly with permissions', () => {
|
||||
url: 'http://example.org',
|
||||
description: 'app description',
|
||||
}}
|
||||
location={{ locale: 'en-GB' }}
|
||||
locationSettings={{ locale: 'en-GB' }}
|
||||
/>
|
||||
</AccessProvider>
|
||||
</ThemeProvider>
|
||||
|
@ -33,7 +33,7 @@ class ClientApplications extends PureComponent {
|
||||
fetchApplication: PropTypes.func.isRequired,
|
||||
appName: PropTypes.string,
|
||||
application: PropTypes.object,
|
||||
location: PropTypes.object,
|
||||
locationSettings: PropTypes.object.isRequired,
|
||||
storeApplicationMetaData: PropTypes.func.isRequired,
|
||||
deleteApplication: PropTypes.func.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
@ -54,8 +54,8 @@ class ClientApplications extends PureComponent {
|
||||
.finally(() => this.setState({ loading: false }));
|
||||
}
|
||||
formatFullDateTime = v =>
|
||||
formatFullDateTimeWithLocale(v, this.props.location.locale);
|
||||
formatDate = v => formatDateWithLocale(v, this.props.location.locale);
|
||||
formatFullDateTimeWithLocale(v, this.props.locationSettings.locale);
|
||||
formatDate = v => formatDateWithLocale(v, this.props.locationSettings.locale);
|
||||
|
||||
deleteApplication = async evt => {
|
||||
evt.preventDefault();
|
||||
|
@ -1,23 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import ApplicationEdit from './application-edit-component';
|
||||
import { fetchApplication, storeApplicationMetaData, deleteApplication } from './../../store/application/actions';
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
let application = state.applications.getIn(['apps', props.appName]);
|
||||
const location = state.settings.toJS().location || {};
|
||||
if (application) {
|
||||
application = application.toJS();
|
||||
}
|
||||
return {
|
||||
application,
|
||||
location,
|
||||
};
|
||||
};
|
||||
|
||||
const Container = connect(mapStateToProps, {
|
||||
fetchApplication,
|
||||
storeApplicationMetaData,
|
||||
deleteApplication,
|
||||
})(ApplicationEdit);
|
||||
|
||||
export default Container;
|
@ -0,0 +1,30 @@
|
||||
import { connect } from 'react-redux';
|
||||
import ApplicationEdit from './application-edit-component';
|
||||
import {
|
||||
deleteApplication,
|
||||
fetchApplication,
|
||||
storeApplicationMetaData,
|
||||
} from '../../store/application/actions';
|
||||
import { useLocationSettings } from '../../hooks/useLocationSettings';
|
||||
|
||||
const ApplicationEditContainer = props => {
|
||||
const { locationSettings } = useLocationSettings();
|
||||
|
||||
return <ApplicationEdit {...props} locationSettings={locationSettings} />;
|
||||
};
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
let application = state.applications.getIn(['apps', props.appName]);
|
||||
if (application) {
|
||||
application = application.toJS();
|
||||
}
|
||||
return {
|
||||
application,
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, {
|
||||
fetchApplication,
|
||||
storeApplicationMetaData,
|
||||
deleteApplication,
|
||||
})(ApplicationEditContainer);
|
@ -13,16 +13,21 @@ interface IPermissionSwitchProps extends OverridableComponent<any> {
|
||||
checked: boolean;
|
||||
}
|
||||
|
||||
const PermissionSwitch: React.FC<IPermissionSwitchProps> = ({
|
||||
permission,
|
||||
tooltip = '',
|
||||
disabled,
|
||||
projectId,
|
||||
environmentId,
|
||||
checked,
|
||||
onChange,
|
||||
...rest
|
||||
}) => {
|
||||
const PermissionSwitch = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
IPermissionSwitchProps
|
||||
>((props, ref) => {
|
||||
const {
|
||||
permission,
|
||||
tooltip = '',
|
||||
disabled,
|
||||
projectId,
|
||||
environmentId,
|
||||
checked,
|
||||
onChange,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const { hasAccess } = useContext(AccessContext);
|
||||
|
||||
let access;
|
||||
@ -45,11 +50,12 @@ const PermissionSwitch: React.FC<IPermissionSwitchProps> = ({
|
||||
onChange={onChange}
|
||||
disabled={disabled || !access}
|
||||
checked={checked}
|
||||
ref={ref}
|
||||
{...rest}
|
||||
/>
|
||||
</span>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default PermissionSwitch;
|
||||
|
@ -1,25 +1,21 @@
|
||||
import { Tooltip } from '@material-ui/core';
|
||||
import { connect } from 'react-redux';
|
||||
import { formatDateWithLocale, formatFullDateTimeWithLocale } from '../../../common/util';
|
||||
import { useLocationSettings } from "../../../../hooks/useLocationSettings";
|
||||
|
||||
interface CreatedAtProps {
|
||||
time: Date;
|
||||
//@ts-ignore
|
||||
location: any;
|
||||
}
|
||||
|
||||
const CreatedAt = ({time, location}: CreatedAtProps) => {
|
||||
const CreatedAt = ({time}: CreatedAtProps) => {
|
||||
const { locationSettings } = useLocationSettings();
|
||||
|
||||
return (
|
||||
<Tooltip title={`Created at ${formatFullDateTimeWithLocale(time, location.locale)}`}>
|
||||
<Tooltip title={`Created at ${formatFullDateTimeWithLocale(time, locationSettings.locale)}`}>
|
||||
<span>
|
||||
{formatDateWithLocale(time, location.locale)}
|
||||
{formatDateWithLocale(time, locationSettings.locale)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: any) => ({
|
||||
location: state.settings.toJS().location,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(CreatedAt);
|
||||
export default CreatedAt;
|
||||
|
@ -11,24 +11,21 @@ import EventCard from './EventCard/EventCard';
|
||||
import { useStyles } from './EventLog.styles.js';
|
||||
|
||||
const EventLog = ({
|
||||
updateSetting,
|
||||
title,
|
||||
history,
|
||||
settings,
|
||||
eventSettings,
|
||||
setEventSettings,
|
||||
locationSettings,
|
||||
displayInline,
|
||||
location,
|
||||
hideName,
|
||||
}) => {
|
||||
const styles = useStyles();
|
||||
const toggleShowDiff = () => {
|
||||
updateSetting('showData', !settings.showData);
|
||||
setEventSettings({ showData: !eventSettings.showData });
|
||||
};
|
||||
const formatFulldateTime = v => {
|
||||
return formatFullDateTimeWithLocale(v, location.locale);
|
||||
return formatFullDateTimeWithLocale(v, locationSettings.locale);
|
||||
};
|
||||
|
||||
const showData = settings.showData;
|
||||
|
||||
if (!history || history.length < 0) {
|
||||
return null;
|
||||
}
|
||||
@ -44,7 +41,7 @@ const EventLog = ({
|
||||
</div>
|
||||
);
|
||||
|
||||
if (showData) {
|
||||
if (eventSettings.showData) {
|
||||
entries = history.map(entry => (
|
||||
<EventJson key={`log${entry.id}`} entry={entry} />
|
||||
));
|
||||
@ -63,7 +60,7 @@ const EventLog = ({
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={showData}
|
||||
checked={eventSettings.showData}
|
||||
onChange={toggleShowDiff}
|
||||
color="primary"
|
||||
/>
|
||||
@ -82,12 +79,12 @@ const EventLog = ({
|
||||
};
|
||||
|
||||
EventLog.propTypes = {
|
||||
updateSettings: PropTypes.func,
|
||||
history: PropTypes.array,
|
||||
eventSettings: PropTypes.object.isRequired,
|
||||
setEventSettings: PropTypes.func.isRequired,
|
||||
locationSettings: PropTypes.object.isRequired,
|
||||
title: PropTypes.string,
|
||||
settings: PropTypes.object,
|
||||
displayInline: PropTypes.bool,
|
||||
location: PropTypes.object,
|
||||
hideName: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default EventLog;
|
||||
|
@ -1,18 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import EventLog from './EventLog';
|
||||
import { updateSettingForGroup } from '../../../store/settings/actions';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const settings = state.settings.toJS().history || {};
|
||||
const location = state.settings.toJS().location || {};
|
||||
return {
|
||||
settings,
|
||||
location,
|
||||
};
|
||||
};
|
||||
|
||||
const EventLogContainer = connect(mapStateToProps, {
|
||||
updateSetting: updateSettingForGroup('history'),
|
||||
})(EventLog);
|
||||
|
||||
export default EventLogContainer;
|
27
frontend/src/component/history/EventLog/index.tsx
Normal file
27
frontend/src/component/history/EventLog/index.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import EventLog from './EventLog';
|
||||
import { useEventSettings } from "../../../hooks/useEventSettings";
|
||||
import { useLocationSettings } from "../../../hooks/useLocationSettings";
|
||||
|
||||
interface IEventLogContainerProps {
|
||||
title: string;
|
||||
history: unknown[];
|
||||
displayInline?: boolean;
|
||||
}
|
||||
|
||||
const EventLogContainer = (props: IEventLogContainerProps) => {
|
||||
const { locationSettings } = useLocationSettings();
|
||||
const { eventSettings, setEventSettings } = useEventSettings();
|
||||
|
||||
return (
|
||||
<EventLog
|
||||
title={props.title}
|
||||
history={props.history}
|
||||
eventSettings={eventSettings}
|
||||
setEventSettings={setEventSettings}
|
||||
locationSettings={locationSettings}
|
||||
displayInline={props.displayInline}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default EventLogContainer;
|
@ -1,6 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import OutsideClickHandler from 'react-outside-click-handler';
|
||||
|
||||
import { Avatar, Button } from '@material-ui/core';
|
||||
@ -8,17 +7,19 @@ import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
||||
import { useStyles } from './UserProfile.styles';
|
||||
import { useCommonStyles } from '../../../common.styles';
|
||||
import UserProfileContent from './UserProfileContent/UserProfileContent';
|
||||
import { IUser } from '../../../interfaces/user';
|
||||
import { IUser } from "../../../interfaces/user";
|
||||
import { ILocationSettings } from "../../../hooks/useLocationSettings";
|
||||
|
||||
interface IUserProfileProps {
|
||||
profile: IUser;
|
||||
updateSettingLocation: (field: 'locale', value: string) => void;
|
||||
profile: IUser
|
||||
locationSettings: ILocationSettings
|
||||
setLocationSettings: React.Dispatch<React.SetStateAction<ILocationSettings>>
|
||||
}
|
||||
|
||||
const UserProfile = ({
|
||||
profile,
|
||||
location,
|
||||
updateSettingLocation,
|
||||
locationSettings,
|
||||
setLocationSettings,
|
||||
}: IUserProfileProps) => {
|
||||
const [showProfile, setShowProfile] = useState(false);
|
||||
const [currentLocale, setCurrentLocale] = useState<string>();
|
||||
@ -40,17 +41,15 @@ const UserProfile = ({
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const locale = location.locale || navigator.language;
|
||||
let found = possibleLocales.find(l =>
|
||||
l.toLowerCase().includes(locale.toLowerCase())
|
||||
l.toLowerCase().includes(locationSettings.locale.toLowerCase())
|
||||
);
|
||||
setCurrentLocale(found);
|
||||
|
||||
if (!found) {
|
||||
setPossibleLocales(prev => [...prev, locale]);
|
||||
setPossibleLocales(prev => [...prev, locationSettings.locale]);
|
||||
}
|
||||
/* eslint-disable-next-line*/
|
||||
}, []);
|
||||
}, [locationSettings]);
|
||||
|
||||
const email = profile ? profile.email : '';
|
||||
const imageUrl = email ? profile.imageUrl : 'unknown-user.png';
|
||||
@ -75,7 +74,7 @@ const UserProfile = ({
|
||||
showProfile={showProfile}
|
||||
imageUrl={imageUrl}
|
||||
profile={profile}
|
||||
updateSettingLocation={updateSettingLocation}
|
||||
setLocationSettings={setLocationSettings}
|
||||
possibleLocales={possibleLocales}
|
||||
setCurrentLocale={setCurrentLocale}
|
||||
currentLocale={currentLocale}
|
||||
@ -85,10 +84,4 @@ const UserProfile = ({
|
||||
);
|
||||
};
|
||||
|
||||
UserProfile.propTypes = {
|
||||
profile: PropTypes.object,
|
||||
location: PropTypes.object,
|
||||
updateSettingLocation: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default UserProfile;
|
||||
|
@ -18,25 +18,28 @@ import legacyStyles from '../../user.module.scss';
|
||||
import { getBasePath } from '../../../../utils/format-path';
|
||||
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { IUser } from '../../../../interfaces/user';
|
||||
import { ILocationSettings } from '../../../../hooks/useLocationSettings';
|
||||
|
||||
interface IUserProfileContentProps {
|
||||
showProfile: boolean;
|
||||
profile: IUser;
|
||||
possibleLocales: string[];
|
||||
updateSettingLocation: (field: 'locale', value: string) => void;
|
||||
imageUrl: string;
|
||||
currentLocale?: string;
|
||||
setCurrentLocale: (value: string) => void;
|
||||
setLocationSettings: React.Dispatch<
|
||||
React.SetStateAction<ILocationSettings>
|
||||
>;
|
||||
}
|
||||
|
||||
const UserProfileContent = ({
|
||||
showProfile,
|
||||
profile,
|
||||
possibleLocales,
|
||||
updateSettingLocation,
|
||||
imageUrl,
|
||||
currentLocale,
|
||||
setCurrentLocale,
|
||||
setLocationSettings,
|
||||
}: IUserProfileContentProps) => {
|
||||
const commonStyles = useCommonStyles();
|
||||
const { uiConfig } = useUiConfig();
|
||||
@ -44,10 +47,6 @@ const UserProfileContent = ({
|
||||
const [editingProfile, setEditingProfile] = useState(false);
|
||||
const styles = useStyles();
|
||||
|
||||
const setLocale = (value: string) => {
|
||||
updateSettingLocation('locale', value);
|
||||
};
|
||||
|
||||
// @ts-expect-error
|
||||
const profileAvatarClasses = classnames(styles.avatar, {
|
||||
// @ts-expect-error
|
||||
@ -61,9 +60,9 @@ const UserProfileContent = ({
|
||||
});
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<{ value: unknown }>) => {
|
||||
const value = e.target.value as string;
|
||||
setCurrentLocale(value);
|
||||
setLocale(value);
|
||||
const locale = e.target.value as string;
|
||||
setCurrentLocale(locale);
|
||||
setLocationSettings({ locale });
|
||||
};
|
||||
|
||||
return (
|
||||
@ -99,19 +98,14 @@ const UserProfileContent = ({
|
||||
condition={!editingProfile}
|
||||
show={
|
||||
<>
|
||||
<ConditionallyRender
|
||||
condition={!uiConfig.disablePasswordAuth}
|
||||
show={
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() =>
|
||||
setEditingProfile(true)
|
||||
}
|
||||
>
|
||||
Update password
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender condition={!uiConfig.disablePasswordAuth} show={
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => setEditingProfile(true)}
|
||||
>
|
||||
Update password
|
||||
</Button>
|
||||
} />
|
||||
<div className={commonStyles.divider} />
|
||||
<div className={legacyStyles.showUserSettings}>
|
||||
<FormControl
|
||||
|
@ -1,27 +0,0 @@
|
||||
import useUser from '../../../hooks/api/getters/useUser/useUser';
|
||||
import { connect } from 'react-redux';
|
||||
import UserProfile from './UserProfile';
|
||||
import { updateSettingForGroup } from '../../../store/settings/actions';
|
||||
|
||||
const mapDispatchToProps = {
|
||||
updateSettingLocation: updateSettingForGroup('location'),
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
location: state.settings ? state.settings.toJS().location : {},
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(props => {
|
||||
const user = useUser();
|
||||
|
||||
return (
|
||||
<UserProfile
|
||||
location={props.location}
|
||||
updateSettingLocation={props.updateSettingLocation}
|
||||
profile={user.user}
|
||||
/>
|
||||
);
|
||||
});
|
18
frontend/src/component/user/UserProfile/index.tsx
Normal file
18
frontend/src/component/user/UserProfile/index.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import useUser from '../../../hooks/api/getters/useUser/useUser';
|
||||
import UserProfile from './UserProfile';
|
||||
import { useLocationSettings } from '../../../hooks/useLocationSettings';
|
||||
|
||||
const UserProfileContainer = () => {
|
||||
const user = useUser();
|
||||
const { locationSettings, setLocationSettings } = useLocationSettings();
|
||||
|
||||
return (
|
||||
<UserProfile
|
||||
locationSettings={locationSettings}
|
||||
setLocationSettings={setLocationSettings}
|
||||
profile={user.user}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserProfileContainer;
|
27
frontend/src/hooks/useEventSettings.ts
Normal file
27
frontend/src/hooks/useEventSettings.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { getBasePath } from '../utils/format-path';
|
||||
import { createPersistentGlobalState } from './usePersistentGlobalState';
|
||||
import React from 'react';
|
||||
|
||||
export interface IEventSettings {
|
||||
showData: boolean;
|
||||
}
|
||||
|
||||
interface IUseEventSettingsOutput {
|
||||
eventSettings: IEventSettings;
|
||||
setEventSettings: React.Dispatch<React.SetStateAction<IEventSettings>>;
|
||||
}
|
||||
|
||||
export const useEventSettings = (): IUseEventSettingsOutput => {
|
||||
const [eventSettings, setEventSettings] = useGlobalState();
|
||||
|
||||
return { eventSettings, setEventSettings };
|
||||
};
|
||||
|
||||
const createInitialValue = (): IEventSettings => {
|
||||
return { showData: false };
|
||||
};
|
||||
|
||||
const useGlobalState = createPersistentGlobalState<IEventSettings>(
|
||||
`${getBasePath()}:useEventSettings:v1`,
|
||||
createInitialValue()
|
||||
);
|
29
frontend/src/hooks/useLocationSettings.ts
Normal file
29
frontend/src/hooks/useLocationSettings.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { getBasePath } from '../utils/format-path';
|
||||
import { createPersistentGlobalState } from './usePersistentGlobalState';
|
||||
import React from 'react';
|
||||
|
||||
export interface ILocationSettings {
|
||||
locale: string;
|
||||
}
|
||||
|
||||
interface IUseLocationSettingsOutput {
|
||||
locationSettings: ILocationSettings;
|
||||
setLocationSettings: React.Dispatch<
|
||||
React.SetStateAction<ILocationSettings>
|
||||
>;
|
||||
}
|
||||
|
||||
export const useLocationSettings = (): IUseLocationSettingsOutput => {
|
||||
const [locationSettings, setLocationSettings] = useGlobalState();
|
||||
|
||||
return { locationSettings, setLocationSettings };
|
||||
};
|
||||
|
||||
const createInitialValue = (): ILocationSettings => {
|
||||
return { locale: navigator.language };
|
||||
};
|
||||
|
||||
const useGlobalState = createPersistentGlobalState<ILocationSettings>(
|
||||
`${getBasePath()}:useLocationSettings:v1`,
|
||||
createInitialValue()
|
||||
);
|
@ -7,7 +7,6 @@ import tagTypes from './tag-type';
|
||||
import tags from './tag';
|
||||
import strategies from './strategy';
|
||||
import error from './error';
|
||||
import settings from './settings';
|
||||
import user from './user';
|
||||
import applications from './application';
|
||||
import uiConfig from './ui-config';
|
||||
@ -27,7 +26,6 @@ const unleashStore = combineReducers({
|
||||
tags,
|
||||
featureTags,
|
||||
error,
|
||||
settings,
|
||||
user,
|
||||
applications,
|
||||
uiConfig,
|
||||
|
@ -1,10 +0,0 @@
|
||||
export const UPDATE_SETTING = 'UPDATE_SETTING';
|
||||
|
||||
export const updateSetting = (group, field, value) => ({
|
||||
type: UPDATE_SETTING,
|
||||
group,
|
||||
field,
|
||||
value,
|
||||
});
|
||||
|
||||
export const updateSettingForGroup = group => (field, value) => updateSetting(group, field, value);
|
@ -1,44 +0,0 @@
|
||||
import { fromJS } from 'immutable';
|
||||
import { UPDATE_SETTING } from './actions';
|
||||
import { USER_LOGOUT, USER_LOGIN } from '../user/actions';
|
||||
|
||||
import { getBasePath } from '../../utils/format-path';
|
||||
|
||||
const localStorage = window.localStorage || {
|
||||
setItem: () => {},
|
||||
getItem: () => {},
|
||||
};
|
||||
const basePath = getBasePath();
|
||||
const SETTINGS = `${basePath}:settings`;
|
||||
|
||||
const DEFAULT = fromJS({ location: {} });
|
||||
|
||||
function getInitState() {
|
||||
try {
|
||||
const state = JSON.parse(localStorage.getItem(SETTINGS));
|
||||
return state ? DEFAULT.merge(state) : DEFAULT;
|
||||
} catch (e) {
|
||||
return DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
function updateSetting(state, action) {
|
||||
const newState = state.updateIn([action.group, action.field], () => action.value);
|
||||
|
||||
localStorage.setItem(SETTINGS, JSON.stringify(newState.toJSON()));
|
||||
return newState;
|
||||
}
|
||||
|
||||
const settingStore = (state = getInitState(), action) => {
|
||||
switch (action.type) {
|
||||
case UPDATE_SETTING:
|
||||
return updateSetting(state, action);
|
||||
case USER_LOGOUT:
|
||||
case USER_LOGIN:
|
||||
return getInitState();
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default settingStore;
|
Loading…
Reference in New Issue
Block a user