From fe6a3977f87fb2d963b4e7dc6a1ba685c0ca97fd Mon Sep 17 00:00:00 2001 From: Douglas Lim <97420966+dlimyy@users.noreply.github.com> Date: Mon, 25 Sep 2023 07:24:13 +0800 Subject: [PATCH] [#12571] Instructors Edit Feedback Session: Instructor is able to edit submission opening time to an earlier timing (#12580) * Fix submission opening time bug * Fix bug where save button is disabled * Add method in DateTimeService to compare dates * Change to triggerModelChange --------- Co-authored-by: Cedric Ong <67156011+cedricongjh@users.noreply.github.com> --- .../session-edit-form.component.html | 2 +- .../session-edit-form.component.spec.ts | 23 ++++++ .../session-edit-form.component.ts | 30 ++++++++ .../instructor-session-edit-page.component.ts | 1 + src/web/services/datetime.service.spec.ts | 73 +++++++++++++++++++ src/web/services/datetime.service.ts | 50 +++++++++++++ 6 files changed, 178 insertions(+), 1 deletion(-) diff --git a/src/web/app/components/session-edit-form/session-edit-form.component.html b/src/web/app/components/session-edit-form/session-edit-form.component.html index ea8d26cf803..7f7a7f9e435 100644 --- a/src/web/app/components/session-edit-form/session-edit-form.component.html +++ b/src/web/app/components/session-edit-form/session-edit-form.component.html @@ -135,7 +135,7 @@
Or
-
diff --git a/src/web/app/components/session-edit-form/session-edit-form.component.spec.ts b/src/web/app/components/session-edit-form/session-edit-form.component.spec.ts index 21bce10a45d..3ee97b6f228 100644 --- a/src/web/app/components/session-edit-form/session-edit-form.component.spec.ts +++ b/src/web/app/components/session-edit-form/session-edit-form.component.spec.ts @@ -1,6 +1,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; +import { TimeFormat } from 'src/web/types/datetime-const'; import { TeammatesRouterModule } from '../teammates-router/teammates-router.module'; import { SessionEditFormComponent } from './session-edit-form.component'; import { SessionEditFormModule } from './session-edit-form.module'; @@ -30,4 +31,26 @@ describe('SessionEditFormComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should configure the time to be 23:59 if the hour is 23 and minute is greater than 0', () => { + const time : TimeFormat = { hour: 23, minute: 5 }; + component.configureSubmissionOpeningTime(time); + expect(time.hour).toEqual(23); + expect(time.minute).toEqual(59); + }); + + it('should configure the time correctly if the hour is less than 23 and minute is greater than 0', () => { + const time : TimeFormat = { hour: 22, minute: 5 }; + component.configureSubmissionOpeningTime(time); + expect(time.hour).toEqual(23); + expect(time.minute).toEqual(0); + }); + + it('should configure the time correctly if the minute is 0', () => { + const time : TimeFormat = { hour: 21, minute: 0 }; + component.configureSubmissionOpeningTime(time); + expect(time.hour).toEqual(21); + expect(time.minute).toEqual(0); + }); + }); diff --git a/src/web/app/components/session-edit-form/session-edit-form.component.ts b/src/web/app/components/session-edit-form/session-edit-form.component.ts index 1a90937b16e..56e5dfb96f8 100644 --- a/src/web/app/components/session-edit-form/session-edit-form.component.ts +++ b/src/web/app/components/session-edit-form/session-edit-form.component.ts @@ -134,6 +134,36 @@ export class SessionEditFormComponent { }); } + /** + * Triggers the change of the model when the submission opening date changes. + */ + triggerSubmissionOpeningDateModelChange(field: string, date: DateFormat): void { + const minDate: DateFormat = this.minDateForSubmissionStart; + const minTime: TimeFormat = this.minTimeForSubmissionStart; + + // Case where date is same as earliest date and time is earlier than earliest possible time + if (DateTimeService.compareDateFormat(date, minDate) === 0 + && DateTimeService.compareTimeFormat(this.model.submissionStartTime, minTime) === -1) { + this.configureSubmissionOpeningTime(minTime); + this.model.submissionStartTime = minTime; + } + + this.triggerModelChange(field, date); + } + + /** + * Configures the time for the submission opening time. + */ + configureSubmissionOpeningTime(time : TimeFormat) : void { + if (time.hour === 23 && time.minute > 0) { + time.minute = 59; + } else if (time.hour < 23 && time.minute > 0) { + // Case where minutes is not 0 since the earliest time with 0 minutes is the hour before + time.hour += 1; + time.minute = 0; + } + } + /** * Handles course Id change event. * diff --git a/src/web/app/pages-instructor/instructor-session-edit-page/instructor-session-edit-page.component.ts b/src/web/app/pages-instructor/instructor-session-edit-page/instructor-session-edit-page.component.ts index 921fc82419d..4cc6488ff15 100644 --- a/src/web/app/pages-instructor/instructor-session-edit-page/instructor-session-edit-page.component.ts +++ b/src/web/app/pages-instructor/instructor-session-edit-page/instructor-session-edit-page.component.ts @@ -419,6 +419,7 @@ export class InstructorSessionEditPageComponent extends InstructorSessionBasePag this.statusMessageService.showSuccessToast('The feedback session has been updated.'); }, error: (resp: ErrorMessageOutput) => { + this.sessionEditFormModel.isEditable = true; this.statusMessageService.showErrorToast(resp.error.message); }, }); diff --git a/src/web/services/datetime.service.spec.ts b/src/web/services/datetime.service.spec.ts index b97421b4986..1dee9dfb5b5 100644 --- a/src/web/services/datetime.service.spec.ts +++ b/src/web/services/datetime.service.spec.ts @@ -1,5 +1,6 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; +import { DateFormat, TimeFormat } from '../types/datetime-const'; import { DateTimeService } from './datetime.service'; import { TimezoneService } from './timezone.service'; @@ -77,4 +78,76 @@ describe('DateTimeService', () => { expect(result.minute).toEqual(59); }); + it('should return 1 if the first date\'s year is later than the second date\'s year', () => { + const firstDate : DateFormat = { year: 2023, month: 8, day: 23 }; + const secondDate: DateFormat = { year: 2022, month: 8, day: 23 }; + expect(DateTimeService.compareDateFormat(firstDate, secondDate)).toEqual(1); + }); + + it('should return -1 if the first date\'s year is earlier than the second date\'s year', () => { + const firstDate : DateFormat = { year: 2022, month: 8, day: 23 }; + const secondDate: DateFormat = { year: 2023, month: 8, day: 23 }; + expect(DateTimeService.compareDateFormat(firstDate, secondDate)).toEqual(-1); + }); + + it('should return 1 if year is the same and first date\'s month is later than second date\'s month', () => { + const firstDate : DateFormat = { year: 2023, month: 9, day: 23 }; + const secondDate: DateFormat = { year: 2023, month: 8, day: 23 }; + expect(DateTimeService.compareDateFormat(firstDate, secondDate)).toEqual(1); + }); + + it('should return -1 if if year is the same and first date\'s month is earlier than second date\'s month', () => { + const firstDate : DateFormat = { year: 2023, month: 8, day: 23 }; + const secondDate: DateFormat = { year: 2023, month: 9, day: 23 }; + expect(DateTimeService.compareDateFormat(firstDate, secondDate)).toEqual(-1); + }); + + it('should return 1 if year and month are the same and first date\'s day is later than second date\'s day', () => { + const firstDate : DateFormat = { year: 2023, month: 9, day: 28 }; + const secondDate: DateFormat = { year: 2023, month: 9, day: 23 }; + expect(DateTimeService.compareDateFormat(firstDate, secondDate)).toEqual(1); + }); + + it('should return -1 if year and month are same and first date\'s day is earlier than second date\'s day', () => { + const firstDate : DateFormat = { year: 2023, month: 9, day: 23 }; + const secondDate: DateFormat = { year: 2023, month: 9, day: 28 }; + expect(DateTimeService.compareDateFormat(firstDate, secondDate)).toEqual(-1); + }); + + it('should return 0 if both dates have the same year and month and day', () => { + const firstDate : DateFormat = { year: 2023, month: 9, day: 28 }; + const secondDate: DateFormat = { year: 2023, month: 9, day: 28 }; + expect(DateTimeService.compareDateFormat(firstDate, secondDate)).toEqual(0); + }); + + it('should return 1 if the first timing\'s hour is later than the second timing\'s hour', () => { + const firstTime : TimeFormat = { hour: 21, minute: 0 }; + const secondTime : TimeFormat = { hour: 19, minute: 0 }; + expect(DateTimeService.compareTimeFormat(firstTime, secondTime)).toEqual(1); + }); + + it('should return -1 if the first timing\'s hour is earlier than the second timing\'s hour', () => { + const firstTime : TimeFormat = { hour: 20, minute: 0 }; + const secondTime : TimeFormat = { hour: 21, minute: 0 }; + expect(DateTimeService.compareTimeFormat(firstTime, secondTime)).toEqual(-1); + }); + + it('should return 1 if hour is the same and first timing\'s minute is later than second timing\'s minute', () => { + const firstTime : TimeFormat = { hour: 21, minute: 30 }; + const secondTime : TimeFormat = { hour: 21, minute: 0 }; + expect(DateTimeService.compareTimeFormat(firstTime, secondTime)).toEqual(1); + }); + + it('should return -1 if hour is same and first timing\'s minute is earlier than second timing\'s minute', () => { + const firstTime : TimeFormat = { hour: 21, minute: 0 }; + const secondTime : TimeFormat = { hour: 21, minute: 30 }; + expect(DateTimeService.compareTimeFormat(firstTime, secondTime)).toEqual(-1); + }); + + it('should return 0 if both timings have the same hour and minute', () => { + const firstTime : TimeFormat = { hour: 21, minute: 30 }; + const secondTime : TimeFormat = { hour: 21, minute: 30 }; + expect(DateTimeService.compareTimeFormat(firstTime, secondTime)).toEqual(0); + }); + }); diff --git a/src/web/services/datetime.service.ts b/src/web/services/datetime.service.ts index 9baef02632c..b6d86fcd290 100644 --- a/src/web/services/datetime.service.ts +++ b/src/web/services/datetime.service.ts @@ -123,4 +123,54 @@ export class DateTimeService { minute: mmt.minute(), }; } + + /** + * Compares the first date with the second date and checks whether the first + * date is earlier, same or later than the second date. + * Returns 1 if the first date is later than second date, 0 if the first date is the + * same as the second date and -1 if the first date is earlier than the second date. + */ + static compareDateFormat(firstDate : DateFormat, secondDate : DateFormat) : number { + if (firstDate.year > secondDate.year) { + return 1; + } + if (firstDate.year < secondDate.year) { + return -1; + } + if (firstDate.month > secondDate.month) { + return 1; + } + if (firstDate.month < secondDate.month) { + return -1; + } + if (firstDate.day > secondDate.day) { + return 1; + } + if (firstDate.day < secondDate.day) { + return -1; + } + return 0; + } + + /** + * Compares the first timing with the second timing and checks whether the first + * timing is earlier, same or later than the second timing. + * Returns 1 if the first timing is later than second timing, 0 if the first timing is the + * same as the second timing and -1 if the first timing is earlier than the second timing. + */ + static compareTimeFormat(firstTiming : TimeFormat, secondTiming : TimeFormat) : number { + if (firstTiming.hour > secondTiming.hour) { + return 1; + } + if (firstTiming.hour < secondTiming.hour) { + return -1; + } + if (firstTiming.minute > secondTiming.minute) { + return 1; + } + if (firstTiming.minute < secondTiming.minute) { + return -1; + } + return 0; + } }