From 50ca85ba96b7825d4147431b4c0ad327e1711509 Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Mon, 26 Jul 2021 19:33:49 +0530 Subject: [PATCH 01/12] add tab view to settings tab --- .../components/challenge/challenge.module.ts | 2 + .../challengesettings.component.html | 511 ++++---- .../challengesettings.component.scss | 26 +- .../challengesettings.component.ts | 1098 +++++++++-------- 4 files changed, 839 insertions(+), 798 deletions(-) diff --git a/frontend_v2/src/app/components/challenge/challenge.module.ts b/frontend_v2/src/app/components/challenge/challenge.module.ts index 0294ab3a50..2ef886e3c6 100644 --- a/frontend_v2/src/app/components/challenge/challenge.module.ts +++ b/frontend_v2/src/app/components/challenge/challenge.module.ts @@ -11,6 +11,7 @@ import { MatRadioModule, MatDialogModule, MatSliderModule, + MatTabsModule, } from '@angular/material'; // import components @@ -66,6 +67,7 @@ import { ChallengeanalyticsComponent } from './challengeanalytics/challengeanaly MatRadioModule, MatDialogModule, MatSliderModule, + MatTabsModule, ], exports: [ ChallengeComponent, diff --git a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html index edb5b1f233..c8f143c941 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html @@ -5,269 +5,270 @@
Challenge Settings
-
- -
-
- Edit challenge details -
-
-
-
-
- - -
-
- - Upload New Image -
-
-
- - {{ challenge['title'] }} - - - - - - - -
-
-
- - Challenge Overview - - - - -
-
-
-
- - Terms and Conditions - - - - + + + + +
+
+
+
+ + +
+
+ + Upload New Image +
+
+
+ + {{ challenge['title'] }} + + + + + + + +
+
+
+ + Challenge Overview + + + + +
+
+
+
+ + Terms and Conditions + + + + +
+
+ + + Starts on: + {{ challenge['start_date'] | date: 'medium' }} {{ challenge['start_zone'] }} + + + + + + +
+ + + Ends on: + {{ challenge['end_date'] | date: 'medium' }} {{ challenge['end_zone'] }} + + + + + + +
+ + + {{ publishChallenge.state }} + + + +
+ Close Participation + +
+
+
+ + +
+
+ Banned emails Ids: +
+
+ + + + {{ email }} + cancel + + + + +
{{ message }}
+
+ Update +
+
-
- - - Starts on: - {{ challenge['start_date'] | date: 'medium' }} {{ challenge['start_zone'] }} - - - - - - -
- - - Ends on: - {{ challenge['end_date'] | date: 'medium' }} {{ challenge['end_zone'] }} - - - - - - -
- - - {{ publishChallenge.state }} - - - -
- Close Participation - -
-
-
+ + + + + +
+
+
+
+ +
- -
-
- Edit phase details -
-
-
-
-
- +
+ + Phase Details + + + +      + + Is Public + + + +      + + Submission Visibility + + + + +
+ +
+
+ -
- - Phase Details - - - -      - - Is Public - - - -      - - Submission Visibility - - - - + + +
+
+
+
+ + +
+
+
+ + Leaderboard Visibility + + + +      +
+
+
+
-
-
-
+ - -
-
- Edit leaderboard details -
-
-
-
-
- - + + + +
+
+
+ + + Evaluation Criteria + + + +    + + + Evaluation Script + + + + +
+
-
-
- - Leaderboard Visibility - - - -      + +
+
+
+
Submission worker actions
+
+
+
+
+ + + +
+
+
+
+
Submission worker logs
+
+
+
+
{{ log }}
+
-
-
-
-
- - -
-
- Evaluation and Annotations -
-
-
-
- - - Evaluation Criteria - - - -    - - - Evaluation Script - - - - -
-
-
+ + -
-
- Banned emails Ids: -
-
- - - - {{ email }} - cancel - - - - -
{{ message }}
-
- Update -
-
-
-
-
-
-
Submission worker actions
-
-
-
-
- - - -
-
-
-
-
Submission worker logs
-
-
-
-
{{ log }}
-
-
+
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 543e84f175..b18f7602dc 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss @@ -3,14 +3,27 @@ .challenge-card { .bottom-card-container { + padding-top: 0px; .settings-section { - padding: 20px 30px; + padding: 50px; border: 1px solid; border-radius: 5px; min-height: 50px; color: rgb(101, 97, 97); } } + .row { + margin: 4% 0px 4% 0px; + } +} + +input { + border-bottom: none; +} + +::ng-deep .mat-tab-label { + font-weight: $fw-light; + font-size: $fs-16; } .phase-card { @@ -21,12 +34,22 @@ margin-left: 25px; } +.upload-container { + text-align:center; +} + @include screen-medium { .settings-section { padding: 10px 20px !important; } } +@media (min-width: 992px) { + .col-md-12 { + width: auto; + } +} + @include screen-small-medium { .settings-section { padding: 10px 10px !important; @@ -48,7 +71,6 @@ } .challenge-detail { - margin-left: 25%; padding: 8px; } 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 5f60443037..2fcb7525bd 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.ts +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.ts @@ -30,6 +30,16 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { */ challenge: any; + /** + * Is challenge host + */ + isChallengeHost = false; + + /** + * To call the API inside modal for editing the challenge details + */ + apiCall: any; + /** * Challenge phase list */ @@ -50,21 +60,40 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { */ filteredPhaseSplits = []; + /** + * Currently selected phase + */ + selectedPhase: any = null; /** * Phase selection type (radio button or select box) */ phaseSelectionType = 'selectBox'; + /** + * Select box list type + */ + phaseSelectionListType = 'phase'; + /** - * Select box list type + * If the submission is public */ - phaseSelectionListType = 'phase'; + isSubmissionPublic : boolean = false; + + /** + * If the phase is public + */ + isPhasePublic : boolean = false; /** - * Currently selected phase + * If leaderboard is public */ - selectedPhase: any = null; + isLeaderboardPublic : boolean = false; + + /** + * Currently selected phase split + */ + selectedPhaseSplit: any = null; /** * Phase selection type (radio button or select box) @@ -77,9 +106,11 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { phaseLeaderboardSelectionListType = 'settingsPhaseSplit'; /** - * Currently selected phase split + * If leaderboard of phase split is public + * 1 -> private + * 3 -> public */ - selectedPhaseSplit: any = null; + isPhaseSplitLeaderboardPublic: number = 1; /** * store worker logs @@ -91,16 +122,6 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { */ pollingInterval: any; - /** - * Is challenge host - */ - isChallengeHost = false; - - /** - * To call the API inside modal for editing the challenge details - */ - apiCall: any; - /** * Participants banned emails ids */ @@ -120,28 +141,6 @@ 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; - - /** - * If leaderboard of phase split is public - * 1 -> private - * 3 -> public - */ - isPhaseSplitLeaderboardPublic: number = 1; /** * phase visibility state and it's icon @@ -207,6 +206,20 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { this.challenge = challenge; }); + this.challengeService.isChallengeHost.subscribe((status) => { + this.isChallengeHost = status; + }); + + this.challengeService.currentChallengePublishState.subscribe((publishChallenge) => { + this.publishChallenge.state = publishChallenge.state; + this.publishChallenge.icon = publishChallenge.icon; + }); + + if (!this.challenge["remote_evaluation"]) { + this.fetchWorkerLogs(); + this.startLoadingLogs(); + } + this.challengeService.currentPhases.subscribe((phases) => { this.phases = phases; for (let i = 0; i < this.phases.length; i++) { @@ -220,15 +233,6 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { this.filteredPhases = this.phases; }); - this.challengeService.isChallengeHost.subscribe((status) => { - this.isChallengeHost = status; - }); - - this.challengeService.currentChallengePublishState.subscribe((publishChallenge) => { - this.publishChallenge.state = publishChallenge.state; - this.publishChallenge.icon = publishChallenge.icon; - }); - this.challengeService.currentPhaseSplit.subscribe((phaseSplits) => { this.phaseSplits = phaseSplits; for (let i = 0; i < this.phaseSplits.length; i++) { @@ -241,121 +245,461 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { } this.filteredPhaseSplits = this.phaseSplits; }); - - if (!this.challenge["remote_evaluation"]) { - this.fetchWorkerLogs(); - this.startLoadingLogs(); - } } - updateView() { - this.bannedEmailIds = this.challenge.banned_email_ids || []; - this.formerBannedEmailIds = this.bannedEmailIds.concat(); // Creating deep copy - } + // Edit Challenge Details -> /** - * Add banned email chip - * @param event current event + * Edit challenge title function */ - add(event: MatChipInputEvent): void { + editChallengeTitle() { const SELF = this; - const input = event.input; - const value = event.value; - SELF.isValidationError = false; - SELF.message = ''; - // Add our fruit - if ((value || '').trim()) { - if (!SELF.validateEmail(value.trim())) { - SELF.isValidationError = true; - SELF.message = 'Please enter a valid email!'; - } else { - SELF.bannedEmailIds.push(value.trim()); - } - } + SELF.apiCall = (params) => { + const BODY = JSON.stringify(params); + SELF.apiService + .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) + .subscribe( + (data) => { + SELF.challenge.title = data.title; + SELF.globalService.showToast('success', 'The challenge title is successfully updated!', 5); + }, + (err) => { + SELF.globalService.handleApiError(err, true); + SELF.globalService.showToast('error', err); + }, + () => {} + ); + }; - // Reset the input value - if (input && !SELF.isValidationError) { - input.value = ''; - } + const PARAMS = { + title: 'Edit Challenge Title', + content: '', + confirm: 'Submit', + deny: 'Cancel', + form: [ + { + name: 'editChallengeTitle', + isRequired: true, + label: 'title', + placeholder: 'Challenge Title', + type: 'text', + value: this.challenge.title, + }, + ], + confirmCallback: SELF.apiCall, + }; + SELF.globalService.showModal(PARAMS); } /** - * This is called when a phase split is selected (from child components) + * Delete challenge */ - phaseSplitSelected () { + deleteChallenge() { const SELF = this; - return (phaseSplit) => { - SELF.selectedPhaseSplit = phaseSplit; - SELF.isPhaseSplitLeaderboardPublic = SELF.selectedPhaseSplit['visibility']; - if(SELF.isPhaseSplitLeaderboardPublic == 3) { - SELF.leaderboardVisibility.state = 'Public'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; - } - else { - SELF.leaderboardVisibility.state = 'Private'; - SELF.leaderboardVisibility.icon = 'fa fa fa-toggle-off grey-text text-darken-1'; - } - } + const redirectTo = '/dashboard'; + + SELF.apiCall = () => { + const BODY = JSON.stringify({}); + SELF.apiService.postUrl(SELF.endpointsService.deleteChallengeURL(SELF.challenge.id), BODY).subscribe( + (data) => { + SELF.router.navigate([redirectTo]); + SELF.globalService.showToast('success', 'The Challenge is successfully deleted!', 5); + }, + (err) => { + SELF.globalService.handleApiError(err, true); + SELF.globalService.showToast('error', err); + }, + () => {} + ); + }; + + const PARAMS = { + title: 'Delete Challenge', + content: '', + confirm: 'I understand consequences, delete the challenge', + deny: 'Cancel', + form: [ + { + name: 'challegenDeleteInput', + isRequired: true, + label: '', + placeholder: 'Please type in the name of the challenge to confirm', + type: 'text', + value: '', + }, + ], + confirmCallback: SELF.apiCall, + }; + SELF.globalService.showModal(PARAMS); } /** - * Leadeboard Visibility toggle function + * Edit challenge image function */ - toggleLeaderboardVisibility() { + editChallengeImage() { const SELF = this; - let toggleLeaderboardVisibilityState, visibility; - if (SELF.leaderboardVisibility.state === 'Public') { - toggleLeaderboardVisibilityState = 'private'; - visibility = 1; - SELF.leaderboardVisibility.state = 'Private'; - SELF.leaderboardVisibility.icon = 'fa fa fa-toggle-off grey-text text-darken-1'; - } else { - toggleLeaderboardVisibilityState = 'public'; - visibility = 3; - SELF.leaderboardVisibility.state = 'Public'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; - } - const BODY: FormData = new FormData(); - BODY.append("visibility", visibility); + SELF.apiCall = (params) => { + const FORM_DATA: FormData = new FormData(); + FORM_DATA.append('image', params['image']); SELF.apiService - .patchFileUrl( - SELF.endpointsService.particularChallengePhaseSplitUrl(SELF.selectedPhaseSplit['id']), - BODY - ) + .patchFileUrl( + SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), + FORM_DATA + ) .subscribe( (data) => { - SELF.selectedPhaseSplit['visibility'] = data.visibility; - SELF.challengeService.changePhaseSplitSelected(true); - if (visibility == 3) { - SELF.selectedPhaseSplit['showPrivate'] = false; - SELF.leaderboardVisibility.state = 'Public'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; - } else { - SELF.selectedPhaseSplit['showPrivate'] = true; - SELF.leaderboardVisibility.state = 'Private'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1'; - } - SELF.globalService.showToast( - 'success', - 'The phase split was successfully made ' + toggleLeaderboardVisibilityState, - 5 - ); + SELF.challenge.image = data.image; + SELF.globalService.showToast('success', 'The Challenge image successfully updated!', 5); }, (err) => { SELF.globalService.handleApiError(err, true); SELF.globalService.showToast('error', err); - if (visibility == 3) { - SELF.leaderboardVisibility.state = 'Private'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1'; + }, + () => {} + ); + }; + + /** + * Parameters of the modal + */ + const PARAMS = { + title: 'Edit Challenge Image', + content: '', + confirm: 'Submit', + deny: 'Cancel', + form: [ + { + name: 'Challenge Image', + isRequired: true, + label: 'image', + placeholder: '', + type: 'file', + value: '', + }, + ], + confirmCallback: SELF.apiCall, + }; + SELF.globalService.showModal(PARAMS); + } + + /** + * Edit challenge overview function + */ + + editChallengeOverview() { + const SELF = this; + + SELF.apiCall = (params) => { + const BODY = JSON.stringify(params); + SELF.apiService + .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) + .subscribe( + (data) => { + SELF.challenge.description = data.description; + SELF.globalService.showToast('success', 'The description is successfully updated!', 5); + }, + (err) => { + SELF.globalService.handleApiError(err, true); + SELF.globalService.showToast('error', err); + }, + () => this.logger.info('EDIT-CHALLENGE-DESCRIPTION-FINISHED') + ); + }; + + const PARAMS = { + title: 'Edit Challenge Description', + label: 'description', + isEditorRequired: true, + editorContent: this.challenge.description, + confirm: 'Submit', + deny: 'Cancel', + confirmCallback: SELF.apiCall, + }; + SELF.globalService.showModal(PARAMS); + } + + /** + * Edit terms and conditions of the challenge + */ + editTermsAndConditions() { + const SELF = this; + SELF.apiCall = (params) => { + const BODY = JSON.stringify(params); + SELF.apiService + .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) + .subscribe( + (data) => { + SELF.challenge.terms_and_conditions = data.terms_and_conditions; + this.updateView(); + SELF.globalService.showToast('success', 'The terms and conditions are successfully updated!', 5); + }, + (err) => { + SELF.globalService.handleApiError(err, true); + SELF.globalService.showToast('error', err); + }, + () => this.logger.info('EDIT-TERMS-AND-CONDITIONS-FINISHED') + ); + }; + + /** + * Parameters of the modal + */ + const PARAMS = { + title: 'Edit Terms And Conditions', + label: 'terms_and_conditions', + isEditorRequired: true, + editorContent: this.challenge.terms_and_conditions, + confirm: 'Submit', + deny: 'Cancel', + confirmCallback: SELF.apiCall, + }; + SELF.globalService.showModal(PARAMS); + } + + /** + * Edit challenge start and end date function + */ + challengeDateDialog() { + const SELF = this; + SELF.apiCall = (params) => { + if (new Date(params.start_date).valueOf() < new Date(params.end_date).valueOf()) { + const BODY = JSON.stringify({ + start_date: new Date(params.start_date).toISOString(), + end_date: new Date(params.end_date).toISOString(), + }); + SELF.apiService + .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) + .subscribe( + (data) => { + SELF.challenge.start_date = data.start_date; + SELF.challenge.end_date = data.end_date; + SELF.globalService.showToast('success', 'The Challenge start and end date successfully updated!', 5); + }, + (err) => { + SELF.globalService.handleApiError(err, true); + SELF.globalService.showToast('error', err); + }, + () => {} + ); + } else { + SELF.globalService.showToast('error', 'The challenge start date cannot be same or greater than end date.', 5); + } + }; + const PARAMS = { + title: 'Edit Challenge Start and End Date', + content: '', + confirm: 'Confirm', + deny: 'Cancel', + form: [ + { + isRequired: false, + label: 'start_date', + placeholder: 'Start Date and Time', + type: 'text', + value: moment(this.challenge.start_date).format('MM-DD-YYYY hh:mm a'), + }, + { + isRequired: false, + label: 'end_date', + placeholder: 'End Date and Time', + type: 'text', + value: moment(this.challenge.end_date).format('MM-DD-YYYY hh:mm a'), + }, + ], + isButtonDisabled: true, + confirmCallback: SELF.apiCall, + }; + SELF.globalService.showModal(PARAMS); + } + + /** + * Publish challenge click function + */ + togglePublishChallengeState() { + const SELF = this; + let toggleChallengePublishState, isPublished; + if (this.publishChallenge.state === 'Published') { + toggleChallengePublishState = 'private'; + isPublished = false; + } else { + toggleChallengePublishState = 'public'; + isPublished = true; + } + SELF.apiCall = () => { + const BODY = JSON.stringify({ + published: isPublished, + }); + SELF.apiService + .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) + .subscribe( + (data) => { + if (isPublished) { + this.publishChallenge.state = 'Published'; + this.publishChallenge.icon = 'fa fa-eye green-text'; } else { - SELF.leaderboardVisibility.state = 'Public'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; + this.publishChallenge.state = 'Not Published'; + this.publishChallenge.icon = 'fa fa-eye-slash red-text'; } + SELF.globalService.showToast( + 'success', + 'The challenge was successfully made ' + toggleChallengePublishState, + 5 + ); }, - () => this.logger.info('LEADERBOARD-VISIBILITY-UPDATE-FINISHED') + (err) => { + SELF.globalService.handleApiError(err, true); + SELF.globalService.showToast('error', err); + }, + () => this.logger.info('PUBLISH-CHALLENGE-UPDATE-FINISHED') ); + }; + + const PARAMS = { + title: 'Make this challenge ' + toggleChallengePublishState + '?', + content: '', + confirm: "Yes, I'm sure", + deny: 'No', + confirmCallback: SELF.apiCall, + }; + SELF.globalService.showConfirm(PARAMS); + } + + /** + * Close participation function + */ + stopParticipation(event) { + event.preventDefault(); + const participationState = this.challenge['is_registration_open'] ? 'Close' : 'Open'; + const closeParticipationMsg = 'Participation is closed successfully'; + const openParticipationMsg = 'Participation is opened successfully'; + + this.apiCall = () => { + if (this.isChallengeHost && this.challenge['id'] !== null) { + const BODY = JSON.stringify({ + is_registration_open: !this.challenge['is_registration_open'], + }); + this.apiService + .patchUrl(this.endpointsService.editChallengeDetailsURL(this.challenge.creator.id, this.challenge.id), BODY) + .subscribe( + () => { + this.challenge['is_registration_open'] = !this.challenge['is_registration_open']; + if (this.challenge['is_registration_open']) { + this.globalService.showToast('success', openParticipationMsg, 5); + } else { + this.globalService.showToast('success', closeParticipationMsg, 5); + } + }, + (err) => { + this.globalService.handleApiError(err, true); + this.globalService.showToast('error', err); + }, + () => {} + ); + } + }; + + const PARAMS = { + title: participationState + ' participation in the challenge?', + content: '', + confirm: "Yes, I'm sure", + deny: 'No', + confirmCallback: this.apiCall, + }; + this.globalService.showConfirm(PARAMS); + } + + // Banned Email Ids -> + + updateView() { + this.bannedEmailIds = this.challenge.banned_email_ids || []; + this.formerBannedEmailIds = this.bannedEmailIds.concat(); // Creating deep copy + } + + /** + * Add banned email chip + * @param event current event + */ + add(event: MatChipInputEvent): void { + const SELF = this; + const input = event.input; + const value = event.value; + SELF.isValidationError = false; + SELF.message = ''; + + // Add our fruit + if ((value || '').trim()) { + if (!SELF.validateEmail(value.trim())) { + SELF.isValidationError = true; + SELF.message = 'Please enter a valid email!'; + } else { + SELF.bannedEmailIds.push(value.trim()); + } + } + + // Reset the input value + if (input && !SELF.isValidationError) { + input.value = ''; + } + } + + /** + * Remove banned email chip + * @param email Banned email id + */ + remove(email): void { + const SELF = this; + const index = SELF.bannedEmailIds.indexOf(email); + + if (index >= 0) { + SELF.bannedEmailIds.splice(index, 1); + } + + // updating the banned Email Ids list + SELF.updateBannedEmailList(); + } + + validateEmail(email) { + if (email === '') { + return true; + } + const regex = /^\s*[\w\-\+_]+(\.[\w\-\+_]+)*\@[\w\-\+_]+\.[\w\-\+_]+(\.[\w\-\+_]+)*\s*$/; + return String(email).search(regex) !== -1; + } + + reflectChange() { + if (this.bannedEmailIds.toString() === this.formerBannedEmailIds.toString()) { + this.globalService.showToast('error', 'No change to reflect!'); + } else if (this.isValidationError) { + this.globalService.showToast('error', 'Please enter a valid email!'); + } else { + this.updateBannedEmailList(); } + } + + updateBannedEmailList() { + const SELF = this; + const BODY = JSON.stringify({ + banned_email_ids: SELF.bannedEmailIds, + }); + SELF.apiService + .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) + .subscribe( + (data) => { + SELF.challenge.banned_email_ids = data.banned_email_ids; + SELF.isBannedEmailInputVisible = false; + SELF.globalService.showToast('success', 'Banned participant emails are successfully updated!', 5); + this.formerBannedEmailIds = this.bannedEmailIds.concat(); // Creating deep copy + }, + (err) => { + SELF.globalService.handleApiError(err, true); + SELF.globalService.showToast('error', err); + }, + () => {} + ); + } + + // Edit Phase Details -> /** * Called when a phase is selected (from child component) @@ -386,6 +730,9 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { }; } + /** + * Edit Phase Details function + */ editPhaseDetails() { const SELF = this; SELF.apiCall = (params) => { @@ -436,7 +783,7 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { /** * Phase Visibility toggle function */ - togglePhaseVisibility() { + togglePhaseVisibility() { const SELF = this; let togglePhaseVisibilityState, isPublic; if (SELF.phaseVisibility.state === 'Public') { @@ -486,7 +833,7 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { /** * Submission Visibility toggle function */ - toggleSubmissionVisibility() { + toggleSubmissionVisibility() { const SELF = this; if(SELF.isLeaderboardPublic == true) { let toggleSubmissionVisibilityState, isSubmissionPublic; @@ -536,285 +883,86 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { } } - /** - * Remove banned email chip - * @param email Banned email id - */ - remove(email): void { - const SELF = this; - const index = SELF.bannedEmailIds.indexOf(email); - - if (index >= 0) { - SELF.bannedEmailIds.splice(index, 1); - } - - // updating the banned Email Ids list - SELF.updateBannedEmailList(); - } - - validateEmail(email) { - if (email === '') { - return true; - } - const regex = /^\s*[\w\-\+_]+(\.[\w\-\+_]+)*\@[\w\-\+_]+\.[\w\-\+_]+(\.[\w\-\+_]+)*\s*$/; - return String(email).search(regex) !== -1; - } - - reflectChange() { - if (this.bannedEmailIds.toString() === this.formerBannedEmailIds.toString()) { - this.globalService.showToast('error', 'No change to reflect!'); - } else if (this.isValidationError) { - this.globalService.showToast('error', 'Please enter a valid email!'); - } else { - this.updateBannedEmailList(); - } - } - - updateBannedEmailList() { - const SELF = this; - const BODY = JSON.stringify({ - banned_email_ids: SELF.bannedEmailIds, - }); - SELF.apiService - .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) - .subscribe( - (data) => { - SELF.challenge.banned_email_ids = data.banned_email_ids; - SELF.isBannedEmailInputVisible = false; - SELF.globalService.showToast('success', 'Banned participant emails are successfully updated!', 5); - this.formerBannedEmailIds = this.bannedEmailIds.concat(); // Creating deep copy - }, - (err) => { - SELF.globalService.handleApiError(err, true); - SELF.globalService.showToast('error', err); - }, - () => {} - ); - } - - /** - * Close participation function - */ - stopParticipation(event) { - event.preventDefault(); - const participationState = this.challenge['is_registration_open'] ? 'Close' : 'Open'; - const closeParticipationMsg = 'Participation is closed successfully'; - const openParticipationMsg = 'Participation is opened successfully'; - - this.apiCall = () => { - if (this.isChallengeHost && this.challenge['id'] !== null) { - const BODY = JSON.stringify({ - is_registration_open: !this.challenge['is_registration_open'], - }); - this.apiService - .patchUrl(this.endpointsService.editChallengeDetailsURL(this.challenge.creator.id, this.challenge.id), BODY) - .subscribe( - () => { - this.challenge['is_registration_open'] = !this.challenge['is_registration_open']; - if (this.challenge['is_registration_open']) { - this.globalService.showToast('success', openParticipationMsg, 5); - } else { - this.globalService.showToast('success', closeParticipationMsg, 5); - } - }, - (err) => { - this.globalService.handleApiError(err, true); - this.globalService.showToast('error', err); - }, - () => {} - ); - } - }; - - const PARAMS = { - title: participationState + ' participation in the challenge?', - content: '', - confirm: "Yes, I'm sure", - deny: 'No', - confirmCallback: this.apiCall, - }; - this.globalService.showConfirm(PARAMS); - } - - /** - * Edit challenge title function - */ - editChallengeTitle() { - const SELF = this; - - SELF.apiCall = (params) => { - const BODY = JSON.stringify(params); - SELF.apiService - .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) - .subscribe( - (data) => { - SELF.challenge.title = data.title; - SELF.globalService.showToast('success', 'The challenge title is successfully updated!', 5); - }, - (err) => { - SELF.globalService.handleApiError(err, true); - SELF.globalService.showToast('error', err); - }, - () => {} - ); - }; - - const PARAMS = { - title: 'Edit Challenge Title', - content: '', - confirm: 'Submit', - deny: 'Cancel', - form: [ - { - name: 'editChallengeTitle', - isRequired: true, - label: 'title', - placeholder: 'Challenge Title', - type: 'text', - value: this.challenge.title, - }, - ], - confirmCallback: SELF.apiCall, - }; - SELF.globalService.showModal(PARAMS); - } - - /** - * Edit terms and conditions of the challenge - */ - editTermsAndConditions() { - const SELF = this; - SELF.apiCall = (params) => { - const BODY = JSON.stringify(params); - SELF.apiService - .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) - .subscribe( - (data) => { - SELF.challenge.terms_and_conditions = data.terms_and_conditions; - this.updateView(); - SELF.globalService.showToast('success', 'The terms and conditions are successfully updated!', 5); - }, - (err) => { - SELF.globalService.handleApiError(err, true); - SELF.globalService.showToast('error', err); - }, - () => this.logger.info('EDIT-TERMS-AND-CONDITIONS-FINISHED') - ); - }; - - /** - * Parameters of the modal - */ - const PARAMS = { - title: 'Edit Terms And Conditions', - label: 'terms_and_conditions', - isEditorRequired: true, - editorContent: this.challenge.terms_and_conditions, - confirm: 'Submit', - deny: 'Cancel', - confirmCallback: SELF.apiCall, - }; - SELF.globalService.showModal(PARAMS); - } - + // Edit Leaderboard Details -> /** - * Delete challenge + * This is called when a phase split is selected (from child components) */ - deleteChallenge() { + phaseSplitSelected () { const SELF = this; - const redirectTo = '/dashboard'; - - SELF.apiCall = () => { - const BODY = JSON.stringify({}); - SELF.apiService.postUrl(SELF.endpointsService.deleteChallengeURL(SELF.challenge.id), BODY).subscribe( - (data) => { - SELF.router.navigate([redirectTo]); - SELF.globalService.showToast('success', 'The Challenge is successfully deleted!', 5); - }, - (err) => { - SELF.globalService.handleApiError(err, true); - SELF.globalService.showToast('error', err); - }, - () => {} - ); - }; - - const PARAMS = { - title: 'Delete Challenge', - content: '', - confirm: 'I understand consequences, delete the challenge', - deny: 'Cancel', - form: [ - { - name: 'challegenDeleteInput', - isRequired: true, - label: '', - placeholder: 'Please type in the name of the challenge to confirm', - type: 'text', - value: '', - }, - ], - confirmCallback: SELF.apiCall, - }; - SELF.globalService.showModal(PARAMS); + return (phaseSplit) => { + SELF.selectedPhaseSplit = phaseSplit; + SELF.isPhaseSplitLeaderboardPublic = SELF.selectedPhaseSplit['visibility']; + if(SELF.isPhaseSplitLeaderboardPublic == 3) { + SELF.leaderboardVisibility.state = 'Public'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; + } + else { + SELF.leaderboardVisibility.state = 'Private'; + SELF.leaderboardVisibility.icon = 'fa fa fa-toggle-off grey-text text-darken-1'; + } + } } /** - * Edit challenge start and end date function + * Leadeboard Visibility toggle function */ - challengeDateDialog() { + toggleLeaderboardVisibility() { const SELF = this; - SELF.apiCall = (params) => { - if (new Date(params.start_date).valueOf() < new Date(params.end_date).valueOf()) { - const BODY = JSON.stringify({ - start_date: new Date(params.start_date).toISOString(), - end_date: new Date(params.end_date).toISOString(), - }); - SELF.apiService - .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) - .subscribe( - (data) => { - SELF.challenge.start_date = data.start_date; - SELF.challenge.end_date = data.end_date; - SELF.globalService.showToast('success', 'The Challenge start and end date successfully updated!', 5); - }, - (err) => { - SELF.globalService.handleApiError(err, true); - SELF.globalService.showToast('error', err); - }, - () => {} - ); - } else { - SELF.globalService.showToast('error', 'The challenge start date cannot be same or greater than end date.', 5); - } - }; - const PARAMS = { - title: 'Edit Challenge Start and End Date', - content: '', - confirm: 'Confirm', - deny: 'Cancel', - form: [ - { - isRequired: false, - label: 'start_date', - placeholder: 'Start Date and Time', - type: 'text', - value: moment(this.challenge.start_date).format('MM-DD-YYYY hh:mm a'), - }, - { - isRequired: false, - label: 'end_date', - placeholder: 'End Date and Time', - type: 'text', - value: moment(this.challenge.end_date).format('MM-DD-YYYY hh:mm a'), - }, - ], - isButtonDisabled: true, - confirmCallback: SELF.apiCall, - }; - SELF.globalService.showModal(PARAMS); - } + let toggleLeaderboardVisibilityState, visibility; + if (SELF.leaderboardVisibility.state === 'Public') { + toggleLeaderboardVisibilityState = 'private'; + visibility = 1; + SELF.leaderboardVisibility.state = 'Private'; + SELF.leaderboardVisibility.icon = 'fa fa fa-toggle-off grey-text text-darken-1'; + } else { + toggleLeaderboardVisibilityState = 'public'; + visibility = 3; + SELF.leaderboardVisibility.state = 'Public'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; + } + const BODY: FormData = new FormData(); + BODY.append("visibility", visibility); + SELF.apiService + .patchFileUrl( + SELF.endpointsService.particularChallengePhaseSplitUrl(SELF.selectedPhaseSplit['id']), + BODY + ) + .subscribe( + (data) => { + SELF.selectedPhaseSplit['visibility'] = data.visibility; + SELF.challengeService.changePhaseSplitSelected(true); + if (visibility == 3) { + SELF.selectedPhaseSplit['showPrivate'] = false; + SELF.leaderboardVisibility.state = 'Public'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; + } else { + SELF.selectedPhaseSplit['showPrivate'] = true; + SELF.leaderboardVisibility.state = 'Private'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1'; + } + SELF.globalService.showToast( + 'success', + 'The phase split was successfully made ' + toggleLeaderboardVisibilityState, + 5 + ); + }, + (err) => { + SELF.globalService.handleApiError(err, true); + SELF.globalService.showToast('error', err); + if (visibility == 3) { + SELF.leaderboardVisibility.state = 'Private'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1'; + } else { + SELF.leaderboardVisibility.state = 'Public'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; + } + }, + () => this.logger.info('LEADERBOARD-VISIBILITY-UPDATE-FINISHED') + ); + } + + // Edit Evaluation Script and Criteria -> /** * Edit evaluation criteria of the challenge @@ -900,90 +1048,7 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { SELF.globalService.showModal(PARAMS); } - /** - * Edit challenge image function - */ - editChallengeImage() { - const SELF = this; - SELF.apiCall = (params) => { - const FORM_DATA: FormData = new FormData(); - FORM_DATA.append('image', params['image']); - SELF.apiService - .patchFileUrl( - SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), - FORM_DATA - ) - .subscribe( - (data) => { - SELF.challenge.image = data.image; - SELF.globalService.showToast('success', 'The Challenge image successfully updated!', 5); - }, - (err) => { - SELF.globalService.handleApiError(err, true); - SELF.globalService.showToast('error', err); - }, - () => {} - ); - }; - - /** - * Parameters of the modal - */ - const PARAMS = { - title: 'Edit Challenge Image', - content: '', - confirm: 'Submit', - deny: 'Cancel', - form: [ - { - name: 'Challenge Image', - isRequired: true, - label: 'image', - placeholder: '', - type: 'file', - value: '', - }, - ], - confirmCallback: SELF.apiCall, - }; - SELF.globalService.showModal(PARAMS); - } - - /** - * Edit challenge overview function - */ - - editChallengeOverview() { - const SELF = this; - - SELF.apiCall = (params) => { - const BODY = JSON.stringify(params); - SELF.apiService - .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) - .subscribe( - (data) => { - SELF.challenge.description = data.description; - SELF.globalService.showToast('success', 'The description is successfully updated!', 5); - }, - (err) => { - SELF.globalService.handleApiError(err, true); - SELF.globalService.showToast('error', err); - }, - () => this.logger.info('EDIT-CHALLENGE-DESCRIPTION-FINISHED') - ); - }; - - const PARAMS = { - title: 'Edit Challenge Description', - label: 'description', - isEditorRequired: true, - editorContent: this.challenge.description, - confirm: 'Submit', - deny: 'Cancel', - confirmCallback: SELF.apiCall, - }; - SELF.globalService.showModal(PARAMS); - } + // Worker logs -> /** * API call to manage the worker from UI. @@ -1035,61 +1100,12 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { SELF.fetchWorkerLogs(); }, 5000); } - - ngOnDestroy() { - clearInterval(this.pollingInterval); - } - + /** - * Publish challenge click function + * Component on destroyed. */ - togglePublishChallengeState() { - const SELF = this; - let toggleChallengePublishState, isPublished; - if (this.publishChallenge.state === 'Published') { - toggleChallengePublishState = 'private'; - isPublished = false; - } else { - toggleChallengePublishState = 'public'; - isPublished = true; - } - SELF.apiCall = () => { - const BODY = JSON.stringify({ - published: isPublished, - }); - SELF.apiService - .patchUrl(SELF.endpointsService.editChallengeDetailsURL(SELF.challenge.creator.id, SELF.challenge.id), BODY) - .subscribe( - (data) => { - if (isPublished) { - this.publishChallenge.state = 'Published'; - this.publishChallenge.icon = 'fa fa-eye green-text'; - } else { - this.publishChallenge.state = 'Not Published'; - this.publishChallenge.icon = 'fa fa-eye-slash red-text'; - } - SELF.globalService.showToast( - 'success', - 'The challenge was successfully made ' + toggleChallengePublishState, - 5 - ); - }, - (err) => { - SELF.globalService.handleApiError(err, true); - SELF.globalService.showToast('error', err); - }, - () => this.logger.info('PUBLISH-CHALLENGE-UPDATE-FINISHED') - ); - }; - - const PARAMS = { - title: 'Make this challenge ' + toggleChallengePublishState + '?', - content: '', - confirm: "Yes, I'm sure", - deny: 'No', - confirmCallback: SELF.apiCall, - }; - SELF.globalService.showConfirm(PARAMS); + ngOnDestroy() { + clearInterval(this.pollingInterval); } } From 955f5b70707ccd4e9c187fe178a17736875a2854 Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Mon, 26 Jul 2021 19:53:34 +0530 Subject: [PATCH 02/12] fix worker title --- .../challengesettings/challengesettings.component.html | 4 ++-- .../challengesettings/challengesettings.component.scss | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html index c8f143c941..9fad76bd2a 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html @@ -230,8 +230,8 @@
Challenge Settings
-
-
+
+
Submission worker actions
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 b18f7602dc..c8afe5a318 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss @@ -34,6 +34,10 @@ input { margin-left: 25px; } +.worker-title { + margin-bottom: 2%; +} + .upload-container { text-align:center; } From 0b1154e907be361d00cd15aeb1785b6196ecd4dc Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Mon, 26 Jul 2021 21:26:54 +0530 Subject: [PATCH 03/12] change tab-heading --- .../challengesettings/challengesettings.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html index 9fad76bd2a..fb6ae32d61 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html @@ -206,7 +206,7 @@
Challenge Settings
- +
From ef4012ee28306a3c94fe68f328edfae56b60459f Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Tue, 27 Jul 2021 14:37:25 +0530 Subject: [PATCH 04/12] add :host -> does not change styles when coming from other compoenent --- .../challengesettings/challengesettings.component.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 c8afe5a318..5b1cfa72f3 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss @@ -21,9 +21,9 @@ input { border-bottom: none; } -::ng-deep .mat-tab-label { - font-weight: $fw-light; - font-size: $fs-16; +:host ::ng-deep .mat-tab-label .mat-tab-label-content{ + font-weight: $fw-light !important; + font-size: $fs-16 !important; } .phase-card { From 3575f942b1a6e4629a5a215ad5968c789249187e Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Fri, 30 Jul 2021 20:35:33 +0530 Subject: [PATCH 05/12] merge phase and leaderboard tab --- .../challengesettings.component.html | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html index fb6ae32d61..bd7d75d8f3 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html @@ -6,7 +6,7 @@
Challenge Settings
- +
@@ -135,8 +135,11 @@
Challenge Settings
- +
+
+ Edit Phase +
@@ -173,11 +176,11 @@
Challenge Settings
- - -
+
+ Edit Leaderboard +
@@ -203,10 +206,11 @@
Challenge Settings
+ - +
From 8f234637065d0c3abe760588a51ee4051fe03373 Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Tue, 3 Aug 2021 18:33:36 +0530 Subject: [PATCH 06/12] show defauly options in select phase --- .../challengeleaderboard.component.html | 2 +- .../challengesettings.component.html | 2 +- .../challengesubmit.component.ts | 17 +++++++++--- .../selectphase/selectphase.component.html | 9 ++++--- .../selectphase/selectphase.component.ts | 26 +++++++++++++++++++ 5 files changed, 46 insertions(+), 10 deletions(-) diff --git a/frontend_v2/src/app/components/challenge/challengeleaderboard/challengeleaderboard.component.html b/frontend_v2/src/app/components/challenge/challengeleaderboard/challengeleaderboard.component.html index d8ab8bc653..30cd029661 100644 --- a/frontend_v2/src/app/components/challenge/challengeleaderboard/challengeleaderboard.component.html +++ b/frontend_v2/src/app/components/challenge/challengeleaderboard/challengeleaderboard.component.html @@ -20,7 +20,7 @@
Leaderboard
Challenge Settings
{ SELF.selectedPhase = phase; + SELF.isPhaseSelected = true; SELF.isLeaderboardPublic = phase['leaderboard_public']; + console.log(this.isLeaderboardPublic); if (SELF.challenge['id'] && phase['id']) { SELF.getMetaDataDetails(SELF.challenge['id'], phase['id']); SELF.fetchRemainingSubmissions(SELF.challenge['id'], phase['id']); SELF.clearMetaAttributeValues(); SELF.submissionError = ''; - SELF.components['_results'].forEach((element) => { - element.value = ''; - element.message = ''; - }); + if(SELF.components) { + SELF.components['_results'].forEach((element) => { + element.value = ''; + element.message = ''; + }); + } } }; } diff --git a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.html b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.html index cdeb130a9f..e7e89d478e 100644 --- a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.html +++ b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.html @@ -3,6 +3,7 @@ Select phase - + {{ phaseName }} @@ -64,7 +65,7 @@ Select Phase Split - + Phase: {{ phaseName }}, Split:  - + Phase:{{ key.challenge_phase_name }}, Split: {{ key.dataset_split_name }}   @@ -108,7 +109,7 @@ - + Phase:{{ key.challenge_phase_name }}, Split: {{ key.dataset_split_name }}   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 199d60bc11..0e795e09aa 100644 --- a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.ts +++ b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.ts @@ -16,6 +16,16 @@ export class SelectphaseComponent implements OnInit, OnChanges { */ @Input() phases: any; + /** + * Phase Splits list + */ + @Input() settingsPhaseSplits: any; + + /** + * Phase Splits list + */ + @Input() phaseSplits: any; + /** * Selected phase callback */ @@ -86,6 +96,8 @@ export class SelectphaseComponent implements OnInit, OnChanges { */ challenge: any; + radioSelected: number; + /** * Constructor. * @param globalService GlobalService Injection. @@ -100,6 +112,20 @@ export class SelectphaseComponent implements OnInit, OnChanges { this.challengeService.currentChallenge.subscribe((challenge) => { this.challenge = challenge; }); + + if(this.phases) { + this.selectedPhase = this.phases[0]; + this.radioSelected = this.phases[0].id; + this.selectPhase(this.phases[0]); + } + else if(this.settingsPhaseSplits) { + this.selectedPhaseSplit = this.settingsPhaseSplits[0]; + this.selectSettingsPhaseSplit(this.settingsPhaseSplits[0], "selectBox", "settingsPhaseSplit"); + } + else { + this.selectedPhaseSplit = this.phaseSplits[0]; + this.selectPhaseSplit(this.phaseSplits[0], "selectBox", "phaseSplit"); + } } /** From 3db3413d9c7a65242b3b40459e9793df82e00211 Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Tue, 3 Aug 2021 18:36:55 +0530 Subject: [PATCH 07/12] add comments --- .../challenge/challengesubmit/challengesubmit.component.ts | 1 - .../components/utility/selectphase/selectphase.component.ts | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) 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 c289642e73..ec40609eb7 100644 --- a/frontend_v2/src/app/components/challenge/challengesubmit/challengesubmit.component.ts +++ b/frontend_v2/src/app/components/challenge/challengesubmit/challengesubmit.component.ts @@ -482,7 +482,6 @@ export class ChallengesubmitComponent implements OnInit { SELF.selectedPhase = phase; SELF.isPhaseSelected = true; SELF.isLeaderboardPublic = phase['leaderboard_public']; - console.log(this.isLeaderboardPublic); 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 0e795e09aa..2153497366 100644 --- a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.ts +++ b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.ts @@ -17,7 +17,7 @@ export class SelectphaseComponent implements OnInit, OnChanges { @Input() phases: any; /** - * Phase Splits list + * Phase Splits list for settings tab */ @Input() settingsPhaseSplits: any; @@ -96,6 +96,9 @@ export class SelectphaseComponent implements OnInit, OnChanges { */ challenge: any; + /** + * Select default radio option if same as phase id + */ radioSelected: number; /** From 423049d0cf0b7484ec4d4a28259913b1ca8046cb Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Thu, 5 Aug 2021 20:42:28 +0530 Subject: [PATCH 08/12] fix private label for small screen size --- .../challengesettings.component.scss | 14 ++++---------- .../utility/selectphase/selectphase.component.html | 8 ++++---- .../utility/selectphase/selectphase.component.scss | 11 +++++++++++ 3 files changed, 19 insertions(+), 14 deletions(-) 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 5b1cfa72f3..816cb40206 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss @@ -42,9 +42,9 @@ input { text-align:center; } -@include screen-medium { +@media (max-width: 992px) { .settings-section { - padding: 10px 20px !important; + padding: 50px !important; } } @@ -54,15 +54,9 @@ input { } } -@include screen-small-medium { +@media (max-width: 600px) { .settings-section { - padding: 10px 10px !important; - } -} - -@include screen-small { - .settings-section { - padding: 10px 5px !important; + padding: 25px !important; } } diff --git a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.html b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.html index e7e89d478e..74845ecbd2 100644 --- a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.html +++ b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.html @@ -40,9 +40,9 @@ Select phase - {{ phaseName }} + {{ phaseName }} - + Private @@ -71,7 +71,7 @@ Phase: {{ phaseName }}, Split:  {{ settingsSplitName }}   - + Private @@ -103,7 +103,7 @@ Phase: {{ phaseName }}, Split:  {{ splitName }}   - + Private diff --git a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.scss b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.scss index 142e73be80..7728cd91b2 100644 --- a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.scss +++ b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.scss @@ -28,6 +28,17 @@ padding-right: 0px; } +@media (max-width: 400px) { + .mat-form-field { + margin-right: 40px; + display: block; + } + .col-xs-12 { + padding-bottom: 5px; + width: 80%; + } +} + ::ng-deep .mat-select-placeholder { padding-bottom: 10px; } From a8cc232ba80e4e7bc2eb11131e55c5861ff33861 Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Fri, 6 Aug 2021 19:35:33 +0530 Subject: [PATCH 09/12] fix spacing issues --- .../challengesettings/challengesettings.component.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 816cb40206..6068fcc30b 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss @@ -3,7 +3,7 @@ .challenge-card { .bottom-card-container { - padding-top: 0px; + padding: 0px 30px; .settings-section { padding: 50px; border: 1px solid; @@ -13,7 +13,7 @@ } } .row { - margin: 4% 0px 4% 0px; + margin: 20px 0px 3% 0px; } } From 0a56b59b99769ef36727956199a386ad14686dab Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Mon, 9 Aug 2021 13:46:55 +0530 Subject: [PATCH 10/12] add evaluation script heading --- .../challengesettings/challengesettings.component.html | 5 +++++ .../challengesettings/challengesettings.component.scss | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html index 744316c1e9..9c6ef3f5ba 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.html @@ -213,6 +213,11 @@
Challenge Settings
+
+
+
Evaluation script
+
+
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 6068fcc30b..1984bb61be 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.scss @@ -17,6 +17,10 @@ } } +.row .col { + padding: 0px; +} + input { border-bottom: none; } From 4c38efed1884969c90d14525fb799dd3797ba587 Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Fri, 13 Aug 2021 00:36:41 +0530 Subject: [PATCH 11/12] add check for empty arrays --- .../components/utility/selectphase/selectphase.component.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 2153497366..0936782f59 100644 --- a/frontend_v2/src/app/components/utility/selectphase/selectphase.component.ts +++ b/frontend_v2/src/app/components/utility/selectphase/selectphase.component.ts @@ -116,16 +116,16 @@ export class SelectphaseComponent implements OnInit, OnChanges { this.challenge = challenge; }); - if(this.phases) { + if(Array.isArray(this.phases) && this.phases.length) { this.selectedPhase = this.phases[0]; this.radioSelected = this.phases[0].id; this.selectPhase(this.phases[0]); } - else if(this.settingsPhaseSplits) { + else if(Array.isArray(this.settingsPhaseSplits) && this.settingsPhaseSplits.length) { this.selectedPhaseSplit = this.settingsPhaseSplits[0]; this.selectSettingsPhaseSplit(this.settingsPhaseSplits[0], "selectBox", "settingsPhaseSplit"); } - else { + else if(Array.isArray(this.phaseSplits) && this.phaseSplits.length) { this.selectedPhaseSplit = this.phaseSplits[0]; this.selectPhaseSplit(this.phaseSplits[0], "selectBox", "phaseSplit"); } From 8558f635177010b99e880ff9ef2eff6eadbe3331 Mon Sep 17 00:00:00 2001 From: gautamjajoo Date: Fri, 13 Aug 2021 17:11:32 +0530 Subject: [PATCH 12/12] make phase splits private when phase is private --- .../challengesettings.component.ts | 132 +++++++++++------- 1 file changed, 85 insertions(+), 47 deletions(-) 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 2fcb7525bd..e4de5f05b1 100644 --- a/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.ts +++ b/frontend_v2/src/app/components/challenge/challengesettings/challengesettings.component.ts @@ -809,6 +809,37 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { SELF.selectedPhase['is_public'] = data.is_public; SELF.selectedPhase['showPrivate'] = !data.is_public; SELF.challengeService.changePhaseSelected(true); + if(!SELF.selectedPhase['is_public']) { + for(let i = 0; i < SELF.phaseSplits.length; i++) { + if(SELF.phaseSplits[i]['challenge_phase_name'] === SELF.selectedPhase['name'] && SELF.phaseSplits[i]['visibility'] == 3) { + let visibility: any = 1; + const BODY: FormData = new FormData(); + BODY.append("visibility", visibility); + SELF.apiService + .patchFileUrl( + SELF.endpointsService.particularChallengePhaseSplitUrl(SELF.phaseSplits[i]['id']), + BODY + ) + .subscribe( + (data) => { + SELF.phaseSplits[i]['visibility'] = data.visibility; + SELF.challengeService.changePhaseSplitSelected(true); + SELF.phaseSplits[i]['showPrivate'] = true; + if(SELF.selectedPhaseSplit === SELF.phaseSplits[i]) { + SELF.leaderboardVisibility.state = 'Private'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1'; + } + }, + (err) => { + SELF.globalService.handleApiError(err, true); + SELF.globalService.showToast('error', err); + }, + () => this.logger.info('Change leaderboard visibility after phase is updated') + ); + } + } + } + SELF.globalService.showToast( 'success', 'The phase was successfully made ' + togglePhaseVisibilityState, @@ -909,58 +940,65 @@ export class ChallengesettingsComponent implements OnInit, OnDestroy { */ toggleLeaderboardVisibility() { const SELF = this; - let toggleLeaderboardVisibilityState, visibility; - if (SELF.leaderboardVisibility.state === 'Public') { - toggleLeaderboardVisibilityState = 'private'; - visibility = 1; - SELF.leaderboardVisibility.state = 'Private'; - SELF.leaderboardVisibility.icon = 'fa fa fa-toggle-off grey-text text-darken-1'; - } else { - toggleLeaderboardVisibilityState = 'public'; - visibility = 3; - SELF.leaderboardVisibility.state = 'Public'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; + let toggleLeaderboardVisibilityState, visibility, phaseIsPublic; + for(let i = 0; i < SELF.filteredPhases.length; i++) { + if(SELF.filteredPhases[i]['name'] === SELF.selectedPhaseSplit['challenge_phase_name']) { + phaseIsPublic = SELF.filteredPhases[i]['is_public']; + } } + if(phaseIsPublic) { + if (SELF.leaderboardVisibility.state === 'Public') { + toggleLeaderboardVisibilityState = 'private'; + visibility = 1; + SELF.leaderboardVisibility.state = 'Private'; + SELF.leaderboardVisibility.icon = 'fa fa fa-toggle-off grey-text text-darken-1'; + } else { + toggleLeaderboardVisibilityState = 'public'; + visibility = 3; + SELF.leaderboardVisibility.state = 'Public'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; + } const BODY: FormData = new FormData(); BODY.append("visibility", visibility); SELF.apiService - .patchFileUrl( - SELF.endpointsService.particularChallengePhaseSplitUrl(SELF.selectedPhaseSplit['id']), - BODY - ) - .subscribe( - (data) => { - SELF.selectedPhaseSplit['visibility'] = data.visibility; - SELF.challengeService.changePhaseSplitSelected(true); - if (visibility == 3) { - SELF.selectedPhaseSplit['showPrivate'] = false; - SELF.leaderboardVisibility.state = 'Public'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; - } else { - SELF.selectedPhaseSplit['showPrivate'] = true; - SELF.leaderboardVisibility.state = 'Private'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1'; - } - SELF.globalService.showToast( - 'success', - 'The phase split was successfully made ' + toggleLeaderboardVisibilityState, - 5 - ); - }, - (err) => { - SELF.globalService.handleApiError(err, true); - SELF.globalService.showToast('error', err); - if (visibility == 3) { - SELF.leaderboardVisibility.state = 'Private'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1'; - } else { - SELF.leaderboardVisibility.state = 'Public'; - SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; - } - }, - () => this.logger.info('LEADERBOARD-VISIBILITY-UPDATE-FINISHED') - ); + .patchFileUrl(SELF.endpointsService.particularChallengePhaseSplitUrl(SELF.selectedPhaseSplit['id']),BODY) + .subscribe( + (data) => { + SELF.selectedPhaseSplit['visibility'] = data.visibility; + SELF.challengeService.changePhaseSplitSelected(true); + if (visibility == 3) { + SELF.selectedPhaseSplit['showPrivate'] = false; + SELF.leaderboardVisibility.state = 'Public'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; + } else { + SELF.selectedPhaseSplit['showPrivate'] = true; + SELF.leaderboardVisibility.state = 'Private'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1'; + } + SELF.globalService.showToast( + 'success', + 'The phase split was successfully made ' + toggleLeaderboardVisibilityState, + 5 + ); + }, + (err) => { + SELF.globalService.handleApiError(err, true); + SELF.globalService.showToast('error', err); + if (visibility == 3) { + SELF.leaderboardVisibility.state = 'Private'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-off grey-text text-darken-1'; + } else { + SELF.leaderboardVisibility.state = 'Public'; + SELF.leaderboardVisibility.icon = 'fa fa-toggle-on green-text'; + } + }, + () => this.logger.info('LEADERBOARD-VISIBILITY-UPDATE-FINISHED') + ); } + else { + SELF.globalService.showToast('error', 'The phase is private, please make the phase public'); + } + } // Edit Evaluation Script and Criteria ->