diff --git a/packages/webapp/src/classes/client/index.ts b/packages/webapp/src/classes/client/index.ts index 0b7eafb9..7f64cf20 100644 --- a/packages/webapp/src/classes/client/index.ts +++ b/packages/webapp/src/classes/client/index.ts @@ -13,8 +13,8 @@ export type ImportMapInfo = { description?: string; contentType?: string; content?: ArrayBuffer | null | string; - } + export type Label = { id: number; title: string; @@ -72,7 +72,9 @@ interface Client { renameMap(id: number, basicInfo: BasicMapInfo): Promise; fetchAllMaps(): Promise; duplicateMap(id: number, basicInfo: BasicMapInfo): Promise; + updateAccountLanguage(locale: LocaleCode): Promise; + updateAccountPassword(pasword: string): Promise; updateStarred(id: number, starred: boolean): Promise; updateMapToPublic(id: number, starred: boolean): Promise; diff --git a/packages/webapp/src/classes/client/mock-client/index.ts b/packages/webapp/src/classes/client/mock-client/index.ts index 06605d3b..cd773b46 100644 --- a/packages/webapp/src/classes/client/mock-client/index.ts +++ b/packages/webapp/src/classes/client/mock-client/index.ts @@ -35,6 +35,10 @@ class MockClient implements Client { } + updateAccountPassword(pasword: string): Promise { + return Promise.resolve(); + } + updateAccountLanguage(locale: LocaleCode): Promise { localStorage.setItem('locale', locale); return Promise.resolve(); diff --git a/packages/webapp/src/classes/client/rest-client/index.ts b/packages/webapp/src/classes/client/rest-client/index.ts index d261b7b3..f41d823c 100644 --- a/packages/webapp/src/classes/client/rest-client/index.ts +++ b/packages/webapp/src/classes/client/rest-client/index.ts @@ -10,6 +10,20 @@ export default class RestClient implements Client { this.baseUrl = baseUrl; this.sessionExpired = sessionExpired; } + + updateAccountPassword(pasword: string): Promise { + 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 { const handler = (success: () => void, reject: (error: ErrorInfo) => void) => { diff --git a/packages/webapp/src/components/maps-page/account-menu/index.tsx b/packages/webapp/src/components/maps-page/account-menu/index.tsx index 5fd10b59..77c2bf4e 100644 --- a/packages/webapp/src/components/maps-page/account-menu/index.tsx +++ b/packages/webapp/src/components/maps-page/account-menu/index.tsx @@ -1,34 +1,36 @@ -import { IconButton, Link, ListItemIcon, Menu, MenuItem, Tooltip } from '@material-ui/core'; -import { AccountCircle, ExitToAppOutlined, SettingsApplicationsOutlined } from '@material-ui/icons'; +import { FormControl, IconButton, Link, ListItemIcon, Menu, MenuItem, Tooltip } from '@material-ui/core'; +import { AccountCircle, ExitToAppOutlined, LockOpenOutlined, SettingsApplicationsOutlined } from '@material-ui/icons'; import React from "react"; -import { FormattedMessage } from "react-intl"; -import { useQueryClient } from "react-query"; -import Client, { } from "../../../classes/client"; +import { FormattedMessage, useIntl } from "react-intl"; +import { useMutation } from "react-query"; +import Client, { ErrorInfo } from "../../../classes/client"; import { useSelector } from 'react-redux'; import { activeInstance, fetchAccount } from '../../../redux/clientSlice'; +import BaseDialog from '../action-dispatcher/base-dialog'; +import Input from '../../form/input'; const AccountMenu = () => { - - const [anchorEl, setAnchorEl] = React.useState(null); const open = Boolean(anchorEl); + const [openRenameDialog, setOpenRenameDialog] = React.useState(false); + const handleMenu = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; - + const handleClose = () => { setAnchorEl(null); }; - const account = fetchAccount(); + const account = fetchAccount(); return ( `}> - + { + { handleClose(), setOpenRenameDialog(true) }}> + + + + + + @@ -61,8 +70,88 @@ const AccountMenu = () => { - + {openRenameDialog && + setOpenRenameDialog(false)} /> + } ); } + + +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(defaultModel); + const [error, setError] = React.useState(); + const intl = useIntl(); + + const mutation = useMutation((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): 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): void => { + event.preventDefault(); + + const name = event.target.name; + const value = event.target.value; + setModel({ ...model, [name as keyof ChangePasswordModel]: value }); + } + + return ( +
+ + + + + + + + +
+ ); +} + + + export default AccountMenu; \ No newline at end of file diff --git a/packages/webapp/src/components/maps-page/language-menu/index.tsx b/packages/webapp/src/components/maps-page/language-menu/index.tsx index 44d4919e..90d31e6e 100644 --- a/packages/webapp/src/components/maps-page/language-menu/index.tsx +++ b/packages/webapp/src/components/maps-page/language-menu/index.tsx @@ -13,7 +13,7 @@ const LanguageMenu = () => { const queryClient = useQueryClient(); const client: Client = useSelector(activeInstance); const [anchorEl, setAnchorEl] = React.useState(null); - const [helpDialogOpen, setHelpDialogOpen] = React.useState(false); + const [openHelpDialog, setHelpDialogOpen] = React.useState(false); const open = Boolean(anchorEl); const intl = useIntl(); @@ -92,25 +92,26 @@ const LanguageMenu = () => { - setHelpDialogOpen(false)} /> + {openHelpDialog && + setHelpDialogOpen(false)} /> + } ); } type HelpUsToTranslateDialogProp = { - open: boolean, onClose: () => void } -const HelpUsToTranslateDialog = ({ open, onClose }: HelpUsToTranslateDialogProp) => { +const HelpUsToTranslateDialog = ({ onClose }: HelpUsToTranslateDialogProp) => { return ( - Help us to Translate ! + Help us to support more languages ! - 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. @@ -120,4 +121,5 @@ const HelpUsToTranslateDialog = ({ open, onClose }: HelpUsToTranslateDialogProp) ); } + export default LanguageMenu;