From 9ae6b24c9c97d72719ecd7c3c9e302f62905a682 Mon Sep 17 00:00:00 2001 From: vaghelaparth5 Date: Sun, 14 Sep 2025 15:03:09 +1000 Subject: [PATCH] feat(unit-date-selector): migrate directive to Angular --- angular.json | 1 - .../common/unit-code/unit-code.component.ts | 3 +- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 8 ++ .../unit-dates-selector.coffee | 79 ------------- .../unit-dates-selector.component.html | 110 ++++++++++++++++++ .../unit-dates-selector.component.scss | 0 .../unit-dates-selector.tpl.html | 65 ----------- .../unit-dates-selector.ts | 91 +++++++++++++++ .../units/states/rollover/rollover.tpl.html | 2 +- 10 files changed, 214 insertions(+), 147 deletions(-) delete mode 100644 src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.coffee create mode 100644 src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.component.html create mode 100644 src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.component.scss delete mode 100644 src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.tpl.html create mode 100644 src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.ts diff --git a/angular.json b/angular.json index f2ecb001f1..5dedd22091 100644 --- a/angular.json +++ b/angular.json @@ -36,7 +36,6 @@ "src/styles.scss", "./node_modules/bootstrap/dist/css/bootstrap.css", "./node_modules/ngx-bootstrap/datepicker/bs-datepicker.css", - "./build/assets/doubtfire.css", "./build/assets/node_modules/angular-xeditable/dist/css/xeditable.css", "./build/assets/node_modules/codemirror/lib/codemirror.css", "./build/assets/node_modules/codemirror/theme/xq-light.css", diff --git a/src/app/common/unit-code/unit-code.component.ts b/src/app/common/unit-code/unit-code.component.ts index 462597afe1..9e628c0b65 100644 --- a/src/app/common/unit-code/unit-code.component.ts +++ b/src/app/common/unit-code/unit-code.component.ts @@ -57,7 +57,8 @@ export class UnitCodeComponent implements OnInit, OnDestroy { flip() { this.showState = 'out'; // Trigger animation out setTimeout(() => { - this.currentIndex = (this.currentIndex + 1) % this.unitCodeParts.length; + // A small fix for the frontend code to compile. + this.currentIndex = (this.currentIndex + 1) % this.unitCodeParts?.length; this.showState = 'in'; // Trigger animation in after a delay }, 200); // Delay to match the animation duration } diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index c714ff0e5a..7d3231bab1 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -267,6 +267,7 @@ const MY_DATE_FORMAT = { }, }; import { UnitStudentEnrolmentModalComponent } from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component'; +import { UnitDatesSelectorComponent } from './units/states/rollover/directives/unit-dates-selector/unit-dates-selector'; @NgModule({ // Components we declare @@ -309,6 +310,7 @@ import { UnitStudentEnrolmentModalComponent } from './units/modals/unit-student- TaskDefinitionOverseerComponent, TaskDefinitionScormComponent, UnitAnalyticsComponent, + UnitDatesSelectorComponent, StudentTutorialSelectComponent, StudentCampusSelectComponent, TaskListItemComponent, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index d9245086aa..b1dbb0a60a 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -222,6 +222,7 @@ import {GradeService} from './common/services/grade.service'; import {TaskScormCardComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component'; import { UnitStudentEnrolmentModalService } from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service'; import { PrivacyPolicy } from './config/privacy-policy/privacy-policy'; +import { UnitDatesSelectorComponent } from './units/states/rollover/directives/unit-dates-selector/unit-dates-selector'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -329,6 +330,13 @@ DoubtfireAngularJSModule.directive( 'userBadge', downgradeComponent({component: UserBadgeComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fUnitDatesSelector', + downgradeComponent({component: UnitDatesSelectorComponent}), +); + + DoubtfireAngularJSModule.directive( 'fTaskSubmissionCard', downgradeComponent({component: TaskSubmissionCardComponent}), diff --git a/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.coffee b/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.coffee deleted file mode 100644 index 07569a20a0..0000000000 --- a/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.coffee +++ /dev/null @@ -1,79 +0,0 @@ -angular.module('doubtfire.units.states.rollover.directives.unit-dates-selector', []) - -# -# Editor for the basic details of a unit, such as the name, code -# start and end dates etc. -# -.directive('unitDatesSelector', -> - replace: true - restrict: 'E' - templateUrl: 'units/states/rollover/directives/unit-dates-selector/unit-dates-selector.tpl.html' - controller: ($scope, $state, $rootScope, DoubtfireConstants, alertService, newTeachingPeriodService) -> - $scope.calOptions = { - startOpened: false - endOpened: false - } - - # Get the configurable, external name of Doubtfire - $scope.externalName = DoubtfireConstants.ExternalName - - $scope.saveData = { - id: $scope.unit.id, - toPeriod: null, - startDate: null, - endDate: null - } - - # get the teaching periods- gets an object with the loaded teaching periods - newTeachingPeriodService.cache.values.subscribe( - (periods) -> - $scope.teachingPeriodValues = [{value: undefined, text: "None"}] - other = periods.filter((tp) -> tp.endDate > Date.now()).map((p) -> {value: p, text: "#{p.year} #{p.period}"}) - _.each other, (d) -> $scope.teachingPeriodValues.push(d) - - if (periods.length > 0) - $scope.saveData.toPeriod = periods[periods.length - 1] - ) - - $scope.teachingPeriodSelected = ($event) -> - $scope.saveData.toPeriod = $event - - # Datepicker opener - $scope.open = ($event, pickerData) -> - $event.preventDefault() - $event.stopPropagation() - - if pickerData == 'start' - $scope.calOptions.startOpened = ! $scope.calOptions.startOpened - $scope.calOptions.endOpened = false - else - $scope.calOptions.startOpened = false - $scope.calOptions.endOpened = ! $scope.calOptions.endOpened - - $scope.dateOptions = { - formatYear: 'yy', - startingDay: 1 - } - - $scope.saveUnit = -> - if $scope.saveData.toPeriod - body = { - teaching_period_id: $scope.saveData.toPeriod.id - } - else - body = { - start_date: $scope.saveData.startDate - end_date: $scope.saeData.endDate - } - $scope.unit.rolloverTo(body).subscribe({ - next: (response) -> - alertService.success( "Unit created.", 2000) - $state.go("units/admin", {unitId: response.id}) - error: (response) -> - alertService.error "Error creating unit - #{response}" - - }) - - - -) diff --git a/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.component.html b/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.component.html new file mode 100644 index 0000000000..acea3e1143 --- /dev/null +++ b/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.component.html @@ -0,0 +1,110 @@ +
+
+
+

Create Unit

+

Duplicate an existing unit by specifying the time period.

+
+ +
+
+ + +
+ +
+ + + +
+
+ + +
+ +
+
+ + + + + + + + + + + +
+
+
+ + +
+ +
+
+ + + + + + + + + + + +
+
+
+
+ + + +
+
+
diff --git a/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.component.scss b/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.tpl.html b/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.tpl.html deleted file mode 100644 index 08d6a1a87d..0000000000 --- a/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.tpl.html +++ /dev/null @@ -1,65 +0,0 @@ -
-
-
-

Create Unit

- Duplicate an existing unit by specifying the time period. -
-
-
-
- -
- -
-
- -
- -
-
- - - - - -
-
-
- -
- -
-
- - - - - -
-
-
-
- -
-
-
diff --git a/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.ts b/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.ts new file mode 100644 index 0000000000..21ffc2c18c --- /dev/null +++ b/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.ts @@ -0,0 +1,91 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { Router } from '@angular/router'; +import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; +import { TeachingPeriod } from 'src/app/api/models/teaching-period'; +import { Unit } from 'src/app/api/models/unit'; +import { AlertService } from 'src/app/common/services/alert.service'; +import { TeachingPeriodService as NewTeachingPeriodService } from 'src/app/api/services/teaching-period.service'; + +@Component({ + selector: 'f-unit-dates-selector', + templateUrl: 'unit-dates-selector.component.html', + styleUrls: ['unit-dates-selector.component.scss'] +}) +export class UnitDatesSelectorComponent implements OnInit { + @Input() unit!: Unit; + + form: FormGroup; + calOptions = { + startOpened: false, + endOpened: false + }; + + dateOptions = { + formatYear: 'yy', + startingDay: 1 + }; + + teachingPeriodValues: { value: TeachingPeriod | undefined; text: string }[] = []; + + // External name is a BehaviorSubject + externalName$ = this.doubtfireConstants.ExternalName; + + constructor( + private fb: FormBuilder, + private router: Router, + private alertService: AlertService, + private newTeachingPeriodService: NewTeachingPeriodService, + private doubtfireConstants: DoubtfireConstants + ) { + this.form = this.fb.group({ + toPeriod: [null], + startDate: [null], + endDate: [null] + }); + } + + ngOnInit(): void { + this.newTeachingPeriodService.cache.values.subscribe((periods: TeachingPeriod[]) => { + const now = Date.now(); + this.teachingPeriodValues = [{ value: undefined, text: 'None' }]; + + const futurePeriods = periods + .filter(tp => new Date(tp.endDate).getTime() > now) + .map(tp => ({ + value: tp, + text: `${tp.year} ${tp.period}` + })); + + this.teachingPeriodValues.push(...futurePeriods); + + if (periods.length > 0) { + this.form.patchValue({ toPeriod: periods[periods.length - 1] }); + } + }); + } + + openPicker(picker: 'start' | 'end'): void { + this.calOptions.startOpened = picker === 'start' ? !this.calOptions.startOpened : false; + this.calOptions.endOpened = picker === 'end' ? !this.calOptions.endOpened : false; + } + + saveUnit(): void { + const { toPeriod, startDate, endDate } = this.form.value; + + const body: any = toPeriod + ? { teaching_period_id: toPeriod.id } + : { start_date: startDate, end_date: endDate }; + + // Call model method directly (uses AppInjector internally) + this.unit.rolloverTo(body).subscribe({ + next: (response: Unit) => { + this.alertService.success('Unit created.', 2000); + this.router.navigate(['/units/admin', response.id]); + }, + error: (err: any) => { + this.alertService.error(`Error creating unit - ${err}`); + } + }); + } +} diff --git a/src/app/units/states/rollover/rollover.tpl.html b/src/app/units/states/rollover/rollover.tpl.html index aa2a80abe2..7ef3d1f8cb 100644 --- a/src/app/units/states/rollover/rollover.tpl.html +++ b/src/app/units/states/rollover/rollover.tpl.html @@ -1,3 +1,3 @@
- +