Skip to content

Commit 1484f07

Browse files
authored
Merge pull request #26 from docusign/task/MYM-28
Enhance logic with redux actions
2 parents e8d0910 + 7441493 commit 1484f07

File tree

31 files changed

+408
-248
lines changed

31 files changed

+408
-248
lines changed

client/src/App.jsx

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ import TriggerWorkflowAuthenticated from './pages/TriggerWorkflow/TriggerWorkflo
88
import TriggerWorkflowFormAuthenticated from './pages/TriggerWorkflowForm/TriggerWorkflowForm.jsx';
99
import { LoginStatus, ROUTE } from './constants.js';
1010
import { api } from './api';
11+
import {
12+
authorizeUser,
13+
closeLoadingCircleInPopup,
14+
closePopupWindow,
15+
openLoadingCircleInPopup,
16+
openPopupWindow,
17+
} from './store/actions';
1118

1219
function App() {
1320
const location = useLocation();
@@ -18,16 +25,16 @@ function App() {
1825

1926
useEffect(() => {
2027
const fetchCallback = async () => {
21-
if (code && code.length > 0) {
22-
const { data: userInfo } = await api.acg.callbackExecute(code);
23-
dispatch({
24-
type: 'LOGIN',
25-
payload: { authType: LoginStatus.ACG, userName: userInfo.name, userEmail: userInfo.email },
26-
});
27-
navigate(ROUTE.HOME);
28-
dispatch({ type: 'CLOSE_POPUP' });
29-
dispatch({ type: 'LOADED_POPUP' });
30-
}
28+
if (!code || code?.length <= 0) return;
29+
30+
dispatch(openPopupWindow());
31+
dispatch(openLoadingCircleInPopup());
32+
33+
const { data: userInfo } = await api.acg.callbackExecute(code);
34+
dispatch(authorizeUser(LoginStatus.ACG, userInfo.name, userInfo.email));
35+
navigate(ROUTE.HOME);
36+
dispatch(closePopupWindow());
37+
dispatch(closeLoadingCircleInPopup());
3138
};
3239

3340
fetchCallback();

client/src/api/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import axios from 'axios';
22
import { persistor, store } from '../store/store';
3+
import { clearAllState } from '../store/actions';
34

45
const isDev = process.env.NODE_ENV === 'development';
56
const apiUrl = isDev ? process.env.BACKEND_DEV_HOST : process.env.BACKEND_PROD_HOST;
@@ -13,7 +14,7 @@ instance.interceptors.response.use(
1314
response => response,
1415
err => {
1516
if (err?.response?.status === 401) {
16-
store.dispatch({ type: 'CLEAR_STATE' });
17+
store.dispatch(clearAllState());
1718
}
1819
throw err;
1920
}

client/src/components/Card/Card.jsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ import Dropdown from '../Dropdown/Dropdown.jsx';
66
import { WorkflowOptions } from '../../constants.js';
77
import CreateWorkflowMoreinfoPopup from '../Popups/CreateWorkflowMoreInfo/CreateWorkflowMoreInfo.jsx';
88
import textContent from '../../assets/text.json';
9+
import { openPopupWindow, closePopupWindow } from '../../store/actions';
910

1011
const Card = ({ img, title, description, linkTo, dropDown, moreInfo }) => {
11-
const [isBtsOpened, setBtsOpened] = useState(false);
12+
const [isBehindTheScenesOpened, setBehindTheScenesOpened] = useState(false);
1213
const dispatch = useDispatch();
13-
const isOpened = useSelector(state => state.popup.isOpened);
14+
const isPopupOpened = useSelector(state => state.popup.isOpened);
1415

1516
const togglePopup = async () => {
16-
setBtsOpened(!isBtsOpened);
17-
dispatch({ type: isOpened ? 'CLOSE_POPUP' : 'OPEN_POPUP' });
17+
setBehindTheScenesOpened(!isBehindTheScenesOpened);
18+
dispatch(!isPopupOpened ? openPopupWindow() : closePopupWindow());
1819
};
1920

2021
return (
@@ -39,7 +40,7 @@ const Card = ({ img, title, description, linkTo, dropDown, moreInfo }) => {
3940
)}
4041
<Dropdown options={WorkflowOptions} />
4142
</div>
42-
{isBtsOpened && <CreateWorkflowMoreinfoPopup togglePopup={togglePopup} />}
43+
{isBehindTheScenesOpened && <CreateWorkflowMoreinfoPopup togglePopup={togglePopup} />}
4344
</div>
4445
)}
4546
</div>

client/src/components/Dropdown/Dropdown.jsx

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,44 @@ import { useState } from 'react';
22
import { useDispatch, useSelector } from 'react-redux';
33
import styles from './Dropdown.module.css';
44
import WorkflowCreationPopup from '../Popups/WorkflowDefinitionCreation/WorkflowDefinitionCreation.jsx';
5-
import { api } from '../../api';
65
import textContent from '../../assets/text.json';
6+
import { api } from '../../api';
7+
import {
8+
openPopupWindow,
9+
closePopupWindow,
10+
openLoadingCircleInPopup,
11+
closeLoadingCircleInPopup,
12+
showErrorTextInPopup,
13+
clearErrorTextInPopup,
14+
saveCreatedWorkflow,
15+
clearCreatedWorkflowFromState,
16+
} from '../../store/actions';
717

818
const Dropdown = ({ options }) => {
919
const dispatch = useDispatch();
10-
const isOpened = useSelector(state => state.popup.isOpened);
20+
const isPopupOpened = useSelector(state => state.popup.isOpened);
1121
const [selectedDocument, setSelectedDocument] = useState(options[0].value);
1222

13-
const togglePopup = () => {
14-
dispatch({ type: isOpened ? 'CLOSE_POPUP' : 'OPEN_POPUP' });
15-
dispatch({ type: 'CLEAR_ERROR_POPUP' });
16-
dispatch({ type: 'CLEAR_CREATED_WORKFLOW' });
23+
const closePopup = () => {
24+
dispatch(closePopupWindow());
25+
dispatch(clearErrorTextInPopup());
26+
dispatch(clearCreatedWorkflowFromState());
1727
};
1828

1929
const handleCreateWorkflow = async ({ value, type }) => {
2030
setSelectedDocument(value);
21-
dispatch({ type: 'OPEN_POPUP' });
22-
dispatch({ type: 'LOADING_POPUP' });
31+
dispatch(openPopupWindow());
32+
dispatch(openLoadingCircleInPopup());
2333
const { status, data } = await api.workflows.createWorkflowDefinition(type);
2434

2535
if (status === 400) {
26-
dispatch({
27-
type: 'SET_ERROR_POPUP',
28-
payload: { errorMessage: data.message, errorHeader: null, templateName: data.templateName },
29-
});
30-
dispatch({ type: 'LOADED_POPUP' });
36+
dispatch(showErrorTextInPopup(null, data.message, data.templateName));
37+
dispatch(closeLoadingCircleInPopup());
3138
return;
3239
}
3340

34-
dispatch({ type: 'CREATED_WORKFLOW', payload: { workflowId: data.workflowDefinitionId } });
35-
dispatch({ type: 'LOADED_POPUP' });
41+
dispatch(saveCreatedWorkflow(data.workflowDefinitionId));
42+
dispatch(closeLoadingCircleInPopup());
3643
};
3744

3845
return (
@@ -59,9 +66,9 @@ const Dropdown = ({ options }) => {
5966
))}
6067
</div>
6168

62-
{isOpened && (
69+
{isPopupOpened && (
6370
<WorkflowCreationPopup
64-
togglePopup={togglePopup}
71+
togglePopup={closePopup}
6572
message={options.find(option => option.value === selectedDocument).message}
6673
/>
6774
)}

client/src/components/Header/Header.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import source from '../../assets/img/github-source.svg';
66
import textContent from '../../assets/text.json';
77
import { LoginStatus, ROUTE } from '../../constants.js';
88
import { api } from '../../api';
9+
import { clearAllState } from '../../store/actions';
910

1011
const Header = () => {
1112
const dispatch = useDispatch();
@@ -23,7 +24,7 @@ const Header = () => {
2324
await api.jwt.logout();
2425
}
2526

26-
dispatch({ type: 'CLEAR_STATE' });
27+
dispatch(clearAllState());
2728
};
2829

2930
return (

client/src/components/LoginForm/LoginForm.jsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,38 @@ import { useNavigate } from 'react-router-dom';
33
import { useDispatch } from 'react-redux';
44
import styles from './LoginForm.module.css';
55
import withPopup from '../../hocs/withPopup/withPopup.jsx';
6+
import textContent from '../../assets/text.json';
67
import { LoginStatus, ROUTE } from '../../constants.js';
78
import { api } from '../../api';
8-
import textContent from '../../assets/text.json';
9+
import {
10+
authorizeUser,
11+
closeLoadingCircleInPopup,
12+
closePopupWindow,
13+
openLoadingCircleInPopup,
14+
} from '../../store/actions';
915

10-
const LoginForm = ({ togglePopup, setLoading }) => {
16+
const LoginForm = ({ togglePopup }) => {
1117
const [authType, setAuthType] = useState(LoginStatus.ACG);
1218
const dispatch = useDispatch();
1319
const navigate = useNavigate();
1420

1521
const handleSubmit = async e => {
1622
e.preventDefault();
17-
dispatch({ type: 'LOADING_POPUP' });
23+
dispatch(openLoadingCircleInPopup());
1824

1925
try {
2026
if (authType === LoginStatus.JWT) {
2127
const { data: userInfo } = await api.jwt.login();
22-
dispatch({ type: 'LOGIN', payload: { authType, userName: userInfo.name, userEmail: userInfo.email } });
28+
dispatch(authorizeUser(authType, userInfo.name, userInfo.email));
2329
navigate(ROUTE.HOME);
24-
dispatch({ type: 'CLOSE_POPUP' });
25-
dispatch({ type: 'LOADED_POPUP' });
30+
dispatch(closePopupWindow());
31+
dispatch(closeLoadingCircleInPopup());
2632
}
2733
if (authType === LoginStatus.ACG) {
2834
api.acg.login();
2935
}
3036
} catch (error) {
31-
setLoading(false);
37+
dispatch(closeLoadingCircleInPopup());
3238
console.log(error);
3339
}
3440
};
@@ -55,9 +61,7 @@ const LoginForm = ({ togglePopup, setLoading }) => {
5561
/>
5662
{textContent.login.acg}
5763
</label>
58-
<label className={styles.subLabel}>
59-
{textContent.login.acgDescription}
60-
</label>
64+
<label className={styles.subLabel}>{textContent.login.acgDescription}</label>
6165
</div>
6266
<div className={styles.radioButtonWrapper}>
6367
<label className={styles.label}>
@@ -70,9 +74,7 @@ const LoginForm = ({ togglePopup, setLoading }) => {
7074
/>
7175
{textContent.login.jwt}
7276
</label>
73-
<label className={styles.subLabel}>
74-
{textContent.login.jwtDescription}
75-
</label>
77+
<label className={styles.subLabel}>{textContent.login.jwtDescription}</label>
7678
</div>
7779
</div>
7880
<div className={styles.formButtons}>

client/src/components/Popups/WorkflowDefinitionCreation/WorkflowDefinitionCreation.jsx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@ import styles from './WorkflowDefinitionCreation.module.css';
33
import withPopup from '../../../hocs/withPopup/withPopup.jsx';
44
import imgError from '../../../assets/img/workflow-trigger.svg';
55
import imgSuccess from '../../../assets/img/success.svg';
6-
import { api } from '../../../api';
76
import textContent from '../../../assets/text.json';
7+
import { api } from '../../../api';
8+
import {
9+
closeLoadingCircleInPopup,
10+
openLoadingCircleInPopup,
11+
showErrorTextInPopup,
12+
publishCreatedWorkflow,
13+
} from '../../../store/actions';
814

915
const WorkflowDefinitionCreation = ({ message }) => {
1016
const dispatch = useDispatch();
@@ -20,24 +26,24 @@ const WorkflowDefinitionCreation = ({ message }) => {
2026
const handlePublishWorkflow = async () => {
2127
if (!lastCreatedWorkflow.id) return;
2228

23-
dispatch({ type: 'LOADING_POPUP' });
29+
dispatch(openLoadingCircleInPopup());
2430
const workflow = await api.workflows.publishWorkflow(lastCreatedWorkflow.id);
2531

2632
if (workflow?.status === 200) {
27-
dispatch({ type: 'PUBLISHED_LAST_WORKFLOW' });
28-
dispatch({ type: 'LOADED_POPUP' });
33+
dispatch(publishCreatedWorkflow());
34+
dispatch(closeLoadingCircleInPopup());
2935
return;
3036
}
3137

32-
dispatch({
33-
type: 'SET_ERROR_POPUP',
34-
payload: {
35-
errorHeader: 'Publish workflow was unsuccessful',
36-
errorMessage: 'The Docusign server returned an error during the workflow publishing. Try again later.',
37-
templateName: null,
38-
},
39-
});
40-
dispatch({ type: 'LOADED_POPUP' });
38+
dispatch(
39+
showErrorTextInPopup(
40+
'Publish workflow was unsuccessful',
41+
'The Docusign server returned an error during the workflow publishing. Try again later.',
42+
null
43+
)
44+
);
45+
46+
dispatch(closeLoadingCircleInPopup());
4147
};
4248

4349
if (lastCreatedWorkflow?.isPublished) {

client/src/components/Popups/WorkflowTriggerResult/WorkflowTriggerResult.jsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ import { useDispatch } from 'react-redux';
33
import styles from './WorkflowTriggerResult.module.css';
44
import withPopup from '../../../hocs/withPopup/withPopup.jsx';
55
import imgSuccess from '../../../assets/img/success.svg';
6-
import { ROUTE } from '../../../constants.js';
76
import textContent from '../../../assets/text.json';
7+
import { ROUTE } from '../../../constants.js';
8+
import { closePopupWindow } from '../../../store/actions';
89

910
const WorkflowTriggerResult = ({ workflowInstanceUrl }) => {
1011
const navigate = useNavigate();
1112
const dispatch = useDispatch();
1213

1314
const handleFinishTrigger = async () => {
14-
dispatch({ type: 'CLOSE_POPUP' });
15+
dispatch(closePopupWindow());
1516
navigate(ROUTE.HOME);
1617
};
1718

@@ -20,7 +21,9 @@ const WorkflowTriggerResult = ({ workflowInstanceUrl }) => {
2021
<img src={imgSuccess} alt="" />
2122
<h2>{textContent.popups.workflowTriggered.title}</h2>
2223
<p>{textContent.popups.workflowTriggered.description}</p>
23-
<a href={workflowInstanceUrl} target="_blank" rel="noreferrer" onClick={handleFinishTrigger}>{textContent.buttons.continue}</a>
24+
<a href={workflowInstanceUrl} target="_blank" rel="noreferrer" onClick={handleFinishTrigger}>
25+
{textContent.buttons.continue}
26+
</a>
2427
</div>
2528
);
2629
};

0 commit comments

Comments
 (0)