diff options
| author | crupest <crupest@outlook.com> | 2020-10-31 00:42:06 +0800 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-10-31 00:42:06 +0800 | 
| commit | 1b80b699e477a0c14a069401cf39126d19668bf0 (patch) | |
| tree | 0d1c10cd42398bea87e0169e8a4ec385b71f49bc /FrontEnd/src/app/views/settings/index.tsx | |
| parent | 0062a22423806c9501752132133e14de02355760 (diff) | |
| parent | 5875e7a19ff8eb244e2849647ba35aa898de6b52 (diff) | |
| download | timeline-1b80b699e477a0c14a069401cf39126d19668bf0.tar.gz timeline-1b80b699e477a0c14a069401cf39126d19668bf0.tar.bz2 timeline-1b80b699e477a0c14a069401cf39126d19668bf0.zip | |
Merge pull request #161 from crupest/upgrade
Upgrade packages and split front end and back end.
Diffstat (limited to 'FrontEnd/src/app/views/settings/index.tsx')
| -rw-r--r-- | FrontEnd/src/app/views/settings/index.tsx | 209 | 
1 files changed, 209 insertions, 0 deletions
| diff --git a/FrontEnd/src/app/views/settings/index.tsx b/FrontEnd/src/app/views/settings/index.tsx new file mode 100644 index 00000000..964e7442 --- /dev/null +++ b/FrontEnd/src/app/views/settings/index.tsx @@ -0,0 +1,209 @@ +import React, { useState } from "react"; +import { useHistory } from "react-router"; +import { useTranslation } from "react-i18next"; +import { Form, Container, Row, Col, Button, Modal } from "react-bootstrap"; + +import { useUser, userService } from "@/services/user"; +import OperationDialog, { +  OperationInputErrorInfo, +} from "../common/OperationDialog"; + +interface ChangePasswordDialogProps { +  open: boolean; +  close: () => void; +} + +const ChangePasswordDialog: React.FC<ChangePasswordDialogProps> = (props) => { +  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 userService +          .changePassword(oldPassword as string, newPassword as string) +          .toPromise(); +        await userService.logout(); +        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 show centered onHide={toggle}> +      <Modal.Header> +        <Modal.Title className="text-danger"> +          {t("settings.dialogConfirmLogout.title")} +        </Modal.Title> +      </Modal.Header> +      <Modal.Body>{t("settings.dialogConfirmLogout.prompt")}</Modal.Body> +      <Modal.Footer> +        <Button variant="secondary" onClick={toggle}> +          {t("operationDialog.cancel")} +        </Button> +        <Button variant="danger" onClick={onConfirm}> +          {t("operationDialog.confirm")} +        </Button> +      </Modal.Footer> +    </Modal> +  ); +}; + +const SettingsPage: 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 ( +    <Container fluid> +      {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"> +          <Form.Control +            as="select" +            value={language} +            onChange={(e) => { +              void i18n.changeLanguage(e.target.value); +            }} +          > +            <option value="zh">中文</option> +            <option value="en">English</option> +          </Form.Control> +        </Col> +      </Row> +      {(() => { +        switch (dialog) { +          case "changepassword": +            return ( +              <ChangePasswordDialog +                open +                close={() => { +                  setDialog(null); +                }} +              /> +            ); +          case "logout": +            return ( +              <ConfirmLogoutDialog +                toggle={() => setDialog(null)} +                onConfirm={() => { +                  void userService.logout().then(() => { +                    history.push("/"); +                  }); +                }} +              /> +            ); +          default: +            return null; +        } +      })()} +    </Container> +  ); +}; + +export default SettingsPage; | 
