Implemented UI for the account deletion

This commit is contained in:
ErickSkrauch 2020-07-26 20:06:25 +03:00
parent a790c2b24f
commit 9247ad7178
No known key found for this signature in database
GPG Key ID: 669339FCBB30EE0E
9 changed files with 273 additions and 4 deletions

View File

@ -0,0 +1,19 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { ProfileLayout } from 'app/components/profile/Profile.story';
import DeleteAccount from './DeleteAccount';
storiesOf('Components/Profile', module).add('DeleteAccount', () => (
<ProfileLayout>
<DeleteAccount
onSubmit={() => {
action('onSubmit')();
return Promise.resolve();
}}
/>
</ProfileLayout>
));

View File

@ -0,0 +1,163 @@
import React, { ComponentType } from 'react';
import { FormattedMessage as Message } from 'react-intl';
import { Helmet } from 'react-helmet-async';
import { Button, Form } from 'app/components/ui/form';
import siteName from 'app/pages/root/siteName.intl';
import appName from 'app/components/auth/appInfo/appName.intl';
import { BackButton } from '../ProfileForm';
import styles from '../profileForm.scss';
import ownStyles from './deleteAccount.scss';
interface Props {
onSubmit?: () => Promise<void>;
}
const DeleteAccount: ComponentType<Props> = ({ onSubmit }) => (
<Form onSubmit={onSubmit}>
<div className={styles.contentWithBackButton}>
<BackButton />
<div className={styles.form}>
<div className={styles.formBody}>
<Message key="accountDeletionTitle" defaultMessage="Account deletion">
{(pageTitle) => (
<h3 className={styles.title}>
<Helmet title={pageTitle as string} />
{pageTitle}
</h3>
)}
</Message>
<div className={styles.formRow}>
<p className={styles.description}>
<Message
key="accountDeletionDescription1"
defaultMessage="You are about to delete your Ely.by account, which provides access to various Ely.by services. You won't be able to use them and all your account data will be lost."
/>
</p>
<p className={styles.description}>
<Message
key="accountDeletionDescription2"
defaultMessage="You may also lose access to game servers and some third-party services if the Ely.by's authorization service was used to enter them."
/>
</p>
</div>
<div className={styles.formRow}>
<div className={styles.sectionTitle}>
<Message key="dataToBeDeleted" defaultMessage="Data to be deleted:" />
</div>
</div>
<div className={ownStyles.removableDataRow}>
<div className={ownStyles.serviceName}>
{/* TODO: missing colon */}
<Message {...siteName} />
</div>
<div className={ownStyles.serviceContents}>
<ul>
<li>
<Message key="posts" defaultMessage="Posts" tagName="span" />
</li>
<li>
<Message key="friends" defaultMessage="Friends" tagName="span" />
</li>
<li>
<Message key="directMessages" defaultMessage="Direct messages" tagName="span" />
</li>
<li>
<Message key="cubes" defaultMessage="Cubes" tagName="span" />
</li>
<li>
<Message
key="serversForTheSSS"
defaultMessage="Servers for the server skins system"
tagName="span"
/>
</li>
</ul>
</div>
</div>
<div className={styles.delimiter} />
<div className={ownStyles.removableDataRow}>
<div className={ownStyles.serviceName}>
{/* TODO: missing colon */}
<Message {...appName} />
</div>
<div className={ownStyles.serviceContents}>
<ul>
<li>
<Message key="usernameHistory" defaultMessage="Username history" tagName="span" />
</li>
<li>
<Message key="oauthApps" defaultMessage="OAuth 2.0 applications" tagName="span" />
</li>
<li>
<Message key="minecraftServers" defaultMessage="Minecraft servers" tagName="span" />
</li>
</ul>
</div>
</div>
<div className={styles.delimiter} />
<div className={ownStyles.removableDataRow}>
<div className={ownStyles.serviceName}>Chrly:</div>
<div className={ownStyles.serviceContents}>
<ul>
<li>
<Message key="texturesData" defaultMessage="Textures data" tagName="span" />
</li>
</ul>
</div>
</div>
<div className={styles.delimiter} />
<div className={styles.formRow}>
<div className={styles.sectionTitle}>
<Message key="dataToBeImpersonalized" defaultMessage="Data to be impersonalized:" />
</div>
</div>
<div className={ownStyles.removableDataRow}>
<div className={ownStyles.serviceName}>
{/* TODO: missing colon */}
<Message {...siteName} />
</div>
<div className={ownStyles.serviceContents}>
<ul>
<li>
<Message key="uploadedSkins" defaultMessage="Uploaded skins" tagName="span" />
</li>
<li>
<Message key="comments" defaultMessage="Comments" tagName="span" />
</li>
</ul>
</div>
</div>
<div className={styles.formRow}>
<p className={styles.description}>
<Message
key="dataWontBeErasedImmediately"
defaultMessage="Data won't be erased immediately after account deletion. Within a week you'll be able to restore your account without losing any data."
/>
</p>
</div>
</div>
<Button type="submit" color="red" block>
<Message key="deleteAccount" defaultMessage="Delete account" />
</Button>
</div>
</div>
</Form>
);
export default DeleteAccount;

View File

@ -0,0 +1,35 @@
@import '~app/components/ui/fonts.scss';
.removableDataRow {
composes: formRow from '~app/components/profile/profileForm.scss';
display: flex;
}
.serviceName {
font-family: $font-family-title;
width: 50%;
color: #444;
}
.serviceContents {
width: 50%;
font-size: 12px;
color: #666;
li {
position: relative;
padding-left: 11px;
&:before {
content: '';
position: absolute;
left: 0;
top: 2px;
}
span {
line-height: 16px;
}
}
}

View File

@ -0,0 +1 @@
export { default } from './DeleteAccount';

View File

@ -18,7 +18,7 @@ const MfaStatus: ComponentType<Props> = ({ onProceed }) => (
<div className={mfaStyles.bigIcon}>
<span className={icons.lock} />
</div>
<p className={`${styles.description} ${mfaStyles.mfaTitle}`}>
<p className={mfaStyles.mfaTitle}>
<Message
key="mfaEnabledForYourAcc"
defaultMessage="Twofactor authentication for your account is active now"

View File

@ -2,9 +2,8 @@
@import '~app/components/ui/fonts.scss';
.mfaTitle {
font-size: 18px;
font-family: $font-family-title;
line-height: 1.2;
composes: sectionTitle from '~app/components/profile/profileForm.scss';
text-align: center;
margin-left: 17%;

View File

@ -84,6 +84,20 @@
margin-top: 25px;
}
.sectionTitle {
font-family: $font-family-title;
font-size: 18px;
line-height: 1.2;
color: #444;
margin-top: 25px;
}
.delimiter {
background: #eee;
height: 1px;
margin: 25px -30px;
}
.stepper {
width: 35%;
margin: 0 auto;

View File

@ -0,0 +1,36 @@
import React, { ComponentType, useCallback, useContext, useRef } from 'react';
import { useReduxDispatch } from 'app/functions';
import { changePassword } from 'app/services/api/accounts';
import { FormModel } from 'app/components/ui/form';
import DeleteAccount from 'app/components/profile/deleteAccount';
import { updateUser } from 'app/components/user/actions';
import ProfileContext from 'app/components/profile/Context';
const DeleteAccountPage: ComponentType = () => {
const context = useContext(ProfileContext);
const dispatch = useReduxDispatch();
const { current: form } = useRef(new FormModel());
const onSubmit = useCallback(
() =>
context
.onSubmit({
form,
// TODO: rework
sendData: () => changePassword(context.userId, form.serialize()),
})
.then(() => {
dispatch(
updateUser({
passwordChangedAt: Date.now() / 1000,
}),
);
context.goToProfile();
}),
[context],
);
return <DeleteAccount onSubmit={onSubmit} />;
};
export default DeleteAccountPage;

View File

@ -20,6 +20,7 @@ import ChangePasswordPage from 'app/pages/profile/ChangePasswordPage';
import ChangeUsernamePage from 'app/pages/profile/ChangeUsernamePage';
import ChangeEmailPage from 'app/pages/profile/ChangeEmailPage';
import MultiFactorAuthPage from 'app/pages/profile/MultiFactorAuthPage';
import DeleteAccountPage from 'app/pages/profile/DeleteAccountPage';
interface Props {
userId: number;
@ -50,6 +51,7 @@ const ProfileController: ComponentType<Props> = ({ userId, onSubmit, refreshUser
<Route path="/profile/change-password" exact component={ChangePasswordPage} />
<Route path="/profile/change-username" exact component={ChangeUsernamePage} />
<Route path="/profile/change-email/:step?/:code?" component={ChangeEmailPage} />
<Route path="/profile/delete" component={DeleteAccountPage} />
<Route path="/profile" exact component={Profile} />
<Route path="/" exact component={Profile} />
<Redirect to="/404" />