Skip to content

Commit 8d03ef1

Browse files
committed
Further updates and fixes in the payments segment
1 parent 269a22b commit 8d03ef1

File tree

15 files changed

+265
-59
lines changed

15 files changed

+265
-59
lines changed

src/shared/actions/direct.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,27 @@ function dropAll() {
1414
return null;
1515
}
1616

17+
/**
18+
* Payload creator for the action that inits loading of the specified project
19+
* details.
20+
* @param {Number} projectId
21+
* @return {Number}
22+
*/
23+
function getProjectDetailsInit(projectId) {
24+
return projectId;
25+
}
26+
27+
/**
28+
* Payload creator for the action that actually loads the details of
29+
* the specified project.
30+
* @param {Number} projectId
31+
* @param {String} tokenV3 Topcoder auth token v3.
32+
* @return {Promise} Resolves to the project details object.
33+
*/
34+
function getProjectDetailsDone(projectId, tokenV3) {
35+
return getService(tokenV3).getProjectDetails(projectId);
36+
}
37+
1738
/**
1839
* Payload creator for the action that inits the loading of projects related to
1940
* the user.
@@ -38,6 +59,8 @@ async function getUserProjectsDone(tokenV3) {
3859
export default createActions({
3960
DIRECT: {
4061
DROP_ALL: dropAll,
62+
GET_PROJECT_DETAILS_INIT: getProjectDetailsInit,
63+
GET_PROJECT_DETAILS_DONE: getProjectDetailsDone,
4164
GET_USER_PROJECTS_INIT: getUserProjectsInit,
4265
GET_USER_PROJECTS_DONE: getUserProjectsDone,
4366
},

src/shared/actions/page/sandbox/payments/editor.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* Actions related to the UI state of payment editor page.
33
*/
44

5-
import _ from 'lodash';
65
import { createActions } from 'redux-actions';
76

87
/**
@@ -11,7 +10,7 @@ import { createActions } from 'redux-actions';
1110
* @return {String} Action payload.
1211
*/
1312
function selectProject(projectId) {
14-
return _.toString(projectId);
13+
return projectId;
1514
}
1615

1716
export default createActions({

src/shared/actions/page/sandbox/payments/listing.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@
22
* Actions related to the UI state of member payments listing page.
33
*/
44

5-
import _ from 'lodash';
65
import { createActions } from 'redux-actions';
76

87
/**
98
* Payload creator for the action that selects the specified project.
10-
* @param {String} projectId
9+
* @param {Number} projectId
1110
* @return {String} Action payload.
1211
*/
1312
function selectProject(projectId) {
14-
return _.toString(projectId);
13+
return projectId;
1514
}
1615

1716
export default createActions({

src/shared/components/sandbox/payments/Background/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default function Background({ children, onExit, escapeButton }) {
3030

3131
Background.defaultProps = {
3232
children: null,
33-
escapeButton: true,
33+
escapeButton: false,
3434
onExit: () => {},
3535
};
3636

src/shared/components/sandbox/payments/Editor/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export default function Editor({
1818
selectProject,
1919
}) {
2020
return (
21-
<Background>
21+
<Background escapeButton>
2222
<div styleName="container">
2323
<h1 styleName="title">New Member Payment</h1>
2424
<div styleName="form">
@@ -79,6 +79,6 @@ export default function Editor({
7979

8080
Editor.propTypes = {
8181
projects: PT.arrayOf(PT.object).isRequired,
82-
selectedProjectId: PT.string.isRequired,
82+
selectedProjectId: PT.number.isRequired,
8383
selectProject: PT.func.isRequired,
8484
};

src/shared/components/sandbox/payments/Listing/PaymentRow/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import './style.scss';
1313

1414
export default function PaymentRow({ challenge }) {
1515
return (
16-
<tr styleName="paymentRow" key={challenge.id}>
16+
<tr styleName="paymentRow">
1717
<td styleName="icon">
1818
<TrackAbbreviationTooltip track={challenge.track} subTrack={challenge.subTrack}>
1919
<span>

src/shared/components/sandbox/payments/Listing/index.jsx

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,45 @@ export default function Listing({
1919
selectProject,
2020
}) {
2121
const selectedProjectIdNum = Number(selectedProjectId);
22-
const content = memberTasks
22+
let content = memberTasks
2323
.filter(item => item.projectId === selectedProjectIdNum)
24-
.map(challenge => <PaymentRow challenge={challenge} />);
24+
.map(challenge => (
25+
<PaymentRow
26+
challenge={challenge}
27+
key={challenge.id}
28+
/>
29+
));
30+
31+
if (content.length) {
32+
content = (
33+
<table styleName="table">
34+
<thead>
35+
<tr>
36+
<th />
37+
<th styleName="name">Payment</th>
38+
<th>Amount</th>
39+
<th>Member</th>
40+
<th>Status</th>
41+
</tr>
42+
</thead>
43+
<tbody>
44+
{content}
45+
{
46+
loadingMemberTasks ? (
47+
<tr>
48+
<td colSpan={5}>
49+
<LoadingIndicator />
50+
</td>
51+
</tr>
52+
) : null
53+
}
54+
</tbody>
55+
</table>
56+
);
57+
} else if (loadingMemberTasks) {
58+
content = <LoadingIndicator />;
59+
} else content = 'No member payments associated with this project so far';
60+
2561
return (
2662
<Background>
2763
<div styleName="container">
@@ -43,29 +79,7 @@ export default function Listing({
4379
>New payment</PrimaryButton>
4480
</div>
4581
</div>
46-
<table styleName="table">
47-
<thead>
48-
<tr>
49-
<th />
50-
<th styleName="name">Payment</th>
51-
<th>Amount</th>
52-
<th>Member</th>
53-
<th>Status</th>
54-
</tr>
55-
</thead>
56-
<tbody>
57-
{content}
58-
{
59-
loadingMemberTasks ? (
60-
<tr>
61-
<td colSpan={5}>
62-
<LoadingIndicator />
63-
</td>
64-
</tr>
65-
) : null
66-
}
67-
</tbody>
68-
</table>
82+
{content}
6983
</div>
7084
</Background>
7185
);
@@ -75,6 +89,6 @@ Listing.propTypes = {
7589
loadingMemberTasks: PT.bool.isRequired,
7690
memberTasks: PT.arrayOf(PT.shape()).isRequired,
7791
projects: PT.arrayOf(PT.shape()).isRequired,
78-
selectedProjectId: PT.string.isRequired,
92+
selectedProjectId: PT.number.isRequired,
7993
selectProject: PT.func.isRequired,
8094
};

src/shared/containers/sandbox/payments/Editor.jsx

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,37 @@
11
/**
22
* Payment editor.
33
*/
4+
/* NOTE: Many props in this module are consumed indirectly via helper functions,
5+
* ESLint is not able to track them, hence the rule is disabled for now. */
6+
/* eslint-disable react/no-unused-prop-types */
47

58
import _ from 'lodash';
69
import actions from 'actions';
710
import Editor from 'components/sandbox/payments/Editor';
11+
import LoadingIndicator from 'components/LoadingIndicator';
812
import PT from 'prop-types';
913
import React from 'react';
1014
import { connect } from 'react-redux';
15+
import { goToLogin } from 'utils/tc';
16+
17+
/**
18+
* Handles the loading of project details, if necessary for the specified set
19+
* of props.
20+
* @param {Object} props
21+
*/
22+
function handleProjectDetailsLoading(props) {
23+
const {
24+
loadingProjectDetailsForId,
25+
loadProjectDetails,
26+
projectDetails,
27+
selectedProjectId,
28+
tokenV3,
29+
} = props;
30+
if (!projectDetails && selectedProjectId
31+
&& selectedProjectId !== loadingProjectDetailsForId) {
32+
loadProjectDetails(selectedProjectId, tokenV3);
33+
}
34+
}
1135

1236
class EditorContainer extends React.Component {
1337
componentDidMount() {
@@ -20,12 +44,15 @@ class EditorContainer extends React.Component {
2044
tokenV3,
2145
username,
2246
} = this.props;
47+
if (!tokenV3) return goToLogin();
2348
if (username && username !== loadingProjectsForUsername) {
2449
loadProjects(tokenV3);
2550
}
2651
if (!selectedProjectId && projects.length) {
2752
selectProject(projects[0].id);
2853
}
54+
handleProjectDetailsLoading(this.props);
55+
return undefined;
2956
}
3057

3158
componentWillReceiveProps(nextProps) {
@@ -38,6 +65,7 @@ class EditorContainer extends React.Component {
3865
tokenV3,
3966
username,
4067
} = nextProps;
68+
if (!tokenV3) return goToLogin();
4169
const {
4270
projects: oldProjects,
4371
username: oldUsername,
@@ -57,14 +85,18 @@ class EditorContainer extends React.Component {
5785
)) {
5886
selectProject(projects[0].id);
5987
}
88+
handleProjectDetailsLoading(nextProps);
89+
return undefined;
6090
}
6191

6292
render() {
6393
const {
6494
projects,
6595
selectedProjectId,
6696
selectProject,
97+
tokenV3,
6798
} = this.props;
99+
if (!tokenV3) return <LoadingIndicator />;
68100
return (
69101
<Editor
70102
projects={projects}
@@ -75,11 +107,18 @@ class EditorContainer extends React.Component {
75107
}
76108
}
77109

110+
EditorContainer.defaultProps = {
111+
projectDetails: null,
112+
};
113+
78114
EditorContainer.propTypes = {
115+
loadingProjectDetailsForId: PT.number.isRequired,
79116
loadingProjectsForUsername: PT.string.isRequired,
117+
loadProjectDetails: PT.func.isRequired,
80118
loadProjects: PT.func.isRequired,
119+
projectDetails: PT.shape(),
81120
projects: PT.arrayOf(PT.object).isRequired,
82-
selectedProjectId: PT.string.isRequired,
121+
selectedProjectId: PT.number.isRequired,
83122
selectProject: PT.func.isRequired,
84123
tokenV3: PT.string.isRequired,
85124
username: PT.string.isRequired,
@@ -88,8 +127,16 @@ EditorContainer.propTypes = {
88127
function mapStateToProps(state) {
89128
const { auth, direct } = state;
90129
const page = state.page.sandbox.payments.editor;
130+
131+
let projectDetails = direct.projectDetails;
132+
if (_.get(projectDetails, 'project.projectId') !== page.selectedProjectId) {
133+
projectDetails = null;
134+
}
135+
91136
return {
137+
loadingProjectDetailsForId: direct.loadingProjectDetailsForId,
92138
loadingProjectsForUsername: direct.loadingProjectsForUsername,
139+
projectDetails,
93140
projects: direct.projects,
94141
selectedProjectId: page.selectedProjectId,
95142
tokenV3: auth.tokenV3,
@@ -101,6 +148,10 @@ function mapDispatchToProps(dispatch) {
101148
const { direct } = actions;
102149
const page = actions.page.sandbox.payments.editor;
103150
return {
151+
loadProjectDetails: (projectId, tokenV3) => {
152+
dispatch(direct.getProjectDetailsInit(projectId));
153+
dispatch(direct.getProjectDetailsDone(projectId, tokenV3));
154+
},
104155
loadProjects: (tokenV3) => {
105156
dispatch(direct.getUserProjectsInit(tokenV3));
106157
dispatch(direct.getUserProjectsDone(tokenV3));

0 commit comments

Comments
 (0)