diff options
Diffstat (limited to 'Timeline/ClientApp/src/app/settings/Settings.tsx')
-rw-r--r-- | Timeline/ClientApp/src/app/settings/Settings.tsx | 253 |
1 files changed, 0 insertions, 253 deletions
diff --git a/Timeline/ClientApp/src/app/settings/Settings.tsx b/Timeline/ClientApp/src/app/settings/Settings.tsx deleted file mode 100644 index 96a3fab4..00000000 --- a/Timeline/ClientApp/src/app/settings/Settings.tsx +++ /dev/null @@ -1,253 +0,0 @@ -import React, { useState } from 'react'; -import { useHistory } from 'react-router'; -import { useTranslation } from 'react-i18next'; -import axios, { AxiosError } from 'axios'; -import { - Container, - Row, - Col, - Input, - Modal, - ModalHeader, - ModalBody, - ModalFooter, - Button, -} from 'reactstrap'; - -import { apiBaseUrl } from '../config'; - -import { useUser, userLogout, useUserLoggedIn } from '../data/user'; - -import AppBar from '../common/AppBar'; -import OperationDialog, { - OperationInputErrorInfo, -} from '../common/OperationDialog'; -import { CommonErrorResponse } from '../data/common'; - -interface ChangePasswordDialogProps { - open: boolean; - close: () => void; -} - -async function changePassword( - oldPassword: string, - newPassword: string, - token: string -): Promise<void> { - const url = `${apiBaseUrl}/userop/changepassword?token=${token}`; - try { - await axios.post(url, { - oldPassword, - newPassword, - }); - } catch (e) { - const error = e as AxiosError<CommonErrorResponse>; - if ( - error.response && - error.response.status === 400 && - error.response.data && - error.response.data.message - ) { - throw error.response.data.message; - } - throw e; - } -} - -const ChangePasswordDialog: React.FC<ChangePasswordDialogProps> = (props) => { - const user = useUserLoggedIn(); - const history = useHistory(); - const { t } = useTranslation(); - - const [redirect, setRedirect] = useState<boolean>(false); - - return ( - <OperationDialog - open={props.open} - title={t('settings.dialogChangePassword.title')} - titleColor="dangerous" - inputPrompt={t('settings.dialogChangePassword.prompt')} - inputScheme={[ - { - type: 'text', - label: t('settings.dialogChangePassword.inputOldPassword'), - password: true, - validator: (v) => - v === '' - ? 'settings.dialogChangePassword.errorEmptyOldPassword' - : null, - }, - { - type: 'text', - label: t('settings.dialogChangePassword.inputNewPassword'), - password: true, - validator: (v, values) => { - const error: OperationInputErrorInfo = {}; - error[1] = - v === '' - ? 'settings.dialogChangePassword.errorEmptyNewPassword' - : null; - if (v === values[2]) { - error[2] = null; - } else { - if (values[2] !== '') { - error[2] = 'settings.dialogChangePassword.errorRetypeNotMatch'; - } - } - return error; - }, - }, - { - type: 'text', - label: t('settings.dialogChangePassword.inputRetypeNewPassword'), - password: true, - validator: (v, values) => - v !== values[1] - ? 'settings.dialogChangePassword.errorRetypeNotMatch' - : null, - }, - ]} - onProcess={async ([oldPassword, newPassword]) => { - await changePassword( - oldPassword as string, - newPassword as string, - user.token - ); - userLogout(); - setRedirect(true); - }} - close={() => { - props.close(); - if (redirect) { - history.push('/login'); - } - }} - /> - ); -}; - -const ConfirmLogoutDialog: React.FC<{ - toggle: () => void; - onConfirm: () => void; -}> = ({ toggle, onConfirm }) => { - const { t } = useTranslation(); - - return ( - <Modal isOpen centered> - <ModalHeader className="text-danger"> - {t('settings.dialogConfirmLogout.title')} - </ModalHeader> - <ModalBody>{t('settings.dialogConfirmLogout.prompt')}</ModalBody> - <ModalFooter> - <Button color="secondary" onClick={toggle}> - {t('operationDialog.cancel')} - </Button> - <Button color="danger" onClick={onConfirm}> - {t('operationDialog.confirm')} - </Button> - </ModalFooter> - </Modal> - ); -}; - -const Settings: React.FC = (_) => { - const { i18n, t } = useTranslation(); - const user = useUser(); - const history = useHistory(); - - const [dialog, setDialog] = useState<null | 'changepassword' | 'logout'>( - null - ); - - const language = i18n.language.slice(0, 2); - - return ( - <> - <AppBar /> - <Container fluid className="mt-appbar"> - {user ? ( - <> - <Row className="border-bottom p-3 cursor-pointer"> - <Col xs="12"> - <h5 - onClick={() => { - history.push(`/users/${user.username}`); - }} - > - {t('settings.gotoSelf')} - </h5> - </Col> - </Row> - <Row className="border-bottom p-3 cursor-pointer"> - <Col xs="12"> - <h5 - className="text-danger" - onClick={() => setDialog('changepassword')} - > - {t('settings.changePassword')} - </h5> - </Col> - </Row> - <Row className="border-bottom p-3 cursor-pointer"> - <Col xs="12"> - <h5 - className="text-danger" - onClick={() => { - setDialog('logout'); - }} - > - {t('settings.logout')} - </h5> - </Col> - </Row> - </> - ) : null} - <Row className="align-items-center border-bottom p-3"> - <Col xs="12" sm="auto"> - <h5>{t('settings.languagePrimary')}</h5> - <p>{t('settings.languageSecondary')}</p> - </Col> - <Col xs="auto" className="ml-auto"> - <Input - type="select" - value={language} - onChange={(e) => { - void i18n.changeLanguage(e.target.value); - }} - > - <option value="zh">中文</option> - <option value="en">English</option> - </Input> - </Col> - </Row> - {(() => { - switch (dialog) { - case 'changepassword': - return ( - <ChangePasswordDialog - open - close={() => { - setDialog(null); - }} - /> - ); - case 'logout': - return ( - <ConfirmLogoutDialog - toggle={() => setDialog(null)} - onConfirm={() => { - userLogout(); - history.push('/'); - }} - /> - ); - default: - return null; - } - })()} - </Container> - </> - ); -}; - -export default Settings; |