diff --git a/apps/challenges/serializers.py b/apps/challenges/serializers.py
index 6e28744f12..4fa6a24bee 100644
--- a/apps/challenges/serializers.py
+++ b/apps/challenges/serializers.py
@@ -103,6 +103,7 @@ class Meta:
"allowed_submission_file_types",
"default_submission_meta_attributes",
"allowed_email_ids",
+ "is_submission_public",
)
diff --git a/frontend_v2/src/app/components/challenge/challengephases/editphasemodal/editphasemodal.component.html b/frontend_v2/src/app/components/challenge/challengephases/editphasemodal/editphasemodal.component.html
index 6af6dac21a..924da573c7 100644
--- a/frontend_v2/src/app/components/challenge/challengephases/editphasemodal/editphasemodal.component.html
+++ b/frontend_v2/src/app/components/challenge/challengephases/editphasemodal/editphasemodal.component.html
@@ -76,6 +76,7 @@
+
diff --git a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss
index 0de5a6dbb1..543e84f175 100644
--- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss
+++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss
@@ -13,6 +13,14 @@
}
}
+.phase-card {
+ width:50vw;
+}
+
+.phase-button {
+ margin-left: 25px;
+}
+
@include screen-medium {
.settings-section {
padding: 10px 20px !important;
diff --git a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.ts b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.ts
index 924a462226..96265fcc37 100644
--- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.ts
+++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.ts
@@ -89,13 +89,44 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy {
* Email error message
*/
message: string;
+
+ /**
+ * If the submission is public
+ */
+ isSubmissionPublic : boolean = false;
+
+ /**
+ * If the phase is public
+ */
+ isPhasePublic : boolean = false;
+
+ /**
+ * If leaderboard is public
+ */
+ isLeaderboardPublic : boolean = false;
+
+ /**
+ * phase visibility state and it's icon
+ */
+ phaseVisibility = {
+ state: 'Private',
+ icon: 'fa fa-toggle-off',
+ };
+
+ /**
+ * submission visibility state and it's icon
+ */
+ submissionVisibility = {
+ state: 'Private',
+ icon: 'fa fa-toggle-off',
+ };
/**
* publish challenge state and it's icon
*/
publishChallenge = {
state: 'Not Published',
- icon: 'fa fa-eye-slash red-text',
+ icon: 'fa fa-toggle-off',
};
/**
@@ -188,49 +219,180 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy {
const SELF = this;
return (phase) => {
SELF.selectedPhase = phase;
+ SELF.isPhasePublic = SELF.selectedPhase['is_public'];
+ SELF.isSubmissionPublic = SELF.selectedPhase['is_submission_public'];
+ SELF.isLeaderboardPublic = SELF.selectedPhase['leaderboard_public'];
+ if (SELF.isPhasePublic) {
+ SELF.phaseVisibility.state = 'Public';
+ SELF.phaseVisibility.icon = 'fa fa-toggle-on green-text';
+ }
+ else {
+ SELF.phaseVisibility.state = 'Private';
+ SELF.phaseVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1';
+ }
+ if (SELF.isSubmissionPublic) {
+ SELF.submissionVisibility.state = 'Public';
+ SELF.submissionVisibility.icon = 'fa fa-toggle-on green-text';
+ }
+ else {
+ SELF.submissionVisibility.state = 'Private';
+ SELF.submissionVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1';
+ }
+ };
+ }
- SELF.apiCall = (params) => {
- const FORM_DATA: FormData = new FormData();
- for (const key in params) {
- if (params[key]) {
- FORM_DATA.append(key, params[key]);
- }
+ editPhaseDetails() {
+ const SELF = this;
+ SELF.apiCall = (params) => {
+ const FORM_DATA: FormData = new FormData();
+ for (const key in params) {
+ if (params[key]) {
+ FORM_DATA.append(key, params[key]);
}
+ }
+ SELF.apiService
+ .patchFileUrl(
+ SELF.endpointsService.updateChallengePhaseDetailsURL(SELF.challenge.id, SELF.selectedPhase['id']),
+ FORM_DATA
+ )
+ .subscribe(
+ (data) => {
+ SELF.selectedPhase = data;
+ SELF.challengeService.fetchPhases(SELF.challenge['id']);
+ SELF.challengeService.changePhaseSelected(true);
+ SELF.selectedPhase = false;
+ SELF.globalService.showToast('success', 'The challenge phase details are successfully updated!');
+ },
+ (err) => {
+ SELF.globalService.showToast('error', err);
+ },
+ () => {this.logger.info('PHASE-UPDATE-FINISHED')}
+ );
+ };
+
+ const PARAMS = {
+ title: 'Edit Challenge Phase Details',
+ name: SELF.selectedPhase['name'],
+ label: 'description',
+ description: SELF.selectedPhase['description'],
+ startDate: SELF.selectedPhase['start_date'],
+ endDate: SELF.selectedPhase['end_date'],
+ maxSubmissionsPerDay: SELF.selectedPhase['max_submissions_per_day'],
+ maxSubmissionsPerMonth: SELF.selectedPhase['max_submissions_per_month'],
+ maxSubmissions: SELF.selectedPhase['max_submissions'],
+ maxConcurrentSubmissionsAllowed: SELF.selectedPhase['max_concurrent_submissions_allowed'],
+ allowedSubmissionFileTypes: SELF.selectedPhase['allowed_submission_file_types'],
+ confirm: 'Submit',
+ deny: 'Cancel',
+ confirmCallback: SELF.apiCall,
+ };
+ SELF.globalService.showEditPhaseModal(PARAMS);
+}
+
+ /**
+ * Phase Visibility toggle function
+ */
+ togglePhaseVisibility() {
+ const SELF = this;
+ let togglePhaseVisibilityState, isPublic;
+ if (SELF.phaseVisibility.state === 'Public') {
+ togglePhaseVisibilityState = 'private';
+ isPublic = false;
+ SELF.phaseVisibility.state = 'Private';
+ SELF.phaseVisibility.icon = 'fa fa-toggle-off';
+ } else {
+ togglePhaseVisibilityState = 'public';
+ isPublic = true;
+ SELF.phaseVisibility.state = 'Public';
+ SELF.phaseVisibility.icon = 'fa fa-toggle-on green-text';
+ }
+ const BODY: FormData = new FormData();
+ BODY.append("is_public", isPublic);
+ SELF.apiService
+ .patchFileUrl(
+ SELF.endpointsService.updateChallengePhaseDetailsURL(SELF.selectedPhase['challenge'], SELF.selectedPhase['id']),
+ BODY
+ )
+ .subscribe(
+ (data) => {
+ SELF.challengeService.fetchPhases(SELF.selectedPhase['challenge']);
+ SELF.challengeService.changePhaseSelected(true);
+ SELF.selectedPhase = false;
+ SELF.globalService.showToast(
+ 'success',
+ 'The phase was successfully made ' + togglePhaseVisibilityState,
+ 5
+ );
+ },
+ (err) => {
+ SELF.globalService.handleApiError(err, true);
+ SELF.globalService.showToast('error', err);
+ if (isPublic) {
+ SELF.phaseVisibility.state = 'Private';
+ SELF.phaseVisibility.icon = 'fa fa-toggle-off';
+ } else {
+ SELF.phaseVisibility.state = 'Public';
+ SELF.phaseVisibility.icon = 'fa fa-toggle-on green-text';
+ }
+ },
+ () => this.logger.info('PHASE-VISIBILITY-UPDATE-FINISHED')
+ );
+ }
+
+ /**
+ * Submission Visibility toggle function
+ */
+ toggleSubmissionVisibility() {
+ const SELF = this;
+ if(SELF.isLeaderboardPublic == true) {
+ let toggleSubmissionVisibilityState, isSubmissionPublic;
+ if (SELF.submissionVisibility.state === 'Public') {
+ toggleSubmissionVisibilityState = 'private';
+ isSubmissionPublic = false;
+ SELF.submissionVisibility.state = 'Private';
+ SELF.submissionVisibility.icon = 'fa fa-toggle-off';
+ } else {
+ toggleSubmissionVisibilityState = 'public';
+ isSubmissionPublic = true;
+ SELF.submissionVisibility.state = 'Public';
+ SELF.submissionVisibility.icon = 'fa fa-toggle-on green-text';
+ }
+ const BODY: FormData = new FormData();
+ BODY.append("is_submission_public", isSubmissionPublic);
SELF.apiService
- .patchFileUrl(
- SELF.endpointsService.updateChallengePhaseDetailsURL(SELF.challenge.id, SELF.selectedPhase['id']),
- FORM_DATA
- )
+ .patchFileUrl(
+ SELF.endpointsService.updateChallengePhaseDetailsURL(SELF.selectedPhase['challenge'], SELF.selectedPhase['id']),
+ BODY
+ )
.subscribe(
(data) => {
- SELF.selectedPhase = data;
- SELF.challengeService.fetchPhases(SELF.challenge['id']);
- SELF.globalService.showToast('success', 'The challenge phase details are successfully updated!');
+ SELF.challengeService.fetchPhases(SELF.selectedPhase['challenge']);
+ SELF.challengeService.changePhaseSelected(true);
+ SELF.selectedPhase = false;
+ SELF.globalService.showToast(
+ 'success',
+ 'The submissions were successfully made ' + toggleSubmissionVisibilityState,
+ 5
+ );
},
(err) => {
+ SELF.globalService.handleApiError(err, true);
SELF.globalService.showToast('error', err);
+ if (isSubmissionPublic) {
+ SELF.submissionVisibility.state = 'Private';
+ SELF.submissionVisibility.icon = 'fa fa-toggle-off';
+ } else {
+ SELF.submissionVisibility.state = 'Public';
+ SELF.submissionVisibility.icon = 'fa fa-toggle-on green-text';
+ }
},
- () => {this.logger.info('PHASE-UPDATE-FINISHED')}
+ () => this.logger.info('SUBMISSION-VISIBILITY-UPDATE-FINISHED')
);
- };
-
- const PARAMS = {
- title: 'Edit Challenge Phase Details',
- name: SELF.selectedPhase['name'],
- label: 'description',
- description: SELF.selectedPhase['description'],
- startDate: SELF.selectedPhase['start_date'],
- endDate: SELF.selectedPhase['end_date'],
- maxSubmissionsPerDay: SELF.selectedPhase['max_submissions_per_day'],
- maxSubmissionsPerMonth: SELF.selectedPhase['max_submissions_per_month'],
- maxSubmissions: SELF.selectedPhase['max_submissions'],
- confirm: 'Submit',
- deny: 'Cancel',
- confirmCallback: SELF.apiCall,
- };
- SELF.globalService.showEditPhaseModal(PARAMS);
- };
- }
+ }
+ else {
+ SELF.globalService.showToast('error', "Leaderboard is private, please make the leaderbaord public");
+ }
+ }
/**
* Remove banned email chip
diff --git a/frontend_v2/src/app/components/challenge/challengesubmissions/challengesubmissions.component.html b/frontend_v2/src/app/components/challenge/challengesubmissions/challengesubmissions.component.html
index 5b61795a72..e633b57a7b 100644
--- a/frontend_v2/src/app/components/challenge/challengesubmissions/challengesubmissions.component.html
+++ b/frontend_v2/src/app/components/challenge/challengesubmissions/challengesubmissions.component.html
@@ -139,7 +139,7 @@
My Submissions
Show on leaderboard
diff --git a/frontend_v2/src/app/components/challenge/challengesubmit/challengesubmit.component.html b/frontend_v2/src/app/components/challenge/challengesubmit/challengesubmit.component.html
index 458ae03599..c18a55e034 100644
--- a/frontend_v2/src/app/components/challenge/challengesubmit/challengesubmit.component.html
+++ b/frontend_v2/src/app/components/challenge/challengesubmit/challengesubmit.component.html
@@ -286,13 +286,14 @@ Make Submission
diff --git a/frontend_v2/src/app/components/challenge/challengesubmit/challengesubmit.component.ts b/frontend_v2/src/app/components/challenge/challengesubmit/challengesubmit.component.ts
index 6a5746b031..b19619d9dd 100644
--- a/frontend_v2/src/app/components/challenge/challengesubmit/challengesubmit.component.ts
+++ b/frontend_v2/src/app/components/challenge/challengesubmit/challengesubmit.component.ts
@@ -53,6 +53,11 @@ export class ChallengesubmitComponent implements OnInit {
*/
isPublicSubmission:boolean = true;
+ /**
+ * Is submittion allowed by host
+ */
+ isSubmissionPublic:boolean = false;
+
/**
* Challenge object
*/
@@ -467,6 +472,7 @@ export class ChallengesubmitComponent implements OnInit {
const SELF = this;
return (phase) => {
SELF.selectedPhase = phase;
+ SELF.isSubmissionPublic = phase['is_submission_public'];
if (SELF.challenge['id'] && phase['id']) {
SELF.getMetaDataDetails(SELF.challenge['id'], phase['id']);
SELF.fetchRemainingSubmissions(SELF.challenge['id'], phase['id']);
diff --git a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.ts b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.ts
index e24b401af4..6abdfe0c55 100644
--- a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.ts
+++ b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.ts
@@ -46,6 +46,11 @@ export class SelectphaseComponent implements OnInit, OnChanges {
*/
phaseVisibility = false;
+ /**
+ * If phase selected
+ */
+ isPhaseSelected : boolean = false;
+
/**
* Currently selected phase
*/
@@ -86,7 +91,15 @@ export class SelectphaseComponent implements OnInit, OnChanges {
* Component on changes detected in Input.
* @param change changes detected
*/
- ngOnChanges(change) {}
+ ngOnChanges(change) {
+ this.challengeService.isPhaseSelected.subscribe((isPhaseSelected) => {
+ this.isPhaseSelected = isPhaseSelected;
+ });
+ if(this.isPhaseSelected == true) {
+ this.challengeService.changePhaseSelected(false);
+ this.phaseName = '';
+ }
+ }
/**
* Select a particular phase.
diff --git a/frontend_v2/src/app/services/challenge.service.ts b/frontend_v2/src/app/services/challenge.service.ts
index 3e78be9cf6..942b3317b8 100644
--- a/frontend_v2/src/app/services/challenge.service.ts
+++ b/frontend_v2/src/app/services/challenge.service.ts
@@ -33,6 +33,8 @@ export class ChallengeService {
currentHostTeam = this.hostTeamSource.asObservable();
private challengeHostSource = new BehaviorSubject(false);
isChallengeHost = this.challengeHostSource.asObservable();
+ private phaseSelected = new BehaviorSubject(false);
+ isPhaseSelected = this.phaseSelected.asObservable();
private challengePublishSource = new BehaviorSubject(this.defaultPublishChallenge);
currentChallengePublishState = this.challengePublishSource.asObservable();
@@ -66,6 +68,14 @@ export class ChallengeService {
this.challengeHostSource.next(isChallengeHost);
}
+ /**
+ * Update the status for selectPhase component after details are updated
+ * @param selectedPhase new updated phase details status
+ */
+ changePhaseSelected(selectedPhase: boolean) {
+ this.phaseSelected.next(selectedPhase);
+ }
+
/**
* Update challenge publish state and icon for current challenge.
* @param publishChallenge new challenge publish status and icon.
diff --git a/tests/unit/challenges/test_views.py b/tests/unit/challenges/test_views.py
index 6a3f95923b..e2d7a4d846 100644
--- a/tests/unit/challenges/test_views.py
+++ b/tests/unit/challenges/test_views.py
@@ -2057,6 +2057,7 @@ def test_get_challenge_phase(self):
"allowed_submission_file_types": self.challenge_phase.allowed_submission_file_types,
"default_submission_meta_attributes": self.challenge_phase.default_submission_meta_attributes,
"allowed_email_ids": self.challenge_phase.allowed_email_ids,
+ "is_submission_public": self.challenge_phase.is_submission_public,
},
{
"id": self.private_challenge_phase.id,
@@ -2084,6 +2085,7 @@ def test_get_challenge_phase(self):
"allowed_submission_file_types": self.challenge_phase.allowed_submission_file_types,
"default_submission_meta_attributes": self.private_challenge_phase.default_submission_meta_attributes,
"allowed_email_ids": self.challenge_phase.allowed_email_ids,
+ "is_submission_public": self.challenge_phase.is_submission_public,
},
]
@@ -2119,6 +2121,7 @@ def test_get_challenge_phase_when_user_is_not_authenticated(self):
"allowed_submission_file_types": self.challenge_phase.allowed_submission_file_types,
"default_submission_meta_attributes": self.challenge_phase.default_submission_meta_attributes,
"allowed_email_ids": self.challenge_phase.allowed_email_ids,
+ "is_submission_public": self.challenge_phase.is_submission_public,
}
]
self.client.force_authenticate(user=None)
@@ -2164,6 +2167,7 @@ def test_get_challenge_phase_when_user_is_host(self):
"allowed_submission_file_types": self.challenge_phase.allowed_submission_file_types,
"default_submission_meta_attributes": self.challenge_phase.default_submission_meta_attributes,
"allowed_email_ids": self.challenge_phase.allowed_email_ids,
+ "is_submission_public": self.challenge_phase.is_submission_public,
},
{
"id": self.private_challenge_phase.id,
@@ -2191,6 +2195,7 @@ def test_get_challenge_phase_when_user_is_host(self):
"is_partial_submission_evaluation_enabled": self.private_challenge_phase.is_partial_submission_evaluation_enabled,
"default_submission_meta_attributes": self.private_challenge_phase.default_submission_meta_attributes,
"allowed_email_ids": self.private_challenge_phase.allowed_email_ids,
+ "is_submission_public": self.private_challenge_phase.is_submission_public,
},
]
@@ -2540,6 +2545,7 @@ def test_get_particular_challenge_phase_if_user_is_participant(self):
"allowed_submission_file_types": self.challenge_phase.allowed_submission_file_types,
"default_submission_meta_attributes": self.challenge_phase.default_submission_meta_attributes,
"allowed_email_ids": self.challenge_phase.allowed_email_ids,
+ "is_submission_public": self.challenge_phase.is_submission_public,
}
self.client.force_authenticate(user=self.participant_user)
response = self.client.get(self.url, {})
@@ -2640,6 +2646,7 @@ def test_update_challenge_phase_when_user_is_its_creator(self):
"allowed_submission_file_types": self.challenge_phase.allowed_submission_file_types,
"default_submission_meta_attributes": self.challenge_phase.default_submission_meta_attributes,
"allowed_email_ids": self.challenge_phase.allowed_email_ids,
+ "is_submission_public": self.challenge_phase.is_submission_public,
}
response = self.client.put(
self.url, {"name": new_name, "description": new_description}
@@ -2740,6 +2747,7 @@ def test_particular_challenge_phase_partial_update(self):
"allowed_submission_file_types": self.challenge_phase.allowed_submission_file_types,
"default_submission_meta_attributes": self.challenge_phase.default_submission_meta_attributes,
"allowed_email_ids": self.challenge_phase.allowed_email_ids,
+ "is_submission_public": self.challenge_phase.is_submission_public,
}
response = self.client.patch(self.url, self.partial_update_data)
self.assertEqual(response.data, expected)
@@ -4257,6 +4265,7 @@ def test_get_challenge_phase_by_pk(self):
"allowed_submission_file_types": self.challenge_phase.allowed_submission_file_types,
"default_submission_meta_attributes": self.challenge_phase.default_submission_meta_attributes,
"allowed_email_ids": self.challenge_phase.allowed_email_ids,
+ "is_submission_public": self.challenge_phase.is_submission_public,
}
response = self.client.get(self.url, {})
self.assertEqual(response.data, expected)