Complete change password.

This commit is contained in:
Paulo Gustavo Veiga 2021-02-15 00:47:10 -08:00
parent 616396fe6a
commit 3a10dce222
5 changed files with 130 additions and 19 deletions

View File

@ -13,8 +13,8 @@ export type ImportMapInfo = {
description?: string; description?: string;
contentType?: string; contentType?: string;
content?: ArrayBuffer | null | string; content?: ArrayBuffer | null | string;
} }
export type Label = { export type Label = {
id: number; id: number;
title: string; title: string;
@ -72,7 +72,9 @@ interface Client {
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>; renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>;
fetchAllMaps(): Promise<MapInfo[]>; fetchAllMaps(): Promise<MapInfo[]>;
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>; duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>;
updateAccountLanguage(locale: LocaleCode): Promise<void>; updateAccountLanguage(locale: LocaleCode): Promise<void>;
updateAccountPassword(pasword: string): Promise<void>;
updateStarred(id: number, starred: boolean): Promise<void>; updateStarred(id: number, starred: boolean): Promise<void>;
updateMapToPublic(id: number, starred: boolean): Promise<void>; updateMapToPublic(id: number, starred: boolean): Promise<void>;

View File

@ -35,6 +35,10 @@ class MockClient implements Client {
} }
updateAccountPassword(pasword: string): Promise<void> {
return Promise.resolve();
}
updateAccountLanguage(locale: LocaleCode): Promise<void> { updateAccountLanguage(locale: LocaleCode): Promise<void> {
localStorage.setItem('locale', locale); localStorage.setItem('locale', locale);
return Promise.resolve(); return Promise.resolve();

View File

@ -10,6 +10,20 @@ export default class RestClient implements Client {
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
this.sessionExpired = sessionExpired; this.sessionExpired = sessionExpired;
} }
updateAccountPassword(pasword: string): Promise<void> {
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
axios.put(`${this.baseUrl}/c/restful/account/password`,
pasword,
{ headers: { 'Content-Type': 'text/plain' } }
).then(() => {
success();
}).catch(error => {
const errorInfo = this.parseResponseOnError(error.response);
reject(errorInfo);
});
}
return new Promise(handler); }
updateAccountLanguage(locale: LocaleCode): Promise<void> { updateAccountLanguage(locale: LocaleCode): Promise<void> {
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => { const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {

View File

@ -1,34 +1,36 @@
import { IconButton, Link, ListItemIcon, Menu, MenuItem, Tooltip } from '@material-ui/core'; import { FormControl, IconButton, Link, ListItemIcon, Menu, MenuItem, Tooltip } from '@material-ui/core';
import { AccountCircle, ExitToAppOutlined, SettingsApplicationsOutlined } from '@material-ui/icons'; import { AccountCircle, ExitToAppOutlined, LockOpenOutlined, SettingsApplicationsOutlined } from '@material-ui/icons';
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { useQueryClient } from "react-query"; import { useMutation } from "react-query";
import Client, { } from "../../../classes/client"; import Client, { ErrorInfo } from "../../../classes/client";
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { activeInstance, fetchAccount } from '../../../redux/clientSlice'; import { activeInstance, fetchAccount } from '../../../redux/clientSlice';
import BaseDialog from '../action-dispatcher/base-dialog';
import Input from '../../form/input';
const AccountMenu = () => { const AccountMenu = () => {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl); const open = Boolean(anchorEl);
const [openRenameDialog, setOpenRenameDialog] = React.useState<boolean>(false);
const handleMenu = (event: React.MouseEvent<HTMLElement>) => { const handleMenu = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget); setAnchorEl(event.currentTarget);
}; };
const handleClose = () => { const handleClose = () => {
setAnchorEl(null); setAnchorEl(null);
}; };
const account = fetchAccount(); const account = fetchAccount();
return ( return (
<span> <span>
<Tooltip title={`${account?.firstName} ${account?.lastName} <${account?.email}>`}> <Tooltip title={`${account?.firstName} ${account?.lastName} <${account?.email}>`}>
<IconButton <IconButton
onClick={handleMenu}> onClick={handleMenu}>
<AccountCircle fontSize="large" style={{color:'black'}}/> <AccountCircle fontSize="large" style={{ color: 'black' }} />
</IconButton > </IconButton >
</Tooltip> </Tooltip>
<Menu id="appbar-profile" <Menu id="appbar-profile"
@ -53,6 +55,13 @@ const AccountMenu = () => {
<FormattedMessage id="menu.account" defaultMessage="Account" /> <FormattedMessage id="menu.account" defaultMessage="Account" />
</MenuItem> </MenuItem>
<MenuItem onClick={() => { handleClose(), setOpenRenameDialog(true) }}>
<ListItemIcon>
<LockOpenOutlined fontSize="small" />
</ListItemIcon>
<FormattedMessage id="menu.change-password" defaultMessage="Change Password" />
</MenuItem>
<MenuItem onClick={handleClose}> <MenuItem onClick={handleClose}>
<Link color="textSecondary" href="/c/logout"> <Link color="textSecondary" href="/c/logout">
<ListItemIcon> <ListItemIcon>
@ -61,8 +70,88 @@ const AccountMenu = () => {
<FormattedMessage id="menu.signout" defaultMessage="Sign Out" /> <FormattedMessage id="menu.signout" defaultMessage="Sign Out" />
</Link> </Link>
</MenuItem> </MenuItem>
</Menu> </Menu>
{openRenameDialog &&
<ChangePasswordDialog onClose={() => setOpenRenameDialog(false)} />
}
</span>); </span>);
} }
type ChangePasswordDialogProps = {
onClose: () => void
}
type ChangePasswordModel = {
password: string,
retryPassword: string
}
const defaultModel: ChangePasswordModel = { password: '', retryPassword: '' };
const ChangePasswordDialog = ({ onClose }: ChangePasswordDialogProps) => {
const client: Client = useSelector(activeInstance);
const [model, setModel] = React.useState<ChangePasswordModel>(defaultModel);
const [error, setError] = React.useState<ErrorInfo>();
const intl = useIntl();
const mutation = useMutation<void, ErrorInfo, ChangePasswordModel>((model: ChangePasswordModel) => {
return client.updateAccountPassword(model.password);
},
{
onSuccess: () => {
onClose()
},
onError: (error) => {
setError(error);
}
}
);
const handleOnClose = (): void => {
onClose();
setModel(defaultModel);
setError(undefined);
};
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
event.preventDefault();
// Check password are equal ...
if (model.password != model.retryPassword) {
setError({ msg: intl.formatMessage({ id: 'changepwd.password-match', defaultMessage: 'Password do not match. Please, try again.' }) });
return;
}
mutation.mutate(model);
};
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
event.preventDefault();
const name = event.target.name;
const value = event.target.value;
setModel({ ...model, [name as keyof ChangePasswordModel]: value });
}
return (
<div>
<BaseDialog onClose={handleOnClose} onSubmit={handleOnSubmit} error={error}
title={intl.formatMessage({ id: 'changepwd.title', defaultMessage: 'Change Password' })}
description={intl.formatMessage({ id: 'changepwd.description', defaultMessage: 'Please, provide the new password for your account.' })}
submitButton={intl.formatMessage({ id: 'changepwd.button', defaultMessage: 'Change' })}>
<FormControl fullWidth={true}>
<Input name="password" type="password" label={intl.formatMessage({ id: "changepwd.password", defaultMessage: "Password" })}
value={model.password} onChange={handleOnChange} error={error} fullWidth={true} autoComplete="new-password" />
<Input name="retryPassword" type="password" label={intl.formatMessage({ id: "changepwd.confirm-password", defaultMessage: "Confirm Password" })}
value={model.retryPassword} onChange={handleOnChange} required={true} fullWidth={true} autoComplete="new-password" />
</FormControl>
</BaseDialog>
</div>
);
}
export default AccountMenu; export default AccountMenu;

View File

@ -13,7 +13,7 @@ const LanguageMenu = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const client: Client = useSelector(activeInstance); const client: Client = useSelector(activeInstance);
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [helpDialogOpen, setHelpDialogOpen] = React.useState<boolean>(false); const [openHelpDialog, setHelpDialogOpen] = React.useState<boolean>(false);
const open = Boolean(anchorEl); const open = Boolean(anchorEl);
const intl = useIntl(); const intl = useIntl();
@ -92,25 +92,26 @@ const LanguageMenu = () => {
<FormattedMessage id="language.help" defaultMessage="Help to Translate" /> <FormattedMessage id="language.help" defaultMessage="Help to Translate" />
</MenuItem> </MenuItem>
</Menu> </Menu>
<HelpUsToTranslateDialog open={helpDialogOpen} onClose={() => setHelpDialogOpen(false)} /> {openHelpDialog &&
<HelpUsToTranslateDialog onClose={() => setHelpDialogOpen(false)} />
}
</span>); </span>);
} }
type HelpUsToTranslateDialogProp = { type HelpUsToTranslateDialogProp = {
open: boolean,
onClose: () => void onClose: () => void
} }
const HelpUsToTranslateDialog = ({ open, onClose }: HelpUsToTranslateDialogProp) => { const HelpUsToTranslateDialog = ({ onClose }: HelpUsToTranslateDialogProp) => {
return ( return (
<Dialog <Dialog
open={open} open={true}
onClose={onClose} onClose={onClose}
> >
<DialogTitle>Help us to Translate !</DialogTitle> <DialogTitle>Help us to support more languages !</DialogTitle>
<DialogContent> <DialogContent>
<DialogContentText> <DialogContentText>
We need your help !. You could help us to support more languages. If you are interested, send us an email to team@wisemapping.com. We need your help !. If you are interested, send us an email to team@wisemapping.com.
</DialogContentText> </DialogContentText>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
@ -120,4 +121,5 @@ const HelpUsToTranslateDialog = ({ open, onClose }: HelpUsToTranslateDialogProp)
); );
} }
export default LanguageMenu; export default LanguageMenu;