Skip to content

Commit 0823e31

Browse files
committed
Adding account deletion feature
1 parent 5dcc2e8 commit 0823e31

12 files changed

Lines changed: 372 additions & 352 deletions

File tree

package-lock.json

Lines changed: 212 additions & 346 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"jest-when": "^2.3.1",
4747
"mini-css-extract-plugin": "^0.4.5",
4848
"mkdirp": "^0.5.1",
49-
"node-sass": "^4.10.0",
49+
"node-sass": "^4.14.1",
5050
"prettier": "^2.0.2",
5151
"react-test-renderer": "^16.8.6",
5252
"redux-saga-test-plan": "^3.7.0",
@@ -73,9 +73,9 @@
7373
"dot-prop-immutable": "^1.5.0",
7474
"history": "^4.7.2",
7575
"immutable": "^4.0.0-rc.12",
76-
"jquery": "^3.3.1",
76+
"jquery": "^3.5.1",
7777
"local-storage": "^1.4.2",
78-
"lodash": "^4.17.11",
78+
"lodash": "^4.17.20",
7979
"promise": "^8.0.2",
8080
"prop-types": "^15.6.2",
8181
"query-string": "^6.2.0",
@@ -99,7 +99,7 @@
9999
"simple-line-icons": "^2.4.1",
100100
"styled-components": "^4.1.2",
101101
"webpack": "^4.26.1",
102-
"webpack-dev-server": "^3.2.1"
102+
"webpack-dev-server": "^3.11.0"
103103
},
104104
"scripts": {
105105
"start": "webpack-dev-server --history-api-fallback --config webpack.dev.js",

src/display/shared/modals/ModalContainer.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const propTypes = {
2828
closeUpsertCharacterModal: PropTypes.func.isRequired,
2929
closeUpsertPublicViewModal: PropTypes.func.isRequired,
3030
closeUpsertThreadModal: PropTypes.func.isRequired,
31+
closeDeleteAccountConfirmationModal: PropTypes.func.isRequired,
3132
deletePublicView: PropTypes.func.isRequired,
3233
isBulkUntrackThreadsModalOpen: PropTypes.bool.isRequired,
3334
isBulkUpdateTagModalOpen: PropTypes.bool.isRequired,
@@ -38,6 +39,7 @@ const propTypes = {
3839
isUpsertCharacterModalOpen: PropTypes.bool.isRequired,
3940
isUpsertPublicViewModalOpen: PropTypes.bool.isRequired,
4041
isUpsertThreadModalOpen: PropTypes.bool.isRequired,
42+
isDeleteAccountConfirmationModalOpen: PropTypes.bool.isRequired,
4143
sortedCharacters: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
4244
sortedTags: PropTypes.arrayOf(PropTypes.string).isRequired,
4345
threadToEdit: PropTypes.shape({
@@ -48,6 +50,7 @@ const propTypes = {
4850
upsertCharacter: PropTypes.func.isRequired,
4951
upsertPublicView: PropTypes.func.isRequired,
5052
upsertThread: PropTypes.func.isRequired,
53+
submitUserAccountDeletion: PropTypes.func.isRequired,
5154
tagToEdit: PropTypes.shape({
5255
selectedTag: PropTypes.string,
5356
updatedValue: PropTypes.string
@@ -71,6 +74,7 @@ function mapStateToProps(state) {
7174
isDeletePublicViewModalOpen: ui.isDeletePublicViewModalOpen,
7275
isBulkUpdateTagModalOpen: ui.isBulkUpdateTagModalOpen,
7376
isBulkDeleteTagModalOpen: ui.isBulkDeleteTagModalOpen,
77+
isDeleteAccountConfirmationModalOpen: ui.isDeleteAccountConfirmationModalOpen,
7478
characterToEdit,
7579
threadToEdit,
7680
bulkThreadsToEdit,
@@ -97,6 +101,7 @@ const ModalContainer = (props) => {
97101
closeUpsertCharacterModal,
98102
closeUpsertPublicViewModal,
99103
closeUpsertThreadModal,
104+
closeDeleteAccountConfirmationModal,
100105
deletePublicView,
101106
isBulkUntrackThreadsModalOpen,
102107
isBulkUpdateTagModalOpen,
@@ -107,6 +112,7 @@ const ModalContainer = (props) => {
107112
isUpsertCharacterModalOpen,
108113
isUpsertPublicViewModalOpen,
109114
isUpsertThreadModalOpen,
115+
isDeleteAccountConfirmationModalOpen,
110116
sortedCharacters,
111117
sortedTags,
112118
threadToEdit,
@@ -116,7 +122,8 @@ const ModalContainer = (props) => {
116122
upsertPublicView,
117123
upsertThread,
118124
viewToEdit,
119-
tagToEdit
125+
tagToEdit,
126+
submitUserAccountDeletion
120127
} = props;
121128
return (
122129
<div>
@@ -231,6 +238,22 @@ const ModalContainer = (props) => {
231238
</span>
232239
}
233240
/>
241+
<GenericConfirmationModal
242+
isModalOpen={isDeleteAccountConfirmationModalOpen}
243+
submitCallback={submitUserAccountDeletion}
244+
submitButtonText="Confirm Deletion"
245+
closeCallback={closeDeleteAccountConfirmationModal}
246+
closeButtonText="Cancel"
247+
data={null}
248+
headerText="Really Delete Account?"
249+
bodyText={
250+
<span>
251+
Are you sure you want to delete your account? <strong>This action cannot be undone.</strong>{' '}
252+
You will be unable to access any tracked characters or threads in the future,{' '}
253+
unless you create a new account and re-add them.
254+
</span>
255+
}
256+
/>
234257
</div>
235258
);
236259
};
@@ -249,7 +272,9 @@ export default connect(mapStateToProps, {
249272
closeUpsertCharacterModal: actions.closeUpsertCharacterModal,
250273
closeUpsertPublicViewModal: actions.closeUpsertPublicViewModal,
251274
closeUpsertThreadModal: actions.closeUpsertThreadModal,
275+
closeDeleteAccountConfirmationModal: actions.closeDeleteAccountConfirmationModal,
252276
deletePublicView: actions.deletePublicView,
277+
submitUserAccountDeletion: actions.submitUserAccountDeletion,
253278
untrackCharacter: actions.untrackCharacter,
254279
untrackThread: actions.untrackThread,
255280
upsertCharacter: actions.upsertCharacter,

src/display/views/settings/Settings.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
44
import { connect } from 'react-redux';
55
import ChangePasswordPane from './components/ChangePasswordPane';
66
import UpdateAccountInfoPane from './components/UpdateAccountInfoPane';
7+
import DeleteAccountPane from './components/DeleteAccountPane';
78
import * as actions from '../../../infrastructure/actions';
89
import TabContent from '../../shared/styled/TabContent';
910
import StaticTabNav from '../../shared/static/StaticTabNav';
@@ -14,6 +15,7 @@ const propTypes = {
1415
user: PropTypes.shape({}).isRequired,
1516
submitUserChangePassword: PropTypes.func.isRequired,
1617
submitUserAccountInfo: PropTypes.func.isRequired,
18+
openDeleteAccountConfirmationModal: PropTypes.func.isRequired,
1719
match: PropTypes.shape({
1820
url: PropTypes.string,
1921
params: PropTypes.shape({
@@ -32,6 +34,10 @@ function mapStateToProps(state) {
3234
const Settings = (props) => {
3335
const { user, submitUserChangePassword, submitUserAccountInfo, match } = props;
3436
const options = Object.values(tabs.SETTINGS);
37+
const onDeleteAccountClicked = (e) => {
38+
e.preventDefault();
39+
props.openDeleteAccountConfirmationModal();
40+
}
3541
return (
3642
<div className="animated fadeIn static-container settings-container">
3743
<Row>
@@ -54,6 +60,7 @@ const Settings = (props) => {
5460
submitAccountInfoForm={submitUserAccountInfo}
5561
user={user}
5662
/>
63+
<DeleteAccountPane onDeleteAccountClicked={onDeleteAccountClicked} />
5764
</TabContent>
5865
</Col>
5966
</Row>
@@ -64,5 +71,6 @@ const Settings = (props) => {
6471
Settings.propTypes = propTypes;
6572
export default connect(mapStateToProps, {
6673
submitUserChangePassword: actions.submitUserChangePassword,
67-
submitUserAccountInfo: actions.submitUserAccountInfo
74+
submitUserAccountInfo: actions.submitUserAccountInfo,
75+
openDeleteAccountConfirmationModal: actions.openDeleteAccountConfirmationModal
6876
})(Settings);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { TabPane, Button, CardHeader, CardBody } from 'reactstrap';
4+
import Card from '../../../shared/styled/Card';
5+
6+
const propTypes = {
7+
onDeleteAccountClicked: PropTypes.func.isRequired
8+
};
9+
const DeleteAccountPane = ({ onDeleteAccountClicked }) => {
10+
return (
11+
<TabPane tabId="delete-account">
12+
<Card>
13+
<CardHeader>
14+
<i className="fas fa-trash-alt" /> Delete Account
15+
</CardHeader>
16+
<CardBody className="card-body text-center">
17+
<Button type="submit" color="danger" onClick={onDeleteAccountClicked}>
18+
Delete Account
19+
</Button>
20+
</CardBody>
21+
</Card>
22+
</TabPane>
23+
);
24+
}
25+
DeleteAccountPane.propTypes = propTypes;
26+
export default DeleteAccountPane;

src/infrastructure/actions/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ export {
1111
OPEN_DELETE_PUBLIC_VIEW_MODAL,
1212
openDeletePublicViewModal
1313
} from './ui/deletePublicViewModal';
14+
export {
15+
CLOSE_DELETE_ACCOUNT_CONFIRMATION_MODAL,
16+
closeDeleteAccountConfirmationModal,
17+
OPEN_DELETE_ACCOUNT_CONFIRMATION_MODAL,
18+
openDeleteAccountConfirmationModal
19+
} from './ui/deleteAccountConfirmationModal';
1420
export {
1521
CLOSE_UNTRACK_CHARACTER_MODAL,
1622
closeUntrackCharacterModal,
@@ -197,6 +203,14 @@ export {
197203
submitUserChangePasswordFailure,
198204
submitUserChangePasswordSuccess
199205
} from './user/submitUserChangePassword';
206+
export {
207+
SUBMIT_USER_ACCOUNT_DELETION,
208+
SUBMIT_USER_ACCOUNT_DELETION_FAILURE,
209+
SUBMIT_USER_ACCOUNT_DELETION_SUCCESS,
210+
submitUserAccountDeletion,
211+
submitUserAccountDeletionFailure,
212+
submitUserAccountDeletionSuccess
213+
} from './user/submitUserAccountDeletion';
200214
export {
201215
SUBMIT_USER_FORGOT_PASSWORD_FAILURE,
202216
SUBMIT_USER_FORGOT_PASSWORD_SUCCESS,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const CLOSE_DELETE_ACCOUNT_CONFIRMATION_MODAL = 'CLOSE_DELETE_ACCOUNT_CONFIRMATION_MODAL';
2+
export function closeDeleteAccountConfirmationModal() {
3+
return {
4+
type: CLOSE_DELETE_ACCOUNT_CONFIRMATION_MODAL
5+
};
6+
}
7+
export const OPEN_DELETE_ACCOUNT_CONFIRMATION_MODAL = 'OPEN_DELETE_ACCOUNT_CONFIRMATION_MODAL';
8+
export function openDeleteAccountConfirmationModal() {
9+
return {
10+
type: OPEN_DELETE_ACCOUNT_CONFIRMATION_MODAL
11+
};
12+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import analytics from '../../constants/analytics';
2+
3+
export const SUBMIT_USER_ACCOUNT_DELETION = 'SUBMIT_USER_ACCOUNT_DELETION';
4+
export function submitUserAccountDeletion() {
5+
return {
6+
type: SUBMIT_USER_ACCOUNT_DELETION,
7+
analytics: {
8+
func: analytics.funcs.EVENT,
9+
event: {
10+
category: analytics.categories.ACCOUNT,
11+
action: 'Deleted account'
12+
}
13+
}
14+
};
15+
}
16+
export const SUBMIT_USER_ACCOUNT_DELETION_FAILURE = 'SUBMIT_USER_ACCOUNT_DELETION_FAILURE';
17+
export function submitUserAccountDeletionFailure(data) {
18+
return {
19+
type: SUBMIT_USER_ACCOUNT_DELETION_FAILURE,
20+
data
21+
};
22+
}
23+
export const SUBMIT_USER_ACCOUNT_DELETION_SUCCESS = 'SUBMIT_USER_ACCOUNT_DELETION_SUCCESS';
24+
export function submitUserAccountDeletionSuccess() {
25+
return {
26+
type: SUBMIT_USER_ACCOUNT_DELETION_SUCCESS
27+
};
28+
}

src/infrastructure/constants/tabs.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ export default {
2525
CHANGE_USERNAME: {
2626
href: '/settings/change-username',
2727
name: 'Change Username/Email'
28+
},
29+
DELETE_ACCOUNT: {
30+
href: '/settings/delete-account',
31+
name: 'Delete Account'
2832
}
2933
},
3034
TOOLS: {

src/infrastructure/reducers/ui.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import {
77
CLOSE_UPSERT_CHARACTER_MODAL,
88
CLOSE_UPSERT_PUBLIC_VIEW_MODAL,
99
CLOSE_UPSERT_THREAD_MODAL,
10+
CLOSE_DELETE_ACCOUNT_CONFIRMATION_MODAL,
1011
OPEN_BULK_UNTRACK_THREADS_MODAL,
1112
OPEN_UNTRACK_CHARACTER_MODAL,
1213
OPEN_UNTRACK_THREAD_MODAL,
1314
OPEN_UPSERT_CHARACTER_MODAL,
1415
OPEN_UPSERT_PUBLIC_VIEW_MODAL,
1516
OPEN_UPSERT_THREAD_MODAL,
17+
OPEN_DELETE_ACCOUNT_CONFIRMATION_MODAL,
1618
SUBMIT_USER_LOGOUT,
1719
TOGGLE_HEADER_PROFILE_DROPDOWN,
1820
TOGGLE_HEADER_ADD_MENU_DROPDOWN,
@@ -54,6 +56,7 @@ const defaultState = {
5456
isDeletePublicViewModalOpen: false,
5557
isBulkUpdateTagModalOpen: false,
5658
isBulkDeleteTagModalOpen: false,
59+
isDeleteAccountConfirmationModalOpen: false,
5760
useLightTheme: false
5861
};
5962

@@ -142,6 +145,14 @@ function ui(state = defaultState, action) {
142145
return Object.assign({}, state, {
143146
isDeletePublicViewModalOpen: false
144147
});
148+
case OPEN_DELETE_ACCOUNT_CONFIRMATION_MODAL:
149+
return Object.assign({}, state, {
150+
isDeleteAccountConfirmationModalOpen: true
151+
});
152+
case CLOSE_DELETE_ACCOUNT_CONFIRMATION_MODAL:
153+
return Object.assign({}, state, {
154+
isDeleteAccountConfirmationModalOpen: false
155+
});
145156
case OPEN_BULK_UPDATE_TAG_MODAL:
146157
return Object.assign({}, state, {
147158
isBulkUpdateTagModalOpen: true

0 commit comments

Comments
 (0)