From d16a0365d79dc1c702d0343e17fc005143129dbf Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 18 Sep 2022 16:43:18 -0400 Subject: [PATCH] chore: Move language and account delete from Profile -> Preferences --- app/scenes/Settings/Preferences.tsx | 82 +++++++++++++-- app/scenes/Settings/Profile.tsx | 67 +----------- app/scenes/UserDelete.tsx | 112 ++++++++++----------- shared/i18n/locales/en_US/translation.json | 11 +- 4 files changed, 132 insertions(+), 140 deletions(-) diff --git a/app/scenes/Settings/Preferences.tsx b/app/scenes/Settings/Preferences.tsx index 0d3fe019c..c30a0a5e4 100644 --- a/app/scenes/Settings/Preferences.tsx +++ b/app/scenes/Settings/Preferences.tsx @@ -1,55 +1,119 @@ import { observer } from "mobx-react"; import { SettingsIcon } from "outline-icons"; import * as React from "react"; -import { useTranslation } from "react-i18next"; +import { Trans, useTranslation } from "react-i18next"; +import { languageOptions } from "@shared/i18n"; +import Button from "~/components/Button"; import Heading from "~/components/Heading"; +import InputSelect from "~/components/InputSelect"; import Scene from "~/components/Scene"; import Switch from "~/components/Switch"; import useCurrentUser from "~/hooks/useCurrentUser"; import useStores from "~/hooks/useStores"; import useToasts from "~/hooks/useToasts"; +import UserDelete from "../UserDelete"; import SettingRow from "./components/SettingRow"; function Preferences() { const { t } = useTranslation(); const { showToast } = useToasts(); - const { auth } = useStores(); + const { dialogs, auth } = useStores(); const user = useCurrentUser(); - const handleChange = async (ev: React.ChangeEvent) => { - const newPreferences = { + const handlePreferenceChange = async ( + ev: React.ChangeEvent + ) => { + const preferences = { ...user.preferences, [ev.target.name]: ev.target.checked, }; - await auth.updateUser({ - preferences: newPreferences, - }); + await auth.updateUser({ preferences }); showToast(t("Preferences saved"), { type: "success", }); }; + const handleLanguageChange = async (language: string) => { + await auth.updateUser({ language }); + showToast(t("Preferences saved"), { + type: "success", + }); + }; + + const showDeleteAccount = () => { + dialogs.openModal({ + title: t("Delete account"), + content: , + }); + }; + return ( } > {t("Preferences")} + + + Choose the interface language. Community translations are accepted + though our{" "} + + translation portal + + . + + + } + > + + + + +

 

+ + + + + +
); } diff --git a/app/scenes/Settings/Profile.tsx b/app/scenes/Settings/Profile.tsx index 5fc88b0eb..8fdceb971 100644 --- a/app/scenes/Settings/Profile.tsx +++ b/app/scenes/Settings/Profile.tsx @@ -1,16 +1,11 @@ import { observer } from "mobx-react"; import { ProfileIcon } from "outline-icons"; import * as React from "react"; -import { Trans, useTranslation } from "react-i18next"; -import styled from "styled-components"; -import { languageOptions } from "@shared/i18n"; -import UserDelete from "~/scenes/UserDelete"; +import { useTranslation } from "react-i18next"; import Button from "~/components/Button"; import Heading from "~/components/Heading"; import Input from "~/components/Input"; -import InputSelect from "~/components/InputSelect"; import Scene from "~/components/Scene"; -import Text from "~/components/Text"; import useCurrentUser from "~/hooks/useCurrentUser"; import useStores from "~/hooks/useStores"; import useToasts from "~/hooks/useToasts"; @@ -23,8 +18,6 @@ const Profile = () => { const form = React.useRef(null); const [name, setName] = React.useState(user.name || ""); const [avatarUrl, setAvatarUrl] = React.useState(user.avatarUrl); - const [showDeleteModal, setShowDeleteModal] = React.useState(false); - const [language, setLanguage] = React.useState(user.language); const { showToast } = useToasts(); const { t } = useTranslation(); @@ -35,7 +28,6 @@ const Profile = () => { await auth.updateUser({ name, avatarUrl, - language, }); showToast(t("Profile saved"), { type: "success", @@ -67,14 +59,6 @@ const Profile = () => { }); }; - const handleLanguageChange = (value: string) => { - setLanguage(value); - }; - - const toggleDeleteAccount = () => { - setShowDeleteModal((prev) => !prev); - }; - const isValid = form.current?.checkValidity(); const { isSaving } = auth; @@ -95,6 +79,7 @@ const Profile = () => { /> { /> - - - Please note that translations are currently in early access. - Community contributions are accepted though our{" "} - - translation portal - - . - - - } - > - - - - - -

{t("Delete Account")}

- - - You may delete your account at any time, note that this is - unrecoverable - - - -
- {showDeleteModal && } ); }; -const DangerZone = styled.div` - margin-top: 60px; -`; - export default observer(Profile); diff --git a/app/scenes/UserDelete.tsx b/app/scenes/UserDelete.tsx index 116b27b7e..d430e6248 100644 --- a/app/scenes/UserDelete.tsx +++ b/app/scenes/UserDelete.tsx @@ -5,7 +5,6 @@ import { useTranslation, Trans } from "react-i18next"; import Button from "~/components/Button"; import Flex from "~/components/Flex"; import { ReactHookWrappedInput as Input } from "~/components/Input"; -import Modal from "~/components/Modal"; import Text from "~/components/Text"; import env from "~/env"; import useStores from "~/hooks/useStores"; @@ -15,11 +14,7 @@ type FormData = { code: string; }; -type Props = { - onRequestClose: () => void; -}; - -function UserDelete({ onRequestClose }: Props) { +function UserDelete() { const [isWaitingCode, setWaitingCode] = React.useState(false); const { auth } = useStores(); const { showToast } = useToasts(); @@ -63,61 +58,58 @@ function UserDelete({ onRequestClose }: Props) { }); return ( - - -
- {isWaitingCode ? ( - <> - - - A confirmation code has been sent to your email address, - please enter the code below to permanantly destroy your - account. - - - - , - }} - /> - - + + {isWaitingCode ? ( + <> + + + A confirmation code has been sent to your email address, please + enter the code below to permanantly destroy your account. + + + + , + }} /> - - ) : ( - <> - - - Are you sure? Deleting your account will destroy identifying - data associated with your user and cannot be undone. You will - be immediately logged out of Outline and all your API tokens - will be revoked. - - - - )} - {env.EMAIL_ENABLED && !isWaitingCode ? ( - - ) : ( - - )} - -
-
+ + + + ) : ( + <> + + + Are you sure? Deleting your account will destroy identifying + data associated with your user and cannot be undone. You will be + immediately logged out of Outline and all your API tokens will + be revoked. + + + + )} + {env.EMAIL_ENABLED && !isWaitingCode ? ( + + ) : ( + + )} + + ); } diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 6d5122d07..bac7fdbf3 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -685,19 +685,18 @@ "Your email address should be updated in your SSO provider.": "Your email address should be updated in your SSO provider.", "The email integration is currently disabled. Please set the associated environment variables and restart the server to enable notifications.": "The email integration is currently disabled. Please set the associated environment variables and restart the server to enable notifications.", "Preferences saved": "Preferences saved", + "Delete account": "Delete account", + "Language": "Language", + "Choose the interface language. Community translations are accepted though our <2>translation portal.": "Choose the interface language. Community translations are accepted though our <2>translation portal.", "Remember previous location": "Remember previous location", - "Automatically return to the document you were last viewing when the app is re-opened": "Automatically return to the document you were last viewing when the app is re-opened", + "Automatically return to the document you were last viewing when the app is re-opened.": "Automatically return to the document you were last viewing when the app is re-opened.", + "You may delete your account at any time, note that this is unrecoverable": "You may delete your account at any time, note that this is unrecoverable", "Profile saved": "Profile saved", "Profile picture updated": "Profile picture updated", "Unable to upload new profile picture": "Unable to upload new profile picture", "Photo": "Photo", "Choose a photo or image to represent yourself.": "Choose a photo or image to represent yourself.", "This could be your real name, or a nickname — however you’d like people to refer to you.": "This could be your real name, or a nickname — however you’d like people to refer to you.", - "Language": "Language", - "Please note that translations are currently in early access. Community contributions are accepted though our <2>translation portal.": "Please note that translations are currently in early access. Community contributions are accepted though our <2>translation portal.", - "Delete Account": "Delete Account", - "You may delete your account at any time, note that this is unrecoverable": "You may delete your account at any time, note that this is unrecoverable", - "Delete account": "Delete account", "Are you sure you want to require invites?": "Are you sure you want to require invites?", "I’m sure": "I’m sure", "New users will first need to be invited to create an account. Default role and Allowed domains will no longer apply.": "New users will first need to be invited to create an account. Default role and Allowed domains will no longer apply.",