Skip to content

Commit a282fce

Browse files
authored
Merge pull request #7236 from topcoder-platform/develop
PM-5516
2 parents 540f940 + 553185c commit a282fce

9 files changed

Lines changed: 148 additions & 34 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { resolveSubmissionMode } from 'components/SubmissionPage/Submit';
2+
3+
const topgearCommunitiesList = {
4+
data: [
5+
{
6+
groupIds: ['wipro-group-id'],
7+
mainSubdomain: 'topgear',
8+
},
9+
],
10+
loadingUuid: '',
11+
timestamp: Date.now(),
12+
};
13+
14+
describe('resolveSubmissionMode', () => {
15+
test('uses zip upload when submission_type metadata is zip', () => {
16+
expect(resolveSubmissionMode(
17+
[{ name: 'submission_type', value: 'zip' }],
18+
['wipro-group-id'],
19+
topgearCommunitiesList,
20+
)).toEqual({
21+
isLoadingCommunitiesList: false,
22+
isUrlSubmission: false,
23+
});
24+
});
25+
26+
test('uses URL upload when submission_type metadata is url', () => {
27+
expect(resolveSubmissionMode(
28+
[{ name: 'submission_type', value: 'url' }],
29+
[],
30+
topgearCommunitiesList,
31+
)).toEqual({
32+
isLoadingCommunitiesList: false,
33+
isUrlSubmission: true,
34+
});
35+
});
36+
37+
test('falls back to URL upload for Topgear groups when metadata is absent', () => {
38+
expect(resolveSubmissionMode(
39+
[],
40+
['wipro-group-id'],
41+
topgearCommunitiesList,
42+
)).toEqual({
43+
isLoadingCommunitiesList: false,
44+
isUrlSubmission: true,
45+
});
46+
});
47+
48+
test('waits for communities list before applying the legacy group fallback', () => {
49+
expect(resolveSubmissionMode(
50+
[],
51+
['wipro-group-id'],
52+
{
53+
data: [],
54+
loadingUuid: '',
55+
timestamp: 0,
56+
},
57+
)).toEqual({
58+
isLoadingCommunitiesList: true,
59+
isUrlSubmission: false,
60+
});
61+
});
62+
});

__tests__/shared/utils/terms.test.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@ describe('terms utils', () => {
1212
expect(isNdaTerm({ title: 'Assignment Terms' })).toBe(false);
1313
});
1414

15-
test('uses configured DocuSign template for NDA terms', () => {
15+
test('uses terms-service DocuSign template for NDA terms when present', () => {
1616
expect(getDocuSignTemplateIdForTerm({
1717
docusignTemplateId: 'old-template-id',
1818
title: 'Appirio NDA v2.0',
19+
})).toBe('old-template-id');
20+
});
21+
22+
test('uses configured DocuSign template for NDA terms without a template id', () => {
23+
expect(getDocuSignTemplateIdForTerm({
24+
title: 'Appirio NDA v2.0',
1925
})).toBe(NEW_NDA_TEMPLATE_ID);
2026
});
2127

config/backup-default.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ module.exports = {
7070
* agreement flow. */
7171
MOCK_TERMS_SERVICE: false,
7272

73-
/* Optional DocuSign template override for NDA-like terms. When set, the
74-
* terms modal requests this template for terms whose title includes NDA or
75-
* Non-Disclosure, even if the Terms API still returns an older template id.
73+
/* Optional DocuSign template fallback for NDA-like terms. The terms modal
74+
* prefers the template id returned by the Terms API because backend
75+
* completion is persisted against that same template id.
7676
*/
7777
NDA_DOCUSIGN_TEMPLATE_ID: '400b989d-1c75-4889-b6f6-421e1f924709',
7878

config/default.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ module.exports = {
7272
* agreement flow. */
7373
MOCK_TERMS_SERVICE: false,
7474

75-
/* Optional DocuSign template override for NDA-like terms. When set, the
76-
* terms modal requests this template for terms whose title includes NDA or
77-
* Non-Disclosure, even if the Terms API still returns an older template id.
75+
/* Optional DocuSign template fallback for NDA-like terms. The terms modal
76+
* prefers the template id returned by the Terms API because backend
77+
* completion is persisted against that same template id.
7878
*/
7979
NDA_DOCUSIGN_TEMPLATE_ID: '400b989d-1c75-4889-b6f6-421e1f924709',
8080

src/shared/components/SubmissionPage/FilestackFilePicker/index.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
*
55
* Description:
66
* Component for uploading a file using Filestack Picker
7-
* and Drag + Drop. Does not store the file contents in form. Instead,
7+
* and Drag + Drop, or accepting a URL for Topgear submissions.
8+
* Does not store the file contents in form. Instead,
89
* uploads file to S3 storage container and sets the
910
* S3 storage details to Redux store for submission.
1011
*/

src/shared/components/SubmissionPage/Submit/index.jsx

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
*
55
* Description:
66
* Page that is shown when a user is trying to submit a Submission.
7-
* Allows user to upload Submission.zip file using a Filestack plugin.
7+
* Allows users to submit either a standard zip upload or a Topgear URL,
8+
* depending on challenge metadata and legacy Topgear group defaults.
89
*/
910
/* eslint-env browser */
1011

@@ -21,6 +22,58 @@ import FilestackFilePicker from '../FilestackFilePicker';
2122
import Uploading from '../Uploading';
2223
import style from './styles.scss';
2324

25+
const SUBMISSION_TYPE_METADATA_FIELD = 'submission_type';
26+
const SUBMISSION_TYPE_URL = 'url';
27+
const SUBMISSION_TYPE_ZIP = 'zip';
28+
29+
/**
30+
* Resolves which submission experience should be shown for the challenge.
31+
* Explicit `submission_type` metadata wins over the historical Topgear group
32+
* check. When the metadata is absent or invalid, the current fallback remains:
33+
* Topgear/Wipro challenges use URL submission and all others use zip upload.
34+
*
35+
* @param {Array<Object>} metadata Challenge metadata entries.
36+
* @param {Array<String>} groups Challenge group ids.
37+
* @param {Object} communitiesList Loaded community metadata from Redux.
38+
* @return {{isLoadingCommunitiesList: Boolean, isUrlSubmission: Boolean}}
39+
*/
40+
export function resolveSubmissionMode(metadata, groups, communitiesList) {
41+
const submissionType = _.toLower(_.toString(_.get(
42+
_.find(metadata, { name: SUBMISSION_TYPE_METADATA_FIELD }),
43+
'value',
44+
'',
45+
)).trim());
46+
47+
if (submissionType === SUBMISSION_TYPE_ZIP || submissionType === SUBMISSION_TYPE_URL) {
48+
return {
49+
isLoadingCommunitiesList: false,
50+
isUrlSubmission: submissionType === SUBMISSION_TYPE_URL,
51+
};
52+
}
53+
54+
if (_.isEmpty(groups)) {
55+
return {
56+
isLoadingCommunitiesList: false,
57+
isUrlSubmission: false,
58+
};
59+
}
60+
61+
if (!communitiesList.timestamp) {
62+
return {
63+
isLoadingCommunitiesList: true,
64+
isUrlSubmission: false,
65+
};
66+
}
67+
68+
const topGearCommunity = _.find(communitiesList.data, { mainSubdomain: 'topgear' });
69+
const topGearGroupIds = _.get(topGearCommunity, 'groupIds', []);
70+
71+
return {
72+
isLoadingCommunitiesList: false,
73+
isUrlSubmission: _.some(groups, groupId => groupId && _.includes(topGearGroupIds, groupId)),
74+
};
75+
}
76+
2477
/**
2578
* Submissions Page shown to develop challengers.
2679
*/
@@ -137,31 +190,15 @@ class Submit extends React.Component {
137190
setSubmissionFilestackData,
138191
submitForm,
139192
groups,
193+
metadata,
140194
} = this.props;
141195

142196
const id = 'file-picker-submission';
143-
144-
let isLoadingCommunitiesList = false;
145-
let isChallengeBelongToTopgearGroup = false;
146-
// check if challenge belong to any group
147-
if (!_.isEmpty(groups)) {
148-
// check if communitiesList is loaded
149-
if (communitiesList.timestamp > 0) {
150-
const topGearCommunity = _.find(communitiesList.data, { mainSubdomain: 'topgear' });
151-
if (topGearCommunity) {
152-
// check the group info match with group list
153-
_.forOwn(groups, (value) => {
154-
if (value && _.includes(topGearCommunity.groupIds, value)) {
155-
isChallengeBelongToTopgearGroup = true;
156-
return false;
157-
}
158-
return true;
159-
});
160-
}
161-
} else {
162-
isLoadingCommunitiesList = true;
163-
}
164-
}
197+
const submissionMode = resolveSubmissionMode(metadata, groups, communitiesList);
198+
const {
199+
isLoadingCommunitiesList,
200+
isUrlSubmission: isChallengeBelongToTopgearGroup,
201+
} = submissionMode;
165202

166203
const submissionInstruction = isChallengeBelongToTopgearGroup ? (
167204
<div>
@@ -427,6 +464,7 @@ Submit.propTypes = {
427464
timestamp: PT.number.isRequired,
428465
}).isRequired,
429466
groups: PT.arrayOf(PT.shape()).isRequired,
467+
metadata: PT.arrayOf(PT.shape()).isRequired,
430468
isSubmitting: PT.bool.isRequired,
431469
submitDone: PT.bool.isRequired,
432470
errorMsg: PT.string,

src/shared/components/SubmissionPage/index.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ SubmissionsPage.propTypes = {
8787
timestamp: PT.number.isRequired,
8888
}).isRequired,
8989
groups: PT.arrayOf(PT.shape()).isRequired,
90+
metadata: PT.arrayOf(PT.shape()).isRequired,
9091
track: PT.string.isRequired,
9192
status: PT.string.isRequired,
9293
submitForm: PT.func.isRequired,

src/shared/containers/SubmissionPage.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ SubmissionsPageContainer.propTypes = {
139139
status: PT.string.isRequired,
140140
isRegistered: PT.bool.isRequired,
141141
groups: PT.arrayOf(PT.shape()).isRequired,
142+
metadata: PT.arrayOf(PT.shape()).isRequired,
142143
errorMsg: PT.string.isRequired,
143144
isSubmitting: PT.bool.isRequired,
144145
submitDone: PT.bool.isRequired,
@@ -193,6 +194,7 @@ const mapStateToProps = (state, ownProps) => {
193194
status: details.status,
194195
isRegistered: details.isRegistered,
195196
groups: details.groups,
197+
metadata: details.metadata || [],
196198
isSubmitting: submission.isSubmitting,
197199
submitDone: submission.submitDone,
198200
errorMsg: submission.submitErrorMsg,

src/shared/utils/terms.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@ export function isNdaTerm(term = {}) {
1616
* Resolves the DocuSign template id to use for a terms-service record.
1717
*
1818
* @param {Object|null} term terms-service record or details payload.
19-
* @returns {String|Number|undefined} configured NDA template id for NDA terms,
20-
* or the template id returned by terms-service for all other terms.
19+
* @returns {String|Number|undefined} the template id returned by terms-service,
20+
* or the configured NDA fallback when an NDA term has no template id.
2121
*/
2222
export function getDocuSignTemplateIdForTerm(term = {}) {
23+
if (term && term.docusignTemplateId) {
24+
return term.docusignTemplateId;
25+
}
26+
2327
const configuredNdaTemplateId = config.NDA_DOCUSIGN_TEMPLATE_ID;
2428
if (configuredNdaTemplateId && isNdaTerm(term)) {
2529
return configuredNdaTemplateId;
2630
}
2731

28-
return term ? term.docusignTemplateId : undefined;
32+
return undefined;
2933
}

0 commit comments

Comments
 (0)