From 246011e2924fafd3fb67da6446b89735b8e871df Mon Sep 17 00:00:00 2001 From: Leo Luong Date: Sun, 7 Aug 2022 13:16:15 +1000 Subject: [PATCH 0001/1531] new: create initial files for migration of unauthorized --- .../states/unauthorised/unauthorised.component.html | 0 .../states/unauthorised/unauthorised.component.scss | 0 .../states/unauthorised/unauthorised.component.ts | 10 ++++++++++ 3 files changed, 10 insertions(+) create mode 100644 src/app/errors/states/unauthorised/unauthorised.component.html create mode 100644 src/app/errors/states/unauthorised/unauthorised.component.scss create mode 100644 src/app/errors/states/unauthorised/unauthorised.component.ts diff --git a/src/app/errors/states/unauthorised/unauthorised.component.html b/src/app/errors/states/unauthorised/unauthorised.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/errors/states/unauthorised/unauthorised.component.scss b/src/app/errors/states/unauthorised/unauthorised.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/errors/states/unauthorised/unauthorised.component.ts b/src/app/errors/states/unauthorised/unauthorised.component.ts new file mode 100644 index 0000000000..60254f6f70 --- /dev/null +++ b/src/app/errors/states/unauthorised/unauthorised.component.ts @@ -0,0 +1,10 @@ +import { Component} from '@angular/core'; + +@Component({ + selector: 'unauthorised', + templateUrl: 'unauthorised.component.html', + styleUrls: ['unauthorised.component.scss'], +}) +export class UnauthorisedComponent { + constructor(){} +} \ No newline at end of file From 22611c632131b59b27374b11ace21c5ad4e0b7c3 Mon Sep 17 00:00:00 2001 From: Leo Luong Date: Sun, 7 Aug 2022 13:26:47 +1000 Subject: [PATCH 0002/1531] migrate:unlink old components --- src/app/doubtfire-angular.module.ts | 2 ++ src/app/doubtfire-angularjs.module.ts | 4 +++- src/app/doubtfire.states.ts | 24 ++++++++++++++++++- .../unauthorised/unauthorised.component.ts | 4 ++-- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index febb3b8164..33d494bb99 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -164,6 +164,7 @@ import { HeaderComponent } from './common/header/header.component'; import { UnitDropdownComponent } from './common/header/unit-dropdown/unit-dropdown.component'; import { TaskDropdownComponent } from './common/header/task-dropdown/task-dropdown.component'; import { SplashScreenComponent } from './home/splash-screen/splash-screen.component'; +import { UnauthorisedComponent } from './errors/states/unauthorised/unauthorised.component'; @NgModule({ // Components we declare @@ -221,6 +222,7 @@ import { SplashScreenComponent } from './home/splash-screen/splash-screen.compon UnitDropdownComponent, TaskDropdownComponent, SplashScreenComponent, + UnauthorisedComponent, ], // Module Imports imports: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index c8ec2ba1d8..8cc5001dfb 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -236,7 +236,6 @@ import 'build/src/app/api/models/unit.js'; import 'build/src/app/api/api.js'; import 'build/src/app/api/resource-plus.js'; import 'build/src/app/errors/errors.js'; -import 'build/src/app/errors/states/unauthorised/unauthorised.js'; import 'build/src/app/errors/states/not-found/not-found.js'; import 'build/src/app/errors/states/timeout/timeout.js'; import 'build/src/app/errors/states/states.js'; @@ -289,6 +288,7 @@ import { TaskAssessmentModalService } from './common/modals/task-assessment-moda import { TaskSubmissionHistoryComponent } from './tasks/task-submission-history/task-submission-history.component'; import { HeaderComponent } from './common/header/header.component'; import { GlobalStateService } from './projects/states/index/global-state.service'; +import { UnauthorisedComponent } from './errors/states/unauthorised/unauthorised.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -396,6 +396,8 @@ DoubtfireAngularJSModule.directive( downgradeComponent({ component: TaskPlagiarismCardComponent }) ); +DoubtfireAngularJSModule.directive('unauthorised', downgradeComponent({ component: UnauthorisedComponent })); + // Global configuration // If the user enters a URL that doesn't match any known URL (state), send them to `/home` diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index cb9b495500..b4859fac58 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -2,6 +2,7 @@ import { NgHybridStateDeclaration } from '@uirouter/angular-hybrid'; import { Ng2ViewDeclaration } from '@uirouter/angular'; import { InstitutionSettingsComponent } from './admin/institution-settings/institution-settings.component'; import { HomeComponent } from './home/states/home/home.component'; +import { UnauthorisedComponent } from './errors/states/unauthorised/unauthorised.component'; /* @@ -50,7 +51,28 @@ const institutionSettingsState: NgHybridStateDeclaration = { } }; +const UnauthoriedState: NgHybridStateDeclaration = { + name: 'unauthorised', + url: '/unauthorised', // You get here with this url + views: { + // These are the 2 views - the header and main from the body of DF + header: { + // Header is still angularjs + controller: 'BasicHeaderCtrl', // This is the angularjs controller + templateUrl: 'common/header/header.tpl.html', // and the related template html + } as unknown as Ng2ViewDeclaration, // Need dodgy cast to get compiler to ignore type data + main: { + // Main body links to angular component + component: UnauthorisedComponent, + }, + }, + data: { + // Add data used by header + pageTitle: 'Unauthorised', + roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin'], + }, +}; /** * Export the list of states we have created in angular */ -export const doubtfireStates = [institutionSettingsState, HomeState]; +export const doubtfireStates = [institutionSettingsState, HomeState, UnauthoriedState]; diff --git a/src/app/errors/states/unauthorised/unauthorised.component.ts b/src/app/errors/states/unauthorised/unauthorised.component.ts index 60254f6f70..a41aebb8cf 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.ts +++ b/src/app/errors/states/unauthorised/unauthorised.component.ts @@ -1,4 +1,4 @@ -import { Component} from '@angular/core'; +import { Component } from '@angular/core'; @Component({ selector: 'unauthorised', @@ -7,4 +7,4 @@ import { Component} from '@angular/core'; }) export class UnauthorisedComponent { constructor(){} -} \ No newline at end of file +} From a94db3d8838355dfa763c544fdbe978bc258b066 Mon Sep 17 00:00:00 2001 From: Leo Luong Date: Sun, 7 Aug 2022 13:27:32 +1000 Subject: [PATCH 0003/1531] migrate:unlink old components --- .../errors/states/unauthorised/unauthorised.component.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/app/errors/states/unauthorised/unauthorised.component.html b/src/app/errors/states/unauthorised/unauthorised.component.html index e69de29bb2..4f92fedc18 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.html +++ b/src/app/errors/states/unauthorised/unauthorised.component.html @@ -0,0 +1,7 @@ +
+
+ +

Unauthorised

+

You do not have sufficient permissions to access this resource, or your session has expired.

+
+
\ No newline at end of file From c269b04a3a1694cb2056313a0335f1d4f3e7f3be Mon Sep 17 00:00:00 2001 From: Leo Luong Date: Sun, 7 Aug 2022 13:30:22 +1000 Subject: [PATCH 0004/1531] migrate:unlink old components --- src/app/errors/states/states.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/errors/states/states.coffee b/src/app/errors/states/states.coffee index 84cdc11e25..ffcf5c77f7 100644 --- a/src/app/errors/states/states.coffee +++ b/src/app/errors/states/states.coffee @@ -1,5 +1,4 @@ angular.module("doubtfire.errors.states", [ "doubtfire.errors.states.not-found" "doubtfire.errors.states.timeout" - "doubtfire.errors.states.unauthorised" ]) From 275f4c01b255060acf2c4c76803133c7615b1b6a Mon Sep 17 00:00:00 2001 From: Leo Luong Date: Sun, 7 Aug 2022 13:31:57 +1000 Subject: [PATCH 0005/1531] migrate: adjust style --- .../errors/states/unauthorised/unauthorised.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/errors/states/unauthorised/unauthorised.component.html b/src/app/errors/states/unauthorised/unauthorised.component.html index 4f92fedc18..e5566606d5 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.html +++ b/src/app/errors/states/unauthorised/unauthorised.component.html @@ -1,6 +1,6 @@ -
-
- +
+
+

Unauthorised

You do not have sufficient permissions to access this resource, or your session has expired.

From 917a36b69fd3f90e9173a9fef6852507dea419bb Mon Sep 17 00:00:00 2001 From: Leo Luong Date: Sun, 7 Aug 2022 13:34:44 +1000 Subject: [PATCH 0006/1531] migrate: update unit test for unauthorised component --- .../unauthorised.component.spec.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/app/errors/states/unauthorised/unauthorised.component.spec.ts diff --git a/src/app/errors/states/unauthorised/unauthorised.component.spec.ts b/src/app/errors/states/unauthorised/unauthorised.component.spec.ts new file mode 100644 index 0000000000..dcd275e0fd --- /dev/null +++ b/src/app/errors/states/unauthorised/unauthorised.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UnauthorisedComponent } from './unauthorised.component'; + +describe('UnauthorisedComponent', () => { + let component: UnauthorisedComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UnauthorisedComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UnauthorisedComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); \ No newline at end of file From 427ec6e20d597307a7643bd3e70c922b088d2bde Mon Sep 17 00:00:00 2001 From: Anthony Papoutsis Date: Fri, 19 Aug 2022 19:00:45 +1000 Subject: [PATCH 0007/1531] build: create initial files for migration of unit-student-enrollment-modal --- ...it-student-enrollment-modal.component.html | 26 +++++++++++++++++++ ...it-student-enrollment-modal.component.scss | 0 ...unit-student-enrollment-modal.component.ts | 10 +++++++ .../unit-student-enrollment-modal.service.ts | 0 .../unit-student-enrollment-modal.spec.ts | 0 5 files changed, 36 insertions(+) create mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.html create mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.scss create mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.ts create mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.service.ts create mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.spec.ts diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.html b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.html new file mode 100644 index 0000000000..428daca3dd --- /dev/null +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.html @@ -0,0 +1,26 @@ +
+ + + +
diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.scss b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.ts new file mode 100644 index 0000000000..4b84e82634 --- /dev/null +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.ts @@ -0,0 +1,10 @@ +import { Component, Input, Inject } from '@angular/core'; + +@Component({ + selector: 'unit-student-enrollment-modal', + templateUrl: 'unit-student-enrollment-modal.component.html', + styleUrls: ['unit-student-enrollment-modal.component.scss'], +}) +export class UnitStudentEnrollmentModalComponent { + constructor() {} +} diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.service.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.service.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.spec.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.spec.ts new file mode 100644 index 0000000000..e69de29bb2 From 45fc26c8ec5d11b2e86304113c486aa9e9e19503 Mon Sep 17 00:00:00 2001 From: Anthony Papoutsis Date: Sat, 27 Aug 2022 11:56:28 +1000 Subject: [PATCH 0008/1531] build: material ui and functioanlity --- package-lock.json | 73 +++++++++++++++++++ src/app/ajs-upgraded-providers.ts | 7 ++ src/app/doubtfire-angular.module.ts | 4 + src/app/doubtfire-angularjs.module.ts | 23 +++--- src/app/units/modals/modals.coffee | 1 - ...nit-student-enrolment-modal.component.html | 34 +++++++++ ...nit-student-enrolment-modal.component.scss | 27 +++++++ .../unit-student-enrolment-modal.component.ts | 55 ++++++++++++++ .../unit-student-enrolment-modal.service.ts | 20 +++++ .../unit-student-enrolment-modal.spec.ts | 0 .../unit-student-enrolment-modal.tpl.html | 2 +- 11 files changed, 233 insertions(+), 13 deletions(-) create mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html create mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.scss create mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts create mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts create mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts diff --git a/package-lock.json b/package-lock.json index ab253c8d86..80bef8d980 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44085,6 +44085,79 @@ "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.18.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "send": { + "version": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + } } }, "server-destroy": { diff --git a/src/app/ajs-upgraded-providers.ts b/src/app/ajs-upgraded-providers.ts index cb3e586088..c4aef6e1e2 100644 --- a/src/app/ajs-upgraded-providers.ts +++ b/src/app/ajs-upgraded-providers.ts @@ -30,6 +30,13 @@ export const calendarModal = new InjectionToken('CalendarModal'); export const aboutDoubtfireModal = new InjectionToken('AboutDoubtfireModal'); export const groupService = new InjectionToken('groupService'); export const plagiarismReportModal = new InjectionToken('PlagiarismReportModal'); +export const CampusService = new InjectionToken('campusService'); + +export const campusServiceProvider = { + provide: CampusService, + useFactory: (i: any) => i.get('campusService'), + deps: ['$injector'], +}; // Define a provider for the above injection token... // It will get the service from AngularJS via the factory diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index febb3b8164..4a7de72f49 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -76,6 +76,7 @@ import { aboutDoubtfireModalProvider, calendarModalProvider, userNotificationSettingsModalProvider, + campusServiceProvider, } from './ajs-upgraded-providers'; import { TaskCommentComposerComponent, @@ -164,6 +165,7 @@ import { HeaderComponent } from './common/header/header.component'; import { UnitDropdownComponent } from './common/header/unit-dropdown/unit-dropdown.component'; import { TaskDropdownComponent } from './common/header/task-dropdown/task-dropdown.component'; import { SplashScreenComponent } from './home/splash-screen/splash-screen.component'; +import { UnitStudentEnrolmentModalComponent } from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component'; @NgModule({ // Components we declare @@ -221,6 +223,7 @@ import { SplashScreenComponent } from './home/splash-screen/splash-screen.compon UnitDropdownComponent, TaskDropdownComponent, SplashScreenComponent, + UnitStudentEnrolmentModalComponent, ], // Module Imports imports: [ @@ -332,6 +335,7 @@ import { SplashScreenComponent } from './home/splash-screen/splash-screen.compon TasksInTutorialsPipe, TasksForInboxSearchPipe, IsActiveUnitRole, + campusServiceProvider, ], }) // There is no longer any requirement for an EntryComponents section diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index c8ec2ba1d8..d3ce823e71 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -128,7 +128,6 @@ import 'build/src/app/groups/group-member-list/group-member-list.js'; import 'build/src/app/groups/group-set-selector/group-set-selector.js'; import 'build/src/app/groups/tutor-group-manager/tutor-group-manager.js'; import 'build/src/app/groups/student-group-manager/student-group-manager.js'; -import 'build/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.js'; import 'build/src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.js'; import 'build/src/app/units/modals/modals.js'; import 'build/src/app/units/units.js'; @@ -289,6 +288,7 @@ import { TaskAssessmentModalService } from './common/modals/task-assessment-moda import { TaskSubmissionHistoryComponent } from './tasks/task-submission-history/task-submission-history.component'; import { HeaderComponent } from './common/header/header.component'; import { GlobalStateService } from './projects/states/index/global-state.service'; +import { UnitStudentEnrolmentModalService } from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -322,16 +322,14 @@ DoubtfireAngularJSModule.factory('checkForUpdateService', downgradeInjectable(Ch DoubtfireAngularJSModule.factory('TaskAssessmentModal', downgradeInjectable(TaskAssessmentModalService)); DoubtfireAngularJSModule.factory('TaskSubmission', downgradeInjectable(TaskSubmissionService)); DoubtfireAngularJSModule.factory('GlobalStateService', downgradeInjectable(GlobalStateService)); +DoubtfireAngularJSModule.factory('UnitStudentEnrolmentModal', downgradeInjectable(UnitStudentEnrolmentModalService)); // directive -> component DoubtfireAngularJSModule.directive( 'taskCommentComposer', downgradeComponent({ component: TaskCommentComposerComponent }) ); -DoubtfireAngularJSModule.directive( - 'appHeader', - downgradeComponent({ component: HeaderComponent }) -); +DoubtfireAngularJSModule.directive('appHeader', downgradeComponent({ component: HeaderComponent })); DoubtfireAngularJSModule.directive( 'intelligentDiscussionPlayer', downgradeComponent({ component: IntelligentDiscussionPlayerComponent }) @@ -374,12 +372,15 @@ DoubtfireAngularJSModule.directive( downgradeComponent({ component: TaskDescriptionCardComponent }) ); -DoubtfireAngularJSModule.directive('taskAssessor', - downgradeComponent({ component: TaskAssessorComponent })); -DoubtfireAngularJSModule.directive('taskAssessmentComment', - downgradeComponent({ component: TaskAssessmentCommentComponent })); -DoubtfireAngularJSModule.directive('taskSubmissionHistory', - downgradeComponent({ component: TaskSubmissionHistoryComponent })); +DoubtfireAngularJSModule.directive('taskAssessor', downgradeComponent({ component: TaskAssessorComponent })); +DoubtfireAngularJSModule.directive( + 'taskAssessmentComment', + downgradeComponent({ component: TaskAssessmentCommentComponent }) +); +DoubtfireAngularJSModule.directive( + 'taskSubmissionHistory', + downgradeComponent({ component: TaskSubmissionHistoryComponent }) +); // Global configuration DoubtfireAngularJSModule.directive( diff --git a/src/app/units/modals/modals.coffee b/src/app/units/modals/modals.coffee index fb091e725e..9b2b2c391f 100644 --- a/src/app/units/modals/modals.coffee +++ b/src/app/units/modals/modals.coffee @@ -1,4 +1,3 @@ angular.module('doubtfire.units.modals', [ 'doubtfire.units.modals.unit-ilo-edit-modal' - 'doubtfire.units.modals.unit-student-enrolment-modal' ]) diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html new file mode 100644 index 0000000000..7b25032b56 --- /dev/null +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html @@ -0,0 +1,34 @@ + diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.scss b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.scss new file mode 100644 index 0000000000..4ffc18b0ce --- /dev/null +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.scss @@ -0,0 +1,27 @@ +.modal-complete { + width: 500px; +} + +.modal-heading-container { + margin-bottom: 16px; +} + +.modal-heading { + font-size: 24px; +} + +.modal-content-container { + margin-top: 16px; +} + +.modal-container { + display: flex; + justify-content: space-around; + align-items: center; +} + +.card-actions { + margin-top: 8px; + display: flex; + justify-content: flex-end; +} diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts new file mode 100644 index 0000000000..328b04ae9a --- /dev/null +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts @@ -0,0 +1,55 @@ +import { Component, Input, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { alertService, CampusService } from 'src/app/ajs-upgraded-providers'; + +@Component({ + selector: 'unit-student-enrolment-modal', + templateUrl: 'unit-student-enrolment-modal.component.html', + styleUrls: ['unit-student-enrolment-modal.component.scss'], +}) +export class UnitStudentEnrolmentModalComponent { + unit: any; + campuses: any = []; + projects: any; + student_id: string; + campus_id: any; + this; + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + @Inject(alertService) public alert: any, + @Inject(CampusService) public campusService: any + ) {} + + ngOnInit() { + this.unit = this.data.unit; + this.projects = this.data.unit.students; + this.campusService.query().subscribe((campuses: any) => { + this.campuses = campuses; + }); + console.log(this.unit); + console.log(this.projects); + } + + enrolStudent(student_id, campus_id) { + console.log(this.unit.id, student_id, campus_id); + if (campus_id == null) { + this.alert.add('danger', 'Campus missing. Please indicate student campus', 5000); + return; + } + + return this.unit.$create( + { unit_id: this.unit.id, student_num: student_id, campus_id: campus_id }, + (project: { project_id }) => { + if (!this.unit.studentEnrolled(project.project_id)) { + this.alert.add('success', 'Student enrolled', 2000); + } else { + this.alert.add('danger', 'Student is already enrolled', 2000); + } + }, + (response: { data: { error } }) => + this.alert.add('danger', `Error enrolling student: ${response.data.error}`, 6000) + ); + } +} diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts new file mode 100644 index 0000000000..6d99509ab7 --- /dev/null +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; +import { MatDialogRef, MatDialog } from '@angular/material/dialog'; +import { UnitStudentEnrolmentModalComponent } from './unit-student-enrolment-modal.component'; + +@Injectable({ + providedIn: 'root', +}) +export class UnitStudentEnrolmentModalService { + constructor(public dialog: MatDialog) {} + + public show(unit: any, project: any) { + let dialogRef: MatDialogRef; + dialogRef = this.dialog.open(UnitStudentEnrolmentModalComponent, { + data: { + unit, + project, + }, + }); + } +} diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.tpl.html b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.tpl.html index 3605bbfe53..53bfe9afd0 100644 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.tpl.html +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.tpl.html @@ -7,7 +7,7 @@

Enrol Student

- +
From da51e8e0cc9518a2a76447a48079b42f144064fc Mon Sep 17 00:00:00 2001 From: Anthony Papoutsis Date: Sat, 27 Aug 2022 11:59:30 +1000 Subject: [PATCH 0009/1531] fix: duplicate files --- ...it-student-enrollment-modal.component.html | 26 ------------------- ...it-student-enrollment-modal.component.scss | 0 ...unit-student-enrollment-modal.component.ts | 10 ------- .../unit-student-enrollment-modal.service.ts | 0 .../unit-student-enrollment-modal.spec.ts | 0 5 files changed, 36 deletions(-) delete mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.html delete mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.scss delete mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.ts delete mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.service.ts delete mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.spec.ts diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.html b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.html deleted file mode 100644 index 428daca3dd..0000000000 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.html +++ /dev/null @@ -1,26 +0,0 @@ -
- - - -
diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.scss b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.ts deleted file mode 100644 index 4b84e82634..0000000000 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, Input, Inject } from '@angular/core'; - -@Component({ - selector: 'unit-student-enrollment-modal', - templateUrl: 'unit-student-enrollment-modal.component.html', - styleUrls: ['unit-student-enrollment-modal.component.scss'], -}) -export class UnitStudentEnrollmentModalComponent { - constructor() {} -} diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.service.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.service.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.spec.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrollment-modal.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 From 070ed11f520dcbcfa470063185a1d53036bbd3ce Mon Sep 17 00:00:00 2001 From: Anthony Papoutsis Date: Wed, 31 Aug 2022 14:01:37 +1000 Subject: [PATCH 0010/1531] build: complete --- src/app/ajs-upgraded-providers.ts | 7 +++ src/app/doubtfire-angular.module.ts | 2 + .../unit-student-enrolment-modal.coffee | 45 ------------------- .../unit-student-enrolment-modal.component.ts | 15 ++++--- .../unit-student-enrolment-modal.service.ts | 3 +- .../unit-student-enrolment-modal.spec.ts | 27 +++++++++++ .../unit-student-enrolment-modal.tpl.html | 26 ----------- 7 files changed, 45 insertions(+), 80 deletions(-) delete mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.coffee delete mode 100644 src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.tpl.html diff --git a/src/app/ajs-upgraded-providers.ts b/src/app/ajs-upgraded-providers.ts index c4aef6e1e2..554a5e4e3d 100644 --- a/src/app/ajs-upgraded-providers.ts +++ b/src/app/ajs-upgraded-providers.ts @@ -31,6 +31,13 @@ export const aboutDoubtfireModal = new InjectionToken('AboutDoubtfireModal'); export const groupService = new InjectionToken('groupService'); export const plagiarismReportModal = new InjectionToken('PlagiarismReportModal'); export const CampusService = new InjectionToken('campusService'); +export const Project = new InjectionToken('Project'); + +export const projectProvider = { + provide: Project, + useFactory: (i: any) => i.get('Project'), + deps: ['$injector'], +}; export const campusServiceProvider = { provide: CampusService, diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 4a7de72f49..679f643767 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -77,6 +77,7 @@ import { calendarModalProvider, userNotificationSettingsModalProvider, campusServiceProvider, + projectProvider, } from './ajs-upgraded-providers'; import { TaskCommentComposerComponent, @@ -336,6 +337,7 @@ import { UnitStudentEnrolmentModalComponent } from './units/modals/unit-student- TasksForInboxSearchPipe, IsActiveUnitRole, campusServiceProvider, + projectProvider, ], }) // There is no longer any requirement for an EntryComponents section diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.coffee b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.coffee deleted file mode 100644 index 4c3f117660..0000000000 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.coffee +++ /dev/null @@ -1,45 +0,0 @@ -angular.module('doubtfire.units.modals.unit-student-enrolment-modal', []) -# -# Modal to enrol a student in the given tutorial -# -.factory('UnitStudentEnrolmentModal', ($modal) -> - UnitStudentEnrolmentModal = {} - - # Must provide unit - UnitStudentEnrolmentModal.show = (unit) -> - $modal.open - controller: 'UnitStudentEnrolmentModalCtrl' - templateUrl: 'units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.tpl.html' - resolve: { - unit: -> unit - } - - UnitStudentEnrolmentModal -) -.controller('UnitStudentEnrolmentModalCtrl', ($scope, $modalInstance, Project, unit, alertService, campusService) -> - $scope.unit = unit - $scope.projects = unit.students - $scope.campuses = [] - $scope.data = { campus_id: 1 } # need in object for observing - - campusService.query().subscribe( (campuses) -> - $scope.campuses = campuses - $scope.data.campus_id = campuses[0].id - ) - - $scope.enrolStudent = (student_id, campus_id) -> - if ! campus_id? - alertService.add('danger', 'Campus missing. Please indicate student campus', 5000) - return - Project.create {unit_id: unit.id, student_num: student_id, campus_id: campus_id }, - (project) -> - if ! unit.studentEnrolled project.project_id - unit.addStudent project - alertService.add("success", "Student enrolled", 2000) - $modalInstance.close() - else - alertService.add("danger", "Student is already enrolled", 2000) - $modalInstance.close() - (response) -> - alertService.add("danger", "Error enrolling student: #{response.data.error}", 6000) -) diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts index 328b04ae9a..c58d56df74 100644 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts @@ -1,6 +1,6 @@ -import { Component, Input, Inject } from '@angular/core'; +import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { alertService, CampusService } from 'src/app/ajs-upgraded-providers'; +import { alertService, CampusService, Project } from 'src/app/ajs-upgraded-providers'; @Component({ selector: 'unit-student-enrolment-modal', @@ -13,13 +13,13 @@ export class UnitStudentEnrolmentModalComponent { projects: any; student_id: string; campus_id: any; - this; constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, @Inject(alertService) public alert: any, - @Inject(CampusService) public campusService: any + @Inject(CampusService) public campusService: any, + @Inject(Project) private project: any ) {} ngOnInit() { @@ -38,12 +38,13 @@ export class UnitStudentEnrolmentModalComponent { this.alert.add('danger', 'Campus missing. Please indicate student campus', 5000); return; } - - return this.unit.$create( + this.project.create( { unit_id: this.unit.id, student_num: student_id, campus_id: campus_id }, - (project: { project_id }) => { + (project) => { if (!this.unit.studentEnrolled(project.project_id)) { + this.unit.addStudent(project); this.alert.add('success', 'Student enrolled', 2000); + this.dialogRef.close(); } else { this.alert.add('danger', 'Student is already enrolled', 2000); } diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts index 6d99509ab7..5ecec93bc9 100644 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts @@ -8,12 +8,11 @@ import { UnitStudentEnrolmentModalComponent } from './unit-student-enrolment-mod export class UnitStudentEnrolmentModalService { constructor(public dialog: MatDialog) {} - public show(unit: any, project: any) { + public show(unit: any) { let dialogRef: MatDialogRef; dialogRef = this.dialog.open(UnitStudentEnrolmentModalComponent, { data: { unit, - project, }, }); } diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts index e69de29bb2..7331956e18 100644 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts @@ -0,0 +1,27 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; +import { UnitStudentEnrolmentModalComponent } from './unit-student-enrolment-modal.component'; + +describe('RolloverTeachingPeriodModalComponent', () => { + let component: UnitStudentEnrolmentModalComponent; + let fixture: ComponentFixture; + + beforeEach( + waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [UnitStudentEnrolmentModalComponent], + providers: [{ provide: DoubtfireConstants }], + }).compileComponents(); + }) + ); + + beforeEach(() => { + fixture = TestBed.createComponent(UnitStudentEnrolmentModalComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.tpl.html b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.tpl.html deleted file mode 100644 index 53bfe9afd0..0000000000 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.tpl.html +++ /dev/null @@ -1,26 +0,0 @@ -
- - - -
From 97686fcad49cd1fd4af9aef266af26064fdfb186 Mon Sep 17 00:00:00 2001 From: Leo Luong Date: Fri, 9 Sep 2022 16:35:28 +1000 Subject: [PATCH 0011/1531] chore: update html template --- .../unauthorised/unauthorised.component.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/app/errors/states/unauthorised/unauthorised.component.html b/src/app/errors/states/unauthorised/unauthorised.component.html index e5566606d5..a0f26d25c2 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.html +++ b/src/app/errors/states/unauthorised/unauthorised.component.html @@ -1,7 +1,7 @@ -
-
- -

Unauthorised

-

You do not have sufficient permissions to access this resource, or your session has expired.

-
-
\ No newline at end of file +
+
+ +

Unauthorised

+

You do not have sufficient permissions to access this resource, or your session has expired.

+
+
\ No newline at end of file From a31cc1bfb9a03a60a0c087cb84ae559fb515b404 Mon Sep 17 00:00:00 2001 From: Leo Luong Date: Mon, 12 Sep 2022 11:15:40 +1000 Subject: [PATCH 0012/1531] chore: delete old files --- .../states/unauthorised/unauthorised.coffee | 19 ------------------- .../states/unauthorised/unauthorised.tpl.html | 7 ------- 2 files changed, 26 deletions(-) delete mode 100644 src/app/errors/states/unauthorised/unauthorised.coffee delete mode 100644 src/app/errors/states/unauthorised/unauthorised.tpl.html diff --git a/src/app/errors/states/unauthorised/unauthorised.coffee b/src/app/errors/states/unauthorised/unauthorised.coffee deleted file mode 100644 index 1c16b98025..0000000000 --- a/src/app/errors/states/unauthorised/unauthorised.coffee +++ /dev/null @@ -1,19 +0,0 @@ -angular.module("doubtfire.errors.states.unauthorised", []) - -# -# Define the unauthorised state -# -.config((headerServiceProvider) -> - stateData = - url: "/unauthorised" - views: - main: - controller: "UnauthorisedCtrl" - templateUrl: "errors/states/unauthorised/unauthorised.tpl.html" - data: - pageTitle: "_Unauthorised_" - - headerServiceProvider.state "unauthorised", stateData -) - -.controller("UnauthorisedCtrl", ($scope) ->) diff --git a/src/app/errors/states/unauthorised/unauthorised.tpl.html b/src/app/errors/states/unauthorised/unauthorised.tpl.html deleted file mode 100644 index a0f26d25c2..0000000000 --- a/src/app/errors/states/unauthorised/unauthorised.tpl.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
- -

Unauthorised

-

You do not have sufficient permissions to access this resource, or your session has expired.

-
-
\ No newline at end of file From 164659e66a352612ce9e66c1b37e0eec6107e004 Mon Sep 17 00:00:00 2001 From: Leo Luong Date: Tue, 13 Sep 2022 12:51:18 +1000 Subject: [PATCH 0013/1531] chore: upload icon --- src/app/errors/errors.scss | 10 +--------- .../unauthorised/unauthorised.component.html | 12 ++++++------ .../unauthorised/unauthorised.component.scss | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/app/errors/errors.scss b/src/app/errors/errors.scss index bb20204bca..8b13789179 100644 --- a/src/app/errors/errors.scss +++ b/src/app/errors/errors.scss @@ -1,9 +1 @@ -.error-container { - h1 + p { - margin-top: 20px; - } - i { - margin-top: 30px; - font-size: 100px; - } -} + diff --git a/src/app/errors/states/unauthorised/unauthorised.component.html b/src/app/errors/states/unauthorised/unauthorised.component.html index a0f26d25c2..6954101277 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.html +++ b/src/app/errors/states/unauthorised/unauthorised.component.html @@ -1,7 +1,7 @@ -
-
- -

Unauthorised

-

You do not have sufficient permissions to access this resource, or your session has expired.

+ +
+ warning
-
\ No newline at end of file +

Unauthorised

+

You do not have sufficient permissions to access this resource, or your session has expired.

+ diff --git a/src/app/errors/states/unauthorised/unauthorised.component.scss b/src/app/errors/states/unauthorised/unauthorised.component.scss index e69de29bb2..52cb7522ff 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.scss +++ b/src/app/errors/states/unauthorised/unauthorised.component.scss @@ -0,0 +1,14 @@ +.icon-display { + font-size: 15rem; + padding-top: 10px; + padding-bottom: 10px; + +} + +.icon-container{ + padding-right: 12rem; +} + +.text-centre{ + text-align: center; +} \ No newline at end of file From ae20c0371389573c11bd2efe4da4da1fb1f10ec4 Mon Sep 17 00:00:00 2001 From: Chanputhi Date: Sun, 18 Dec 2022 00:29:56 +1100 Subject: [PATCH 0014/1531] build: create initial file for privacy-policy.ts migration --- .../config/privacy-policy/privacy-policy.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/app/config/privacy-policy/privacy-policy.ts diff --git a/src/app/config/privacy-policy/privacy-policy.ts b/src/app/config/privacy-policy/privacy-policy.ts new file mode 100644 index 0000000000..8142d8b08c --- /dev/null +++ b/src/app/config/privacy-policy/privacy-policy.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import API_URL from 'src/app/config/constants/apiURL'; + +interface Response { + privacy: string; + plagiarism: string; +} + +@Injectable({ + providedIn: 'root' +}) + +export class PrivacyPolicy { + privacy = ''; + plagiarism = ''; + loaded = false; + + public API_URL: string = API_URL; + + constructor(private http: HttpClient) { + + const url: string = `${this.API_URL}/settings/privacy`; + + this.http + .get(url) + .subscribe(response => { + this.privacy = response.privacy; + this.plagiarism = response.plagiarism; + this.loaded = true; + }); + } +} \ No newline at end of file From 36ed3ba44126d9a29b366999e49b07631a93e308 Mon Sep 17 00:00:00 2001 From: Chanputhi Date: Sun, 18 Dec 2022 00:35:51 +1100 Subject: [PATCH 0015/1531] test: create privacy-policy.spec.ts for testing the privacy-policy service --- .../config/privacy-policy/privacy-policy.spec.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/app/config/privacy-policy/privacy-policy.spec.ts diff --git a/src/app/config/privacy-policy/privacy-policy.spec.ts b/src/app/config/privacy-policy/privacy-policy.spec.ts new file mode 100644 index 0000000000..23982f5ecd --- /dev/null +++ b/src/app/config/privacy-policy/privacy-policy.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import {PrivacyPolicy } from './privacy-policy'; + +describe('PrivacyPolicy', () => { + let service: PrivacyPolicy; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(PrivacyPolicy); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); \ No newline at end of file From c3f860cdbc10a38505bfbf6b14e381042bdc58f2 Mon Sep 17 00:00:00 2001 From: Chanputhi Date: Sun, 18 Dec 2022 00:45:07 +1100 Subject: [PATCH 0016/1531] migrate: linking new and unlink old module from doubtfire-angularjs and doubtfire-angular --- src/app/config/config.coffee | 1 - src/app/doubtfire-angular.module.ts | 2 ++ src/app/doubtfire-angularjs.module.ts | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app/config/config.coffee b/src/app/config/config.coffee index 853d046373..a97f457d3b 100644 --- a/src/app/config/config.coffee +++ b/src/app/config/config.coffee @@ -13,5 +13,4 @@ angular.module('doubtfire.config', [ 'doubtfire.config.runtime' 'doubtfire.config.root-controller' 'doubtfire.config.debug' - 'doubtfire.config.privacy-policy' ]) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 6087e7228d..d6ecea7f5f 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -175,6 +175,7 @@ import { EditProfileFormComponent } from './common/edit-profile-form/edit-profil import { TransitionHooksService } from './sessions/transition-hooks.service'; import { EditProfileComponent } from './account/edit-profile/edit-profile.component'; import { UserBadgeComponent } from './common/user-badge/user-badge.component'; +import { PrivacyPolicy } from './config/privacy-policy/privacy-policy'; @NgModule({ // Components we declare @@ -358,6 +359,7 @@ import { UserBadgeComponent } from './common/user-badge/user-badge.component'; TasksInTutorialsPipe, TasksForInboxSearchPipe, IsActiveUnitRole, + PrivacyPolicy ], }) // There is no longer any requirement for an EntryComponents section diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 6cab1797bc..3152b71ec4 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -60,7 +60,7 @@ import 'build/src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment-modal/t import 'build/src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.js'; import 'build/src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.js'; import 'build/src/app/tasks/task-definition-editor/task-definition-editor.js'; -import 'build/src/app/config/privacy-policy/privacy-policy.js'; + import 'build/src/app/config/runtime/runtime.js'; import 'build/src/app/config/config.js'; import 'build/src/app/config/root-controller/root-controller.js'; @@ -265,6 +265,7 @@ import { TaskDefinitionService } from './api/services/task-definition.service'; import { EditProfileDialogService } from './common/modals/edit-profile-dialog/edit-profile-dialog.service'; import { GroupService } from './api/services/group.service'; import { UserBadgeComponent } from './common/user-badge/user-badge.component'; +import { PrivacyPolicy } from './config/privacy-policy/privacy-policy'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -311,6 +312,7 @@ DoubtfireAngularJSModule.factory('TaskSubmission', downgradeInjectable(TaskSubmi DoubtfireAngularJSModule.factory('GlobalStateService', downgradeInjectable(GlobalStateService)); DoubtfireAngularJSModule.factory('TransitionHooksService', downgradeInjectable(TransitionHooksService)); DoubtfireAngularJSModule.factory('EditProfileService', downgradeInjectable(EditProfileDialogService)); +DoubtfireAngularJSModule.factory('PrivacyPolicy', downgradeInjectable(PrivacyPolicy)); // directive -> component DoubtfireAngularJSModule.directive( From 940c25acd27c5cfe9ffaa9c4fddd4f5a183e0ecc Mon Sep 17 00:00:00 2001 From: Chanputhi Date: Sun, 18 Dec 2022 00:47:25 +1100 Subject: [PATCH 0017/1531] remove: delete the old privacy-policy.coffescript from the file --- .../config/privacy-policy/privacy-policy.coffee | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 src/app/config/privacy-policy/privacy-policy.coffee diff --git a/src/app/config/privacy-policy/privacy-policy.coffee b/src/app/config/privacy-policy/privacy-policy.coffee deleted file mode 100644 index a7a1a84efa..0000000000 --- a/src/app/config/privacy-policy/privacy-policy.coffee +++ /dev/null @@ -1,17 +0,0 @@ -angular.module("doubtfire.config.privacy-policy", []) - -.factory('PrivacyPolicy', ($http, DoubtfireConstants) -> - privacyPolicy = { - privacy: '', - plagiarism: '', - loaded: false, - } - - $http.get("#{DoubtfireConstants.API_URL}/settings/privacy").then ((response) -> - privacyPolicy.privacy = response.data.privacy - privacyPolicy.plagiarism = response.data.plagiarism - privacyPolicy.loaded = true - ) - - privacyPolicy -) From f1cc39e59dd224c55ee0e8b5f1d50855263d147e Mon Sep 17 00:00:00 2001 From: brandonsmith301 Date: Fri, 16 Feb 2024 13:16:31 +1100 Subject: [PATCH 0018/1531] feat: visualisations Updated Both Progress Burndown Chart And Pie Chart Change by Brandon --- package-lock.json | 19336 ++++++++++------ package.json | 2 + src/app/doubtfire-angular.module.ts | 7 + src/app/doubtfire-angularjs.module.ts | 13 + .../progress-dashboard.tpl.html | 10 +- .../progressburndownchart.component.html | 19 + .../progressburndownchart.component.scss | 0 .../progressburndownchart.component.ts | 132 + .../taskvisualisation.component.html | 7 + .../taskvisualisation.component.scss | 0 .../taskvisualisation.component.ts | 99 + 11 files changed, 12256 insertions(+), 7369 deletions(-) create mode 100644 src/app/visualisations/progress-burndown-chart/progressburndownchart.component.html create mode 100644 src/app/visualisations/progress-burndown-chart/progressburndownchart.component.scss create mode 100644 src/app/visualisations/progress-burndown-chart/progressburndownchart.component.ts create mode 100644 src/app/visualisations/task-visualisation/taskvisualisation.component.html create mode 100644 src/app/visualisations/task-visualisation/taskvisualisation.component.scss create mode 100644 src/app/visualisations/task-visualisation/taskvisualisation.component.ts diff --git a/package-lock.json b/package-lock.json index 09d112c716..5732ac6a28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "@angular/service-worker": "^17.0.3", "@angular/upgrade": "^17.0.3", "@ctrl/ngx-emoji-mart": "^9.2.0", + "@swimlane/ngx-charts": "^20.5.0", "@uirouter/angular": "^12.0", "@uirouter/angular-hybrid": "^16.0", "@uirouter/angularjs": "^1.0.30", @@ -66,6 +67,7 @@ "ngx-bootstrap": "^6.1.0", "ngx-entity-service": "^0.0.37", "ngx-lottie": "^10.0.0", + "npm": "^10.4.0", "nvd3": "1.8.6", "rxjs": "~7.4.0", "showdown": "1.3.0", @@ -5710,6 +5712,38 @@ "dev": true, "license": "MIT" }, + "node_modules/@swimlane/ngx-charts": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@swimlane/ngx-charts/-/ngx-charts-20.5.0.tgz", + "integrity": "sha512-PNBIHdu/R3ceD7jnw1uCBVOj4k3T6IxfdW6xsDsglGkZyoWMEEq4tLoEurjLEKzmDtRv9c35kVNOXy0lkOuXeA==", + "dependencies": { + "d3-array": "^3.1.1", + "d3-brush": "^3.0.0", + "d3-color": "^3.1.0", + "d3-ease": "^3.0.1", + "d3-format": "^3.1.0", + "d3-hierarchy": "^3.1.0", + "d3-interpolate": "^3.0.1", + "d3-sankey": "^0.12.3", + "d3-scale": "^4.0.2", + "d3-selection": "^3.0.0", + "d3-shape": "^3.2.0", + "d3-time-format": "^3.0.0", + "d3-transition": "^3.0.1", + "rfdc": "^1.3.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/animations": ">=12.0.0", + "@angular/cdk": ">=12.0.0", + "@angular/common": ">=12.0.0", + "@angular/core": ">=12.0.0", + "@angular/forms": ">=12.0.0", + "@angular/platform-browser": ">=12.0.0", + "@angular/platform-browser-dynamic": ">=12.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "dev": true, @@ -7387,7 +7421,7 @@ }, "node_modules/anymatch": { "version": "3.1.3", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -8073,7 +8107,7 @@ }, "node_modules/binary-extensions": { "version": "2.2.0", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8280,7 +8314,7 @@ }, "node_modules/braces": { "version": "3.0.2", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.0.1" @@ -9024,7 +9058,7 @@ }, "node_modules/chokidar": { "version": "3.5.3", - "devOptional": true, + "dev": true, "funding": [ { "type": "individual", @@ -10060,6 +10094,238 @@ "version": "3.5.17", "license": "BSD-3-Clause" }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", + "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", + "dependencies": { + "d3-time": "1 - 2" + } + }, + "node_modules/d3-time-format/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-time-format/node_modules/d3-time": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz", + "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==", + "dependencies": { + "d3-array": "2" + } + }, + "node_modules/d3-time-format/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, "node_modules/dargs": { "version": "7.0.0", "dev": true, @@ -12221,7 +12487,7 @@ }, "node_modules/fill-range": { "version": "7.0.1", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -12723,7 +12989,7 @@ }, "node_modules/glob-parent": { "version": "5.1.2", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -14995,6 +15261,14 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, "node_modules/interpret": { "version": "1.1.0", "dev": true, @@ -15086,7 +15360,7 @@ }, "node_modules/is-binary-path": { "version": "2.1.0", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -15240,7 +15514,7 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -15255,7 +15529,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -15322,7 +15596,7 @@ }, "node_modules/is-number": { "version": "7.0.0", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -18331,7 +18605,7 @@ }, "node_modules/normalize-path": { "version": "3.0.0", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -18345,6 +18619,162 @@ "node": ">=0.10.0" } }, + "node_modules/npm": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.4.0.tgz", + "integrity": "sha512-RS7Mx0OVfXlOcQLRePuDIYdFCVBPCNapWHplDK+mh7GDdP/Tvor4ocuybRRPSvfcRb2vjRJt1fHCqw3cr8qACQ==", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/promise-spawn", + "@npmcli/run-script", + "@sigstore/tuf", + "abbrev", + "archy", + "cacache", + "chalk", + "ci-info", + "cli-columns", + "cli-table3", + "columnify", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "ms", + "node-gyp", + "nopt", + "normalize-package-data", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "npmlog", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "semver", + "spdx-expression-parse", + "ssri", + "supports-color", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^7.2.1", + "@npmcli/config": "^8.0.2", + "@npmcli/fs": "^3.1.0", + "@npmcli/map-workspaces": "^3.0.4", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.1", + "@npmcli/run-script": "^7.0.4", + "@sigstore/tuf": "^2.3.0", + "abbrev": "^2.0.0", + "archy": "~1.0.0", + "cacache": "^18.0.2", + "chalk": "^5.3.0", + "ci-info": "^4.0.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.3", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.3", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^7.0.1", + "ini": "^4.1.1", + "init-package-json": "^6.0.0", + "is-cidr": "^5.0.3", + "json-parse-even-better-errors": "^3.0.1", + "libnpmaccess": "^8.0.1", + "libnpmdiff": "^6.0.3", + "libnpmexec": "^7.0.4", + "libnpmfund": "^5.0.1", + "libnpmhook": "^10.0.0", + "libnpmorg": "^6.0.1", + "libnpmpack": "^6.0.3", + "libnpmpublish": "^9.0.2", + "libnpmsearch": "^7.0.0", + "libnpmteam": "^6.0.0", + "libnpmversion": "^5.0.1", + "make-fetch-happen": "^13.0.0", + "minimatch": "^9.0.3", + "minipass": "^7.0.4", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^10.0.1", + "nopt": "^7.2.0", + "normalize-package-data": "^6.0.0", + "npm-audit-report": "^5.0.0", + "npm-install-checks": "^6.3.0", + "npm-package-arg": "^11.0.1", + "npm-pick-manifest": "^9.0.0", + "npm-profile": "^9.0.0", + "npm-registry-fetch": "^16.1.0", + "npm-user-validate": "^2.0.0", + "npmlog": "^7.0.1", + "p-map": "^4.0.0", + "pacote": "^17.0.6", + "parse-conflict-json": "^3.0.1", + "proc-log": "^3.0.0", + "qrcode-terminal": "^0.12.0", + "read": "^2.1.0", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1", + "ssri": "^10.0.5", + "supports-color": "^9.4.0", + "tar": "^6.2.0", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^5.0.0", + "which": "^4.0.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/npm-bundled": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", @@ -18547,631 +18977,653 @@ "node": ">=8" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, + "node_modules/npm/node_modules/@colors/colors": { + "version": "1.5.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "boolbase": "^1.0.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "engines": { + "node": ">=12" } }, - "node_modules/num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==", - "dev": true - }, - "node_modules/number-is-nan": { - "version": "1.0.1", + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "inBundle": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/nvd3": { - "version": "1.8.6", - "license": "Apache-2.0", - "peerDependencies": { - "d3": "^3.4.4" - } + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "inBundle": true, + "license": "MIT" }, - "node_modules/nx": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/nx/-/nx-17.0.3.tgz", - "integrity": "sha512-VShJISKCYt3iVJoMUPZiv67+0tiItxWMnfVmTmPZPio2Fu+wGc9U4ijjPxcmp2RJmLRaxkB9cn5rlrAvkIrNMA==", - "dev": true, - "hasInstallScript": true, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT", "dependencies": { - "@nrwl/tao": "17.0.3", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.6", - "axios": "^1.5.1", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.3.1", - "dotenv-expand": "~10.0.0", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "fs-extra": "^11.1.0", - "glob": "7.1.4", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "js-yaml": "4.1.0", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "3.0.5", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "semver": "7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "v8-compile-cache": "2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "17.0.3", - "@nx/nx-darwin-x64": "17.0.3", - "@nx/nx-freebsd-x64": "17.0.3", - "@nx/nx-linux-arm-gnueabihf": "17.0.3", - "@nx/nx-linux-arm64-gnu": "17.0.3", - "@nx/nx-linux-arm64-musl": "17.0.3", - "@nx/nx-linux-x64-gnu": "17.0.3", - "@nx/nx-linux-x64-musl": "17.0.3", - "@nx/nx-win32-arm64-msvc": "17.0.3", - "@nx/nx-win32-x64-msvc": "17.0.3" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, - "peerDependencies": { - "@swc-node/register": "^1.6.7", - "@swc/core": "^1.3.85" + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nx/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "inBundle": true, + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/nx/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "node_modules/npm/node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "inBundle": true, + "license": "ISC" }, - "node_modules/nx/node_modules/axios": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", - "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/agent": { + "version": "2.2.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/arborist": { + "version": "7.3.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^3.1.0", + "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/metavuln-calculator": "^7.0.0", + "@npmcli/name-from-folder": "^2.0.0", + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/query": "^3.0.1", + "@npmcli/run-script": "^7.0.2", + "bin-links": "^4.0.1", + "cacache": "^18.0.0", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^7.0.1", + "json-parse-even-better-errors": "^3.0.0", + "json-stringify-nice": "^1.1.4", + "minimatch": "^9.0.0", + "nopt": "^7.0.0", + "npm-install-checks": "^6.2.0", + "npm-package-arg": "^11.0.1", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "npmlog": "^7.0.1", + "pacote": "^17.0.4", + "parse-conflict-json": "^3.0.0", + "proc-log": "^3.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^10.0.5", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" }, - "engines": { - "node": ">=10" + "bin": { + "arborist": "bin/index.js" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true, - "engines": { - "node": ">=6" + "node_modules/npm/node_modules/@npmcli/config": { + "version": "8.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^4.0.0", + "ini": "^4.1.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/disparity-colors": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "color-name": "~1.1.4" + "ansi-styles": "^4.3.0" }, "engines": { - "node": ">=7.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/nx/node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, + "license": "MIT", "dependencies": { - "escape-string-regexp": "^1.0.5" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/nx/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/fs": { + "version": "3.1.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "semver": "^7.3.5" }, "engines": { - "node": ">= 6" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/git": { + "version": "5.0.4", + "inBundle": true, + "license": "ISC", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@npmcli/promise-spawn": "^7.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" }, "engines": { - "node": ">=14.14" - } - }, - "node_modules/nx/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "argparse": "^2.0.1" + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" }, "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/nx/node_modules/lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true, + "installed-package-contents": "lib/index.js" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/map-workspaces": { + "version": "3.0.4", + "inBundle": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" }, "engines": { - "node": "*" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { + "version": "7.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "has-flag": "^4.0.0" + "cacache": "^18.0.0", + "json-parse-even-better-errors": "^3.0.0", + "pacote": "^17.0.0", + "semver": "^7.3.5" }, "engines": { - "node": ">=8" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", "engines": { - "node": ">=6" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" + "node_modules/npm/node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "dev": true, - "license": "Apache-2.0", + "node_modules/npm/node_modules/@npmcli/package-json": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + }, "engines": { - "node": "*" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/@npmcli/promise-spawn": { + "version": "7.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object-copy": { - "version": "0.1.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/@npmcli/query": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "postcss-selector-parser": "^6.0.10" }, "engines": { - "node": ">=0.10.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/@npmcli/run-script": { + "version": "7.0.4", + "inBundle": true, + "license": "ISC", "dependencies": { - "is-buffer": "^1.1.5" + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", + "which": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object-hash": { - "version": "3.0.0", - "dev": true, + "node_modules/npm/node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "inBundle": true, "license": "MIT", + "optional": true, "engines": { - "node": ">= 6" + "node": ">=14" } }, - "node_modules/object-inspect": { - "version": "1.12.3", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/npm/node_modules/@sigstore/bundle": { + "version": "2.1.1", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/@sigstore/core": { + "version": "0.2.0", + "inBundle": true, + "license": "Apache-2.0", "engines": { - "node": ">= 0.4" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object-visit": { - "version": "1.0.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/@sigstore/protobuf-specs": { + "version": "0.2.1", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/sign": { + "version": "2.2.1", + "inBundle": true, + "license": "Apache-2.0", "dependencies": { - "isobject": "^3.0.0" + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", + "@sigstore/protobuf-specs": "^0.2.1", + "make-fetch-happen": "^13.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object.assign": { - "version": "4.1.4", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/@sigstore/tuf": { + "version": "2.3.0", + "inBundle": true, + "license": "Apache-2.0", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "@sigstore/protobuf-specs": "^0.2.1", + "tuf-js": "^2.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object.defaults": { - "version": "1.1.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/@sigstore/verify": { + "version": "0.1.0", + "inBundle": true, + "license": "Apache-2.0", "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", + "@sigstore/protobuf-specs": "^0.2.1" }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object.map": { - "version": "1.0.1", - "dev": true, + "node_modules/npm/node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/models": { + "version": "2.0.0", + "inBundle": true, "license": "MIT", "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.3" }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object.pick": { - "version": "1.3.0", - "dev": true, + "node_modules/npm/node_modules/abbrev": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/agent-base": { + "version": "7.1.0", + "inBundle": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "debug": "^4.3.4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 14" } }, - "node_modules/object.values": { - "version": "1.1.6", - "dev": true, + "node_modules/npm/node_modules/aggregate-error": { + "version": "3.1.0", + "inBundle": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-styles": { + "version": "6.2.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true + "node_modules/npm/node_modules/aproba": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" }, - "node_modules/on-finished": { - "version": "2.3.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/archy": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/are-we-there-yet": { + "version": "4.0.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/balanced-match": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/bin-links": { + "version": "4.0.3", + "inBundle": true, + "license": "ISC", "dependencies": { - "ee-first": "1.1.1" + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" }, "engines": { - "node": ">= 0.8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/on-headers": { - "version": "1.0.2", - "dev": true, + "node_modules/npm/node_modules/binary-extensions": { + "version": "2.2.0", + "inBundle": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/once": { - "version": "1.4.0", - "dev": true, - "license": "ISC", + "node_modules/npm/node_modules/brace-expansion": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", "dependencies": { - "wrappy": "1" + "balanced-match": "^1.0.0" } }, - "node_modules/onetime": { - "version": "5.1.2", + "node_modules/npm/node_modules/builtins": { + "version": "5.0.1", + "inBundle": true, "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "semver": "^7.0.0" } }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "node_modules/npm/node_modules/cacache": { + "version": "18.0.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/openurl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", - "integrity": "sha512-d/gTkTb1i1GKz5k3XE3XFV/PxQ1k45zDqGP2OA7YhgsaLoqm6qRvARAZOFer1fcXritWlGBRCu/UgeS4HAnXAA==", - "dev": true - }, - "node_modules/opn": { + "node_modules/npm/node_modules/chalk": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", - "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", - "dev": true, - "dependencies": { - "is-wsl": "^1.1.0" + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm/node_modules/chownr": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/opn/node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", - "dev": true, + "node_modules/npm/node_modules/ci-info": { + "version": "4.0.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "inBundle": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/optimist": { - "version": "0.6.1", - "dev": true, - "license": "MIT/X11", + "node_modules/npm/node_modules/cidr-regex": { + "version": "4.0.3", + "inBundle": true, + "license": "BSD-2-Clause", "dependencies": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "ip-regex": "^5.0.0" + }, + "engines": { + "node": ">=14" } }, - "node_modules/optimist/node_modules/minimist": { - "version": "0.0.10", - "dev": true, - "license": "MIT" - }, - "node_modules/optimist/node_modules/wordwrap": { - "version": "0.0.3", - "dev": true, + "node_modules/npm/node_modules/clean-stack": { + "version": "2.2.0", + "inBundle": true, "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">=6" } }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, + "node_modules/npm/node_modules/cli-columns": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 10" } }, - "node_modules/ora": { - "version": "5.4.1", + "node_modules/npm/node_modules/cli-table3": { + "version": "0.6.3", + "inBundle": true, "license": "MIT", "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "string-width": "^4.2.0" }, "engines": { - "node": ">=10" + "node": "10.* || >= 12.*" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "@colors/colors": "1.5.0" } }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/npm/node_modules/clone": { + "version": "1.0.4", + "inBundle": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=0.8" } }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "node_modules/npm/node_modules/cmd-shim": { + "version": "6.0.2", + "inBundle": true, + "license": "ISC", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/ora/node_modules/color-convert": { + "node_modules/npm/node_modules/color-convert": { "version": "2.0.1", + "inBundle": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -19180,1149 +19632,1150 @@ "node": ">=7.0.0" } }, - "node_modules/ora/node_modules/color-name": { + "node_modules/npm/node_modules/color-name": { "version": "1.1.4", + "inBundle": true, "license": "MIT" }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" + "node_modules/npm/node_modules/color-support": { + "version": "1.1.3", + "inBundle": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" } }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/npm/node_modules/columnify": { + "version": "1.6.0", + "inBundle": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "node_modules/ordered-ast-traverse": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ordered-esprima-props": "~1.1.0" - } + "node_modules/npm/node_modules/common-ancestor-path": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC" }, - "node_modules/ordered-esprima-props": { + "node_modules/npm/node_modules/console-control-strings": { "version": "1.1.0", - "dev": true, - "license": "MIT" + "inBundle": true, + "license": "ISC" }, - "node_modules/os-homedir": { - "version": "1.0.2", - "dev": true, + "node_modules/npm/node_modules/cross-spawn": { + "version": "7.0.3", + "inBundle": true, "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/os-locale": { - "version": "1.4.0", - "license": "MIT", + "node_modules/npm/node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "lcid": "^1.0.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", + "node_modules/npm/node_modules/cssesc": { + "version": "3.0.0", + "inBundle": true, "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "dev": true, - "license": "ISC", - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "node": ">=4" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "dev": true, + "node_modules/npm/node_modules/debug": { + "version": "4.3.4", + "inBundle": true, "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "ms": "2.1.2" }, "engines": { - "node": ">=10" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/p-locate": { - "version": "5.0.0", - "dev": true, + "node_modules/npm/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/defaults": { + "version": "1.0.4", + "inBundle": true, "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" + "clone": "^1.0.2" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dependencies": { - "aggregate-error": "^3.0.0" - }, + "node_modules/npm/node_modules/diff": { + "version": "5.1.0", + "inBundle": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.3.1" } }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, + "node_modules/npm/node_modules/eastasianwidth": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/emoji-regex": { + "version": "8.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/encoding": { + "version": "0.1.13", + "inBundle": true, + "license": "MIT", + "optional": true, "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" + "iconv-lite": "^0.6.2" } }, - "node_modules/p-retry/node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, + "node_modules/npm/node_modules/env-paths": { + "version": "2.2.1", + "inBundle": true, + "license": "MIT", "engines": { - "node": ">= 4" + "node": ">=6" } }, - "node_modules/p-try": { - "version": "2.2.0", - "dev": true, + "node_modules/npm/node_modules/err-code": { + "version": "2.0.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/exponential-backoff": { + "version": "3.1.1", + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/npm/node_modules/fastest-levenshtein": { + "version": "1.0.16", + "inBundle": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 4.9.1" } }, - "node_modules/pacote": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-17.0.4.tgz", - "integrity": "sha512-eGdLHrV/g5b5MtD5cTPyss+JxOlaOloSMG3UwPMAvL8ywaLJ6beONPF40K4KKl/UI6q5hTKCJq5rCu8tkF+7Dg==", + "node_modules/npm/node_modules/foreground-child": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "@npmcli/git": "^5.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/promise-spawn": "^7.0.0", - "@npmcli/run-script": "^7.0.0", - "cacache": "^18.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^11.0.0", - "npm-packlist": "^8.0.0", - "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^16.0.0", - "proc-log": "^3.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^7.0.0", - "read-package-json-fast": "^3.0.0", - "sigstore": "^2.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "lib/bin.js" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "node_modules/param-case": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^2.2.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/fs-minipass": { + "version": "3.0.3", + "inBundle": true, + "license": "ISC", "dependencies": { - "callsites": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">=6" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "dev": true, + "node_modules/npm/node_modules/function-bind": { + "version": "1.1.2", + "inBundle": true, "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/gauge": { + "version": "5.0.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^4.0.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" }, "engines": { - "node": ">=0.8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/glob": { + "version": "10.3.10", + "inBundle": true, + "license": "ISC", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } + "node_modules/npm/node_modules/graceful-fs": { + "version": "4.2.11", + "inBundle": true, + "license": "ISC" }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "node_modules/npm/node_modules/has-unicode": { + "version": "2.0.1", + "inBundle": true, + "license": "ISC" }, - "node_modules/parse5": { - "version": "7.1.2", - "devOptional": true, + "node_modules/npm/node_modules/hasown": { + "version": "2.0.0", + "inBundle": true, "license": "MIT", "dependencies": { - "entities": "^4.4.0" + "function-bind": "^1.1.2" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": ">= 0.4" } }, - "node_modules/parse5-html-rewriting-stream": { - "version": "7.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/hosted-git-info": { + "version": "7.0.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "entities": "^4.3.0", - "parse5": "^7.0.0", - "parse5-sax-parser": "^7.0.0" + "lru-cache": "^10.0.1" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/parse5-sax-parser": { + "node_modules/npm/node_modules/http-cache-semantics": { + "version": "4.1.1", + "inBundle": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/http-proxy-agent": { "version": "7.0.0", - "dev": true, + "inBundle": true, "license": "MIT", "dependencies": { - "parse5": "^7.0.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": ">= 14" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "dev": true, + "node_modules/npm/node_modules/https-proxy-agent": { + "version": "7.0.2", + "inBundle": true, "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, "engines": { - "node": ">= 0.8" + "node": ">= 14" } }, - "node_modules/pascalcase": { - "version": "0.1.1", - "dev": true, + "node_modules/npm/node_modules/iconv-lite": { + "version": "0.6.3", + "inBundle": true, "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/path-dirname": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/ignore-walk": { + "version": "6.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minimatch": "^9.0.0" + }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, + "node_modules/npm/node_modules/imurmurhash": { + "version": "0.1.4", + "inBundle": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.8.19" } }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "dev": true, - "license": "(WTFPL OR MIT)" - }, - "node_modules/path-key": { - "version": "3.1.1", + "node_modules/npm/node_modules/indent-string": { + "version": "4.0.0", + "inBundle": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "license": "MIT" + "node_modules/npm/node_modules/ini": { + "version": "4.1.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, - "node_modules/path-root": { - "version": "0.1.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/init-package-json": { + "version": "6.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "path-root-regex": "^0.1.0" + "npm-package-arg": "^11.0.0", + "promzard": "^1.0.0", + "read": "^2.0.0", + "read-package-json": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^5.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "dev": true, + "node_modules/npm/node_modules/ip": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/ip-regex": { + "version": "5.0.0", + "inBundle": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "node_modules/npm/node_modules/is-cidr": { + "version": "5.0.3", + "inBundle": true, + "license": "BSD-2-Clause", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "cidr-regex": "4.0.3" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=14" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", - "engines": { - "node": "14 || >=16.14" + "node_modules/npm/node_modules/is-core-module": { + "version": "2.13.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "dev": true, + "node_modules/npm/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "inBundle": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/pdfjs-dist": { - "version": "2.16.105", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz", - "integrity": "sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==", - "dependencies": { - "dommatrix": "^1.0.3", - "web-streams-polyfill": "^3.2.1" - }, - "peerDependencies": { - "worker-loader": "^3.0.8" - }, - "peerDependenciesMeta": { - "worker-loader": { - "optional": true - } - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "dev": true, + "node_modules/npm/node_modules/is-lambda": { + "version": "1.0.1", + "inBundle": true, "license": "MIT" }, - "node_modules/picocolors": { - "version": "1.0.0", - "dev": true, + "node_modules/npm/node_modules/isexe": { + "version": "2.0.0", + "inBundle": true, "license": "ISC" }, - "node_modules/picomatch": { - "version": "2.3.1", - "devOptional": true, - "license": "MIT", + "node_modules/npm/node_modules/jackspeak": { + "version": "2.3.6", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, "engines": { - "node": ">=8.6" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.3.1", - "dev": true, - "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" + "url": "https://github.com/sponsors/isaacs" }, - "engines": { - "node": ">=0.10" + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/pify": { - "version": "2.3.0", - "dev": true, + "node_modules/npm/node_modules/json-parse-even-better-errors": { + "version": "3.0.1", + "inBundle": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pinkie": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node_modules/npm/node_modules/json-stringify-nice": { + "version": "1.1.4", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/npm/node_modules/jsonparse": { + "version": "1.3.1", + "engines": [ + "node >= 0.2.0" + ], + "inBundle": true, + "license": "MIT" }, - "node_modules/pirates": { - "version": "4.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } + "node_modules/npm/node_modules/just-diff": { + "version": "6.0.2", + "inBundle": true, + "license": "MIT" }, - "node_modules/piscina": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.1.0.tgz", - "integrity": "sha512-sjbLMi3sokkie+qmtZpkfMCUJTpbxJm/wvaPzU28vmYSsTSW8xk9JcFUsbqGJdtPpIQ9tuj+iDcTtgZjwnOSig==", - "dev": true, + "node_modules/npm/node_modules/just-diff-apply": { + "version": "5.5.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/libnpmaccess": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "eventemitter-asyncresource": "^1.0.0", - "hdr-histogram-js": "^2.0.1", - "hdr-histogram-percentiles-obj": "^3.0.0" + "npm-package-arg": "^11.0.1", + "npm-registry-fetch": "^16.0.0" }, - "optionalDependencies": { - "nice-napi": "^1.0.2" + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", - "dev": true, + "node_modules/npm/node_modules/libnpmdiff": { + "version": "6.0.6", + "inBundle": true, + "license": "ISC", "dependencies": { - "find-up": "^6.3.0" + "@npmcli/arborist": "^7.2.1", + "@npmcli/disparity-colors": "^3.0.0", + "@npmcli/installed-package-contents": "^2.0.2", + "binary-extensions": "^2.2.0", + "diff": "^5.1.0", + "minimatch": "^9.0.0", + "npm-package-arg": "^11.0.1", + "pacote": "^17.0.4", + "tar": "^6.2.0" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, + "node_modules/npm/node_modules/libnpmexec": { + "version": "7.0.7", + "inBundle": true, + "license": "ISC", "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" + "@npmcli/arborist": "^7.2.1", + "@npmcli/run-script": "^7.0.2", + "ci-info": "^4.0.0", + "npm-package-arg": "^11.0.1", + "npmlog": "^7.0.1", + "pacote": "^17.0.4", + "proc-log": "^3.0.0", + "read": "^2.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, + "node_modules/npm/node_modules/libnpmfund": { + "version": "5.0.4", + "inBundle": true, + "license": "ISC", "dependencies": { - "p-locate": "^6.0.0" + "@npmcli/arborist": "^7.2.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, + "node_modules/npm/node_modules/libnpmhook": { + "version": "10.0.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "yocto-queue": "^1.0.0" + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, + "node_modules/npm/node_modules/libnpmorg": { + "version": "6.0.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "p-limit": "^4.0.0" + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, + "node_modules/npm/node_modules/libnpmpack": { + "version": "6.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.2.1", + "@npmcli/run-script": "^7.0.2", + "npm-package-arg": "^11.0.1", + "pacote": "^17.0.4" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-dir/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true, - "engines": { - "node": ">=12.20" + "node_modules/npm/node_modules/libnpmpublish": { + "version": "9.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "ci-info": "^4.0.0", + "normalize-package-data": "^6.0.0", + "npm-package-arg": "^11.0.1", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.7", + "sigstore": "^2.2.0", + "ssri": "^10.0.5" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-up": { - "version": "3.1.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/libnpmsearch": { + "version": "7.0.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "find-up": "^3.0.0" + "npm-registry-fetch": "^16.0.0" }, "engines": { - "node": ">=8" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/libnpmteam": { + "version": "6.0.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "locate-path": "^3.0.0" + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.0.0" }, "engines": { - "node": ">=6" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/libnpmversion": { + "version": "5.0.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "@npmcli/git": "^5.0.3", + "@npmcli/run-script": "^7.0.2", + "json-parse-even-better-errors": "^3.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.7" }, "engines": { - "node": ">=6" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, + "node_modules/npm/node_modules/lru-cache": { + "version": "10.1.0", + "inBundle": true, + "license": "ISC", "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "14 || >=16.14" } }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/make-fetch-happen": { + "version": "13.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "p-limit": "^2.0.0" + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" }, "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/portscanner": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", - "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", - "dev": true, + "node_modules/npm/node_modules/minimatch": { + "version": "9.0.3", + "inBundle": true, + "license": "ISC", "dependencies": { - "async": "^2.6.0", - "is-number-like": "^1.0.3" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=0.4", - "npm": ">=1.0.0" - } - }, - "node_modules/portscanner/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/minipass": { + "version": "7.0.4", + "inBundle": true, + "license": "ISC", "engines": { - "node": ">=0.10.0" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/npm/node_modules/minipass-collect": { + "version": "2.0.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "minipass": "^7.0.3" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/postcss-import": { - "version": "15.1.0", - "dev": true, + "node_modules/npm/node_modules/minipass-fetch": { + "version": "3.0.4", + "inBundle": true, "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" }, "engines": { - "node": ">=14.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" }, - "peerDependencies": { - "postcss": "^8.0.0" + "optionalDependencies": { + "encoding": "^0.1.13" } }, - "node_modules/postcss-js": { - "version": "4.0.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/minipass-flush": { + "version": "1.0.5", + "inBundle": true, + "license": "ISC", "dependencies": { - "camelcase-css": "^2.0.1" + "minipass": "^3.0.0" }, "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" + "node": ">= 8" } }, - "node_modules/postcss-load-config": { - "version": "4.0.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } + "node": ">=8" } }, - "node_modules/postcss-load-config/node_modules/yaml": { - "version": "2.2.2", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 14" + "node_modules/npm/node_modules/minipass-json-stream": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" } }, - "node_modules/postcss-loader": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", - "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", - "dev": true, + "node_modules/npm/node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", "dependencies": { - "cosmiconfig": "^8.2.0", - "jiti": "^1.18.2", - "semver": "^7.3.8" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" + "node": ">=8" } }, - "node_modules/postcss-loader/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/postcss-loader/node_modules/cosmiconfig": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", - "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", - "dev": true, + "node_modules/npm/node_modules/minipass-pipeline": { + "version": "1.2.4", + "inBundle": true, + "license": "ISC", "dependencies": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" + "minipass": "^3.0.0" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" + "node": ">=8" } }, - "node_modules/postcss-loader/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, + "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", "dependencies": { - "argparse": "^2.0.1" + "yallist": "^4.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=8" } }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" + "node_modules/npm/node_modules/minipass-sized": { + "version": "1.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" }, - "peerDependencies": { - "postcss": "^8.1.0" + "engines": { + "node": ">=8" } }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", - "dev": true, + "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" + "yallist": "^4.0.0" }, "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=8" } }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, + "node_modules/npm/node_modules/minizlib": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.4" + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">= 8" } }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, + "node_modules/npm/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", "dependencies": { - "icss-utils": "^5.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=8" } }, - "node_modules/postcss-nested": { - "version": "6.0.1", - "dev": true, + "node_modules/npm/node_modules/mkdirp": { + "version": "1.0.4", + "inBundle": true, "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.0.11" + "bin": { + "mkdirp": "bin/cmd.js" }, "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" + "node": ">=10" } }, - "node_modules/postcss-scss": { - "version": "0.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss": "^5.1.0" + "node_modules/npm/node_modules/ms": { + "version": "2.1.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/mute-stream": { + "version": "1.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/postcss-scss/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, + "node_modules/npm/node_modules/negotiator": { + "version": "0.6.3", + "inBundle": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/postcss-scss/node_modules/ansi-styles": { - "version": "2.2.1", - "dev": true, + "node_modules/npm/node_modules/node-gyp": { + "version": "10.0.1", + "inBundle": true, "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/postcss-scss/node_modules/chalk": { - "version": "1.1.3", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/nopt": { + "version": "7.2.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" }, "engines": { - "node": ">=0.10.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/postcss-scss/node_modules/chalk/node_modules/supports-color": { - "version": "2.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/normalize-package-data": { + "version": "6.0.0", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, "engines": { - "node": ">=0.8.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/postcss-scss/node_modules/has-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/npm-audit-report": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", "engines": { - "node": ">=0.10.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/postcss-scss/node_modules/postcss": { - "version": "5.2.18", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/npm-bundled": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "npm-normalize-package-bin": "^3.0.0" }, "engines": { - "node": ">=0.12" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/postcss-scss/node_modules/source-map": { - "version": "0.5.7", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/npm/node_modules/npm-install-checks": { + "version": "6.3.0", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/postcss-scss/node_modules/strip-ansi": { + "node_modules/npm/node_modules/npm-normalize-package-bin": { "version": "3.0.1", - "dev": true, - "license": "MIT", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-package-arg": { + "version": "11.0.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "ansi-regex": "^2.0.0" + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/postcss-scss/node_modules/supports-color": { - "version": "3.2.3", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/npm-packlist": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "has-flag": "^1.0.0" + "ignore-walk": "^6.0.4" }, "engines": { - "node": ">=0.8.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/postcss-selector-parser": { - "version": "6.0.11", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/npm-pick-manifest": { + "version": "9.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" }, "engines": { - "node": ">=4" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, + "node_modules/npm/node_modules/npm-profile": { + "version": "9.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0" + }, "engines": { - "node": ">= 0.8.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/preprocess": { - "version": "3.2.0", - "dev": true, + "node_modules/npm/node_modules/npm-registry-fetch": { + "version": "16.1.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "xregexp": "3.1.0" + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^3.0.0" }, "engines": { - "node": ">= 0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/prettier": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", - "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, + "node_modules/npm/node_modules/npm-user-validate": { + "version": "2.0.0", + "inBundle": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/npmlog": { + "version": "7.0.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "fast-diff": "^1.1.2" + "are-we-there-yet": "^4.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^5.0.0", + "set-blocking": "^2.0.0" }, "engines": { - "node": ">=6.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, + "node_modules/npm/node_modules/p-map": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, + "node_modules/npm/node_modules/pacote": { + "version": "17.0.6", + "inBundle": true, + "license": "ISC", "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^7.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^7.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^2.2.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, + "node_modules/npm/node_modules/parse-conflict-json": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, "engines": { - "node": ">=10" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/path-key": { + "version": "3.1.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/path-scurry": { + "version": "1.10.1", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/proc-log": { + "node_modules/npm/node_modules/postcss-selector-parser": { + "version": "6.0.15", + "inBundle": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/proc-log": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "inBundle": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "dev": true, - "license": "MIT" + "node_modules/npm/node_modules/promise-all-reject-late": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/promise": { - "version": "7.3.1", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "asap": "~2.0.3" + "node_modules/npm/node_modules/promise-call-limit": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/promise-inflight": { + "node_modules/npm/node_modules/promise-inflight": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" + "inBundle": true, + "license": "ISC" }, - "node_modules/promise-retry": { + "node_modules/npm/node_modules/promise-retry": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "inBundle": true, + "license": "MIT", "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -20331,260 +20784,275 @@ "node": ">=10" } }, - "node_modules/protractor": { - "version": "7.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/promzard": { + "version": "1.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "@types/q": "^0.0.32", - "@types/selenium-webdriver": "^3.0.0", - "blocking-proxy": "^1.0.0", - "browserstack": "^1.5.1", - "chalk": "^1.1.3", - "glob": "^7.0.3", - "jasmine": "2.8.0", - "jasminewd2": "^2.1.0", - "q": "1.4.1", - "saucelabs": "^1.5.0", - "selenium-webdriver": "3.6.0", - "source-map-support": "~0.4.0", - "webdriver-js-extender": "2.1.0", - "webdriver-manager": "^12.1.7", - "yargs": "^15.3.1" - }, - "bin": { - "protractor": "bin/protractor", - "webdriver-manager": "bin/webdriver-manager" + "read": "^2.0.0" }, "engines": { - "node": ">=10.13.x" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/protractor/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/qrcode-terminal": { + "version": "0.12.0", + "inBundle": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/npm/node_modules/read": { + "version": "2.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/protractor/node_modules/ansi-styles": { - "version": "2.2.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/read-cmd-shim": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", "engines": { - "node": ">=0.10.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/protractor/node_modules/chalk": { - "version": "1.1.3", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/read-package-json": { + "version": "7.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/protractor/node_modules/cliui": { - "version": "6.0.0", - "dev": true, + "node_modules/npm/node_modules/read-package-json-fast": { + "version": "3.0.2", + "inBundle": true, "license": "ISC", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/protractor/node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, + "node_modules/npm/node_modules/retry": { + "version": "0.12.0", + "inBundle": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/protractor/node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, + "node_modules/npm/node_modules/safer-buffer": { + "version": "2.1.2", + "inBundle": true, "license": "MIT", + "optional": true + }, + "node_modules/npm/node_modules/semver": { + "version": "7.5.4", + "inBundle": true, + "license": "ISC", "dependencies": { - "ansi-regex": "^5.0.1" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/protractor/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "color-name": "~1.1.4" + "yallist": "^4.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" } }, - "node_modules/protractor/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" + "node_modules/npm/node_modules/set-blocking": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" }, - "node_modules/protractor/node_modules/find-up": { - "version": "4.1.0", - "dev": true, + "node_modules/npm/node_modules/shebang-command": { + "version": "2.0.0", + "inBundle": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/protractor/node_modules/glob": { - "version": "7.2.3", - "dev": true, + "node_modules/npm/node_modules/shebang-regex": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/signal-exit": { + "version": "4.1.0", + "inBundle": true, "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, "engines": { - "node": "*" + "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/protractor/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/sigstore": { + "version": "2.2.0", + "inBundle": true, + "license": "Apache-2.0", "dependencies": { - "p-locate": "^4.1.0" + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", + "@sigstore/protobuf-specs": "^0.2.1", + "@sigstore/sign": "^2.2.1", + "@sigstore/tuf": "^2.3.0", + "@sigstore/verify": "^0.1.0" }, "engines": { - "node": ">=8" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/protractor/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, + "node_modules/npm/node_modules/smart-buffer": { + "version": "4.2.0", + "inBundle": true, "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/protractor/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, + "node_modules/npm/node_modules/socks": { + "version": "2.7.1", + "inBundle": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" }, "engines": { - "node": ">=8" + "node": ">= 10.13.0", + "npm": ">= 3.0.0" } }, - "node_modules/protractor/node_modules/q": { - "version": "1.4.1", - "dev": true, + "node_modules/npm/node_modules/socks-proxy-agent": { + "version": "8.0.2", + "inBundle": true, "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/protractor/node_modules/source-map": { - "version": "0.5.7", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" + "node": ">= 14" } }, - "node_modules/protractor/node_modules/source-map-support": { - "version": "0.4.18", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/spdx-correct": { + "version": "3.2.0", + "inBundle": true, + "license": "Apache-2.0", "dependencies": { - "source-map": "^0.5.6" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/protractor/node_modules/strip-ansi": { + "node_modules/npm/node_modules/spdx-exceptions": { + "version": "2.3.0", + "inBundle": true, + "license": "CC-BY-3.0" + }, + "node_modules/npm/node_modules/spdx-expression-parse": { "version": "3.0.1", - "dev": true, + "inBundle": true, "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/protractor/node_modules/supports-color": { - "version": "2.0.0", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/spdx-license-ids": { + "version": "3.0.16", + "inBundle": true, + "license": "CC0-1.0" + }, + "node_modules/npm/node_modules/ssri": { + "version": "10.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, "engines": { - "node": ">=0.8.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/protractor/node_modules/wrap-ansi": { - "version": "6.2.0", - "dev": true, + "node_modules/npm/node_modules/string-width": { + "version": "4.2.3", + "inBundle": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/protractor/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, + "node_modules/npm/node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "inBundle": true, "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { "node": ">=8" } }, - "node_modules/protractor/node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, + "node_modules/npm/node_modules/strip-ansi": { + "version": "6.0.1", + "inBundle": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/protractor/node_modules/wrap-ansi/node_modules/strip-ansi": { + "node_modules/npm/node_modules/strip-ansi-cjs": { + "name": "strip-ansi", "version": "6.0.1", - "dev": true, + "inBundle": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -20593,2403 +21061,2160 @@ "node": ">=8" } }, - "node_modules/protractor/node_modules/y18n": { - "version": "4.0.3", - "dev": true, - "license": "ISC" - }, - "node_modules/protractor/node_modules/yargs": { - "version": "15.4.1", - "dev": true, + "node_modules/npm/node_modules/supports-color": { + "version": "9.4.0", + "inBundle": true, "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/npm/node_modules/tar": { + "version": "6.2.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/protractor/node_modules/yargs-parser": { - "version": "18.1.3", - "dev": true, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "inBundle": true, "license": "ISC", "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "minipass": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">= 8" } }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, + "node_modules/npm/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "node_modules/prr": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "optional": true + "node_modules/npm/node_modules/text-table": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT" }, - "node_modules/psl": { - "version": "1.9.0", - "dev": true, + "node_modules/npm/node_modules/tiny-relative-date": { + "version": "1.3.0", + "inBundle": true, "license": "MIT" }, - "node_modules/pug": { - "version": "2.0.4", - "dev": true, + "node_modules/npm/node_modules/treeverse": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/tuf-js": { + "version": "2.2.0", + "inBundle": true, "license": "MIT", - "optional": true, "dependencies": { - "pug-code-gen": "^2.0.2", - "pug-filters": "^3.1.1", - "pug-lexer": "^4.1.0", - "pug-linker": "^3.0.6", - "pug-load": "^2.0.12", - "pug-parser": "^5.0.1", - "pug-runtime": "^2.0.5", - "pug-strip-comments": "^1.0.4" + "@tufjs/models": "2.0.0", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pug-attrs": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/npm/node_modules/unique-filename": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "constantinople": "^3.0.1", - "js-stringify": "^1.0.1", - "pug-runtime": "^2.0.5" + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pug-code-gen": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/npm/node_modules/unique-slug": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "constantinople": "^3.1.2", - "doctypes": "^1.1.0", - "js-stringify": "^1.0.1", - "pug-attrs": "^2.0.4", - "pug-error": "^1.3.3", - "pug-runtime": "^2.0.5", - "void-elements": "^2.0.1", - "with": "^5.0.0" + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pug-error": { - "version": "1.3.3", - "dev": true, - "license": "MIT", - "optional": true + "node_modules/npm/node_modules/util-deprecate": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" }, - "node_modules/pug-filters": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/npm/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "inBundle": true, + "license": "Apache-2.0", "dependencies": { - "clean-css": "^4.1.11", - "constantinople": "^3.0.1", - "jstransformer": "1.0.0", - "pug-error": "^1.3.3", - "pug-walk": "^1.1.8", - "resolve": "^1.1.6", - "uglify-js": "^2.6.1" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/pug-lexer": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/npm/node_modules/validate-npm-package-name": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "character-parser": "^2.1.1", - "is-expression": "^3.0.0", - "pug-error": "^1.3.3" + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pug-linker": { - "version": "3.0.6", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "pug-error": "^1.3.3", - "pug-walk": "^1.1.8" - } + "node_modules/npm/node_modules/walk-up-path": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC" }, - "node_modules/pug-load": { - "version": "2.0.12", - "dev": true, + "node_modules/npm/node_modules/wcwidth": { + "version": "1.0.1", + "inBundle": true, "license": "MIT", - "optional": true, "dependencies": { - "object-assign": "^4.1.0", - "pug-walk": "^1.1.8" + "defaults": "^1.0.3" } }, - "node_modules/pug-parser": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/npm/node_modules/which": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", "dependencies": { - "pug-error": "^1.3.3", - "token-stream": "0.0.1" + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" } }, - "node_modules/pug-runtime": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "optional": true + "node_modules/npm/node_modules/which/node_modules/isexe": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16" + } }, - "node_modules/pug-strip-comments": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/npm/node_modules/wide-align": { + "version": "1.1.5", + "inBundle": true, + "license": "ISC", "dependencies": { - "pug-error": "^1.3.3" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "node_modules/pug-walk": { - "version": "1.1.8", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/punycode": { - "version": "2.3.0", + "node_modules/npm/node_modules/wrap-ansi": { + "version": "8.1.0", + "inBundle": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/q": { - "version": "1.5.1", - "dev": true, + "node_modules/npm/node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "inBundle": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/qjobs": { - "version": "1.2.0", - "dev": true, + "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, "license": "MIT", - "engines": { - "node": ">=0.9" - } - }, - "node_modules/qs": { - "version": "6.11.1", - "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=0.6" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/quick-lru": { - "version": "4.0.1", - "dev": true, + "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "inBundle": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "dev": true, + "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "inBundle": true, "license": "MIT", "dependencies": { - "safe-buffer": "^5.1.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/range-parser": { - "version": "1.2.1", - "dev": true, + "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "inBundle": true, "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">= 0.6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/raw-body": { - "version": "2.5.2", - "dev": true, - "license": "MIT", + "node_modules/npm/node_modules/write-file-atomic": { + "version": "5.0.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">= 0.8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", + "node_modules/npm/node_modules/yallist": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, - "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "boolbase": "^1.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "node_modules/num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==", "dev": true }, - "node_modules/read-cache": { - "version": "1.0.0", - "dev": true, + "node_modules/number-is-nan": { + "version": "1.0.1", "license": "MIT", - "dependencies": { - "pify": "^2.3.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/read-package-json": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.0.tgz", - "integrity": "sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==", - "dependencies": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" + "node_modules/nvd3": { + "version": "1.8.6", + "license": "Apache-2.0", + "peerDependencies": { + "d3": "^3.4.4" } }, - "node_modules/read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "node_modules/nx": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/nx/-/nx-17.0.3.tgz", + "integrity": "sha512-VShJISKCYt3iVJoMUPZiv67+0tiItxWMnfVmTmPZPio2Fu+wGc9U4ijjPxcmp2RJmLRaxkB9cn5rlrAvkIrNMA==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" + "@nrwl/tao": "17.0.3", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.6", + "axios": "^1.5.1", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.3.1", + "dotenv-expand": "~10.0.0", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "fs-extra": "^11.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "js-yaml": "4.1.0", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "3.0.5", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "semver": "7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "v8-compile-cache": "2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "17.0.3", + "@nx/nx-darwin-x64": "17.0.3", + "@nx/nx-freebsd-x64": "17.0.3", + "@nx/nx-linux-arm-gnueabihf": "17.0.3", + "@nx/nx-linux-arm64-gnu": "17.0.3", + "@nx/nx-linux-arm64-musl": "17.0.3", + "@nx/nx-linux-x64-gnu": "17.0.3", + "@nx/nx-linux-x64-musl": "17.0.3", + "@nx/nx-win32-arm64-msvc": "17.0.3", + "@nx/nx-win32-x64-msvc": "17.0.3" + }, + "peerDependencies": { + "@swc-node/register": "^1.6.7", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "node_modules/nx/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/read-package-json/node_modules/brace-expansion": { + "node_modules/nx/node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/nx/node_modules/axios": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", + "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", + "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/read-package-json/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "node_modules/nx/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/read-package-json/node_modules/hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "dependencies": { - "lru-cache": "^10.0.1" - }, + "node_modules/nx/node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "node_modules/nx/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=7.0.0" } }, - "node_modules/read-package-json/node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", - "engines": { - "node": "14 || >=16.14" - } + "node_modules/nx/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/read-package-json/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/nx/node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/read-package-json/node_modules/normalize-package-data": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", - "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", - "dependencies": { - "hosted-git-info": "^7.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg": { - "version": "3.0.0", + "node_modules/nx/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, - "license": "MIT", "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=4" + "node": ">= 6" } }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "3.0.0", + "node_modules/nx/node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", "dev": true, - "license": "MIT", "dependencies": { - "pify": "^3.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=14.14" } }, - "node_modules/read-pkg/node_modules/pify": { - "version": "3.0.0", + "node_modules/nx/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/readable-stream": { - "version": "2.3.8", + "node_modules/nx/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/readable-stream/node_modules/isarray": { - "version": "1.0.0", + "node_modules/nx/node_modules/lines-and-columns": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", "dev": true, - "license": "MIT" - }, - "node_modules/readdirp": { - "version": "3.6.0", - "devOptional": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, "engines": { - "node": ">=8.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/rechoir": { - "version": "0.7.1", + "node_modules/nx/node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", "dev": true, - "license": "MIT", "dependencies": { - "resolve": "^1.9.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.10" + "node": "*" } }, - "node_modules/redent": { - "version": "3.0.0", + "node_modules/nx/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "node_modules/nx/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "dependencies": { - "regenerate": "^1.4.2" + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "node_modules/nx/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" + "engines": { + "node": ">=12" } }, - "node_modules/regex-not": { - "version": "1.0.2", + "node_modules/oauth-sign": { + "version": "0.9.0", "dev": true, - "license": "MIT", - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, + "license": "Apache-2.0", "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/regex-not/node_modules/extend-shallow": { - "version": "3.0.2", + "node_modules/object-assign": { + "version": "4.1.1", "dev": true, "license": "MIT", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/regex-not/node_modules/is-extendable": { - "version": "1.0.1", + "node_modules/object-copy": { + "version": "0.1.0", "dev": true, "license": "MIT", "dependencies": { - "is-plain-object": "^2.0.4" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/regex-parser": { - "version": "2.2.11", - "dev": true, - "license": "MIT" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "node_modules/object-hash": { + "version": "3.0.0", "dev": true, - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, + "license": "MIT", "engines": { - "node": ">=4" - } - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" + "node": ">= 6" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "node_modules/object-inspect": { + "version": "1.12.3", "dev": true, - "bin": { - "jsesc": "bin/jsesc" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/relateurl": { - "version": "0.2.7", + "node_modules/object-keys": { + "version": "1.1.1", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">= 0.4" } }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "dev": true, - "license": "ISC" - }, - "node_modules/repeat-element": { - "version": "1.1.4", + "node_modules/object-visit": { + "version": "1.0.1", "dev": true, "license": "MIT", + "dependencies": { + "isobject": "^3.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/repeat-string": { - "version": "1.6.1", + "node_modules/object.assign": { + "version": "4.1.4", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">=0.10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/request": { - "version": "2.88.2", + "node_modules/object.defaults": { + "version": "1.1.0", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" }, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", + "node_modules/object.map": { + "version": "1.0.1", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", "license": "MIT", + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", + "node_modules/object.pick": { + "version": "1.3.0", + "dev": true, "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/requires-port": { - "version": "1.0.0", + "node_modules/object.values": { + "version": "1.1.6", "dev": true, - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-dir": { - "version": "1.0.1", + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.3.0", "dev": true, "license": "MIT", "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "ee-first": "1.1.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/resolve-from": { - "version": "5.0.0", + "node_modules/on-headers": { + "version": "1.0.2", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/resolve-global": { - "version": "1.0.0", + "node_modules/once": { + "version": "1.4.0", "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", "license": "MIT", "dependencies": { - "global-dirs": "^0.1.1" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=8" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resolve-pkg": { - "version": "2.0.0", - "dev": true, - "license": "MIT", + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dependencies": { - "resolve-from": "^5.0.0" + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resolve-url": { - "version": "0.2.1", - "dev": true, - "license": "MIT" + "node_modules/openurl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", + "integrity": "sha512-d/gTkTb1i1GKz5k3XE3XFV/PxQ1k45zDqGP2OA7YhgsaLoqm6qRvARAZOFer1fcXritWlGBRCu/UgeS4HAnXAA==", + "dev": true }, - "node_modules/resolve-url-loader": { - "version": "5.0.0", + "node_modules/opn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", + "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", "dev": true, - "license": "MIT", "dependencies": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.14", - "source-map": "0.6.1" + "is-wsl": "^1.1.0" }, "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/resolve-url-loader/node_modules/loader-utils": { - "version": "2.0.4", + "node_modules/opn/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", "dev": true, - "license": "MIT", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, "engines": { - "node": ">=8.9.0" + "node": ">=4" } }, - "node_modules/resolve-url-loader/node_modules/source-map": { + "node_modules/optimist": { "version": "0.6.1", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT/X11", + "dependencies": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "node_modules/optimist/node_modules/minimist": { + "version": "0.0.10", + "dev": true, + "license": "MIT" + }, + "node_modules/optimist/node_modules/wordwrap": { + "version": "0.0.3", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.4.0" } }, - "node_modules/resp-modifier": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz", - "integrity": "sha512-U1+0kWC/+4ncRFYqQWTx/3qkfE6a4B/h3XXgmXypfa0SPZ3t7cbbaFk297PjQS/yov24R18h6OZe6iZwj3NSLw==", + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { - "debug": "^2.2.0", - "minimatch": "^3.0.2" + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/resp-modifier/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, + "node_modules/ora": { + "version": "5.4.1", + "license": "MIT", "dependencies": { - "ms": "2.0.0" + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resp-modifier/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/restore-cursor": { - "version": "3.1.0", + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ret": { - "version": "0.1.15", - "dev": true, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.12" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "engines": { - "node": ">= 4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/reusify": { - "version": "1.0.4", - "dev": true, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/rfdc": { - "version": "1.3.0", - "dev": true, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", "license": "MIT" }, - "node_modules/right-align": { - "version": "0.1.3", - "dev": true, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", "license": "MIT", - "optional": true, - "dependencies": { - "align-text": "^0.1.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "license": "ISC", + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", "dependencies": { - "glob": "^7.1.3" + "has-flag": "^4.0.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">=8" + } + }, + "node_modules/ordered-ast-traverse": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ordered-esprima-props": "~1.1.0" + } + }, + "node_modules/ordered-esprima-props": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "license": "MIT", + "dependencies": { + "lcid": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", + "node_modules/os-tmpdir": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", "dev": true, "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" }, "engines": { - "node": "*" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "node_modules/p-locate": { + "version": "5.0.0", "dev": true, - "bin": { - "rollup": "dist/bin/rollup" + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" }, "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" + "node": ">=10" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dependencies": { - "execa": "^5.0.0" + "aggregate-error": "^3.0.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/run-async": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", - "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, "engines": { - "node": ">=0.12.0" + "node": ">=8" } }, - "node_modules/run-parallel": { - "version": "1.2.0", + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" + "engines": { + "node": ">= 4" } }, - "node_modules/rx": { - "version": "2.3.24", - "dev": true + "node_modules/p-try": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/rxjs": { - "version": "7.4.0", - "license": "Apache-2.0", + "node_modules/pacote": { + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-17.0.4.tgz", + "integrity": "sha512-eGdLHrV/g5b5MtD5cTPyss+JxOlaOloSMG3UwPMAvL8ywaLJ6beONPF40K4KKl/UI6q5hTKCJq5rCu8tkF+7Dg==", "dependencies": { - "tslib": "~2.1.0" + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^7.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^7.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^2.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/rxjs/node_modules/tslib": { - "version": "2.1.0", - "license": "0BSD" - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "license": "MIT" - }, - "node_modules/safe-json-parse": { - "version": "1.0.1", + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, - "node_modules/safe-regex": { - "version": "1.1.0", + "node_modules/param-case": { + "version": "2.1.1", "dev": true, "license": "MIT", "dependencies": { - "ret": "~0.1.10" + "no-case": "^2.2.0" } }, - "node_modules/safe-regex-test": { - "version": "1.0.0", + "node_modules/parent-module": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "callsites": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/safevalues": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/safevalues/-/safevalues-0.3.4.tgz", - "integrity": "sha512-LRneZZRXNgjzwG4bDQdOTSbze3fHm1EAKN/8bePxnlEZiBmkYEDggaHbuvHI9/hoqHbGfsEA7tWS9GhYHZBBsw==" - }, - "node_modules/sass": { - "version": "1.69.5", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz", - "integrity": "sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==", + "node_modules/parse-filepath": { + "version": "1.0.2", "dev": true, + "license": "MIT", "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=0.8" } }, - "node_modules/sass-loader": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz", - "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==", + "node_modules/parse-json": { + "version": "5.2.0", "dev": true, + "license": "MIT", "dependencies": { - "neo-async": "^2.6.2" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": ">= 14.15.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sass/node_modules/immutable": { - "version": "4.3.0", + "node_modules/parse-node-version": { + "version": "1.0.1", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.10" + } }, - "node_modules/saucelabs": { - "version": "1.5.0", + "node_modules/parse-passwd": { + "version": "1.0.0", "dev": true, - "dependencies": { - "https-proxy-agent": "^2.2.1" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/saucelabs/node_modules/agent-base": { - "version": "4.3.0", - "dev": true, + "node_modules/parse5": { + "version": "7.1.2", + "devOptional": true, "license": "MIT", "dependencies": { - "es6-promisify": "^5.0.0" + "entities": "^4.4.0" }, - "engines": { - "node": ">= 4.0.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/saucelabs/node_modules/debug": { - "version": "3.2.7", + "node_modules/parse5-html-rewriting-stream": { + "version": "7.0.0", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/saucelabs/node_modules/https-proxy-agent": { - "version": "2.2.4", + "node_modules/parse5-sax-parser": { + "version": "7.0.0", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" + "parse5": "^7.0.0" }, - "engines": { - "node": ">= 4.5.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/sax": { - "version": "1.2.4", + "node_modules/parseurl": { + "version": "1.3.3", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "node_modules/schema-utils": { - "version": "4.0.1", + "node_modules/pascalcase": { + "version": "0.1.1", "dev": true, "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=0.10.0" } }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true + "node_modules/path-dirname": { + "version": "1.0.2", + "dev": true, + "license": "MIT" }, - "node_modules/selenium-webdriver": { - "version": "3.6.0", + "node_modules/path-exists": { + "version": "4.0.0", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "jszip": "^3.1.3", - "rimraf": "^2.5.4", - "tmp": "0.0.30", - "xml2js": "^0.4.17" - }, + "license": "MIT", "engines": { - "node": ">= 6.9.0" + "node": ">=8" } }, - "node_modules/selenium-webdriver/node_modules/glob": { - "version": "7.2.3", + "node_modules/path-is-absolute": { + "version": "1.0.1", "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10.0" } }, - "node_modules/selenium-webdriver/node_modules/rimraf": { - "version": "2.7.1", + "node_modules/path-is-inside": { + "version": "1.0.2", "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "license": "(WTFPL OR MIT)" + }, + "node_modules/path-key": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/selenium-webdriver/node_modules/tmp": { - "version": "0.0.30", + "node_modules/path-parse": { + "version": "1.0.7", + "license": "MIT" + }, + "node_modules/path-root": { + "version": "0.1.1", "dev": true, "license": "MIT", "dependencies": { - "os-tmpdir": "~1.0.1" + "path-root-regex": "^0.1.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "node_modules/path-root-regex": { + "version": "0.1.2", "dev": true, - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", "engines": { - "node": ">=10" + "node": "14 || >=16.14" } }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "license": "ISC" + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "node_modules/path-type": { + "version": "4.0.0", "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, + "node_modules/pdfjs-dist": { + "version": "2.16.105", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz", + "integrity": "sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==", "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" + "dommatrix": "^1.0.3", + "web-streams-polyfill": "^3.2.1" }, - "engines": { - "node": ">=4" + "peerDependencies": { + "worker-loader": "^3.0.8" + }, + "peerDependenciesMeta": { + "worker-loader": { + "optional": true + } } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/send/node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "node_modules/performance-now": { + "version": "2.1.0", "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } + "license": "MIT" }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/picocolors": { + "version": "1.0.0", "dev": true, - "engines": { - "node": ">= 0.8" - } + "license": "ISC" }, - "node_modules/serialize-javascript": { - "version": "6.0.1", + "node_modules/picomatch": { + "version": "2.3.1", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/serve-index": { - "version": "1.9.1", + "node_modules/pidtree": { + "version": "0.3.1", "dev": true, "license": "MIT", - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "bin": { + "pidtree": "bin/pidtree.js" }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.10" } }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", + "node_modules/pify": { + "version": "2.3.0", "dev": true, "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", + "node_modules/pinkie": { + "version": "2.0.4", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", + "node_modules/pinkie-promise": { + "version": "2.0.1", "dev": true, "license": "MIT", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "pinkie": "^2.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "dev": true, - "license": "ISC" - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "dev": true, - "license": "ISC" - }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", + "node_modules/pirates": { + "version": "4.0.5", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 6" } }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "node_modules/piscina": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.1.0.tgz", + "integrity": "sha512-sjbLMi3sokkie+qmtZpkfMCUJTpbxJm/wvaPzU28vmYSsTSW8xk9JcFUsbqGJdtPpIQ9tuj+iDcTtgZjwnOSig==", "dev": true, "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" + "eventemitter-asyncresource": "^1.0.0", + "hdr-histogram-js": "^2.0.1", + "hdr-histogram-percentiles-obj": "^3.0.0" }, - "engines": { - "node": ">= 0.8.0" + "optionalDependencies": { + "nice-napi": "^1.0.2" } }, - "node_modules/server-destroy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", - "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==", - "dev": true - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/set-value": { - "version": "2.0.1", + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", "dev": true, - "license": "MIT", "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "find-up": "^6.3.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "dev": true, - "license": "ISC" - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, "dependencies": { - "kind-of": "^6.0.2" + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "license": "MIT", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, "dependencies": { - "shebang-regex": "^3.0.0" + "p-locate": "^6.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.1", - "dev": true, - "license": "MIT", + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shelljs": { - "version": "0.3.0", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, - "license": "BSD*", - "bin": { - "shjs": "bin/shjs" + "dependencies": { + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=0.8.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/showdown": { - "version": "1.3.0", - "license": "BSD-2-Clause", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, "dependencies": { - "yargs": "^3.15.0" + "p-limit": "^4.0.0" }, - "bin": { - "showdown": "bin/showdown.js" - } - }, - "node_modules/showdown/node_modules/ansi-regex": { - "version": "2.1.1", - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/showdown/node_modules/camelcase": { - "version": "2.1.1", - "license": "MIT", + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/showdown/node_modules/cliui": { - "version": "3.2.0", - "license": "ISC", - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/showdown/node_modules/is-fullwidth-code-point": { + "node_modules/pkg-dir/node_modules/yocto-queue": { "version": "1.0.0", - "license": "MIT", - "dependencies": { - "number-is-nan": "^1.0.0" - }, + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/showdown/node_modules/string-width": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "node": ">=12.20" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/showdown/node_modules/strip-ansi": { - "version": "3.0.1", + "node_modules/pkg-up": { + "version": "3.1.0", + "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" + "find-up": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/showdown/node_modules/window-size": { - "version": "0.1.4", + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "dev": true, "license": "MIT", - "bin": { - "window-size": "cli.js" + "dependencies": { + "locate-path": "^3.0.0" }, "engines": { - "node": ">= 0.10.0" + "node": ">=6" } }, - "node_modules/showdown/node_modules/wrap-ansi": { - "version": "2.1.0", + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "dev": true, "license": "MIT", "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/showdown/node_modules/y18n": { - "version": "3.2.2", - "license": "ISC" - }, - "node_modules/showdown/node_modules/yargs": { - "version": "3.32.0", - "license": "MIT", - "dependencies": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" + "node": ">=6" } }, - "node_modules/side-channel": { - "version": "1.0.4", + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sigmund": { - "version": "1.0.1", - "license": "ISC" - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "license": "ISC" - }, - "node_modules/sigstore": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.1.0.tgz", - "integrity": "sha512-kPIj+ZLkyI3QaM0qX8V/nSsweYND3W448pwkDgS6CQ74MfhEkIR8ToK5Iyx46KJYRjseVcD3Rp9zAmUAj6ZjPw==", + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "dev": true, + "license": "MIT", "dependencies": { - "@sigstore/bundle": "^2.1.0", - "@sigstore/protobuf-specs": "^0.2.1", - "@sigstore/sign": "^2.1.0", - "@sigstore/tuf": "^2.1.0" + "p-limit": "^2.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=6" } }, - "node_modules/simple-fmt": { - "version": "0.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/simple-is": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { + "node_modules/pkg-up/node_modules/path-exists": { "version": "3.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "node": ">=4" } }, - "node_modules/snapdragon": { - "version": "0.8.2", + "node_modules/portscanner": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", + "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", "dev": true, - "license": "MIT", "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "async": "^2.6.0", + "is-number-like": "^1.0.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4", + "npm": ">=1.0.0" } }, - "node_modules/snapdragon-node": { - "version": "2.1.1", + "node_modules/portscanner/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dev": true, - "license": "MIT", "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" + "lodash": "^4.17.14" } }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", + "node_modules/posix-character-classes": { + "version": "0.1.1", "dev": true, "license": "MIT", - "dependencies": { - "is-descriptor": "^1.0.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "kind-of": "^6.0.0" + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14" } }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", + "node_modules/postcss-import": { + "version": "15.1.0", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^6.0.0" + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" }, "engines": { - "node": ">=0.10.0" + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" } }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", + "node_modules/postcss-js": { + "version": "4.0.1", "dev": true, "license": "MIT", "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "camelcase-css": "^2.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "kind-of": "^3.2.0" + "node": "^12 || ^14 || >= 16" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" } }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", + "node_modules/postcss-load-config": { + "version": "4.0.1", "dev": true, "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "lilconfig": "^2.0.5", + "yaml": "^2.1.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "node": ">= 14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/snapdragon/node_modules/source-map": { - "version": "0.5.7", + "node_modules/postcss-load-config/node_modules/yaml": { + "version": "2.2.2", "dev": true, - "license": "BSD-3-Clause", + "license": "ISC", "engines": { - "node": ">=0.10.0" + "node": ">= 14" } }, - "node_modules/socket.io": { - "version": "4.6.1", + "node_modules/postcss-loader": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", + "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", "dev": true, - "license": "MIT", "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.4.1", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.1" + "cosmiconfig": "^8.2.0", + "jiti": "^1.18.2", + "semver": "^7.3.8" }, "engines": { - "node": ">=10.0.0" + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" } }, - "node_modules/socket.io-adapter": { - "version": "2.5.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ws": "~8.11.0" - } + "node_modules/postcss-loader/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "node_modules/socket.io-client": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz", - "integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==", + "node_modules/postcss-loader/node_modules/cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", "dev": true, "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.2", - "engine.io-client": "~6.5.2", - "socket.io-parser": "~4.2.4" + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" } }, - "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "node_modules/postcss-loader/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "argparse": "^2.0.1" }, - "engines": { - "node": ">=10.0.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/sockjs/node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", "dev": true, "dependencies": { - "websocket-driver": ">=0.5.1" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" }, "engines": { - "node": ">=0.8.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/sockjs/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" + "postcss-selector-parser": "^6.0.4" }, "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "socks": "^2.7.1" + "node": "^10 || ^12 || >= 14" }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/socks/node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/source-map-js": { - "version": "1.0.2", + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, - "license": "BSD-3-Clause", + "dependencies": { + "icss-utils": "^5.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/source-map-loader": { - "version": "4.0.1", + "node_modules/postcss-nested": { + "version": "6.0.1", "dev": true, "license": "MIT", "dependencies": { - "abab": "^2.0.6", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.2" + "postcss-selector-parser": "^6.0.11" }, "engines": { - "node": ">= 14.15.0" + "node": ">=12.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://opencollective.com/postcss/" }, "peerDependencies": { - "webpack": "^5.72.1" + "postcss": "^8.2.14" } }, - "node_modules/source-map-resolve": { - "version": "0.5.3", + "node_modules/postcss-scss": { + "version": "0.1.9", "dev": true, "license": "MIT", "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "postcss": "^5.1.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", + "node_modules/postcss-scss/node_modules/ansi-regex": { + "version": "2.1.1", "dev": true, "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/source-map-url": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/spawn-command": { - "version": "0.0.2-1", + "node_modules/postcss-scss/node_modules/ansi-styles": { + "version": "2.2.1", "dev": true, - "license": "MIT" - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "license": "CC0-1.0" - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "node_modules/postcss-scss/node_modules/chalk": { + "version": "1.1.3", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "node_modules/postcss-scss/node_modules/chalk/node_modules/supports-color": { + "version": "2.0.0", "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" + "license": "MIT", + "engines": { + "node": ">=0.8.0" } }, - "node_modules/spdy-transport/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/postcss-scss/node_modules/has-flag": { + "version": "1.0.0", "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, + "license": "MIT", "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/split-string": { - "version": "3.1.0", + "node_modules/postcss-scss/node_modules/postcss": { + "version": "5.2.18", "dev": true, "license": "MIT", "dependencies": { - "extend-shallow": "^3.0.0" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.12" } }, - "node_modules/split-string/node_modules/extend-shallow": { - "version": "3.0.2", + "node_modules/postcss-scss/node_modules/source-map": { + "version": "0.5.7", "dev": true, - "license": "MIT", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/split-string/node_modules/is-extendable": { - "version": "1.0.1", + "node_modules/postcss-scss/node_modules/strip-ansi": { + "version": "3.0.1", "dev": true, "license": "MIT", "dependencies": { - "is-plain-object": "^2.0.4" + "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/split2": { - "version": "3.2.2", + "node_modules/postcss-scss/node_modules/supports-color": { + "version": "3.2.3", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "readable-stream": "^3.0.0" + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" } }, - "node_modules/split2/node_modules/readable-stream": { - "version": "3.6.2", + "node_modules/postcss-selector-parser": { + "version": "6.0.11", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, - "node_modules/sshpk": { - "version": "1.17.0", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "license": "MIT", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "node_modules/preprocess": { + "version": "3.2.0", + "dev": true, "dependencies": { - "minipass": "^7.0.3" + "xregexp": "3.1.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 0.10.0" } }, - "node_modules/stable": { - "version": "0.1.8", + "node_modules/prettier": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", "dev": true, - "license": "MIT" + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } }, - "node_modules/static-extend": { - "version": "0.1.2", + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "fast-diff": "^1.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/statuses": { - "version": "1.3.1", + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stream-throttle": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", - "integrity": "sha512-889+B9vN9dq7/vLbGyuHeZ6/ctf5sNuGWsDy89uNxkFTAgzy0eK7+w5fL3KLNRTkLle7EgZGvHUphZW0Q26MnQ==", + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "commander": "^2.2.0", - "limiter": "^1.0.5" - }, - "bin": { - "throttleproxy": "bin/throttleproxy.js" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/streamroller": { - "version": "3.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { - "node": ">=8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/streamroller/node_modules/fs-extra": { - "version": "8.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", "engines": { - "node": ">=6 <7 || >=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/streamroller/node_modules/jsonfile": { - "version": "4.0.0", + "node_modules/process-nextick-args": { + "version": "2.0.1", "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } + "license": "MIT" }, - "node_modules/streamroller/node_modules/universalify": { - "version": "0.1.2", + "node_modules/promise": { + "version": "7.3.1", "dev": true, "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "license": "MIT", + "optional": true, "dependencies": { - "safe-buffer": "~5.1.0" + "asap": "~2.0.3" } }, - "node_modules/string-template": { - "version": "0.2.1", - "dev": true + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" }, - "node_modules/string-width": { - "version": "4.2.3", - "license": "MIT", + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "err-code": "^2.0.2", + "retry": "^0.12.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/protractor": { + "version": "7.0.0", + "dev": true, + "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.1.7", + "yargs": "^15.3.1" + }, + "bin": { + "protractor": "bin/protractor", + "webdriver-manager": "bin/webdriver-manager" }, "engines": { - "node": ">=8" + "node": ">=10.13.x" } }, - "node_modules/string.prototype.padend": { - "version": "3.1.4", + "node_modules/protractor/node_modules/ansi-regex": { + "version": "2.1.1", "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", + "node_modules/protractor/node_modules/ansi-styles": { + "version": "2.2.1", "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", + "node_modules/protractor/node_modules/chalk": { + "version": "1.1.3", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", + "node_modules/protractor/node_modules/cliui": { + "version": "6.0.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, - "node_modules/stringmap": { - "version": "0.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/stringset": { - "version": "0.2.1", + "node_modules/protractor/node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", "dev": true, - "license": "MIT" - }, - "node_modules/strip-ansi": { - "version": "6.0.1", "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", + "node_modules/protractor/node_modules/cliui/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -22997,1540 +23222,1399 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "3.0.0", + "node_modules/protractor/node_modules/color-convert": { + "version": "2.0.1", "dev": true, "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=4" + "node": ">=7.0.0" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", + "node_modules/protractor/node_modules/color-name": { + "version": "1.1.4", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/strip-indent": { - "version": "3.0.0", + "node_modules/protractor/node_modules/find-up": { + "version": "4.1.0", "dev": true, "license": "MIT", "dependencies": { - "min-indent": "^1.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strong-log-transformer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "node_modules/protractor/node_modules/glob": { + "version": "7.2.3", "dev": true, + "license": "ISC", "dependencies": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" - }, - "bin": { - "sl-log-transformer": "bin/sl-log-transformer.js" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=4" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sucrase": { - "version": "3.32.0", + "node_modules/protractor/node_modules/locate-path": { + "version": "5.0.0", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" + "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, - "node_modules/sucrase/node_modules/commander": { - "version": "4.1.1", + "node_modules/protractor/node_modules/p-limit": { + "version": "2.3.0", "dev": true, "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "7.1.6", - "dev": true, - "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "p-try": "^2.0.0" }, "engines": { - "node": "*" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-color": { - "version": "5.5.0", + "node_modules/protractor/node_modules/p-locate": { + "version": "4.1.0", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", + "node_modules/protractor/node_modules/q": { + "version": "1.4.1", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.6.0", + "teleport": ">=0.2.0" } }, - "node_modules/symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "node_modules/protractor/node_modules/source-map": { + "version": "0.5.7", + "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=0.10" + "node": ">=0.10.0" } }, - "node_modules/synckit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", - "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "node_modules/protractor/node_modules/source-map-support": { + "version": "0.4.18", "dev": true, + "license": "MIT", "dependencies": { - "@pkgr/utils": "^2.3.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" + "source-map": "^0.5.6" } }, - "node_modules/tailwindcss": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", - "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", + "node_modules/protractor/node_modules/strip-ansi": { + "version": "3.0.1", "dev": true, + "license": "MIT", "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.18.2", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" + "ansi-regex": "^2.0.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=0.10.0" } }, - "node_modules/tailwindcss/node_modules/arg": { - "version": "5.0.2", + "node_modules/protractor/node_modules/supports-color": { + "version": "2.0.0", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } }, - "node_modules/tailwindcss/node_modules/glob-parent": { - "version": "6.0.2", + "node_modules/protractor/node_modules/wrap-ansi": { + "version": "6.2.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=8" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "node_modules/protractor/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "node_modules/protractor/node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "node_modules/protractor/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", "dev": true, + "license": "MIT", "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/protractor/node_modules/y18n": { + "version": "4.0.3", + "dev": true, + "license": "ISC" + }, + "node_modules/protractor/node_modules/yargs": { + "version": "15.4.1", "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/protractor/node_modules/yargs-parser": { + "version": "18.1.3", + "dev": true, + "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" }, "engines": { - "node": ">= 8" + "node": ">=6" } }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "engines": { - "node": ">=8" + "node": ">= 0.10" } }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, "engines": { - "node": ">=10" + "node": ">= 0.10" } }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true }, - "node_modules/terser": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", - "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "node_modules/prr": { + "version": "1.0.1", "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } + "license": "MIT", + "optional": true }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.7", + "node_modules/psl": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/pug": { + "version": "2.0.4", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "pug-code-gen": "^2.0.2", + "pug-filters": "^3.1.1", + "pug-lexer": "^4.1.0", + "pug-linker": "^3.0.6", + "pug-load": "^2.0.12", + "pug-parser": "^5.0.1", + "pug-runtime": "^2.0.5", + "pug-strip-comments": "^1.0.4" } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", + "node_modules/pug-attrs": { + "version": "2.0.4", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "constantinople": "^3.0.1", + "js-stringify": "^1.0.1", + "pug-runtime": "^2.0.5" } }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", + "node_modules/pug-code-gen": { + "version": "2.0.3", "dev": true, "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" + "optional": true, + "dependencies": { + "constantinople": "^3.1.2", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.1", + "pug-attrs": "^2.0.4", + "pug-error": "^1.3.3", + "pug-runtime": "^2.0.5", + "void-elements": "^2.0.1", + "with": "^5.0.0" } }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", + "node_modules/pug-error": { + "version": "1.3.3", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.2", + "node_modules/pug-filters": { + "version": "3.1.1", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "clean-css": "^4.1.11", + "constantinople": "^3.0.1", + "jstransformer": "1.0.0", + "pug-error": "^1.3.3", + "pug-walk": "^1.1.8", + "resolve": "^1.1.6", + "uglify-js": "^2.6.1" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "node_modules/pug-lexer": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "character-parser": "^2.1.1", + "is-expression": "^3.0.0", + "pug-error": "^1.3.3" + } }, - "node_modules/test-exclude": { - "version": "6.0.0", + "node_modules/pug-linker": { + "version": "3.0.6", "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" + "pug-error": "^1.3.3", + "pug-walk": "^1.1.8" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", + "node_modules/pug-load": { + "version": "2.0.12", "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "object-assign": "^4.1.0", + "pug-walk": "^1.1.8" } }, - "node_modules/text-extensions": { - "version": "1.9.0", + "node_modules/pug-parser": { + "version": "5.0.1", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10" + "optional": true, + "dependencies": { + "pug-error": "^1.3.3", + "token-stream": "0.0.1" } }, - "node_modules/text-table": { - "version": "0.2.0", + "node_modules/pug-runtime": { + "version": "2.0.5", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, - "node_modules/thenify": { - "version": "3.3.1", + "node_modules/pug-strip-comments": { + "version": "1.0.4", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "any-promise": "^1.0.0" + "pug-error": "^1.3.3" } }, - "node_modules/thenify-all": { - "version": "1.6.0", + "node_modules/pug-walk": { + "version": "1.1.8", "dev": true, "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, + "optional": true + }, + "node_modules/punycode": { + "version": "2.3.0", + "license": "MIT", "engines": { - "node": ">=0.8" + "node": ">=6" } }, - "node_modules/through": { - "version": "2.3.8", + "node_modules/q": { + "version": "1.5.1", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } }, - "node_modules/through2": { - "version": "4.0.2", + "node_modules/qjobs": { + "version": "1.2.0", "dev": true, "license": "MIT", - "dependencies": { - "readable-stream": "3" + "engines": { + "node": ">=0.9" } }, - "node_modules/through2/node_modules/readable-stream": { - "version": "3.6.2", + "node_modules/qs": { + "version": "6.11.1", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "side-channel": "^1.0.4" }, "engines": { - "node": ">= 6" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true + "node_modules/queue-microtask": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, - "node_modules/tiny-lr": { - "version": "1.1.1", + "node_modules/quick-lru": { + "version": "4.0.1", "dev": true, "license": "MIT", - "dependencies": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" + "engines": { + "node": ">=8" } }, - "node_modules/tiny-lr/node_modules/debug": { - "version": "3.2.7", + "node_modules/randombytes": { + "version": "2.1.0", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "safe-buffer": "^5.1.0" } }, - "node_modules/titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "node_modules/range-parser": { + "version": "1.2.1", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/tmp": { - "version": "0.2.1", + "node_modules/raw-body": { + "version": "2.5.2", "dev": true, "license": "MIT", "dependencies": { - "rimraf": "^3.0.0" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/to-object-path": { - "version": "0.3.0", + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/read-cache": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "pify": "^2.3.0" + } + }, + "node_modules/read-package-json": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.0.tgz", + "integrity": "sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==", + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/to-regex": { + "node_modules/read-package-json-fast": { "version": "3.0.2", - "dev": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "devOptional": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, + "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", "engines": { - "node": ">=8.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/to-regex/node_modules/define-property": { - "version": "2.0.2", - "dev": true, - "license": "MIT", + "node_modules/read-package-json/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "balanced-match": "^1.0.0" + } + }, + "node_modules/read-package-json/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=0.10.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/to-regex/node_modules/extend-shallow": { - "version": "3.0.2", - "dev": true, - "license": "MIT", + "node_modules/read-package-json/node_modules/hosted-git-info": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", + "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "lru-cache": "^10.0.1" }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/to-regex/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "dev": true, - "license": "MIT", + "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/lru-cache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/read-package-json/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dependencies": { - "kind-of": "^6.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/to-regex/node_modules/is-data-descriptor": { - "version": "1.0.0", - "dev": true, - "license": "MIT", + "node_modules/read-package-json/node_modules/normalize-package-data": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", + "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", "dependencies": { - "kind-of": "^6.0.0" + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/to-regex/node_modules/is-descriptor": { - "version": "1.0.2", + "node_modules/read-pkg": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/to-regex/node_modules/is-extendable": { - "version": "1.0.1", + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "is-plain-object": "^2.0.4" + "pify": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/toidentifier": { - "version": "1.0.1", + "node_modules/read-pkg/node_modules/pify": { + "version": "3.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=0.6" + "node": ">=4" } }, - "node_modules/token-stream": { - "version": "0.0.1", + "node_modules/readable-stream": { + "version": "2.3.8", "dev": true, "license": "MIT", - "optional": true - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/tryor": { - "version": "0.1.2", + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", "dev": true, "license": "MIT" }, - "node_modules/ts-api-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", - "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "node_modules/readdirp": { + "version": "3.6.0", "dev": true, - "engines": { - "node": ">=16.13.0" + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" }, - "peerDependencies": { - "typescript": ">=4.2.0" + "engines": { + "node": ">=8.10.0" } }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", + "node_modules/rechoir": { + "version": "0.7.1", "dev": true, - "license": "Apache-2.0" - }, - "node_modules/ts-md5": { - "version": "1.3.1", "license": "MIT", + "dependencies": { + "resolve": "^1.9.0" + }, "engines": { - "node": ">=12" + "node": ">= 0.10" } }, - "node_modules/ts-node": { - "version": "10.9.1", + "node_modules/redent": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "engines": { + "node": ">=8" } }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", "dev": true, - "license": "BSD-3-Clause", + "dependencies": { + "regenerate": "^1.4.2" + }, "engines": { - "node": ">=0.3.1" + "node": ">=4" } }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, - "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "@babel/runtime": "^7.8.4" } }, - "node_modules/tsconfig-paths/node_modules/json5": { + "node_modules/regex-not": { "version": "1.0.2", "dev": true, "license": "MIT", "dependencies": { - "minimist": "^1.2.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/tuf-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.1.0.tgz", - "integrity": "sha512-eD7YPPjVlMzdggrOeE8zwoegUaG/rt6Bt3jwoQPunRiNVzgcCE009UDFJKJjG+Gk9wFu6W/Vi+P5d/5QpdD9jA==", + "node_modules/regex-not/node_modules/extend-shallow": { + "version": "3.0.2", + "dev": true, + "license": "MIT", "dependencies": { - "@tufjs/models": "2.0.0", - "debug": "^4.3.4", - "make-fetch-happen": "^13.0.0" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", + "node_modules/regex-not/node_modules/is-extendable": { + "version": "1.0.1", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "is-plain-object": "^2.0.4" }, "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", + "node_modules/regex-parser": { + "version": "2.2.11", "dev": true, - "license": "Unlicense" + "license": "MIT" }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", "dev": true, + "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/type-is": { - "version": "1.6.18", + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, - "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/typed-array-length": { - "version": "1.0.4", + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "jsesc": "~0.5.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "regjsparser": "bin/parser" } }, - "node_modules/typed-assert": { - "version": "1.0.9", - "dev": true, - "license": "MIT" - }, - "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", "dev": true, "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" + "jsesc": "bin/jsesc" } }, - "node_modules/ua-parser-js": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", - "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", + "node_modules/relateurl": { + "version": "0.2.7", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], + "license": "MIT", "engines": { - "node": "*" + "node": ">= 0.10" } }, - "node_modules/uglify-js": { - "version": "2.7.5", + "node_modules/remove-trailing-separator": { + "version": "1.1.0", "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "dependencies": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } + "license": "ISC" }, - "node_modules/uglify-js/node_modules/async": { - "version": "0.2.10", + "node_modules/repeat-element": { + "version": "1.1.4", "dev": true, - "optional": true + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/uglify-js/node_modules/camelcase": { - "version": "1.2.1", + "node_modules/repeat-string": { + "version": "1.6.1", "dev": true, "license": "MIT", - "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, - "node_modules/uglify-js/node_modules/cliui": { - "version": "2.1.0", + "node_modules/request": { + "version": "2.88.2", "dev": true, - "license": "ISC", - "optional": true, + "license": "Apache-2.0", "dependencies": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/uglify-js/node_modules/source-map": { - "version": "0.5.7", + "node_modules/request/node_modules/qs": { + "version": "6.5.3", "dev": true, "license": "BSD-3-Clause", - "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.6" } }, - "node_modules/uglify-js/node_modules/wordwrap": { - "version": "0.0.2", - "dev": true, - "license": "MIT/X11", - "optional": true, + "node_modules/require-directory": { + "version": "2.1.1", + "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/uglify-js/node_modules/yargs": { - "version": "3.10.0", - "dev": true, + "node_modules/require-from-string": { + "version": "2.0.2", "license": "MIT", - "optional": true, - "dependencies": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/uglify-to-browserify": { - "version": "1.0.2", - "license": "MIT" + "node_modules/require-main-filename": { + "version": "2.0.0", + "dev": true, + "license": "ISC" }, - "node_modules/unbox-primitive": { - "version": "1.0.2", + "node_modules/requires-port": { + "version": "1.0.0", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unc-path-regex": { - "version": "0.1.2", + "node_modules/resolve-dir": { + "version": "1.0.1", "dev": true, "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/underscore": { - "version": "1.13.6", + "node_modules/resolve-from": { + "version": "5.0.0", "dev": true, - "license": "MIT" - }, - "node_modules/underscore.string": { - "version": "2.3.3", + "license": "MIT", "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/undici": { - "version": "5.27.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", - "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", + "node_modules/resolve-global": { + "version": "1.0.0", "dev": true, + "license": "MIT", "dependencies": { - "@fastify/busboy": "^2.0.0" + "global-dirs": "^0.1.1" }, "engines": { - "node": ">=14.0" + "node": ">=8" } }, - "node_modules/unicode-canonical-property-names-ecmascript": { + "node_modules/resolve-pkg": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "node_modules/resolve-url": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve-url-loader": { + "version": "5.0.0", "dev": true, + "license": "MIT", "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" }, "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.4", "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, "engines": { - "node": ">=4" + "node": ">=8.9.0" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/union-value": { - "version": "1.0.1", + "node_modules/resp-modifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz", + "integrity": "sha512-U1+0kWC/+4ncRFYqQWTx/3qkfE6a4B/h3XXgmXypfa0SPZ3t7cbbaFk297PjQS/yov24R18h6OZe6iZwj3NSLw==", "dev": true, - "license": "MIT", "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" + "debug": "^2.2.0", + "minimatch": "^3.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "node_modules/resp-modifier/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "ms": "2.0.0" } }, - "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "node_modules/resp-modifier/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/universalify": { - "version": "2.0.0", + "node_modules/ret": { + "version": "0.1.15", "dev": true, "license": "MIT", "engines": { - "node": ">= 10.0.0" + "node": ">=0.12" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "dev": true, - "license": "MIT", + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "engines": { - "node": ">= 0.8" + "node": ">= 4" } }, - "node_modules/unset-value": { - "version": "1.0.0", + "node_modules/reusify": { + "version": "1.0.4", "dev": true, "license": "MIT", - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, "engines": { + "iojs": ">=1.0.0", "node": ">=0.10.0" } }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", + "node_modules/rfdc": { + "version": "1.3.0", + "license": "MIT" + }, + "node_modules/right-align": { + "version": "0.1.3", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "align-text": "^0.1.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", + "node_modules/rimraf": { + "version": "3.0.2", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "isarray": "1.0.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/unset-value/node_modules/isarray": { - "version": "1.0.0", + "node_modules/rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", "dev": true, - "license": "MIT" + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/upath": { - "version": "1.2.0", - "dev": true, - "license": "MIT", + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", "engines": { - "node": ">=4", - "yarn": "*" + "node": ">=0.12.0" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "node_modules/run-parallel": { + "version": "1.2.0", "dev": true, "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "type": "github", + "url": "https://github.com/sponsors/feross" }, { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" + "type": "patreon", + "url": "https://www.patreon.com/feross" }, { - "type": "github", - "url": "https://github.com/sponsors/ai" + "type": "consulting", + "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "queue-microtask": "^1.2.2" } }, - "node_modules/upper-case": { - "version": "1.1.3", - "dev": true, - "license": "MIT" + "node_modules/rx": { + "version": "2.3.24", + "dev": true }, - "node_modules/uri-js": { - "version": "4.4.1", - "license": "BSD-2-Clause", + "node_modules/rxjs": { + "version": "7.4.0", + "license": "Apache-2.0", "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uri-path": { - "version": "1.0.0", - "dev": true, - "license": "WTFPL OR MIT", - "engines": { - "node": ">= 0.10" + "tslib": "~2.1.0" } }, - "node_modules/urix": { - "version": "0.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/use": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "node_modules/rxjs/node_modules/tslib": { + "version": "2.1.0", + "license": "0BSD" }, - "node_modules/util-deprecate": { - "version": "1.0.2", + "node_modules/safe-buffer": { + "version": "5.1.2", "license": "MIT" }, - "node_modules/utils-merge": { + "node_modules/safe-json-parse": { "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } + "dev": true }, - "node_modules/uuid": { - "version": "3.4.0", + "node_modules/safe-regex": { + "version": "1.1.0", "dev": true, "license": "MIT", - "bin": { - "uuid": "bin/uuid" + "dependencies": { + "ret": "~0.1.10" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/v8flags": { - "version": "3.2.0", + "node_modules/safe-regex-test": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "homedir-polyfill": "^1.0.1" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" }, - "node_modules/vary": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } + "node_modules/safevalues": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/safevalues/-/safevalues-0.3.4.tgz", + "integrity": "sha512-LRneZZRXNgjzwG4bDQdOTSbze3fHm1EAKN/8bePxnlEZiBmkYEDggaHbuvHI9/hoqHbGfsEA7tWS9GhYHZBBsw==" }, - "node_modules/verror": { - "version": "1.10.0", + "node_modules/sass": { + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz", + "integrity": "sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==", "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/vite": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", - "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", + "node_modules/sass-loader": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz", + "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==", "dev": true, "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - }, - "bin": { - "vite": "bin/vite.js" + "neo-async": "^2.6.2" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">= 14.15.0" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { + "fibers": { "optional": true }, - "lightningcss": { + "node-sass": { "optional": true }, "sass": { "optional": true }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { + "sass-embedded": { "optional": true } } }, - "node_modules/void-elements": { - "version": "2.0.1", + "node_modules/sass/node_modules/immutable": { + "version": "4.3.0", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/watchpack": { - "version": "2.4.0", + "node_modules/saucelabs": { + "version": "1.5.0", "dev": true, - "license": "MIT", "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "https-proxy-agent": "^2.2.1" }, "engines": { - "node": ">=10.13.0" + "node": "*" } }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "node_modules/saucelabs/node_modules/agent-base": { + "version": "4.3.0", "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", "license": "MIT", "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "es6-promisify": "^5.0.0" + }, "engines": { - "node": ">= 8" + "node": ">= 4.0.0" } }, - "node_modules/webdriver-js-extender": { - "version": "2.1.0", + "node_modules/saucelabs/node_modules/debug": { + "version": "3.2.7", "dev": true, "license": "MIT", "dependencies": { - "@types/selenium-webdriver": "^3.0.0", - "selenium-webdriver": "^3.0.1" - }, - "engines": { - "node": ">=6.9.x" + "ms": "^2.1.1" } }, - "node_modules/webdriver-manager": { - "version": "12.1.9", + "node_modules/saucelabs/node_modules/https-proxy-agent": { + "version": "2.2.4", "dev": true, "license": "MIT", "dependencies": { - "adm-zip": "^0.5.2", - "chalk": "^1.1.1", - "del": "^2.2.0", - "glob": "^7.0.3", - "ini": "^1.3.4", - "minimist": "^1.2.0", - "q": "^1.4.1", - "request": "^2.87.0", - "rimraf": "^2.5.2", - "semver": "^5.3.0", - "xml2js": "^0.4.17" - }, - "bin": { - "webdriver-manager": "bin/webdriver-manager" + "agent-base": "^4.3.0", + "debug": "^3.1.0" }, "engines": { - "node": ">=6.9.x" + "node": ">= 4.5.0" } }, - "node_modules/webdriver-manager/node_modules/ansi-regex": { - "version": "2.1.1", + "node_modules/sax": { + "version": "1.2.4", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "ISC" }, - "node_modules/webdriver-manager/node_modules/ansi-styles": { - "version": "2.2.1", + "node_modules/schema-utils": { + "version": "4.0.1", "dev": true, "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/webdriver-manager/node_modules/chalk": { - "version": "1.1.3", + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selenium-webdriver": { + "version": "3.6.0", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6.9.0" } }, - "node_modules/webdriver-manager/node_modules/glob": { + "node_modules/selenium-webdriver/node_modules/glob": { "version": "7.2.3", "dev": true, "license": "ISC", @@ -24549,12 +24633,7 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/webdriver-manager/node_modules/ini": { - "version": "1.3.8", - "dev": true, - "license": "ISC" - }, - "node_modules/webdriver-manager/node_modules/rimraf": { + "node_modules/selenium-webdriver/node_modules/rimraf": { "version": "2.7.1", "dev": true, "license": "ISC", @@ -24565,719 +24644,3441 @@ "rimraf": "bin.js" } }, - "node_modules/webdriver-manager/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/webdriver-manager/node_modules/strip-ansi": { - "version": "3.0.1", + "node_modules/selenium-webdriver/node_modules/tmp": { + "version": "0.0.30", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" + "os-tmpdir": "~1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4.0" } }, - "node_modules/webdriver-manager/node_modules/supports-color": { - "version": "2.0.0", + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, - "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, "engines": { - "node": ">=0.8.0" + "node": ">=10" } }, - "node_modules/webpack": { - "version": "5.89.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", - "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", - "dev": true, + "node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" + "lru-cache": "^6.0.0" }, "bin": { - "webpack": "bin/webpack.js" + "semver": "bin/semver.js" }, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "node": ">=10" } }, - "node_modules/webpack-dev-middleware": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.1.tgz", - "integrity": "sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==", - "dev": true, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.12", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } + "node": ">=10" } }, - "node_modules/webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dev": true, "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.13.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } + "node": ">= 0.8.0" } }, - "node_modules/webpack-dev-server/node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "engines": { - "node": ">=0.8" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "node": ">=4" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" + "ee-first": "1.1.1" }, "engines": { - "node": ">=10.0.0" + "node": ">= 0.8" } }, - "node_modules/webpack-sources": { - "version": "3.2.3", + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=10.13.0" + "node": ">= 0.8" } }, - "node_modules/webpack-subresource-integrity": { - "version": "5.1.0", + "node_modules/serialize-javascript": { + "version": "6.0.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", "dev": true, "license": "MIT", "dependencies": { - "typed-assert": "^1.0.8" + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" }, "engines": { - "node": ">= 12" - }, - "peerDependencies": { - "html-webpack-plugin": ">= 5.0.0-beta.1 < 6", - "webpack": "^5.12.0" - }, - "peerDependenciesMeta": { - "html-webpack-plugin": { - "optional": true - } + "node": ">= 0.8.0" } }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "ms": "2.0.0" } }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" }, "engines": { - "node": ">=8.0.0" + "node": ">= 0.6" } }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } + "license": "ISC" }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, + "license": "ISC" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">= 0.6" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" }, "engines": { - "node": ">=0.8.0" + "node": ">= 0.8.0" } }, - "node_modules/websocket-extensions": { - "version": "0.1.4", + "node_modules/server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==", + "dev": true + }, + "node_modules/set-blocking": { + "version": "2.0.0", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=0.8.0" - } + "license": "ISC" }, - "node_modules/which": { - "version": "2.0.2", - "license": "ISC", + "node_modules/set-value": { + "version": "2.0.1", + "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" }, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", + "node_modules/setimmediate": { + "version": "1.0.5", "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/which-module": { - "version": "2.0.1", + "node_modules/setprototypeof": { + "version": "1.2.0", "dev": true, "license": "ISC" }, - "node_modules/which-typed-array": { - "version": "1.1.9", + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, - "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "kind-of": "^6.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true + "node_modules/shebang-command": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/window-size": { - "version": "0.1.0", + "node_modules/shebang-regex": { + "version": "3.0.0", + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/with": { - "version": "5.1.1", + "node_modules/shell-quote": { + "version": "1.8.1", "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "acorn": "^3.1.0", - "acorn-globals": "^3.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/with/node_modules/acorn": { - "version": "3.3.0", + "node_modules/shelljs": { + "version": "0.3.0", "dev": true, - "license": "MIT", - "optional": true, + "license": "BSD*", "bin": { - "acorn": "bin/acorn" + "shjs": "bin/shjs" }, "engines": { - "node": ">=0.4.0" + "node": ">=0.8.0" } }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "license": "MIT", + "node_modules/showdown": { + "version": "1.3.0", + "license": "BSD-2-Clause", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" + "yargs": "^3.15.0" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "bin": { + "showdown": "bin/showdown.js" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/showdown/node_modules/ansi-regex": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/showdown/node_modules/camelcase": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/showdown/node_modules/cliui": { + "version": "3.2.0", + "license": "ISC", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/showdown/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/showdown/node_modules/string-width": { + "version": "1.0.2", + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/showdown/node_modules/strip-ansi": { + "version": "3.0.1", + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "ansi-regex": "^2.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=0.10.0" } }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "node_modules/showdown/node_modules/window-size": { + "version": "0.1.4", + "license": "MIT", + "bin": { + "window-size": "cli.js" + }, + "engines": { + "node": ">= 0.10.0" + } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/showdown/node_modules/wrap-ansi": { + "version": "2.1.0", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" + } + }, + "node_modules/showdown/node_modules/y18n": { + "version": "3.2.2", + "license": "ISC" + }, + "node_modules/showdown/node_modules/yargs": { + "version": "3.32.0", + "license": "MIT", + "dependencies": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", + "node_modules/sigmund": { + "version": "1.0.1", + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC" + }, + "node_modules/sigstore": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.1.0.tgz", + "integrity": "sha512-kPIj+ZLkyI3QaM0qX8V/nSsweYND3W448pwkDgS6CQ74MfhEkIR8ToK5Iyx46KJYRjseVcD3Rp9zAmUAj6ZjPw==", "dependencies": { - "color-name": "~1.1.4" + "@sigstore/bundle": "^2.1.0", + "@sigstore/protobuf-specs": "^0.2.1", + "@sigstore/sign": "^2.1.0", + "@sigstore/tuf": "^2.1.0" }, "engines": { - "node": ">=7.0.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", + "node_modules/simple-fmt": { + "version": "0.1.0", + "dev": true, "license": "MIT" }, - "node_modules/wrappy": { - "version": "1.0.2", + "node_modules/simple-is": { + "version": "0.2.0", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/ws": { - "version": "8.11.0", + "node_modules/slash": { + "version": "3.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node": ">=8" } }, - "node_modules/xml2js": { - "version": "0.4.23", + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", "dev": true, "license": "MIT", "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, "engines": { - "node": ">=4.0.0" + "node": ">=0.10.0" } }, - "node_modules/xmlbuilder": { - "version": "11.0.1", + "node_modules/snapdragon-node": { + "version": "2.1.1", "dev": true, "license": "MIT", + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, "engines": { - "node": ">=4.0" + "node": ">=0.10.0" } }, - "node_modules/xmlhttprequest-ssl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", - "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^1.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/xregexp": { - "version": "3.1.0", + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", "dev": true, - "license": "MIT" - }, - "node_modules/y18n": { - "version": "5.0.8", - "license": "ISC", + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.0" + }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/yaml": { - "version": "1.10.2", + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "node_modules/snapdragon-util": { + "version": "3.0.1", + "dev": true, + "license": "MIT", "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "kind-of": "^3.2.0" }, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/yargs-parser": { - "version": "20.2.9", + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "license": "ISC", + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/yn": { - "version": "3.1.1", + "node_modules/socket.io": { + "version": "4.6.1", "dev": true, "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.4.1", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" + }, "engines": { - "node": ">=6" + "node": ">=10.0.0" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", + "node_modules/socket.io-adapter": { + "version": "2.5.2", "dev": true, "license": "MIT", + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-client": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz", + "integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==", + "dev": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + }, "engines": { - "node": ">=10" + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/zlib-browserify": { - "version": "0.0.1", - "license": "MIT" + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } }, - "node_modules/zone.js": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.2.tgz", - "integrity": "sha512-X4U7J1isDhoOmHmFWiLhloWc2lzMkdnumtfQ1LXzf/IOZp5NQYuMUTaviVzG/q1ugMBIXzin2AqeVJUoSEkNyQ==", + "node_modules/sockjs/node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, "dependencies": { - "tslib": "^2.3.0" + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" } - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true }, - "@alloc/quick-lru": { - "version": "5.2.0", - "dev": true + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } }, - "@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks/node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, - "@angular-devkit/architect": { - "version": "0.1700.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1700.1.tgz", - "integrity": "sha512-w84luzQNRjlt7XxX3+jyzcwBBv3gAjjvFWTjN1E5mlpDCUXgYmQ3CMowFHeu0U06HD5Sapap9p2l6GoajuZK5Q==", - "requires": { - "@angular-devkit/core": "17.0.1", - "rxjs": "7.8.1" + "node_modules/source-map-loader": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, + "peerDependencies": { + "webpack": "^5.72.1" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "dev": true, + "license": "MIT", "dependencies": { - "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "requires": { - "tslib": "^2.1.0" - } - } + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, - "@angular-devkit/build-angular": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.0.1.tgz", - "integrity": "sha512-OomGAeBg/OOxzPpoU7EkdD3WwhKip+0Giy/cGtkalSgQ5vWTuZhf8UnxwTf7xEXW5LtvfoTtv7sKmb1dJT7FzA==", + "node_modules/source-map-support": { + "version": "0.5.21", "dev": true, - "requires": { - "@ampproject/remapping": "2.2.1", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/spawn-command": { + "version": "0.0.2-1", + "dev": true, + "license": "MIT" + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "license": "CC0-1.0" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "dev": true, + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.2", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/sshpk": { + "version": "1.17.0", + "dev": true, + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "dev": true, + "license": "MIT" + }, + "node_modules/static-extend": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-throttle": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", + "integrity": "sha512-889+B9vN9dq7/vLbGyuHeZ6/ctf5sNuGWsDy89uNxkFTAgzy0eK7+w5fL3KLNRTkLle7EgZGvHUphZW0Q26MnQ==", + "dev": true, + "dependencies": { + "commander": "^2.2.0", + "limiter": "^1.0.5" + }, + "bin": { + "throttleproxy": "bin/throttleproxy.js" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/streamroller": { + "version": "3.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/fs-extra": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/streamroller/node_modules/jsonfile": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/streamroller/node_modules/universalify": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-template": { + "version": "0.2.1", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringmap": { + "version": "0.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/stringset": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strong-log-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", + "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "dev": true, + "dependencies": { + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" + }, + "bin": { + "sl-log-transformer": "bin/sl-log-transformer.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sucrase": { + "version": "3.32.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "7.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tailwindcss": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", + "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.12", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.18.2", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/arg": { + "version": "5.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/terser": { + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.5" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/through": { + "version": "2.3.8", + "dev": true, + "license": "MIT" + }, + "node_modules/through2": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "3.6.2", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/tiny-lr": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "body": "^5.1.0", + "debug": "^3.1.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.3.0", + "object-assign": "^4.1.0", + "qs": "^6.4.0" + } + }, + "node_modules/tiny-lr/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-regex/node_modules/define-property": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-data-descriptor": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-descriptor": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-extendable": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-stream": { + "version": "0.0.1", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tryor": { + "version": "0.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/ts-md5": { + "version": "1.3.1", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tuf-js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.1.0.tgz", + "integrity": "sha512-eD7YPPjVlMzdggrOeE8zwoegUaG/rt6Bt3jwoQPunRiNVzgcCE009UDFJKJjG+Gk9wFu6W/Vi+P5d/5QpdD9jA==", + "dependencies": { + "@tufjs/models": "2.0.0", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "dev": true, + "license": "Unlicense" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-assert": { + "version": "1.0.9", + "dev": true, + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ua-parser-js": { + "version": "1.0.37", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", + "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/uglify-js": { + "version": "2.7.5", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uglify-js/node_modules/async": { + "version": "0.2.10", + "dev": true, + "optional": true + }, + "node_modules/uglify-js/node_modules/camelcase": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uglify-js/node_modules/cliui": { + "version": "2.1.0", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "node_modules/uglify-js/node_modules/source-map": { + "version": "0.5.7", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uglify-js/node_modules/wordwrap": { + "version": "0.0.2", + "dev": true, + "license": "MIT/X11", + "optional": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/uglify-js/node_modules/yargs": { + "version": "3.10.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + }, + "node_modules/uglify-to-browserify": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/underscore": { + "version": "1.13.6", + "dev": true, + "license": "MIT" + }, + "node_modules/underscore.string": { + "version": "2.3.3", + "engines": { + "node": "*" + } + }, + "node_modules/undici": { + "version": "5.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", + "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/upper-case": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-path": { + "version": "1.0.0", + "dev": true, + "license": "WTFPL OR MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/use": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/v8flags": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", + "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", + "dev": true, + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/void-elements": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webdriver-js-extender": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/webdriver-manager": { + "version": "12.1.9", + "dev": true, + "license": "MIT", + "dependencies": { + "adm-zip": "^0.5.2", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + }, + "bin": { + "webdriver-manager": "bin/webdriver-manager" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/webdriver-manager/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/ansi-styles": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/chalk": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/glob": { + "version": "7.2.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/webdriver-manager/node_modules/ini": { + "version": "1.3.8", + "dev": true, + "license": "ISC" + }, + "node_modules/webdriver-manager/node_modules/rimraf": { + "version": "2.7.1", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/webdriver-manager/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/webdriver-manager/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/supports-color": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/webpack": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.1.tgz", + "integrity": "sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.14.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", + "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-subresource-integrity": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "typed-assert": "^1.0.8" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "html-webpack-plugin": ">= 5.0.0-beta.1 < 6", + "webpack": "^5.12.0" + }, + "peerDependenciesMeta": { + "html-webpack-plugin": { + "optional": true + } + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/window-size": { + "version": "0.1.0", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/with": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "acorn": "^3.1.0", + "acorn-globals": "^3.0.0" + } + }, + "node_modules/with/node_modules/acorn": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.11.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xregexp": { + "version": "3.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/y18n": { + "version": "5.0.8", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zlib-browserify": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/zone.js": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.2.tgz", + "integrity": "sha512-X4U7J1isDhoOmHmFWiLhloWc2lzMkdnumtfQ1LXzf/IOZp5NQYuMUTaviVzG/q1ugMBIXzin2AqeVJUoSEkNyQ==", + "dependencies": { + "tslib": "^2.3.0" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@alloc/quick-lru": { + "version": "5.2.0", + "dev": true + }, + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@angular-devkit/architect": { + "version": "0.1700.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1700.1.tgz", + "integrity": "sha512-w84luzQNRjlt7XxX3+jyzcwBBv3gAjjvFWTjN1E5mlpDCUXgYmQ3CMowFHeu0U06HD5Sapap9p2l6GoajuZK5Q==", + "requires": { + "@angular-devkit/core": "17.0.1", + "rxjs": "7.8.1" + }, + "dependencies": { + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "requires": { + "tslib": "^2.1.0" + } + } + } + }, + "@angular-devkit/build-angular": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.0.1.tgz", + "integrity": "sha512-OomGAeBg/OOxzPpoU7EkdD3WwhKip+0Giy/cGtkalSgQ5vWTuZhf8UnxwTf7xEXW5LtvfoTtv7sKmb1dJT7FzA==", + "dev": true, + "requires": { + "@ampproject/remapping": "2.2.1", "@angular-devkit/architect": "0.1700.1", "@angular-devkit/build-webpack": "0.1700.1", "@angular-devkit/core": "17.0.1", @@ -26327,8 +29128,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "requires": {} + "dev": true }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -28707,8 +31507,7 @@ "version": "17.0.1", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.0.1.tgz", "integrity": "sha512-IfiWIBY1GntfJFV/U1CSOHZ7zF5p0zFMFzux7/iGXUXit299LTdJ5mZTe9++lFcH6dPHgEPWlinuYAfzorY4ng==", - "dev": true, - "requires": {} + "dev": true }, "@nodelib/fs.scandir": { "version": "2.1.5", @@ -29055,6 +31854,28 @@ "version": "3.1.0", "dev": true }, + "@swimlane/ngx-charts": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@swimlane/ngx-charts/-/ngx-charts-20.5.0.tgz", + "integrity": "sha512-PNBIHdu/R3ceD7jnw1uCBVOj4k3T6IxfdW6xsDsglGkZyoWMEEq4tLoEurjLEKzmDtRv9c35kVNOXy0lkOuXeA==", + "requires": { + "d3-array": "^3.1.1", + "d3-brush": "^3.0.0", + "d3-color": "^3.1.0", + "d3-ease": "^3.0.1", + "d3-format": "^3.1.0", + "d3-hierarchy": "^3.1.0", + "d3-interpolate": "^3.0.1", + "d3-sankey": "^0.12.3", + "d3-scale": "^4.0.2", + "d3-selection": "^3.0.0", + "d3-shape": "^3.2.0", + "d3-time-format": "^3.0.0", + "d3-transition": "^3.0.1", + "rfdc": "^1.3.0", + "tslib": "^2.0.0" + } + }, "@tsconfig/node10": { "version": "1.0.9", "dev": true @@ -29586,15 +32407,13 @@ } }, "@uirouter/angularjs": { - "version": "1.1.0", - "requires": {} + "version": "1.1.0" }, "@uirouter/core": { "version": "6.1.0" }, "@uirouter/rx": { - "version": "1.0.0", - "requires": {} + "version": "1.0.0" }, "@ungap/structured-clone": { "version": "1.2.0", @@ -29606,8 +32425,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.0.1.tgz", "integrity": "sha512-pcub+YbFtFhaGRTo1832FQHQSHvMrlb43974e2eS8EKleR3p1cDdkJFPci1UhwkEf1J9Bz+wKBSzqpKp7nNj2A==", - "dev": true, - "requires": {} + "dev": true }, "@webassemblyjs/ast": { "version": "1.11.6", @@ -29839,15 +32657,13 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "requires": {} + "dev": true }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "acorn-walk": { "version": "8.2.0", @@ -30068,16 +32884,13 @@ } }, "grunt-contrib-clean": { - "version": "0.4.1", - "requires": {} + "version": "0.4.1" }, "grunt-contrib-concat": { - "version": "0.3.0", - "requires": {} + "version": "0.3.0" }, "grunt-contrib-copy": { - "version": "0.4.1", - "requires": {} + "version": "0.4.1" }, "grunt-contrib-uglify": { "version": "0.2.7", @@ -30239,8 +33052,7 @@ "version": "1.5.11" }, "angular-ui-bootstrap": { - "version": "0.13.4", - "requires": {} + "version": "0.13.4" }, "angular-ui-codemirror": { "version": "0.3.0" @@ -30255,8 +33067,7 @@ "version": "1.0.3" }, "angulartics-google-analytics": { - "version": "0.1.4", - "requires": {} + "version": "0.1.4" }, "ansi-colors": { "version": "4.1.3" @@ -30291,7 +33102,7 @@ }, "anymatch": { "version": "3.1.3", - "devOptional": true, + "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -30763,7 +33574,7 @@ }, "binary-extensions": { "version": "2.2.0", - "devOptional": true + "dev": true }, "bindings": { "version": "1.5.0", @@ -30925,7 +33736,7 @@ }, "braces": { "version": "3.0.2", - "devOptional": true, + "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -31467,7 +34278,7 @@ }, "chokidar": { "version": "3.5.3", - "devOptional": true, + "dev": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -32153,6 +34964,191 @@ "d3": { "version": "3.5.17" }, + "d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "requires": { + "internmap": "1 - 2" + } + }, + "d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + } + }, + "d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" + }, + "d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==" + }, + "d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + } + }, + "d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==" + }, + "d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==" + }, + "d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==" + }, + "d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "requires": { + "d3-color": "1 - 3" + } + }, + "d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==" + }, + "d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "requires": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + }, + "dependencies": { + "d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "requires": { + "internmap": "^1.0.0" + } + }, + "d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + }, + "d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "requires": { + "d3-path": "1" + } + }, + "internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" + } + } + }, + "d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "requires": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + } + }, + "d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==" + }, + "d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "requires": { + "d3-path": "^3.1.0" + } + }, + "d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "requires": { + "d3-array": "2 - 3" + } + }, + "d3-time-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", + "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", + "requires": { + "d3-time": "1 - 2" + }, + "dependencies": { + "d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "requires": { + "internmap": "^1.0.0" + } + }, + "d3-time": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz", + "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==", + "requires": { + "d3-array": "2" + } + }, + "internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" + } + } + }, + "d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==" + }, + "d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "requires": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + } + }, "dargs": { "version": "7.0.0", "dev": true @@ -33061,8 +36057,7 @@ }, "eslint-config-prettier": { "version": "8.8.0", - "dev": true, - "requires": {} + "dev": true }, "eslint-import-resolver-node": { "version": "0.3.7", @@ -33158,8 +36153,7 @@ }, "eslint-plugin-prefer-arrow": { "version": "1.2.3", - "dev": true, - "requires": {} + "dev": true }, "eslint-plugin-prettier": { "version": "5.0.1", @@ -33661,7 +36655,7 @@ }, "fill-range": { "version": "7.0.1", - "devOptional": true, + "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -33885,310 +36879,913 @@ "functions-have-names": "^1.2.2" } }, - "functions-have-names": { - "version": "1.2.3", - "dev": true - }, - "gaze": { - "version": "1.1.3", + "functions-have-names": { + "version": "1.2.3", + "dev": true + }, + "gaze": { + "version": "1.1.3", + "dev": true, + "requires": { + "globule": "^1.0.0" + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5" + }, + "get-intrinsic": { + "version": "1.2.0", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-package-type": { + "version": "0.1.0", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "dev": true + }, + "get-symbol-description": { + "version": "1.0.0", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "get-value": { + "version": "2.0.6", + "dev": true + }, + "getobject": { + "version": "1.0.2", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "git-raw-commits": { + "version": "2.0.11", + "dev": true, + "requires": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "dev": true + }, + "global-dirs": { + "version": "0.1.1", + "dev": true, + "requires": { + "ini": "^1.3.4" + }, + "dependencies": { + "ini": { + "version": "1.3.8", + "dev": true + } + } + }, + "global-modules": { + "version": "1.0.0", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "dependencies": { + "ini": { + "version": "1.3.8", + "dev": true + }, + "which": { + "version": "1.3.1", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globalthis": { + "version": "1.0.3", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "11.1.0", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "globule": { + "version": "1.3.4", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "^4.17.21", + "minimatch": "~3.0.2" + }, + "dependencies": { + "glob": { + "version": "7.1.7", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.8", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "gopd": { + "version": "1.0.1", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "graceful-fs": { + "version": "4.2.11" + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "grunt": { + "version": "1.6.1", + "dev": true, + "requires": { + "dateformat": "~4.6.2", + "eventemitter2": "~0.4.13", + "exit": "~0.1.2", + "findup-sync": "~5.0.0", + "glob": "~7.1.6", + "grunt-cli": "~1.4.3", + "grunt-known-options": "~2.0.0", + "grunt-legacy-log": "~3.0.0", + "grunt-legacy-util": "~2.0.1", + "iconv-lite": "~0.6.3", + "js-yaml": "~3.14.0", + "minimatch": "~3.0.4", + "nopt": "~3.0.6" + }, + "dependencies": { + "glob": { + "version": "7.1.7", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.8", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "grunt-bump": { + "version": "0.8.0", + "dev": true, + "requires": { + "semver": "^5.1.0" + }, + "dependencies": { + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + } + } + }, + "grunt-cli": { + "version": "1.4.3", + "dev": true, + "requires": { + "grunt-known-options": "~2.0.0", + "interpret": "~1.1.0", + "liftup": "~3.0.1", + "nopt": "~4.0.1", + "v8flags": "~3.2.0" + }, + "dependencies": { + "nopt": { + "version": "4.0.3", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + } + } + }, + "grunt-coffeelint": { + "version": "0.0.16", + "dev": true, + "requires": { + "coffeelint": "^1", + "coffeelint-stylish": "~0.1.0" + } + }, + "grunt-contrib-clean": { + "version": "1.0.0", + "dev": true, + "requires": { + "async": "^1.5.2", + "rimraf": "^2.5.1" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "grunt-contrib-coffee": { + "version": "1.0.0", "dev": true, "requires": { - "globule": "^1.0.0" - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5" - }, - "get-intrinsic": { - "version": "1.2.0", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "chalk": "~1.0.0", + "coffee-script": "~1.10.0", + "lodash": "~4.3.0", + "uri-path": "~1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "chalk": { + "version": "1.0.0", + "dev": true, + "requires": { + "ansi-styles": "^2.0.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^1.0.3", + "strip-ansi": "^2.0.1", + "supports-color": "^1.3.0" + } + }, + "coffee-script": { + "version": "1.10.0", + "dev": true + }, + "has-ansi": { + "version": "1.0.3", + "dev": true, + "requires": { + "ansi-regex": "^1.1.0", + "get-stdin": "^4.0.1" + } + }, + "lodash": { + "version": "4.3.0", + "dev": true + }, + "strip-ansi": { + "version": "2.0.1", + "dev": true, + "requires": { + "ansi-regex": "^1.0.0" + } + }, + "supports-color": { + "version": "1.3.1", + "dev": true + } } }, - "get-package-type": { - "version": "0.1.0", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "dev": true - }, - "get-symbol-description": { - "version": "1.0.0", + "grunt-contrib-concat": { + "version": "1.0.1", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "chalk": "^1.0.0", + "source-map": "^0.5.3" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "dev": true + } } }, - "get-value": { - "version": "2.0.6", - "dev": true - }, - "getobject": { + "grunt-contrib-connect": { "version": "1.0.2", - "dev": true - }, - "getpass": { - "version": "0.1.7", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "async": "^1.5.2", + "connect": "^3.4.0", + "connect-livereload": "^0.5.0", + "http2": "^3.3.4", + "morgan": "^1.6.1", + "opn": "^4.0.0", + "portscanner": "^1.0.0", + "serve-index": "^1.7.1", + "serve-static": "^1.10.0" + }, + "dependencies": { + "opn": { + "version": "4.0.2", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "portscanner": { + "version": "1.2.0", + "dev": true, + "requires": { + "async": "1.5.2" + } + } } }, - "git-raw-commits": { - "version": "2.0.11", + "grunt-contrib-copy": { + "version": "1.0.0", "dev": true, "requires": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" + "chalk": "^1.1.1", + "file-sync-cmp": "^0.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "dev": true + } } }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "grunt-contrib-jshint": { + "version": "1.0.0", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "chalk": "^1.1.1", + "hooker": "^0.2.3", + "jshint": "~2.9.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "dev": true + } } }, - "glob-parent": { - "version": "5.1.2", - "devOptional": true, + "grunt-contrib-watch": { + "version": "1.1.0", + "dev": true, "requires": { - "is-glob": "^4.0.1" + "async": "^2.6.0", + "gaze": "^1.1.0", + "lodash": "^4.17.10", + "tiny-lr": "^1.1.1" + }, + "dependencies": { + "async": { + "version": "2.6.4", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + } } }, - "glob-to-regexp": { - "version": "0.4.1", - "dev": true - }, - "global-dirs": { - "version": "0.1.1", + "grunt-env": { + "version": "0.4.4", "dev": true, "requires": { - "ini": "^1.3.4" + "ini": "~1.3.0", + "lodash": "~2.4.1" }, "dependencies": { "ini": { "version": "1.3.8", "dev": true + }, + "lodash": { + "version": "2.4.2", + "dev": true } } }, - "global-modules": { - "version": "1.0.0", + "grunt-html2js": { + "version": "0.6.0", "dev": true, "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "chokidar": "^2", + "html-minifier": "^3", + "pug": "^2" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "dev": true + }, + "braces": { + "version": "2.3.2", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "chokidar": { + "version": "2.1.8", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "define-property": { + "version": "2.0.2", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "fill-range": { + "version": "4.0.0", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-binary-path": { + "version": "1.0.1", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extendable": { + "version": "1.0.1", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-number": { + "version": "3.0.0", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + } + } + }, + "readdirp": { + "version": "2.2.1", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } } }, - "global-prefix": { - "version": "1.0.2", + "grunt-karma": { + "version": "2.0.0", "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "lodash": "^3.10.1" }, "dependencies": { - "ini": { - "version": "1.3.8", + "lodash": { + "version": "3.10.1", "dev": true - }, - "which": { - "version": "1.3.1", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "grunt-known-options": { + "version": "2.0.0", "dev": true }, - "globalthis": { - "version": "1.0.3", - "dev": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "globby": { - "version": "11.1.0", + "grunt-legacy-log": { + "version": "3.0.0", "dev": true, "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "colors": "~1.1.2", + "grunt-legacy-log-utils": "~2.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.19" } }, - "globule": { - "version": "1.3.4", + "grunt-legacy-log-utils": { + "version": "2.1.0", "dev": true, "requires": { - "glob": "~7.1.1", - "lodash": "^4.17.21", - "minimatch": "~3.0.2" + "chalk": "~4.1.0", + "lodash": "~4.17.19" }, "dependencies": { - "glob": { - "version": "7.1.7", + "ansi-styles": { + "version": "4.3.0", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "color-convert": "^2.0.1" } }, - "minimatch": { - "version": "3.0.8", + "chalk": { + "version": "4.1.2", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } - } - } - }, - "gopd": { - "version": "1.0.1", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.11" - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "grunt": { - "version": "1.6.1", - "dev": true, - "requires": { - "dateformat": "~4.6.2", - "eventemitter2": "~0.4.13", - "exit": "~0.1.2", - "findup-sync": "~5.0.0", - "glob": "~7.1.6", - "grunt-cli": "~1.4.3", - "grunt-known-options": "~2.0.0", - "grunt-legacy-log": "~3.0.0", - "grunt-legacy-util": "~2.0.1", - "iconv-lite": "~0.6.3", - "js-yaml": "~3.14.0", - "minimatch": "~3.0.4", - "nopt": "~3.0.6" - }, - "dependencies": { - "glob": { - "version": "7.1.7", + }, + "color-convert": { + "version": "2.0.1", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "color-name": "~1.1.4" } }, - "minimatch": { - "version": "3.0.8", + "color-name": { + "version": "1.1.4", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "7.2.0", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "has-flag": "^4.0.0" } } } }, - "grunt-bump": { - "version": "0.8.0", + "grunt-legacy-util": { + "version": "2.0.1", "dev": true, "requires": { - "semver": "^5.1.0" + "async": "~3.2.0", + "exit": "~0.1.2", + "getobject": "~1.0.0", + "hooker": "~0.2.3", + "lodash": "~4.17.21", + "underscore.string": "~3.3.5", + "which": "~2.0.2" }, "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "async": { + "version": "3.2.4", "dev": true - } - } - }, - "grunt-cli": { - "version": "1.4.3", - "dev": true, - "requires": { - "grunt-known-options": "~2.0.0", - "interpret": "~1.1.0", - "liftup": "~3.0.1", - "nopt": "~4.0.1", - "v8flags": "~3.2.0" - }, - "dependencies": { - "nopt": { - "version": "4.0.3", + }, + "sprintf-js": { + "version": "1.1.2", + "dev": true + }, + "underscore.string": { + "version": "3.3.6", "dev": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "sprintf-js": "^1.1.1", + "util-deprecate": "^1.0.2" } } } }, - "grunt-coffeelint": { - "version": "0.0.16", - "dev": true, + "grunt-lib-contrib": { + "version": "0.6.1", "requires": { - "coffeelint": "^1", - "coffeelint-stylish": "~0.1.0" + "zlib-browserify": "0.0.1" } }, - "grunt-contrib-clean": { - "version": "1.0.0", + "grunt-newer": { + "version": "1.3.0", "dev": true, "requires": { "async": "^1.5.2", - "rimraf": "^2.5.1" + "rimraf": "^2.5.2" }, "dependencies": { "glob": { @@ -34212,1265 +37809,1347 @@ } } }, - "grunt-contrib-coffee": { - "version": "1.0.0", + "grunt-ng-annotate": { + "version": "3.0.0", "dev": true, "requires": { - "chalk": "~1.0.0", - "coffee-script": "~1.10.0", - "lodash": "~4.3.0", - "uri-path": "~1.0.0" + "lodash.clonedeep": "^4.5.0", + "ng-annotate": "^1.2.1" + } + }, + "grunt-postcss": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/grunt-postcss/-/grunt-postcss-0.8.0.tgz", + "integrity": "sha512-Y/GlBwlSXET86uudGM6Sn5Qtjas5PT2AwjMGqKNnSaoxJSfhNY4chpAnOs72VQ4y3LqrP0y5f/i7CroyZqsuJA==", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "diff": "^2.0.2", + "postcss": "^5.0.0" }, "dependencies": { "ansi-regex": { - "version": "1.1.1", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true }, "ansi-styles": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true }, "chalk": { - "version": "1.0.0", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, "requires": { - "ansi-styles": "^2.0.1", + "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", - "has-ansi": "^1.0.3", - "strip-ansi": "^2.0.1", - "supports-color": "^1.3.0" + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, - "coffee-script": { - "version": "1.10.0", + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", "dev": true }, - "has-ansi": { - "version": "1.0.3", + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "ansi-regex": "^1.1.0", - "get-stdin": "^4.0.1" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + }, + "dependencies": { + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } } }, - "lodash": { - "version": "4.3.0", + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true }, "strip-ansi": { - "version": "2.0.1", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, "requires": { - "ansi-regex": "^1.0.0" + "ansi-regex": "^2.0.0" } }, "supports-color": { - "version": "1.3.1", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true } } }, - "grunt-contrib-concat": { - "version": "1.0.1", + "grunt-preprocess": { + "version": "5.1.0", "dev": true, "requires": { - "chalk": "^1.0.0", - "source-map": "^0.5.3" + "lodash": "^4.5.0", + "preprocess": "^3.0.2" + } + }, + "grunt-sass": { + "version": "3.1.0", + "dev": true + }, + "grunt-sass-globbing": { + "version": "1.5.1", + "dev": true + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "dev": true - }, - "chalk": { - "version": "1.1.3", + "ajv": { + "version": "6.12.6", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "source-map": { - "version": "0.5.7", + "json-schema-traverse": { + "version": "0.4.1", "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", + } + } + }, + "hard-rejection": { + "version": "2.1.0", + "dev": true + }, + "has": { + "version": "1.0.3", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", "dev": true } } }, - "grunt-contrib-connect": { + "has-bigints": { "version": "1.0.2", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.0", "dev": true, "requires": { - "async": "^1.5.2", - "connect": "^3.4.0", - "connect-livereload": "^0.5.0", - "http2": "^3.3.4", - "morgan": "^1.6.1", - "opn": "^4.0.0", - "portscanner": "^1.0.0", - "serve-index": "^1.7.1", - "serve-static": "^1.10.0" + "get-intrinsic": "^1.1.1" + } + }, + "has-proto": { + "version": "1.0.1", + "dev": true + }, + "has-symbols": { + "version": "1.0.3" + }, + "has-tostringtag": { + "version": "1.0.0", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "has-value": { + "version": "1.0.0", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { - "opn": { - "version": "4.0.2", + "is-number": { + "version": "3.0.0", "dev": true, "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, - "portscanner": { - "version": "1.2.0", + "kind-of": { + "version": "4.0.0", "dev": true, "requires": { - "async": "1.5.2" + "is-buffer": "^1.1.5" } } } }, - "grunt-contrib-copy": { - "version": "1.0.0", + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "hdr-histogram-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", + "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", + "dev": true, + "requires": { + "@assemblyscript/loader": "^0.10.1", + "base64-js": "^1.2.0", + "pako": "^1.0.3" + } + }, + "hdr-histogram-percentiles-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", + "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", + "dev": true + }, + "he": { + "version": "1.2.0", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hooker": { + "version": "0.2.3" + }, + "hosted-git-info": { + "version": "2.8.9", + "dev": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-entities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "dev": true + }, + "html-minifier": { + "version": "3.5.21", "dev": true, "requires": { - "chalk": "^1.1.1", - "file-sync-cmp": "^0.1.0" + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", + "commander": { + "version": "2.17.1", "dev": true }, - "ansi-styles": { - "version": "2.2.1", + "source-map": { + "version": "0.6.1", "dev": true }, - "chalk": { - "version": "1.1.3", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", + "uglify-js": { + "version": "3.4.10", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "dev": true + } } - }, - "supports-color": { - "version": "2.0.0", - "dev": true } } }, - "grunt-contrib-jshint": { - "version": "1.0.0", + "htmlparser2": { + "version": "3.8.3", "dev": true, "requires": { - "chalk": "^1.1.1", - "hooker": "^0.2.3", - "jshint": "~2.9.1" + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "dev": true + "dom-serializer": { + "version": "0.2.2", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.3.0", + "dev": true + }, + "entities": { + "version": "2.2.0", + "dev": true + } + } }, - "ansi-styles": { - "version": "2.2.1", + "domelementtype": { + "version": "1.3.1", "dev": true }, - "chalk": { - "version": "1.1.3", + "domhandler": { + "version": "2.3.0", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "domelementtype": "1" } }, - "strip-ansi": { - "version": "3.0.1", + "domutils": { + "version": "1.5.1", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "dom-serializer": "0", + "domelementtype": "1" } }, - "supports-color": { - "version": "2.0.0", + "entities": { + "version": "1.0.0", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", "dev": true } } }, - "grunt-contrib-watch": { - "version": "1.1.0", + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", "dev": true, "requires": { - "async": "^2.6.0", - "gaze": "^1.1.0", - "lodash": "^4.17.10", - "tiny-lr": "^1.1.1" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "dependencies": { - "async": { - "version": "2.6.4", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } + "statuses": { + "version": "2.0.1", + "dev": true } } }, - "grunt-env": { - "version": "0.4.4", + "http-parser-js": { + "version": "0.5.8", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", "dev": true, "requires": { - "ini": "~1.3.0", - "lodash": "~2.4.1" + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, + "http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "requires": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" }, "dependencies": { - "ini": { - "version": "1.3.8", - "dev": true - }, - "lodash": { - "version": "2.4.2", + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true } } }, - "grunt-html2js": { - "version": "0.6.0", + "http-signature": { + "version": "1.2.0", "dev": true, "requires": { - "chokidar": "^2", - "html-minifier": "^3", - "pug": "^2" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "http2": { + "version": "3.3.7", + "dev": true + }, + "https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } + }, + "human-signals": { + "version": "2.1.0", + "dev": true + }, + "husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true + }, + "iconv-lite": { + "version": "0.6.3", + "devOptional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true + }, + "ieee754": { + "version": "1.2.1" + }, + "ignore": { + "version": "5.2.4", + "dev": true + }, + "ignore-walk": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz", + "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==", + "requires": { + "minimatch": "^9.0.0" }, "dependencies": { - "anymatch": { - "version": "2.0.0", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "binary-extensions": { - "version": "1.13.1", - "dev": true - }, - "braces": { - "version": "2.3.2", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "chokidar": { - "version": "2.1.8", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "define-property": { - "version": "2.0.2", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "fill-range": { - "version": "4.0.0", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "glob-parent": { - "version": "3.1.0", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-binary-path": { - "version": "1.0.1", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-number": { - "version": "3.0.0", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - } - } - }, - "readdirp": { - "version": "2.2.1", - "dev": true, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "balanced-match": "^1.0.0" } }, - "to-regex-range": { - "version": "2.1.1", - "dev": true, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "brace-expansion": "^2.0.1" } } } }, - "grunt-karma": { - "version": "2.0.0", + "image-size": { + "version": "0.5.5", + "dev": true, + "optional": true + }, + "immediate": { + "version": "3.0.6", + "dev": true + }, + "immutable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", + "integrity": "sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", "dev": true, "requires": { - "lodash": "^3.10.1" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "dependencies": { - "lodash": { - "version": "3.10.1", + "resolve-from": { + "version": "4.0.0", "dev": true } } }, - "grunt-known-options": { - "version": "2.0.0", - "dev": true + "imurmurhash": { + "version": "0.1.4" }, - "grunt-legacy-log": { - "version": "3.0.0", - "dev": true, - "requires": { - "colors": "~1.1.2", - "grunt-legacy-log-utils": "~2.1.0", - "hooker": "~0.2.3", - "lodash": "~4.17.19" + "indent-string": { + "version": "4.0.0" + }, + "inflight": { + "version": "1.0.6", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" } }, - "grunt-legacy-log-utils": { - "version": "2.1.0", - "dev": true, + "inherits": { + "version": "2.0.4" + }, + "ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==" + }, + "inquirer": { + "version": "9.2.11", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.11.tgz", + "integrity": "sha512-B2LafrnnhbRzCWfAdOXisUzL89Kg8cVJlYmhqoi3flSiV/TveO+nsXwgKr9h9PIo+J1hz7nBSk6gegRIMBBf7g==", "requires": { - "chalk": "~4.1.0", - "lodash": "~4.17.19" + "@ljharb/through": "^2.3.9", + "ansi-escapes": "^4.3.2", + "chalk": "^5.3.0", + "cli-cursor": "^3.1.0", + "cli-width": "^4.1.0", + "external-editor": "^3.1.0", + "figures": "^5.0.0", + "lodash": "^4.17.21", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" }, "dependencies": { "ansi-styles": { "version": "4.3.0", - "dev": true, + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { "color-convert": "^2.0.1" } }, "chalk": { - "version": "4.1.2", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==" }, "color-convert": { "version": "2.0.1", - "dev": true, + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "requires": { "color-name": "~1.1.4" } }, "color-name": { "version": "1.1.4", - "dev": true + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "has-flag": { - "version": "4.0.0", - "dev": true + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "requires": { + "tslib": "^2.1.0" + } }, - "supports-color": { - "version": "7.2.0", - "dev": true, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "requires": { - "has-flag": "^4.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } } } }, - "grunt-legacy-util": { - "version": "2.0.1", + "internal-slot": { + "version": "1.0.5", "dev": true, "requires": { - "async": "~3.2.0", - "exit": "~0.1.2", - "getobject": "~1.0.0", - "hooker": "~0.2.3", - "lodash": "~4.17.21", - "underscore.string": "~3.3.5", - "which": "~2.0.2" - }, - "dependencies": { - "async": { - "version": "3.2.4", - "dev": true - }, - "sprintf-js": { - "version": "1.1.2", - "dev": true - }, - "underscore.string": { - "version": "3.3.6", - "dev": true, - "requires": { - "sprintf-js": "^1.1.1", - "util-deprecate": "^1.0.2" - } - } + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" } }, - "grunt-lib-contrib": { - "version": "0.6.1", + "internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" + }, + "interpret": { + "version": "1.1.0", + "dev": true + }, + "invert-kv": { + "version": "1.0.0" + }, + "ip": { + "version": "1.1.8", + "dev": true + }, + "ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "dev": true, "requires": { - "zlib-browserify": "0.0.1" + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" } }, - "grunt-newer": { - "version": "1.3.0", + "is-accessor-descriptor": { + "version": "0.1.6", "dev": true, "requires": { - "async": "^1.5.2", - "rimraf": "^2.5.2" + "kind-of": "^3.0.2" }, "dependencies": { - "glob": { - "version": "7.2.3", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "rimraf": { - "version": "2.7.1", + "kind-of": { + "version": "3.2.2", "dev": true, "requires": { - "glob": "^7.1.3" + "is-buffer": "^1.1.5" } } } }, - "grunt-ng-annotate": { - "version": "3.0.0", + "is-array-buffer": { + "version": "3.0.2", "dev": true, "requires": { - "lodash.clonedeep": "^4.5.0", - "ng-annotate": "^1.2.1" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" } }, - "grunt-postcss": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/grunt-postcss/-/grunt-postcss-0.8.0.tgz", - "integrity": "sha512-Y/GlBwlSXET86uudGM6Sn5Qtjas5PT2AwjMGqKNnSaoxJSfhNY4chpAnOs72VQ4y3LqrP0y5f/i7CroyZqsuJA==", + "is-arrayish": { + "version": "0.2.1", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", "dev": true, "requires": { - "chalk": "^1.0.0", - "diff": "^2.0.2", - "postcss": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - }, - "dependencies": { - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true - } + "has-bigints": "^1.0.1" } }, - "grunt-preprocess": { - "version": "5.1.0", + "is-binary-path": { + "version": "2.1.0", "dev": true, "requires": { - "lodash": "^4.5.0", - "preprocess": "^3.0.2" + "binary-extensions": "^2.0.0" } }, - "grunt-sass": { - "version": "3.1.0", - "dev": true, - "requires": {} - }, - "grunt-sass-globbing": { - "version": "1.5.1", + "is-boolean-object": { + "version": "1.1.2", "dev": true, - "requires": {} + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "is-buffer": { + "version": "1.1.6", "dev": true }, - "har-schema": { - "version": "2.0.0", + "is-callable": { + "version": "1.2.7", "dev": true }, - "har-validator": { - "version": "5.1.5", + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "requires": { + "hasown": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", "dev": true, "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" + "kind-of": "^3.0.2" }, "dependencies": { - "ajv": { - "version": "6.12.6", + "kind-of": { + "version": "3.2.2", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "is-buffer": "^1.1.5" } - }, - "json-schema-traverse": { - "version": "0.4.1", - "dev": true } } }, - "hard-rejection": { - "version": "2.1.0", - "dev": true - }, - "has": { - "version": "1.0.3", + "is-date-object": { + "version": "1.0.5", + "dev": true, "requires": { - "function-bind": "^1.1.1" + "has-tostringtag": "^1.0.0" } }, - "has-ansi": { - "version": "2.0.0", + "is-descriptor": { + "version": "0.1.6", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", + "kind-of": { + "version": "5.1.0", "dev": true } } }, - "has-bigints": { - "version": "1.0.2", - "dev": true + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" }, - "has-flag": { + "is-expression": { "version": "3.0.0", + "dev": true, + "optional": true, + "requires": { + "acorn": "~4.0.2", + "object-assign": "^4.0.1" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "dev": true, + "optional": true + } + } + }, + "is-extendable": { + "version": "0.1.1", "dev": true }, - "has-property-descriptors": { + "is-extglob": { + "version": "2.1.1", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, + "is-glob": { + "version": "4.0.3", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-inside-container": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, "requires": { - "get-intrinsic": "^1.1.1" + "is-docker": "^3.0.0" + }, + "dependencies": { + "is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true + } } }, - "has-proto": { + "is-interactive": { + "version": "1.0.0" + }, + "is-lambda": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" + }, + "is-negative-zero": { + "version": "2.0.2", "dev": true }, - "has-symbols": { - "version": "1.0.3" + "is-number": { + "version": "7.0.0", + "dev": true }, - "has-tostringtag": { - "version": "1.0.0", + "is-number-like": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", + "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "lodash.isfinite": "^3.3.2" } }, - "has-value": { - "version": "1.0.0", + "is-number-object": { + "version": "1.0.7", "dev": true, "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "has-tostringtag": "^1.0.0" } }, - "has-values": { + "is-obj": { + "version": "2.0.0", + "dev": true + }, + "is-path-cwd": { "version": "1.0.0", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-path-inside": "^1.0.0" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", + "is-path-inside": { + "version": "1.0.1", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "path-is-inside": "^1.0.1" } } } }, - "hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "is-path-inside": { + "version": "3.0.3", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.2.2", + "dev": true, + "optional": true + }, + "is-regex": { + "version": "1.1.4", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-relative": { + "version": "1.0.0", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "2.0.1", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-text-path": { + "version": "1.0.1", + "dev": true, "requires": { - "function-bind": "^1.1.2" + "text-extensions": "^1.0.0" } }, - "hdr-histogram-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", - "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", + "is-typed-array": { + "version": "1.1.10", "dev": true, "requires": { - "@assemblyscript/loader": "^0.10.1", - "base64-js": "^1.2.0", - "pako": "^1.0.3" + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" } }, - "hdr-histogram-percentiles-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", - "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", + "is-typedarray": { + "version": "1.0.0", "dev": true }, - "he": { - "version": "1.2.0", - "dev": true + "is-unc-path": { + "version": "1.0.0", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } }, - "homedir-polyfill": { - "version": "1.0.3", + "is-unicode-supported": { + "version": "0.1.0" + }, + "is-weakref": { + "version": "1.0.2", "dev": true, "requires": { - "parse-passwd": "^1.0.0" + "call-bind": "^1.0.2" } }, - "hooker": { - "version": "0.2.3" + "is-what": { + "version": "3.14.1", + "dev": true }, - "hosted-git-info": { - "version": "2.8.9", + "is-windows": { + "version": "1.0.2", "dev": true }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" + "is-docker": "^2.0.0" } }, - "html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "isbinaryfile": { + "version": "4.0.10", "dev": true }, - "html-escaper": { - "version": "2.0.2", + "isexe": { + "version": "2.0.0" + }, + "isobject": { + "version": "3.0.1", "dev": true }, - "html-minifier": { - "version": "3.5.21", + "isstream": { + "version": "0.1.2", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "5.2.1", "dev": true, "requires": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "dependencies": { - "commander": { - "version": "2.17.1", + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true - }, - "source-map": { - "version": "0.6.1", + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", "dev": true }, - "uglify-js": { - "version": "3.4.10", + "supports-color": { + "version": "7.2.0", "dev": true, "requires": { - "commander": "~2.19.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "dev": true - } + "has-flag": "^4.0.0" } } } }, - "htmlparser2": { - "version": "3.8.3", + "istanbul-lib-source-maps": { + "version": "3.0.6", "dev": true, "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" }, "dependencies": { - "dom-serializer": { - "version": "0.2.2", + "glob": { + "version": "7.2.3", "dev": true, "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - }, - "dependencies": { - "domelementtype": { - "version": "2.3.0", - "dev": true - }, - "entities": { - "version": "2.2.0", - "dev": true - } + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "domelementtype": { - "version": "1.3.1", + "istanbul-lib-coverage": { + "version": "2.0.5", "dev": true }, - "domhandler": { - "version": "2.3.0", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", + "make-dir": { + "version": "2.1.0", "dev": true, "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "pify": "^4.0.1", + "semver": "^5.6.0" } }, - "entities": { - "version": "1.0.0", - "dev": true - }, - "isarray": { - "version": "0.0.1", + "pify": { + "version": "4.0.1", "dev": true }, - "readable-stream": { - "version": "1.1.14", + "rimraf": { + "version": "2.7.1", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "glob": "^7.1.3" } }, - "string_decoder": { - "version": "0.10.31", + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true - } - } - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "dependencies": { - "statuses": { - "version": "2.0.1", + }, + "source-map": { + "version": "0.6.1", "dev": true } } }, - "http-parser-js": { - "version": "0.5.8", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", + "istanbul-reports": { + "version": "3.1.5", "dev": true, "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" } }, - "http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" } }, - "http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", "dev": true, "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" }, "dependencies": { - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "http-signature": { - "version": "1.2.0", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "http2": { - "version": "3.3.7", - "dev": true - }, - "https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "dev": true - }, - "husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", - "dev": true - }, - "iconv-lite": { - "version": "0.6.3", - "devOptional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "jasmine": { + "version": "2.8.0", "dev": true, - "requires": {} - }, - "ieee754": { - "version": "1.2.1" - }, - "ignore": { - "version": "5.2.4", - "dev": true - }, - "ignore-walk": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz", - "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==", "requires": { - "minimatch": "^9.0.0" + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" }, "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "glob": { + "version": "7.2.3", + "dev": true, "requires": { - "balanced-match": "^1.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "requires": { - "brace-expansion": "^2.0.1" - } + "jasmine-core": { + "version": "2.8.0", + "dev": true } } }, - "image-size": { - "version": "0.5.5", - "dev": true, - "optional": true - }, - "immediate": { - "version": "3.0.6", - "dev": true - }, - "immutable": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", - "integrity": "sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==", + "jasmine-core": { + "version": "4.1.1", "dev": true }, - "import-fresh": { - "version": "3.3.0", + "jasmine-spec-reporter": { + "version": "5.0.2", "dev": true, "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "colors": "1.4.0" }, "dependencies": { - "resolve-from": { - "version": "4.0.0", + "colors": { + "version": "1.4.0", "dev": true } } }, - "imurmurhash": { - "version": "0.1.4" - }, - "indent-string": { - "version": "4.0.0" - }, - "inflight": { - "version": "1.0.6", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4" - }, - "ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==" - }, - "inquirer": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.11.tgz", - "integrity": "sha512-B2LafrnnhbRzCWfAdOXisUzL89Kg8cVJlYmhqoi3flSiV/TveO+nsXwgKr9h9PIo+J1hz7nBSk6gegRIMBBf7g==", - "requires": { - "@ljharb/through": "^2.3.9", - "ansi-escapes": "^4.3.2", - "chalk": "^5.3.0", - "cli-cursor": "^3.1.0", - "cli-width": "^4.1.0", - "external-editor": "^3.1.0", - "figures": "^5.0.0", - "lodash": "^4.17.21", - "mute-stream": "1.0.0", - "ora": "^5.4.1", - "run-async": "^3.0.0", - "rxjs": "^7.8.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0" + "jasminewd2": { + "version": "2.2.0", + "dev": true + }, + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "dependencies": { "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { "color-convert": "^2.0.1" } }, "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { "color-name": "~1.1.4" } @@ -35478,561 +39157,657 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "requires": { - "tslib": "^2.1.0" - } + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "has-flag": "^4.0.0" } } } }, - "internal-slot": { - "version": "1.0.5", + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", "dev": true, "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "interpret": { - "version": "1.1.0", + "jiti": { + "version": "1.18.2", "dev": true }, - "invert-kv": { - "version": "1.0.0" + "jquery": { + "version": "2.1.4" }, - "ip": { - "version": "1.1.8", + "js-base64": { + "version": "2.6.4", "dev": true }, - "ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "js-stringify": { + "version": "1.0.2", + "dev": true, + "optional": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "is-absolute": { - "version": "1.0.0", + "js-yaml": { + "version": "3.14.1", "dev": true, "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, - "is-accessor-descriptor": { - "version": "0.1.6", + "jsbn": { + "version": "0.1.1", + "dev": true + }, + "jsdoc-type-pratt-parser": { + "version": "3.1.0", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "jshint": { + "version": "2.9.7", "dev": true, "requires": { - "kind-of": "^3.0.2" + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.10", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" }, "dependencies": { - "kind-of": { - "version": "3.2.2", + "minimatch": { + "version": "3.0.8", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "brace-expansion": "^1.1.7" } + }, + "strip-json-comments": { + "version": "1.0.4", + "dev": true } } }, - "is-array-buffer": { - "version": "3.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - } + "json-parse-better-errors": { + "version": "1.0.2", + "dev": true }, - "is-arrayish": { - "version": "0.2.1", + "json-parse-even-better-errors": { + "version": "2.3.1", "dev": true }, - "is-bigint": { - "version": "1.0.4", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } + "json-schema": { + "version": "0.4.0", + "dev": true }, - "is-binary-path": { - "version": "2.1.0", - "devOptional": true, - "requires": { - "binary-extensions": "^2.0.0" - } + "json-schema-traverse": { + "version": "1.0.0" }, - "is-boolean-object": { - "version": "1.1.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true }, - "is-buffer": { - "version": "1.1.6", + "json-stringify-safe": { + "version": "5.0.1", "dev": true }, - "is-callable": { - "version": "1.2.7", + "json5": { + "version": "2.2.3", "dev": true }, - "is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "requires": { - "hasown": "^2.0.0" - } + "jsonc-parser": { + "version": "3.2.0" }, - "is-data-descriptor": { - "version": "0.1.4", + "jsonfile": { + "version": "6.1.0", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" } }, - "is-date-object": { - "version": "1.0.5", + "jsonparse": { + "version": "1.3.1" + }, + "JSONStream": { + "version": "1.3.5", "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" } }, - "is-descriptor": { - "version": "0.1.6", + "jsprim": { + "version": "1.4.2", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "dev": true - } + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" } }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - }, - "is-expression": { - "version": "3.0.0", + "jstransformer": { + "version": "1.0.0", "dev": true, "optional": true, "requires": { - "acorn": "~4.0.2", - "object-assign": "^4.0.1" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "dev": true, - "optional": true - } + "is-promise": "^2.0.0", + "promise": "^7.0.1" } }, - "is-extendable": { - "version": "0.1.1", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "devOptional": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0" - }, - "is-glob": { - "version": "4.0.3", - "devOptional": true, + "jszip": { + "version": "3.10.1", + "dev": true, "requires": { - "is-extglob": "^2.1.1" + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" } }, - "is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "karma": { + "version": "6.4.2", "dev": true, "requires": { - "is-docker": "^3.0.0" + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" }, "dependencies": { - "is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "cliui": { + "version": "7.0.4", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "connect": { + "version": "3.7.0", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + } + }, + "debug": { + "version": "2.6.9", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "finalhandler": { + "version": "1.1.2", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "glob": { + "version": "7.2.3", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.35", "dev": true + }, + "yargs": { + "version": "16.2.0", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } } } }, - "is-interactive": { - "version": "1.0.0" - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" - }, - "is-negative-zero": { - "version": "2.0.2", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "devOptional": true - }, - "is-number-like": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", - "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", - "dev": true, - "requires": { - "lodash.isfinite": "^3.3.2" - } - }, - "is-number-object": { - "version": "1.0.7", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-obj": { - "version": "2.0.0", - "dev": true - }, - "is-path-cwd": { - "version": "1.0.0", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", + "karma-chrome-launcher": { + "version": "3.1.1", "dev": true, "requires": { - "is-path-inside": "^1.0.0" + "which": "^1.2.1" }, "dependencies": { - "is-path-inside": { - "version": "1.0.1", + "which": { + "version": "1.3.1", "dev": true, "requires": { - "path-is-inside": "^1.0.1" + "isexe": "^2.0.0" } } } }, - "is-path-inside": { + "karma-coverage-istanbul-reporter": { "version": "3.0.3", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", "dev": true, "requires": { - "isobject": "^3.0.1" + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^3.0.2", + "minimatch": "^3.0.4" } }, - "is-promise": { - "version": "2.2.2", - "dev": true, - "optional": true - }, - "is-regex": { - "version": "1.1.4", + "karma-jasmine": { + "version": "4.0.2", "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "jasmine-core": "^3.6.0" + }, + "dependencies": { + "jasmine-core": { + "version": "3.99.1", + "dev": true + } } }, - "is-relative": { - "version": "1.0.0", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } + "karma-jasmine-html-reporter": { + "version": "1.7.0", + "dev": true }, - "is-shared-array-buffer": { - "version": "1.0.2", + "karma-source-map-support": { + "version": "1.4.0", "dev": true, "requires": { - "call-bind": "^1.0.2" + "source-map-support": "^0.5.5" } }, - "is-stream": { - "version": "2.0.1", + "kind-of": { + "version": "6.0.3", + "dev": true + }, + "klona": { + "version": "2.0.6", "dev": true }, - "is-string": { - "version": "1.0.7", + "launch-editor": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" } }, - "is-symbol": { + "lazy-cache": { "version": "1.0.4", "dev": true, + "optional": true + }, + "lcid": { + "version": "1.0.0", "requires": { - "has-symbols": "^1.0.2" + "invert-kv": "^1.0.0" } }, - "is-text-path": { - "version": "1.0.1", + "less": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", + "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", "dev": true, "requires": { - "text-extensions": "^1.0.0" + "copy-anything": "^2.0.1", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "parse-node-version": "^1.0.1", + "source-map": "~0.6.0", + "tslib": "^2.3.0" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "dev": true, + "optional": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "mime": { + "version": "1.6.0", + "dev": true, + "optional": true + }, + "pify": { + "version": "4.0.1", + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "dev": true, + "optional": true + } } }, - "is-typed-array": { - "version": "1.1.10", + "less-loader": { + "version": "11.1.0", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "klona": "^2.0.4" } }, - "is-typedarray": { - "version": "1.0.0", - "dev": true - }, - "is-unc-path": { - "version": "1.0.0", + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { - "unc-path-regex": "^0.1.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, - "is-unicode-supported": { - "version": "0.1.0" - }, - "is-weakref": { - "version": "1.0.2", + "license-webpack-plugin": { + "version": "4.0.2", "dev": true, "requires": { - "call-bind": "^1.0.2" + "webpack-sources": "^3.0.0" } }, - "is-what": { - "version": "3.14.1", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "dev": true + "lie": { + "version": "3.3.0", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "liftup": { + "version": "3.0.1", + "dev": true, "requires": { - "is-docker": "^2.0.0" + "extend": "^3.0.2", + "findup-sync": "^4.0.0", + "fined": "^1.2.0", + "flagged-respawn": "^1.0.1", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.1", + "rechoir": "^0.7.0", + "resolve": "^1.19.0" + }, + "dependencies": { + "findup-sync": { + "version": "4.0.0", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + } + } } }, - "isbinaryfile": { - "version": "4.0.10", + "lilconfig": { + "version": "2.1.0", "dev": true }, - "isexe": { - "version": "2.0.0" - }, - "isobject": { - "version": "3.0.1", + "limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==", "dev": true }, - "isstream": { - "version": "0.1.2", + "lines-and-columns": { + "version": "1.2.4", "dev": true }, - "istanbul-lib-coverage": { - "version": "3.2.0", + "livereload-js": { + "version": "2.4.0", "dev": true }, - "istanbul-lib-instrument": { - "version": "5.2.1", + "load-grunt-tasks": { + "version": "5.1.0", "dev": true, "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } + "arrify": "^2.0.1", + "multimatch": "^4.0.0", + "pkg-up": "^3.1.0", + "resolve-pkg": "^2.0.0" } }, - "istanbul-lib-report": { - "version": "3.0.0", + "load-json-file": { + "version": "4.0.0", "dev": true, "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "dependencies": { - "has-flag": { + "parse-json": { "version": "4.0.0", - "dev": true - }, - "supports-color": { - "version": "7.2.0", "dev": true, "requires": { - "has-flag": "^4.0.0" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } + }, + "pify": { + "version": "3.0.0", + "dev": true } } }, - "istanbul-lib-source-maps": { - "version": "3.0.6", + "loader-runner": { + "version": "4.3.0", + "dev": true + }, + "loader-utils": { + "version": "3.2.1", + "dev": true + }, + "localtunnel": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.2.tgz", + "integrity": "sha512-n418Cn5ynvJd7m/N1d9WVJISLJF/ellZnfsLnx8WBWGzxv/ntNcFkJ1o6se5quUhCplfLGBNL5tYHiq5WF3Nug==", "dev": true, "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" + "axios": "0.21.4", + "debug": "4.3.2", + "openurl": "1.1.1", + "yargs": "17.1.1" }, "dependencies": { - "glob": { - "version": "7.2.3", + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "istanbul-lib-coverage": { - "version": "2.0.5", - "dev": true - }, - "make-dir": { - "version": "2.1.0", + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "ms": "2.1.2" } }, - "pify": { - "version": "4.0.1", - "dev": true - }, - "rimraf": { - "version": "2.7.1", + "yargs": { + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz", + "integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==", "dev": true, "requires": { - "glob": "^7.1.3" + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "dev": true } } }, - "istanbul-reports": { - "version": "3.1.5", + "locate-path": { + "version": "6.0.0", "dev": true, "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "p-locate": "^5.0.0" } }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } + "lodash": { + "version": "4.17.21" }, - "jake": { - "version": "10.8.7", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", - "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", - "dev": true, + "lodash.clonedeep": { + "version": "4.5.0", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "lodash.isfinite": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", + "integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", "requires": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "dependencies": { "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } }, - "async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true - }, "chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -36040,1739 +39815,2580 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "version": "1.1.4" }, "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "version": "4.0.0" }, "supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } } } }, - "jasmine": { - "version": "2.8.0", + "log4js": { + "version": "6.9.1", "dev": true, "requires": { - "exit": "^0.1.2", - "glob": "^7.0.6", - "jasmine-core": "~2.8.0" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "jasmine-core": { - "version": "2.8.0", - "dev": true - } + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" } }, - "jasmine-core": { - "version": "4.1.1", + "longest": { + "version": "1.0.1", + "dev": true, + "optional": true + }, + "lottie-web": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", + "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + }, + "lower-case": { + "version": "1.1.4", "dev": true }, - "jasmine-spec-reporter": { - "version": "5.0.2", + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "requires": { - "colors": "1.4.0" + "yallist": "^3.0.2" + } + }, + "magic-string": { + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "requires": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "make-dir": { + "version": "3.1.0", + "dev": true, + "requires": { + "semver": "^6.0.0" }, "dependencies": { - "colors": { - "version": "1.4.0", + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } }, - "jasminewd2": { - "version": "2.2.0", + "make-error": { + "version": "1.3.6", "dev": true }, - "jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "make-fetch-happen": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", + "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "requires": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + } + }, + "make-iterator": { + "version": "1.0.1", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "dev": true + }, + "map-obj": { + "version": "4.3.0", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "marked": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-10.0.0.tgz", + "integrity": "sha512-YiGcYcWj50YrwBgNzFoYhQ1hT6GmQbFG8SksnYJX1z4BXTHSOrz1GB5/Jm2yQvMg4nN1FHP4M6r03R10KrVUiA==" + }, + "media-typer": { + "version": "0.3.0", + "dev": true + }, + "memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "requires": { + "fs-monkey": "^1.0.4" + } + }, + "memorystream": { + "version": "0.3.1", + "dev": true + }, + "meow": { + "version": "8.1.2", "dev": true, "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "find-up": { + "version": "4.1.0", "dev": true, "requires": { - "color-convert": "^2.0.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "hosted-git-info": { + "version": "4.1.0", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "lru-cache": "^6.0.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "locate-path": { + "version": "5.0.0", "dev": true, "requires": { - "color-name": "~1.1.4" + "p-locate": "^4.1.0" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "normalize-package-data": { + "version": "3.0.3", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "p-limit": { + "version": "2.3.0", "dev": true, "requires": { - "has-flag": "^4.0.0" + "p-try": "^2.0.0" } - } - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "dev": true }, - "supports-color": { - "version": "8.1.1", + "p-locate": { + "version": "4.1.0", "dev": true, "requires": { - "has-flag": "^4.0.0" + "p-limit": "^2.2.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "dev": true + } } + }, + "type-fest": { + "version": "0.18.1", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "dev": true } } }, - "jiti": { - "version": "1.18.2", + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", "dev": true }, - "jquery": { - "version": "2.1.4" - }, - "js-base64": { - "version": "2.6.4", + "merge-stream": { + "version": "2.0.0", "dev": true }, - "js-stringify": { - "version": "1.0.2", - "dev": true, - "optional": true + "merge2": { + "version": "1.4.1", + "dev": true }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true }, - "js-yaml": { - "version": "3.14.1", + "micromatch": { + "version": "4.0.5", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, - "jsbn": { - "version": "0.1.1", - "dev": true - }, - "jsdoc-type-pratt-parser": { - "version": "3.1.0", + "mime": { + "version": "2.6.0", "dev": true }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "mime-db": { + "version": "1.52.0", "dev": true }, - "jshint": { - "version": "2.9.7", + "mime-types": { + "version": "2.1.35", "dev": true, "requires": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.10", - "minimatch": "~3.0.2", - "shelljs": "0.3.x", - "strip-json-comments": "1.0.x" - }, - "dependencies": { - "minimatch": { - "version": "3.0.8", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "strip-json-comments": { - "version": "1.0.4", - "dev": true - } + "mime-db": "1.52.0" } }, - "json-parse-better-errors": { - "version": "1.0.2", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true - }, - "json-schema": { - "version": "0.4.0", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0" + "mimic-fn": { + "version": "2.1.0" }, - "json-stable-stringify-without-jsonify": { + "min-indent": { "version": "1.0.1", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "dev": true - }, - "json5": { - "version": "2.2.3", - "dev": true - }, - "jsonc-parser": { - "version": "3.2.0" - }, - "jsonfile": { - "version": "6.1.0", + "mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "schema-utils": "^4.0.0" } }, - "jsonparse": { - "version": "1.3.1" + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true }, - "JSONStream": { - "version": "1.3.5", + "minimatch": { + "version": "3.1.2", "dev": true, "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" + "brace-expansion": "^1.1.7" } }, - "jsprim": { - "version": "1.4.2", + "minimist": { + "version": "1.2.8", + "dev": true + }, + "minimist-options": { + "version": "4.1.0", "dev": true, "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "dependencies": { + "arrify": { + "version": "1.0.1", + "dev": true + } } }, - "jstransformer": { - "version": "1.0.0", - "dev": true, - "optional": true, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "requires": { - "is-promise": "^2.0.0", - "promise": "^7.0.1" + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } } }, - "jszip": { - "version": "3.10.1", - "dev": true, + "minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", "requires": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" + "encoding": "^0.1.13", + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" } }, - "karma": { - "version": "6.4.2", - "dev": true, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "requires": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.4.1", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" + "minipass": "^3.0.0" }, "dependencies": { - "cliui": { - "version": "7.0.4", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "connect": { - "version": "3.7.0", - "dev": true, + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" + "yallist": "^4.0.0" } }, - "debug": { - "version": "2.6.9", - "dev": true, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "requires": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "requires": { - "ms": "2.0.0" + "yallist": "^4.0.0" } }, - "finalhandler": { - "version": "1.1.2", - "dev": true, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" + "yallist": "^4.0.0" } }, - "glob": { - "version": "7.2.3", - "dev": true, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "yallist": "^4.0.0" } }, - "ms": { - "version": "2.0.0", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "dev": true - }, - "ua-parser-js": { - "version": "0.7.35", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "dev": true, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yallist": "^4.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, - "karma-chrome-launcher": { - "version": "3.1.1", + "mitt": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", + "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==", + "dev": true + }, + "mixin-deep": { + "version": "1.3.2", "dev": true, "requires": { - "which": "^1.2.1" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "dependencies": { - "which": { - "version": "1.3.1", + "is-extendable": { + "version": "1.0.1", "dev": true, "requires": { - "isexe": "^2.0.0" + "is-plain-object": "^2.0.4" } } } }, - "karma-coverage-istanbul-reporter": { - "version": "3.0.3", + "mkdirp": { + "version": "0.5.6", "dev": true, "requires": { - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^3.0.6", - "istanbul-reports": "^3.0.2", - "minimatch": "^3.0.4" + "minimist": "^1.2.6" } }, - "karma-jasmine": { - "version": "4.0.2", + "moment": { + "version": "2.29.4" + }, + "morgan": { + "version": "1.10.0", "dev": true, "requires": { - "jasmine-core": "^3.6.0" + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" }, "dependencies": { - "jasmine-core": { - "version": "3.99.1", + "debug": { + "version": "2.6.9", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", "dev": true } } }, - "karma-jasmine-html-reporter": { - "version": "1.7.0", - "dev": true, - "requires": {} + "mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "dev": true }, - "karma-source-map-support": { - "version": "1.4.0", + "ms": { + "version": "2.1.2" + }, + "multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dev": true, "requires": { - "source-map-support": "^0.5.5" + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" } }, - "kind-of": { - "version": "6.0.3", - "dev": true + "multimatch": { + "version": "4.0.0", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } }, - "klona": { - "version": "2.0.6", - "dev": true + "mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==" }, - "launch-editor": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", - "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", + "mz": { + "version": "2.7.0", "dev": true, "requires": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" } }, - "lazy-cache": { - "version": "1.0.4", + "nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", "dev": true, "optional": true }, - "lcid": { - "version": "1.0.0", - "requires": { - "invert-kv": "^1.0.0" - } + "nanoid": { + "version": "3.3.6", + "dev": true }, - "less": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", - "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", + "nanomatch": { + "version": "1.2.13", "dev": true, "requires": { - "copy-anything": "^2.0.1", - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "parse-node-version": "^1.0.1", - "source-map": "~0.6.0", - "tslib": "^2.3.0" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { - "make-dir": { - "version": "2.1.0", + "define-property": { + "version": "2.0.2", "dev": true, - "optional": true, "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" } }, - "mime": { - "version": "1.6.0", + "extend-shallow": { + "version": "3.0.2", "dev": true, - "optional": true + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } }, - "pify": { - "version": "4.0.1", + "is-accessor-descriptor": { + "version": "1.0.0", "dev": true, - "optional": true + "requires": { + "kind-of": "^6.0.0" + } }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "is-data-descriptor": { + "version": "1.0.0", "dev": true, - "optional": true + "requires": { + "kind-of": "^6.0.0" + } }, - "source-map": { - "version": "0.6.1", + "is-descriptor": { + "version": "1.0.2", "dev": true, - "optional": true + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extendable": { + "version": "1.0.1", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, - "less-loader": { - "version": "11.1.0", - "dev": true, - "requires": { - "klona": "^2.0.4" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "license-webpack-plugin": { - "version": "4.0.2", - "dev": true, - "requires": { - "webpack-sources": "^3.0.0" - } - }, - "lie": { - "version": "3.3.0", - "dev": true, - "requires": { - "immediate": "~3.0.5" - } + "natural-compare": { + "version": "1.4.0", + "dev": true }, - "liftup": { - "version": "3.0.1", + "needle": { + "version": "3.2.0", "dev": true, + "optional": true, "requires": { - "extend": "^3.0.2", - "findup-sync": "^4.0.0", - "fined": "^1.2.0", - "flagged-respawn": "^1.0.1", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.1", - "rechoir": "^0.7.0", - "resolve": "^1.19.0" + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" }, "dependencies": { - "findup-sync": { - "version": "4.0.0", + "debug": { + "version": "3.2.7", "dev": true, + "optional": true, "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^4.0.2", - "resolve-dir": "^1.0.1" + "ms": "^2.1.1" } } } }, - "lilconfig": { - "version": "2.1.0", - "dev": true - }, - "limiter": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", - "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "dev": true + "negotiator": { + "version": "0.6.3" }, - "livereload-js": { - "version": "2.4.0", + "neo-async": { + "version": "2.6.2", "dev": true }, - "load-grunt-tasks": { - "version": "5.1.0", - "dev": true, - "requires": { - "arrify": "^2.0.1", - "multimatch": "^4.0.0", - "pkg-up": "^3.1.0", - "resolve-pkg": "^2.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", + "ng-annotate": { + "version": "1.2.2", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "acorn": "~2.6.4", + "alter": "~0.2.0", + "convert-source-map": "~1.1.2", + "optimist": "~0.6.1", + "ordered-ast-traverse": "~1.1.1", + "simple-fmt": "~0.1.0", + "simple-is": "~0.2.0", + "source-map": "~0.5.3", + "stable": "~0.1.5", + "stringmap": "~0.2.2", + "stringset": "~0.2.1", + "tryor": "~0.1.2" }, "dependencies": { - "parse-json": { - "version": "4.0.0", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } + "acorn": { + "version": "2.6.4", + "dev": true }, - "pify": { - "version": "3.0.0", + "convert-source-map": { + "version": "1.1.3", + "dev": true + }, + "source-map": { + "version": "0.5.7", "dev": true } } }, - "loader-runner": { - "version": "4.3.0", - "dev": true + "ng-csv": { + "version": "0.2.3" }, - "loader-utils": { - "version": "3.2.1", - "dev": true + "ng-file-upload": { + "version": "5.0.9" }, - "localtunnel": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.2.tgz", - "integrity": "sha512-n418Cn5ynvJd7m/N1d9WVJISLJF/ellZnfsLnx8WBWGzxv/ntNcFkJ1o6se5quUhCplfLGBNL5tYHiq5WF3Nug==", - "dev": true, + "ng2-pdf-viewer": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ng2-pdf-viewer/-/ng2-pdf-viewer-10.0.0.tgz", + "integrity": "sha512-zEefcAsTpDoxFceQYs3ycPMaUAkt5UX4OcTstVQoNqRK6w+vOY+V8z8aFCuBwnt+7iN1EHaIpquOf4S9mWc04g==", "requires": { - "axios": "0.21.4", - "debug": "4.3.2", - "openurl": "1.1.1", - "yargs": "17.1.1" - }, - "dependencies": { - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "yargs": { - "version": "17.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz", - "integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - } + "pdfjs-dist": "~2.16.105", + "tslib": "^2.3.0" } }, - "locate-path": { - "version": "6.0.0", - "dev": true, + "ngx-bootstrap": { + "version": "6.2.0" + }, + "ngx-entity-service": { + "version": "0.0.37", + "resolved": "https://registry.npmjs.org/ngx-entity-service/-/ngx-entity-service-0.0.37.tgz", + "integrity": "sha512-clUk5EVKoxECHau0NB+VSvJh2hjtCd4TF5gJBFHEBBBZOZKYKagv/oQKIVntQweuKx6gQMAvy8g8CuTpUb9k0g==", "requires": { - "p-locate": "^5.0.0" + "tslib": "^2.3.0" } }, - "lodash": { - "version": "4.17.21" + "ngx-lottie": { + "version": "10.0.0", + "requires": { + "@scarf/scarf": "^1.1.1", + "tslib": "^2.3.0" + } }, - "lodash.clonedeep": { - "version": "4.5.0", - "dev": true + "nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "optional": true, + "requires": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "nice-try": { + "version": "1.0.5", "dev": true }, - "lodash.isfinite": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", - "integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==", - "dev": true + "no-case": { + "version": "2.3.2", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } }, - "lodash.merge": { - "version": "4.6.2", + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "optional": true + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", "dev": true }, - "log-symbols": { - "version": "4.1.0", + "node-gyp": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", + "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "requires": { - "color-convert": "^2.0.1" - } + "abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==" }, - "chalk": { - "version": "4.1.2", + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "balanced-match": "^1.0.0" } }, - "color-convert": { - "version": "2.0.1", + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "requires": { - "color-name": "~1.1.4" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" } }, - "color-name": { - "version": "1.1.4" + "isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" }, - "has-flag": { - "version": "4.0.0" + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "requires": { + "brace-expansion": "^2.0.1" + } }, - "supports-color": { + "nopt": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", "requires": { - "has-flag": "^4.0.0" + "abbrev": "^2.0.0" + } + }, + "which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "requires": { + "isexe": "^3.1.1" } } } }, - "log4js": { - "version": "6.9.1", - "dev": true, - "requires": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.5" - } - }, - "longest": { - "version": "1.0.1", + "node-gyp-build": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", + "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", "dev": true, "optional": true }, - "lottie-web": { - "version": "5.12.2", - "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", - "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + "node-machine-id": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", + "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", + "dev": true }, - "lower-case": { - "version": "1.1.4", + "node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "nopt": { + "version": "3.0.6", "dev": true, "requires": { - "yallist": "^3.0.2" - } - }, - "magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", - "requires": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "abbrev": "1" } }, - "make-dir": { - "version": "3.1.0", + "normalize-package-data": { + "version": "2.5.0", "dev": true, "requires": { - "semver": "^6.0.0" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" }, "dependencies": { "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true } } }, - "make-error": { - "version": "1.3.6", - "dev": true - }, - "make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", - "requires": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - } - }, - "make-iterator": { - "version": "1.0.1", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "dev": true - }, - "map-obj": { - "version": "4.3.0", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "marked": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-10.0.0.tgz", - "integrity": "sha512-YiGcYcWj50YrwBgNzFoYhQ1hT6GmQbFG8SksnYJX1z4BXTHSOrz1GB5/Jm2yQvMg4nN1FHP4M6r03R10KrVUiA==" - }, - "media-typer": { - "version": "0.3.0", + "normalize-path": { + "version": "3.0.0", "dev": true }, - "memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "requires": { - "fs-monkey": "^1.0.4" - } - }, - "memorystream": { - "version": "0.3.1", + "normalize-range": { + "version": "0.1.2", "dev": true }, - "meow": { - "version": "8.1.2", - "dev": true, + "npm": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.4.0.tgz", + "integrity": "sha512-RS7Mx0OVfXlOcQLRePuDIYdFCVBPCNapWHplDK+mh7GDdP/Tvor4ocuybRRPSvfcRb2vjRJt1fHCqw3cr8qACQ==", "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "dev": true, + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^7.2.1", + "@npmcli/config": "^8.0.2", + "@npmcli/fs": "^3.1.0", + "@npmcli/map-workspaces": "^3.0.4", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.1", + "@npmcli/run-script": "^7.0.4", + "@sigstore/tuf": "^2.3.0", + "abbrev": "^2.0.0", + "archy": "~1.0.0", + "cacache": "^18.0.2", + "chalk": "^5.3.0", + "ci-info": "^4.0.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.3", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.3", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^7.0.1", + "ini": "^4.1.1", + "init-package-json": "^6.0.0", + "is-cidr": "^5.0.3", + "json-parse-even-better-errors": "^3.0.1", + "libnpmaccess": "^8.0.1", + "libnpmdiff": "^6.0.3", + "libnpmexec": "^7.0.4", + "libnpmfund": "^5.0.1", + "libnpmhook": "^10.0.0", + "libnpmorg": "^6.0.1", + "libnpmpack": "^6.0.3", + "libnpmpublish": "^9.0.2", + "libnpmsearch": "^7.0.0", + "libnpmteam": "^6.0.0", + "libnpmversion": "^5.0.1", + "make-fetch-happen": "^13.0.0", + "minimatch": "^9.0.3", + "minipass": "^7.0.4", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^10.0.1", + "nopt": "^7.2.0", + "normalize-package-data": "^6.0.0", + "npm-audit-report": "^5.0.0", + "npm-install-checks": "^6.3.0", + "npm-package-arg": "^11.0.1", + "npm-pick-manifest": "^9.0.0", + "npm-profile": "^9.0.0", + "npm-registry-fetch": "^16.1.0", + "npm-user-validate": "^2.0.0", + "npmlog": "^7.0.1", + "p-map": "^4.0.0", + "pacote": "^17.0.6", + "parse-conflict-json": "^3.0.1", + "proc-log": "^3.0.0", + "qrcode-terminal": "^0.12.0", + "read": "^2.1.0", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1", + "ssri": "^10.0.5", + "supports-color": "^9.4.0", + "tar": "^6.2.0", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^5.0.0", + "which": "^4.0.0", + "write-file-atomic": "^5.0.1" + }, + "dependencies": { + "@colors/colors": { + "version": "1.5.0", + "bundled": true, + "optional": true + }, + "@isaacs/cliui": { + "version": "8.0.2", + "bundled": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "bundled": true + }, + "emoji-regex": { + "version": "9.2.2", + "bundled": true + }, + "string-width": { + "version": "5.1.2", + "bundled": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "bundled": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "@isaacs/string-locale-compare": { + "version": "1.1.0", + "bundled": true + }, + "@npmcli/agent": { + "version": "2.2.0", + "bundled": true, + "requires": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.1" + } + }, + "@npmcli/arborist": { + "version": "7.3.1", + "bundled": true, + "requires": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^3.1.0", + "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/metavuln-calculator": "^7.0.0", + "@npmcli/name-from-folder": "^2.0.0", + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/query": "^3.0.1", + "@npmcli/run-script": "^7.0.2", + "bin-links": "^4.0.1", + "cacache": "^18.0.0", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^7.0.1", + "json-parse-even-better-errors": "^3.0.0", + "json-stringify-nice": "^1.1.4", + "minimatch": "^9.0.0", + "nopt": "^7.0.0", + "npm-install-checks": "^6.2.0", + "npm-package-arg": "^11.0.1", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "npmlog": "^7.0.1", + "pacote": "^17.0.4", + "parse-conflict-json": "^3.0.0", + "proc-log": "^3.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^10.0.5", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" + } + }, + "@npmcli/config": { + "version": "8.1.0", + "bundled": true, + "requires": { + "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^4.0.0", + "ini": "^4.1.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + } + }, + "@npmcli/disparity-colors": { + "version": "3.0.0", + "bundled": true, + "requires": { + "ansi-styles": "^4.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "bundled": true, + "requires": { + "color-convert": "^2.0.1" + } + } + } + }, + "@npmcli/fs": { + "version": "3.1.0", + "bundled": true, + "requires": { + "semver": "^7.3.5" + } + }, + "@npmcli/git": { + "version": "5.0.4", + "bundled": true, + "requires": { + "@npmcli/promise-spawn": "^7.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + } + }, + "@npmcli/installed-package-contents": { + "version": "2.0.2", + "bundled": true, + "requires": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + } + }, + "@npmcli/map-workspaces": { + "version": "3.0.4", + "bundled": true, + "requires": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + } + }, + "@npmcli/metavuln-calculator": { + "version": "7.0.0", + "bundled": true, + "requires": { + "cacache": "^18.0.0", + "json-parse-even-better-errors": "^3.0.0", + "pacote": "^17.0.0", + "semver": "^7.3.5" + } + }, + "@npmcli/name-from-folder": { + "version": "2.0.0", + "bundled": true + }, + "@npmcli/node-gyp": { + "version": "3.0.0", + "bundled": true + }, + "@npmcli/package-json": { + "version": "5.0.0", + "bundled": true, + "requires": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + } + }, + "@npmcli/promise-spawn": { + "version": "7.0.1", + "bundled": true, + "requires": { + "which": "^4.0.0" + } + }, + "@npmcli/query": { + "version": "3.0.1", + "bundled": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "@npmcli/run-script": { + "version": "7.0.4", + "bundled": true, + "requires": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", + "which": "^4.0.0" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "bundled": true, + "optional": true + }, + "@sigstore/bundle": { + "version": "2.1.1", + "bundled": true, + "requires": { + "@sigstore/protobuf-specs": "^0.2.1" + } + }, + "@sigstore/core": { + "version": "0.2.0", + "bundled": true + }, + "@sigstore/protobuf-specs": { + "version": "0.2.1", + "bundled": true + }, + "@sigstore/sign": { + "version": "2.2.1", + "bundled": true, + "requires": { + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", + "@sigstore/protobuf-specs": "^0.2.1", + "make-fetch-happen": "^13.0.0" + } + }, + "@sigstore/tuf": { + "version": "2.3.0", + "bundled": true, + "requires": { + "@sigstore/protobuf-specs": "^0.2.1", + "tuf-js": "^2.2.0" + } + }, + "@sigstore/verify": { + "version": "0.1.0", + "bundled": true, + "requires": { + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", + "@sigstore/protobuf-specs": "^0.2.1" + } + }, + "@tufjs/canonical-json": { + "version": "2.0.0", + "bundled": true + }, + "@tufjs/models": { + "version": "2.0.0", + "bundled": true, + "requires": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.3" + } + }, + "abbrev": { + "version": "2.0.0", + "bundled": true + }, + "agent-base": { + "version": "7.1.0", + "bundled": true, + "requires": { + "debug": "^4.3.4" + } + }, + "aggregate-error": { + "version": "3.1.0", + "bundled": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "bundled": true + }, + "ansi-styles": { + "version": "6.2.1", + "bundled": true + }, + "aproba": { + "version": "2.0.0", + "bundled": true + }, + "archy": { + "version": "1.0.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "4.0.2", + "bundled": true + }, + "balanced-match": { + "version": "1.0.2", + "bundled": true + }, + "bin-links": { + "version": "4.0.3", + "bundled": true, + "requires": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + } + }, + "binary-extensions": { + "version": "2.2.0", + "bundled": true + }, + "brace-expansion": { + "version": "2.0.1", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "builtins": { + "version": "5.0.1", + "bundled": true, + "requires": { + "semver": "^7.0.0" + } + }, + "cacache": { + "version": "18.0.2", + "bundled": true, + "requires": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + } + }, + "chalk": { + "version": "5.3.0", + "bundled": true + }, + "chownr": { + "version": "2.0.0", + "bundled": true + }, + "ci-info": { + "version": "4.0.0", + "bundled": true + }, + "cidr-regex": { + "version": "4.0.3", + "bundled": true, + "requires": { + "ip-regex": "^5.0.0" + } + }, + "clean-stack": { + "version": "2.2.0", + "bundled": true + }, + "cli-columns": { + "version": "4.0.0", + "bundled": true, + "requires": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + } + }, + "cli-table3": { + "version": "0.6.3", + "bundled": true, + "requires": { + "@colors/colors": "1.5.0", + "string-width": "^4.2.0" + } + }, + "clone": { + "version": "1.0.4", + "bundled": true + }, + "cmd-shim": { + "version": "6.0.2", + "bundled": true + }, + "color-convert": { + "version": "2.0.1", + "bundled": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "bundled": true + }, + "color-support": { + "version": "1.1.3", + "bundled": true + }, + "columnify": { + "version": "1.6.0", + "bundled": true, + "requires": { + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + } + }, + "common-ancestor-path": { + "version": "1.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "cross-spawn": { + "version": "7.0.3", + "bundled": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "cssesc": { + "version": "3.0.0", + "bundled": true + }, + "debug": { + "version": "4.3.4", + "bundled": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "bundled": true + } + } + }, + "defaults": { + "version": "1.0.4", + "bundled": true, + "requires": { + "clone": "^1.0.2" + } + }, + "diff": { + "version": "5.1.0", + "bundled": true + }, + "eastasianwidth": { + "version": "0.2.0", + "bundled": true + }, + "emoji-regex": { + "version": "8.0.0", + "bundled": true + }, + "encoding": { + "version": "0.1.13", + "bundled": true, + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "env-paths": { + "version": "2.2.1", + "bundled": true + }, + "err-code": { + "version": "2.0.3", + "bundled": true + }, + "exponential-backoff": { + "version": "3.1.1", + "bundled": true + }, + "fastest-levenshtein": { + "version": "1.0.16", + "bundled": true + }, + "foreground-child": { + "version": "3.1.1", + "bundled": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, + "fs-minipass": { + "version": "3.0.3", + "bundled": true, + "requires": { + "minipass": "^7.0.3" + } + }, + "function-bind": { + "version": "1.1.2", + "bundled": true + }, + "gauge": { + "version": "5.0.1", + "bundled": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^4.0.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "glob": { + "version": "10.3.10", + "bundled": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "graceful-fs": { + "version": "4.2.11", + "bundled": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hasown": { + "version": "2.0.0", + "bundled": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "hosted-git-info": { + "version": "7.0.1", + "bundled": true, + "requires": { + "lru-cache": "^10.0.1" + } + }, + "http-cache-semantics": { + "version": "4.1.1", + "bundled": true + }, + "http-proxy-agent": { + "version": "7.0.0", + "bundled": true, + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, + "https-proxy-agent": { + "version": "7.0.2", + "bundled": true, + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } + }, + "iconv-lite": { + "version": "0.6.3", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "ignore-walk": { + "version": "6.0.4", + "bundled": true, + "requires": { + "minimatch": "^9.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "indent-string": { + "version": "4.0.0", + "bundled": true + }, + "ini": { + "version": "4.1.1", + "bundled": true + }, + "init-package-json": { + "version": "6.0.0", + "bundled": true, + "requires": { + "npm-package-arg": "^11.0.0", + "promzard": "^1.0.0", + "read": "^2.0.0", + "read-package-json": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^5.0.0" + } + }, + "ip": { + "version": "2.0.0", + "bundled": true + }, + "ip-regex": { + "version": "5.0.0", + "bundled": true + }, + "is-cidr": { + "version": "5.0.3", + "bundled": true, + "requires": { + "cidr-regex": "4.0.3" + } + }, + "is-core-module": { + "version": "2.13.1", + "bundled": true, + "requires": { + "hasown": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "bundled": true + }, + "is-lambda": { + "version": "1.0.1", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "jackspeak": { + "version": "2.3.6", + "bundled": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" } }, - "hosted-git-info": { - "version": "4.1.0", - "dev": true, + "json-parse-even-better-errors": { + "version": "3.0.1", + "bundled": true + }, + "json-stringify-nice": { + "version": "1.1.4", + "bundled": true + }, + "jsonparse": { + "version": "1.3.1", + "bundled": true + }, + "just-diff": { + "version": "6.0.2", + "bundled": true + }, + "just-diff-apply": { + "version": "5.5.0", + "bundled": true + }, + "libnpmaccess": { + "version": "8.0.2", + "bundled": true, "requires": { - "lru-cache": "^6.0.0" + "npm-package-arg": "^11.0.1", + "npm-registry-fetch": "^16.0.0" } }, - "locate-path": { - "version": "5.0.0", - "dev": true, + "libnpmdiff": { + "version": "6.0.6", + "bundled": true, "requires": { - "p-locate": "^4.1.0" + "@npmcli/arborist": "^7.2.1", + "@npmcli/disparity-colors": "^3.0.0", + "@npmcli/installed-package-contents": "^2.0.2", + "binary-extensions": "^2.2.0", + "diff": "^5.1.0", + "minimatch": "^9.0.0", + "npm-package-arg": "^11.0.1", + "pacote": "^17.0.4", + "tar": "^6.2.0" + } + }, + "libnpmexec": { + "version": "7.0.7", + "bundled": true, + "requires": { + "@npmcli/arborist": "^7.2.1", + "@npmcli/run-script": "^7.0.2", + "ci-info": "^4.0.0", + "npm-package-arg": "^11.0.1", + "npmlog": "^7.0.1", + "pacote": "^17.0.4", + "proc-log": "^3.0.0", + "read": "^2.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" + } + }, + "libnpmfund": { + "version": "5.0.4", + "bundled": true, + "requires": { + "@npmcli/arborist": "^7.2.1" + } + }, + "libnpmhook": { + "version": "10.0.1", + "bundled": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.0.0" + } + }, + "libnpmorg": { + "version": "6.0.2", + "bundled": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.0.0" + } + }, + "libnpmpack": { + "version": "6.0.6", + "bundled": true, + "requires": { + "@npmcli/arborist": "^7.2.1", + "@npmcli/run-script": "^7.0.2", + "npm-package-arg": "^11.0.1", + "pacote": "^17.0.4" + } + }, + "libnpmpublish": { + "version": "9.0.4", + "bundled": true, + "requires": { + "ci-info": "^4.0.0", + "normalize-package-data": "^6.0.0", + "npm-package-arg": "^11.0.1", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.7", + "sigstore": "^2.2.0", + "ssri": "^10.0.5" + } + }, + "libnpmsearch": { + "version": "7.0.1", + "bundled": true, + "requires": { + "npm-registry-fetch": "^16.0.0" + } + }, + "libnpmteam": { + "version": "6.0.1", + "bundled": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.0.0" + } + }, + "libnpmversion": { + "version": "5.0.2", + "bundled": true, + "requires": { + "@npmcli/git": "^5.0.3", + "@npmcli/run-script": "^7.0.2", + "json-parse-even-better-errors": "^3.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.7" } }, "lru-cache": { - "version": "6.0.0", - "dev": true, + "version": "10.1.0", + "bundled": true + }, + "make-fetch-happen": { + "version": "13.0.0", + "bundled": true, + "requires": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "bundled": true, "requires": { - "yallist": "^4.0.0" + "brace-expansion": "^2.0.1" } }, - "normalize-package-data": { - "version": "3.0.3", - "dev": true, + "minipass": { + "version": "7.0.4", + "bundled": true + }, + "minipass-collect": { + "version": "2.0.1", + "bundled": true, "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "minipass": "^7.0.3" } }, - "p-limit": { - "version": "2.3.0", - "dev": true, + "minipass-fetch": { + "version": "3.0.4", + "bundled": true, "requires": { - "p-try": "^2.0.0" + "encoding": "^0.1.13", + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" } }, - "p-locate": { - "version": "4.1.0", - "dev": true, + "minipass-flush": { + "version": "1.0.5", + "bundled": true, "requires": { - "p-limit": "^2.2.0" + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } + } } }, - "read-pkg": { - "version": "5.2.0", - "dev": true, + "minipass-json-stream": { + "version": "1.0.1", + "bundled": true, "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" }, "dependencies": { - "hosted-git-info": { - "version": "2.8.9", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "dev": true, + "minipass": { + "version": "3.3.6", + "bundled": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "yallist": "^4.0.0" } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "type-fest": { - "version": "0.6.0", - "dev": true } } }, - "read-pkg-up": { - "version": "7.0.1", - "dev": true, + "minipass-pipeline": { + "version": "1.2.4", + "bundled": true, "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" + "minipass": "^3.0.0" }, "dependencies": { - "type-fest": { - "version": "0.8.1", - "dev": true + "minipass": { + "version": "3.3.6", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } } } }, - "type-fest": { - "version": "0.18.1", - "dev": true + "minipass-sized": { + "version": "1.0.3", + "bundled": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } + } + } }, - "yallist": { - "version": "4.0.0", - "dev": true - } - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "2.6.0", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0" - }, - "min-indent": { - "version": "1.0.1", - "dev": true - }, - "mini-css-extract-plugin": { - "version": "2.7.6", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", - "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", - "dev": true, - "requires": { - "schema-utils": "^4.0.0" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "dev": true - }, - "minimist-options": { - "version": "4.1.0", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "dependencies": { - "arrify": { - "version": "1.0.1", - "dev": true - } - } - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "minizlib": { + "version": "2.1.2", + "bundled": true, "requires": { + "minipass": "^3.0.0", "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } + } } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "requires": { - "encoding": "^0.1.13", - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "mkdirp": { + "version": "1.0.4", + "bundled": true + }, + "ms": { + "version": "2.1.3", + "bundled": true + }, + "mute-stream": { + "version": "1.0.0", + "bundled": true + }, + "negotiator": { + "version": "0.6.3", + "bundled": true + }, + "node-gyp": { + "version": "10.0.1", + "bundled": true, + "requires": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + } + }, + "nopt": { + "version": "7.2.0", + "bundled": true, "requires": { - "yallist": "^4.0.0" + "abbrev": "^2.0.0" } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minipass-json-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", - "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", - "requires": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "normalize-package-data": { + "version": "6.0.0", + "bundled": true, "requires": { - "yallist": "^4.0.0" + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "npm-audit-report": { + "version": "5.0.0", + "bundled": true + }, + "npm-bundled": { + "version": "3.0.0", + "bundled": true, "requires": { - "yallist": "^4.0.0" + "npm-normalize-package-bin": "^3.0.0" } }, - "yallist": { + "npm-install-checks": { + "version": "6.3.0", + "bundled": true, + "requires": { + "semver": "^7.1.1" + } + }, + "npm-normalize-package-bin": { + "version": "3.0.1", + "bundled": true + }, + "npm-package-arg": { + "version": "11.0.1", + "bundled": true, + "requires": { + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + } + }, + "npm-packlist": { + "version": "8.0.2", + "bundled": true, + "requires": { + "ignore-walk": "^6.0.4" + } + }, + "npm-pick-manifest": { + "version": "9.0.0", + "bundled": true, + "requires": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" + } + }, + "npm-profile": { + "version": "9.0.0", + "bundled": true, + "requires": { + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0" + } + }, + "npm-registry-fetch": { + "version": "16.1.0", + "bundled": true, + "requires": { + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^3.0.0" + } + }, + "npm-user-validate": { + "version": "2.0.0", + "bundled": true + }, + "npmlog": { + "version": "7.0.1", + "bundled": true, + "requires": { + "are-we-there-yet": "^4.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^5.0.0", + "set-blocking": "^2.0.0" + } + }, + "p-map": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "bundled": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "pacote": { + "version": "17.0.6", + "bundled": true, + "requires": { + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^7.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^7.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^2.2.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + } + }, + "parse-conflict-json": { + "version": "3.0.1", + "bundled": true, "requires": { - "yallist": "^4.0.0" + "json-parse-even-better-errors": "^3.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" } }, - "yallist": { + "path-key": { + "version": "3.1.1", + "bundled": true + }, + "path-scurry": { + "version": "1.10.1", + "bundled": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + } + }, + "postcss-selector-parser": { + "version": "6.0.15", + "bundled": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "proc-log": { + "version": "3.0.0", + "bundled": true + }, + "promise-all-reject-late": { + "version": "1.0.1", + "bundled": true + }, + "promise-call-limit": { + "version": "3.0.1", + "bundled": true + }, + "promise-inflight": { + "version": "1.0.1", + "bundled": true + }, + "promise-retry": { + "version": "2.0.1", + "bundled": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "promzard": { + "version": "1.0.0", + "bundled": true, + "requires": { + "read": "^2.0.0" + } + }, + "qrcode-terminal": { + "version": "0.12.0", + "bundled": true + }, + "read": { + "version": "2.1.0", + "bundled": true, + "requires": { + "mute-stream": "~1.0.0" + } + }, + "read-cmd-shim": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "bundled": true + }, + "read-package-json": { + "version": "7.0.0", + "bundled": true, + "requires": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0" + } + }, + "read-package-json-fast": { + "version": "3.0.2", + "bundled": true, + "requires": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + } + }, + "retry": { + "version": "0.12.0", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "semver": { + "version": "7.5.4", + "bundled": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "2.0.0", + "bundled": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "bundled": true + }, + "signal-exit": { + "version": "4.1.0", + "bundled": true + }, + "sigstore": { + "version": "2.2.0", + "bundled": true, "requires": { - "yallist": "^4.0.0" + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", + "@sigstore/protobuf-specs": "^0.2.1", + "@sigstore/sign": "^2.2.1", + "@sigstore/tuf": "^2.3.0", + "@sigstore/verify": "^0.1.0" } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "mitt": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", - "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==", - "dev": true - }, - "mixin-deep": { - "version": "1.3.2", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "dev": true, + "smart-buffer": { + "version": "4.2.0", + "bundled": true + }, + "socks": { + "version": "2.7.1", + "bundled": true, "requires": { - "is-plain-object": "^2.0.4" + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" } - } - } - }, - "mkdirp": { - "version": "0.5.6", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "moment": { - "version": "2.29.4" - }, - "morgan": { - "version": "1.10.0", - "dev": true, - "requires": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "dev": true, + }, + "socks-proxy-agent": { + "version": "8.0.2", + "bundled": true, "requires": { - "ms": "2.0.0" + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" } }, - "ms": { - "version": "2.0.0", - "dev": true - } - } - }, - "mrmime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", - "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "dev": true - }, - "ms": { - "version": "2.1.2" - }, - "multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "requires": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - } - }, - "multimatch": { - "version": "4.0.0", - "dev": true, - "requires": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" - } - }, - "mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==" - }, - "mz": { - "version": "2.7.0", - "dev": true, - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "3.3.6", - "dev": true - }, - "nanomatch": { - "version": "1.2.13", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "dev": true, + "spdx-correct": { + "version": "3.2.0", + "bundled": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "extend-shallow": { - "version": "3.0.2", - "dev": true, + "spdx-exceptions": { + "version": "2.3.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "bundled": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "is-accessor-descriptor": { - "version": "1.0.0", - "dev": true, + "spdx-license-ids": { + "version": "3.0.16", + "bundled": true + }, + "ssri": { + "version": "10.0.5", + "bundled": true, "requires": { - "kind-of": "^6.0.0" + "minipass": "^7.0.3" } }, - "is-data-descriptor": { - "version": "1.0.0", - "dev": true, + "string-width": { + "version": "4.2.3", + "bundled": true, "requires": { - "kind-of": "^6.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, - "is-descriptor": { - "version": "1.0.2", - "dev": true, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "bundled": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, - "is-extendable": { - "version": "1.0.1", - "dev": true, + "strip-ansi": { + "version": "6.0.1", + "bundled": true, "requires": { - "is-plain-object": "^2.0.4" + "ansi-regex": "^5.0.1" } - } - } - }, - "natural-compare": { - "version": "1.4.0", - "dev": true - }, - "needle": { - "version": "3.2.0", - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "dev": true, - "optional": true, + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "bundled": true, "requires": { - "ms": "^2.1.1" + "ansi-regex": "^5.0.1" } - } - } - }, - "negotiator": { - "version": "0.6.3" - }, - "neo-async": { - "version": "2.6.2", - "dev": true - }, - "ng-annotate": { - "version": "1.2.2", - "dev": true, - "requires": { - "acorn": "~2.6.4", - "alter": "~0.2.0", - "convert-source-map": "~1.1.2", - "optimist": "~0.6.1", - "ordered-ast-traverse": "~1.1.1", - "simple-fmt": "~0.1.0", - "simple-is": "~0.2.0", - "source-map": "~0.5.3", - "stable": "~0.1.5", - "stringmap": "~0.2.2", - "stringset": "~0.2.1", - "tryor": "~0.1.2" - }, - "dependencies": { - "acorn": { - "version": "2.6.4", - "dev": true }, - "convert-source-map": { - "version": "1.1.3", - "dev": true + "supports-color": { + "version": "9.4.0", + "bundled": true }, - "source-map": { - "version": "0.5.7", - "dev": true - } - } - }, - "ng-csv": { - "version": "0.2.3" - }, - "ng-file-upload": { - "version": "5.0.9" - }, - "ng2-pdf-viewer": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/ng2-pdf-viewer/-/ng2-pdf-viewer-10.0.0.tgz", - "integrity": "sha512-zEefcAsTpDoxFceQYs3ycPMaUAkt5UX4OcTstVQoNqRK6w+vOY+V8z8aFCuBwnt+7iN1EHaIpquOf4S9mWc04g==", - "requires": { - "pdfjs-dist": "~2.16.105", - "tslib": "^2.3.0" - } - }, - "ngx-bootstrap": { - "version": "6.2.0", - "requires": {} - }, - "ngx-entity-service": { - "version": "0.0.37", - "resolved": "https://registry.npmjs.org/ngx-entity-service/-/ngx-entity-service-0.0.37.tgz", - "integrity": "sha512-clUk5EVKoxECHau0NB+VSvJh2hjtCd4TF5gJBFHEBBBZOZKYKagv/oQKIVntQweuKx6gQMAvy8g8CuTpUb9k0g==", - "requires": { - "tslib": "^2.3.0" - } - }, - "ngx-lottie": { - "version": "10.0.0", - "requires": { - "@scarf/scarf": "^1.1.1", - "tslib": "^2.3.0" - } - }, - "nice-napi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", - "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", - "dev": true, - "optional": true, - "requires": { - "node-addon-api": "^3.0.0", - "node-gyp-build": "^4.2.2" - } - }, - "nice-try": { - "version": "1.0.5", - "dev": true - }, - "no-case": { - "version": "2.3.2", - "dev": true, - "requires": { - "lower-case": "^1.1.1" - } - }, - "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "optional": true - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true - }, - "node-gyp": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", - "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", - "requires": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^4.0.0" - }, - "dependencies": { - "abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==" + "tar": { + "version": "6.2.0", + "bundled": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "fs-minipass": { + "version": "2.1.0", + "bundled": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass": { + "version": "5.0.0", + "bundled": true + } + } }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "text-table": { + "version": "0.2.0", + "bundled": true + }, + "tiny-relative-date": { + "version": "1.3.0", + "bundled": true + }, + "treeverse": { + "version": "3.0.0", + "bundled": true + }, + "tuf-js": { + "version": "2.2.0", + "bundled": true, "requires": { - "balanced-match": "^1.0.0" + "@tufjs/models": "2.0.0", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.0" } }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "unique-filename": { + "version": "3.0.0", + "bundled": true, "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "unique-slug": "^4.0.0" } }, - "isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" + "unique-slug": { + "version": "4.0.0", + "bundled": true, + "requires": { + "imurmurhash": "^0.1.4" + } }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, "requires": { - "brace-expansion": "^2.0.1" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "validate-npm-package-name": { + "version": "5.0.0", + "bundled": true, "requires": { - "abbrev": "^2.0.0" + "builtins": "^5.0.0" + } + }, + "walk-up-path": { + "version": "3.0.1", + "bundled": true + }, + "wcwidth": { + "version": "1.0.1", + "bundled": true, + "requires": { + "defaults": "^1.0.3" } }, "which": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "bundled": true, "requires": { "isexe": "^3.1.1" + }, + "dependencies": { + "isexe": { + "version": "3.1.1", + "bundled": true + } } + }, + "wide-align": { + "version": "1.1.5", + "bundled": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "bundled": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "bundled": true + }, + "emoji-regex": { + "version": "9.2.2", + "bundled": true + }, + "string-width": { + "version": "5.1.2", + "bundled": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "bundled": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "bundled": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "bundled": true, + "requires": { + "color-convert": "^2.0.1" + } + } + } + }, + "write-file-atomic": { + "version": "5.0.1", + "bundled": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + } + }, + "yallist": { + "version": "4.0.0", + "bundled": true } } }, - "node-gyp-build": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", - "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", - "dev": true, - "optional": true - }, - "node-machine-id": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", - "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", - "dev": true - }, - "node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true - }, - "nopt": { - "version": "3.0.6", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "devOptional": true - }, - "normalize-range": { - "version": "0.1.2", - "dev": true - }, "npm-bundled": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", @@ -37935,8 +42551,7 @@ "version": "1.0.1" }, "nvd3": { - "version": "1.8.6", - "requires": {} + "version": "1.8.6" }, "nx": { "version": "17.0.3", @@ -38625,7 +43240,7 @@ }, "picomatch": { "version": "2.3.1", - "devOptional": true + "dev": true }, "pidtree": { "version": "0.3.1", @@ -38874,8 +43489,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} + "dev": true }, "postcss-modules-local-by-default": { "version": "4.0.3", @@ -39620,7 +44234,7 @@ }, "readdirp": { "version": "3.6.0", - "devOptional": true, + "dev": true, "requires": { "picomatch": "^2.2.1" } @@ -39921,8 +44535,7 @@ "dev": true }, "rfdc": { - "version": "1.3.0", - "dev": true + "version": "1.3.0" }, "right-align": { "version": "0.1.3", @@ -41233,8 +45846,7 @@ }, "ajv-keywords": { "version": "3.5.2", - "dev": true, - "requires": {} + "dev": true }, "json-schema-traverse": { "version": "0.4.1", @@ -41440,7 +46052,7 @@ }, "to-regex-range": { "version": "5.0.1", - "devOptional": true, + "dev": true, "requires": { "is-number": "^7.0.0" } @@ -41478,8 +46090,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", - "dev": true, - "requires": {} + "dev": true }, "ts-interface-checker": { "version": "0.1.13", @@ -42072,8 +46683,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "eslint-scope": { "version": "5.1.1", @@ -42180,8 +46790,7 @@ "version": "8.14.2", "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -42342,8 +46951,7 @@ }, "ws": { "version": "8.11.0", - "dev": true, - "requires": {} + "dev": true }, "xml2js": { "version": "0.4.23", diff --git a/package.json b/package.json index 3a7fa99f4c..614fb17a03 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "@angular/service-worker": "^17.0.3", "@angular/upgrade": "^17.0.3", "@ctrl/ngx-emoji-mart": "^9.2.0", + "@swimlane/ngx-charts": "^20.5.0", "@uirouter/angular": "^12.0", "@uirouter/angular-hybrid": "^16.0", "@uirouter/angularjs": "^1.0.30", @@ -83,6 +84,7 @@ "ngx-bootstrap": "^6.1.0", "ngx-entity-service": "^0.0.37", "ngx-lottie": "^10.0.0", + "npm": "^10.4.0", "nvd3": "1.8.6", "rxjs": "~7.4.0", "showdown": "1.3.0", diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 18cf37a91b..37ae44744b 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -7,6 +7,7 @@ import { UpgradeModule } from '@angular/upgrade/static'; import { AppInjector, setAppInjector } from './app-injector'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NgxChartsModule } from '@swimlane/ngx-charts'; // Lottie animation module import { LottieModule, LottieCacheModule } from 'ngx-lottie'; @@ -229,6 +230,8 @@ import { FUnitTaskListComponent } from './units/states/tasks/viewer/directives/f import { FTaskDetailsViewComponent } from './units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component'; import { FTaskSheetViewComponent } from './units/states/tasks/viewer/directives/f-task-sheet-view/f-task-sheet-view.component'; import { TasksViewerComponent } from './units/states/tasks/tasks-viewer/tasks-viewer.component'; +import { ProgressBurndownChartComponent } from './visualisations/progress-burndown-chart/progressburndownchart.component'; +import { TaskVisualisationComponent } from './visualisations/task-visualisation/taskvisualisation.component'; @NgModule({ // Components we declare @@ -327,6 +330,9 @@ import { TasksViewerComponent } from './units/states/tasks/tasks-viewer/tasks-vi TasksViewerComponent, FUsersComponent, FUnitsComponent, + ProgressBurndownChartComponent, + TaskVisualisationComponent + ], // Module Imports imports: [ @@ -390,6 +396,7 @@ import { TasksViewerComponent } from './units/states/tasks/tasks-viewer/tasks-vi MatDatepickerModule, MatNativeDateModule, MatDialogModuleNew, + NgxChartsModule ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index e84dd192a2..c827862990 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -239,6 +239,8 @@ import { FUnitTaskListComponent } from './units/states/tasks/viewer/directives/f import { FTaskDetailsViewComponent } from './units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component'; import { FTaskSheetViewComponent } from './units/states/tasks/viewer/directives/f-task-sheet-view/f-task-sheet-view.component'; import { TasksViewerComponent } from './units/states/tasks/tasks-viewer/tasks-viewer.component'; +import { ProgressBurndownChartComponent } from './visualisations/progress-burndown-chart/progressburndownchart.component'; +import { TaskVisualisationComponent } from './visualisations/task-visualisation/taskvisualisation.component'; import { FUnitsComponent } from './admin/states/f-units/f-units.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ @@ -398,3 +400,14 @@ const otherwiseConfigBlock = [ }, ]; DoubtfireAngularJSModule.config(otherwiseConfigBlock); + + +DoubtfireAngularJSModule.directive( + 'appProgressBurndownChart', + downgradeComponent({ component: ProgressBurndownChartComponent }) +); + +DoubtfireAngularJSModule.directive( + 'appTaskVisualisation', + downgradeComponent({ component: TaskVisualisationComponent }) +); diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.tpl.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.tpl.html index 763c0e37ce..d2becf0880 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.tpl.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.tpl.html @@ -26,7 +26,7 @@

Progress Burndown

- +
- - + +
- - +
From 64b1bfb2918993e58a6659948d9621fc7d0b8ba4 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Sat, 13 Apr 2024 21:56:47 +1000 Subject: [PATCH 0062/1531] fix: use modal for Numbas and enable authentication --- src/app/ajs-upgraded-providers.ts | 7 ++ src/app/api/services/numbas.service.ts | 55 -------------- .../api/services/spec/numbas.service.spec.ts | 66 ---------------- .../numbas-component.component.html | 7 +- .../numbas-component.component.scss | 17 +++++ .../numbas-component.component.ts | 76 ++++++------------- .../numbas-modal.component.ts | 20 +++++ src/app/doubtfire-angular.module.ts | 4 +- src/app/doubtfire-angularjs.module.ts | 2 + .../upload-submission-modal.coffee | 5 +- .../upload-submission-modal.tpl.html | 6 +- 11 files changed, 83 insertions(+), 182 deletions(-) delete mode 100644 src/app/api/services/numbas.service.ts delete mode 100644 src/app/api/services/spec/numbas.service.spec.ts create mode 100644 src/app/common/numbas-component/numbas-modal.component.ts diff --git a/src/app/ajs-upgraded-providers.ts b/src/app/ajs-upgraded-providers.ts index 795869225d..9d5b0f0203 100644 --- a/src/app/ajs-upgraded-providers.ts +++ b/src/app/ajs-upgraded-providers.ts @@ -18,6 +18,7 @@ export const rootScope = new InjectionToken('$rootScope'); export const calendarModal = new InjectionToken('CalendarModal'); export const aboutDoubtfireModal = new InjectionToken('AboutDoubtfireModal'); export const plagiarismReportModal = new InjectionToken('PlagiarismReportModal'); +export const numbasModal = new InjectionToken('NumbasModal'); // Define a provider for the above injection token... // It will get the service from AngularJS via the factory @@ -116,3 +117,9 @@ export const UnitStudentEnrolmentModalProvider = { useFactory: (i) => i.get('UnitStudentEnrolmentModal'), deps: ['$injector'], }; + +export const numbasModalProvider = { + provide: numbasModal, + useFactory: (i) => i.get('NumbasModal'), + deps: ['$injector'], +}; \ No newline at end of file diff --git a/src/app/api/services/numbas.service.ts b/src/app/api/services/numbas.service.ts deleted file mode 100644 index f8812f1ac7..0000000000 --- a/src/app/api/services/numbas.service.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { Observable, throwError } from 'rxjs'; -import { catchError, map, retry } from 'rxjs/operators'; -import API_URL from 'src/app/config/constants/apiURL'; - -@Injectable({ - providedIn: 'root' -}) -export class NumbasService { - constructor(private http: HttpClient) {} - - /** - * Fetches a specified resource for a given unit and task. - * - * @param taskDefId - The ID of the task definition - * @param resourcePath - Path to the desired resource - * @returns An Observable with the Blob of the fetched resource - */ - fetchResource(taskDefId: number, resourcePath: string): Observable { - const resourceUrl = `${API_URL}/numbas_api/${taskDefId}/${resourcePath}`; - const resourceMimeType = this.getMimeType(resourcePath); - - return this.http.get(resourceUrl, { responseType: 'blob' }).pipe( - retry(3), - map((blob) => new Blob([blob], { type: resourceMimeType })), - catchError((error: HttpErrorResponse) => { - console.error('Error fetching Numbas resource:', error); - return throwError('Error fetching Numbas resource.'); - }) - ); - } - - /** - * Determines the MIME type of a resource based on its extension. - * - * @param resourcePath - Path of the resource - * @returns MIME type string corresponding to the resource's extension - */ - getMimeType(resourcePath: string): string { - const extension = resourcePath.split('.').pop()?.toLowerCase(); - const mimeTypeMap: { [key: string]: string } = { - 'html': 'text/html', - 'css': 'text/css', - 'js': 'application/javascript', - 'json': 'application/json', - 'png': 'image/png', - 'jpg': 'image/jpeg', - 'gif': 'image/gif', - 'svg': 'image/svg+xml' - }; - - return mimeTypeMap[extension || ''] || 'text/plain'; - } -} diff --git a/src/app/api/services/spec/numbas.service.spec.ts b/src/app/api/services/spec/numbas.service.spec.ts deleted file mode 100644 index a29b13e149..0000000000 --- a/src/app/api/services/spec/numbas.service.spec.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { TestBed, fakeAsync, tick } from '@angular/core/testing'; -import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; -import { NumbasService } from '../numbas.service'; -import { HttpRequest } from '@angular/common/http'; - - -describe('NumbasService', () => { - let numbasService: NumbasService; - let httpMock: HttpTestingController; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [HttpClientTestingModule], - providers: [NumbasService], - }); - - numbasService = TestBed.inject(NumbasService); - httpMock = TestBed.inject(HttpTestingController); - }); - - afterEach(() => { - httpMock.verify(); - }); - - it('should fetch resource as expected', fakeAsync(() => { - const dummyBlob = new Blob(['dummy blob'], { type: 'text/html' }); - - const unitId = 'sampleUnitId'; - const taskId = 'sampleTaskId'; - const resourcePath = 'sampleResource.html'; - - numbasService.fetchResource(unitId, taskId, resourcePath).subscribe((blob) => { - expect(blob.size).toBe(dummyBlob.size); - expect(blob.type).toBe(dummyBlob.type); - }); - - const req = httpMock.expectOne(`http://localhost:3000/api/numbas_api/${unitId}/${taskId}/${resourcePath}`); - expect(req.request.method).toBe('GET'); - - req.flush(dummyBlob); - - tick(); - })); - - it('should upload test as expected', fakeAsync(() => { - const dummyResponse = { success: true, message: 'File uploaded successfully' }; - - const unitId = 'sampleUnitId'; - const taskId = 'sampleTaskId'; - const file = new File(['dummy content'], 'sample.txt', { type: 'text/plain' }); - - numbasService.uploadTest(unitId, taskId, file).subscribe((response) => { - expect(response).toEqual(dummyResponse); - }); - - const req = httpMock.expectOne(`http://localhost:3000/api/numbas_api/uploadNumbasTest`); - expect(req.request.method).toBe('POST'); - - req.flush(dummyResponse); - - tick(); - })); - -}); - - diff --git a/src/app/common/numbas-component/numbas-component.component.html b/src/app/common/numbas-component/numbas-component.component.html index dba53ea116..d562f02239 100644 --- a/src/app/common/numbas-component/numbas-component.component.html +++ b/src/app/common/numbas-component/numbas-component.component.html @@ -1,3 +1,4 @@ - +
+ + +
\ No newline at end of file diff --git a/src/app/common/numbas-component/numbas-component.component.scss b/src/app/common/numbas-component/numbas-component.component.scss index e69de29bb2..5e24cc5d9e 100644 --- a/src/app/common/numbas-component/numbas-component.component.scss +++ b/src/app/common/numbas-component/numbas-component.component.scss @@ -0,0 +1,17 @@ +.mat-dialog-content { + position: relative; +} + +iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 95%; +} + +button { + position: absolute; + bottom: 20px; + right: 20px; +} \ No newline at end of file diff --git a/src/app/common/numbas-component/numbas-component.component.ts b/src/app/common/numbas-component/numbas-component.component.ts index 529a64b9ae..6c8369ab77 100644 --- a/src/app/common/numbas-component/numbas-component.component.ts +++ b/src/app/common/numbas-component/numbas-component.component.ts @@ -1,7 +1,11 @@ -import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core'; +import { Component, OnInit, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { Task } from 'src/app/api/models/task'; import { NumbasLmsService } from 'src/app/api/services/numbas-lms.service'; -import { NumbasService } from 'src/app/api/services/numbas.service'; +import { UserService } from 'src/app/api/services/user.service'; +import { AppInjector } from 'src/app/app-injector'; +import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; declare global { interface Window { API_1484_11: any; } @@ -10,20 +14,29 @@ declare global { @Component({ selector: 'f-numbas-component', templateUrl: './numbas-component.component.html', - styleUrls: ['numbas-component.component.scss'], + styleUrls: ['./numbas-component.component.scss'], }) -export class NumbasComponent implements OnInit, OnChanges { - @Input() task: Task; - +export class NumbasComponent implements OnInit { + task: Task; currentMode: 'attempt' | 'review' = 'attempt'; + iframeSrc: SafeResourceUrl; constructor( - private numbasService: NumbasService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { task: Task, mode: 'attempt' | 'review' }, private lmsService: NumbasLmsService, + private userService: UserService, + private sanitizer: DomSanitizer ) {} ngOnInit(): void { - this.interceptIframeRequests(); + this.task = this.data.task; + this.lmsService.setTask(this.task); + + this.currentMode = this.data.mode; + + const user = this.userService.currentUser; + this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(`${AppInjector.get(DoubtfireConstants).API_URL}/numbas_api/${this.task.taskDefId}/${user.authenticationToken}/${user.username}/index.html`); window.API_1484_11 = { Initialize: () => this.lmsService.Initialize(this.currentMode), @@ -37,50 +50,7 @@ export class NumbasComponent implements OnInit, OnChanges { }; } - ngOnChanges(changes: SimpleChanges): void { - if (changes.task) { - this.task = changes.task.currentValue; - this.lmsService.setTask(this.task); - } - } - - launchNumbasTest(mode: 'attempt' | 'review' = 'attempt'): void { - this.currentMode = mode; - - const iframe = document.createElement('iframe'); - iframe.src = `http://localhost:3000/api/numbas_api/${this.task.taskDefId}/index.html`; - - iframe.style.position = 'fixed'; - iframe.style.top = '0'; - iframe.style.left = '0'; - iframe.style.width = '100%'; - iframe.style.height = '100%'; - iframe.style.zIndex = '9999'; - - document.body.appendChild(iframe); - } - - interceptIframeRequests(): void { - const originalOpen = XMLHttpRequest.prototype.open; - const numbasService = this.numbasService; - const taskDefId = this.task.taskDefId; - XMLHttpRequest.prototype.open = function (this: XMLHttpRequest, method: string, url: string | URL, async: boolean = true, username?: string | null, password?: string | null) { - if (typeof url === 'string' && url.startsWith('/api/numbas_api/')) { - const resourcePath = url.replace('/api/numbas_api/', ''); - this.abort(); - numbasService.fetchResource(taskDefId, resourcePath).subscribe( - (resourceData) => { - if (this.onload) { - this.onload.call(this, resourceData); - } - }, - (error) => { - console.error('Error fetching Numbas resource:', error); - } - ); - } else { - originalOpen.call(this, method, url, async, username, password); - } - }; + removeNumbasTest(): void { + this.dialogRef.close(); } } diff --git a/src/app/common/numbas-component/numbas-modal.component.ts b/src/app/common/numbas-component/numbas-modal.component.ts new file mode 100644 index 0000000000..73b2122c17 --- /dev/null +++ b/src/app/common/numbas-component/numbas-modal.component.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; +import { NumbasComponent } from './numbas-component.component'; +import { Task } from 'src/app/api/models/task'; + +@Injectable({ + providedIn: 'root', +}) +export class NumbasModal { + constructor(public dialog: MatDialog) { } + + public show(task: Task, mode: 'attempt' | 'review'): void { + let dialogRef: MatDialogRef; + + dialogRef = this.dialog.open(NumbasComponent, { + data: { task, mode }, + width: '95%', height: '90%' + }); + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index d15c23b234..48f54027d1 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -226,7 +226,7 @@ import {TasksViewerComponent} from './units/states/tasks/tasks-viewer/tasks-view import {UnitCodeComponent} from './common/unit-code/unit-code.component'; import {GradeService} from './common/services/grade.service'; import {NumbasComponent} from './common/numbas-component/numbas-component.component'; -import {NumbasService} from './api/services/numbas.service'; +import {NumbasModal} from './common/numbas-component/numbas-modal.component'; import {NumbasLmsService} from './api/services/numbas-lms.service'; @NgModule({ @@ -402,7 +402,7 @@ import {NumbasLmsService} from './api/services/numbas-lms.service'; TasksForInboxSearchPipe, IsActiveUnitRole, CreateNewUnitModal, - NumbasService, + NumbasModal, NumbasLmsService, provideLottieOptions({ player: () => player, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 317094dc2e..b88fbeb298 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -226,6 +226,7 @@ import {MarkedPipe} from './common/pipes/marked.pipe'; import {AlertService} from './common/services/alert.service'; import {GradeService} from './common/services/grade.service'; import {NumbasComponent} from './common/numbas-component/numbas-component.component'; +import {NumbasModal} from './common/numbas-component/numbas-modal.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -308,6 +309,7 @@ DoubtfireAngularJSModule.factory( downgradeInjectable(EditProfileDialogService), ); DoubtfireAngularJSModule.factory('CreateNewUnitModal', downgradeInjectable(CreateNewUnitModal)); +DoubtfireAngularJSModule.factory('NumbasModal', downgradeInjectable(NumbasModal)); // directive -> component DoubtfireAngularJSModule.directive( diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee index 485843f780..68d742362e 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee @@ -32,7 +32,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) UploadSubmissionModal ) -.controller('UploadSubmissionModalCtrl', ($scope, $rootScope, $timeout, $modalInstance, newTaskService, newProjectService, task, reuploadEvidence, outcomeService, PrivacyPolicy) -> +.controller('UploadSubmissionModalCtrl', ($scope, $rootScope, $timeout, $modalInstance, NumbasModal, newTaskService, newProjectService, task, reuploadEvidence, outcomeService, PrivacyPolicy) -> $scope.privacyPolicy = PrivacyPolicy # Expose task to scope $scope.task = task @@ -155,6 +155,9 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) previous: states.previous } + $scope.launchNumbasDialog = -> + NumbasModal.show $scope.task, 'attempt' + # Whether or not we should disable this button $scope.shouldDisableBtn = { next: -> diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html index 0b99e7eb8f..0527aadd40 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html @@ -52,12 +52,14 @@

Attempt Numbas Test

- + Complete the Numbas test first to proceed to upload evidence of your task completion.
- +
From bcaa8af150aaf68b5cf5fb07ad9cb72037212d5d Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Fri, 26 Apr 2024 22:10:46 +1000 Subject: [PATCH 0063/1531] fix: add accepted Numbas file types --- .../task-definition-numbas.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.ts index 6588453430..f6687a4af9 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.ts @@ -41,7 +41,9 @@ export class TaskDefinitionNumbasComponent { } public uploadNumbasTest(files: FileList) { - const validFiles = Array.from(files as ArrayLike).filter((f) => f.type === 'application/zip'); + console.log(Array.from(files).map(f => f.type)); + const validMimeTypes = ['application/zip', 'application/x-zip-compressed', 'multipart/x-zip']; + const validFiles = Array.from(files as ArrayLike).filter(f => validMimeTypes.includes(f.type)); if (validFiles.length > 0) { const file = validFiles[0]; this.taskDefinitionService.uploadNumbasData(this.taskDefinition, file).subscribe({ From 5d0606c56eaeb929d5873cae7038ce729581512c Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 30 Apr 2024 11:30:07 +1000 Subject: [PATCH 0064/1531] fix: initialise SCORM API wrapper before iframe loads --- .../numbas-component/numbas-component.component.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/app/common/numbas-component/numbas-component.component.ts b/src/app/common/numbas-component/numbas-component.component.ts index 6c8369ab77..488c0a6333 100644 --- a/src/app/common/numbas-component/numbas-component.component.ts +++ b/src/app/common/numbas-component/numbas-component.component.ts @@ -3,7 +3,6 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { Task } from 'src/app/api/models/task'; import { NumbasLmsService } from 'src/app/api/services/numbas-lms.service'; -import { UserService } from 'src/app/api/services/user.service'; import { AppInjector } from 'src/app/app-injector'; import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; @@ -25,7 +24,6 @@ export class NumbasComponent implements OnInit { private dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: { task: Task, mode: 'attempt' | 'review' }, private lmsService: NumbasLmsService, - private userService: UserService, private sanitizer: DomSanitizer ) {} @@ -33,11 +31,6 @@ export class NumbasComponent implements OnInit { this.task = this.data.task; this.lmsService.setTask(this.task); - this.currentMode = this.data.mode; - - const user = this.userService.currentUser; - this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(`${AppInjector.get(DoubtfireConstants).API_URL}/numbas_api/${this.task.taskDefId}/${user.authenticationToken}/${user.username}/index.html`); - window.API_1484_11 = { Initialize: () => this.lmsService.Initialize(this.currentMode), Terminate: () => this.lmsService.Terminate(), @@ -48,6 +41,10 @@ export class NumbasComponent implements OnInit { GetErrorString: (errorCode: string) => this.lmsService.GetErrorString(errorCode), GetDiagnostic: (errorCode: string) => this.lmsService.GetDiagnostic(errorCode) }; + + this.currentMode = this.data.mode; + + this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(`${AppInjector.get(DoubtfireConstants).API_URL}/numbas_api/${this.task.taskDefId}/index.html`); } removeNumbasTest(): void { From 2810ce65d423a137600d621a98bf27dbc221921c Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 30 Apr 2024 11:32:29 +1000 Subject: [PATCH 0065/1531] fix: retrieve test attempt data correctly --- src/app/api/services/numbas-lms.service.ts | 29 ++++++++-------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/app/api/services/numbas-lms.service.ts b/src/app/api/services/numbas-lms.service.ts index de5a25bcc9..a24c8d31ed 100644 --- a/src/app/api/services/numbas-lms.service.ts +++ b/src/app/api/services/numbas-lms.service.ts @@ -1,7 +1,5 @@ -import { Injectable, Input } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { BehaviorSubject, Observable, throwError } from 'rxjs'; -import { TaskService } from './task.service'; +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; import { UserService } from './user.service'; import API_URL from 'src/app/config/constants/apiURL'; import { Task } from '../models/task'; @@ -10,7 +8,6 @@ import { Task } from '../models/task'; providedIn: 'root' }) export class NumbasLmsService { - private readonly apiBaseUrl = `${API_URL}/test_attempts`; private defaultValues: { [key: string]: string } = { @@ -35,11 +32,7 @@ export class NumbasLmsService { dataStore: { [key: string]: any } = this.getDefaultDataStore(); - constructor( - private http: HttpClient, - private taskService: TaskService, - private userService: UserService - ) { + constructor(private userService: UserService) { this.learnerId = this.userService.currentUser.studentId; } @@ -74,7 +67,7 @@ export class NumbasLmsService { try { const completedTest = JSON.parse(xhr.responseText); - const parsedExamData = JSON.parse(completedTest.data.exam_data || '{}'); + const parsedExamData = JSON.parse(completedTest.exam_data || '{}'); // Set entire suspendData string to cmi.suspend_data this.SetValue('cmi.suspend_data', JSON.stringify(parsedExamData)); @@ -108,17 +101,17 @@ export class NumbasLmsService { try { latestTest = JSON.parse(xhr.responseText); console.log('Latest test result:', latestTest); - this.testId = latestTest.data.id; + this.testId = latestTest.id; - if (latestTest.data['cmi_entry'] === 'ab-initio') { + if (latestTest['cmi_entry'] === 'ab-initio') { console.log("starting new test"); this.SetValue('cmi.learner_id', this.learnerId); this.dataStore['name'] = examName; - this.dataStore['attempt_number'] = latestTest.data['attempt_number']; + this.dataStore['attempt_number'] = latestTest['attempt_number']; console.log(this.dataStore); - } else if (latestTest.data['cmi_entry'] === 'resume') { + } else if (latestTest['cmi_entry'] === 'resume') { console.log("resuming test"); - const parsedExamData = JSON.parse(latestTest.data.exam_data || '{}'); + const parsedExamData = JSON.parse(latestTest.exam_data || '{}'); this.dataStore = JSON.parse(JSON.stringify(parsedExamData)); @@ -127,7 +120,7 @@ export class NumbasLmsService { this.initializationComplete$.next(true); - console.log("finished initlizing"); + console.log("finished initializing"); return 'true'; } catch (error) { console.error('Error:', error); @@ -153,7 +146,7 @@ export class NumbasLmsService { this.SetValue('cmi.entry', 'RO'); const cmientry = this.GetValue('cmi.entry'); const data = { - task_id: this.taskId, + id: this.taskId, name: ExamName, attempt_number: currentAttemptNumber, pass_status: status === 'passed', From e46214dd59d86014bb04d1c31f3a3bf21240e32b Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 30 Apr 2024 13:02:50 +1000 Subject: [PATCH 0066/1531] fix: send task id with numbas completed attempt data --- src/app/api/services/numbas-lms.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/api/services/numbas-lms.service.ts b/src/app/api/services/numbas-lms.service.ts index a24c8d31ed..40ce0942b3 100644 --- a/src/app/api/services/numbas-lms.service.ts +++ b/src/app/api/services/numbas-lms.service.ts @@ -69,7 +69,7 @@ export class NumbasLmsService { const completedTest = JSON.parse(xhr.responseText); const parsedExamData = JSON.parse(completedTest.exam_data || '{}'); - // Set entire suspendData string to cmi.suspend_data + // Set entire parsedExamData string to cmi.suspend_data this.SetValue('cmi.suspend_data', JSON.stringify(parsedExamData)); // Use SetValue to set parsedExamData values to dataStore @@ -146,14 +146,14 @@ export class NumbasLmsService { this.SetValue('cmi.entry', 'RO'); const cmientry = this.GetValue('cmi.entry'); const data = { - id: this.taskId, name: ExamName, attempt_number: currentAttemptNumber, pass_status: status === 'passed', exam_data: JSON.stringify(this.dataStore), completed: true, exam_result: examResult, - cmi_entry: cmientry + cmi_entry: cmientry, + task_id: this.taskId }; const xhr = new XMLHttpRequest(); From 84646dcf7b28c65c8c28f046197d08d3325795be Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Sun, 5 May 2024 16:33:19 +1000 Subject: [PATCH 0067/1531] refactor: modify numbas files to match PoC --- src/app/api/services/numbas-lms.service.ts | 38 +++++++++---------- .../services/spec/numbas-lms.service.spec.ts | 2 +- .../numbas-component.component.ts | 2 + 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/app/api/services/numbas-lms.service.ts b/src/app/api/services/numbas-lms.service.ts index 40ce0942b3..6479a6ed93 100644 --- a/src/app/api/services/numbas-lms.service.ts +++ b/src/app/api/services/numbas-lms.service.ts @@ -17,7 +17,7 @@ export class NumbasLmsService { 'numbas.duration_extension.units': 'seconds', 'cmi.mode': 'normal', 'cmi.undefinedlearner_response': '1', - 'cmi.undefinedresult' : '0' + 'cmi.undefinedresult': '0' }; private testId: number = 0; @@ -67,14 +67,14 @@ export class NumbasLmsService { try { const completedTest = JSON.parse(xhr.responseText); - const parsedExamData = JSON.parse(completedTest.exam_data || '{}'); + let parsedSuspendData = JSON.parse(completedTest.data.suspend_data || '{}'); - // Set entire parsedExamData string to cmi.suspend_data - this.SetValue('cmi.suspend_data', JSON.stringify(parsedExamData)); + // Set entire suspendData string to cmi.suspend_data + this.SetValue('cmi.suspend_data', JSON.stringify(parsedSuspendData)); - // Use SetValue to set parsedExamData values to dataStore - Object.keys(parsedExamData).forEach(key => { - this.SetValue(key, parsedExamData[key]); + // Use SetValue to set parsedSuspendData values to dataStore + Object.keys(parsedSuspendData).forEach(key => { + this.SetValue(key, parsedSuspendData[key]); }); this.SetValue('cmi.entry', 'RO'); @@ -101,19 +101,19 @@ export class NumbasLmsService { try { latestTest = JSON.parse(xhr.responseText); console.log('Latest test result:', latestTest); - this.testId = latestTest.id; + this.testId = latestTest.data.id; - if (latestTest['cmi_entry'] === 'ab-initio') { + if (latestTest.data['cmi_entry'] === 'ab-initio') { console.log("starting new test"); this.SetValue('cmi.learner_id', this.learnerId); this.dataStore['name'] = examName; - this.dataStore['attempt_number'] = latestTest['attempt_number']; + this.dataStore['attempt_number'] = latestTest.data['attempt_number']; console.log(this.dataStore); - } else if (latestTest['cmi_entry'] === 'resume') { + } else if (latestTest.data['cmi_entry'] === 'resume') { console.log("resuming test"); - const parsedExamData = JSON.parse(latestTest.exam_data || '{}'); + let parsedSuspendData = JSON.parse(latestTest.data.suspend_data || '{}'); - this.dataStore = JSON.parse(JSON.stringify(parsedExamData)); + this.dataStore = JSON.parse(JSON.stringify(parsedSuspendData)); console.log(this.dataStore); } @@ -149,7 +149,7 @@ export class NumbasLmsService { name: ExamName, attempt_number: currentAttemptNumber, pass_status: status === 'passed', - exam_data: JSON.stringify(this.dataStore), + suspend_data: JSON.stringify(this.dataStore), completed: true, exam_result: examResult, cmi_entry: cmientry, @@ -184,7 +184,7 @@ export class NumbasLmsService { return 'true'; } - //function to save the state of the exam. + // Saves the state of the exam. Commit(): string { if (!this.initializationComplete$.getValue()) { console.warn('Initialization not complete. Cannot commit.'); @@ -198,12 +198,9 @@ export class NumbasLmsService { } console.log("Committing dataStore:", this.dataStore); - // Directly stringify the dataStore - const jsonData = JSON.stringify(this.dataStore); - // Use XHR to send the request const xhr = new XMLHttpRequest(); - xhr.open('PUT', `${this.apiBaseUrl}/${this.testId}/exam_data`, true); + xhr.open('PUT', `${this.apiBaseUrl}/${this.testId}/suspend`, true); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onload = () => { @@ -218,7 +215,8 @@ export class NumbasLmsService { console.error('Request failed.'); }; - xhr.send(jsonData); + const requestData = { suspend_data: this.dataStore }; + xhr.send(JSON.stringify(requestData)); return 'true'; } diff --git a/src/app/api/services/spec/numbas-lms.service.spec.ts b/src/app/api/services/spec/numbas-lms.service.spec.ts index f456d5a894..7d29ef75e0 100644 --- a/src/app/api/services/spec/numbas-lms.service.spec.ts +++ b/src/app/api/services/spec/numbas-lms.service.spec.ts @@ -55,7 +55,7 @@ describe('NumbasLmsService', () => { it('should handle review mode and get latest completed test result', () => { const mockResponse = { data: { - exam_data: JSON.stringify({ someData: 'value' }) + suspend_data: JSON.stringify({ someData: 'value' }) } }; diff --git a/src/app/common/numbas-component/numbas-component.component.ts b/src/app/common/numbas-component/numbas-component.component.ts index 488c0a6333..f5453e0dcc 100644 --- a/src/app/common/numbas-component/numbas-component.component.ts +++ b/src/app/common/numbas-component/numbas-component.component.ts @@ -48,6 +48,8 @@ export class NumbasComponent implements OnInit { } removeNumbasTest(): void { + const iframe = document.getElementsByTagName('iframe')[0]; + iframe?.parentNode?.removeChild(iframe); this.dialogRef.close(); } } From 48a31da1442f1e14f497c614053d9002c9f2631b Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 7 May 2024 03:00:27 +1000 Subject: [PATCH 0068/1531] feat: display numbas task comments --- src/app/api/models/task.ts | 6 +++ src/app/doubtfire-angular.module.ts | 2 + .../numbas-comment.component.html | 10 ++++ .../numbas-comment.component.scss | 51 +++++++++++++++++++ .../numbas-comment.component.ts | 21 ++++++++ .../task-comments-viewer.component.html | 8 +++ .../task-comments-viewer.component.scss | 2 +- .../task-comments-viewer.component.ts | 6 ++- 8 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.html create mode 100644 src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.scss create mode 100644 src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index 2aa167adfd..403165cfee 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -507,6 +507,12 @@ export class Task extends Entity { ); } + public get numbasEnabled(): boolean { + return ( + this.definition.hasEnabledNumbasTest && this.definition.hasNumbasData + ); + } + public submissionUrl(asAttachment: boolean = false): string { return `${AppInjector.get(DoubtfireConstants).API_URL}/projects/${ this.project.id diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 48f54027d1..c634965f6f 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -228,6 +228,7 @@ import {GradeService} from './common/services/grade.service'; import {NumbasComponent} from './common/numbas-component/numbas-component.component'; import {NumbasModal} from './common/numbas-component/numbas-modal.component'; import {NumbasLmsService} from './api/services/numbas-lms.service'; +import {NumbasCommentComponent} from './tasks/task-comments-viewer/numbas-comment/numbas-comment.component'; @NgModule({ // Components we declare @@ -331,6 +332,7 @@ import {NumbasLmsService} from './api/services/numbas-lms.service'; FTaskBadgeComponent, FUnitsComponent, NumbasComponent, + NumbasCommentComponent, ], // Services we provide providers: [ diff --git a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.html b/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.html new file mode 100644 index 0000000000..d87863bee8 --- /dev/null +++ b/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.html @@ -0,0 +1,10 @@ +
+
+
+
+
+ +
+
+
+
diff --git a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.scss b/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.scss new file mode 100644 index 0000000000..31df73023a --- /dev/null +++ b/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.scss @@ -0,0 +1,51 @@ +div { + width: 100%; +} + +p { + color: #2c2c2c; + text-align: center; +} + +hr { + width: 100%; +} + +.hr-fade { + background: linear-gradient(to right, transparent, #9696969d, transparent); + width: 100%; + margin-top: 1px; +} + +.hr-text { + margin: 0; + line-height: 1em; + position: relative; + outline: 0; + border: 0; + color: black; + text-align: center; + height: 1.5em; + opacity: 0.8; + &:before { + content: ""; + background: linear-gradient(to right, transparent, #9696969d, transparent); + position: absolute; + left: 0; + top: 50%; + width: 100%; + height: 1px; + } + &:after { + content: attr(data-content); + position: relative; + display: inline-block; + color: black; + + padding: 0 0.5em; + line-height: 1.5em; + + color: #9696969d; + background-color: #fff; + } +} diff --git a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts b/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts new file mode 100644 index 0000000000..eed512fe19 --- /dev/null +++ b/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts @@ -0,0 +1,21 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { Task, TaskComment } from 'src/app/api/models/doubtfire-model'; +import { NumbasModal } from 'src/app/common/numbas-component/numbas-modal.component'; + +@Component({ + selector: 'numbas-comment', + templateUrl: './numbas-comment.component.html', + styleUrls: ['./numbas-comment.component.scss'], +}) +export class NumbasCommentComponent implements OnInit { + @Input() task: Task; + @Input() comment: TaskComment; + + constructor(private modalService: NumbasModal) {} + + ngOnInit() {} + + reviewNumbasTest() { + this.modalService.show(this.task, 'review'); + } +} diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html index d104df63af..cd18eda9ba 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html @@ -72,6 +72,14 @@ > +
+ +
+
{ if ( @@ -150,7 +154,7 @@ export class TaskCommentsViewerComponent implements OnChanges, OnInit { } shouldShowAuthorIcon(commentType: string) { - return !(commentType === 'extension' || commentType === 'status' || commentType == 'assessment'); + return !(commentType === 'extension' || commentType === 'status' || commentType == 'assessment' || commentType == 'numbas'); } commentClasses(comment: TaskComment): object { From 0652b56f69eb850c2dfb43be54d07beb4c4eb469 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 7 May 2024 07:10:54 +1000 Subject: [PATCH 0069/1531] feat: add test attempt service and minor numbas related changes --- src/app/api/models/test-attempt.ts | 14 +++++++++++--- src/app/api/services/numbas-lms.service.ts | 12 ++++++------ src/app/api/services/task-comment.service.ts | 2 +- src/app/doubtfire-angular.module.ts | 2 ++ src/app/doubtfire-angularjs.module.ts | 2 ++ .../upload-submission-modal.coffee | 2 +- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/app/api/models/test-attempt.ts b/src/app/api/models/test-attempt.ts index 77e4af1724..e6f2e5d61d 100644 --- a/src/app/api/models/test-attempt.ts +++ b/src/app/api/models/test-attempt.ts @@ -1,14 +1,22 @@ import { Entity } from "ngx-entity-service"; +import { Task } from "./task"; export class TestAttempt extends Entity { - id: number; + public id: number; name: string; attemptNumber: number; passStatus: boolean; - examData: string; + suspendData: string; completed: boolean; cmiEntry: string; examResult: string; attemptedAt: Date; - associatedTaskId: number; + taskId: number; + + task: Task; + + constructor(task: Task) { + super(); + this.task = task; + } } diff --git a/src/app/api/services/numbas-lms.service.ts b/src/app/api/services/numbas-lms.service.ts index 6479a6ed93..59d94e0526 100644 --- a/src/app/api/services/numbas-lms.service.ts +++ b/src/app/api/services/numbas-lms.service.ts @@ -21,7 +21,7 @@ export class NumbasLmsService { }; private testId: number = 0; - private taskId: number; + private task: Task; private learnerId: string; initializationComplete$ = new BehaviorSubject(false); @@ -37,7 +37,7 @@ export class NumbasLmsService { } setTask(task: Task) { - this.taskId = task.id; + this.task = task; } getDefaultDataStore() { @@ -56,7 +56,7 @@ export class NumbasLmsService { if (mode === 'review') { this.SetValue('cmi.mode', 'review'); - xhr.open("GET", `${this.apiBaseUrl}/completed-latest?task_id=${this.taskId}`, false); + xhr.open("GET", `${this.apiBaseUrl}/completed-latest?task_id=${this.task.id}`, false); xhr.send(); console.log(xhr.responseText); @@ -88,7 +88,7 @@ export class NumbasLmsService { } } - xhr.open("GET", `${this.apiBaseUrl}/latest?task_id=${this.taskId}`, false); + xhr.open("GET", `${this.apiBaseUrl}/latest?task_id=${this.task.id}`, false); xhr.send(); console.log(xhr.responseText); @@ -139,7 +139,7 @@ export class NumbasLmsService { Terminate(): string { console.log('Terminate Called'); const examResult = this.dataStore["cmi.score.raw"]; - const status = this.GetValue("cmi.completion_status"); + const status = this.GetValue("cmi.success_status"); this.dataStore['completed'] = true; const currentAttemptNumber = this.dataStore['attempt_number'] || 0; const ExamName = this.dataStore['name']; @@ -153,7 +153,7 @@ export class NumbasLmsService { completed: true, exam_result: examResult, cmi_entry: cmientry, - task_id: this.taskId + task_id: this.task.id }; const xhr = new XMLHttpRequest(); diff --git a/src/app/api/services/task-comment.service.ts b/src/app/api/services/task-comment.service.ts index 9e646be77d..e3c80797a4 100644 --- a/src/app/api/services/task-comment.service.ts +++ b/src/app/api/services/task-comment.service.ts @@ -145,7 +145,7 @@ export class TaskCommentService extends CachedEntityService { const opts: RequestOptions = { endpointFormat: this.commentEndpointFormat }; // Based on the comment type - add to the body and configure the end point - if (commentType === 'text') { + if (commentType === 'text' || commentType === 'numbas') { body.append('comment', data); } else if (commentType === 'discussion') { opts.endpointFormat = this.discussionEndpointFormat; diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index c634965f6f..e1f4d2356f 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -229,6 +229,7 @@ import {NumbasComponent} from './common/numbas-component/numbas-component.compon import {NumbasModal} from './common/numbas-component/numbas-modal.component'; import {NumbasLmsService} from './api/services/numbas-lms.service'; import {NumbasCommentComponent} from './tasks/task-comments-viewer/numbas-comment/numbas-comment.component'; +import {TestAttemptService} from './api/services/test-attempt.service'; @NgModule({ // Components we declare @@ -406,6 +407,7 @@ import {NumbasCommentComponent} from './tasks/task-comments-viewer/numbas-commen CreateNewUnitModal, NumbasModal, NumbasLmsService, + TestAttemptService, provideLottieOptions({ player: () => player, }), diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index b88fbeb298..fa817ced4e 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -227,6 +227,7 @@ import {AlertService} from './common/services/alert.service'; import {GradeService} from './common/services/grade.service'; import {NumbasComponent} from './common/numbas-component/numbas-component.component'; import {NumbasModal} from './common/numbas-component/numbas-modal.component'; +import {TestAttemptService} from './api/services/test-attempt.service'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -310,6 +311,7 @@ DoubtfireAngularJSModule.factory( ); DoubtfireAngularJSModule.factory('CreateNewUnitModal', downgradeInjectable(CreateNewUnitModal)); DoubtfireAngularJSModule.factory('NumbasModal', downgradeInjectable(NumbasModal)); +DoubtfireAngularJSModule.factory('testAttemptService', downgradeInjectable(TestAttemptService)); // directive -> component DoubtfireAngularJSModule.directive( diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee index 68d742362e..f9552b3567 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee @@ -128,7 +128,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) removed.push('group') if !isRFF || !task.isGroupTask() removed.push('alignment') if !isRFF || !task.unit.ilos.length > 0 removed.push('comments') if isTestSubmission - removed.push('numbas') if !task.definition.hasEnabledNumbasTest + removed.push('numbas') if !isRFF || !task.definition.hasEnabledNumbasTest removed # Initialises the states initialise: -> From a576f484bc434728eab9632c022bccf1ed26cb01 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 7 May 2024 07:11:52 +1000 Subject: [PATCH 0070/1531] feat: add test attempt service --- src/app/api/services/test-attempt.service.ts | 40 ++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/app/api/services/test-attempt.service.ts diff --git a/src/app/api/services/test-attempt.service.ts b/src/app/api/services/test-attempt.service.ts new file mode 100644 index 0000000000..094f2baa0c --- /dev/null +++ b/src/app/api/services/test-attempt.service.ts @@ -0,0 +1,40 @@ +import { Injectable } from "@angular/core"; +import { EntityService } from "ngx-entity-service"; +import { TestAttempt } from "../models/test-attempt"; +import { HttpClient } from "@angular/common/http"; +import API_URL from "src/app/config/constants/apiURL"; +import { Task } from "../models/task"; +import { Observable } from "rxjs"; +import { AppInjector } from "src/app/app-injector"; +import { DoubtfireConstants } from "src/app/config/constants/doubtfire-constants"; + +@Injectable() +export class TestAttemptService extends EntityService { + protected readonly endpointFormat = '/test_attempts?id=:id:'; + + constructor(httpClient: HttpClient) { + super(httpClient, API_URL); + + this.mapping.addKeys( + 'id', + 'name', + 'attemptNumber', + 'passStatus', + 'suspendData', + 'completed', + 'cmiEntry', + 'examResult', + 'attemptedAt', + 'taskId' + ); + } + + public createInstanceFrom(json: object, other?: any): TestAttempt { + return new TestAttempt(other as Task); + } + + public getLatestCompletedTestAttempt(task: Task): Observable { + const url = `${AppInjector.get(DoubtfireConstants).API_URL}/test_attempts/completed-latest?task_id=${task.id}`; + return AppInjector.get(HttpClient).get(url); + } +} \ No newline at end of file From 2b1dcfc717eb770dd623c62ac99d8d961d1c3124 Mon Sep 17 00:00:00 2001 From: ublefo <90136978+ublefo@users.noreply.github.com> Date: Tue, 7 May 2024 16:29:44 +1000 Subject: [PATCH 0071/1531] fix: ensure counters are incremented after object creation --- src/app/api/services/numbas-lms.service.ts | 25 ++++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/app/api/services/numbas-lms.service.ts b/src/app/api/services/numbas-lms.service.ts index 59d94e0526..5593fba3f0 100644 --- a/src/app/api/services/numbas-lms.service.ts +++ b/src/app/api/services/numbas-lms.service.ts @@ -13,16 +13,16 @@ export class NumbasLmsService { private defaultValues: { [key: string]: string } = { 'cmi.completion_status': 'not attempted', 'cmi.entry': 'ab-initio', + 'cmi.objectives._count': '0', + 'cmi.interactions._count': '0', 'numbas.user_role': 'learner', - 'numbas.duration_extension.units': 'seconds', 'cmi.mode': 'normal', - 'cmi.undefinedlearner_response': '1', - 'cmi.undefinedresult': '0' }; private testId: number = 0; private task: Task; - private learnerId: string; + private readonly learnerId: string; + private readonly learnerName: string; initializationComplete$ = new BehaviorSubject(false); private scormErrors: { [key: string]: string } = { @@ -33,7 +33,9 @@ export class NumbasLmsService { dataStore: { [key: string]: any } = this.getDefaultDataStore(); constructor(private userService: UserService) { - this.learnerId = this.userService.currentUser.studentId; + const user = this.userService.currentUser; + this.learnerId = user.studentId; + this.learnerName = user.firstName + user.lastName; } setTask(task: Task) { @@ -106,6 +108,7 @@ export class NumbasLmsService { if (latestTest.data['cmi_entry'] === 'ab-initio') { console.log("starting new test"); this.SetValue('cmi.learner_id', this.learnerId); + this.SetValue('cmi.learner_name', this.learnerName); this.dataStore['name'] = examName; this.dataStore['attempt_number'] = latestTest.data['attempt_number']; console.log(this.dataStore); @@ -178,9 +181,17 @@ export class NumbasLmsService { } SetValue(element: string, value: any): string { - if (element.startsWith('cmi.')) { - this.dataStore[element] = value; + console.log(`SetValue:`, element, value); + this.dataStore[element] = value; + if (element.match('cmi.interactions.\\d+.id')) { + console.log('Incrementing cmi.interactions._count'); + this.dataStore['cmi.interactions._count']++; } + if (element.match('cmi.objectives.\\d+.id')) { + console.log('Incrementing cmi.objectives._count'); + this.dataStore['cmi.objectives._count']++; + } + // console.log("dataStore after value set:", this.dataStore); return 'true'; } From aa20a273f6a4e8e0f597da164adb330deaff470c Mon Sep 17 00:00:00 2001 From: ublefo <90136978+ublefo@users.noreply.github.com> Date: Tue, 7 May 2024 23:20:13 +1000 Subject: [PATCH 0072/1531] refactor: rename scorm service --- .../{numbas-lms.service.ts => scorm-lms.service.ts} | 2 +- src/app/api/services/spec/numbas-lms.service.spec.ts | 8 ++++---- .../common/numbas-component/numbas-component.component.ts | 4 ++-- src/app/doubtfire-angular.module.ts | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) rename src/app/api/services/{numbas-lms.service.ts => scorm-lms.service.ts} (99%) diff --git a/src/app/api/services/numbas-lms.service.ts b/src/app/api/services/scorm-lms.service.ts similarity index 99% rename from src/app/api/services/numbas-lms.service.ts rename to src/app/api/services/scorm-lms.service.ts index 5593fba3f0..bd7b5f1085 100644 --- a/src/app/api/services/numbas-lms.service.ts +++ b/src/app/api/services/scorm-lms.service.ts @@ -7,7 +7,7 @@ import { Task } from '../models/task'; @Injectable({ providedIn: 'root' }) -export class NumbasLmsService { +export class ScormLmsService { private readonly apiBaseUrl = `${API_URL}/test_attempts`; private defaultValues: { [key: string]: string } = { diff --git a/src/app/api/services/spec/numbas-lms.service.spec.ts b/src/app/api/services/spec/numbas-lms.service.spec.ts index 7d29ef75e0..f38d5fc080 100644 --- a/src/app/api/services/spec/numbas-lms.service.spec.ts +++ b/src/app/api/services/spec/numbas-lms.service.spec.ts @@ -1,12 +1,12 @@ import { TestBed } from '@angular/core/testing'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; -import { NumbasLmsService } from '../numbas-lms.service'; +import { ScormLmsService } from '../scorm-lms.service'; import { TaskService } from '../task.service'; import { UserService } from '../user.service'; import { of } from 'rxjs'; describe('NumbasLmsService', () => { - let service: NumbasLmsService; + let service: ScormLmsService; let httpTestingController: HttpTestingController; let mockUserService: Partial; let mockTaskService: Partial; @@ -27,13 +27,13 @@ describe('NumbasLmsService', () => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [ - NumbasLmsService, + ScormLmsService, { provide: UserService, useValue: mockUserService }, { provide: TaskService, useValue: mockTaskService } ] }); - service = TestBed.inject(NumbasLmsService); + service = TestBed.inject(ScormLmsService); httpTestingController = TestBed.inject(HttpTestingController); }); diff --git a/src/app/common/numbas-component/numbas-component.component.ts b/src/app/common/numbas-component/numbas-component.component.ts index f5453e0dcc..2f977ef60c 100644 --- a/src/app/common/numbas-component/numbas-component.component.ts +++ b/src/app/common/numbas-component/numbas-component.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { Task } from 'src/app/api/models/task'; -import { NumbasLmsService } from 'src/app/api/services/numbas-lms.service'; +import { ScormLmsService } from 'src/app/api/services/scorm-lms.service'; import { AppInjector } from 'src/app/app-injector'; import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; @@ -23,7 +23,7 @@ export class NumbasComponent implements OnInit { constructor( private dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: { task: Task, mode: 'attempt' | 'review' }, - private lmsService: NumbasLmsService, + private lmsService: ScormLmsService, private sanitizer: DomSanitizer ) {} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index e1f4d2356f..e5b2e1b2a7 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -227,7 +227,7 @@ import {UnitCodeComponent} from './common/unit-code/unit-code.component'; import {GradeService} from './common/services/grade.service'; import {NumbasComponent} from './common/numbas-component/numbas-component.component'; import {NumbasModal} from './common/numbas-component/numbas-modal.component'; -import {NumbasLmsService} from './api/services/numbas-lms.service'; +import {ScormLmsService} from './api/services/scorm-lms.service'; import {NumbasCommentComponent} from './tasks/task-comments-viewer/numbas-comment/numbas-comment.component'; import {TestAttemptService} from './api/services/test-attempt.service'; @@ -406,7 +406,7 @@ import {TestAttemptService} from './api/services/test-attempt.service'; IsActiveUnitRole, CreateNewUnitModal, NumbasModal, - NumbasLmsService, + ScormLmsService, TestAttemptService, provideLottieOptions({ player: () => player, From fdd5667d1744f5ad135bba946a8d2daee6648605 Mon Sep 17 00:00:00 2001 From: ublefo <90136978+ublefo@users.noreply.github.com> Date: Wed, 8 May 2024 22:08:12 +1000 Subject: [PATCH 0073/1531] refactor: generalize scorm player components and services --- src/app/ajs-upgraded-providers.ts | 10 +++--- ...ms.service.ts => scorm-adapter.service.ts} | 8 ++--- ....spec.ts => scorm-adapter.service.spec.ts} | 11 +++--- .../scorm-player-modal.component.ts} | 10 +++--- .../scorm-player.component.html} | 4 +-- .../scorm-player.component.scss} | 0 .../scorm-player.component.spec.ts} | 12 +++---- .../scorm-player.component.ts} | 36 ++++++++++--------- src/app/doubtfire-angular.module.ts | 12 +++---- src/app/doubtfire-angularjs.module.ts | 11 +++--- .../upload-submission-modal.coffee | 11 +++--- .../upload-submission-modal.tpl.html | 8 ++--- .../numbas-comment.component.ts | 4 +-- 13 files changed, 71 insertions(+), 66 deletions(-) rename src/app/api/services/{scorm-lms.service.ts => scorm-adapter.service.ts} (97%) rename src/app/api/services/spec/{numbas-lms.service.spec.ts => scorm-adapter.service.spec.ts} (91%) rename src/app/common/{numbas-component/numbas-modal.component.ts => scorm-player/scorm-player-modal.component.ts} (64%) rename src/app/common/{numbas-component/numbas-component.component.html => scorm-player/scorm-player.component.html} (74%) rename src/app/common/{numbas-component/numbas-component.component.scss => scorm-player/scorm-player.component.scss} (100%) rename src/app/common/{numbas-component/numbas-component.component.spec.ts => scorm-player/scorm-player.component.spec.ts} (51%) rename src/app/common/{numbas-component/numbas-component.component.ts => scorm-player/scorm-player.component.ts} (50%) diff --git a/src/app/ajs-upgraded-providers.ts b/src/app/ajs-upgraded-providers.ts index 9d5b0f0203..f114da1c79 100644 --- a/src/app/ajs-upgraded-providers.ts +++ b/src/app/ajs-upgraded-providers.ts @@ -18,7 +18,7 @@ export const rootScope = new InjectionToken('$rootScope'); export const calendarModal = new InjectionToken('CalendarModal'); export const aboutDoubtfireModal = new InjectionToken('AboutDoubtfireModal'); export const plagiarismReportModal = new InjectionToken('PlagiarismReportModal'); -export const numbasModal = new InjectionToken('NumbasModal'); +export const scormPlayerModal = new InjectionToken('ScormPlayerModal'); // Define a provider for the above injection token... // It will get the service from AngularJS via the factory @@ -118,8 +118,8 @@ export const UnitStudentEnrolmentModalProvider = { deps: ['$injector'], }; -export const numbasModalProvider = { - provide: numbasModal, - useFactory: (i) => i.get('NumbasModal'), +export const ScormPlayerModalProvider = { + provide: scormPlayerModal, + useFactory: (i) => i.get('ScormPlayerModal'), deps: ['$injector'], -}; \ No newline at end of file +}; diff --git a/src/app/api/services/scorm-lms.service.ts b/src/app/api/services/scorm-adapter.service.ts similarity index 97% rename from src/app/api/services/scorm-lms.service.ts rename to src/app/api/services/scorm-adapter.service.ts index bd7b5f1085..3202331804 100644 --- a/src/app/api/services/scorm-lms.service.ts +++ b/src/app/api/services/scorm-adapter.service.ts @@ -7,7 +7,7 @@ import { Task } from '../models/task'; @Injectable({ providedIn: 'root' }) -export class ScormLmsService { +export class ScormAdapterService { private readonly apiBaseUrl = `${API_URL}/test_attempts`; private defaultValues: { [key: string]: string } = { @@ -207,7 +207,7 @@ export class ScormLmsService { if (!this.isTestCompleted()) { this.dataStore['cmi.exit'] = 'suspend'; } - console.log("Committing dataStore:", this.dataStore); + console.log("Committing DataModel:", this.dataStore); // Use XHR to send the request const xhr = new XMLHttpRequest(); @@ -216,9 +216,9 @@ export class ScormLmsService { xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 400) { - console.log('Suspend data saved successfully.'); + console.log('DataModel saved successfully.'); } else { - console.error('Error saving suspend data:', xhr.responseText); + console.error('Error saving DataModel:', xhr.responseText); } }; diff --git a/src/app/api/services/spec/numbas-lms.service.spec.ts b/src/app/api/services/spec/scorm-adapter.service.spec.ts similarity index 91% rename from src/app/api/services/spec/numbas-lms.service.spec.ts rename to src/app/api/services/spec/scorm-adapter.service.spec.ts index f38d5fc080..5d3a52caac 100644 --- a/src/app/api/services/spec/numbas-lms.service.spec.ts +++ b/src/app/api/services/spec/scorm-adapter.service.spec.ts @@ -1,12 +1,11 @@ import { TestBed } from '@angular/core/testing'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; -import { ScormLmsService } from '../scorm-lms.service'; +import { ScormAdapterService } from '../scorm-adapter.service'; import { TaskService } from '../task.service'; import { UserService } from '../user.service'; -import { of } from 'rxjs'; -describe('NumbasLmsService', () => { - let service: ScormLmsService; +describe('ScormAdapterService', () => { + let service: ScormAdapterService; let httpTestingController: HttpTestingController; let mockUserService: Partial; let mockTaskService: Partial; @@ -27,13 +26,13 @@ describe('NumbasLmsService', () => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [ - ScormLmsService, + ScormAdapterService, { provide: UserService, useValue: mockUserService }, { provide: TaskService, useValue: mockTaskService } ] }); - service = TestBed.inject(ScormLmsService); + service = TestBed.inject(ScormAdapterService); httpTestingController = TestBed.inject(HttpTestingController); }); diff --git a/src/app/common/numbas-component/numbas-modal.component.ts b/src/app/common/scorm-player/scorm-player-modal.component.ts similarity index 64% rename from src/app/common/numbas-component/numbas-modal.component.ts rename to src/app/common/scorm-player/scorm-player-modal.component.ts index 73b2122c17..443add9bed 100644 --- a/src/app/common/numbas-component/numbas-modal.component.ts +++ b/src/app/common/scorm-player/scorm-player-modal.component.ts @@ -1,18 +1,18 @@ import { Injectable } from '@angular/core'; import { MatDialog, MatDialogRef } from '@angular/material/dialog'; -import { NumbasComponent } from './numbas-component.component'; +import { ScormPlayerComponent } from './scorm-player.component'; import { Task } from 'src/app/api/models/task'; @Injectable({ providedIn: 'root', }) -export class NumbasModal { +export class ScormPlayerModal { constructor(public dialog: MatDialog) { } - + public show(task: Task, mode: 'attempt' | 'review'): void { - let dialogRef: MatDialogRef; + let dialogRef: MatDialogRef; - dialogRef = this.dialog.open(NumbasComponent, { + dialogRef = this.dialog.open(ScormPlayerComponent, { data: { task, mode }, width: '95%', height: '90%' }); diff --git a/src/app/common/numbas-component/numbas-component.component.html b/src/app/common/scorm-player/scorm-player.component.html similarity index 74% rename from src/app/common/numbas-component/numbas-component.component.html rename to src/app/common/scorm-player/scorm-player.component.html index d562f02239..5089ad9de3 100644 --- a/src/app/common/numbas-component/numbas-component.component.html +++ b/src/app/common/scorm-player/scorm-player.component.html @@ -1,4 +1,4 @@
- -
\ No newline at end of file + +
diff --git a/src/app/common/numbas-component/numbas-component.component.scss b/src/app/common/scorm-player/scorm-player.component.scss similarity index 100% rename from src/app/common/numbas-component/numbas-component.component.scss rename to src/app/common/scorm-player/scorm-player.component.scss diff --git a/src/app/common/numbas-component/numbas-component.component.spec.ts b/src/app/common/scorm-player/scorm-player.component.spec.ts similarity index 51% rename from src/app/common/numbas-component/numbas-component.component.spec.ts rename to src/app/common/scorm-player/scorm-player.component.spec.ts index 31dad5e305..7980df7c3c 100644 --- a/src/app/common/numbas-component/numbas-component.component.spec.ts +++ b/src/app/common/scorm-player/scorm-player.component.spec.ts @@ -1,18 +1,18 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { NumbasComponent } from './numbas-component.component'; +import { ScormPlayerComponent } from './scorm-player.component'; -describe('NumbasComponent', () => { - let component: NumbasComponent; - let fixture: ComponentFixture; +describe('ScormPlayerComponent', () => { + let component: ScormPlayerComponent; + let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ NumbasComponent ] + declarations: [ ScormPlayerComponent ] }) .compileComponents(); - fixture = TestBed.createComponent(NumbasComponent); + fixture = TestBed.createComponent(ScormPlayerComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/common/numbas-component/numbas-component.component.ts b/src/app/common/scorm-player/scorm-player.component.ts similarity index 50% rename from src/app/common/numbas-component/numbas-component.component.ts rename to src/app/common/scorm-player/scorm-player.component.ts index 2f977ef60c..7ed98b3cfe 100644 --- a/src/app/common/numbas-component/numbas-component.component.ts +++ b/src/app/common/scorm-player/scorm-player.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { Task } from 'src/app/api/models/task'; -import { ScormLmsService } from 'src/app/api/services/scorm-lms.service'; +import { ScormAdapterService } from 'src/app/api/services/scorm-adapter.service'; import { AppInjector } from 'src/app/app-injector'; import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; @@ -11,35 +11,35 @@ declare global { } @Component({ - selector: 'f-numbas-component', - templateUrl: './numbas-component.component.html', - styleUrls: ['./numbas-component.component.scss'], + selector: 'f-scorm-player', + templateUrl: './scorm-player.component.html', + styleUrls: ['./scorm-player.component.scss'], }) -export class NumbasComponent implements OnInit { +export class ScormPlayerComponent implements OnInit { task: Task; currentMode: 'attempt' | 'review' = 'attempt'; iframeSrc: SafeResourceUrl; constructor( - private dialogRef: MatDialogRef, + private dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: { task: Task, mode: 'attempt' | 'review' }, - private lmsService: ScormLmsService, + private scormAdapter: ScormAdapterService, private sanitizer: DomSanitizer ) {} ngOnInit(): void { this.task = this.data.task; - this.lmsService.setTask(this.task); + this.scormAdapter.setTask(this.task); window.API_1484_11 = { - Initialize: () => this.lmsService.Initialize(this.currentMode), - Terminate: () => this.lmsService.Terminate(), - GetValue: (element: string) => this.lmsService.GetValue(element), - SetValue: (element: string, value: string) => this.lmsService.SetValue(element, value), - Commit: () => this.lmsService.Commit(), - GetLastError: () => this.lmsService.GetLastError(), - GetErrorString: (errorCode: string) => this.lmsService.GetErrorString(errorCode), - GetDiagnostic: (errorCode: string) => this.lmsService.GetDiagnostic(errorCode) + Initialize: () => this.scormAdapter.Initialize(this.currentMode), + Terminate: () => this.scormAdapter.Terminate(), + GetValue: (element: string) => this.scormAdapter.GetValue(element), + SetValue: (element: string, value: string) => this.scormAdapter.SetValue(element, value), + Commit: () => this.scormAdapter.Commit(), + GetLastError: () => this.scormAdapter.GetLastError(), + GetErrorString: (errorCode: string) => this.scormAdapter.GetErrorString(errorCode), + GetDiagnostic: (errorCode: string) => this.scormAdapter.GetDiagnostic(errorCode) }; this.currentMode = this.data.mode; @@ -47,7 +47,9 @@ export class NumbasComponent implements OnInit { this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(`${AppInjector.get(DoubtfireConstants).API_URL}/numbas_api/${this.task.taskDefId}/index.html`); } - removeNumbasTest(): void { + close(): void { + console.log('SCORM player closing, commiting DataModel!'); + this.scormAdapter.Commit(); const iframe = document.getElementsByTagName('iframe')[0]; iframe?.parentNode?.removeChild(iframe); this.dialogRef.close(); diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index e5b2e1b2a7..23145ccaea 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -72,6 +72,7 @@ import { gradeTaskModalProvider, uploadSubmissionModalProvider, ConfirmationModalProvider, + ScormPlayerModalProvider, } from './ajs-upgraded-providers'; import { TaskCommentComposerComponent, @@ -225,9 +226,8 @@ import {FTaskSheetViewComponent} from './units/states/tasks/viewer/directives/f- import {TasksViewerComponent} from './units/states/tasks/tasks-viewer/tasks-viewer.component'; import {UnitCodeComponent} from './common/unit-code/unit-code.component'; import {GradeService} from './common/services/grade.service'; -import {NumbasComponent} from './common/numbas-component/numbas-component.component'; -import {NumbasModal} from './common/numbas-component/numbas-modal.component'; -import {ScormLmsService} from './api/services/scorm-lms.service'; +import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; +import {ScormAdapterService} from './api/services/scorm-adapter.service'; import {NumbasCommentComponent} from './tasks/task-comments-viewer/numbas-comment/numbas-comment.component'; import {TestAttemptService} from './api/services/test-attempt.service'; @@ -332,7 +332,7 @@ import {TestAttemptService} from './api/services/test-attempt.service'; FUsersComponent, FTaskBadgeComponent, FUnitsComponent, - NumbasComponent, + ScormPlayerComponent, NumbasCommentComponent, ], // Services we provide @@ -405,8 +405,8 @@ import {TestAttemptService} from './api/services/test-attempt.service'; TasksForInboxSearchPipe, IsActiveUnitRole, CreateNewUnitModal, - NumbasModal, - ScormLmsService, + ScormPlayerModalProvider, + ScormAdapterService, TestAttemptService, provideLottieOptions({ player: () => player, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index fa817ced4e..3cd6555bd8 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -225,8 +225,8 @@ import {FUnitsComponent} from './admin/states/f-units/f-units.component'; import {MarkedPipe} from './common/pipes/marked.pipe'; import {AlertService} from './common/services/alert.service'; import {GradeService} from './common/services/grade.service'; -import {NumbasComponent} from './common/numbas-component/numbas-component.component'; -import {NumbasModal} from './common/numbas-component/numbas-modal.component'; +import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; +import {ScormPlayerModal} from './common/scorm-player/scorm-player-modal.component'; import {TestAttemptService} from './api/services/test-attempt.service'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ @@ -310,7 +310,7 @@ DoubtfireAngularJSModule.factory( downgradeInjectable(EditProfileDialogService), ); DoubtfireAngularJSModule.factory('CreateNewUnitModal', downgradeInjectable(CreateNewUnitModal)); -DoubtfireAngularJSModule.factory('NumbasModal', downgradeInjectable(NumbasModal)); +DoubtfireAngularJSModule.factory('ScormPlayerModal', downgradeInjectable(ScormPlayerModal)); DoubtfireAngularJSModule.factory('testAttemptService', downgradeInjectable(TestAttemptService)); // directive -> component @@ -446,7 +446,10 @@ DoubtfireAngularJSModule.directive( ); DoubtfireAngularJSModule.directive('fUnits', downgradeComponent({component: FUnitsComponent})); -DoubtfireAngularJSModule.directive('fNumbasComponent', downgradeComponent({component: NumbasComponent})); +DoubtfireAngularJSModule.directive( + 'fScormPlayerComponent', + downgradeComponent({component: ScormPlayerComponent}), +); // Global configuration DoubtfireAngularJSModule.directive( diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee index f9552b3567..6a17bd558c 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee @@ -32,7 +32,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) UploadSubmissionModal ) -.controller('UploadSubmissionModalCtrl', ($scope, $rootScope, $timeout, $modalInstance, NumbasModal, newTaskService, newProjectService, task, reuploadEvidence, outcomeService, PrivacyPolicy) -> +.controller('UploadSubmissionModalCtrl', ($scope, $rootScope, $timeout, $modalInstance, ScormPlayerModal, newTaskService, newProjectService, task, reuploadEvidence, outcomeService, PrivacyPolicy) -> $scope.privacyPolicy = PrivacyPolicy # Expose task to scope $scope.task = task @@ -100,7 +100,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) # States functionality states = { # All possible states - all: ['group', 'numbas', 'files', 'alignment', 'comments', 'uploading'] + all: ['group', 'scorm-assessment', 'files', 'alignment', 'comments', 'uploading'] # Only states which are shown (populated in initialise) shown: [] # The currently active state (set in initialise) @@ -128,7 +128,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) removed.push('group') if !isRFF || !task.isGroupTask() removed.push('alignment') if !isRFF || !task.unit.ilos.length > 0 removed.push('comments') if isTestSubmission - removed.push('numbas') if !isRFF || !task.definition.hasEnabledNumbasTest + removed.push('scorm-assessment') if !isRFF || !task.definition.hasEnabledNumbasTest removed # Initialises the states initialise: -> @@ -155,8 +155,9 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) previous: states.previous } - $scope.launchNumbasDialog = -> - NumbasModal.show $scope.task, 'attempt' + $scope.launchScormPlayer = -> + console.clear() + ScormPlayerModal.show $scope.task, 'attempt' # Whether or not we should disable this button $scope.shouldDisableBtn = { diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html index 0527aadd40..8b6c89bea3 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html @@ -44,9 +44,9 @@

+ class="state state-scorm-assessment" + ng-class="{'state-hidden-left': isHidden('scorm-assessment').left, + 'state-hidden-right': isHidden('scorm-assessment').right}">

@@ -57,7 +57,7 @@

-
diff --git a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts b/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts index eed512fe19..650a110d0f 100644 --- a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit, Input } from '@angular/core'; import { Task, TaskComment } from 'src/app/api/models/doubtfire-model'; -import { NumbasModal } from 'src/app/common/numbas-component/numbas-modal.component'; +import { ScormPlayerModal } from 'src/app/common/scorm-player/scorm-player-modal.component'; @Component({ selector: 'numbas-comment', @@ -11,7 +11,7 @@ export class NumbasCommentComponent implements OnInit { @Input() task: Task; @Input() comment: TaskComment; - constructor(private modalService: NumbasModal) {} + constructor(private modalService: ScormPlayerModal) {} ngOnInit() {} From 226d9193251fb675c92bec8265508477857a4ec9 Mon Sep 17 00:00:00 2001 From: ublefo <90136978+ublefo@users.noreply.github.com> Date: Wed, 8 May 2024 22:29:37 +1000 Subject: [PATCH 0074/1531] fix: use nullish coalescing when retrieving data from the datamodel also disallow dismissing modal to ensure datamodel is committed --- src/app/api/services/scorm-adapter.service.ts | 10 +++++----- .../scorm-player/scorm-player-modal.component.ts | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/app/api/services/scorm-adapter.service.ts b/src/app/api/services/scorm-adapter.service.ts index 3202331804..22c0205a33 100644 --- a/src/app/api/services/scorm-adapter.service.ts +++ b/src/app/api/services/scorm-adapter.service.ts @@ -69,7 +69,7 @@ export class ScormAdapterService { try { const completedTest = JSON.parse(xhr.responseText); - let parsedSuspendData = JSON.parse(completedTest.data.suspend_data || '{}'); + let parsedSuspendData = JSON.parse(completedTest.data.suspend_data ?? '{}'); // Set entire suspendData string to cmi.suspend_data this.SetValue('cmi.suspend_data', JSON.stringify(parsedSuspendData)); @@ -114,7 +114,7 @@ export class ScormAdapterService { console.log(this.dataStore); } else if (latestTest.data['cmi_entry'] === 'resume') { console.log("resuming test"); - let parsedSuspendData = JSON.parse(latestTest.data.suspend_data || '{}'); + let parsedSuspendData = JSON.parse(latestTest.data.suspend_data ?? '{}'); this.dataStore = JSON.parse(JSON.stringify(parsedSuspendData)); @@ -132,7 +132,7 @@ export class ScormAdapterService { } isTestCompleted(): boolean { - return this.dataStore?.['completed'] || false; + return this.dataStore?.['completed'] ?? false; } private resetDataStore() { @@ -144,7 +144,7 @@ export class ScormAdapterService { const examResult = this.dataStore["cmi.score.raw"]; const status = this.GetValue("cmi.success_status"); this.dataStore['completed'] = true; - const currentAttemptNumber = this.dataStore['attempt_number'] || 0; + const currentAttemptNumber = this.dataStore['attempt_number'] ?? 0; const ExamName = this.dataStore['name']; this.SetValue('cmi.entry', 'RO'); const cmientry = this.GetValue('cmi.entry'); @@ -177,7 +177,7 @@ export class ScormAdapterService { } GetValue(element: string): string { - return this.dataStore[element] || ''; + return this.dataStore[element] ?? ''; } SetValue(element: string, value: any): string { diff --git a/src/app/common/scorm-player/scorm-player-modal.component.ts b/src/app/common/scorm-player/scorm-player-modal.component.ts index 443add9bed..190e7bf570 100644 --- a/src/app/common/scorm-player/scorm-player-modal.component.ts +++ b/src/app/common/scorm-player/scorm-player-modal.component.ts @@ -14,7 +14,8 @@ export class ScormPlayerModal { dialogRef = this.dialog.open(ScormPlayerComponent, { data: { task, mode }, - width: '95%', height: '90%' + width: '95%', height: '90%', + disableClose: true, }); } } From 20472257c87711955b79008fa3cb7517151a4424 Mon Sep 17 00:00:00 2001 From: ublefo <90136978+ublefo@users.noreply.github.com> Date: Thu, 9 May 2024 06:18:20 +1000 Subject: [PATCH 0075/1531] refactor: separate out scorm datamodel and player context --- src/app/api/models/doubtfire-model.ts | 2 + src/app/api/models/scorm-datamodel.ts | 58 ++++++ src/app/api/models/scorm-player-context.ts | 33 +++ src/app/api/services/scorm-adapter.service.ts | 190 +++++++++--------- .../scorm-player/scorm-player.component.ts | 4 +- 5 files changed, 193 insertions(+), 94 deletions(-) create mode 100644 src/app/api/models/scorm-datamodel.ts create mode 100644 src/app/api/models/scorm-player-context.ts diff --git a/src/app/api/models/doubtfire-model.ts b/src/app/api/models/doubtfire-model.ts index 3cb4911083..baca2f22d2 100644 --- a/src/app/api/models/doubtfire-model.ts +++ b/src/app/api/models/doubtfire-model.ts @@ -32,6 +32,8 @@ export * from './task-comment/discussion-comment'; export * from '../services/task-outcome-alignment.service'; export * from './task-similarity'; export * from './tii-action'; +export * from './scorm-datamodel'; +export * from './scorm-player-context'; // Users -- are students or staff export * from './user/user'; diff --git a/src/app/api/models/scorm-datamodel.ts b/src/app/api/models/scorm-datamodel.ts new file mode 100644 index 0000000000..e9d105f3c7 --- /dev/null +++ b/src/app/api/models/scorm-datamodel.ts @@ -0,0 +1,58 @@ +export class ScormDataModel { + initState: {[key: string]: string} = { + 'cmi.completion_status': 'not attempted', + 'cmi.entry': 'ab-initio', + 'cmi.objectives._count': '0', + 'cmi.interactions._count': '0', + 'cmi.mode': 'normal', + }; + + dataModel: {[key: string]: any} = {}; + readonly msgPrefix = 'SCORM DataModel: '; + + constructor() { + this.dataModel = {}; + } + + public init() { + console.log(this.msgPrefix + 'initializing DataModel with default values'); + this.dataModel = this.initState; + } + + public restore(dataModel: {[key: string]: any} = {}) { + console.log(this.msgPrefix + 'restoring DataModel with provided data'); + this.dataModel = dataModel; + } + + public get(key: string): string { + return this.dataModel[key] ?? ''; + } + + public dump(): {[key: string]: any} { + return this.dataModel; + } + + public set(key: string, value: any): string { + console.log(this.msgPrefix + 'set: ', key, value); + this.dataModel[key] = value; + if (key.match('cmi.interactions.\\d+.id')) { + const interactionPath = key.match('cmi.interactions.\\d+'); + const objectivesCounterForInteraction = interactionPath.toString() + '.objectives._count'; + console.log('Incrementing cmi.interactions._count'); + this.dataModel['cmi.interactions._count']++; + console.log(`Initializing ${objectivesCounterForInteraction}`); + this.dataModel[objectivesCounterForInteraction] = 0; + } + if (key.match('cmi.interactions.\\d+.objectives.\\d+.id')) { + const interactionPath = key.match('cmi.interactions.\\d+.objectives'); + const objectivesCounterForInteraction = interactionPath.toString() + '._count'; + console.log(`Incrementing ${objectivesCounterForInteraction}`); + this.dataModel[objectivesCounterForInteraction.toString()]++; + } + if (key.match('cmi.objectives.\\d+.id')) { + console.log('Incrementing cmi.objectives._count'); + this.dataModel['cmi.objectives._count']++; + } + return 'true'; + } +} diff --git a/src/app/api/models/scorm-player-context.ts b/src/app/api/models/scorm-player-context.ts new file mode 100644 index 0000000000..5f1c4bd3ba --- /dev/null +++ b/src/app/api/models/scorm-player-context.ts @@ -0,0 +1,33 @@ +import { Task, User } from 'src/app/api/models/doubtfire-model'; + +export class ScormPlayerContext { + task: Task; + mode: 'browse' | 'normal' | 'review'; + user: User; + attemptNumber: number; + attemptId: number; + learnerName: string; + learnerId: number; + + constructor(user: User) { + this.user = user; + this.learnerId = user.id; + this.learnerName = user.firstName + ' ' + user.lastName; + } + + public setTask(task: Task): void { + this.task = task; + } + + public setMode(mode: 'browse' | 'normal' | 'review'): void { + this.mode = mode; + } + + public setAttemptNumber(attemptNumber: number = 1): void { + this.attemptNumber = attemptNumber; + } + + public setAttemptId(attemptId: number): void { + this.attemptId = attemptId; + } +} diff --git a/src/app/api/services/scorm-adapter.service.ts b/src/app/api/services/scorm-adapter.service.ts index 22c0205a33..6c5353746b 100644 --- a/src/app/api/services/scorm-adapter.service.ts +++ b/src/app/api/services/scorm-adapter.service.ts @@ -2,63 +2,76 @@ import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { UserService } from './user.service'; import API_URL from 'src/app/config/constants/apiURL'; -import { Task } from '../models/task'; +import { Task, ScormDataModel, ScormPlayerContext } from 'src/app/api/models/doubtfire-model'; @Injectable({ providedIn: 'root' }) export class ScormAdapterService { private readonly apiBaseUrl = `${API_URL}/test_attempts`; + private dataModel: ScormDataModel; + private playerContext: ScormPlayerContext; - private defaultValues: { [key: string]: string } = { - 'cmi.completion_status': 'not attempted', - 'cmi.entry': 'ab-initio', - 'cmi.objectives._count': '0', - 'cmi.interactions._count': '0', - 'numbas.user_role': 'learner', - 'cmi.mode': 'normal', - }; - - private testId: number = 0; - private task: Task; - private readonly learnerId: string; - private readonly learnerName: string; initializationComplete$ = new BehaviorSubject(false); - private scormErrors: { [key: string]: string } = { - "0": "No error", - "101": "General exception", + private scormErrorCodes: {[key: string]: string} = { + '0': 'No Error', + '101': 'General Exception', + '102': 'General Initialization Failure', + '103': 'Already Initialized', + '104': 'Content Instance Terminated', + '111': 'General Termination Failure', + '112': 'Termination Before Initialization', + '113': 'Termination After Termination', + '122': 'Retrieve Data Before Initialization', + '123': 'Retrieve Data After Termination', + '132': 'Store Data Before Initialization', + '133': 'Store Data After Termination', + '142': 'Commit Before Initialization', + '143': 'Commit After Termination', + '201': 'General Argument Error', + '301': 'General Get Failure', + '351': 'General Set Failure', + '391': 'General Commit Failure', + '401': 'Undefined Data Model Element', + '402': 'Unimplemented Data Model Element', + '403': 'Data Model Element Value Not Initialized', + '404': 'Data Model Element Is Read Only', + '405': 'Data Model Element Is Write Only', + '406': 'Data Model Element Type Mismatch', + '407': 'Data Model Element Value Out Of Range', + '408': 'Data Model Dependency Not Established', }; - dataStore: { [key: string]: any } = this.getDefaultDataStore(); - constructor(private userService: UserService) { - const user = this.userService.currentUser; - this.learnerId = user.studentId; - this.learnerName = user.firstName + user.lastName; + this.dataModel = new ScormDataModel(); + this.playerContext = new ScormPlayerContext(this.userService.currentUser); } setTask(task: Task) { - this.task = task; + this.playerContext.setTask(task); } - getDefaultDataStore() { - // Use spread operator to merge defaultValues into the dataStore - return { - ...this.defaultValues, - pass_status: false, - completed: false, - }; - } + // getDefaultDataStore() { + // // Use spread operator to merge defaultValues into the dataStore + // return { + // ...this.defaultValues, + // pass_status: false, + // completed: false, + // }; + // } Initialize(mode: 'attempt' | 'review' = 'attempt'): string { console.log('Initialize() function called'); - const examName = 'test Exam Name 1'; - let xhr = new XMLHttpRequest(); + const xhr = new XMLHttpRequest(); if (mode === 'review') { this.SetValue('cmi.mode', 'review'); - xhr.open("GET", `${this.apiBaseUrl}/completed-latest?task_id=${this.task.id}`, false); + xhr.open( + 'GET', + `${this.apiBaseUrl}/completed-latest?task_id=${this.playerContext.task.id}`, + false, + ); xhr.send(); console.log(xhr.responseText); @@ -69,15 +82,17 @@ export class ScormAdapterService { try { const completedTest = JSON.parse(xhr.responseText); - let parsedSuspendData = JSON.parse(completedTest.data.suspend_data ?? '{}'); + const parsedDataModel = JSON.parse(completedTest.data.suspend_data ?? '{}'); // Set entire suspendData string to cmi.suspend_data - this.SetValue('cmi.suspend_data', JSON.stringify(parsedSuspendData)); + this.SetValue('cmi.suspend_data', JSON.stringify(parsedDataModel)); - // Use SetValue to set parsedSuspendData values to dataStore - Object.keys(parsedSuspendData).forEach(key => { - this.SetValue(key, parsedSuspendData[key]); - }); + // // Use SetValue to set parsedSuspendData values to dataStore + // Object.keys(parsedDataModel).forEach((key) => { + // this.SetValue(key, parsedDataModel[key]); + // }); + + this.dataModel.restore(parsedDataModel); this.SetValue('cmi.entry', 'RO'); this.SetValue('cmi.mode', 'review'); @@ -90,7 +105,7 @@ export class ScormAdapterService { } } - xhr.open("GET", `${this.apiBaseUrl}/latest?task_id=${this.task.id}`, false); + xhr.open('GET', `${this.apiBaseUrl}/latest?task_id=${this.playerContext.task.id}`, false); xhr.send(); console.log(xhr.responseText); @@ -103,27 +118,27 @@ export class ScormAdapterService { try { latestTest = JSON.parse(xhr.responseText); console.log('Latest test result:', latestTest); - this.testId = latestTest.data.id; + this.playerContext.attemptId = latestTest.data.id; if (latestTest.data['cmi_entry'] === 'ab-initio') { - console.log("starting new test"); - this.SetValue('cmi.learner_id', this.learnerId); - this.SetValue('cmi.learner_name', this.learnerName); - this.dataStore['name'] = examName; - this.dataStore['attempt_number'] = latestTest.data['attempt_number']; - console.log(this.dataStore); - } else if (latestTest.data['cmi_entry'] === 'resume') { - console.log("resuming test"); - let parsedSuspendData = JSON.parse(latestTest.data.suspend_data ?? '{}'); + console.log('starting new test'); + this.dataModel.init(); + this.SetValue('cmi.learner_id', this.playerContext.learnerId); + this.SetValue('cmi.learner_name', this.playerContext.learnerName); - this.dataStore = JSON.parse(JSON.stringify(parsedSuspendData)); + this.dataModel.set('attempt_number', latestTest.data['attempt_number']); + console.log(this.dataModel.dump()); + } else if (latestTest.data['cmi_entry'] === 'resume') { + console.log('resuming test'); + const restoredDataModel = JSON.parse(latestTest.data.suspend_data ?? '{}'); + this.dataModel.restore(JSON.parse(JSON.stringify(restoredDataModel))); - console.log(this.dataStore); + console.log(this.dataModel.dump()); } this.initializationComplete$.next(true); - console.log("finished initializing"); + console.log('finished initializing'); return 'true'; } catch (error) { console.error('Error:', error); @@ -131,67 +146,56 @@ export class ScormAdapterService { } } - isTestCompleted(): boolean { - return this.dataStore?.['completed'] ?? false; - } - - private resetDataStore() { - this.dataStore = this.getDefaultDataStore(); - } + // isTestCompleted(): boolean { + // return this.dataModel.get('completed') ?? false; + // } Terminate(): string { console.log('Terminate Called'); - const examResult = this.dataStore["cmi.score.raw"]; - const status = this.GetValue("cmi.success_status"); - this.dataStore['completed'] = true; - const currentAttemptNumber = this.dataStore['attempt_number'] ?? 0; - const ExamName = this.dataStore['name']; - this.SetValue('cmi.entry', 'RO'); - const cmientry = this.GetValue('cmi.entry'); + const examResult = this.dataModel.get('cmi.score.raw'); + const status = this.dataModel.get('cmi.success_status'); + this.dataModel.set('completed', true); + const currentAttemptNumber = this.dataModel.get('attempt_number') ?? 0; + const ExamName = this.dataModel.get('name'); + this.dataModel.set('cmi.entry', 'RO'); + const cmientry = this.dataModel.get('cmi.entry'); const data = { name: ExamName, attempt_number: currentAttemptNumber, pass_status: status === 'passed', - suspend_data: JSON.stringify(this.dataStore), + suspend_data: JSON.stringify(this.dataModel.dump()), completed: true, exam_result: examResult, cmi_entry: cmientry, - task_id: this.task.id + task_id: this.playerContext.task.id }; const xhr = new XMLHttpRequest(); - if (this.testId) { - xhr.open("PUT", `${this.apiBaseUrl}/${this.testId}`, false); + if (this.playerContext.attemptId) { + xhr.open('PUT', `${this.apiBaseUrl}/${this.playerContext.attemptId}`, false); } else { - xhr.open("POST", this.apiBaseUrl, false); + xhr.open('POST', this.apiBaseUrl, false); } - xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); + xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); xhr.send(JSON.stringify(data)); if (xhr.status !== 200) { console.error('Error sending test data:', xhr.statusText); return 'false'; } - this.resetDataStore(); + this.dataModel.init(); return 'true'; } GetValue(element: string): string { - return this.dataStore[element] ?? ''; + const value = this.dataModel.get(element); + console.log(`GetValue:`, element, value); + return value; } SetValue(element: string, value: any): string { console.log(`SetValue:`, element, value); - this.dataStore[element] = value; - if (element.match('cmi.interactions.\\d+.id')) { - console.log('Incrementing cmi.interactions._count'); - this.dataStore['cmi.interactions._count']++; - } - if (element.match('cmi.objectives.\\d+.id')) { - console.log('Incrementing cmi.objectives._count'); - this.dataStore['cmi.objectives._count']++; - } - // console.log("dataStore after value set:", this.dataStore); + this.dataModel.set(element, value); return 'true'; } @@ -203,15 +207,15 @@ export class ScormAdapterService { } // Set cmi.entry to 'resume' before committing dataStore - this.dataStore['cmi.entry'] = 'resume'; - if (!this.isTestCompleted()) { - this.dataStore['cmi.exit'] = 'suspend'; - } - console.log("Committing DataModel:", this.dataStore); + this.dataModel.set('cmi.entry', 'resume'); + // if (!this.isTestCompleted()) { + // this.dataModel.set('cmi.exit', 'suspend'); + // } + console.log('Committing DataModel:', this.dataModel.dump()); // Use XHR to send the request const xhr = new XMLHttpRequest(); - xhr.open('PUT', `${this.apiBaseUrl}/${this.testId}/suspend`, true); + xhr.open('PUT', `${this.apiBaseUrl}/${this.playerContext.attemptId}/suspend`, true); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onload = () => { @@ -226,7 +230,7 @@ export class ScormAdapterService { console.error('Request failed.'); }; - const requestData = { suspend_data: this.dataStore }; + const requestData = { suspend_data: this.dataModel.dump() }; xhr.send(JSON.stringify(requestData)); return 'true'; } diff --git a/src/app/common/scorm-player/scorm-player.component.ts b/src/app/common/scorm-player/scorm-player.component.ts index 7ed98b3cfe..428f6869b7 100644 --- a/src/app/common/scorm-player/scorm-player.component.ts +++ b/src/app/common/scorm-player/scorm-player.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; -import { Task } from 'src/app/api/models/task'; +import { Task, ScormDataModel, ScormPlayerContext } from 'src/app/api/models/doubtfire-model'; import { ScormAdapterService } from 'src/app/api/services/scorm-adapter.service'; import { AppInjector } from 'src/app/app-injector'; import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; @@ -16,6 +16,8 @@ declare global { styleUrls: ['./scorm-player.component.scss'], }) export class ScormPlayerComponent implements OnInit { + context: ScormPlayerContext; + task: Task; currentMode: 'attempt' | 'review' = 'attempt'; iframeSrc: SafeResourceUrl; From b0863c7cf9319862b224705b50a238d2fabc5ec9 Mon Sep 17 00:00:00 2001 From: ublefo <90136978+ublefo@users.noreply.github.com> Date: Sun, 12 May 2024 08:43:22 +1000 Subject: [PATCH 0076/1531] refactor: rewrite test attempt code --- src/app/api/models/scorm-datamodel.ts | 24 +- src/app/api/models/scorm-player-context.ts | 69 +++- src/app/api/models/task-definition.ts | 14 +- src/app/api/models/task.ts | 2 +- src/app/api/services/scorm-adapter.service.ts | 350 +++++++++--------- src/app/api/services/task-comment.service.ts | 2 +- .../api/services/task-definition.service.ts | 10 +- .../scorm-player-modal.component.ts | 15 +- .../scorm-player/scorm-player.component.ts | 41 +- .../upload-submission-modal.coffee | 2 +- .../numbas-comment.component.ts | 6 +- .../task-comments-viewer.component.html | 2 +- .../task-comments-viewer.component.scss | 2 +- .../task-definition-numbas.component.html | 10 +- 14 files changed, 289 insertions(+), 260 deletions(-) diff --git a/src/app/api/models/scorm-datamodel.ts b/src/app/api/models/scorm-datamodel.ts index e9d105f3c7..9454db78f6 100644 --- a/src/app/api/models/scorm-datamodel.ts +++ b/src/app/api/models/scorm-datamodel.ts @@ -1,12 +1,4 @@ export class ScormDataModel { - initState: {[key: string]: string} = { - 'cmi.completion_status': 'not attempted', - 'cmi.entry': 'ab-initio', - 'cmi.objectives._count': '0', - 'cmi.interactions._count': '0', - 'cmi.mode': 'normal', - }; - dataModel: {[key: string]: any} = {}; readonly msgPrefix = 'SCORM DataModel: '; @@ -14,17 +6,13 @@ export class ScormDataModel { this.dataModel = {}; } - public init() { - console.log(this.msgPrefix + 'initializing DataModel with default values'); - this.dataModel = this.initState; - } - - public restore(dataModel: {[key: string]: any} = {}) { + public restore(dataModel: string) { console.log(this.msgPrefix + 'restoring DataModel with provided data'); - this.dataModel = dataModel; + this.dataModel = JSON.parse(dataModel); } public get(key: string): string { + // console.log(`SCORM DataModel: get ${key} ${this.dataModel[key]}`); return this.dataModel[key] ?? ''; } @@ -33,23 +21,27 @@ export class ScormDataModel { } public set(key: string, value: any): string { - console.log(this.msgPrefix + 'set: ', key, value); + // console.log(this.msgPrefix + 'set: ', key, value); this.dataModel[key] = value; if (key.match('cmi.interactions.\\d+.id')) { + // cmi.interactions._count must be incremented after a new interaction is crated const interactionPath = key.match('cmi.interactions.\\d+'); const objectivesCounterForInteraction = interactionPath.toString() + '.objectives._count'; console.log('Incrementing cmi.interactions._count'); this.dataModel['cmi.interactions._count']++; + // cmi.interactions.n.objectives._count must be initialized after an interaction is created console.log(`Initializing ${objectivesCounterForInteraction}`); this.dataModel[objectivesCounterForInteraction] = 0; } if (key.match('cmi.interactions.\\d+.objectives.\\d+.id')) { const interactionPath = key.match('cmi.interactions.\\d+.objectives'); const objectivesCounterForInteraction = interactionPath.toString() + '._count'; + // cmi.interactions.n.objectives._count must be incremented after objective creation console.log(`Incrementing ${objectivesCounterForInteraction}`); this.dataModel[objectivesCounterForInteraction.toString()]++; } if (key.match('cmi.objectives.\\d+.id')) { + // cmi.objectives._count must be incremented after a new objective is crated console.log('Incrementing cmi.objectives._count'); this.dataModel['cmi.objectives._count']++; } diff --git a/src/app/api/models/scorm-player-context.ts b/src/app/api/models/scorm-player-context.ts index 5f1c4bd3ba..f3b3b8a13f 100644 --- a/src/app/api/models/scorm-player-context.ts +++ b/src/app/api/models/scorm-player-context.ts @@ -1,9 +1,56 @@ -import { Task, User } from 'src/app/api/models/doubtfire-model'; +import {Task, User} from 'src/app/api/models/doubtfire-model'; + +type DataModelState = 'Uninitialized' | 'Initialized' | 'Terminated'; + +type DataModelError = Record; +const CMIErrorCodes: DataModelError = { + 0: 'No Error', + 101: 'General Exception', + 102: 'General Initialization Failure', + 103: 'Already Initialized', + 104: 'Content Instance Terminated', + 111: 'General Termination Failure', + 112: 'Termination Before Initialization', + 113: 'Termination After Termination', + 122: 'Retrieve Data Before Initialization', + 123: 'Retrieve Data After Termination', + 132: 'Store Data Before Initialization', + 133: 'Store Data After Termination', + 142: 'Commit Before Initialization', + 143: 'Commit After Termination', + 201: 'General Argument Error', + 301: 'General Get Failure', + 351: 'General Set Failure', + 391: 'General Commit Failure', + 401: 'Undefined Data Model Element', + 402: 'Unimplemented Data Model Element', + 403: 'Data Model Element Value Not Initialized', + 404: 'Data Model Element Is Read Only', + 405: 'Data Model Element Is Write Only', + 406: 'Data Model Element Type Mismatch', + 407: 'Data Model Element Value Out Of Range', + 408: 'Data Model Dependency Not Established', +}; export class ScormPlayerContext { - task: Task; mode: 'browse' | 'normal' | 'review'; + state: DataModelState; + + private _errorCode: number; + get errorCode() { + return this._errorCode; + } + set errorCode(value: number) { + this._errorCode = value; + } + + getErrorMessage(value: string): string { + return CMIErrorCodes[value]; + } + + task: Task; user: User; + attemptNumber: number; attemptId: number; learnerName: string; @@ -13,21 +60,7 @@ export class ScormPlayerContext { this.user = user; this.learnerId = user.id; this.learnerName = user.firstName + ' ' + user.lastName; - } - - public setTask(task: Task): void { - this.task = task; - } - - public setMode(mode: 'browse' | 'normal' | 'review'): void { - this.mode = mode; - } - - public setAttemptNumber(attemptNumber: number = 1): void { - this.attemptNumber = attemptNumber; - } - - public setAttemptId(attemptId: number): void { - this.attemptId = attemptId; + this.state = 'Uninitialized'; + this.errorCode = 0; } } diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index a669b2fe36..985b810137 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -31,10 +31,10 @@ export class TaskDefinition extends Entity { groupSet: GroupSet = null; hasTaskSheet: boolean; hasTaskResources: boolean; - hasEnabledNumbasTest: boolean; - hasNumbasData: boolean; - hasNumbasTimeDelay: boolean; - numbasAttemptLimit: number = 0; + scormEnabled: boolean; + hasScormData: boolean; + scormTimeDelayEnabled: boolean; + scormAttemptLimit: number = 0; hasTaskAssessmentResources: boolean; isGraded: boolean; maxQualityPts: number; @@ -158,7 +158,7 @@ export class TaskDefinition extends Entity { public getNumbasTestUrl(asAttachment: boolean = false) { const constants = AppInjector.get(DoubtfireConstants); - return `${constants.API_URL}/units/${this.unit.id}/task_definitions/${this.id}/numbas_data.json${ + return `${constants.API_URL}/units/${this.unit.id}/task_definitions/${this.id}/scorm_data.json${ asAttachment ? '?as_attachment=true' : '' }`; } @@ -190,7 +190,7 @@ export class TaskDefinition extends Entity { public get numbasTestUploadUrl(): string { return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.unit.id}/task_definitions/${ this.id - }/numbas_data`; + }/scorm_data`; } public get taskAssessmentResourcesUploadUrl(): string { @@ -217,7 +217,7 @@ export class TaskDefinition extends Entity { public deleteNumbasTest(): Observable { const httpClient = AppInjector.get(HttpClient); - return httpClient.delete(this.numbasTestUploadUrl).pipe(tap(() => (this.hasNumbasData = false))); + return httpClient.delete(this.numbasTestUploadUrl).pipe(tap(() => (this.hasScormData = false))); } public deleteTaskAssessmentResources(): Observable { diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index 403165cfee..3803d325b6 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -509,7 +509,7 @@ export class Task extends Entity { public get numbasEnabled(): boolean { return ( - this.definition.hasEnabledNumbasTest && this.definition.hasNumbasData + this.definition.scormEnabled && this.definition.hasScormData ); } diff --git a/src/app/api/services/scorm-adapter.service.ts b/src/app/api/services/scorm-adapter.service.ts index 6c5353746b..8886121031 100644 --- a/src/app/api/services/scorm-adapter.service.ts +++ b/src/app/api/services/scorm-adapter.service.ts @@ -1,222 +1,212 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; -import { UserService } from './user.service'; +import {Injectable} from '@angular/core'; +import {UserService} from './user.service'; import API_URL from 'src/app/config/constants/apiURL'; -import { Task, ScormDataModel, ScormPlayerContext } from 'src/app/api/models/doubtfire-model'; +import {Task, ScormDataModel, ScormPlayerContext} from 'src/app/api/models/doubtfire-model'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class ScormAdapterService { private readonly apiBaseUrl = `${API_URL}/test_attempts`; private dataModel: ScormDataModel; - private playerContext: ScormPlayerContext; - - initializationComplete$ = new BehaviorSubject(false); - - private scormErrorCodes: {[key: string]: string} = { - '0': 'No Error', - '101': 'General Exception', - '102': 'General Initialization Failure', - '103': 'Already Initialized', - '104': 'Content Instance Terminated', - '111': 'General Termination Failure', - '112': 'Termination Before Initialization', - '113': 'Termination After Termination', - '122': 'Retrieve Data Before Initialization', - '123': 'Retrieve Data After Termination', - '132': 'Store Data Before Initialization', - '133': 'Store Data After Termination', - '142': 'Commit Before Initialization', - '143': 'Commit After Termination', - '201': 'General Argument Error', - '301': 'General Get Failure', - '351': 'General Set Failure', - '391': 'General Commit Failure', - '401': 'Undefined Data Model Element', - '402': 'Unimplemented Data Model Element', - '403': 'Data Model Element Value Not Initialized', - '404': 'Data Model Element Is Read Only', - '405': 'Data Model Element Is Write Only', - '406': 'Data Model Element Type Mismatch', - '407': 'Data Model Element Value Out Of Range', - '408': 'Data Model Dependency Not Established', - }; + private context: ScormPlayerContext; + private xhr: XMLHttpRequest; constructor(private userService: UserService) { this.dataModel = new ScormDataModel(); - this.playerContext = new ScormPlayerContext(this.userService.currentUser); + this.context = new ScormPlayerContext(this.userService.currentUser); + this.xhr = new XMLHttpRequest(); } - setTask(task: Task) { - this.playerContext.setTask(task); + set task(task: Task) { + this.context.task = task; } - // getDefaultDataStore() { - // // Use spread operator to merge defaultValues into the dataStore - // return { - // ...this.defaultValues, - // pass_status: false, - // completed: false, - // }; - // } - - Initialize(mode: 'attempt' | 'review' = 'attempt'): string { - console.log('Initialize() function called'); - const xhr = new XMLHttpRequest(); - if (mode === 'review') { - this.SetValue('cmi.mode', 'review'); - - xhr.open( - 'GET', - `${this.apiBaseUrl}/completed-latest?task_id=${this.playerContext.task.id}`, - false, - ); - xhr.send(); - console.log(xhr.responseText); + get state() { + return this.context.state; + } - if (xhr.status !== 200) { - console.error('Error fetching latest completed test result:', xhr.statusText); - return 'false'; - } + destroy() { + this.dataModel = new ScormDataModel(); + this.context.state = 'Uninitialized'; + } - try { - const completedTest = JSON.parse(xhr.responseText); - const parsedDataModel = JSON.parse(completedTest.data.suspend_data ?? '{}'); + Initialize(): string { + console.log('API_1484_11: Initialize'); + + // TODO: error handling and reporting + switch (this.context.state) { + case 'Initialized': + this.context.errorCode = 103; + console.log('Already Initialized'); + break; + case 'Terminated': + this.context.errorCode = 104; + console.log('Content Instance Terminated'); + break; + } - // Set entire suspendData string to cmi.suspend_data - this.SetValue('cmi.suspend_data', JSON.stringify(parsedDataModel)); + // TODO: move this part into the player component + this.xhr.open('GET', `${this.apiBaseUrl}/${this.context.task.id}/latest`, false); - // // Use SetValue to set parsedSuspendData values to dataStore - // Object.keys(parsedDataModel).forEach((key) => { - // this.SetValue(key, parsedDataModel[key]); - // }); + let noTestFound = false; + let startNewTest = false; - this.dataModel.restore(parsedDataModel); + this.xhr.onload = () => { + if (this.xhr.status >= 200 && this.xhr.status < 400) { + console.log('Retrieved the latest attempt.'); + } else if (this.xhr.status == 404) { + console.log('Not found.'); + noTestFound = true; + } else { + console.error('Error saving DataModel:', this.xhr.responseText); + } + }; - this.SetValue('cmi.entry', 'RO'); - this.SetValue('cmi.mode', 'review'); + this.xhr.send(); + console.log(this.xhr.responseText); - console.log('Latest completed test data:', completedTest); - return 'true'; - } catch (error) { - console.error('Error:', error); - return 'false'; + if (!noTestFound) { + const latestSession = JSON.parse(this.xhr.responseText); + console.log('Latest exam session:', latestSession); + this.context.attemptId = latestSession.id; + if (latestSession.completion_status) { + startNewTest = true; } + } else { + startNewTest = true; } - xhr.open('GET', `${this.apiBaseUrl}/latest?task_id=${this.playerContext.task.id}`, false); - xhr.send(); - console.log(xhr.responseText); - - if (xhr.status !== 200) { - console.error('Error fetching latest test result:', xhr.statusText); - return 'false'; + if (!startNewTest) { + this.xhr.open( + 'PATCH', + `${this.apiBaseUrl}/${this.context.task.id}/session/${this.context.attemptId}`, + false, + ); + this.xhr.send(); + console.log(this.xhr.responseText); + + const currentSession = JSON.parse(this.xhr.responseText); + console.log('Current exam session:', currentSession); + this.context.attemptId = currentSession.id; + this.dataModel.restore(currentSession.cmi_datamodel); + console.log(this.dataModel.dump()); + } else { + this.xhr.open('POST', `${this.apiBaseUrl}/${this.context.task.id}/session`, false); + this.xhr.send(); + console.log(this.xhr.responseText); + + const currentSession = JSON.parse(this.xhr.responseText); + console.log('Current exam session:', currentSession); + this.context.attemptId = currentSession.id; + this.dataModel.restore(currentSession.cmi_datamodel); + console.log(this.dataModel.dump()); } - let latestTest; - try { - latestTest = JSON.parse(xhr.responseText); - console.log('Latest test result:', latestTest); - this.playerContext.attemptId = latestTest.data.id; - - if (latestTest.data['cmi_entry'] === 'ab-initio') { - console.log('starting new test'); - this.dataModel.init(); - this.SetValue('cmi.learner_id', this.playerContext.learnerId); - this.SetValue('cmi.learner_name', this.playerContext.learnerName); - - this.dataModel.set('attempt_number', latestTest.data['attempt_number']); - console.log(this.dataModel.dump()); - } else if (latestTest.data['cmi_entry'] === 'resume') { - console.log('resuming test'); - const restoredDataModel = JSON.parse(latestTest.data.suspend_data ?? '{}'); - this.dataModel.restore(JSON.parse(JSON.stringify(restoredDataModel))); - - console.log(this.dataModel.dump()); - } - - this.initializationComplete$.next(true); - - console.log('finished initializing'); - return 'true'; - } catch (error) { - console.error('Error:', error); - return 'false'; - } + this.context.state = 'Initialized'; + return 'true'; } - // isTestCompleted(): boolean { - // return this.dataModel.get('completed') ?? false; - // } - Terminate(): string { - console.log('Terminate Called'); - const examResult = this.dataModel.get('cmi.score.raw'); - const status = this.dataModel.get('cmi.success_status'); - this.dataModel.set('completed', true); - const currentAttemptNumber = this.dataModel.get('attempt_number') ?? 0; - const ExamName = this.dataModel.get('name'); - this.dataModel.set('cmi.entry', 'RO'); - const cmientry = this.dataModel.get('cmi.entry'); - const data = { - name: ExamName, - attempt_number: currentAttemptNumber, - pass_status: status === 'passed', - suspend_data: JSON.stringify(this.dataModel.dump()), - completed: true, - exam_result: examResult, - cmi_entry: cmientry, - task_id: this.playerContext.task.id - }; - - const xhr = new XMLHttpRequest(); - if (this.playerContext.attemptId) { - xhr.open('PUT', `${this.apiBaseUrl}/${this.playerContext.attemptId}`, false); - } else { - xhr.open('POST', this.apiBaseUrl, false); + console.log('API_1484_11: Terminate'); + + // TODO: error handling and reporting + switch (this.context.state) { + case 'Uninitialized': + this.context.errorCode = 112; + console.log('Termination Before Initialization'); + break; + case 'Terminated': + this.context.errorCode = 113; + console.log('Termination After Termination'); + break; } - xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); - xhr.send(JSON.stringify(data)); - if (xhr.status !== 200) { - console.error('Error sending test data:', xhr.statusText); - return 'false'; - } - this.dataModel.init(); + this.xhr.open( + 'PATCH', + `${this.apiBaseUrl}/${this.context.task.id}/session/${this.context.attemptId}`, + false, + ); + this.xhr.setRequestHeader('Content-Type', 'application/json'); + const requestData = { + terminated: true, + }; + this.xhr.send(JSON.stringify(requestData)); + console.log(this.xhr.responseText); + + // all done, clearing datamodel and setting state to terminated + this.dataModel = new ScormDataModel(); + this.context.state = 'Terminated'; return 'true'; } GetValue(element: string): string { const value = this.dataModel.get(element); - console.log(`GetValue:`, element, value); + + // TODO: error reporting + // TODO: can't get until init is done + switch (this.context.state) { + case 'Uninitialized': + this.context.errorCode = 122; + console.log('Retrieve Data Before Initialization'); + break; + case 'Terminated': + this.context.errorCode = 123; + console.log('Retrieve Data After Termination'); + break; + } + + console.log(`API_1484_11: GetValue:`, element, value); return value; } SetValue(element: string, value: any): string { - console.log(`SetValue:`, element, value); + console.log(`API_1484_11: SetValue:`, element, value); + + // TODO: error reporting + // TODO: can't set until init is done + switch (this.context.state) { + case 'Uninitialized': + this.context.errorCode = 132; + console.log('Store Data Before Initialization'); + break; + case 'Terminated': + this.context.errorCode = 133; + console.log('Store Data After Termination'); + break; + } + this.dataModel.set(element, value); return 'true'; } - // Saves the state of the exam. Commit(): string { - if (!this.initializationComplete$.getValue()) { - console.warn('Initialization not complete. Cannot commit.'); - return 'false'; + console.log('API_1484_11: Commit'); + + // TODO: error reporting + // TODO: can't commit until init is done + switch (this.context.state) { + case 'Uninitialized': + this.context.errorCode = 142; + console.log('Commit Before Initialization'); + break; + case 'Terminated': + this.context.errorCode = 143; + console.log('Commit After Termination'); + break; } - // Set cmi.entry to 'resume' before committing dataStore - this.dataModel.set('cmi.entry', 'resume'); - // if (!this.isTestCompleted()) { - // this.dataModel.set('cmi.exit', 'suspend'); - // } - console.log('Committing DataModel:', this.dataModel.dump()); - - // Use XHR to send the request const xhr = new XMLHttpRequest(); - xhr.open('PUT', `${this.apiBaseUrl}/${this.playerContext.attemptId}/suspend`, true); + xhr.open( + 'PATCH', + `${this.apiBaseUrl}/${this.context.task.id}/session/${this.context.attemptId}`, + true, + ); xhr.setRequestHeader('Content-Type', 'application/json'); + const requestData = { + cmi_datamodel: JSON.stringify(this.dataModel.dump()), + }; + xhr.send(JSON.stringify(requestData)); xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 400) { @@ -230,23 +220,27 @@ export class ScormAdapterService { console.error('Request failed.'); }; - const requestData = { suspend_data: this.dataModel.dump() }; - xhr.send(JSON.stringify(requestData)); + this.context.errorCode = 0; return 'true'; } - // Placeholder methods for SCORM error handling GetLastError(): string { - //console.log('Get Last Error called'); - return "0"; + const lastError = this.context.errorCode.toString(); + if (lastError !== '0') { + console.log(`API_1484_11: GetLastError: ${lastError}`); + } + return lastError; } GetErrorString(errorCode: string): string { - return ''; + const errorString = this.context.getErrorMessage(errorCode); + console.log(`API_1484_11: GetErrorString:`, errorCode, errorString); + return errorString; } GetDiagnostic(errorCode: string): string { - //console.log('Get Diagnoistic called'); - return ''; + // TODO: implement this + console.log(`API_1484_11: GetDiagnostic:`, errorCode); + return 'GetDiagnostic is currently not implemented'; } } diff --git a/src/app/api/services/task-comment.service.ts b/src/app/api/services/task-comment.service.ts index e3c80797a4..5f034b870d 100644 --- a/src/app/api/services/task-comment.service.ts +++ b/src/app/api/services/task-comment.service.ts @@ -145,7 +145,7 @@ export class TaskCommentService extends CachedEntityService { const opts: RequestOptions = { endpointFormat: this.commentEndpointFormat }; // Based on the comment type - add to the body and configure the end point - if (commentType === 'text' || commentType === 'numbas') { + if (commentType === 'text' || commentType === 'scorm') { body.append('comment', data); } else if (commentType === 'discussion') { opts.endpointFormat = this.discussionEndpointFormat; diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 6047af0546..a738626884 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -93,10 +93,10 @@ export class TaskDefinitionService extends CachedEntityService { 'hasTaskSheet', 'hasTaskResources', 'hasTaskAssessmentResources', - 'hasEnabledNumbasTest', - 'hasNumbasData', - 'hasNumbasTimeDelay', - 'numbasAttemptLimit', + 'scormEnabled', + 'hasScormData', + 'scormTimeDelayEnabled', + 'scormAttemptLimit', 'isGraded', 'maxQualityPts', 'overseerImageId', @@ -108,7 +108,7 @@ export class TaskDefinitionService extends CachedEntityService { 'hasTaskSheet', 'hasTaskResources', 'hasTaskAssessmentResources', - 'hasNumbasData' + 'hasScormData' ); } diff --git a/src/app/common/scorm-player/scorm-player-modal.component.ts b/src/app/common/scorm-player/scorm-player-modal.component.ts index 190e7bf570..2fb4630263 100644 --- a/src/app/common/scorm-player/scorm-player-modal.component.ts +++ b/src/app/common/scorm-player/scorm-player-modal.component.ts @@ -1,20 +1,21 @@ -import { Injectable } from '@angular/core'; -import { MatDialog, MatDialogRef } from '@angular/material/dialog'; -import { ScormPlayerComponent } from './scorm-player.component'; -import { Task } from 'src/app/api/models/task'; +import {Injectable} from '@angular/core'; +import {MatDialog, MatDialogRef} from '@angular/material/dialog'; +import {ScormPlayerComponent} from './scorm-player.component'; +import {Task} from 'src/app/api/models/task'; @Injectable({ providedIn: 'root', }) export class ScormPlayerModal { - constructor(public dialog: MatDialog) { } + constructor(public dialog: MatDialog) {} public show(task: Task, mode: 'attempt' | 'review'): void { let dialogRef: MatDialogRef; dialogRef = this.dialog.open(ScormPlayerComponent, { - data: { task, mode }, - width: '95%', height: '90%', + data: {task, mode}, + width: '95%', + height: '90%', disableClose: true, }); } diff --git a/src/app/common/scorm-player/scorm-player.component.ts b/src/app/common/scorm-player/scorm-player.component.ts index 428f6869b7..1b89e36bae 100644 --- a/src/app/common/scorm-player/scorm-player.component.ts +++ b/src/app/common/scorm-player/scorm-player.component.ts @@ -1,13 +1,15 @@ -import { Component, OnInit, Inject } from '@angular/core'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; -import { Task, ScormDataModel, ScormPlayerContext } from 'src/app/api/models/doubtfire-model'; -import { ScormAdapterService } from 'src/app/api/services/scorm-adapter.service'; -import { AppInjector } from 'src/app/app-injector'; -import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; +import {Component, OnInit, Inject} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser'; +import {Task, ScormPlayerContext} from 'src/app/api/models/doubtfire-model'; +import {ScormAdapterService} from 'src/app/api/services/scorm-adapter.service'; +import {AppInjector} from 'src/app/app-injector'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; declare global { - interface Window { API_1484_11: any; } + interface Window { + API_1484_11: any; + } } @Component({ @@ -24,34 +26,41 @@ export class ScormPlayerComponent implements OnInit { constructor( private dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: { task: Task, mode: 'attempt' | 'review' }, + @Inject(MAT_DIALOG_DATA) public data: {task: Task; mode: 'attempt' | 'review'}, private scormAdapter: ScormAdapterService, - private sanitizer: DomSanitizer + private sanitizer: DomSanitizer, ) {} ngOnInit(): void { this.task = this.data.task; - this.scormAdapter.setTask(this.task); + this.scormAdapter.task = this.task; window.API_1484_11 = { - Initialize: () => this.scormAdapter.Initialize(this.currentMode), + Initialize: () => this.scormAdapter.Initialize(), Terminate: () => this.scormAdapter.Terminate(), GetValue: (element: string) => this.scormAdapter.GetValue(element), SetValue: (element: string, value: string) => this.scormAdapter.SetValue(element, value), Commit: () => this.scormAdapter.Commit(), GetLastError: () => this.scormAdapter.GetLastError(), GetErrorString: (errorCode: string) => this.scormAdapter.GetErrorString(errorCode), - GetDiagnostic: (errorCode: string) => this.scormAdapter.GetDiagnostic(errorCode) + GetDiagnostic: (errorCode: string) => this.scormAdapter.GetDiagnostic(errorCode), }; this.currentMode = this.data.mode; - this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(`${AppInjector.get(DoubtfireConstants).API_URL}/numbas_api/${this.task.taskDefId}/index.html`); + this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl( + `${AppInjector.get(DoubtfireConstants).API_URL}/scorm/${this.task.taskDefId}/index.html`, + ); } close(): void { - console.log('SCORM player closing, commiting DataModel!'); - this.scormAdapter.Commit(); + if (this.scormAdapter.state == 'Initialized') { + console.log('SCORM player closing during an initialized session, commiting DataModel'); + this.scormAdapter.Commit(); + } + // TODO: would be nice if we can destroy this entire adapter object when the modal is closed + console.log('Clearing player context and DataModel'); + this.scormAdapter.destroy(); const iframe = document.getElementsByTagName('iframe')[0]; iframe?.parentNode?.removeChild(iframe); this.dialogRef.close(); diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee index 6a17bd558c..7c0baf7ee9 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee @@ -128,7 +128,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) removed.push('group') if !isRFF || !task.isGroupTask() removed.push('alignment') if !isRFF || !task.unit.ilos.length > 0 removed.push('comments') if isTestSubmission - removed.push('scorm-assessment') if !isRFF || !task.definition.hasEnabledNumbasTest + removed.push('scorm-assessment') if !isRFF || !task.definition.scormEnabled removed # Initialises the states initialise: -> diff --git a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts b/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts index 650a110d0f..c8ba676c55 100644 --- a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts @@ -1,6 +1,6 @@ -import { Component, OnInit, Input } from '@angular/core'; -import { Task, TaskComment } from 'src/app/api/models/doubtfire-model'; -import { ScormPlayerModal } from 'src/app/common/scorm-player/scorm-player-modal.component'; +import {Component, OnInit, Input} from '@angular/core'; +import {Task, TaskComment} from 'src/app/api/models/doubtfire-model'; +import {ScormPlayerModal} from 'src/app/common/scorm-player/scorm-player-modal.component'; @Component({ selector: 'numbas-comment', diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html index cd18eda9ba..0be0e7b758 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html @@ -72,7 +72,7 @@ >
-
+
- + Enable Numbas Test @@ -10,7 +10,7 @@ accept="application/zip" [desiredFileName]="'Numbas zip'" /> - @if (taskDefinition.hasNumbasData) { + @if (taskDefinition.hasScormData) {
- @if (taskDefinition.hasEnabledNumbasTest) { + @if (taskDefinition.scormEnabled) {
- + Enable incremental time delays between test attempts @@ -34,7 +34,7 @@ min="0" max="100" type="number" - [(ngModel)]="taskDefinition.numbasAttemptLimit" + [(ngModel)]="taskDefinition.scormAttemptLimit" [formControl]="attemptLimitControl" /> From 644c025e698480276a068d717589be547817ddc8 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 14 May 2024 13:18:33 +1000 Subject: [PATCH 0077/1531] refactor: rename numbas references to scorm and fix typos --- src/app/api/models/scorm-datamodel.ts | 4 +- src/app/api/models/task-definition.ts | 8 +- src/app/api/models/task.ts | 2 +- .../spec/scorm-adapter.service.spec.ts | 87 ------------------- .../api/services/task-definition.service.ts | 4 +- .../scorm-player-modal.component.ts | 2 +- .../scorm-player/scorm-player.component.ts | 4 +- src/app/doubtfire-angular.module.ts | 8 +- .../upload-submission-modal.coffee | 2 +- .../upload-submission-modal.tpl.html | 6 +- .../scorm-comment.component.html} | 4 +- .../scorm-comment.component.scss} | 0 .../scorm-comment.component.ts} | 10 +-- .../task-comments-viewer.component.html | 8 +- .../task-comments-viewer.component.ts | 6 +- .../task-definition-editor.component.html | 6 +- .../task-definition-scorm.component.html} | 14 +-- .../task-definition-scorm.component.scss} | 0 .../task-definition-scorm.component.ts} | 32 +++---- 19 files changed, 60 insertions(+), 147 deletions(-) delete mode 100644 src/app/api/services/spec/scorm-adapter.service.spec.ts rename src/app/tasks/task-comments-viewer/{numbas-comment/numbas-comment.component.html => scorm-comment/scorm-comment.component.html} (65%) rename src/app/tasks/task-comments-viewer/{numbas-comment/numbas-comment.component.scss => scorm-comment/scorm-comment.component.scss} (100%) rename src/app/tasks/task-comments-viewer/{numbas-comment/numbas-comment.component.ts => scorm-comment/scorm-comment.component.ts} (66%) rename src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/{task-definition-numbas/task-definition-numbas.component.html => task-definition-scorm/task-definition-scorm.component.html} (78%) rename src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/{task-definition-numbas/task-definition-numbas.component.scss => task-definition-scorm/task-definition-scorm.component.scss} (100%) rename src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/{task-definition-numbas/task-definition-numbas.component.ts => task-definition-scorm/task-definition-scorm.component.ts} (58%) diff --git a/src/app/api/models/scorm-datamodel.ts b/src/app/api/models/scorm-datamodel.ts index 9454db78f6..7559318eb5 100644 --- a/src/app/api/models/scorm-datamodel.ts +++ b/src/app/api/models/scorm-datamodel.ts @@ -24,7 +24,7 @@ export class ScormDataModel { // console.log(this.msgPrefix + 'set: ', key, value); this.dataModel[key] = value; if (key.match('cmi.interactions.\\d+.id')) { - // cmi.interactions._count must be incremented after a new interaction is crated + // cmi.interactions._count must be incremented after a new interaction is created const interactionPath = key.match('cmi.interactions.\\d+'); const objectivesCounterForInteraction = interactionPath.toString() + '.objectives._count'; console.log('Incrementing cmi.interactions._count'); @@ -41,7 +41,7 @@ export class ScormDataModel { this.dataModel[objectivesCounterForInteraction.toString()]++; } if (key.match('cmi.objectives.\\d+.id')) { - // cmi.objectives._count must be incremented after a new objective is crated + // cmi.objectives._count must be incremented after a new objective is created console.log('Incrementing cmi.objectives._count'); this.dataModel['cmi.objectives._count']++; } diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index 985b810137..538b449338 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -156,7 +156,7 @@ export class TaskDefinition extends Entity { }`; } - public getNumbasTestUrl(asAttachment: boolean = false) { + public getScormDataUrl(asAttachment: boolean = false) { const constants = AppInjector.get(DoubtfireConstants); return `${constants.API_URL}/units/${this.unit.id}/task_definitions/${this.id}/scorm_data.json${ asAttachment ? '?as_attachment=true' : '' @@ -187,7 +187,7 @@ export class TaskDefinition extends Entity { }/task_resources`; } - public get numbasTestUploadUrl(): string { + public get scormDataUploadUrl(): string { return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.unit.id}/task_definitions/${ this.id }/scorm_data`; @@ -215,9 +215,9 @@ export class TaskDefinition extends Entity { return httpClient.delete(this.taskResourcesUploadUrl).pipe(tap(() => (this.hasTaskResources = false))); } - public deleteNumbasTest(): Observable { + public deleteScormData(): Observable { const httpClient = AppInjector.get(HttpClient); - return httpClient.delete(this.numbasTestUploadUrl).pipe(tap(() => (this.hasScormData = false))); + return httpClient.delete(this.scormDataUploadUrl).pipe(tap(() => (this.hasScormData = false))); } public deleteTaskAssessmentResources(): Observable { diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index 3803d325b6..556d0a7dd2 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -507,7 +507,7 @@ export class Task extends Entity { ); } - public get numbasEnabled(): boolean { + public get scormEnabled(): boolean { return ( this.definition.scormEnabled && this.definition.hasScormData ); diff --git a/src/app/api/services/spec/scorm-adapter.service.spec.ts b/src/app/api/services/spec/scorm-adapter.service.spec.ts deleted file mode 100644 index 5d3a52caac..0000000000 --- a/src/app/api/services/spec/scorm-adapter.service.spec.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; -import { ScormAdapterService } from '../scorm-adapter.service'; -import { TaskService } from '../task.service'; -import { UserService } from '../user.service'; - -describe('ScormAdapterService', () => { - let service: ScormAdapterService; - let httpTestingController: HttpTestingController; - let mockUserService: Partial; - let mockTaskService: Partial; - - const mockUserData = { - currentUser: { studentId: '12345' } - }; - - beforeEach(() => { - mockUserService = { - currentUser: mockUserData.currentUser - }; - - mockTaskService = { - // you can add mocked methods if needed for the TaskService - }; - - TestBed.configureTestingModule({ - imports: [HttpClientTestingModule], - providers: [ - ScormAdapterService, - { provide: UserService, useValue: mockUserService }, - { provide: TaskService, useValue: mockTaskService } - ] - }); - - service = TestBed.inject(ScormAdapterService); - httpTestingController = TestBed.inject(HttpTestingController); - }); - - afterEach(() => { - httpTestingController.verify(); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); - - it('should initialize with default values', () => { - expect(service.GetValue('cmi.completion_status')).toBe('not attempted'); - expect(service.GetValue('cmi.entry')).toBe('ab-initio'); - }); - - describe('Initialize function', () => { - - it('should handle review mode and get latest completed test result', () => { - const mockResponse = { - data: { - suspend_data: JSON.stringify({ someData: 'value' }) - } - }; - - service.Initialize('review'); - const req = httpTestingController.expectOne(`${service['apiBaseUrl']}/completed-latest`); - expect(req.request.method).toEqual('GET'); - req.flush(mockResponse); - - expect(service.GetValue('cmi.suspend_data')).toEqual(JSON.stringify({ someData: 'value' })); - }); - - it('should handle attempt mode and get latest test result', () => { - const mockResponse = { - data: { - id: 1, - cmi_entry: 'ab-initio', - attempt_number: 2 - } - }; - - service.Initialize('attempt'); - const req = httpTestingController.expectOne(`${service['apiBaseUrl']}/latest`); - expect(req.request.method).toEqual('GET'); - req.flush(mockResponse); - - expect(service.GetValue('cmi.learner_id')).toBe('12345'); - }); - }); - -}); diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index a738626884..defd83dc77 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -134,9 +134,9 @@ export class TaskDefinitionService extends CachedEntityService { return AppInjector.get(HttpClient).post(taskDefinition.taskAssessmentResourcesUploadUrl, formData); } - public uploadNumbasData(taskDefinition: TaskDefinition, file: File): Observable { + public uploadScormData(taskDefinition: TaskDefinition, file: File): Observable { const formData = new FormData(); formData.append('file', file); - return AppInjector.get(HttpClient).post(taskDefinition.numbasTestUploadUrl, formData); + return AppInjector.get(HttpClient).post(taskDefinition.scormDataUploadUrl, formData); } } diff --git a/src/app/common/scorm-player/scorm-player-modal.component.ts b/src/app/common/scorm-player/scorm-player-modal.component.ts index 2fb4630263..cd7740571c 100644 --- a/src/app/common/scorm-player/scorm-player-modal.component.ts +++ b/src/app/common/scorm-player/scorm-player-modal.component.ts @@ -9,7 +9,7 @@ import {Task} from 'src/app/api/models/task'; export class ScormPlayerModal { constructor(public dialog: MatDialog) {} - public show(task: Task, mode: 'attempt' | 'review'): void { + public show(task: Task, mode: 'browse' | 'normal' | 'review'): void { let dialogRef: MatDialogRef; dialogRef = this.dialog.open(ScormPlayerComponent, { diff --git a/src/app/common/scorm-player/scorm-player.component.ts b/src/app/common/scorm-player/scorm-player.component.ts index 1b89e36bae..106e6a8520 100644 --- a/src/app/common/scorm-player/scorm-player.component.ts +++ b/src/app/common/scorm-player/scorm-player.component.ts @@ -21,12 +21,12 @@ export class ScormPlayerComponent implements OnInit { context: ScormPlayerContext; task: Task; - currentMode: 'attempt' | 'review' = 'attempt'; + currentMode: 'browse' | 'normal' | 'review' = 'normal'; iframeSrc: SafeResourceUrl; constructor( private dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: {task: Task; mode: 'attempt' | 'review'}, + @Inject(MAT_DIALOG_DATA) public data: {task: Task, mode: 'browse' | 'normal' | 'review'}, private scormAdapter: ScormAdapterService, private sanitizer: DomSanitizer, ) {} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 23145ccaea..110ae4a3a2 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -204,7 +204,7 @@ import {TaskDefinitionUploadComponent} from './units/states/edit/directives/unit import {TaskDefinitionOptionsComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component'; import {TaskDefinitionResourcesComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component'; import {TaskDefinitionOverseerComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component'; -import {TaskDefinitionNumbasComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component'; +import {TaskDefinitionScormComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component'; import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-route.component'; import {FileDropComponent} from './common/file-drop/file-drop.component'; import {UnitTaskEditorComponent} from './units/states/edit/directives/unit-tasks-editor/unit-task-editor.component'; @@ -228,7 +228,7 @@ import {UnitCodeComponent} from './common/unit-code/unit-code.component'; import {GradeService} from './common/services/grade.service'; import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; import {ScormAdapterService} from './api/services/scorm-adapter.service'; -import {NumbasCommentComponent} from './tasks/task-comments-viewer/numbas-comment/numbas-comment.component'; +import {ScormCommentComponent} from './tasks/task-comments-viewer/scorm-comment/scorm-comment.component'; import {TestAttemptService} from './api/services/test-attempt.service'; @NgModule({ @@ -268,7 +268,7 @@ import {TestAttemptService} from './api/services/test-attempt.service'; TaskDefinitionOptionsComponent, TaskDefinitionResourcesComponent, TaskDefinitionOverseerComponent, - TaskDefinitionNumbasComponent, + TaskDefinitionScormComponent, UnitAnalyticsComponent, StudentTutorialSelectComponent, StudentCampusSelectComponent, @@ -333,7 +333,7 @@ import {TestAttemptService} from './api/services/test-attempt.service'; FTaskBadgeComponent, FUnitsComponent, ScormPlayerComponent, - NumbasCommentComponent, + ScormCommentComponent, ], // Services we provide providers: [ diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee index 7c0baf7ee9..976c116f33 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee @@ -157,7 +157,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) $scope.launchScormPlayer = -> console.clear() - ScormPlayerModal.show $scope.task, 'attempt' + ScormPlayerModal.show $scope.task, 'normal' # Whether or not we should disable this button $scope.shouldDisableBtn = { diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html index 8b6c89bea3..0b296c2099 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html @@ -50,15 +50,15 @@

- Attempt Numbas Test + Attempt SCORM Test

- Complete the Numbas test first to proceed to upload evidence of your task completion. + Complete the SCORM test first to proceed to upload evidence of your task completion.
diff --git a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.html b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html similarity index 65% rename from src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.html rename to src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html index d87863bee8..b74db43a07 100644 --- a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.html +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html @@ -1,9 +1,9 @@
-
+
- +
diff --git a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.scss b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.scss similarity index 100% rename from src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.scss rename to src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.scss diff --git a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts similarity index 66% rename from src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts rename to src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts index c8ba676c55..817a6cd64f 100644 --- a/src/app/tasks/task-comments-viewer/numbas-comment/numbas-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts @@ -3,11 +3,11 @@ import {Task, TaskComment} from 'src/app/api/models/doubtfire-model'; import {ScormPlayerModal} from 'src/app/common/scorm-player/scorm-player-modal.component'; @Component({ - selector: 'numbas-comment', - templateUrl: './numbas-comment.component.html', - styleUrls: ['./numbas-comment.component.scss'], + selector: 'scorm-comment', + templateUrl: './scorm-comment.component.html', + styleUrls: ['./scorm-comment.component.scss'], }) -export class NumbasCommentComponent implements OnInit { +export class ScormCommentComponent implements OnInit { @Input() task: Task; @Input() comment: TaskComment; @@ -15,7 +15,7 @@ export class NumbasCommentComponent implements OnInit { ngOnInit() {} - reviewNumbasTest() { + reviewScormTest() { this.modalService.show(this.task, 'review'); } } diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html index 0be0e7b758..aa20275ff6 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html @@ -72,12 +72,12 @@ >
-
- + + *ngIf="scormEnabled" + >
diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts index 7436cd7d79..8ad719f339 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts @@ -98,8 +98,8 @@ export class TaskCommentsViewerComponent implements OnChanges, OnInit { return this.constants.IsOverseerEnabled.value; } - get numbasEnabled(): boolean { - return this.task.numbasEnabled; + get scormEnabled(): boolean { + return this.task.scormEnabled; } uploadFiles(event) { @@ -154,7 +154,7 @@ export class TaskCommentsViewerComponent implements OnChanges, OnInit { } shouldShowAuthorIcon(commentType: string) { - return !(commentType === 'extension' || commentType === 'status' || commentType == 'assessment' || commentType == 'numbas'); + return !(commentType === 'extension' || commentType === 'status' || commentType == 'assessment' || commentType == 'scorm'); } commentClasses(comment: TaskComment): object { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html index bd2c7ec65d..6bc386569e 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html @@ -105,10 +105,10 @@

-

Upload Numbas test

-

Upload the corresponding Numbas test

+

Upload SCORM test

+

Upload the corresponding SCORM 2004 test (e.g. Numbas)

- +

diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html similarity index 78% rename from src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.html rename to src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html index 36acb4ca4c..433405669b 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html @@ -1,22 +1,22 @@
- Enable Numbas Test + Enable test for task
@if (taskDefinition.hasScormData) {
- -
} diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.scss b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.scss similarity index 100% rename from src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.scss rename to src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.scss diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts similarity index 58% rename from src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.ts rename to src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts index f6687a4af9..8f2b72fcb9 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-numbas/task-definition-numbas.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts @@ -7,11 +7,11 @@ import { TaskDefinitionService } from 'src/app/api/services/task-definition.serv import { FileDownloaderService } from 'src/app/common/file-downloader/file-downloader.service'; @Component({ - selector: 'f-task-definition-numbas', - templateUrl: 'task-definition-numbas.component.html', - styleUrls: ['task-definition-numbas.component.scss'], + selector: 'f-task-definition-scorm', + templateUrl: 'task-definition-scorm.component.html', + styleUrls: ['task-definition-scorm.component.scss'], }) -export class TaskDefinitionNumbasComponent { +export class TaskDefinitionScormComponent { @Input() taskDefinition: TaskDefinition; constructor( @@ -26,32 +26,32 @@ export class TaskDefinitionNumbasComponent { return this.taskDefinition?.unit; } - public downloadNumbasTest() { + public downloadScormData() { this.fileDownloaderService.downloadFile( - this.taskDefinition.getNumbasTestUrl(true), - this.taskDefinition.name + '-Numbas.zip', + this.taskDefinition.getScormDataUrl(true), + this.taskDefinition.name + '-SCORM.zip', ); } - public removeNumbasTest() { - this.taskDefinition.deleteNumbasTest().subscribe({ - next: () => this.alerts.add('success', 'Deleted Numbas test', 2000), - error: (message) => this.alerts.add('danger', message, 6000), + public removeScormData() { + this.taskDefinition.deleteScormData().subscribe({ + next: () => this.alerts.success('Deleted SCORM test data', 2000), + error: (message) => this.alerts.error(message, 6000), }); } - public uploadNumbasTest(files: FileList) { + public uploadScormData(files: FileList) { console.log(Array.from(files).map(f => f.type)); const validMimeTypes = ['application/zip', 'application/x-zip-compressed', 'multipart/x-zip']; const validFiles = Array.from(files as ArrayLike).filter(f => validMimeTypes.includes(f.type)); if (validFiles.length > 0) { const file = validFiles[0]; - this.taskDefinitionService.uploadNumbasData(this.taskDefinition, file).subscribe({ - next: () => this.alerts.add('success', 'Uploaded Numbas test data', 2000), - error: (message) => this.alerts.add('danger', message, 6000), + this.taskDefinitionService.uploadScormData(this.taskDefinition, file).subscribe({ + next: () => this.alerts.success('Uploaded SCORM test data', 2000), + error: (message) => this.alerts.error(message, 6000), }); } else { - this.alerts.add('danger', 'Please drop a zip file to upload Numbas test data for this task', 6000); + this.alerts.error('Please drop a zip file to upload SCORM test data for this task', 6000); } } } From 2ac487f13c3743f2b5b805521964bdcbca7cdc15 Mon Sep 17 00:00:00 2001 From: ublefo <90136978+ublefo@users.noreply.github.com> Date: Tue, 14 May 2024 13:25:23 +1000 Subject: [PATCH 0078/1531] fix: ensure datamodel is updated on termination --- src/app/api/services/scorm-adapter.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/api/services/scorm-adapter.service.ts b/src/app/api/services/scorm-adapter.service.ts index 8886121031..9519f4cc2c 100644 --- a/src/app/api/services/scorm-adapter.service.ts +++ b/src/app/api/services/scorm-adapter.service.ts @@ -129,6 +129,7 @@ export class ScormAdapterService { ); this.xhr.setRequestHeader('Content-Type', 'application/json'); const requestData = { + cmi_datamodel: JSON.stringify(this.dataModel.dump()), terminated: true, }; this.xhr.send(JSON.stringify(requestData)); From fc023af462656e3557e2970f211fa4d59ee1e3d5 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 14 May 2024 14:24:31 +1000 Subject: [PATCH 0079/1531] feat: allow changing scorm review config and add minor UI changes --- src/app/api/models/task-definition.ts | 1 + .../api/services/task-definition.service.ts | 1 + .../task-definition-editor.component.html | 2 +- .../task-definition-scorm.component.html | 49 ++++++++++--------- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index 538b449338..ca2d188eb6 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -33,6 +33,7 @@ export class TaskDefinition extends Entity { hasTaskResources: boolean; scormEnabled: boolean; hasScormData: boolean; + scormAllowReview: boolean; scormTimeDelayEnabled: boolean; scormAttemptLimit: number = 0; hasTaskAssessmentResources: boolean; diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index defd83dc77..3776432fd8 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -95,6 +95,7 @@ export class TaskDefinitionService extends CachedEntityService { 'hasTaskAssessmentResources', 'scormEnabled', 'hasScormData', + 'scormAllowReview', 'scormTimeDelayEnabled', 'scormAttemptLimit', 'isGraded', diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html index 6bc386569e..bf75eda5b5 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html @@ -105,7 +105,7 @@

-

Upload SCORM test

+

SCORM test

Upload the corresponding SCORM 2004 test (e.g. Numbas)

diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html index 433405669b..5b3b54c111 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html @@ -3,30 +3,35 @@ Enable test for task -
- - @if (taskDefinition.hasScormData) { -
- - -
- } -
- @if (taskDefinition.scormEnabled) { +
+ + @if (taskDefinition.hasScormData) { +
+ + +
+ } +
+
- - Enable incremental time delays between test attempts - +
+ + Enable incremental time delays between test attempts + + + Allow students to review completed test attempt + +
Attempt limit Date: Tue, 14 May 2024 14:29:48 +1000 Subject: [PATCH 0080/1531] refactor: remove test attempt model and service --- src/app/api/models/test-attempt.ts | 22 ----------- src/app/api/services/test-attempt.service.ts | 40 -------------------- src/app/doubtfire-angular.module.ts | 2 - src/app/doubtfire-angularjs.module.ts | 2 - 4 files changed, 66 deletions(-) delete mode 100644 src/app/api/models/test-attempt.ts delete mode 100644 src/app/api/services/test-attempt.service.ts diff --git a/src/app/api/models/test-attempt.ts b/src/app/api/models/test-attempt.ts deleted file mode 100644 index e6f2e5d61d..0000000000 --- a/src/app/api/models/test-attempt.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Entity } from "ngx-entity-service"; -import { Task } from "./task"; - -export class TestAttempt extends Entity { - public id: number; - name: string; - attemptNumber: number; - passStatus: boolean; - suspendData: string; - completed: boolean; - cmiEntry: string; - examResult: string; - attemptedAt: Date; - taskId: number; - - task: Task; - - constructor(task: Task) { - super(); - this.task = task; - } -} diff --git a/src/app/api/services/test-attempt.service.ts b/src/app/api/services/test-attempt.service.ts deleted file mode 100644 index 094f2baa0c..0000000000 --- a/src/app/api/services/test-attempt.service.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Injectable } from "@angular/core"; -import { EntityService } from "ngx-entity-service"; -import { TestAttempt } from "../models/test-attempt"; -import { HttpClient } from "@angular/common/http"; -import API_URL from "src/app/config/constants/apiURL"; -import { Task } from "../models/task"; -import { Observable } from "rxjs"; -import { AppInjector } from "src/app/app-injector"; -import { DoubtfireConstants } from "src/app/config/constants/doubtfire-constants"; - -@Injectable() -export class TestAttemptService extends EntityService { - protected readonly endpointFormat = '/test_attempts?id=:id:'; - - constructor(httpClient: HttpClient) { - super(httpClient, API_URL); - - this.mapping.addKeys( - 'id', - 'name', - 'attemptNumber', - 'passStatus', - 'suspendData', - 'completed', - 'cmiEntry', - 'examResult', - 'attemptedAt', - 'taskId' - ); - } - - public createInstanceFrom(json: object, other?: any): TestAttempt { - return new TestAttempt(other as Task); - } - - public getLatestCompletedTestAttempt(task: Task): Observable { - const url = `${AppInjector.get(DoubtfireConstants).API_URL}/test_attempts/completed-latest?task_id=${task.id}`; - return AppInjector.get(HttpClient).get(url); - } -} \ No newline at end of file diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 110ae4a3a2..f464c6c13d 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -229,7 +229,6 @@ import {GradeService} from './common/services/grade.service'; import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; import {ScormAdapterService} from './api/services/scorm-adapter.service'; import {ScormCommentComponent} from './tasks/task-comments-viewer/scorm-comment/scorm-comment.component'; -import {TestAttemptService} from './api/services/test-attempt.service'; @NgModule({ // Components we declare @@ -407,7 +406,6 @@ import {TestAttemptService} from './api/services/test-attempt.service'; CreateNewUnitModal, ScormPlayerModalProvider, ScormAdapterService, - TestAttemptService, provideLottieOptions({ player: () => player, }), diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 3cd6555bd8..eb119b464b 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -227,7 +227,6 @@ import {AlertService} from './common/services/alert.service'; import {GradeService} from './common/services/grade.service'; import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; import {ScormPlayerModal} from './common/scorm-player/scorm-player-modal.component'; -import {TestAttemptService} from './api/services/test-attempt.service'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -311,7 +310,6 @@ DoubtfireAngularJSModule.factory( ); DoubtfireAngularJSModule.factory('CreateNewUnitModal', downgradeInjectable(CreateNewUnitModal)); DoubtfireAngularJSModule.factory('ScormPlayerModal', downgradeInjectable(ScormPlayerModal)); -DoubtfireAngularJSModule.factory('testAttemptService', downgradeInjectable(TestAttemptService)); // directive -> component DoubtfireAngularJSModule.directive( From ce53396ab93a98b30a78d9259849262bcec5e9ff Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Wed, 15 May 2024 17:39:20 +1000 Subject: [PATCH 0081/1531] refactor: use task card and new tab for scorm and match comment display --- src/app/ajs-upgraded-providers.ts | 7 --- src/app/api/models/scorm-player-context.ts | 4 +- src/app/api/services/scorm-adapter.service.ts | 20 +++++---- .../scorm-player-modal.component.ts | 22 ---------- .../scorm-player/scorm-player.component.html | 5 +-- .../scorm-player/scorm-player.component.scss | 12 ++---- .../scorm-player/scorm-player.component.ts | 43 +++++++++++-------- src/app/doubtfire-angular.module.ts | 4 +- src/app/doubtfire-angularjs.module.ts | 13 +++--- src/app/doubtfire.states.ts | 30 +++++++++++++ .../task-scorm-card.component.html | 27 ++++++++++++ .../task-scorm-card.component.scss | 0 .../task-scorm-card.component.ts | 31 +++++++++++++ .../task-dashboard/task-dashboard.tpl.html | 1 + .../upload-submission-modal.coffee | 9 +--- .../upload-submission-modal.tpl.html | 20 --------- .../scorm-comment.component.html | 5 ++- .../scorm-comment/scorm-comment.component.ts | 5 +-- 18 files changed, 147 insertions(+), 111 deletions(-) delete mode 100644 src/app/common/scorm-player/scorm-player-modal.component.ts create mode 100644 src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html create mode 100644 src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.scss create mode 100644 src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts diff --git a/src/app/ajs-upgraded-providers.ts b/src/app/ajs-upgraded-providers.ts index f114da1c79..795869225d 100644 --- a/src/app/ajs-upgraded-providers.ts +++ b/src/app/ajs-upgraded-providers.ts @@ -18,7 +18,6 @@ export const rootScope = new InjectionToken('$rootScope'); export const calendarModal = new InjectionToken('CalendarModal'); export const aboutDoubtfireModal = new InjectionToken('AboutDoubtfireModal'); export const plagiarismReportModal = new InjectionToken('PlagiarismReportModal'); -export const scormPlayerModal = new InjectionToken('ScormPlayerModal'); // Define a provider for the above injection token... // It will get the service from AngularJS via the factory @@ -117,9 +116,3 @@ export const UnitStudentEnrolmentModalProvider = { useFactory: (i) => i.get('UnitStudentEnrolmentModal'), deps: ['$injector'], }; - -export const ScormPlayerModalProvider = { - provide: scormPlayerModal, - useFactory: (i) => i.get('ScormPlayerModal'), - deps: ['$injector'], -}; diff --git a/src/app/api/models/scorm-player-context.ts b/src/app/api/models/scorm-player-context.ts index f3b3b8a13f..ed7df07c0a 100644 --- a/src/app/api/models/scorm-player-context.ts +++ b/src/app/api/models/scorm-player-context.ts @@ -1,4 +1,4 @@ -import {Task, User} from 'src/app/api/models/doubtfire-model'; +import {User} from 'src/app/api/models/doubtfire-model'; type DataModelState = 'Uninitialized' | 'Initialized' | 'Terminated'; @@ -48,7 +48,7 @@ export class ScormPlayerContext { return CMIErrorCodes[value]; } - task: Task; + taskId: number; user: User; attemptNumber: number; diff --git a/src/app/api/services/scorm-adapter.service.ts b/src/app/api/services/scorm-adapter.service.ts index 9519f4cc2c..cb6a780952 100644 --- a/src/app/api/services/scorm-adapter.service.ts +++ b/src/app/api/services/scorm-adapter.service.ts @@ -1,7 +1,7 @@ import {Injectable} from '@angular/core'; import {UserService} from './user.service'; import API_URL from 'src/app/config/constants/apiURL'; -import {Task, ScormDataModel, ScormPlayerContext} from 'src/app/api/models/doubtfire-model'; +import {ScormDataModel, ScormPlayerContext} from 'src/app/api/models/doubtfire-model'; @Injectable({ providedIn: 'root', @@ -18,8 +18,12 @@ export class ScormAdapterService { this.xhr = new XMLHttpRequest(); } - set task(task: Task) { - this.context.task = task; + set taskId(taskId: number) { + this.context.taskId = taskId; + } + + set mode(mode: 'browse' | 'normal' | 'review') { + this.context.mode = mode; } get state() { @@ -47,7 +51,7 @@ export class ScormAdapterService { } // TODO: move this part into the player component - this.xhr.open('GET', `${this.apiBaseUrl}/${this.context.task.id}/latest`, false); + this.xhr.open('GET', `${this.apiBaseUrl}/${this.context.taskId}/latest`, false); let noTestFound = false; let startNewTest = false; @@ -80,7 +84,7 @@ export class ScormAdapterService { if (!startNewTest) { this.xhr.open( 'PATCH', - `${this.apiBaseUrl}/${this.context.task.id}/session/${this.context.attemptId}`, + `${this.apiBaseUrl}/${this.context.taskId}/session/${this.context.attemptId}`, false, ); this.xhr.send(); @@ -92,7 +96,7 @@ export class ScormAdapterService { this.dataModel.restore(currentSession.cmi_datamodel); console.log(this.dataModel.dump()); } else { - this.xhr.open('POST', `${this.apiBaseUrl}/${this.context.task.id}/session`, false); + this.xhr.open('POST', `${this.apiBaseUrl}/${this.context.taskId}/session`, false); this.xhr.send(); console.log(this.xhr.responseText); @@ -124,7 +128,7 @@ export class ScormAdapterService { this.xhr.open( 'PATCH', - `${this.apiBaseUrl}/${this.context.task.id}/session/${this.context.attemptId}`, + `${this.apiBaseUrl}/${this.context.taskId}/session/${this.context.attemptId}`, false, ); this.xhr.setRequestHeader('Content-Type', 'application/json'); @@ -200,7 +204,7 @@ export class ScormAdapterService { const xhr = new XMLHttpRequest(); xhr.open( 'PATCH', - `${this.apiBaseUrl}/${this.context.task.id}/session/${this.context.attemptId}`, + `${this.apiBaseUrl}/${this.context.taskId}/session/${this.context.attemptId}`, true, ); xhr.setRequestHeader('Content-Type', 'application/json'); diff --git a/src/app/common/scorm-player/scorm-player-modal.component.ts b/src/app/common/scorm-player/scorm-player-modal.component.ts deleted file mode 100644 index cd7740571c..0000000000 --- a/src/app/common/scorm-player/scorm-player-modal.component.ts +++ /dev/null @@ -1,22 +0,0 @@ -import {Injectable} from '@angular/core'; -import {MatDialog, MatDialogRef} from '@angular/material/dialog'; -import {ScormPlayerComponent} from './scorm-player.component'; -import {Task} from 'src/app/api/models/task'; - -@Injectable({ - providedIn: 'root', -}) -export class ScormPlayerModal { - constructor(public dialog: MatDialog) {} - - public show(task: Task, mode: 'browse' | 'normal' | 'review'): void { - let dialogRef: MatDialogRef; - - dialogRef = this.dialog.open(ScormPlayerComponent, { - data: {task, mode}, - width: '95%', - height: '90%', - disableClose: true, - }); - } -} diff --git a/src/app/common/scorm-player/scorm-player.component.html b/src/app/common/scorm-player/scorm-player.component.html index 5089ad9de3..4855cf4d2b 100644 --- a/src/app/common/scorm-player/scorm-player.component.html +++ b/src/app/common/scorm-player/scorm-player.component.html @@ -1,4 +1 @@ -
- - -
+ diff --git a/src/app/common/scorm-player/scorm-player.component.scss b/src/app/common/scorm-player/scorm-player.component.scss index 5e24cc5d9e..f011d35aee 100644 --- a/src/app/common/scorm-player/scorm-player.component.scss +++ b/src/app/common/scorm-player/scorm-player.component.scss @@ -1,5 +1,7 @@ -.mat-dialog-content { +f-scorm-player { position: relative; + height: 100vh; + width: 100vw; } iframe { @@ -7,11 +9,5 @@ iframe { top: 0; left: 0; width: 100%; - height: 95%; + height: 100%; } - -button { - position: absolute; - bottom: 20px; - right: 20px; -} \ No newline at end of file diff --git a/src/app/common/scorm-player/scorm-player.component.ts b/src/app/common/scorm-player/scorm-player.component.ts index 106e6a8520..e1c68dc872 100644 --- a/src/app/common/scorm-player/scorm-player.component.ts +++ b/src/app/common/scorm-player/scorm-player.component.ts @@ -1,10 +1,10 @@ -import {Component, OnInit, Inject} from '@angular/core'; -import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {Component, OnInit, Input, HostListener} from '@angular/core'; import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser'; -import {Task, ScormPlayerContext} from 'src/app/api/models/doubtfire-model'; +import {ScormPlayerContext} from 'src/app/api/models/doubtfire-model'; import {ScormAdapterService} from 'src/app/api/services/scorm-adapter.service'; import {AppInjector} from 'src/app/app-injector'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; declare global { interface Window { @@ -20,20 +20,29 @@ declare global { export class ScormPlayerComponent implements OnInit { context: ScormPlayerContext; - task: Task; - currentMode: 'browse' | 'normal' | 'review' = 'normal'; + @Input() + taskId: number; + + @Input() + taskDefId: number; + + @Input() + mode: 'browse' | 'normal' | 'review'; + iframeSrc: SafeResourceUrl; constructor( - private dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: {task: Task, mode: 'browse' | 'normal' | 'review'}, + private globalState: GlobalStateService, private scormAdapter: ScormAdapterService, private sanitizer: DomSanitizer, ) {} ngOnInit(): void { - this.task = this.data.task; - this.scormAdapter.task = this.task; + this.globalState.setView(ViewType.OTHER); + this.globalState.hideHeader(); + + this.scormAdapter.taskId = this.taskId; + this.scormAdapter.mode = this.mode; window.API_1484_11 = { Initialize: () => this.scormAdapter.Initialize(), @@ -46,23 +55,21 @@ export class ScormPlayerComponent implements OnInit { GetDiagnostic: (errorCode: string) => this.scormAdapter.GetDiagnostic(errorCode), }; - this.currentMode = this.data.mode; - this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl( - `${AppInjector.get(DoubtfireConstants).API_URL}/scorm/${this.task.taskDefId}/index.html`, + `${AppInjector.get(DoubtfireConstants).API_URL}/scorm/${this.taskDefId}/index.html`, ); } - close(): void { + @HostListener('window:beforeunload', ['$event']) + beforeUnload($event: any): void { if (this.scormAdapter.state == 'Initialized') { console.log('SCORM player closing during an initialized session, commiting DataModel'); this.scormAdapter.Commit(); } - // TODO: would be nice if we can destroy this entire adapter object when the modal is closed - console.log('Clearing player context and DataModel'); + } + + @HostListener('window:unload', ['$event']) + onUnload($event: any): void { this.scormAdapter.destroy(); - const iframe = document.getElementsByTagName('iframe')[0]; - iframe?.parentNode?.removeChild(iframe); - this.dialogRef.close(); } } diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index f464c6c13d..dabcd49145 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -72,7 +72,6 @@ import { gradeTaskModalProvider, uploadSubmissionModalProvider, ConfirmationModalProvider, - ScormPlayerModalProvider, } from './ajs-upgraded-providers'; import { TaskCommentComposerComponent, @@ -229,6 +228,7 @@ import {GradeService} from './common/services/grade.service'; import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; import {ScormAdapterService} from './api/services/scorm-adapter.service'; import {ScormCommentComponent} from './tasks/task-comments-viewer/scorm-comment/scorm-comment.component'; +import {TaskScormCardComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component'; @NgModule({ // Components we declare @@ -333,6 +333,7 @@ import {ScormCommentComponent} from './tasks/task-comments-viewer/scorm-comment/ FUnitsComponent, ScormPlayerComponent, ScormCommentComponent, + TaskScormCardComponent, ], // Services we provide providers: [ @@ -404,7 +405,6 @@ import {ScormCommentComponent} from './tasks/task-comments-viewer/scorm-comment/ TasksForInboxSearchPipe, IsActiveUnitRole, CreateNewUnitModal, - ScormPlayerModalProvider, ScormAdapterService, provideLottieOptions({ player: () => player, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index eb119b464b..bc5ad5ed4a 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -225,8 +225,7 @@ import {FUnitsComponent} from './admin/states/f-units/f-units.component'; import {MarkedPipe} from './common/pipes/marked.pipe'; import {AlertService} from './common/services/alert.service'; import {GradeService} from './common/services/grade.service'; -import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; -import {ScormPlayerModal} from './common/scorm-player/scorm-player-modal.component'; +import {TaskScormCardComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -309,7 +308,6 @@ DoubtfireAngularJSModule.factory( downgradeInjectable(EditProfileDialogService), ); DoubtfireAngularJSModule.factory('CreateNewUnitModal', downgradeInjectable(CreateNewUnitModal)); -DoubtfireAngularJSModule.factory('ScormPlayerModal', downgradeInjectable(ScormPlayerModal)); // directive -> component DoubtfireAngularJSModule.directive( @@ -367,6 +365,10 @@ DoubtfireAngularJSModule.directive( 'activityTypeList', downgradeComponent({component: ActivityTypeListComponent}), ); +DoubtfireAngularJSModule.directive( + 'fTaskScormCard', + downgradeComponent({component: TaskScormCardComponent}), +); DoubtfireAngularJSModule.directive( 'fTaskStatusCard', downgradeComponent({component: TaskStatusCardComponent}), @@ -444,11 +446,6 @@ DoubtfireAngularJSModule.directive( ); DoubtfireAngularJSModule.directive('fUnits', downgradeComponent({component: FUnitsComponent})); -DoubtfireAngularJSModule.directive( - 'fScormPlayerComponent', - downgradeComponent({component: ScormPlayerComponent}), -); - // Global configuration DoubtfireAngularJSModule.directive( 'taskCommentsViewer', diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index b9f95e88af..23b60886d6 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -8,6 +8,7 @@ import {TeachingPeriodListComponent} from './admin/states/teaching-periods/teach import {AcceptEulaComponent} from './eula/accept-eula/accept-eula.component'; import {FUsersComponent} from './admin/states/f-users/f-users.component'; import {FUnitsComponent} from './admin/states/f-units/f-units.component'; +import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; /* * Use this file to store any states that are sourced by angular components. @@ -291,6 +292,34 @@ const ViewAllUnits: NgHybridStateDeclaration = { }, }; +/** + * Define the SCORM Player state. + */ +const ScormPlayerState: NgHybridStateDeclaration = { + name: 'scorm-player', + url: '/task_def/:task_def_id/task/:task_id/scorm-player/:mode', + resolve: { + taskId: function ($stateParams) { + return $stateParams.task_id; + }, + taskDefId: function ($stateParams) { + return $stateParams.task_def_id; + }, + mode: function ($stateParams) { + return $stateParams.mode; + }, + }, + views: { + main: { + component: ScormPlayerComponent, + }, + }, + data: { + pageTitle: 'Knowledge Check', + roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin'], + }, +}; + /** * Export the list of states we have created in angular */ @@ -306,4 +335,5 @@ export const doubtfireStates = [ ViewAllProjectsState, ViewAllUnits, AdministerUnits, + ScormPlayerState, ]; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html new file mode 100644 index 0000000000..67265461cd --- /dev/null +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html @@ -0,0 +1,27 @@ + + + Knowledge Check + + +

+ You have to successfully pass this knowledge check to complete the task. +

+

+ You have {{ (task.definition.scormAttemptLimit > 0) ? task.definition.scormAttemptLimit : 'unlimited' }} attempts to complete this test. +

+

+ There will be an increased time delay between test attempts. First 2 attempts will not have a time delay in between. +

+
+ + + + +
diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.scss b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts new file mode 100644 index 0000000000..7d7dce6e1b --- /dev/null +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts @@ -0,0 +1,31 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {Task} from 'src/app/api/models/task'; +import {TaskService} from 'src/app/api/services/task.service'; + +@Component({ + selector: 'f-task-scorm-card', + templateUrl: './task-scorm-card.component.html', + styleUrls: ['./task-scorm-card.component.scss'], +}) +export class TaskScormCardComponent implements OnInit { + @Input() task: Task; + attemptsLeft: number; + + constructor( + private taskService: TaskService, + ) {} + + ngOnInit(): void { + if (this.task) { + + } + } + + launchScormPlayer(): void { + window.open(`#/task_def/${this.task.taskDefId}/task/${this.task.id}/scorm-player/normal`, '_blank'); + } + + requestMoreAttempts(): void { + + } +} diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html index 0962ddd82a..8402f4252c 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html @@ -42,6 +42,7 @@
+ diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee index 976c116f33..b9c9ebd2b9 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee @@ -32,7 +32,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) UploadSubmissionModal ) -.controller('UploadSubmissionModalCtrl', ($scope, $rootScope, $timeout, $modalInstance, ScormPlayerModal, newTaskService, newProjectService, task, reuploadEvidence, outcomeService, PrivacyPolicy) -> +.controller('UploadSubmissionModalCtrl', ($scope, $rootScope, $timeout, $modalInstance, newTaskService, newProjectService, task, reuploadEvidence, outcomeService, PrivacyPolicy) -> $scope.privacyPolicy = PrivacyPolicy # Expose task to scope $scope.task = task @@ -100,7 +100,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) # States functionality states = { # All possible states - all: ['group', 'scorm-assessment', 'files', 'alignment', 'comments', 'uploading'] + all: ['group', 'files', 'alignment', 'comments', 'uploading'] # Only states which are shown (populated in initialise) shown: [] # The currently active state (set in initialise) @@ -128,7 +128,6 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) removed.push('group') if !isRFF || !task.isGroupTask() removed.push('alignment') if !isRFF || !task.unit.ilos.length > 0 removed.push('comments') if isTestSubmission - removed.push('scorm-assessment') if !isRFF || !task.definition.scormEnabled removed # Initialises the states initialise: -> @@ -155,10 +154,6 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) previous: states.previous } - $scope.launchScormPlayer = -> - console.clear() - ScormPlayerModal.show $scope.task, 'normal' - # Whether or not we should disable this button $scope.shouldDisableBtn = { next: -> diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html index 0b296c2099..9caab7897e 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html @@ -43,26 +43,6 @@

-
-
-
-

- Attempt SCORM Test -

- - Complete the SCORM test first to proceed to upload evidence of your task completion. - -
-
- -
-
-
diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html index b74db43a07..ffe375f19d 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html @@ -1,9 +1,10 @@
-
+
- + +

diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts index 817a6cd64f..b584629668 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts @@ -1,6 +1,5 @@ import {Component, OnInit, Input} from '@angular/core'; import {Task, TaskComment} from 'src/app/api/models/doubtfire-model'; -import {ScormPlayerModal} from 'src/app/common/scorm-player/scorm-player-modal.component'; @Component({ selector: 'scorm-comment', @@ -11,11 +10,11 @@ export class ScormCommentComponent implements OnInit { @Input() task: Task; @Input() comment: TaskComment; - constructor(private modalService: ScormPlayerModal) {} + constructor() {} ngOnInit() {} reviewScormTest() { - this.modalService.show(this.task, 'review'); + window.open(`#/task_def/${this.task.taskDefId}/task/${this.task.id}/scorm-player/review`, '_blank'); } } From c022c925bc8b569a416c24696b54580248413001 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Sat, 1 Jun 2024 20:14:54 +1000 Subject: [PATCH 0082/1531] refactor: change url params for test attempts --- src/app/api/models/scorm-player-context.ts | 3 +- src/app/api/services/scorm-adapter.service.ts | 39 +++++++++---------- .../scorm-player/scorm-player.component.ts | 5 ++- src/app/doubtfire.states.ts | 8 ++-- .../task-scorm-card.component.ts | 5 ++- .../scorm-comment/scorm-comment.component.ts | 5 ++- 6 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/app/api/models/scorm-player-context.ts b/src/app/api/models/scorm-player-context.ts index ed7df07c0a..c065957ac0 100644 --- a/src/app/api/models/scorm-player-context.ts +++ b/src/app/api/models/scorm-player-context.ts @@ -48,7 +48,8 @@ export class ScormPlayerContext { return CMIErrorCodes[value]; } - taskId: number; + projectId: number; + taskDefId: number; user: User; attemptNumber: number; diff --git a/src/app/api/services/scorm-adapter.service.ts b/src/app/api/services/scorm-adapter.service.ts index cb6a780952..233c7aed6a 100644 --- a/src/app/api/services/scorm-adapter.service.ts +++ b/src/app/api/services/scorm-adapter.service.ts @@ -7,7 +7,6 @@ import {ScormDataModel, ScormPlayerContext} from 'src/app/api/models/doubtfire-m providedIn: 'root', }) export class ScormAdapterService { - private readonly apiBaseUrl = `${API_URL}/test_attempts`; private dataModel: ScormDataModel; private context: ScormPlayerContext; private xhr: XMLHttpRequest; @@ -18,8 +17,12 @@ export class ScormAdapterService { this.xhr = new XMLHttpRequest(); } - set taskId(taskId: number) { - this.context.taskId = taskId; + set projectId(projectId: number) { + this.context.projectId = projectId; + } + + set taskDefId(taskDefId: number) { + this.context.taskDefId = taskDefId; } set mode(mode: 'browse' | 'normal' | 'review') { @@ -51,7 +54,11 @@ export class ScormAdapterService { } // TODO: move this part into the player component - this.xhr.open('GET', `${this.apiBaseUrl}/${this.context.taskId}/latest`, false); + this.xhr.open( + 'GET', + `${API_URL}/projects/${this.context.projectId}/task_def_id/${this.context.taskDefId}/test_attempts/latest`, + false, + ); let noTestFound = false; let startNewTest = false; @@ -82,11 +89,7 @@ export class ScormAdapterService { } if (!startNewTest) { - this.xhr.open( - 'PATCH', - `${this.apiBaseUrl}/${this.context.taskId}/session/${this.context.attemptId}`, - false, - ); + this.xhr.open('PATCH', `${API_URL}/test_attempts/${this.context.attemptId}`, false); this.xhr.send(); console.log(this.xhr.responseText); @@ -96,7 +99,11 @@ export class ScormAdapterService { this.dataModel.restore(currentSession.cmi_datamodel); console.log(this.dataModel.dump()); } else { - this.xhr.open('POST', `${this.apiBaseUrl}/${this.context.taskId}/session`, false); + this.xhr.open( + 'POST', + `${API_URL}/projects/${this.context.projectId}/task_def_id/${this.context.taskDefId}/test_attempts`, + false, + ); this.xhr.send(); console.log(this.xhr.responseText); @@ -126,11 +133,7 @@ export class ScormAdapterService { break; } - this.xhr.open( - 'PATCH', - `${this.apiBaseUrl}/${this.context.taskId}/session/${this.context.attemptId}`, - false, - ); + this.xhr.open('PATCH', `${API_URL}/test_attempts/${this.context.attemptId}`, false); this.xhr.setRequestHeader('Content-Type', 'application/json'); const requestData = { cmi_datamodel: JSON.stringify(this.dataModel.dump()), @@ -202,11 +205,7 @@ export class ScormAdapterService { } const xhr = new XMLHttpRequest(); - xhr.open( - 'PATCH', - `${this.apiBaseUrl}/${this.context.taskId}/session/${this.context.attemptId}`, - true, - ); + xhr.open('PATCH', `${API_URL}/test_attempts/${this.context.attemptId}`, true); xhr.setRequestHeader('Content-Type', 'application/json'); const requestData = { cmi_datamodel: JSON.stringify(this.dataModel.dump()), diff --git a/src/app/common/scorm-player/scorm-player.component.ts b/src/app/common/scorm-player/scorm-player.component.ts index e1c68dc872..9c2ee9edb4 100644 --- a/src/app/common/scorm-player/scorm-player.component.ts +++ b/src/app/common/scorm-player/scorm-player.component.ts @@ -21,7 +21,7 @@ export class ScormPlayerComponent implements OnInit { context: ScormPlayerContext; @Input() - taskId: number; + projectId: number; @Input() taskDefId: number; @@ -41,7 +41,8 @@ export class ScormPlayerComponent implements OnInit { this.globalState.setView(ViewType.OTHER); this.globalState.hideHeader(); - this.scormAdapter.taskId = this.taskId; + this.scormAdapter.projectId = this.projectId; + this.scormAdapter.taskDefId = this.taskDefId; this.scormAdapter.mode = this.mode; window.API_1484_11 = { diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index 23b60886d6..8f48cd06fd 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -297,13 +297,13 @@ const ViewAllUnits: NgHybridStateDeclaration = { */ const ScormPlayerState: NgHybridStateDeclaration = { name: 'scorm-player', - url: '/task_def/:task_def_id/task/:task_id/scorm-player/:mode', + url: '/projects/:project_id/task_def_id/:task_definition_id/scorm-player/:mode', resolve: { - taskId: function ($stateParams) { - return $stateParams.task_id; + projectId: function ($stateParams) { + return $stateParams.project_id; }, taskDefId: function ($stateParams) { - return $stateParams.task_def_id; + return $stateParams.task_definition_id; }, mode: function ($stateParams) { return $stateParams.mode; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts index 7d7dce6e1b..8172bcf1ff 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts @@ -22,7 +22,10 @@ export class TaskScormCardComponent implements OnInit { } launchScormPlayer(): void { - window.open(`#/task_def/${this.task.taskDefId}/task/${this.task.id}/scorm-player/normal`, '_blank'); + window.open( + `#/projects/${this.task.project.id}/task_def_id/${this.task.taskDefId}/scorm-player/normal`, + '_blank', + ); } requestMoreAttempts(): void { diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts index b584629668..b16184a042 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts @@ -15,6 +15,9 @@ export class ScormCommentComponent implements OnInit { ngOnInit() {} reviewScormTest() { - window.open(`#/task_def/${this.task.taskDefId}/task/${this.task.id}/scorm-player/review`, '_blank'); + window.open( + `#/projects/${this.task.project.id}/task_def_id/${this.task.taskDefId}/scorm-player/review`, + '_blank', + ); } } From 561b9241c2f44fd69d3f09c656a025f514bbaf3a Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Sun, 2 Jun 2024 02:20:03 +1000 Subject: [PATCH 0083/1531] feat: enable reviewing, passing, deleting test attempts and add test attempt model and service --- src/app/api/models/doubtfire-model.ts | 3 + .../api/models/task-comment/scorm-comment.ts | 9 ++ src/app/api/models/test-attempt.ts | 20 ++++ src/app/api/services/scorm-adapter.service.ts | 29 +++++ src/app/api/services/task-comment.service.ts | 22 +++- src/app/api/services/test-attempt.service.ts | 103 ++++++++++++++++++ .../scorm-player/scorm-player.component.ts | 11 +- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire.states.ts | 38 ++++++- .../scorm-comment.component.html | 11 +- .../scorm-comment/scorm-comment.component.ts | 29 ++++- .../task-comments-viewer.component.html | 4 +- 12 files changed, 259 insertions(+), 22 deletions(-) create mode 100644 src/app/api/models/task-comment/scorm-comment.ts create mode 100644 src/app/api/models/test-attempt.ts create mode 100644 src/app/api/services/test-attempt.service.ts diff --git a/src/app/api/models/doubtfire-model.ts b/src/app/api/models/doubtfire-model.ts index baca2f22d2..d6e4230f6e 100644 --- a/src/app/api/models/doubtfire-model.ts +++ b/src/app/api/models/doubtfire-model.ts @@ -34,6 +34,8 @@ export * from './task-similarity'; export * from './tii-action'; export * from './scorm-datamodel'; export * from './scorm-player-context'; +export * from './test-attempt'; +export * from './task-comment/scorm-comment'; // Users -- are students or staff export * from './user/user'; @@ -58,3 +60,4 @@ export * from '../services/teaching-period-break.service'; export * from '../services/learning-outcome.service'; export * from '../services/group-set.service'; export * from '../services/task-similarity.service'; +export * from '../services/test-attempt.service'; diff --git a/src/app/api/models/task-comment/scorm-comment.ts b/src/app/api/models/task-comment/scorm-comment.ts new file mode 100644 index 0000000000..3356b62b93 --- /dev/null +++ b/src/app/api/models/task-comment/scorm-comment.ts @@ -0,0 +1,9 @@ +import {Task, TaskComment, TestAttempt} from '../doubtfire-model'; + +export class ScormComment extends TaskComment { + testAttempt: TestAttempt; + + constructor(task: Task) { + super(task); + } +} diff --git a/src/app/api/models/test-attempt.ts b/src/app/api/models/test-attempt.ts new file mode 100644 index 0000000000..02bb4bb4e9 --- /dev/null +++ b/src/app/api/models/test-attempt.ts @@ -0,0 +1,20 @@ +import {Entity} from 'ngx-entity-service'; +import {Task} from './doubtfire-model'; + +export class TestAttempt extends Entity { + id: number; + attemptNumber: number; + terminated: boolean; + completionStatus: boolean; + successStatus: boolean; + scoreScaled: number; + cmiDatamodel: string; + attemptedTime: Date; + + task: Task; + + constructor(task: Task) { + super(); + this.task = task; + } +} diff --git a/src/app/api/services/scorm-adapter.service.ts b/src/app/api/services/scorm-adapter.service.ts index 233c7aed6a..b6014f14b4 100644 --- a/src/app/api/services/scorm-adapter.service.ts +++ b/src/app/api/services/scorm-adapter.service.ts @@ -29,6 +29,10 @@ export class ScormAdapterService { this.context.mode = mode; } + set testAttemptId(testAttemptId: number) { + this.context.attemptId = testAttemptId; + } + get state() { return this.context.state; } @@ -53,6 +57,31 @@ export class ScormAdapterService { break; } + if (this.context.mode === 'review') { + this.xhr.open('GET', `${API_URL}/test_attempts/${this.context.attemptId}/review`, false); + + this.xhr.onload = () => { + if (this.xhr.status >= 200 && this.xhr.status < 400) { + console.log('Retrieved the attempt.'); + } else if (this.xhr.status == 404) { + console.log('Not found.'); + noTestFound = true; + } else { + console.error('Error saving DataModel:', this.xhr.responseText); + } + }; + + this.xhr.send(); + console.log(this.xhr.responseText); + + const reviewSession = JSON.parse(this.xhr.responseText); + this.dataModel.restore(reviewSession.cmi_datamodel); + console.log(this.dataModel.dump()); + + this.context.state = 'Initialized'; + return 'true'; + } + // TODO: move this part into the player component this.xhr.open( 'GET', diff --git a/src/app/api/services/task-comment.service.ts b/src/app/api/services/task-comment.service.ts index 5f034b870d..c97ec4c3e0 100644 --- a/src/app/api/services/task-comment.service.ts +++ b/src/app/api/services/task-comment.service.ts @@ -1,4 +1,4 @@ -import { Task, TaskComment, UserService } from 'src/app/api/models/doubtfire-model'; +import { ScormComment, Task, TaskComment, TestAttemptService, UserService } from 'src/app/api/models/doubtfire-model'; import { EventEmitter, Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @@ -32,7 +32,8 @@ export class TaskCommentService extends CachedEntityService { httpClient: HttpClient, private emojiService: EmojiService, private userService: UserService, - private downloader: FileDownloaderService + private downloader: FileDownloaderService, + private testAttemptService: TestAttemptService, ) { super(httpClient, API_URL); @@ -85,7 +86,20 @@ export class TaskCommentService extends CachedEntityService { 'status', 'numberOfPrompts', 'timeDiscussionComplete', - 'timeDiscussionStarted' + 'timeDiscussionStarted', + + // Scorm Comments + { + keys: 'testAttempt', + toEntityFn: (data: object, key: string, comment: ScormComment) => { + const testAttempt = this.testAttemptService.cache.getOrCreate( + data[key].id, + testAttemptService, + data[key], + ); + return testAttempt; + }, + }, ); this.mapping.addJsonKey( @@ -103,6 +117,8 @@ export class TaskCommentService extends CachedEntityService { return new DiscussionComment(other); case 'extension': return new ExtensionComment(other); + case 'scorm': + return new ScormComment(other); default: return new TaskComment(other); } diff --git a/src/app/api/services/test-attempt.service.ts b/src/app/api/services/test-attempt.service.ts new file mode 100644 index 0000000000..7a7ac25ca2 --- /dev/null +++ b/src/app/api/services/test-attempt.service.ts @@ -0,0 +1,103 @@ +import {Injectable} from '@angular/core'; +import {CachedEntityService} from 'ngx-entity-service'; +import API_URL from 'src/app/config/constants/apiURL'; +import {Task, TestAttempt} from 'src/app/api/models/doubtfire-model'; +import {Observable} from 'rxjs'; +import {AppInjector} from 'src/app/app-injector'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {HttpClient} from '@angular/common/http'; + +@Injectable() +export class TestAttemptService extends CachedEntityService { + protected readonly endpointFormat = 'test_attempts/:id:'; + protected readonly forTaskEndpoint = + '/projects/:project_id:/task_definition_id/:task_def_id:/test_attempts'; + protected readonly latestCompletedEndpoint = + this.forTaskEndpoint + '/latest?completed=:completed:'; + + constructor(httpClient: HttpClient) { + super(httpClient, API_URL); + + this.mapping.addKeys( + 'id', + 'attemptNumber', + 'terminated', + 'completionStatus', + 'successStatus', + 'scoreScaled', + 'cmiDatamodel', + 'attemptedTime', + ); + } + + public override createInstanceFrom(_json: object, constructorParams: Task): TestAttempt { + return new TestAttempt(constructorParams); + } + + public getAttemptsForTask(task: Task): Observable { + return this.query( + { + project_id: task.project.id, + task_def_id: task.taskDefId, + }, + { + endpointFormat: this.forTaskEndpoint, + constructorParams: task, + }, + ); + } + + public getLatestCompletedAttempt(task: Task): Observable { + return this.get( + { + project_id: task.project.id, + task_def_id: task.taskDefId, + completed: true, + }, + { + endpointFormat: this.latestCompletedEndpoint, + constructorParams: task, + }, + ); + } + + public overrideSuccessStatus(testAttemptId: number, successStatus: boolean): void { + const http = AppInjector.get(HttpClient); + + http + .patch( + `${AppInjector.get(DoubtfireConstants).API_URL}/test_attempts/${testAttemptId}?success_status=${successStatus}`, + {}, + ) + .subscribe({ + next: (_data) => { + (AppInjector.get(AlertService) as AlertService).success( + 'Attempt pass status successfully overridden.', + 6000, + ); + }, + error: (message) => { + (AppInjector.get(AlertService) as AlertService).error(message, 6000); + }, + }); + } + + public deleteAttempt(testAttemptId: number): void { + const http = AppInjector.get(HttpClient); + + http + .delete(`${AppInjector.get(DoubtfireConstants).API_URL}/test_attempts/${testAttemptId}`, {}) + .subscribe({ + next: (_data) => { + (AppInjector.get(AlertService) as AlertService).success( + 'Attempt successfully deleted.', + 6000, + ); + }, + error: (message) => { + (AppInjector.get(AlertService) as AlertService).error(message, 6000); + }, + }); + } +} diff --git a/src/app/common/scorm-player/scorm-player.component.ts b/src/app/common/scorm-player/scorm-player.component.ts index 9c2ee9edb4..4a32eb0ac7 100644 --- a/src/app/common/scorm-player/scorm-player.component.ts +++ b/src/app/common/scorm-player/scorm-player.component.ts @@ -29,6 +29,9 @@ export class ScormPlayerComponent implements OnInit { @Input() mode: 'browse' | 'normal' | 'review'; + @Input() + testAttemptId: number; + iframeSrc: SafeResourceUrl; constructor( @@ -41,9 +44,13 @@ export class ScormPlayerComponent implements OnInit { this.globalState.setView(ViewType.OTHER); this.globalState.hideHeader(); - this.scormAdapter.projectId = this.projectId; - this.scormAdapter.taskDefId = this.taskDefId; this.scormAdapter.mode = this.mode; + if (this.mode === 'normal') { + this.scormAdapter.projectId = this.projectId; + this.scormAdapter.taskDefId = this.taskDefId; + } else if (this.mode === 'review') { + this.scormAdapter.testAttemptId = this.testAttemptId; + } window.API_1484_11 = { Initialize: () => this.scormAdapter.Initialize(), diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index dabcd49145..5f6e91e775 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -229,6 +229,7 @@ import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component import {ScormAdapterService} from './api/services/scorm-adapter.service'; import {ScormCommentComponent} from './tasks/task-comments-viewer/scorm-comment/scorm-comment.component'; import {TaskScormCardComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component'; +import {TestAttemptService} from './api/services/test-attempt.service'; @NgModule({ // Components we declare @@ -406,6 +407,7 @@ import {TaskScormCardComponent} from './projects/states/dashboard/directives/tas IsActiveUnitRole, CreateNewUnitModal, ScormAdapterService, + TestAttemptService, provideLottieOptions({ player: () => player, }), diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index 8f48cd06fd..0338a550a9 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -295,9 +295,9 @@ const ViewAllUnits: NgHybridStateDeclaration = { /** * Define the SCORM Player state. */ -const ScormPlayerState: NgHybridStateDeclaration = { - name: 'scorm-player', - url: '/projects/:project_id/task_def_id/:task_definition_id/scorm-player/:mode', +const ScormPlayerNormalState: NgHybridStateDeclaration = { + name: 'scorm-player-normal', + url: '/projects/:project_id/task_def_id/:task_definition_id/scorm-player/normal', resolve: { projectId: function ($stateParams) { return $stateParams.project_id; @@ -305,8 +305,8 @@ const ScormPlayerState: NgHybridStateDeclaration = { taskDefId: function ($stateParams) { return $stateParams.task_definition_id; }, - mode: function ($stateParams) { - return $stateParams.mode; + mode: function () { + return 'normal'; }, }, views: { @@ -320,6 +320,31 @@ const ScormPlayerState: NgHybridStateDeclaration = { }, }; +const ScormPlayerReviewState: NgHybridStateDeclaration = { + name: 'scorm-player-review', + url: '/task_def_id/:task_definition_id/scorm-player/review/:test_attempt_id', + resolve: { + taskDefId: function ($stateParams) { + return $stateParams.task_definition_id; + }, + testAttemptId: function ($stateParams) { + return $stateParams.test_attempt_id; + }, + mode: function () { + return 'review'; + }, + }, + views: { + main: { + component: ScormPlayerComponent, + }, + }, + data: { + pageTitle: 'Review Knowledge Check', + roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin'], + }, +}; + /** * Export the list of states we have created in angular */ @@ -335,5 +360,6 @@ export const doubtfireStates = [ ViewAllProjectsState, ViewAllUnits, AdministerUnits, - ScormPlayerState, + ScormPlayerNormalState, + ScormPlayerReviewState, ]; diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html index ffe375f19d..b0536d2ce6 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html @@ -1,10 +1,13 @@ -
-
+
+

- -
+
+ + + +

diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts index b16184a042..201e35544a 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts @@ -1,23 +1,42 @@ import {Component, OnInit, Input} from '@angular/core'; -import {Task, TaskComment} from 'src/app/api/models/doubtfire-model'; +import {Task, ScormComment, User, UserService, TestAttemptService} from 'src/app/api/models/doubtfire-model'; @Component({ - selector: 'scorm-comment', + selector: 'f-scorm-comment', templateUrl: './scorm-comment.component.html', styleUrls: ['./scorm-comment.component.scss'], }) export class ScormCommentComponent implements OnInit { @Input() task: Task; - @Input() comment: TaskComment; + @Input() comment: ScormComment; - constructor() {} + user: User; + + constructor( + private userService: UserService, + private testAttemptService: TestAttemptService, + ) { + this.user = this.userService.currentUser; + } ngOnInit() {} + get canOverridePass(): boolean { + return this.user.isStaff && !this.comment.testAttempt.successStatus; + } + reviewScormTest() { window.open( - `#/projects/${this.task.project.id}/task_def_id/${this.task.taskDefId}/scorm-player/review`, + `#/task_def_id/${this.task.taskDefId}/scorm-player/review/${this.comment.testAttempt.id}`, '_blank', ); } + + passScormAttempt() { + this.testAttemptService.overrideSuccessStatus(this.comment.testAttempt.id, true); + } + + deleteScormAttempt() { + this.testAttemptService.deleteAttempt(this.comment.testAttempt.id); + } } diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html index aa20275ff6..f6228c576a 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html @@ -73,11 +73,11 @@
- + >
From e605a3cfb56f8979b6e8d3ddf16dab7a8d253c03 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Sun, 2 Jun 2024 21:00:31 +1000 Subject: [PATCH 0084/1531] refactor: use new alert service for scorm editor --- .../task-definition-scorm.component.ts | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts index 8f2b72fcb9..3e41aa39d2 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts @@ -1,10 +1,10 @@ -import { Component, Inject, Input } from '@angular/core'; -import { FormControl, Validators } from '@angular/forms'; -import { alertService } from 'src/app/ajs-upgraded-providers'; -import { TaskDefinition } from 'src/app/api/models/task-definition'; -import { Unit } from 'src/app/api/models/unit'; -import { TaskDefinitionService } from 'src/app/api/services/task-definition.service'; -import { FileDownloaderService } from 'src/app/common/file-downloader/file-downloader.service'; +import {Component, Input} from '@angular/core'; +import {FormControl, Validators} from '@angular/forms'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {Unit} from 'src/app/api/models/unit'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; @Component({ selector: 'f-task-definition-scorm', @@ -16,8 +16,8 @@ export class TaskDefinitionScormComponent { constructor( private fileDownloaderService: FileDownloaderService, - @Inject(alertService) private alerts: any, - private taskDefinitionService: TaskDefinitionService + private alerts: AlertService, + private taskDefinitionService: TaskDefinitionService, ) {} public attemptLimitControl = new FormControl('', [Validators.max(100), Validators.min(0)]); @@ -41,9 +41,11 @@ export class TaskDefinitionScormComponent { } public uploadScormData(files: FileList) { - console.log(Array.from(files).map(f => f.type)); + console.log(Array.from(files).map((f) => f.type)); const validMimeTypes = ['application/zip', 'application/x-zip-compressed', 'multipart/x-zip']; - const validFiles = Array.from(files as ArrayLike).filter(f => validMimeTypes.includes(f.type)); + const validFiles = Array.from(files as ArrayLike).filter((f) => + validMimeTypes.includes(f.type), + ); if (validFiles.length > 0) { const file = validFiles[0]; this.taskDefinitionService.uploadScormData(this.taskDefinition, file).subscribe({ From 58c24c3a6760af168a918bc099e755f475eac5f0 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Mon, 3 Jun 2024 00:24:20 +1000 Subject: [PATCH 0085/1531] fix: show correct attempts left and allow tutor to review attempt always --- src/app/api/models/task.ts | 20 +++++++++++++ src/app/api/services/test-attempt.service.ts | 20 ++----------- .../task-scorm-card.component.html | 18 ++++++----- .../task-scorm-card.component.ts | 30 +++++++++++-------- .../scorm-comment.component.html | 18 ++++++++--- 5 files changed, 65 insertions(+), 41 deletions(-) diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index 556d0a7dd2..86ac445fc2 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -15,6 +15,8 @@ import { TaskCommentService, TaskSimilarity, TaskSimilarityService, + TestAttempt, + TestAttemptService, } from './doubtfire-model'; import {Grade} from './grade'; import {LOCALE_ID} from '@angular/core'; @@ -53,6 +55,7 @@ export class Task extends Entity { public readonly commentCache: EntityCache = new EntityCache(); public readonly similarityCache: EntityCache = new EntityCache(); + public readonly testAttemptCache: EntityCache = new EntityCache(); private _unit: Unit; @@ -770,4 +773,21 @@ export class Task extends Entity { }, ); } + + /** + * Fetch the SCORM test attempts for this task. + */ + public fetchTestAttempts(): Observable { + const testAttemptService: TestAttemptService = AppInjector.get(TestAttemptService); + return testAttemptService.query( + { + project_id: this.project.id, + task_def_id: this.taskDefId, + }, + { + cache: this.testAttemptCache, + constructorParams: this, + }, + ); + } } diff --git a/src/app/api/services/test-attempt.service.ts b/src/app/api/services/test-attempt.service.ts index 7a7ac25ca2..6c32ed01a8 100644 --- a/src/app/api/services/test-attempt.service.ts +++ b/src/app/api/services/test-attempt.service.ts @@ -10,11 +10,10 @@ import {HttpClient} from '@angular/common/http'; @Injectable() export class TestAttemptService extends CachedEntityService { - protected readonly endpointFormat = 'test_attempts/:id:'; - protected readonly forTaskEndpoint = - '/projects/:project_id:/task_definition_id/:task_def_id:/test_attempts'; + protected readonly endpointFormat = + '/projects/:project_id:/task_def_id/:task_def_id:/test_attempts'; protected readonly latestCompletedEndpoint = - this.forTaskEndpoint + '/latest?completed=:completed:'; + this.endpointFormat + '/latest?completed=:completed:'; constructor(httpClient: HttpClient) { super(httpClient, API_URL); @@ -35,19 +34,6 @@ export class TestAttemptService extends CachedEntityService { return new TestAttempt(constructorParams); } - public getAttemptsForTask(task: Task): Observable { - return this.query( - { - project_id: task.project.id, - task_def_id: task.taskDefId, - }, - { - endpointFormat: this.forTaskEndpoint, - constructorParams: task, - }, - ); - } - public getLatestCompletedAttempt(task: Task): Observable { return this.get( { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html index 67265461cd..9d518fb1c4 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html @@ -3,24 +3,28 @@ Knowledge Check +

You have to successfully pass this knowledge check to complete the task.

- You have to successfully pass this knowledge check to complete the task. -

-

- You have {{ (task.definition.scormAttemptLimit > 0) ? task.definition.scormAttemptLimit : 'unlimited' }} attempts to complete this test. + You have {{ attemptsLeft !== undefined ? attemptsLeft : 'unlimited' }} attempts left to + complete this test.

- There will be an increased time delay between test attempts. First 2 attempts will not have a time delay in between. + There will be an increased time delay between test attempts. First 2 attempts will not have a + time delay in between.

- - diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts index 8172bcf1ff..cdeb73df0e 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts @@ -1,23 +1,29 @@ -import {Component, Input, OnInit} from '@angular/core'; -import {Task} from 'src/app/api/models/task'; -import {TaskService} from 'src/app/api/services/task.service'; +import {Component, Input, OnChanges, SimpleChanges} from '@angular/core'; +import {Task} from 'src/app/api/models/doubtfire-model'; @Component({ selector: 'f-task-scorm-card', templateUrl: './task-scorm-card.component.html', styleUrls: ['./task-scorm-card.component.scss'], }) -export class TaskScormCardComponent implements OnInit { +export class TaskScormCardComponent implements OnChanges { @Input() task: Task; attemptsLeft: number; - constructor( - private taskService: TaskService, - ) {} - - ngOnInit(): void { - if (this.task) { + ngOnChanges(changes: SimpleChanges) { + if (changes.task && changes.task.currentValue) { + this.attemptsLeft = undefined; + this.getAttemptsLeft(); + } + } + getAttemptsLeft(): void { + if (this.task.definition.scormAttemptLimit != 0) { + this.task.fetchTestAttempts().subscribe((attempts) => { + let count = attempts.length; + if (count > 0 && attempts[0].terminated === false) count--; + this.attemptsLeft = this.task.definition.scormAttemptLimit - count; + }); } } @@ -28,7 +34,5 @@ export class TaskScormCardComponent implements OnInit { ); } - requestMoreAttempts(): void { - - } + requestMoreAttempts(): void {} } diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html index b0536d2ce6..c1dacaa788 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html @@ -2,11 +2,21 @@

-
+
- - - + + +

From d904ffd6fd674f6e61894d517f5aa147d1db6d29 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Wed, 5 Jun 2024 15:17:47 +1000 Subject: [PATCH 0086/1531] feat: enable students to request extra scorm attempt --- src/app/api/models/doubtfire-model.ts | 1 + .../task-comment/scorm-extension-comment.ts | 38 +++++++++++ src/app/api/models/task.ts | 1 + src/app/api/services/task-comment.service.ts | 43 ++++++++++++ src/app/api/services/task.service.ts | 1 + .../scorm-extension-modal.component.html | 45 +++++++++++++ .../scorm-extension-modal.component.ts | 67 +++++++++++++++++++ .../scorm-extension-modal.service.ts | 26 +++++++ src/app/doubtfire-angular.module.ts | 4 ++ .../task-scorm-card.component.html | 6 +- .../task-scorm-card.component.ts | 11 ++- .../scorm-extension-comment.component.html | 32 +++++++++ .../scorm-extension-comment.component.scss | 55 +++++++++++++++ .../scorm-extension-comment.component.ts | 63 +++++++++++++++++ .../task-comments-viewer.component.html | 5 ++ .../task-comments-viewer.component.scss | 4 +- .../task-comments-viewer.component.ts | 8 ++- 17 files changed, 402 insertions(+), 8 deletions(-) create mode 100644 src/app/api/models/task-comment/scorm-extension-comment.ts create mode 100644 src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.html create mode 100644 src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.ts create mode 100644 src/app/common/modals/scorm-extension-modal/scorm-extension-modal.service.ts create mode 100644 src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html create mode 100644 src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.scss create mode 100644 src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts diff --git a/src/app/api/models/doubtfire-model.ts b/src/app/api/models/doubtfire-model.ts index d6e4230f6e..fffc361a4e 100644 --- a/src/app/api/models/doubtfire-model.ts +++ b/src/app/api/models/doubtfire-model.ts @@ -36,6 +36,7 @@ export * from './scorm-datamodel'; export * from './scorm-player-context'; export * from './test-attempt'; export * from './task-comment/scorm-comment'; +export * from './task-comment/scorm-extension-comment'; // Users -- are students or staff export * from './user/user'; diff --git a/src/app/api/models/task-comment/scorm-extension-comment.ts b/src/app/api/models/task-comment/scorm-extension-comment.ts new file mode 100644 index 0000000000..3b4dfbccb6 --- /dev/null +++ b/src/app/api/models/task-comment/scorm-extension-comment.ts @@ -0,0 +1,38 @@ +import {Observable} from 'rxjs'; +import {tap} from 'rxjs/operators'; +import {AppInjector} from 'src/app/app-injector'; +import {TaskCommentService} from '../../services/task-comment.service'; +import {TaskComment, Task} from '../doubtfire-model'; + +export class ScormExtensionComment extends TaskComment { + assessed: boolean; + granted: boolean; + dateAssessed: Date; + taskScormExtensions: number; + + constructor(task: Task) { + super(task); + } + + private assessScormExtension(): Observable { + const tcs: TaskCommentService = AppInjector.get(TaskCommentService); + return tcs.assessScormExtension(this).pipe( + tap((tc: TaskComment) => { + const scormExtension: ScormExtensionComment = tc as ScormExtensionComment; + + const task = tc.task; + task.scormExtensions = scormExtension.taskScormExtensions; + }), + ); + } + + public deny(): Observable { + this.granted = false; + return this.assessScormExtension(); + } + + public grant(): Observable { + this.granted = true; + return this.assessScormExtension(); + } +} diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index 86ac445fc2..ba4bce8e04 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -32,6 +32,7 @@ export class Task extends Entity { status: TaskStatusEnum = 'not_started'; dueDate: Date; extensions: number; + scormExtensions: number; submissionDate: Date; completionDate: Date; timesAssessed: number; diff --git a/src/app/api/services/task-comment.service.ts b/src/app/api/services/task-comment.service.ts index c97ec4c3e0..e7f76d37b1 100644 --- a/src/app/api/services/task-comment.service.ts +++ b/src/app/api/services/task-comment.service.ts @@ -11,6 +11,7 @@ import API_URL from 'src/app/config/constants/apiURL'; import { EmojiService } from 'src/app/common/services/emoji.service'; import { MappingFunctions } from './mapping-fn'; import { FileDownloaderService } from 'src/app/common/file-downloader/file-downloader.service'; +import { ScormExtensionComment } from '../models/task-comment/scorm-extension-comment'; @Injectable() export class TaskCommentService extends CachedEntityService { @@ -22,6 +23,10 @@ export class TaskCommentService extends CachedEntityService { 'projects/:projectId:/task_def_id/:taskDefinitionId:/assess_extension/:id:'; private readonly requestExtensionEndpointFormat = 'projects/:projectId:/task_def_id/:taskDefinitionId:/request_extension'; + private readonly scormExtensionGrantEndpointFormat = + 'projects/:projectId:/task_def_id/:taskDefinitionId:/assess_scorm_extension/:id:'; + private readonly scormRequestExtensionEndpointFormat = + 'projects/:projectId:/task_def_id/:taskDefinitionId:/request_scorm_extension'; private readonly discussionCommentReplyEndpointFormat = "/projects/:project_id:/task_def_id/:task_definition_id:/comments/:task_comment_id:/discussion_comment/reply"; private readonly getDiscussionCommentPromptEndpointFormat = "/projects/:project_id:/task_def_id/:task_definition_id:/comments/:task_comment_id:/discussion_comment/prompt_number/:prompt_number:"; @@ -100,6 +105,9 @@ export class TaskCommentService extends CachedEntityService { return testAttempt; }, }, + + // Scorm Extension Comments + ['taskScormExtensions', 'scorm_extensions'] ); this.mapping.addJsonKey( @@ -119,6 +127,8 @@ export class TaskCommentService extends CachedEntityService { return new ExtensionComment(other); case 'scorm': return new ScormComment(other); + case 'scorm_extension': + return new ScormExtensionComment(other); default: return new TaskComment(other); } @@ -218,6 +228,39 @@ export class TaskCommentService extends CachedEntityService { ); } + public assessScormExtension(extension: ScormExtensionComment): Observable { + const opts: RequestOptions = { + endpointFormat: this.scormExtensionGrantEndpointFormat, + entity: extension, + }; + + return super.update( + { + id: extension.id, + projectId: extension.project.id, + taskDefinitionId: extension.task.definition.id, + }, + opts, + ); + } + + public requestScormExtension(reason: string, task: any): Observable { + const opts: RequestOptions = { + endpointFormat: this.scormRequestExtensionEndpointFormat, + body: { + comment: reason, + }, + cache: task.commentCache, + }; + return super.create( + { + projectId: task.project.id, + taskDefinitionId: task.definition.id, + }, + opts, + ); + } + public postDiscussionReply(comment: TaskComment, replyAudio: Blob): Observable{ const form = new FormData(); const pathIds = { diff --git a/src/app/api/services/task.service.ts b/src/app/api/services/task.service.ts index 344494c0eb..737fe1ea4c 100644 --- a/src/app/api/services/task.service.ts +++ b/src/app/api/services/task.service.ts @@ -46,6 +46,7 @@ export class TaskService extends CachedEntityService { toEntityFn: MappingFunctions.mapDateToEndOfDay, }, 'extensions', + 'scormExtensions', { keys: 'submissionDate', toEntityFn: MappingFunctions.mapDateToDay, diff --git a/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.html b/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.html new file mode 100644 index 0000000000..f39a9580b5 --- /dev/null +++ b/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.html @@ -0,0 +1,45 @@ +

Extra attempt request

+
+

+ Please explain why you require an extra attempt for this knowledge check, the teaching team will + assess the request shortly. +

+ + + Reason + + {{ extensionData.controls.extensionReason.value.length }} / {{ reasonMaxLength }} + @if (extensionData.controls.extensionReason.hasError('required')) { + You must enter a reason + } + @if (extensionData.controls.extensionReason.hasError('minlength')) { + The reason must be at least {{ reasonMinLength }} characters long + } + @if (extensionData.controls.extensionReason.hasError('maxlength')) { + The reason must be less than {{ reasonMaxLength }} characters long + } + +
+ +
+ + +
diff --git a/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.ts b/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.ts new file mode 100644 index 0000000000..c7f5833821 --- /dev/null +++ b/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.ts @@ -0,0 +1,67 @@ +import {Component, Inject, LOCALE_ID} from '@angular/core'; +import {MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; +import {TaskComment, TaskCommentService, Task} from 'src/app/api/models/doubtfire-model'; +import {AppInjector} from 'src/app/app-injector'; +import {FormControl, Validators, FormGroup, FormGroupDirective, NgForm} from '@angular/forms'; +import {ErrorStateMatcher} from '@angular/material/core'; +import {AlertService} from '../../services/alert.service'; + +/** Error when invalid control is dirty, touched, or submitted. */ +export class ReasonErrorStateMatcher implements ErrorStateMatcher { + isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { + const isSubmitted = form && form.submitted; + return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted)); + } +} + +@Component({ + selector: 'f-scorm-extension-modal', + templateUrl: './scorm-extension-modal.component.html', +}) +export class ScormExtensionModalComponent { + protected reasonMinLength: number = 15; + protected reasonMaxLength: number = 256; + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: {task: Task; afterApplication?: () => void}, + private alerts: AlertService, + ) {} + + matcher = new ReasonErrorStateMatcher(); + currentLocale = AppInjector.get(LOCALE_ID); + extensionData = new FormGroup({ + extensionReason: new FormControl('', [ + Validators.required, + Validators.minLength(this.reasonMinLength), + Validators.maxLength(this.reasonMaxLength), + ]), + }); + + private scrollCommentsDown(): void { + setTimeout(() => { + const objDiv = document.querySelector('div.comments-body'); + // let wrappedResult = angular.element(objDiv); + objDiv.scrollTop = objDiv.scrollHeight; + }, 50); + } + + submitApplication() { + const tcs: TaskCommentService = AppInjector.get(TaskCommentService); + tcs + .requestScormExtension(this.extensionData.controls.extensionReason.value, this.data.task) + .subscribe({ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + next: ((tc: TaskComment) => { + this.alerts.success('Extra attempt requested.', 2000); + this.scrollCommentsDown(); + if (typeof this.data.afterApplication === 'function') { + this.data.afterApplication(); + } + }).bind(this), + error: ((response: never) => { + this.alerts.error('Error requesting extra attempt ' + response); + console.log(response); + }).bind(this), + }); + } +} diff --git a/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.service.ts b/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.service.ts new file mode 100644 index 0000000000..7e9b46f8e9 --- /dev/null +++ b/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.service.ts @@ -0,0 +1,26 @@ +import {Injectable} from '@angular/core'; +import {Task} from 'src/app/api/models/task'; +import {MatDialogRef, MatDialog} from '@angular/material/dialog'; +import {ScormExtensionModalComponent} from './scorm-extension-modal.component'; + +@Injectable({ + providedIn: 'root', +}) +export class ScormExtensionModalService { + constructor(public dialog: MatDialog) {} + + public show(task: Task, afterApplication?: any) { + let dialogRef: MatDialogRef; + + dialogRef = this.dialog.open(ScormExtensionModalComponent, { + data: { + task, + afterApplication, + }, + }); + + dialogRef.afterOpened().subscribe((result: any) => {}); + + dialogRef.afterClosed().subscribe((result: any) => {}); + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 5f6e91e775..67e3c3f1dd 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -230,6 +230,8 @@ import {ScormAdapterService} from './api/services/scorm-adapter.service'; import {ScormCommentComponent} from './tasks/task-comments-viewer/scorm-comment/scorm-comment.component'; import {TaskScormCardComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component'; import {TestAttemptService} from './api/services/test-attempt.service'; +import {ScormExtensionCommentComponent} from './tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component'; +import {ScormExtensionModalComponent} from './common/modals/scorm-extension-modal/scorm-extension-modal.component'; @NgModule({ // Components we declare @@ -335,6 +337,8 @@ import {TestAttemptService} from './api/services/test-attempt.service'; ScormPlayerComponent, ScormCommentComponent, TaskScormCardComponent, + ScormExtensionCommentComponent, + ScormExtensionModalComponent, ], // Services we provide providers: [ diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html index 9d518fb1c4..1929afb248 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html @@ -22,10 +22,10 @@ diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts index cdeb73df0e..2713c9ee33 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts @@ -1,5 +1,6 @@ import {Component, Input, OnChanges, SimpleChanges} from '@angular/core'; import {Task} from 'src/app/api/models/doubtfire-model'; +import {ScormExtensionModalService} from 'src/app/common/modals/scorm-extension-modal/scorm-extension-modal.service'; @Component({ selector: 'f-task-scorm-card', @@ -10,6 +11,8 @@ export class TaskScormCardComponent implements OnChanges { @Input() task: Task; attemptsLeft: number; + constructor(private extensions: ScormExtensionModalService) {} + ngOnChanges(changes: SimpleChanges) { if (changes.task && changes.task.currentValue) { this.attemptsLeft = undefined; @@ -22,7 +25,7 @@ export class TaskScormCardComponent implements OnChanges { this.task.fetchTestAttempts().subscribe((attempts) => { let count = attempts.length; if (count > 0 && attempts[0].terminated === false) count--; - this.attemptsLeft = this.task.definition.scormAttemptLimit - count; + this.attemptsLeft = this.task.definition.scormAttemptLimit + this.task.scormExtensions - count; }); } } @@ -34,5 +37,9 @@ export class TaskScormCardComponent implements OnChanges { ); } - requestMoreAttempts(): void {} + requestExtraAttempt(): void { + this.extensions.show(this.task, () => { + this.task.refresh(); + }); + } } diff --git a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html new file mode 100644 index 0000000000..fa7c4cb39f --- /dev/null +++ b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html @@ -0,0 +1,32 @@ +
+ @if (comment.assessed) { +
+
+

reason: {{ comment.text }}

+
+ } + + @if (!comment.assessed) { +
+
+

+ {{ message }}
+ reason: {{ comment.text }} +

+ @if (isNotStudent) { +
+ + +
+ } +
+
+ } +
diff --git a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.scss b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.scss new file mode 100644 index 0000000000..c2917f902e --- /dev/null +++ b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.scss @@ -0,0 +1,55 @@ +div { + width: 100%; +} + +p { + color: #2c2c2c; + text-align: center; +} + +hr { + width: 100%; +} + +.hr-fade { + background: linear-gradient(to right, transparent, #9696969d, transparent); + width: 100%; +} + +.fade-text { + color: #9696969d; + opacity: 0.8; +} + +.hr-text { + margin: 0; + line-height: 1em; + position: relative; + outline: 0; + border: 0; + color: black; + text-align: center; + height: 1.5em; + opacity: 0.8; + &:before { + content: ""; + background: linear-gradient(to right, transparent, #9696969d, transparent); + position: absolute; + left: 0; + top: 50%; + width: 100%; + height: 1px; + } + &:after { + content: attr(data-content); + position: relative; + display: inline-block; + color: black; + + padding: 0 0.5em; + line-height: 1.5em; + + color: #9696969d; + background-color: #fff; + } +} diff --git a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts new file mode 100644 index 0000000000..eb1790edd4 --- /dev/null +++ b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts @@ -0,0 +1,63 @@ +import {Component, OnInit, Input} from '@angular/core'; +import {ScormExtensionComment, TaskComment, Task} from 'src/app/api/models/doubtfire-model'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-scorm-extension-comment', + templateUrl: './scorm-extension-comment.component.html', + styleUrls: ['./scorm-extension-comment.component.scss'], +}) +export class ScormExtensionCommentComponent implements OnInit { + @Input() comment: ScormExtensionComment; + @Input() task: Task; + + constructor(private alerts: AlertService) {} + + private handleError(error: any) { + this.alerts.error('Error: ' + error.data.error, 6000); + } + + ngOnInit() {} + + get message() { + const studentName = this.comment.author.name; + if (this.comment.assessed && this.comment.granted) { + return 'Extra attempt granted.'; + } else if (this.comment.assessed && !this.comment.granted) { + return 'Extra attempt request rejected.'; + } + const subject = this.isStudent ? 'You have ' : studentName + ' has '; + const message = 'requested an extra attempt for the knowledge check.'; + return subject + message; + } + + get isStudent() { + return !this.isNotStudent; + } + + get isNotStudent() { + return this.task.unit.currentUserIsStaff; + } + + denyExtension() { + this.comment.deny().subscribe({ + next: (tc: TaskComment) => { + this.alerts.success('Attempt request denied', 2000); + }, + error: (response) => { + this.handleError(response); + }, + }); + } + + grantExtension() { + this.comment.grant().subscribe({ + next: (tc: TaskComment) => { + this.alerts.success('Attempt request granted', 2000); + }, + error: (response) => { + this.handleError(response); + }, + }); + } +} diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html index f6228c576a..81b09e6011 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html @@ -95,6 +95,11 @@
+
+ + +
+
diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.scss b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.scss index d82983038f..a1b4811941 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.scss +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.scss @@ -140,7 +140,7 @@ $comment-inner-border-radius: 4px; } } - .comment-container .comment-extension { + .comment-container .comment-extension, .comment-container .comment-scorm-extension { width: 100%; } @@ -354,7 +354,7 @@ $comment-inner-border-radius: 4px; } } - .comment .extension-bubble { + .comment .extension-bubble, .comment .scorm_extension-bubble { width: 100%; background-color: transparent; } diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts index 8ad719f339..857f4581f2 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts @@ -154,7 +154,13 @@ export class TaskCommentsViewerComponent implements OnChanges, OnInit { } shouldShowAuthorIcon(commentType: string) { - return !(commentType === 'extension' || commentType === 'status' || commentType == 'assessment' || commentType == 'scorm'); + return !( + commentType === 'extension' || + commentType === 'status' || + commentType == 'assessment' || + commentType === 'scorm' || + commentType === 'scorm_extension' + ); } commentClasses(comment: TaskComment): object { From e92aac4b701035c286916eae230d9342a8f4b538 Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Wed, 5 Jun 2024 17:15:02 +1000 Subject: [PATCH 0087/1531] build: upgrade packages --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 61ba8cb15a..ed19972737 100644 --- a/package.json +++ b/package.json @@ -157,4 +157,4 @@ "@nx/nx-linux-x64-gnu": "^18.0", "@nx/nx-win32-x64-msvc": "^18.0" } -} +} \ No newline at end of file From a869e7cdc00569e5101784b7d16954d0a0398a2d Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Wed, 5 Jun 2024 19:40:45 +1000 Subject: [PATCH 0088/1531] refactor: (refactor) resolve data from route --- .../root-controller/root-controller.coffee | 2 +- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 2 +- src/app/doubtfire.states.ts | 28 +++++++-- src/app/home/states/home/home.component.html | 2 +- src/app/home/states/home/home.component.ts | 4 +- .../project-dashboard.component.html | 9 ++- .../project-dashboard.component.ts | 17 ++---- src/app/projects/states/index/index.coffee | 6 +- .../task-definition-upload.component.html | 59 +++++++++++-------- src/app/units/states/edit/edit.coffee | 6 +- src/app/units/states/index/index.coffee | 8 +-- src/app/units/states/rollover/rollover.coffee | 8 +-- 13 files changed, 90 insertions(+), 63 deletions(-) diff --git a/src/app/config/root-controller/root-controller.coffee b/src/app/config/root-controller/root-controller.coffee index 4a9854fc0e..5502b2ae0e 100644 --- a/src/app/config/root-controller/root-controller.coffee +++ b/src/app/config/root-controller/root-controller.coffee @@ -3,6 +3,6 @@ angular.module('doubtfire.config.root-controller', []) # # The Doubtfire root application controller # -.controller("AppCtrl", (GlobalStateService) -> +.controller("AppCtrl", (globalStateService) -> ) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index d2d55fa723..f5601f7d25 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -173,6 +173,7 @@ import {UnitDropdownComponent} from './common/header/unit-dropdown/unit-dropdown import {TaskDropdownComponent} from './common/header/task-dropdown/task-dropdown.component'; import {SplashScreenComponent} from './home/splash-screen/splash-screen.component'; import {HttpErrorInterceptor} from './common/services/http-error.interceptor'; +import {ProjectDashboardComponent} from './projects/states/dashboard/project-dashboard/project-dashboard.component'; import {TaskDefinitionService} from './api/services/task-definition.service'; import {NewTeachingPeriodDialogComponent} from './admin/states/teaching-periods/teaching-period-list/teaching-period-list.component'; import {MatNativeDateModule} from '@angular/material/core'; @@ -299,6 +300,7 @@ import {TasksViewerComponent} from './units/states/tasks/tasks-viewer/tasks-view UnitDropdownComponent, TaskDropdownComponent, SplashScreenComponent, + ProjectDashboardComponent, ObjectSelectComponent, WelcomeComponent, AcceptEulaComponent, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index c102584ead..c6395115fd 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -297,7 +297,7 @@ DoubtfireAngularJSModule.factory( downgradeInjectable(TaskAssessmentModalService), ); DoubtfireAngularJSModule.factory('TaskSubmission', downgradeInjectable(TaskSubmissionService)); -DoubtfireAngularJSModule.factory('GlobalStateService', downgradeInjectable(GlobalStateService)); +DoubtfireAngularJSModule.factory('globalStateService', downgradeInjectable(GlobalStateService)); DoubtfireAngularJSModule.factory( 'TransitionHooksService', downgradeInjectable(TransitionHooksService), diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index df6102cec7..4f5b7779c3 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -11,6 +11,9 @@ import {FUnitsComponent} from './admin/states/f-units/f-units.component'; import {ProjectDashboardComponent} from './projects/states/dashboard/project-dashboard/project-dashboard.component'; import {AppInjector} from './app-injector'; import {ProjectService} from './api/services/project.service'; +import {Observable, first} from 'rxjs'; +import {GlobalStateService} from './projects/states/index/global-state.service'; +import {Project} from './api/models/project'; /* * Use this file to store any states that are sourced by angular components. @@ -277,13 +280,28 @@ const AbstractProjectState: NgHybridStateDeclaration = { name: 'projects2', url: '/projects2/:projectId', abstract: true, - // views: { - // }, + views: { + main: { + component: ProjectDashboardComponent, + }, + }, resolve: { - project: function ($stateParams) { - console.log('Getting project'); + project$: function ($stateParams) { const projectService = AppInjector.get(ProjectService); - return projectService.get({id: $stateParams.project_id}); + const globalState = AppInjector.get(GlobalStateService); + + return new Observable((observer) => { + globalState.onLoad(() => { + projectService + .get({id: $stateParams.projectId}, {cacheBehaviourOnGet: 'cacheQuery'}) + .subscribe({ + next: (project: Project) => { + observer.next(project); + observer.complete(); + }, + }); + }); + }).pipe(first()); }, }, }; diff --git a/src/app/home/states/home/home.component.html b/src/app/home/states/home/home.component.html index 43504ef9dd..034ed2791a 100644 --- a/src/app/home/states/home/home.component.html +++ b/src/app/home/states/home/home.component.html @@ -89,7 +89,7 @@

Enrolled units

diff --git a/src/app/home/states/home/home.component.ts b/src/app/home/states/home/home.component.ts index 614ef65299..b2cf5f9068 100644 --- a/src/app/home/states/home/home.component.ts +++ b/src/app/home/states/home/home.component.ts @@ -46,8 +46,8 @@ export class HomeComponent implements OnInit, OnDestroy { } ngOnInit(): void { - const last = this.router.stateRegistry.get()[this.router.stateRegistry.get().length - 1]; - this.router.stateService.go(last, {projectId: 55}); + // const last = this.router.stateRegistry.get()[this.router.stateRegistry.get().length - 1]; + // this.router.stateService.go(last, {projectId: 55}); if (this.userService.isAnonymousUser()) { this.router.stateService.go('sign_in'); } diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html index db6d335866..1fd9060d63 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html @@ -1,6 +1,11 @@ -
+
- + {{ project.activeTasks() | json }} + @if (subs$ | async) {
; subs$: Observable; @@ -34,7 +28,6 @@ export class ProjectDashboardComponent implements OnInit { private projectService: ProjectService, private globalStateService: GlobalStateService, ) { - console.log('test'); } startedDragging(event: CdkDragStart, div: HTMLDivElement) { @@ -54,8 +47,10 @@ export class ProjectDashboardComponent implements OnInit { } ngOnInit(): void { - console.log('test'); // projectTasks = this.projectService.loadProject + this.project$.subscribe((project) => { + console.log(project); + }); this.dragMoveAudited$ = this.dragMove$.pipe( withLatestFrom(this.leftComponentStartSize$), diff --git a/src/app/projects/states/index/index.coffee b/src/app/projects/states/index/index.coffee index f48cf9c356..fedb8d7608 100644 --- a/src/app/projects/states/index/index.coffee +++ b/src/app/projects/states/index/index.coffee @@ -17,12 +17,12 @@ angular.module('doubtfire.projects.states.index', []) } ) -.controller("ProjectsIndexStateCtrl", ($scope, $rootScope, $state, $stateParams, newProjectService, listenerService, GlobalStateService) -> +.controller("ProjectsIndexStateCtrl", ($scope, $rootScope, $state, $stateParams, newProjectService, listenerService, globalStateService) -> # Error - required projectId is missing! projectId = +$stateParams.projectId return $state.go('home') unless projectId - GlobalStateService.onLoad () -> + globalStateService.onLoad () -> # Load in project newProjectService.get(projectId, { # Ensure that we cache queries here... so that we get any projects we are in @@ -39,7 +39,7 @@ angular.module('doubtfire.projects.states.index', []) $scope.project = project $scope.unit = project.unit if project.unit.taskDefinitions.length > 0 && project.tasks.length == project.unit.taskDefinitions.length - GlobalStateService.setView('PROJECT', $scope.project) + globalStateService.setView('PROJECT', $scope.project) # Go home if no project was found return $state.go('home') unless project? diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html index fe96cfb2df..d53ee750f9 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html @@ -26,11 +26,11 @@ Check Similarity @if (upreq.type === 'document') { -TurnItIn -} + TurnItIn + } @if (upreq.type === 'code') { -Moss -} + Moss + } @@ -39,11 +39,11 @@ Flag At @if (upreq.type === 'document' && upreq.tiiCheck) { - - -  % - -} + + +  % + + } @@ -51,7 +51,12 @@ - @@ -63,7 +68,9 @@ - + @@ -75,19 +82,19 @@ @if (taskDefinition.needsMoss) { -
- - Language used for Moss checks - - C - C# - C++ - Python - - - - Similarity percent to flag for Moss checks - - -
+
+ + Language used for Moss checks + + C + C# + C++ + Python + + + + Similarity percent to flag for Moss checks + + +
} diff --git a/src/app/units/states/edit/edit.coffee b/src/app/units/states/edit/edit.coffee index a8a9eec6d3..5b4f368a14 100644 --- a/src/app/units/states/edit/edit.coffee +++ b/src/app/units/states/edit/edit.coffee @@ -17,11 +17,11 @@ angular.module('doubtfire.units.states.edit', [ roleWhitelist: ['Convenor', 'Admin'] } ) -.controller('EditUnitStateCtrl', ($scope, $state, $stateParams, alertService, analyticsService, newUnitService, newUserService, GlobalStateService) -> - GlobalStateService.onLoad () -> +.controller('EditUnitStateCtrl', ($scope, $state, $stateParams, alertService, analyticsService, newUnitService, newUserService, globalStateService) -> + globalStateService.onLoad () -> $scope.currentStaff = $scope.unit.staff - $scope.assessingUnitRole = GlobalStateService.loadedUnitRoles.currentValues.find((role) -> role.unit == $scope.unit) + $scope.assessingUnitRole = globalStateService.loadedUnitRoles.currentValues.find((role) -> role.unit == $scope.unit) newUserService.getTutors().subscribe( (tutors) -> $scope.staff = tutors ) diff --git a/src/app/units/states/index/index.coffee b/src/app/units/states/index/index.coffee index cd9322d791..3c0298be1c 100644 --- a/src/app/units/states/index/index.coffee +++ b/src/app/units/states/index/index.coffee @@ -17,14 +17,14 @@ angular.module('doubtfire.units.states.index', []) } ) -.controller("UnitsIndexStateCtrl", ($scope, $rootScope, $state, $stateParams, newUnitService, newProjectService, listenerService, GlobalStateService, newUserService, alertService) -> +.controller("UnitsIndexStateCtrl", ($scope, $rootScope, $state, $stateParams, newUnitService, newProjectService, listenerService, globalStateService, newUserService, alertService) -> # Error - required unitId is missing! unitId = +$stateParams.unitId return $state.go('home') unless unitId - GlobalStateService.onLoad () -> + globalStateService.onLoad () -> # Load assessing unit role - $scope.unitRole = GlobalStateService.loadedUnitRoles.currentValues.find((unitRole) -> unitRole.unit.id == unitId) + $scope.unitRole = globalStateService.loadedUnitRoles.currentValues.find((unitRole) -> unitRole.unit.id == unitId) if (! $scope.unitRole?) && ( newUserService.currentUser.role == "Admin" ) $scope.unitRole = newUserService.adminRoleFor(unitId, newUserService.currentUser) @@ -32,7 +32,7 @@ angular.module('doubtfire.units.states.index', []) # Go home if no unit role was found return $state.go('home') unless $scope.unitRole? - GlobalStateService.setView("UNIT", $scope.unitRole) + globalStateService.setView("UNIT", $scope.unitRole) newUnitService.get(unitId).subscribe({ next: (unit)-> diff --git a/src/app/units/states/rollover/rollover.coffee b/src/app/units/states/rollover/rollover.coffee index 97b958fd94..b951e166dc 100644 --- a/src/app/units/states/rollover/rollover.coffee +++ b/src/app/units/states/rollover/rollover.coffee @@ -14,13 +14,13 @@ angular.module('doubtfire.units.states.rollover', [ roleWhitelist: ['Convenor', 'Admin'] } ) -.controller("RolloverUnitState", ($scope, $state, $stateParams, newUnitService, GlobalStateService) -> +.controller("RolloverUnitState", ($scope, $state, $stateParams, newUnitService, globalStateService) -> unitId = +$stateParams.unitId return $state.go('home') unless unitId - GlobalStateService.onLoad () -> + globalStateService.onLoad () -> # Load assessing unit role - $scope.unitRole = GlobalStateService.loadedUnitRoles.currentValues.find((unitRole) -> unitRole.unit.id == unitId) + $scope.unitRole = globalStateService.loadedUnitRoles.currentValues.find((unitRole) -> unitRole.unit.id == unitId) if (! $scope.unitRole?) && ( newUserService.currentUser.role == "Admin" ) $scope.unitRole = newUserService.adminRoleFor(unitId, newUserService.currentUser) @@ -28,7 +28,7 @@ angular.module('doubtfire.units.states.rollover', [ # Go home if no unit role was found return $state.go('home') unless $scope.unitRole? - GlobalStateService.setView("UNIT", $scope.unitRole) + globalStateService.setView("UNIT", $scope.unitRole) newUnitService.get(unitId).subscribe({ next: (unit)-> $scope.unit = unit From 97e1ea187b769a51ebb66b82d76f21193bb29386 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Wed, 5 Jun 2024 23:15:15 +1000 Subject: [PATCH 0089/1531] fix: add auth headers to scorm adapter xhr requests --- src/app/api/services/scorm-adapter.service.ts | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/app/api/services/scorm-adapter.service.ts b/src/app/api/services/scorm-adapter.service.ts index b6014f14b4..085d41610b 100644 --- a/src/app/api/services/scorm-adapter.service.ts +++ b/src/app/api/services/scorm-adapter.service.ts @@ -59,6 +59,8 @@ export class ScormAdapterService { if (this.context.mode === 'review') { this.xhr.open('GET', `${API_URL}/test_attempts/${this.context.attemptId}/review`, false); + this.xhr.setRequestHeader('Auth-Token', this.context.user.authenticationToken); + this.xhr.setRequestHeader('Username', this.context.user.username); this.xhr.onload = () => { if (this.xhr.status >= 200 && this.xhr.status < 400) { @@ -88,6 +90,8 @@ export class ScormAdapterService { `${API_URL}/projects/${this.context.projectId}/task_def_id/${this.context.taskDefId}/test_attempts/latest`, false, ); + this.xhr.setRequestHeader('Auth-Token', this.context.user.authenticationToken); + this.xhr.setRequestHeader('Username', this.context.user.username); let noTestFound = false; let startNewTest = false; @@ -119,6 +123,8 @@ export class ScormAdapterService { if (!startNewTest) { this.xhr.open('PATCH', `${API_URL}/test_attempts/${this.context.attemptId}`, false); + this.xhr.setRequestHeader('Auth-Token', this.context.user.authenticationToken); + this.xhr.setRequestHeader('Username', this.context.user.username); this.xhr.send(); console.log(this.xhr.responseText); @@ -133,6 +139,8 @@ export class ScormAdapterService { `${API_URL}/projects/${this.context.projectId}/task_def_id/${this.context.taskDefId}/test_attempts`, false, ); + this.xhr.setRequestHeader('Auth-Token', this.context.user.authenticationToken); + this.xhr.setRequestHeader('Username', this.context.user.username); this.xhr.send(); console.log(this.xhr.responseText); @@ -163,6 +171,8 @@ export class ScormAdapterService { } this.xhr.open('PATCH', `${API_URL}/test_attempts/${this.context.attemptId}`, false); + this.xhr.setRequestHeader('Auth-Token', this.context.user.authenticationToken); + this.xhr.setRequestHeader('Username', this.context.user.username); this.xhr.setRequestHeader('Content-Type', 'application/json'); const requestData = { cmi_datamodel: JSON.stringify(this.dataModel.dump()), @@ -233,26 +243,28 @@ export class ScormAdapterService { break; } - const xhr = new XMLHttpRequest(); - xhr.open('PATCH', `${API_URL}/test_attempts/${this.context.attemptId}`, true); - xhr.setRequestHeader('Content-Type', 'application/json'); + this.xhr.open('PATCH', `${API_URL}/test_attempts/${this.context.attemptId}`, true); + this.xhr.setRequestHeader('Auth-Token', this.context.user.authenticationToken); + this.xhr.setRequestHeader('Username', this.context.user.username); + this.xhr.setRequestHeader('Content-Type', 'application/json'); const requestData = { cmi_datamodel: JSON.stringify(this.dataModel.dump()), }; - xhr.send(JSON.stringify(requestData)); + - xhr.onload = () => { - if (xhr.status >= 200 && xhr.status < 400) { + this.xhr.onload = () => { + if (this.xhr.status >= 200 && this.xhr.status < 400) { console.log('DataModel saved successfully.'); } else { - console.error('Error saving DataModel:', xhr.responseText); + console.error('Error saving DataModel:', this.xhr.responseText); } }; - xhr.onerror = () => { + this.xhr.onerror = () => { console.error('Request failed.'); }; + this.xhr.send(JSON.stringify(requestData)); this.context.errorCode = 0; return 'true'; } From f0ff40bfd7e86b904adae94bf8cbe5d56371e011 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Wed, 5 Jun 2024 23:42:14 +1000 Subject: [PATCH 0090/1531] fix: remove attempt number field --- src/app/api/models/scorm-player-context.ts | 1 - src/app/api/models/test-attempt.ts | 1 - src/app/api/services/test-attempt.service.ts | 1 - 3 files changed, 3 deletions(-) diff --git a/src/app/api/models/scorm-player-context.ts b/src/app/api/models/scorm-player-context.ts index c065957ac0..195bc3cd4c 100644 --- a/src/app/api/models/scorm-player-context.ts +++ b/src/app/api/models/scorm-player-context.ts @@ -52,7 +52,6 @@ export class ScormPlayerContext { taskDefId: number; user: User; - attemptNumber: number; attemptId: number; learnerName: string; learnerId: number; diff --git a/src/app/api/models/test-attempt.ts b/src/app/api/models/test-attempt.ts index 02bb4bb4e9..646b9ed64f 100644 --- a/src/app/api/models/test-attempt.ts +++ b/src/app/api/models/test-attempt.ts @@ -3,7 +3,6 @@ import {Task} from './doubtfire-model'; export class TestAttempt extends Entity { id: number; - attemptNumber: number; terminated: boolean; completionStatus: boolean; successStatus: boolean; diff --git a/src/app/api/services/test-attempt.service.ts b/src/app/api/services/test-attempt.service.ts index 6c32ed01a8..df5654855f 100644 --- a/src/app/api/services/test-attempt.service.ts +++ b/src/app/api/services/test-attempt.service.ts @@ -20,7 +20,6 @@ export class TestAttemptService extends CachedEntityService { this.mapping.addKeys( 'id', - 'attemptNumber', 'terminated', 'completionStatus', 'successStatus', From 90853e93c109430669e3f80e4324649cd2d0dba6 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Thu, 6 Jun 2024 13:54:39 +1000 Subject: [PATCH 0091/1531] fix: link task list to definitions for project dashboard --- .../project-dashboard/project-dashboard.component.html | 6 ++++-- .../tasks/tasks-viewer/tasks-viewer.component.html | 4 ++-- .../f-unit-task-list/f-unit-task-list.component.html | 2 +- .../f-unit-task-list/f-unit-task-list.component.ts | 9 ++++++--- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html index 1fd9060d63..3f8d0ba1b9 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html @@ -1,9 +1,11 @@
- {{ project.activeTasks() | json }} + {{ project.activeTasks().length }} + {{ project.unit.taskDefinitions.length }} @if (subs$ | async) { diff --git a/src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.html b/src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.html index 04e36917e5..b9a3259c22 100644 --- a/src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.html +++ b/src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.html @@ -3,7 +3,7 @@
- +
@@ -23,7 +23,7 @@
- +
diff --git a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html b/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html index 1ca78334f0..d21e6003c8 100644 --- a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html +++ b/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html @@ -21,7 +21,7 @@
- + @if (filteredTasks.length === 0) {
No tasks to display
} diff --git a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts b/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts index d4dee931d5..334de8d13e 100644 --- a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts +++ b/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts @@ -11,7 +11,7 @@ import {TasksViewerService} from '../../../tasks-viewer.service'; }) export class FUnitTaskListComponent implements OnInit { @Input() mode: 'project' | 'all-tasks'; - @Input() tasks: TaskDefinition[]; + @Input() taskDefinitions: TaskDefinition[]; filteredTasks: TaskDefinition[]; // list of tasks which match the taskSearch term taskSearch: string = ''; // task search term from user input @@ -23,7 +23,10 @@ export class FUnitTaskListComponent implements OnInit { constructor(private taskViewerService: TasksViewerService) {} applyFilters() { - this.filteredTasks = this.taskDefinitionNamePipe.transform(this.tasks, this.taskSearch); + this.filteredTasks = this.taskDefinitionNamePipe.transform( + this.taskDefinitions, + this.taskSearch, + ); } ngOnInit(): void { @@ -32,7 +35,7 @@ export class FUnitTaskListComponent implements OnInit { this.taskViewerService.selectedTaskDef.subscribe((taskDef) => { this.selectedTaskDef = taskDef; }); - this.taskViewerService.selectedTaskDef.next(this.tasks[0]); + this.taskViewerService.selectedTaskDef.next(this.taskDefinitions[0]); this.taskViewerService.taskSelected.subscribe((taskSelected) => { this.taskSelected = taskSelected; From 119d7eca36b9856724b0a15e151ad32af48775d9 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Thu, 6 Jun 2024 20:23:12 +1000 Subject: [PATCH 0092/1531] chore: wire up project dashboard task list --- .../project-dashboard.component.html | 7 +++- .../project-dashboard.component.ts | 34 +++++++++++++++-- .../f-unit-task-list.component.html | 5 ++- .../f-unit-task-list.component.ts | 37 ++++++++++++++++--- 4 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html index 3f8d0ba1b9..051f7edfdd 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html @@ -2,11 +2,16 @@
{{ project.activeTasks().length }} {{ project.unit.taskDefinitions.length }} +
+

Selected task definition: {{ selectedTaskDefinition.abbreviation }}

+
@if (subs$ | async) {
; + /** + * Reference to the unit task list component so that we can create an + * observer of the selected task definition. + */ + private unitTaskListPlaceholder: FUnitTaskListComponent; + + @ViewChild('unitTaskList') set unitTaskList(content: FUnitTaskListComponent) { + if (content) { + // initially setter gets called with undefined + this.unitTaskListPlaceholder = content; + this.selectedTaskDefinition$ = outputToObservable(this.unitTaskListPlaceholder.selectedTaskDefinition); + + // Triger event for first selected task? -- not a behaviour subject? How can we avoid this? + setTimeout(() => { + this.unitTaskListPlaceholder.selectedTaskDefinition.emit(this.unitTaskListPlaceholder.selectedTaskDef); + }); + } + } + + /** + * The currently selected task definition - selected in the unit task list. + */ + public selectedTaskDefinition$: Observable; + subs$: Observable; private leftComponentStartSize$ = new Subject(); private dragMove$ = new Subject<{event: CdkDragMove; div: HTMLDivElement}>(); private dragMoveAudited$; + projectTasks = []; constructor( private currentUser: UserService, private projectService: ProjectService, private globalStateService: GlobalStateService, - ) { - } + ) {} startedDragging(event: CdkDragStart, div: HTMLDivElement) { event.source.element.nativeElement.classList.add('hovering'); diff --git a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html b/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html index d21e6003c8..96f8b86b88 100644 --- a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html +++ b/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html @@ -30,9 +30,9 @@ @if (task) {
@@ -46,6 +46,7 @@

{{ task.name }}

group }
{{ gradeNames[task.targetGrade] }} Task
+

{{ taskForTaskDef(task).status }}

diff --git a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts b/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts index 334de8d13e..7d68d75f28 100644 --- a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts +++ b/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts @@ -1,6 +1,6 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {Component, Input, OnInit, output} from '@angular/core'; import {Grade} from 'src/app/api/models/grade'; -import {TaskDefinition} from 'src/app/api/models/doubtfire-model'; +import {TaskDefinition, Task} from 'src/app/api/models/doubtfire-model'; import {TaskDefinitionNamePipe} from 'src/app/common/filters/task-definition-name.pipe'; import {TasksViewerService} from '../../../tasks-viewer.service'; @@ -12,6 +12,11 @@ import {TasksViewerService} from '../../../tasks-viewer.service'; export class FUnitTaskListComponent implements OnInit { @Input() mode: 'project' | 'all-tasks'; @Input() taskDefinitions: TaskDefinition[]; + @Input() tasks: Task[]; + + selectedTaskDefinition = output(); + + // @Output() selectedTask: EventEmitter = new EventEmitter(); filteredTasks: TaskDefinition[]; // list of tasks which match the taskSearch term taskSearch: string = ''; // task search term from user input @@ -29,24 +34,44 @@ export class FUnitTaskListComponent implements OnInit { ); } + public get hasTasks(): boolean { + return this.tasks && this.tasks.length > 0; + } + + public taskForTaskDef(taskDef: TaskDefinition): Task { + return this.tasks.find((task) => task.definition.id === taskDef.id); + } + ngOnInit(): void { this.applyFilters(); + // TODO: Remove the service this.taskViewerService.selectedTaskDef.subscribe((taskDef) => { this.selectedTaskDef = taskDef; }); - this.taskViewerService.selectedTaskDef.next(this.taskDefinitions[0]); this.taskViewerService.taskSelected.subscribe((taskSelected) => { this.taskSelected = taskSelected; }); + + // Select the first task definition by default + if (this.taskDefinitions.length > 0) { + this.setSelectedTaskDefinition(this.taskDefinitions[0]); + } } - setSelectedTask(task: TaskDefinition) { - this.taskViewerService.setSelectedTaskDef(task); + setSelectedTaskDefinition(taskDef: TaskDefinition) { + this.selectedTaskDefinition.emit(taskDef); + // const selectedTask = this.taskForTaskDef(taskDef); + // if (selectedTask) { + // this.selectedTask$.next(selectedTask); + // } + + //TODO: remove + this.taskViewerService.setSelectedTaskDef(taskDef); } - isSelectedTask(task: TaskDefinition) { + isSelectedTaskDefinition(task: TaskDefinition) { return this.selectedTaskDef.id == task.id; } } From 9bc48b03905c0a839d78ea13be9817ca73ba54cf Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Thu, 6 Jun 2024 20:53:45 +1000 Subject: [PATCH 0093/1531] fix: disable launch scorm test button if user is staff --- .../task-scorm-card/task-scorm-card.component.html | 7 ++++++- .../task-scorm-card/task-scorm-card.component.ts | 10 ++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html index 1929afb248..ec385b4760 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html @@ -14,7 +14,12 @@

- diff --git a/src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.scss b/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.scss similarity index 100% rename from src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.scss rename to src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.scss diff --git a/src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.spec.ts b/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.spec.ts similarity index 100% rename from src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.spec.ts rename to src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.spec.ts diff --git a/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.ts b/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.ts new file mode 100644 index 0000000000..e079155f96 --- /dev/null +++ b/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.ts @@ -0,0 +1,34 @@ +import {Component, Input} from '@angular/core'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {Unit} from 'src/app/api/models/unit'; +import {BehaviorSubject} from 'rxjs'; + +@Component({ + selector: 'f-tasks-viewer', + templateUrl: './f-tasks-viewer.component.html', + styleUrls: ['./f-tasks-viewer.component.scss'], +}) +export class TasksViewerComponent { + @Input() taskDefs: TaskDefinition[]; + @Input() unit: Unit; + + /** + * Monitor and publish the selected task definition for child components. + * We monitor the task definition list for changes in selected task definition. + */ + selectedTaskDefinition$: BehaviorSubject = new BehaviorSubject( + null, + ); + + public get taskSelected(): boolean { + return this.selectedTaskDef !== null; + } + + public get selectedTaskDef(): TaskDefinition { + return this.selectedTaskDefinition$.value; + } + + public clearTaskSelection(): void { + this.selectedTaskDefinition$.next(null); + } +} diff --git a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html b/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.html similarity index 98% rename from src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html rename to src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.html index 96f8b86b88..9b0adcaf33 100644 --- a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.html +++ b/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.html @@ -12,7 +12,7 @@ spellcheck="false" type="text" placeholder="Search Tasks" - [(ngModel)]="taskSearch" + [(ngModel)]="searchText" (ngModelChange)="applyFilters()" />
diff --git a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.scss b/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.scss similarity index 100% rename from src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.scss rename to src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.scss diff --git a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.spec.ts b/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.spec.ts similarity index 88% rename from src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.spec.ts rename to src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.spec.ts index dc592e52cc..3ac584b5e7 100644 --- a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.spec.ts +++ b/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.spec.ts @@ -1,6 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { FUnitTaskListComponent } from './f-unit-task-list.component'; +import { FUnitTaskListComponent } from './unit-task-list.component'; describe('FUnitTaskListComponent', () => { let component: FUnitTaskListComponent; diff --git a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts b/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.ts similarity index 54% rename from src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts rename to src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.ts index 7d68d75f28..1482c7770d 100644 --- a/src/app/units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component.ts +++ b/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.ts @@ -1,8 +1,8 @@ -import {Component, Input, OnInit, output} from '@angular/core'; +import {Component, Input, OnInit} from '@angular/core'; import {Grade} from 'src/app/api/models/grade'; import {TaskDefinition, Task} from 'src/app/api/models/doubtfire-model'; import {TaskDefinitionNamePipe} from 'src/app/common/filters/task-definition-name.pipe'; -import {TasksViewerService} from '../../../tasks-viewer.service'; +import { BehaviorSubject } from 'rxjs'; @Component({ selector: 'f-unit-task-list', @@ -14,23 +14,21 @@ export class FUnitTaskListComponent implements OnInit { @Input() taskDefinitions: TaskDefinition[]; @Input() tasks: Task[]; - selectedTaskDefinition = output(); + // What is the selected task definition + @Input() selectedTaskDefinition$: BehaviorSubject; // @Output() selectedTask: EventEmitter = new EventEmitter(); filteredTasks: TaskDefinition[]; // list of tasks which match the taskSearch term - taskSearch: string = ''; // task search term from user input + searchText: string = ''; // task search term from user input taskDefinitionNamePipe = new TaskDefinitionNamePipe(); protected gradeNames: string[] = Grade.GRADES; selectedTaskDef: TaskDefinition; - taskSelected: boolean; - - constructor(private taskViewerService: TasksViewerService) {} applyFilters() { this.filteredTasks = this.taskDefinitionNamePipe.transform( this.taskDefinitions, - this.taskSearch, + this.searchText, ); } @@ -45,33 +43,44 @@ export class FUnitTaskListComponent implements OnInit { ngOnInit(): void { this.applyFilters(); - // TODO: Remove the service - this.taskViewerService.selectedTaskDef.subscribe((taskDef) => { + // Watch for changes in the selected task definition... including from us + this.selectedTaskDefinition$.subscribe((taskDef) => { this.selectedTaskDef = taskDef; }); - this.taskViewerService.taskSelected.subscribe((taskSelected) => { - this.taskSelected = taskSelected; - }); + // // TODO: Remove the service + // this.taskViewerService.selectedTaskDef.subscribe((taskDef) => { + // this.selectedTaskDef = taskDef; + // }); - // Select the first task definition by default - if (this.taskDefinitions.length > 0) { - this.setSelectedTaskDefinition(this.taskDefinitions[0]); - } + // this.taskViewerService.taskSelected.subscribe((taskSelected) => { + // this.taskSelected = taskSelected; + // }); + + // // Select the first task definition by default + // if (this.taskDefinitions.length > 0) { + // this.setSelectedTaskDefinition(this.taskDefinitions[0]); + // } } setSelectedTaskDefinition(taskDef: TaskDefinition) { - this.selectedTaskDefinition.emit(taskDef); + if (this.isSelectedTaskDefinition(taskDef)) { + this.selectedTaskDefinition$.next(null); + } else { + this.selectedTaskDefinition$.next(taskDef); + } + + // this.selectedTaskDefinition.emit(taskDef); // const selectedTask = this.taskForTaskDef(taskDef); // if (selectedTask) { // this.selectedTask$.next(selectedTask); // } //TODO: remove - this.taskViewerService.setSelectedTaskDef(taskDef); + // this.taskViewerService.setSelectedTaskDef(taskDef); } - isSelectedTaskDefinition(task: TaskDefinition) { - return this.selectedTaskDef.id == task.id; + public isSelectedTaskDefinition(taskDef: TaskDefinition) { + return this.selectedTaskDef?.id === taskDef?.id; } } From 0e5d9de9df2eaf16e473f4f8fde920ffb59ce765 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Sat, 8 Jun 2024 17:51:01 +1000 Subject: [PATCH 0097/1531] fix: switch staff to unit roles in unit service --- src/app/api/services/unit.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/api/services/unit.service.ts b/src/app/api/services/unit.service.ts index 740e9b6cc1..3c97a11fed 100644 --- a/src/app/api/services/unit.service.ts +++ b/src/app/api/services/unit.service.ts @@ -50,10 +50,10 @@ export class UnitService extends CachedEntityService { toEntityFn: (data: object, jsonKey: string, entity: Unit) => { const unitRoleService = AppInjector.get(UnitRoleService); unitRoleService.cache.get(data[jsonKey]); - } + }, }, { - keys: 'staff', + keys: 'unitRoles', toEntityOp: (data, key, entity) => { const unitRoleService = AppInjector.get(UnitRoleService); // Add staff From ea710d6481157e2fecdd83d5e828b201bbe5afdf Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Sat, 8 Jun 2024 17:58:11 +1000 Subject: [PATCH 0098/1531] refactor: correct file renames to remove f- --- .../f-units.component.html => units/units.component.html} | 0 .../f-units.component.scss => units/units.component.scss} | 0 .../units.component.spec.ts} | 0 .../f-units.component.ts => units/units.component.ts} | 4 ++-- .../f-users.component.html => users/users.component.html} | 0 .../f-users.component.scss => users/users.component.scss} | 0 .../f-users.component.ts => users/users.component.ts} | 4 ++-- .../f-chip/{f-chip.component.html => chip.component.html} | 0 .../f-chip/{f-chip.component.scss => chip.component.scss} | 0 .../{f-chip.component.spec.ts => chip.component.spec.ts} | 2 +- .../f-chip/{f-chip.component.ts => chip.component.ts} | 4 ++-- src/app/doubtfire-angular.module.ts | 6 +++--- src/app/doubtfire-angularjs.module.ts | 4 ++-- src/app/doubtfire.states.ts | 4 ++-- .../task-details-view/task-details-view.component.ts | 4 ++-- .../directives/task-sheet-view/task-sheet-view.component.ts | 4 ++-- .../directives/tasks-viewer/tasks-viewer.component.ts | 4 ++-- .../directives/unit-task-list/unit-task-list.component.ts | 4 ++-- 18 files changed, 22 insertions(+), 22 deletions(-) rename src/app/admin/states/{f-units/f-units.component.html => units/units.component.html} (100%) rename src/app/admin/states/{f-units/f-units.component.scss => units/units.component.scss} (100%) rename src/app/admin/states/{f-units/f-units.component.spec.ts => units/units.component.spec.ts} (100%) rename src/app/admin/states/{f-units/f-units.component.ts => units/units.component.ts} (98%) rename src/app/admin/states/{f-users/f-users.component.html => users/users.component.html} (100%) rename src/app/admin/states/{f-users/f-users.component.scss => users/users.component.scss} (100%) rename src/app/admin/states/{f-users/f-users.component.ts => users/users.component.ts} (98%) rename src/app/common/f-chip/{f-chip.component.html => chip.component.html} (100%) rename src/app/common/f-chip/{f-chip.component.scss => chip.component.scss} (100%) rename src/app/common/f-chip/{f-chip.component.spec.ts => chip.component.spec.ts} (91%) rename src/app/common/f-chip/{f-chip.component.ts => chip.component.ts} (57%) diff --git a/src/app/admin/states/f-units/f-units.component.html b/src/app/admin/states/units/units.component.html similarity index 100% rename from src/app/admin/states/f-units/f-units.component.html rename to src/app/admin/states/units/units.component.html diff --git a/src/app/admin/states/f-units/f-units.component.scss b/src/app/admin/states/units/units.component.scss similarity index 100% rename from src/app/admin/states/f-units/f-units.component.scss rename to src/app/admin/states/units/units.component.scss diff --git a/src/app/admin/states/f-units/f-units.component.spec.ts b/src/app/admin/states/units/units.component.spec.ts similarity index 100% rename from src/app/admin/states/f-units/f-units.component.spec.ts rename to src/app/admin/states/units/units.component.spec.ts diff --git a/src/app/admin/states/f-units/f-units.component.ts b/src/app/admin/states/units/units.component.ts similarity index 98% rename from src/app/admin/states/f-units/f-units.component.ts rename to src/app/admin/states/units/units.component.ts index 03ce4ddad6..c4292152bf 100644 --- a/src/app/admin/states/f-units/f-units.component.ts +++ b/src/app/admin/states/units/units.component.ts @@ -30,8 +30,8 @@ type IUnitOrProject = { @Component({ selector: 'f-units', - templateUrl: './f-units.component.html', - styleUrls: ['./f-units.component.scss'], + templateUrl: './units.component.html', + styleUrls: ['./units.component.scss'], }) export class FUnitsComponent implements OnInit, AfterViewInit { @ViewChild(MatTable, {static: false}) table: MatTable; diff --git a/src/app/admin/states/f-users/f-users.component.html b/src/app/admin/states/users/users.component.html similarity index 100% rename from src/app/admin/states/f-users/f-users.component.html rename to src/app/admin/states/users/users.component.html diff --git a/src/app/admin/states/f-users/f-users.component.scss b/src/app/admin/states/users/users.component.scss similarity index 100% rename from src/app/admin/states/f-users/f-users.component.scss rename to src/app/admin/states/users/users.component.scss diff --git a/src/app/admin/states/f-users/f-users.component.ts b/src/app/admin/states/users/users.component.ts similarity index 98% rename from src/app/admin/states/f-users/f-users.component.ts rename to src/app/admin/states/users/users.component.ts index 7865e6801f..88c70c29e0 100644 --- a/src/app/admin/states/f-users/f-users.component.ts +++ b/src/app/admin/states/users/users.component.ts @@ -12,8 +12,8 @@ import { AlertService } from 'src/app/common/services/alert.service'; @Component({ selector: 'f-users', - templateUrl: './f-users.component.html', - styleUrls: ['./f-users.component.scss'], + templateUrl: './users.component.html', + styleUrls: ['./users.component.scss'], }) export class FUsersComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild(MatTable, { static: false }) table: MatTable; diff --git a/src/app/common/f-chip/f-chip.component.html b/src/app/common/f-chip/chip.component.html similarity index 100% rename from src/app/common/f-chip/f-chip.component.html rename to src/app/common/f-chip/chip.component.html diff --git a/src/app/common/f-chip/f-chip.component.scss b/src/app/common/f-chip/chip.component.scss similarity index 100% rename from src/app/common/f-chip/f-chip.component.scss rename to src/app/common/f-chip/chip.component.scss diff --git a/src/app/common/f-chip/f-chip.component.spec.ts b/src/app/common/f-chip/chip.component.spec.ts similarity index 91% rename from src/app/common/f-chip/f-chip.component.spec.ts rename to src/app/common/f-chip/chip.component.spec.ts index f431488a66..a08f153a40 100644 --- a/src/app/common/f-chip/f-chip.component.spec.ts +++ b/src/app/common/f-chip/chip.component.spec.ts @@ -1,6 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { FChipComponent } from './f-chip.component'; +import { FChipComponent } from './chip.component'; describe('FChipComponent', () => { let component: FChipComponent; diff --git a/src/app/common/f-chip/f-chip.component.ts b/src/app/common/f-chip/chip.component.ts similarity index 57% rename from src/app/common/f-chip/f-chip.component.ts rename to src/app/common/f-chip/chip.component.ts index de2a1e148f..ffabb6d523 100644 --- a/src/app/common/f-chip/f-chip.component.ts +++ b/src/app/common/f-chip/chip.component.ts @@ -2,7 +2,7 @@ import { Component } from '@angular/core'; @Component({ selector: 'f-chip', - templateUrl: './f-chip.component.html', - styleUrls: ['./f-chip.component.scss'], + templateUrl: './chip.component.html', + styleUrls: ['./chip.component.scss'], }) export class FChipComponent {} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 871204b847..ede7f5439b 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -194,7 +194,7 @@ import {TaskDashboardComponent} from './projects/states/dashboard/directives/tas import {InboxComponent} from './units/states/tasks/inbox/inbox.component'; import {ProjectProgressBarComponent} from './common/project-progress-bar/project-progress-bar.component'; import {TeachingPeriodListComponent} from './admin/states/teaching-periods/teaching-period-list/teaching-period-list.component'; -import {FChipComponent} from './common/f-chip/f-chip.component'; +import {FChipComponent} from './common/f-chip/chip.component'; import {TaskSimilarityViewComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component'; import {FileViewerComponent} from './common/file-viewer/file-viewer.component'; import {TaskDefinitionEditorComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component'; @@ -208,7 +208,7 @@ import {TaskDefinitionOverseerComponent} from './units/states/edit/directives/un import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-route.component'; import {FileDropComponent} from './common/file-drop/file-drop.component'; import {UnitTaskEditorComponent} from './units/states/edit/directives/unit-tasks-editor/unit-task-editor.component'; -import {FUsersComponent} from './admin/states/f-users/f-users.component'; +import {FUsersComponent} from './admin/states/users/users.component'; import {ProjectProgressComponent} from './common/project-progress/project-progress.component'; import {CreateNewUnitModal} from './admin/modals/create-new-unit-modal/create-new-unit-modal.component'; import {CreateNewUnitModalContentComponent} from './admin/modals/create-new-unit-modal/create-new-unit-modal-content.component'; @@ -219,7 +219,7 @@ import { import {AcceptEulaComponent} from './eula/accept-eula/accept-eula.component'; import {TiiActionLogComponent} from './admin/tii-action-log/tii-action-log.component'; import {TiiActionService} from './api/services/tii-action.service'; -import {FUnitsComponent} from './admin/states/f-units/f-units.component'; +import {FUnitsComponent} from './admin/states/units/units.component'; import {FUnitTaskListComponent} from './units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component'; import {FTaskDetailsViewComponent} from './units/states/tasks/viewer/directives/task-details-view/task-details-view.component'; import {FTaskSheetViewComponent} from './units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component'; diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index a8aa825897..03426ebc18 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -215,13 +215,13 @@ import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-ro import {UnitTaskEditorComponent} from './units/states/edit/directives/unit-tasks-editor/unit-task-editor.component'; import {TeachingPeriodUnitImportService} from './admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog'; import {CreateNewUnitModal} from './admin/modals/create-new-unit-modal/create-new-unit-modal.component'; -import {FUsersComponent} from './admin/states/f-users/f-users.component'; +import {FUsersComponent} from './admin/states/users/users.component'; import {FUnitTaskListComponent} from './units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component'; import {FTaskDetailsViewComponent} from './units/states/tasks/viewer/directives/task-details-view/task-details-view.component'; import {FTaskSheetViewComponent} from './units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component'; import {TasksViewerComponent} from './units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component'; -import {FUnitsComponent} from './admin/states/f-units/f-units.component'; +import {FUnitsComponent} from './admin/states/units/units.component'; import {MarkedPipe} from './common/pipes/marked.pipe'; import {AlertService} from './common/services/alert.service'; import {GradeService} from './common/services/grade.service'; diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index 8725cff1d0..fe216a6119 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -6,8 +6,8 @@ import {SignInComponent} from './sessions/states/sign-in/sign-in.component'; import {EditProfileComponent} from './account/edit-profile/edit-profile.component'; import {TeachingPeriodListComponent} from './admin/states/teaching-periods/teaching-period-list/teaching-period-list.component'; import {AcceptEulaComponent} from './eula/accept-eula/accept-eula.component'; -import {FUsersComponent} from './admin/states/f-users/f-users.component'; -import {FUnitsComponent} from './admin/states/f-units/f-units.component'; +import {FUsersComponent} from './admin/states/users/users.component'; +import {FUnitsComponent} from './admin/states/units/units.component'; import {ProjectDashboardComponent} from './projects/states/dashboard/project-dashboard/project-dashboard.component'; import {AppInjector} from './app-injector'; import {ProjectService} from './api/services/project.service'; diff --git a/src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.component.ts b/src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.component.ts index d681ebe587..932bf37db1 100644 --- a/src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.component.ts +++ b/src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.component.ts @@ -4,8 +4,8 @@ import {Unit} from 'src/app/api/models/unit'; @Component({ selector: 'f-task-details-view', - templateUrl: './f-task-details-view.component.html', - styleUrls: ['./f-task-details-view.component.scss'], + templateUrl: './task-details-view.component.html', + styleUrls: ['./task-details-view.component.scss'], }) export class FTaskDetailsViewComponent { @Input() taskDef: TaskDefinition; diff --git a/src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.ts b/src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.ts index 5a6171ac97..b5d71a7c52 100644 --- a/src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.ts +++ b/src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.ts @@ -3,8 +3,8 @@ import { TaskDefinition } from 'src/app/api/models/task-definition'; @Component({ selector: 'f-task-sheet-view', - templateUrl: './f-task-sheet-view.component.html', - styleUrls: ['./f-task-sheet-view.component.scss'], + templateUrl: './task-sheet-view.component.html', + styleUrls: ['./task-sheet-view.component.scss'], }) export class FTaskSheetViewComponent { @Input() taskDef: TaskDefinition; diff --git a/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.ts b/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.ts index e079155f96..09b21e3fa4 100644 --- a/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.ts +++ b/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.ts @@ -5,8 +5,8 @@ import {BehaviorSubject} from 'rxjs'; @Component({ selector: 'f-tasks-viewer', - templateUrl: './f-tasks-viewer.component.html', - styleUrls: ['./f-tasks-viewer.component.scss'], + templateUrl: './tasks-viewer.component.html', + styleUrls: ['./tasks-viewer.component.scss'], }) export class TasksViewerComponent { @Input() taskDefs: TaskDefinition[]; diff --git a/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.ts index 1482c7770d..f23c21568e 100644 --- a/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.ts @@ -6,8 +6,8 @@ import { BehaviorSubject } from 'rxjs'; @Component({ selector: 'f-unit-task-list', - templateUrl: './f-unit-task-list.component.html', - styleUrls: ['./f-unit-task-list.component.scss'], + templateUrl: './unit-task-list.component.html', + styleUrls: ['./unit-task-list.component.scss'], }) export class FUnitTaskListComponent implements OnInit { @Input() mode: 'project' | 'all-tasks'; From dc2c0bcbe1d0562bfbe8a8babcca8a77f1fd3a87 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Sat, 8 Jun 2024 18:01:05 +1000 Subject: [PATCH 0099/1531] refactor: update project dashboard to use selected task def subject --- .../project-dashboard/project-dashboard.component.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html index 051f7edfdd..5af2305c8d 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html @@ -10,8 +10,7 @@ [mode]="'project'" [taskDefinitions]="project.unit.taskDefinitions" [tasks]="project.tasks" - (selectedTaskDefinition)="(selectedTaskDefinition$)" - #unitTaskList + [selectedTaskDefinition$]="selectedTaskDefinition$" > @if (subs$ | async) {
Date: Sat, 8 Jun 2024 22:06:21 +1000 Subject: [PATCH 0100/1531] refactor: implement unit root state and new task viewer state --- .../filters/task-definition-name.pipe.ts | 13 +-- .../unit-dropdown.component.html | 2 +- src/app/doubtfire-angular.module.ts | 12 ++- src/app/doubtfire-angularjs.module.ts | 10 +-- src/app/doubtfire.states.ts | 6 +- src/app/units/states/tasks/tasks.coffee | 1 - .../tasks/viewer/directives/directives.coffee | 5 -- .../units/states/tasks/viewer/viewer.coffee | 23 ----- src/app/units/states/tasks/viewer/viewer.scss | 4 - .../units/states/tasks/viewer/viewer.tpl.html | 1 - .../task-details-view.component.html | 0 .../task-details-view.component.scss | 0 .../task-details-view.component.ts | 0 .../task-sheet-view.component.html | 0 .../task-sheet-view.component.scss | 0 .../task-sheet-view.component.spec.ts | 0 .../task-sheet-view.component.ts | 0 .../tasks-viewer/tasks-viewer.component.html | 2 +- .../tasks-viewer/tasks-viewer.component.scss | 0 .../tasks-viewer.component.spec.ts | 0 .../tasks-viewer/tasks-viewer.component.ts | 1 - .../unit-task-list.component.html | 0 .../unit-task-list.component.scss | 0 .../unit-task-list.component.spec.ts | 0 .../unit-task-list.component.ts | 0 .../task-viewer-state.component.html | 3 + .../task-viewer-state.component.scss | 25 ++++++ .../task-viewer-state.component.ts | 44 +++++++++ src/app/units/unit-root-state.component.css | 0 src/app/units/unit-root-state.component.html | 1 + src/app/units/unit-root-state.component.ts | 90 +++++++++++++++++++ 31 files changed, 189 insertions(+), 54 deletions(-) delete mode 100644 src/app/units/states/tasks/viewer/directives/directives.coffee delete mode 100644 src/app/units/states/tasks/viewer/viewer.coffee delete mode 100644 src/app/units/states/tasks/viewer/viewer.scss delete mode 100644 src/app/units/states/tasks/viewer/viewer.tpl.html rename src/app/units/{states/tasks/viewer => task-viewer}/directives/task-details-view/task-details-view.component.html (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/task-details-view/task-details-view.component.scss (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/task-details-view/task-details-view.component.ts (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/task-sheet-view/task-sheet-view.component.html (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/task-sheet-view/task-sheet-view.component.scss (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/task-sheet-view/task-sheet-view.component.spec.ts (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/task-sheet-view/task-sheet-view.component.ts (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/tasks-viewer/tasks-viewer.component.html (97%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/tasks-viewer/tasks-viewer.component.scss (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/tasks-viewer/tasks-viewer.component.spec.ts (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/tasks-viewer/tasks-viewer.component.ts (96%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/unit-task-list/unit-task-list.component.html (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/unit-task-list/unit-task-list.component.scss (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/unit-task-list/unit-task-list.component.spec.ts (100%) rename src/app/units/{states/tasks/viewer => task-viewer}/directives/unit-task-list/unit-task-list.component.ts (100%) create mode 100644 src/app/units/task-viewer/task-viewer-state.component.html create mode 100644 src/app/units/task-viewer/task-viewer-state.component.scss create mode 100644 src/app/units/task-viewer/task-viewer-state.component.ts create mode 100644 src/app/units/unit-root-state.component.css create mode 100644 src/app/units/unit-root-state.component.html create mode 100644 src/app/units/unit-root-state.component.ts diff --git a/src/app/common/filters/task-definition-name.pipe.ts b/src/app/common/filters/task-definition-name.pipe.ts index 155595d2ff..ad9ccdce18 100644 --- a/src/app/common/filters/task-definition-name.pipe.ts +++ b/src/app/common/filters/task-definition-name.pipe.ts @@ -1,4 +1,3 @@ - import { Pipe, PipeTransform } from '@angular/core'; import { Task, TaskDefinition } from '../../api/models/doubtfire-model'; @@ -10,10 +9,12 @@ export class TaskDefinitionNamePipe implements PipeTransform { searchName = searchName.toLowerCase(); return taskDefinitions.filter( // use lodash filter? (td) => { - return td.name.toLowerCase().includes(searchName) || - td.abbreviation.toLowerCase().includes(searchName) || - td.targetGradeText.toLowerCase().includes(searchName) - } - ) + return ( + td?.name.toLowerCase().includes(searchName) || + td?.abbreviation.toLowerCase().includes(searchName) || + td?.targetGradeText.toLowerCase().includes(searchName) + ); + }, + ); } } diff --git a/src/app/common/header/unit-dropdown/unit-dropdown.component.html b/src/app/common/header/unit-dropdown/unit-dropdown.component.html index 8ac2a35e17..60b67ece95 100644 --- a/src/app/common/header/unit-dropdown/unit-dropdown.component.html +++ b/src/app/common/header/unit-dropdown/unit-dropdown.component.html @@ -5,7 +5,7 @@ [shiftBetweenBadges]="false" [width]="80" [unit_code]="unit?.code" - matTooltip="{{ unit.name }}" + matTooltip="{{ unit?.name }}" [matMenuTriggerFor]="menu" #menuState="matMenuTrigger" > diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index ede7f5439b..9582928c63 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -220,12 +220,14 @@ import {AcceptEulaComponent} from './eula/accept-eula/accept-eula.component'; import {TiiActionLogComponent} from './admin/tii-action-log/tii-action-log.component'; import {TiiActionService} from './api/services/tii-action.service'; import {FUnitsComponent} from './admin/states/units/units.component'; -import {FUnitTaskListComponent} from './units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component'; -import {FTaskDetailsViewComponent} from './units/states/tasks/viewer/directives/task-details-view/task-details-view.component'; -import {FTaskSheetViewComponent} from './units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component'; -import {TasksViewerComponent} from './units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component'; +import {FUnitTaskListComponent} from './units/task-viewer/directives/unit-task-list/unit-task-list.component'; +import {FTaskDetailsViewComponent} from './units/task-viewer/directives/task-details-view/task-details-view.component'; +import {FTaskSheetViewComponent} from './units/task-viewer/directives/task-sheet-view/task-sheet-view.component'; +import {TasksViewerComponent} from './units/task-viewer/directives/tasks-viewer/tasks-viewer.component'; import {UnitCodeComponent} from './common/unit-code/unit-code.component'; import {GradeService} from './common/services/grade.service'; +import { UnitRootStateComponent } from './units/unit-root-state.component'; +import { TaskViewerStateComponent } from './units/task-viewer/task-viewer-state.component'; @NgModule({ // Components we declare @@ -325,6 +327,8 @@ import {GradeService} from './common/services/grade.service'; FTaskDetailsViewComponent, FTaskSheetViewComponent, TasksViewerComponent, + UnitRootStateComponent, + TaskViewerStateComponent, FUsersComponent, ProjectProgressComponent, FTaskBadgeComponent, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 03426ebc18..7f77443a7e 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -98,8 +98,6 @@ import 'build/src/app/units/modals/modals.js'; import 'build/src/app/units/units.js'; import 'build/src/app/units/states/tasks/inbox/inbox.js'; import 'build/src/app/units/states/tasks/tasks.js'; -import 'build/src/app/units/states/tasks/viewer/directives/directives.js'; -import 'build/src/app/units/states/tasks/viewer/viewer.js'; import 'build/src/app/units/states/tasks/definition/definition.js'; import 'build/src/app/units/states/portfolios/portfolios.js'; import 'build/src/app/units/states/groups/groups.js'; @@ -216,10 +214,10 @@ import {UnitTaskEditorComponent} from './units/states/edit/directives/unit-tasks import {TeachingPeriodUnitImportService} from './admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog'; import {CreateNewUnitModal} from './admin/modals/create-new-unit-modal/create-new-unit-modal.component'; import {FUsersComponent} from './admin/states/users/users.component'; -import {FUnitTaskListComponent} from './units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component'; -import {FTaskDetailsViewComponent} from './units/states/tasks/viewer/directives/task-details-view/task-details-view.component'; -import {FTaskSheetViewComponent} from './units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component'; -import {TasksViewerComponent} from './units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component'; +import {FUnitTaskListComponent} from './units/task-viewer/directives/unit-task-list/unit-task-list.component'; +import {FTaskDetailsViewComponent} from './units/task-viewer/directives/task-details-view/task-details-view.component'; +import {FTaskSheetViewComponent} from './units/task-viewer/directives/task-sheet-view/task-sheet-view.component'; +import {TasksViewerComponent} from './units/task-viewer/directives/tasks-viewer/tasks-viewer.component'; import {FUnitsComponent} from './admin/states/units/units.component'; import {MarkedPipe} from './common/pipes/marked.pipe'; diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index fe216a6119..f9330cac67 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -14,6 +14,8 @@ import {ProjectService} from './api/services/project.service'; import {Observable, first} from 'rxjs'; import {GlobalStateService} from './projects/states/index/global-state.service'; import {Project} from './api/models/project'; +import {UnitRootState} from './units/unit-root-state.component'; +import { TaskViewerState } from './units/task-viewer/task-viewer-state.component'; /* * Use this file to store any states that are sourced by angular components. @@ -289,7 +291,7 @@ const AbstractProjectState: NgHybridStateDeclaration = { const projectService = AppInjector.get(ProjectService); const globalState = AppInjector.get(GlobalStateService); - return new Observable((observer) => { + return new Observable((observer) => { globalState.onLoad(() => { projectService .get({id: $stateParams.projectId}, {cacheBehaviourOnGet: 'cacheQuery'}) @@ -359,4 +361,6 @@ export const doubtfireStates = [ AdministerUnits, AbstractProjectState, ProjectDashboardState, + UnitRootState, + TaskViewerState, ]; diff --git a/src/app/units/states/tasks/tasks.coffee b/src/app/units/states/tasks/tasks.coffee index 141e0364c6..eba3810469 100644 --- a/src/app/units/states/tasks/tasks.coffee +++ b/src/app/units/states/tasks/tasks.coffee @@ -1,7 +1,6 @@ angular.module('doubtfire.units.states.tasks', [ 'doubtfire.units.states.tasks.inbox' 'doubtfire.units.states.tasks.definition' - 'doubtfire.units.states.tasks.viewer' ]) # diff --git a/src/app/units/states/tasks/viewer/directives/directives.coffee b/src/app/units/states/tasks/viewer/directives/directives.coffee deleted file mode 100644 index 1624d23757..0000000000 --- a/src/app/units/states/tasks/viewer/directives/directives.coffee +++ /dev/null @@ -1,5 +0,0 @@ -angular.module('doubtfire.units.states.tasks.viewer.directives', [ - # 'doubtfire.units.states.tasks.viewer.directives.unit-task-list' - # 'doubtfire.units.states.tasks.viewer.directives.task-sheet-view' - # 'doubtfire.units.states.tasks.viewer.directives.task-details-view' -]) diff --git a/src/app/units/states/tasks/viewer/viewer.coffee b/src/app/units/states/tasks/viewer/viewer.coffee deleted file mode 100644 index 0dde935439..0000000000 --- a/src/app/units/states/tasks/viewer/viewer.coffee +++ /dev/null @@ -1,23 +0,0 @@ -angular.module('doubtfire.units.states.tasks.viewer', [ - 'doubtfire.units.states.tasks.viewer.directives' -]) - -# -# Give feedback when on one-to-one for students (i.e., tasksRequiringFeedback) -# -.config(($stateProvider) -> - $stateProvider.state 'units/tasks/viewer', { - parent: 'units/tasks' - url: '/viewer' - templateUrl: "units/states/tasks/viewer/viewer.tpl.html" - controller: "TaskViewerStateCtrl" - data: - task: "Task List" - pageTitle: "_Home_" - roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor'] - } -) - -.controller('TaskViewerStateCtrl', ($scope) -> - $scope.taskDefs = $scope.unit.taskDefinitions -) diff --git a/src/app/units/states/tasks/viewer/viewer.scss b/src/app/units/states/tasks/viewer/viewer.scss deleted file mode 100644 index 382bfdc247..0000000000 --- a/src/app/units/states/tasks/viewer/viewer.scss +++ /dev/null @@ -1,4 +0,0 @@ -f-tasks-viewer { - height: calc($main-view-max-height + 70px); // temporary fix to reclaim the footer region for this specific page - display: flex; -} diff --git a/src/app/units/states/tasks/viewer/viewer.tpl.html b/src/app/units/states/tasks/viewer/viewer.tpl.html deleted file mode 100644 index 358d6f33a2..0000000000 --- a/src/app/units/states/tasks/viewer/viewer.tpl.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.component.html b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.html similarity index 100% rename from src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.component.html rename to src/app/units/task-viewer/directives/task-details-view/task-details-view.component.html diff --git a/src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.component.scss b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.scss similarity index 100% rename from src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.component.scss rename to src/app/units/task-viewer/directives/task-details-view/task-details-view.component.scss diff --git a/src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.component.ts b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.ts similarity index 100% rename from src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.component.ts rename to src/app/units/task-viewer/directives/task-details-view/task-details-view.component.ts diff --git a/src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.html b/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.html similarity index 100% rename from src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.html rename to src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.html diff --git a/src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.scss b/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.scss similarity index 100% rename from src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.scss rename to src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.scss diff --git a/src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.spec.ts b/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.spec.ts similarity index 100% rename from src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.spec.ts rename to src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.spec.ts diff --git a/src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.ts b/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.ts similarity index 100% rename from src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.component.ts rename to src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.ts diff --git a/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.html b/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.html similarity index 97% rename from src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.html rename to src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.html index 383bd28d2d..c752c41c84 100644 --- a/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.html +++ b/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.html @@ -29,7 +29,7 @@
diff --git a/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.scss b/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.scss similarity index 100% rename from src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.scss rename to src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.scss diff --git a/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.spec.ts b/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.spec.ts similarity index 100% rename from src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.spec.ts rename to src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.spec.ts diff --git a/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.ts b/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.ts similarity index 96% rename from src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.ts rename to src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.ts index 09b21e3fa4..059d881eef 100644 --- a/src/app/units/states/tasks/viewer/directives/tasks-viewer/tasks-viewer.component.ts +++ b/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.ts @@ -9,7 +9,6 @@ import {BehaviorSubject} from 'rxjs'; styleUrls: ['./tasks-viewer.component.scss'], }) export class TasksViewerComponent { - @Input() taskDefs: TaskDefinition[]; @Input() unit: Unit; /** diff --git a/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html similarity index 100% rename from src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.html rename to src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html diff --git a/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.scss b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss similarity index 100% rename from src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.scss rename to src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss diff --git a/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.spec.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts similarity index 100% rename from src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.spec.ts rename to src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts diff --git a/src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts similarity index 100% rename from src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.component.ts rename to src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts diff --git a/src/app/units/task-viewer/task-viewer-state.component.html b/src/app/units/task-viewer/task-viewer-state.component.html new file mode 100644 index 0000000000..ab9fe5dd31 --- /dev/null +++ b/src/app/units/task-viewer/task-viewer-state.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/app/units/task-viewer/task-viewer-state.component.scss b/src/app/units/task-viewer/task-viewer-state.component.scss new file mode 100644 index 0000000000..f3720d4d50 --- /dev/null +++ b/src/app/units/task-viewer/task-viewer-state.component.scss @@ -0,0 +1,25 @@ +.vertical-panel { + border-radius: 10px; + background-color: white; + padding: 8px; + min-width: 60px; + width: 450px; + height: 100%; + + &.mobile { + max-width: 100%; + width: 100%; + padding: 0px; + } +} + +.vertical-spacer { + background-color: #f5f5f5; + z-index: 200; + width: 10px +} + +f-tasks-viewer { + height: calc($main-view-max-height + 70px); // temporary fix to reclaim the footer region for this specific page + display: flex; +} diff --git a/src/app/units/task-viewer/task-viewer-state.component.ts b/src/app/units/task-viewer/task-viewer-state.component.ts new file mode 100644 index 0000000000..26628829c7 --- /dev/null +++ b/src/app/units/task-viewer/task-viewer-state.component.ts @@ -0,0 +1,44 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import {CdkDragEnd, CdkDragMove, CdkDragStart} from '@angular/cdk/drag-drop'; +import {Component, Input, OnInit} from '@angular/core'; +import { + BehaviorSubject, + Observable, + Subject, + auditTime, + first, + merge, + of, + tap, + withLatestFrom, +} from 'rxjs'; +import {TaskDefinition, Unit, UnitService, UserService} from 'src/app/api/models/doubtfire-model'; +import { AppInjector } from '../../app-injector'; +import { NgHybridStateDeclaration } from '@uirouter/angular-hybrid'; +import { GlobalStateService, ViewType } from '../../projects/states/index/global-state.service'; +import { StateService } from '@uirouter/core'; +import { AlertService } from '../../common/services/alert.service'; + +@Component({ + selector: 'f-task-viewer-state', + templateUrl: './task-viewer-state.component.html', + styleUrl: './task-viewer-state.component.scss', +}) +export class TaskViewerStateComponent { + @Input() public unit$: Observable; +} + +export const TaskViewerState: NgHybridStateDeclaration = { + name: 'units2/tasks', + url: '/tasks/:taskDefId', + parent: 'unit-root-state', + data: { + pageTitle: 'Unit Tasks', + roleWhiteList: ['Tutor', 'Convenor', 'Admin', 'Auditor'], + }, + views: { + unitView: { + component: TaskViewerStateComponent, + }, + }, +}; diff --git a/src/app/units/unit-root-state.component.css b/src/app/units/unit-root-state.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/unit-root-state.component.html b/src/app/units/unit-root-state.component.html new file mode 100644 index 0000000000..7261f3fdc6 --- /dev/null +++ b/src/app/units/unit-root-state.component.html @@ -0,0 +1 @@ +
diff --git a/src/app/units/unit-root-state.component.ts b/src/app/units/unit-root-state.component.ts new file mode 100644 index 0000000000..8a6109121f --- /dev/null +++ b/src/app/units/unit-root-state.component.ts @@ -0,0 +1,90 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import {CdkDragEnd, CdkDragMove, CdkDragStart} from '@angular/cdk/drag-drop'; +import {Component, Input, OnInit} from '@angular/core'; +import { + BehaviorSubject, + Observable, + Subject, + auditTime, + first, + merge, + of, + tap, + withLatestFrom, +} from 'rxjs'; +import {Unit, UnitService, UserService} from 'src/app/api/models/doubtfire-model'; +import { AppInjector } from '../app-injector'; +import { NgHybridStateDeclaration } from '@uirouter/angular-hybrid'; +import { GlobalStateService, ViewType } from '../projects/states/index/global-state.service'; +import { StateService } from '@uirouter/core'; +import { AlertService } from '../common/services/alert.service'; + +@Component({ + selector: 'f-unit-root-state', + templateUrl: './unit-root-state.component.html', + styleUrl: './unit-root-state.component.css', +}) +export class UnitRootStateComponent { + @Input() public unit$: Observable; +} + +export const UnitRootState: NgHybridStateDeclaration = { + name: 'unit-root-state', + url: '/units2/:unitId', + abstract: true, + data: { + pageTitle: 'Unit Root State', + roleWhiteList: ['Tutor', 'Convenor', 'Admin', 'Auditor'], + }, + views: { + main: { + component: UnitRootStateComponent, + }, + }, + resolve: { + unit$: function ($stateParams) { + const unitService = AppInjector.get(UnitService); + const globalState = AppInjector.get(GlobalStateService); + const userService = AppInjector.get(UserService); + const stateService = AppInjector.get(StateService); + + return new Observable((observer) => { + globalState.onLoad(() => { + const unitId: number = parseInt($stateParams.unitId); + let unitRole = globalState.loadedUnitRoles.currentValues.find( + (unitRole) => unitRole.unit.id === unitId, + ); + + if ( + !unitRole && + (userService.currentUser.role == 'Admin' || userService.currentUser.role == 'Auditor') + ) { + unitRole = userService.adminOrAuditorRoleFor( + userService.currentUser.role, + unitId, + userService.currentUser, + ); + } + + // Go home if no unit role was found + if (!unitRole) { + console.log('No unit role found for unit', unitId); + return stateService.go('home'); + } + + unitService.get(unitId).subscribe({ + next: (unit: Unit) => { + observer.next(unit); + globalState.setView(ViewType.UNIT, unitRole); + observer.complete(); + }, + error: (err) => { + AppInjector.get(AlertService).error('Error loading unit: ' + err, 8000); + setTimeout(() => stateService.go('home'), 5000); + } + }); + }); + }).pipe(first()); + }, + }, +}; From 3ed44798f86860cac8b1fc8636818d9f5d1aeb6a Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Sun, 9 Jun 2024 09:58:00 +1000 Subject: [PATCH 0101/1531] refactor: move task viewer into state component --- src/app/doubtfire-angular.module.ts | 2 - src/app/doubtfire-angularjs.module.ts | 5 -- .../task-details-view.component.scss | 2 +- .../tasks-viewer/tasks-viewer.component.html | 53 ------------------ .../tasks-viewer/tasks-viewer.component.scss | 20 ------- .../tasks-viewer.component.spec.ts | 20 ------- .../tasks-viewer/tasks-viewer.component.ts | 33 ------------ .../unit-task-list.component.scss | 2 +- .../task-viewer-state.component.html | 54 ++++++++++++++++++- .../task-viewer-state.component.scss | 2 +- .../task-viewer-state.component.ts | 43 ++++++++------- 11 files changed, 80 insertions(+), 156 deletions(-) delete mode 100644 src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.html delete mode 100644 src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.scss delete mode 100644 src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.spec.ts delete mode 100644 src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.ts diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 9582928c63..a7851ca5b5 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -223,7 +223,6 @@ import {FUnitsComponent} from './admin/states/units/units.component'; import {FUnitTaskListComponent} from './units/task-viewer/directives/unit-task-list/unit-task-list.component'; import {FTaskDetailsViewComponent} from './units/task-viewer/directives/task-details-view/task-details-view.component'; import {FTaskSheetViewComponent} from './units/task-viewer/directives/task-sheet-view/task-sheet-view.component'; -import {TasksViewerComponent} from './units/task-viewer/directives/tasks-viewer/tasks-viewer.component'; import {UnitCodeComponent} from './common/unit-code/unit-code.component'; import {GradeService} from './common/services/grade.service'; import { UnitRootStateComponent } from './units/unit-root-state.component'; @@ -326,7 +325,6 @@ import { TaskViewerStateComponent } from './units/task-viewer/task-viewer-state. FUnitTaskListComponent, FTaskDetailsViewComponent, FTaskSheetViewComponent, - TasksViewerComponent, UnitRootStateComponent, TaskViewerStateComponent, FUsersComponent, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 7f77443a7e..1920adebdc 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -217,7 +217,6 @@ import {FUsersComponent} from './admin/states/users/users.component'; import {FUnitTaskListComponent} from './units/task-viewer/directives/unit-task-list/unit-task-list.component'; import {FTaskDetailsViewComponent} from './units/task-viewer/directives/task-details-view/task-details-view.component'; import {FTaskSheetViewComponent} from './units/task-viewer/directives/task-sheet-view/task-sheet-view.component'; -import {TasksViewerComponent} from './units/task-viewer/directives/tasks-viewer/tasks-viewer.component'; import {FUnitsComponent} from './admin/states/units/units.component'; import {MarkedPipe} from './common/pipes/marked.pipe'; @@ -365,10 +364,6 @@ DoubtfireAngularJSModule.directive( 'fTaskStatusCard', downgradeComponent({component: TaskStatusCardComponent}), ); -DoubtfireAngularJSModule.directive( - 'fTasksViewer', - downgradeComponent({component: TasksViewerComponent}), -); DoubtfireAngularJSModule.directive('fInbox', downgradeComponent({component: InboxComponent})); DoubtfireAngularJSModule.directive( 'fTaskDueCard', diff --git a/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.scss b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.scss index dda643e643..b06c626b5a 100644 --- a/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.scss +++ b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.scss @@ -1,6 +1,6 @@ @use '@angular/material' as mat; -@import '../../../../../../../theme.scss'; +@import '/src/theme.scssr'; $my-palette: mat.define-palette($md-formatif); diff --git a/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.html b/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.html deleted file mode 100644 index c752c41c84..0000000000 --- a/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.html +++ /dev/null @@ -1,53 +0,0 @@ - -
-
- -
- -
- -
- - -
-
-
- -
- -
-
-
-
- - -
-
- -
- -
-
- -
- -
- -
-
-
diff --git a/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.scss b/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.scss deleted file mode 100644 index cddaf52b1d..0000000000 --- a/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.scss +++ /dev/null @@ -1,20 +0,0 @@ -.vertical-panel { - border-radius: 10px; - background-color: white; - padding: 8px; - min-width: 60px; - width: 450px; - height: 100%; - - &.mobile { - max-width: 100%; - width: 100%; - padding: 0px; - } -} - -.vertical-spacer { - background-color: #f5f5f5; - z-index: 200; - width: 10px -} diff --git a/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.spec.ts b/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.spec.ts deleted file mode 100644 index bc7a35f057..0000000000 --- a/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { TasksViewerComponent } from './tasks-viewer.component'; - -describe('TasksViewerComponent', () => { - let component: TasksViewerComponent; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - declarations: [TasksViewerComponent], - }); - fixture = TestBed.createComponent(TasksViewerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.ts b/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.ts deleted file mode 100644 index 059d881eef..0000000000 --- a/src/app/units/task-viewer/directives/tasks-viewer/tasks-viewer.component.ts +++ /dev/null @@ -1,33 +0,0 @@ -import {Component, Input} from '@angular/core'; -import {TaskDefinition} from 'src/app/api/models/task-definition'; -import {Unit} from 'src/app/api/models/unit'; -import {BehaviorSubject} from 'rxjs'; - -@Component({ - selector: 'f-tasks-viewer', - templateUrl: './tasks-viewer.component.html', - styleUrls: ['./tasks-viewer.component.scss'], -}) -export class TasksViewerComponent { - @Input() unit: Unit; - - /** - * Monitor and publish the selected task definition for child components. - * We monitor the task definition list for changes in selected task definition. - */ - selectedTaskDefinition$: BehaviorSubject = new BehaviorSubject( - null, - ); - - public get taskSelected(): boolean { - return this.selectedTaskDef !== null; - } - - public get selectedTaskDef(): TaskDefinition { - return this.selectedTaskDefinition$.value; - } - - public clearTaskSelection(): void { - this.selectedTaskDefinition$.next(null); - } -} diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss index 0d460d0ffd..f6aed93b2c 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss @@ -1,6 +1,6 @@ @use '@angular/material' as mat; -@import '../../../../../../../theme.scss'; +@import '/src/theme.scss'; @import '../../../../../../../styles/mixins/scrollable.scss'; $my-palette: mat.define-palette($md-formatif); diff --git a/src/app/units/task-viewer/task-viewer-state.component.html b/src/app/units/task-viewer/task-viewer-state.component.html index ab9fe5dd31..8d19bd1bef 100644 --- a/src/app/units/task-viewer/task-viewer-state.component.html +++ b/src/app/units/task-viewer/task-viewer-state.component.html @@ -1,3 +1,55 @@
- + +
+
+ +
+ +
+ +
+ + +
+
+
+ +
+ +
+
+
+
+ + +
+
+ +
+ +
+
+ +
+ +
+ +
+
+
diff --git a/src/app/units/task-viewer/task-viewer-state.component.scss b/src/app/units/task-viewer/task-viewer-state.component.scss index f3720d4d50..39bcc3f728 100644 --- a/src/app/units/task-viewer/task-viewer-state.component.scss +++ b/src/app/units/task-viewer/task-viewer-state.component.scss @@ -19,7 +19,7 @@ width: 10px } -f-tasks-viewer { +f-task-viewer-state { height: calc($main-view-max-height + 70px); // temporary fix to reclaim the footer region for this specific page display: flex; } diff --git a/src/app/units/task-viewer/task-viewer-state.component.ts b/src/app/units/task-viewer/task-viewer-state.component.ts index 26628829c7..833647f4cb 100644 --- a/src/app/units/task-viewer/task-viewer-state.component.ts +++ b/src/app/units/task-viewer/task-viewer-state.component.ts @@ -1,23 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import {CdkDragEnd, CdkDragMove, CdkDragStart} from '@angular/cdk/drag-drop'; -import {Component, Input, OnInit} from '@angular/core'; -import { - BehaviorSubject, - Observable, - Subject, - auditTime, - first, - merge, - of, - tap, - withLatestFrom, -} from 'rxjs'; -import {TaskDefinition, Unit, UnitService, UserService} from 'src/app/api/models/doubtfire-model'; -import { AppInjector } from '../../app-injector'; -import { NgHybridStateDeclaration } from '@uirouter/angular-hybrid'; -import { GlobalStateService, ViewType } from '../../projects/states/index/global-state.service'; -import { StateService } from '@uirouter/core'; -import { AlertService } from '../../common/services/alert.service'; +import {Component, Input} from '@angular/core'; +import {BehaviorSubject, Observable} from 'rxjs'; +import {TaskDefinition, Unit} from 'src/app/api/models/doubtfire-model'; +import {NgHybridStateDeclaration} from '@uirouter/angular-hybrid'; @Component({ selector: 'f-task-viewer-state', @@ -26,6 +11,26 @@ import { AlertService } from '../../common/services/alert.service'; }) export class TaskViewerStateComponent { @Input() public unit$: Observable; + + /** + * Monitor and publish the selected task definition for child components. + * We monitor the task definition list for changes in selected task definition. + */ + selectedTaskDefinition$: BehaviorSubject = new BehaviorSubject( + null, + ); + + public get taskSelected(): boolean { + return this.selectedTaskDef !== null; + } + + public get selectedTaskDef(): TaskDefinition { + return this.selectedTaskDefinition$.value; + } + + public clearTaskSelection(): void { + this.selectedTaskDefinition$.next(null); + } } export const TaskViewerState: NgHybridStateDeclaration = { From 7d0092b8fc4d28f71884f16cc76bbd4332bdd610 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Sun, 9 Jun 2024 10:15:18 +1000 Subject: [PATCH 0102/1531] refactor: introduce project root state --- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire.states.ts | 35 ++----------- .../states/project-root-state.component.css | 0 .../states/project-root-state.component.html | 1 + .../states/project-root-state.component.ts | 50 +++++++++++++++++++ 5 files changed, 56 insertions(+), 32 deletions(-) create mode 100644 src/app/projects/states/project-root-state.component.css create mode 100644 src/app/projects/states/project-root-state.component.html create mode 100644 src/app/projects/states/project-root-state.component.ts diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index a7851ca5b5..9991e9cb33 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -227,6 +227,7 @@ import {UnitCodeComponent} from './common/unit-code/unit-code.component'; import {GradeService} from './common/services/grade.service'; import { UnitRootStateComponent } from './units/unit-root-state.component'; import { TaskViewerStateComponent } from './units/task-viewer/task-viewer-state.component'; +import { ProjectRootStateComponent } from './projects/states/project-root-state.component'; @NgModule({ // Components we declare @@ -326,6 +327,7 @@ import { TaskViewerStateComponent } from './units/task-viewer/task-viewer-state. FTaskDetailsViewComponent, FTaskSheetViewComponent, UnitRootStateComponent, + ProjectRootStateComponent, TaskViewerStateComponent, FUsersComponent, ProjectProgressComponent, diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index f9330cac67..3e4ea5e853 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -15,6 +15,7 @@ import {Observable, first} from 'rxjs'; import {GlobalStateService} from './projects/states/index/global-state.service'; import {Project} from './api/models/project'; import {UnitRootState} from './units/unit-root-state.component'; +import {ProjectRootState} from './projects/states/project-root-state.component'; import { TaskViewerState } from './units/task-viewer/task-viewer-state.component'; /* @@ -277,43 +278,13 @@ const AdministerUnits: NgHybridStateDeclaration = { }, }; -const AbstractProjectState: NgHybridStateDeclaration = { - name: 'projects2', - url: '/projects2/:projectId', - abstract: true, - views: { - main: { - component: ProjectDashboardComponent, - }, - }, - resolve: { - project$: function ($stateParams) { - const projectService = AppInjector.get(ProjectService); - const globalState = AppInjector.get(GlobalStateService); - - return new Observable((observer) => { - globalState.onLoad(() => { - projectService - .get({id: $stateParams.projectId}, {cacheBehaviourOnGet: 'cacheQuery'}) - .subscribe({ - next: (project: Project) => { - observer.next(project); - observer.complete(); - }, - }); - }); - }).pipe(first()); - }, - }, -}; - // projectDashboardState which gets the project from the abstract state above const ProjectDashboardState: NgHybridStateDeclaration = { name: 'dashboard2', parent: 'projects2', url: '/dashboard2', views: { - main: { + projectView: { component: ProjectDashboardComponent, }, }, @@ -359,7 +330,7 @@ export const doubtfireStates = [ ViewAllProjectsState, ViewAllUnits, AdministerUnits, - AbstractProjectState, + ProjectRootState, ProjectDashboardState, UnitRootState, TaskViewerState, diff --git a/src/app/projects/states/project-root-state.component.css b/src/app/projects/states/project-root-state.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/project-root-state.component.html b/src/app/projects/states/project-root-state.component.html new file mode 100644 index 0000000000..62b885d8dc --- /dev/null +++ b/src/app/projects/states/project-root-state.component.html @@ -0,0 +1 @@ +
diff --git a/src/app/projects/states/project-root-state.component.ts b/src/app/projects/states/project-root-state.component.ts new file mode 100644 index 0000000000..53de8a52b5 --- /dev/null +++ b/src/app/projects/states/project-root-state.component.ts @@ -0,0 +1,50 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import {Component, Input} from '@angular/core'; +import {Observable, first} from 'rxjs'; +import {Project, ProjectService} from 'src/app/api/models/doubtfire-model'; +import {AppInjector} from 'src/app/app-injector'; +import {NgHybridStateDeclaration} from '@uirouter/angular-hybrid'; +import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; + +@Component({ + selector: 'f-project-root-state', + templateUrl: './project-root-state.component.html', + styleUrl: './project-root-state.component.css', +}) +export class ProjectRootStateComponent { + @Input() public project$: Observable; +} + +export const ProjectRootState: NgHybridStateDeclaration = { + name: 'projects2', + url: '/projects2/:projectId', + abstract: true, + data: { + pageTitle: 'Unit Studied', + roleWhiteList: ['Student', 'Tutor', 'Convenor', 'Admin', 'Auditor'], + }, + views: { + main: { + component: ProjectRootStateComponent, + }, + }, + resolve: { + project$: function ($stateParams) { + const projectService = AppInjector.get(ProjectService); + const globalState = AppInjector.get(GlobalStateService); + + return new Observable((observer) => { + const projectId = parseInt($stateParams.projectId); + + globalState.onLoad(() => { + projectService.get({id: projectId}, {cacheBehaviourOnGet: 'cacheQuery'}).subscribe({ + next: (project: Project) => { + observer.next(project); + observer.complete(); + }, + }); + }); + }).pipe(first()); + }, + }, +}; From 4fc36705223ee8567f86632feb6c30ec830e3fe3 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Sun, 9 Jun 2024 10:43:34 +1000 Subject: [PATCH 0103/1531] refactor: ensure tasks selectable in unit task list --- .../unit-task-list.component.html | 23 +++++++++++-------- .../unit-task-list.component.scss | 4 ++-- .../unit-task-list.component.ts | 17 +++++++++----- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index 9b0adcaf33..8231b77aa8 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -22,31 +22,34 @@
- @if (filteredTasks.length === 0) { + @if (filteredTaskDefinitions.length === 0) {
No tasks to display
} - @for (task of filteredTasks; track task) { + @for (taskDef of filteredTaskDefinitions; track taskDef) { - @if (task) { + @if (taskDef) {
- + Selected: {{taskDef.abbreviation}} {{isSelectedTaskDefinition(taskDef)}} +
-

{{ task.name }}

+

{{ taskDef.name }}

- @if (task.isGroupTask()) { + @if (taskDef.isGroupTask()) { group } -
{{ gradeNames[task.targetGrade] }} Task
-

{{ taskForTaskDef(task).status }}

+
{{ gradeNames[taskDef.targetGrade] }} Task
+ @if (hasTasks && taskForTaskDef(taskDef)) { +

{{ taskForTaskDef(taskDef).status }}

+ }
diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss index f6aed93b2c..61c49678b4 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss @@ -1,7 +1,7 @@ @use '@angular/material' as mat; -@import '/src/theme.scss'; -@import '../../../../../../../styles/mixins/scrollable.scss'; +@import 'src/theme.scss'; +@import 'src/styles/mixins/scrollable.scss'; $my-palette: mat.define-palette($md-formatif); diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index f23c21568e..94e1d13fca 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -16,17 +16,17 @@ export class FUnitTaskListComponent implements OnInit { // What is the selected task definition @Input() selectedTaskDefinition$: BehaviorSubject; + selectedTaskDef: TaskDefinition; // @Output() selectedTask: EventEmitter = new EventEmitter(); - filteredTasks: TaskDefinition[]; // list of tasks which match the taskSearch term + filteredTaskDefinitions: TaskDefinition[]; // list of tasks which match the taskSearch term searchText: string = ''; // task search term from user input taskDefinitionNamePipe = new TaskDefinitionNamePipe(); protected gradeNames: string[] = Grade.GRADES; - selectedTaskDef: TaskDefinition; applyFilters() { - this.filteredTasks = this.taskDefinitionNamePipe.transform( + this.filteredTaskDefinitions = this.taskDefinitionNamePipe.transform( this.taskDefinitions, this.searchText, ); @@ -37,7 +37,11 @@ export class FUnitTaskListComponent implements OnInit { } public taskForTaskDef(taskDef: TaskDefinition): Task { - return this.tasks.find((task) => task.definition.id === taskDef.id); + if (!this.hasTasks || !taskDef) { + return null; + } + + return this.tasks.find((task) => task.definition.id === taskDef?.id); } ngOnInit(): void { @@ -80,7 +84,8 @@ export class FUnitTaskListComponent implements OnInit { // this.taskViewerService.setSelectedTaskDef(taskDef); } - public isSelectedTaskDefinition(taskDef: TaskDefinition) { - return this.selectedTaskDef?.id === taskDef?.id; + public isSelectedTaskDefinition(taskDef: TaskDefinition) : boolean { + console.log(taskDef?.abbreviation); + return this.selectedTaskDef?.id === taskDef?.id; } } From c97509f77e8651af89e16a3a6db0562b64ffc5f8 Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Mon, 10 Jun 2024 01:27:20 +1000 Subject: [PATCH 0104/1531] refactor: (wip) add new student experience skeleton --- angular.json | 8 +- src/app/api/models/project.ts | 75 +++-- src/app/common/footer/footer.component.html | 92 ++++-- ...s => project-progress-gauge.component.css} | 3 +- .../project-progress-gauge.component.html | 17 + ...ts => project-progress-gauge.component.ts} | 41 +-- .../project-progress.component.html | 33 -- src/app/common/services/grade.service.ts | 6 +- src/app/doubtfire-angular.module.ts | 15 +- .../project-progress-dashboard.component.html | 57 ++++ .../project-progress-dashboard.component.scss | 11 + .../project-progress-dashboard.component.ts | 48 +++ .../task-dashboard.component.html | 2 +- .../project-dashboard.component.html | 51 +-- .../staff-task-list.component.html | 302 ++++++++++-------- .../task-details-view.component.scss | 2 +- .../unit-task-list.component.html | 5 +- .../unit-task-list.component.ts | 5 +- 18 files changed, 463 insertions(+), 310 deletions(-) rename src/app/common/project-progress/{project-progress.component.css => project-progress-gauge.component.css} (96%) create mode 100644 src/app/common/project-progress/project-progress-gauge.component.html rename src/app/common/project-progress/{project-progress.component.ts => project-progress-gauge.component.ts} (65%) delete mode 100644 src/app/common/project-progress/project-progress.component.html create mode 100644 src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html create mode 100644 src/app/projects/project-progress-dashboard/project-progress-dashboard.component.scss create mode 100644 src/app/projects/project-progress-dashboard/project-progress-dashboard.component.ts diff --git a/angular.json b/angular.json index 2c0b1f0b92..a70e1e5845 100644 --- a/angular.json +++ b/angular.json @@ -10,7 +10,10 @@ "prefix": "f", "schematics": { "@schematics/angular:application": { - "strict": false + "strict": false, + "standalone": false, + "style": "scss", + "skipTests": true } }, "architect": { @@ -167,9 +170,6 @@ } }, "schematics": { - "@schematics/angular:component": { - "style": "scss" - }, "@angular-eslint/schematics:application": { "setParserOptionsProject": true }, diff --git a/src/app/api/models/project.ts b/src/app/api/models/project.ts index ca469e1698..380c62d199 100644 --- a/src/app/api/models/project.ts +++ b/src/app/api/models/project.ts @@ -1,10 +1,10 @@ -import { HttpClient } from '@angular/common/http'; -import { Entity, EntityCache, RequestOptions } from 'ngx-entity-service'; -import { Observable, tap } from 'rxjs'; -import { visualisations } from 'src/app/ajs-upgraded-providers'; -import { AppInjector } from 'src/app/app-injector'; -import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; -import { MappingFunctions } from '../services/mapping-fn'; +import {HttpClient} from '@angular/common/http'; +import {Entity, EntityCache, RequestOptions} from 'ngx-entity-service'; +import {Observable, tap} from 'rxjs'; +import {visualisations} from 'src/app/ajs-upgraded-providers'; +import {AppInjector} from 'src/app/app-injector'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {MappingFunctions} from '../services/mapping-fn'; import { Campus, Grade, @@ -21,8 +21,8 @@ import { Unit, User, } from './doubtfire-model'; -import { TaskOutcomeAlignment } from './task-outcome-alignment'; -import { AlertService } from 'src/app/common/services/alert.service'; +import {TaskOutcomeAlignment} from './task-outcome-alignment'; +import {AlertService} from 'src/app/common/services/alert.service'; export class Project extends Entity { public id: number; @@ -40,7 +40,7 @@ export class Project extends Entity { public hasPortfolio: boolean; public portfolioStatus: number; - public portfolioFiles: { kind: string; name: string; idx: number }[]; + public portfolioFiles: {kind: string; name: string; idx: number}[]; public taskStats: { key: TaskStatusEnum; @@ -48,7 +48,7 @@ export class Project extends Entity { }[]; public orderScale: number; - public burndownChartData: { key: string; values: number[] }[]; + public burndownChartData: {key: string; values: number[]}[]; public readonly taskCache: EntityCache = new EntityCache(); public readonly tutorialEnrolmentsCache: EntityCache = new EntityCache(); public readonly groupCache: EntityCache = new EntityCache(); @@ -172,7 +172,9 @@ export class Project extends Entity { } public activeTasks(): Task[] { - return this.taskCache.currentValues.filter((task) => task.definition.targetGrade <= this.targetGrade); + return this.taskCache.currentValues.filter( + (task) => task.definition.targetGrade <= this.targetGrade, + ); } public calcTopTasks() { @@ -275,16 +277,19 @@ export class Project extends Entity { return httpClient.delete(this.portfolioUrl(false)); } - public deleteFileFromPortfolio(file: { idx: any; kind: any; name: any }) { + public deleteFileFromPortfolio(file: {idx: any; kind: any; name: any}) { const httpClient = AppInjector.get(HttpClient); return httpClient - .delete(`${AppInjector.get(DoubtfireConstants).API_URL}/submission/project/${this.id}/portfolio`, { - body: { - idx: file.idx, - kind: file.kind, - name: file.name, + .delete( + `${AppInjector.get(DoubtfireConstants).API_URL}/submission/project/${this.id}/portfolio`, + { + body: { + idx: file.idx, + kind: file.kind, + name: file.name, + }, }, - }) + ) .pipe( tap(() => { this.portfolioFiles = this.portfolioFiles.filter((value) => value != file); @@ -369,7 +374,7 @@ export class Project extends Entity { tutorialService.switchTutorial(this, tutorial, !this.isEnrolledIn(tutorial)); } - public getProgressStats(): {} { + public get progressStats() { const stats = {}; this.taskStats.forEach((stat) => { @@ -380,15 +385,15 @@ export class Project extends Entity { } public refreshBurndownChartData(): void { - const result: { key: string; values: number[] }[] = []; + const result: {key: string; values: number[]}[] = []; // Setup the dictionaries to contain the keys and values // key = series name // values = array of [ x, y ] values - const projectedResults = { key: 'Projected', values: [] }; - const targetTaskResults = { key: 'Target', values: [] }; - const doneTaskResults = { key: 'To Submit', values: [] }; - const completeTaskResults = { key: 'To Complete', values: [] }; + const projectedResults = {key: 'Projected', values: []}; + const targetTaskResults = {key: 'Target', values: []}; + const doneTaskResults = {key: 'To Submit', values: []}; + const completeTaskResults = {key: 'To Complete', values: []}; result.push(targetTaskResults); result.push(projectedResults); @@ -398,15 +403,19 @@ export class Project extends Entity { // Get the weeks between start and end date as an array // dates = unit.start_date.to_date.step(unit.end_date.to_date + 1.week, step=7).to_a const endDateValue = this.unit.endDate.getTime() + MappingFunctions.weeksMs(3); - const dates = MappingFunctions.step(this.unit.startDate.getTime(), endDateValue, MappingFunctions.weeksMs(1)).map( - (val) => new Date(val), - ); + const dates = MappingFunctions.step( + this.unit.startDate.getTime(), + endDateValue, + MappingFunctions.weeksMs(1), + ).map((val) => new Date(val)); // Get the target task from the unit's task definitions const targetTasks = this.unit.taskDefinitionsForGrade(this.targetGrade); // get total value of all tasks assigned to this project - const total = targetTasks.map((td) => td.weighting).reduce((prev, current, idx, array) => prev + current, 0); + const total = targetTasks + .map((td) => td.weighting) + .reduce((prev, current, idx, array) => prev + current, 0); // exit if no tasks or no weights if (targetTasks.length === 0 || total === 0) { @@ -425,7 +434,10 @@ export class Project extends Entity { // Get the tasks currently marked as done (or ready to mark) const doneTasks = tasks.filter( - (t) => !['working_on_it', 'not_started', 'fix_and_resubmit', 'redo', 'need_help'].includes(t.status), + (t) => + !['working_on_it', 'not_started', 'fix_and_resubmit', 'redo', 'need_help'].includes( + t.status, + ), ); // last done task date) @@ -438,7 +450,8 @@ export class Project extends Entity { } // today is used to determine when to stop adding done tasks - const today = new Date().getTime() > this.unit.endDate.getTime() ? this.unit.endDate : new Date(); + const today = + new Date().getTime() > this.unit.endDate.getTime() ? this.unit.endDate : new Date(); // use weekly completion rate to determine projected progress let completionRate: number = 0; diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index 7e28c72b32..ef45ad43ec 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -1,21 +1,21 @@ @if (selectedTask?.similaritiesDetected) { -
-
-

- Similarities flagged for {{ selectedTask?.project.student.name }} -

-
+
+
+

+ Similarities flagged for {{ selectedTask?.project.student.name }} +

+
}
@@ -71,17 +71,17 @@
@if (selectedTask?.similaritiesDetected) { - + } - - @@ -141,12 +159,16 @@ file_download - {{ selectedTask?.project.targetGradeAcronym }} + {{ + selectedTask?.project.targetGradeAcronym + }}
diff --git a/src/app/common/project-progress/project-progress.component.css b/src/app/common/project-progress/project-progress-gauge.component.css similarity index 96% rename from src/app/common/project-progress/project-progress.component.css rename to src/app/common/project-progress/project-progress-gauge.component.css index db89229c2c..0755ce7a39 100644 --- a/src/app/common/project-progress/project-progress.component.css +++ b/src/app/common/project-progress/project-progress-gauge.component.css @@ -1,4 +1,5 @@ :host { display: block; -} + +} diff --git a/src/app/common/project-progress/project-progress-gauge.component.html b/src/app/common/project-progress/project-progress-gauge.component.html new file mode 100644 index 0000000000..4ccf5a81a5 --- /dev/null +++ b/src/app/common/project-progress/project-progress-gauge.component.html @@ -0,0 +1,17 @@ + + diff --git a/src/app/common/project-progress/project-progress.component.ts b/src/app/common/project-progress/project-progress-gauge.component.ts similarity index 65% rename from src/app/common/project-progress/project-progress.component.ts rename to src/app/common/project-progress/project-progress-gauge.component.ts index 025bced4f7..1cb5acfd27 100644 --- a/src/app/common/project-progress/project-progress.component.ts +++ b/src/app/common/project-progress/project-progress-gauge.component.ts @@ -1,28 +1,19 @@ -import {Component, Injector, OnInit, ViewContainerRef} from '@angular/core'; +import {Component, Injector, Input, OnInit, ViewContainerRef} from '@angular/core'; import {TooltipService} from '@swimlane/ngx-charts'; +import {Project} from 'src/app/api/models/project'; @Component({ - selector: 'f-project-progress', - templateUrl: './project-progress.component.html', - styleUrl: './project-progress.component.css', + selector: 'f-project-progress-gauge', + templateUrl: './project-progress-gauge.component.html', + styleUrl: './project-progress-gauge.component.css', }) -export class ProjectProgressComponent implements OnInit { - ngOnInit(): void { - this.chartToolTipService.injectionService.setRootViewContainer(this.viewContainerRef); - } - - constructor(private injectorObj: Injector) { - this.chartToolTipService = this.injectorObj.get(TooltipService); - this.viewContainerRef = this.injectorObj.get(ViewContainerRef); - } - private chartToolTipService: TooltipService; - readonly viewContainerRef: ViewContainerRef; +export class ProjectProgressGaugeComponent implements OnInit { + @Input() project: Project; - data = [ + protected gaugeData = [ { 'name': 'Pass', 'value': 100, - 'label': '100%', }, { 'name': 'Credit', @@ -37,8 +28,22 @@ export class ProjectProgressComponent implements OnInit { 'value': 19, }, ]; + + ngOnInit(): void { + this.chartToolTipService.injectionService.setRootViewContainer(this.viewContainerRef); + + console.log(this.project.taskStats); + } + + constructor(private injectorObj: Injector) { + this.chartToolTipService = this.injectorObj.get(TooltipService); + this.viewContainerRef = this.injectorObj.get(ViewContainerRef); + } + private chartToolTipService: TooltipService; + readonly viewContainerRef: ViewContainerRef; + smallView = [90, 90]; - view = [400, 250]; + view = [500, 500]; legend: boolean = true; legendPosition: string = 'below'; diff --git a/src/app/common/project-progress/project-progress.component.html b/src/app/common/project-progress/project-progress.component.html deleted file mode 100644 index 50fe53dbeb..0000000000 --- a/src/app/common/project-progress/project-progress.component.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - diff --git a/src/app/common/services/grade.service.ts b/src/app/common/services/grade.service.ts index d2c0ee6213..6a76e5e25c 100644 --- a/src/app/common/services/grade.service.ts +++ b/src/app/common/services/grade.service.ts @@ -8,7 +8,7 @@ export class GradeService { allGradeValues = [-1, 0, 1, 2, 3]; gradeValues = [0, 1, 2, 3]; - grades = { + public grades = { '-1': 'Fail', 0: 'Pass', 1: 'Credit', @@ -16,7 +16,7 @@ export class GradeService { 3: 'High Distinction', }; - gradeIndex = { + public gradeIndex = { Fail: -1, Pass: 0, Credit: 1, @@ -24,7 +24,7 @@ export class GradeService { 'High Distinction': 3, }; - gradeViewData = [ + public gradeViewData = [ {value: -1, viewValue: 'Fail'}, {value: 0, viewValue: 'Pass'}, {value: 1, viewValue: 'Credit'}, diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 9991e9cb33..d71e9cc731 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -15,6 +15,7 @@ import player from 'lottie-web'; import {ClipboardModule} from '@angular/cdk/clipboard'; import {DragDropModule} from '@angular/cdk/drag-drop'; import {MatToolbarModule} from '@angular/material/toolbar'; +import {MatSidenavModule} from '@angular/material/sidenav'; import {MatSelectModule} from '@angular/material/select'; import {MatButtonModule} from '@angular/material/button'; import {MatMenuModule} from '@angular/material/menu'; @@ -209,7 +210,7 @@ import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-ro import {FileDropComponent} from './common/file-drop/file-drop.component'; import {UnitTaskEditorComponent} from './units/states/edit/directives/unit-tasks-editor/unit-task-editor.component'; import {FUsersComponent} from './admin/states/users/users.component'; -import {ProjectProgressComponent} from './common/project-progress/project-progress.component'; +import {ProjectProgressGaugeComponent} from './common/project-progress/project-progress-gauge.component'; import {CreateNewUnitModal} from './admin/modals/create-new-unit-modal/create-new-unit-modal.component'; import {CreateNewUnitModalContentComponent} from './admin/modals/create-new-unit-modal/create-new-unit-modal-content.component'; import { @@ -225,9 +226,10 @@ import {FTaskDetailsViewComponent} from './units/task-viewer/directives/task-det import {FTaskSheetViewComponent} from './units/task-viewer/directives/task-sheet-view/task-sheet-view.component'; import {UnitCodeComponent} from './common/unit-code/unit-code.component'; import {GradeService} from './common/services/grade.service'; -import { UnitRootStateComponent } from './units/unit-root-state.component'; -import { TaskViewerStateComponent } from './units/task-viewer/task-viewer-state.component'; -import { ProjectRootStateComponent } from './projects/states/project-root-state.component'; +import {UnitRootStateComponent} from './units/unit-root-state.component'; +import {TaskViewerStateComponent} from './units/task-viewer/task-viewer-state.component'; +import {ProjectRootStateComponent} from './projects/states/project-root-state.component'; +import {ProjectProgressDashboardComponent} from './projects/project-progress-dashboard/project-progress-dashboard.component'; @NgModule({ // Components we declare @@ -276,6 +278,7 @@ import { ProjectRootStateComponent } from './projects/states/project-root-state. TaskCommentsViewerComponent, UserIconComponent, AudioPlayerComponent, + ProjectProgressDashboardComponent, MarkedPipe, HumanizedDatePipe, IsActiveUnitRole, @@ -330,7 +333,7 @@ import { ProjectRootStateComponent } from './projects/states/project-root-state. ProjectRootStateComponent, TaskViewerStateComponent, FUsersComponent, - ProjectProgressComponent, + ProjectProgressGaugeComponent, FTaskBadgeComponent, FUnitsComponent, ], @@ -418,6 +421,7 @@ import { ProjectRootStateComponent } from './projects/states/project-root-state. DragDropModule, ScrollingModule, MatToolbarModule, + MatSidenavModule, MatFormFieldModule, MatAutocompleteModule, MatInputModule, @@ -447,7 +451,6 @@ import { ProjectRootStateComponent } from './projects/states/project-root-state. MatExpansionModule, MatCardModule, MatGridListModule, - MatSelectModule, MatToolbarModule, MatTabsModule, UpgradeModule, diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html new file mode 100644 index 0000000000..d1c272e131 --- /dev/null +++ b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html @@ -0,0 +1,57 @@ +
+ +
+ + + +

{{ project.unit.name }}

+

{{ project.unit.description }}

+
+
+
+
+ + + +

Targetting

+ + info +
+ + + Target grade + + @for (grade of grades; track grade) { + {{ + grade.viewValue + }} + } + + + +

+
+
+
+ + +
+ + +

Your progress

+ +
+ +
+
+
+
+ + + +
diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.scss b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.scss new file mode 100644 index 0000000000..3a2b24d37b --- /dev/null +++ b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.scss @@ -0,0 +1,11 @@ +:host { + display: block; +} + +h1, +h2, +h3, +h4, +p { + color: black; +} diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.ts b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.ts new file mode 100644 index 0000000000..c9132c5209 --- /dev/null +++ b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.ts @@ -0,0 +1,48 @@ +import {Component, Input, type OnInit} from '@angular/core'; +import {BehaviorSubject, Observable} from 'rxjs'; +import {Project} from 'src/app/api/models/project'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GradeService} from 'src/app/common/services/grade.service'; + +@Component({ + selector: 'f-project-progress-dashboard', + templateUrl: './project-progress-dashboard.component.html', + styleUrl: './project-progress-dashboard.component.scss', +}) +export class ProjectProgressDashboardComponent implements OnInit { + @Input() project$: Observable; + private project: Project; + protected grades; + + constructor( + private gradeService: GradeService, + private projectService: ProjectService, + private alertService: AlertService, + ) {} + + ngOnInit(): void { + this.project$.subscribe((project) => { + this.project = project; + }); + + this.grades = this.gradeService.gradeViewData.slice(1); + + setTimeout(() => { + console.log(this.project.taskStats); + }, 3000); + } + + protected targetGradeClicked(grade: number): void { + this.project.targetGrade = grade; + this.projectService.update(this.project).subscribe({ + next: (project) => { + this.alertService.success('Target grade updated'); + }, + error: (error) => { + console.error(error); + this.alertService.error('Error updating target grade', error); + }, + }); + } +} diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html index a76c3feab4..fa43b725b3 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html @@ -1,5 +1,5 @@
- + diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html index 5af2305c8d..5207f2c725 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html @@ -1,17 +1,14 @@ -
-
- {{ project.activeTasks().length }} - {{ project.unit.taskDefinitions.length }} -
-

Selected task definition: {{ selectedTaskDefinition.abbreviation }}

-
+
+
+ @if (subs$ | async) {
} -
- - - -
- -
- -
- - - -
-
-
+ + + -
+
@if (collapsable) { - - } @if (!isTaskDefMode) { - - } @if (isTaskDefMode) { - + + } + @if (!isTaskDefMode) { + + } + @if (isTaskDefMode) { + }
@@ -140,14 +154,19 @@ - +
-
+
@if (!isNarrow) { -
- -
+
+ +
}
@@ -170,44 +191,45 @@ @if (filteredTasks) { - - - - @if (task) { -
+ + -
- - -
-

{{ task.project.student.name }}

-
- {{ task.definition.abbreviation }} - - {{ task.definition.name }} -
- -
- @if (task.hasGrade()) { -
- {{ task.gradeDesc() }} -
- } - - @if (!isTaskDefMode) { -
- - - - - + + @if (!isTaskDefMode) { +
+ + + + + +
+ } +
+
- } -
- -
- } - + } + - - - + + + }
diff --git a/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.scss b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.scss index b06c626b5a..4d2e096ff0 100644 --- a/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.scss +++ b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.scss @@ -1,6 +1,6 @@ @use '@angular/material' as mat; -@import '/src/theme.scssr'; +@import '/src/theme.scss'; $my-palette: mat.define-palette($md-formatif); diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index 8231b77aa8..0723fe581e 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -21,7 +21,7 @@
- + @if (filteredTaskDefinitions.length === 0) {
No tasks to display
} @@ -37,7 +37,6 @@ >
- Selected: {{taskDef.abbreviation}} {{isSelectedTaskDefinition(taskDef)}}

{{ taskDef.name }}

@@ -60,6 +59,6 @@

{{ taskDef.name }}

} } - +
diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index 94e1d13fca..9ff21d0c78 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -2,7 +2,7 @@ import {Component, Input, OnInit} from '@angular/core'; import {Grade} from 'src/app/api/models/grade'; import {TaskDefinition, Task} from 'src/app/api/models/doubtfire-model'; import {TaskDefinitionNamePipe} from 'src/app/common/filters/task-definition-name.pipe'; -import { BehaviorSubject } from 'rxjs'; +import {BehaviorSubject} from 'rxjs'; @Component({ selector: 'f-unit-task-list', @@ -84,8 +84,7 @@ export class FUnitTaskListComponent implements OnInit { // this.taskViewerService.setSelectedTaskDef(taskDef); } - public isSelectedTaskDefinition(taskDef: TaskDefinition) : boolean { - console.log(taskDef?.abbreviation); + public isSelectedTaskDefinition(taskDef: TaskDefinition): boolean { return this.selectedTaskDef?.id === taskDef?.id; } } From 7b9ace47132f0237bc621d3d0e45c3031e7fac05 Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Mon, 10 Jun 2024 11:25:10 +1000 Subject: [PATCH 0105/1531] feat: (wip) add name to new student experience skeleton --- .../project-progress-dashboard.component.html | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html index d1c272e131..af172d96d9 100644 --- a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html +++ b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html @@ -4,7 +4,9 @@ -

{{ project.unit.name }}

+

+ {{ project.student.nickname || project.student.firstName }}'s {{ project.unit.name }} +

{{ project.unit.description }}

@@ -38,9 +40,10 @@

Targetting

+ + Your progress + -

Your progress

-
From 2e0eb7742a1bdd69e6cda7a85fd2f6e2e92968fc Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Mon, 10 Jun 2024 12:03:05 +1000 Subject: [PATCH 0106/1531] refactor: (wip) prepare for m3 --- package-lock.json | 42 +++++++++++++++++++++--------------------- package.json | 38 +++++++++++++++++++------------------- src/styles.scss | 13 ++++++++----- 3 files changed, 48 insertions(+), 45 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9fc1598ad6..4b21a6feb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,19 +9,19 @@ "version": "8.0.9", "license": "AGPL-3.0", "dependencies": { - "@angular/animations": "^18.0.1", - "@angular/cdk": "^18.0.1", - "@angular/common": "^18.0.1", - "@angular/compiler": "^18.0.1", - "@angular/core": "^18.0.1", - "@angular/forms": "^18.0.1", - "@angular/material": "^18.0.1", - "@angular/material-moment-adapter": "^18.0.1", - "@angular/platform-browser": "^18.0.1", - "@angular/platform-browser-dynamic": "^18.0.1", - "@angular/router": "^18.0.1", - "@angular/service-worker": "^18.0.1", - "@angular/upgrade": "^18.0.1", + "@angular/animations": "^18.0.2", + "@angular/cdk": "^18.0.2", + "@angular/common": "^18.0.2", + "@angular/compiler": "^18.0.2", + "@angular/core": "^18.0.2", + "@angular/forms": "^18.0.2", + "@angular/material": "^18.0.2", + "@angular/material-moment-adapter": "^18.0.2", + "@angular/platform-browser": "^18.0.2", + "@angular/platform-browser-dynamic": "^18.0.2", + "@angular/router": "^18.0.2", + "@angular/service-worker": "^18.0.2", + "@angular/upgrade": "^18.0.2", "@ctrl/ngx-emoji-mart": "^9.2.0", "@ngneat/hotkeys": "^4.0.0", "@swimlane/ngx-charts": "^20.5.0", @@ -48,7 +48,7 @@ "angulartics-google-analytics": "0.1.4", "bootstrap": "~3.4", "bootstrap-sass": "~3.4", - "canvas-confetti": "^1.6.0", + "canvas-confetti": "^1.9", "codemirror": "5.65.0", "core-js": "^3.21.1", "d3": "3.5.17", @@ -58,8 +58,8 @@ "jquery": "2.1.4", "lodash": "~4.17", "lottie-web": "^5.12.2", - "marked": "^11.1.0", - "moment": "^2.29.4", + "marked": "^12", + "moment": "^2.30", "ng-csv": "0.2.3", "ng-file-upload": "~5.0.9", "ng-flex-layout": "^17.3.7-beta.1", @@ -77,8 +77,8 @@ "devDependencies": { "@angular-devkit/build-angular": "^18.0.2", "@angular/cli": "^18.0.2", - "@angular/compiler-cli": "^18.0.1", - "@angular/language-service": "^18.0.1", + "@angular/compiler-cli": "^18.0.2", + "@angular/language-service": "^18.0.2", "@commitlint/cli": "^16.0.1", "@commitlint/config-conventional": "^17", "@types/angular": "1.5.11", @@ -16789,9 +16789,9 @@ } }, "node_modules/marked": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz", - "integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", "bin": { "marked": "bin/marked.js" }, diff --git a/package.json b/package.json index fd8cc0068b..4aa54a248f 100644 --- a/package.json +++ b/package.json @@ -26,19 +26,19 @@ "keywords": [], "author": "", "dependencies": { - "@angular/animations": "^18.0.1", - "@angular/cdk": "^18.0.1", - "@angular/common": "^18.0.1", - "@angular/compiler": "^18.0.1", - "@angular/core": "^18.0.1", - "@angular/forms": "^18.0.1", - "@angular/material": "^18.0.1", - "@angular/material-moment-adapter": "^18.0.1", - "@angular/platform-browser": "^18.0.1", - "@angular/platform-browser-dynamic": "^18.0.1", - "@angular/router": "^18.0.1", - "@angular/service-worker": "^18.0.1", - "@angular/upgrade": "^18.0.1", + "@angular/animations": "^18.0.2", + "@angular/cdk": "^18.0.2", + "@angular/common": "^18.0.2", + "@angular/compiler": "^18.0.2", + "@angular/core": "^18.0.2", + "@angular/forms": "^18.0.2", + "@angular/material": "^18.0.2", + "@angular/material-moment-adapter": "^18.0.2", + "@angular/platform-browser": "^18.0.2", + "@angular/platform-browser-dynamic": "^18.0.2", + "@angular/router": "^18.0.2", + "@angular/service-worker": "^18.0.2", + "@angular/upgrade": "^18.0.2", "@ctrl/ngx-emoji-mart": "^9.2.0", "@ngneat/hotkeys": "^4.0.0", "@swimlane/ngx-charts": "^20.5.0", @@ -65,7 +65,7 @@ "angulartics-google-analytics": "0.1.4", "bootstrap": "~3.4", "bootstrap-sass": "~3.4", - "canvas-confetti": "^1.6.0", + "canvas-confetti": "^1.9", "codemirror": "5.65.0", "core-js": "^3.21.1", "d3": "3.5.17", @@ -75,8 +75,8 @@ "jquery": "2.1.4", "lodash": "~4.17", "lottie-web": "^5.12.2", - "marked": "^11.1.0", - "moment": "^2.29.4", + "marked": "^12", + "moment": "^2.30", "ng-csv": "0.2.3", "ng-file-upload": "~5.0.9", "ng-flex-layout": "^17.3.7-beta.1", @@ -93,9 +93,9 @@ }, "devDependencies": { "@angular-devkit/build-angular": "^18.0.2", - "@angular/compiler-cli": "^18.0.1", + "@angular/compiler-cli": "^18.0.2", "@angular/cli": "^18.0.2", - "@angular/language-service": "^18.0.1", + "@angular/language-service": "^18.0.2", "@commitlint/cli": "^16.0.1", "@commitlint/config-conventional": "^17", "@types/angular": "1.5.11", @@ -158,4 +158,4 @@ "@nx/nx-linux-x64-gnu": "^18.0", "@nx/nx-win32-x64-msvc": "^18.0" } -} \ No newline at end of file +} diff --git a/src/styles.scss b/src/styles.scss index e04a119ea4..f8ab056beb 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,7 +1,5 @@ // For more information: https://material.angular.io/guide/theming @use '@angular/material' as mat; -// @use './styles/m3-theme.scss'; - @include mat.core(); @import './theme.scss'; @@ -10,11 +8,15 @@ @tailwind components; @tailwind utilities; -// $main-view-top-padding: 30px; -// $main-view-bottom-padding: $main-view-top-padding; +$main-view-top-padding: 30px; +$main-view-bottom-padding: $main-view-top-padding; -// $main-view-max-height: calc((var(--vh, 1vh) * (100)) - 85px); +$main-view-max-height: calc((var(--vh, 1vh) * (100)) - 85px); +// This is the new Angular Material 3 theme file which we will migrate to +// @use './styles/m3-theme.scss'; + +// this is a pre-defined green palette for testing. // $theme: mat.define-theme(( // color: ( // theme-type: light, @@ -34,6 +36,7 @@ // @include mat.all-component-themes($theme); // } + .mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field .mdc-notched-outline__notch { border-right-style: hidden; From 6954ac62627e058b6a73c0e83dc8dc8a1740698d Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Tue, 11 Jun 2024 20:50:37 +1000 Subject: [PATCH 0107/1531] fix: ensure loading screen removed in sign in component --- src/app/projects/states/index/global-state.service.ts | 7 ++++++- src/app/sessions/states/sign-in/sign-in.component.ts | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/projects/states/index/global-state.service.ts b/src/app/projects/states/index/global-state.service.ts index bb730a37c8..18d77561ac 100644 --- a/src/app/projects/states/index/global-state.service.ts +++ b/src/app/projects/states/index/global-state.service.ts @@ -251,7 +251,6 @@ export class GlobalStateService implements OnDestroy { * Query the API for the units taught and studied by the current user. */ private loadUnitsAndProjects() { - this.isLoadingSubject.next(true); this.unitRoleService.query().subscribe({ next: (_unitRoles: UnitRole[]) => { // unit roles are now in the cache @@ -264,8 +263,14 @@ export class GlobalStateService implements OnDestroy { this.isLoadingSubject.next(false); }, 800); }, + error: (_response) => { + this.alerts.error('Unable to access the units you study.', 6000); + }, }); }, + error: (_response) => { + this.alerts.error('Unable to access your units.', 6000); + } }); } diff --git a/src/app/sessions/states/sign-in/sign-in.component.ts b/src/app/sessions/states/sign-in/sign-in.component.ts index f41b944018..1ac97cca73 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.ts +++ b/src/app/sessions/states/sign-in/sign-in.component.ts @@ -79,11 +79,13 @@ export class SignInComponent implements OnInit { } }); } else { + this.globalState.isLoadingSubject.next(false); // We are SSO and no credentials this.showCredentials = false; return wait.then(); } } else { + this.globalState.isLoadingSubject.next(false); this.authMethodLoaded = true; this.showCredentials = true; return wait.then(); From 729c438f7f6a988f5ff2fa4035493b5cae1c98f7 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Tue, 11 Jun 2024 20:50:37 +1000 Subject: [PATCH 0108/1531] fix: ensure loading screen removed in sign in component --- src/app/projects/states/index/global-state.service.ts | 7 ++++++- src/app/sessions/states/sign-in/sign-in.component.ts | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/projects/states/index/global-state.service.ts b/src/app/projects/states/index/global-state.service.ts index bb730a37c8..18d77561ac 100644 --- a/src/app/projects/states/index/global-state.service.ts +++ b/src/app/projects/states/index/global-state.service.ts @@ -251,7 +251,6 @@ export class GlobalStateService implements OnDestroy { * Query the API for the units taught and studied by the current user. */ private loadUnitsAndProjects() { - this.isLoadingSubject.next(true); this.unitRoleService.query().subscribe({ next: (_unitRoles: UnitRole[]) => { // unit roles are now in the cache @@ -264,8 +263,14 @@ export class GlobalStateService implements OnDestroy { this.isLoadingSubject.next(false); }, 800); }, + error: (_response) => { + this.alerts.error('Unable to access the units you study.', 6000); + }, }); }, + error: (_response) => { + this.alerts.error('Unable to access your units.', 6000); + } }); } diff --git a/src/app/sessions/states/sign-in/sign-in.component.ts b/src/app/sessions/states/sign-in/sign-in.component.ts index f41b944018..1ac97cca73 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.ts +++ b/src/app/sessions/states/sign-in/sign-in.component.ts @@ -79,11 +79,13 @@ export class SignInComponent implements OnInit { } }); } else { + this.globalState.isLoadingSubject.next(false); // We are SSO and no credentials this.showCredentials = false; return wait.then(); } } else { + this.globalState.isLoadingSubject.next(false); this.authMethodLoaded = true; this.showCredentials = true; return wait.then(); From 5def11c81fd1c1adb9a705b126e6d81cc9510c88 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 11 Jun 2024 21:55:37 +1000 Subject: [PATCH 0109/1531] refactor: remove scorm extension deny button --- .../task-comment/scorm-extension-comment.ts | 5 ----- .../scorm-extension-comment.component.html | 19 ++++++++----------- .../scorm-extension-comment.component.ts | 11 ----------- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/src/app/api/models/task-comment/scorm-extension-comment.ts b/src/app/api/models/task-comment/scorm-extension-comment.ts index 3b4dfbccb6..b8aac7909b 100644 --- a/src/app/api/models/task-comment/scorm-extension-comment.ts +++ b/src/app/api/models/task-comment/scorm-extension-comment.ts @@ -26,11 +26,6 @@ export class ScormExtensionComment extends TaskComment { ); } - public deny(): Observable { - this.granted = false; - return this.assessScormExtension(); - } - public grant(): Observable { this.granted = true; return this.assessScormExtension(); diff --git a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html index fa7c4cb39f..b0a74a991e 100644 --- a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html +++ b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html @@ -14,17 +14,14 @@ reason: {{ comment.text }}

@if (isNotStudent) { -
- - -
+ }
diff --git a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts index eb1790edd4..7585e8d7c9 100644 --- a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts @@ -39,17 +39,6 @@ export class ScormExtensionCommentComponent implements OnInit { return this.task.unit.currentUserIsStaff; } - denyExtension() { - this.comment.deny().subscribe({ - next: (tc: TaskComment) => { - this.alerts.success('Attempt request denied', 2000); - }, - error: (response) => { - this.handleError(response); - }, - }); - } - grantExtension() { this.comment.grant().subscribe({ next: (tc: TaskComment) => { From 703563c86253c60ad30d451ee2d8e0fa7ebbfabb Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 11 Jun 2024 22:20:39 +1000 Subject: [PATCH 0110/1531] feat: disable attempt button if passed and add button to review latest attempt in card --- .../task-scorm-card.component.html | 9 +++- .../task-scorm-card.component.ts | 49 ++++++++++++++++--- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html index ec385b4760..4781d88f2f 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html @@ -18,13 +18,20 @@ mat-stroked-button (click)="launchScormPlayer()" [hidden]="attemptsLeft === 0" - [disabled]="user.isStaff" + [disabled]="user.isStaff || checkIfPassed()" > launch Attempt test + - - - - +@if (isPassed) { + + @if (latestCompletedAttempt.scoreScaled === 1) { + + check + Knowledge Check Passed + + } + @if (latestCompletedAttempt.scoreScaled !== 1) { + + check + Knowledge Check Passed With Mistakes + + } + +

+ You have successfully completed this knowledge check. You can now proceed to submitting task + files. +

+
+ + + +
+} +@if (!isPassed) { + + @if (isPassed === false) { + + close + Knowledge Check Failed + + } + @if (isPassed === undefined) { + + Knowledge Check + + } + +

You have to successfully pass this knowledge check to complete the task.

+

+ You have {{ attemptsLeft !== undefined ? attemptsLeft : 'unlimited' }} attempts left to + complete this test. +

+

+ There will be an increased time delay between test attempts. First 2 attempts will not have + a time delay in between. +

+
+ + + + + +
+} diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts index 80744b104a..25fc9e479a 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts @@ -16,6 +16,7 @@ import {ScormExtensionModalService} from 'src/app/common/modals/scorm-extension- export class TaskScormCardComponent implements OnInit, OnChanges { @Input() task: Task; attemptsLeft: number; + isPassed: boolean; latestCompletedAttempt: TestAttempt; user: User; @@ -39,10 +40,13 @@ export class TaskScormCardComponent implements OnInit, OnChanges { refreshAttemptData(): void { this.attemptsLeft = undefined; - this.getAttemptsLeft(); + this.isPassed = undefined; this.latestCompletedAttempt = undefined; + + this.getAttemptsLeft(); this.testAttemptService.getLatestCompletedAttempt(this.task).subscribe((attempt) => { this.latestCompletedAttempt = attempt; + this.isPassed = attempt.successStatus; }); } @@ -57,13 +61,6 @@ export class TaskScormCardComponent implements OnInit, OnChanges { } } - checkIfPassed(): boolean { - if (this.latestCompletedAttempt) { - return this.latestCompletedAttempt.successStatus; - } - return false; - } - launchScormPlayer(): void { window.open( `#/projects/${this.task.project.id}/task_def_id/${this.task.taskDefId}/scorm-player/normal`, From eea5ac5bec09106045573c964dc373585f17777b Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Fri, 14 Jun 2024 11:02:10 +1000 Subject: [PATCH 0112/1531] chore: ensure lf file endings --- .gitattributes | 2 ++ .gitignore | 1 - .vscode/settings.json | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .gitattributes create mode 100644 .vscode/settings.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..d56abbf304 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore index 9abc43ca67..c5c729aef4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ vendor/ .sass-cache* .bundle* tmp.scss -.vscode .tscache a.env dist/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..8582900e71 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "files.eol": "\n" +} From 0fcb649a0346d78c04d179d2feccee7d920b6b53 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Fri, 14 Jun 2024 11:02:10 +1000 Subject: [PATCH 0113/1531] chore: ensure lf file endings --- .gitattributes | 2 ++ .gitignore | 1 - .vscode/settings.json | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .gitattributes create mode 100644 .vscode/settings.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..d56abbf304 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore index 9abc43ca67..c5c729aef4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ vendor/ .sass-cache* .bundle* tmp.scss -.vscode .tscache a.env dist/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..8582900e71 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "files.eol": "\n" +} From c5dd45c57fd34e8373f11d065a0cd08edef0a794 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Fri, 14 Jun 2024 11:27:05 +1000 Subject: [PATCH 0114/1531] fix: ensure tii open report alerts errors --- .../task-similarity-view.component.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.ts index 2a6739207a..c407d28b4c 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.ts @@ -18,7 +18,7 @@ export class TaskSimilarityViewComponent implements OnChanges { constructor( private taskSimilarityService: TaskSimilarityService, - private alertsService: AlertService, + private alertService: AlertService, private selectedTaskService: SelectedTaskService ) {} @@ -37,7 +37,7 @@ export class TaskSimilarityViewComponent implements OnChanges { this.taskSimilarityService .update({ taskId: similarity.task.id, id: similarity.id }, { entity: similarity }) .subscribe((_) => { - this.alertsService.success('Similarity flag updated'); + this.alertService.success('Similarity flag updated'); similarity.task.similarityFlag = similarity.task.similarityCache.currentValues .map((s) => { return s.flagged; @@ -50,8 +50,13 @@ export class TaskSimilarityViewComponent implements OnChanges { openReport(e: Event, similarity: TaskSimilarity) { e.stopPropagation(); // Open similarity report in new tab - similarity.fetchSimilarityReportUrl().subscribe((url) => { - window.open(url, '_blank'); + similarity.fetchSimilarityReportUrl().subscribe({ + next: (url) => { + window.open(url, '_blank'); + }, + error: (err) => { + this.alertService.error(`Error accessing TurnItIn: ${err}`); + }, }); } } From 456cf466bf49b86467b269ec3d6fb4e63f6a059f Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Sat, 15 Jun 2024 00:10:27 +1000 Subject: [PATCH 0115/1531] fix: fix pdf viewer for portfolios --- .../pdf-viewer/pdf-viewer.component.html | 41 +++++++--- .../common/pdf-viewer/pdf-viewer.component.ts | 11 ++- .../units/states/portfolios/portfolios.coffee | 4 +- .../states/portfolios/portfolios.tpl.html | 82 +++++++++++++++---- 4 files changed, 108 insertions(+), 30 deletions(-) diff --git a/src/app/common/pdf-viewer/pdf-viewer.component.html b/src/app/common/pdf-viewer/pdf-viewer.component.html index 232c89d5ed..87dc97c996 100644 --- a/src/app/common/pdf-viewer/pdf-viewer.component.html +++ b/src/app/common/pdf-viewer/pdf-viewer.component.html @@ -3,25 +3,44 @@
search - + - -
@if (pdfBlobUrl) { - + }
diff --git a/src/app/common/pdf-viewer/pdf-viewer.component.ts b/src/app/common/pdf-viewer/pdf-viewer.component.ts index bb2a85514e..5cd893b5a9 100644 --- a/src/app/common/pdf-viewer/pdf-viewer.component.ts +++ b/src/app/common/pdf-viewer/pdf-viewer.component.ts @@ -1,4 +1,4 @@ -import { HttpResponse } from '@angular/common/http'; +import {HttpResponse} from '@angular/common/http'; import { Component, Input, @@ -7,6 +7,8 @@ import { SimpleChanges, OnChanges, ViewChild, + OnInit, + AfterViewInit, } from '@angular/core'; import {PdfViewerComponent} from 'ng2-pdf-viewer'; import {FileDownloaderService} from '../file-downloader/file-downloader.service'; @@ -17,7 +19,7 @@ import {AlertService} from '../services/alert.service'; templateUrl: './pdf-viewer.component.html', styleUrls: ['./pdf-viewer.component.scss'], }) -export class fPdfViewerComponent implements OnDestroy, OnChanges { +export class fPdfViewerComponent implements OnDestroy, OnChanges, AfterViewInit { private _pdfUrl: string; public pdfBlobUrl: string; @Input() pdfUrl: string; @@ -38,6 +40,11 @@ export class fPdfViewerComponent implements OnDestroy, OnChanges { } } + ngAfterViewInit(): void { + console.log("pdfUrl"); + console.log(this.pdfUrl); + } + ngOnChanges(changes: SimpleChanges): void { this.pdfUrlChanges(changes.pdfUrl.currentValue); } diff --git a/src/app/units/states/portfolios/portfolios.coffee b/src/app/units/states/portfolios/portfolios.coffee index 7e745b33d1..41d0b60797 100644 --- a/src/app/units/states/portfolios/portfolios.coffee +++ b/src/app/units/states/portfolios/portfolios.coffee @@ -122,7 +122,9 @@ angular.module('doubtfire.units.states.portfolios', []) $scope.selectedStudent = student $scope.project = null newProjectService.loadProject(student, $scope.unit).subscribe({ - next: (project) -> $scope.project = project + next: (project) -> + $scope.project = project + $scope.project.preloadedUrl = $scope.project.portfolioUrl() error: (message) -> alertService.error( message, 6000) }) ) diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html index 075680654c..2974d0719a 100644 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ b/src/app/units/states/portfolios/portfolios.tpl.html @@ -27,7 +27,11 @@

Mark Portfolios

>
@@ -39,7 +43,11 @@

Mark Portfolios

-

No portfolios found

- +
@@ -172,7 +210,9 @@

Mark Portfolios

- + @@ -237,7 +277,13 @@

Review Portfolio of {{selectedStudent.student.name}}

No Portfolio Submitted

- +
+ + +
@@ -260,8 +306,12 @@

Grade for {{selectedStudent.student.name}}

ng-class="{'no-rationale': project.gradeRationale == null}" ng-hide="editingRationale" > - -
+ +
Click to add one
From 93b0017c40823038807d0a555983f5c3bfe78ce8 Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Sat, 15 Jun 2024 00:25:41 +1000 Subject: [PATCH 0116/1531] Angular CLI update for packages - @angular/core@18, @angular/cli@18 --- package-lock.json | 811 +++++++++++++++++++++++++++++----------------- package.json | 28 +- 2 files changed, 535 insertions(+), 304 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93bb789c23..085f5d6307 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,20 +9,20 @@ "version": "8.0.9", "license": "AGPL-3.0", "dependencies": { - "@angular/animations": "^18.0.1", + "@angular/animations": "^18.0.3", "@angular/cdk": "^18.0.1", - "@angular/cli": "^18.0.2", - "@angular/common": "^18.0.1", - "@angular/compiler": "^18.0.1", - "@angular/core": "^18.0.1", - "@angular/forms": "^18.0.1", + "@angular/cli": "^18.0.4", + "@angular/common": "^18.0.3", + "@angular/compiler": "^18.0.3", + "@angular/core": "^18.0.3", + "@angular/forms": "^18.0.3", "@angular/material": "^18.0.1", "@angular/material-moment-adapter": "^18.0.1", - "@angular/platform-browser": "^18.0.1", - "@angular/platform-browser-dynamic": "^18.0.1", - "@angular/router": "^18.0.1", - "@angular/service-worker": "^18.0.1", - "@angular/upgrade": "^18.0.1", + "@angular/platform-browser": "^18.0.3", + "@angular/platform-browser-dynamic": "^18.0.3", + "@angular/router": "^18.0.3", + "@angular/service-worker": "^18.0.3", + "@angular/upgrade": "^18.0.3", "@ctrl/ngx-emoji-mart": "^9.2.0", "@ngneat/hotkeys": "^4.0.0", "@uirouter/angular": "^13.0", @@ -75,14 +75,14 @@ "zone.js": "~0.14" }, "devDependencies": { - "@angular-devkit/build-angular": "^18.0.2", + "@angular-devkit/build-angular": "^18.0.4", "@angular-eslint/builder": "^17.3.0", "@angular-eslint/eslint-plugin": "^17.3.0", "@angular-eslint/eslint-plugin-template": "^17.3.0", "@angular-eslint/schematics": "^17.3.0", "@angular-eslint/template-parser": "^17.3.0", - "@angular/compiler-cli": "^18.0.1", - "@angular/language-service": "^18.0.1", + "@angular/compiler-cli": "^18.0.3", + "@angular/language-service": "^18.0.3", "@commitlint/cli": "^16.0.1", "@commitlint/config-conventional": "^17", "@types/angular": "1.5.11", @@ -180,11 +180,11 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1800.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1800.2.tgz", - "integrity": "sha512-PX7lCTAqWe9C40+fie+DAc8vhpGA+JgZKWWrMHUTV/iZx8RXx2X4xGQsqYu36p4i3MSfQdbn+0xLWGmjScPVOQ==", + "version": "0.1800.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1800.4.tgz", + "integrity": "sha512-82TKhYnSO8aGIBo5TxPtyUQnZFcbV+qB2bIIYOAKsJgxAVxLeFD6QA6gTmHOZPXw5pBEPUO/+PUwq+Uk5xesgw==", "dependencies": { - "@angular-devkit/core": "18.0.2", + "@angular-devkit/core": "18.0.4", "rxjs": "7.8.1" }, "engines": { @@ -202,16 +202,16 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.0.2.tgz", - "integrity": "sha512-cQkTx7XaIPj6+DXo6wZmO4iY0hOOfPDnSN/+m84XpBW0tuPGxH7Z9B6wV+Uwcpm9HGPqzRA7VZyPsqbK860b0Q==", + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.0.4.tgz", + "integrity": "sha512-lFu1NDEUPIUxY+CmZJ3JspqVZDesrvdae5RbqQXCl87RfSy+ZDIa7rOtQxyBQtt2BuQIB9pWQSzCMii5kTHd6w==", "dev": true, "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1800.2", - "@angular-devkit/build-webpack": "0.1800.2", - "@angular-devkit/core": "18.0.2", - "@angular/build": "18.0.2", + "@angular-devkit/architect": "0.1800.4", + "@angular-devkit/build-webpack": "0.1800.4", + "@angular-devkit/core": "18.0.4", + "@angular/build": "18.0.4", "@babel/core": "7.24.5", "@babel/generator": "7.24.5", "@babel/helper-annotate-as-pure": "7.22.5", @@ -222,7 +222,7 @@ "@babel/preset-env": "7.24.5", "@babel/runtime": "7.24.5", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "18.0.2", + "@ngtools/webpack": "18.0.4", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.19", @@ -441,12 +441,12 @@ } }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1800.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1800.2.tgz", - "integrity": "sha512-CbTURBhZWzx+5KewS2Nkqy2rwBTFgDCvUwONGWuy1K68+85vOWUKqjkfvriHA+JkWN03w7FzWEtTfcOg0EzYkw==", + "version": "0.1800.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1800.4.tgz", + "integrity": "sha512-EtWyWH3Hb7Rh8u0Jb4cWJKRxlqiUo4qhHKjU+62E8XplWlajbuld3ltL50a3t8lkZQYYgl7nPt53E5kM/zFVrw==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1800.2", + "@angular-devkit/architect": "0.1800.4", "rxjs": "7.8.1" }, "engines": { @@ -469,9 +469,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.0.2.tgz", - "integrity": "sha512-QXcEdfmODc0rKblBerk30yw70fypIkFm6gQBLJgsshpwc+TMA+fuMLcPQebOTzKLtD2tNUkk/7SrWPQIGqeXaA==", + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.0.4.tgz", + "integrity": "sha512-8vYvJ5FF2NjFUia00hv8KWakOjOZ+09PbnNqd+lntJBekIg1lHDOF/vNMlVHtU5LiE1aNi9P/69/VXTckPfU9g==", "dependencies": { "ajv": "8.13.0", "ajv-formats": "3.0.1", @@ -519,11 +519,11 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.0.2.tgz", - "integrity": "sha512-G9yGcoB67sH0eRNWoiQWNn2KwiI7sDasVscYPGKf1yo7JRiXmzX/LpfKRPsZTl+Bs0FItnwDInsqgMisK89/6g==", + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.0.4.tgz", + "integrity": "sha512-hCHmuu/Z1teOQPx1AMJa/gcK6depk+XgU5dIpEvflC+ApW3hglNe2QKaqajDZ+34s+PKAVWa86M8IOV7o/mHuA==", "dependencies": { - "@angular-devkit/core": "18.0.2", + "@angular-devkit/core": "18.0.4", "jsonc-parser": "3.2.1", "magic-string": "0.30.10", "ora": "5.4.1", @@ -643,27 +643,27 @@ } }, "node_modules/@angular/animations": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.0.1.tgz", - "integrity": "sha512-QAY/oxfuFY2Bjr3foniWlLAiddXHu8879lZvXHt1NVOsiav+vD15IEEQsnuQbJPy/EHEnAlUh9UptB4zQIBp/Q==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.0.3.tgz", + "integrity": "sha512-Wlll6y7euIXYsOHpTh0hvVTBs7lVnbKDHiyd4Dz7kAMSeE2zyQo6OcRN+FFH3GH9BUi5UooAICNX8dJDfps6Mw==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.0.1" + "@angular/core": "18.0.3" } }, "node_modules/@angular/build": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.0.2.tgz", - "integrity": "sha512-iPPHdAJ3LiR8t/+39xjvrqMWcTmRrfphzKxXoIVDcswQjVQIk00EYuxinC6EVa7dSKDl1thk1MeCNZ9DIjaAvQ==", + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.0.4.tgz", + "integrity": "sha512-70HQQnbCOXFT5F3ROyWNNfS9A63Fzts5ANJKJY1MJLrn+dgNEG7jdIWjTtvohL3RZz97rlzSq3qRZnfxqf1lsQ==", "dev": true, "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1800.2", + "@angular-devkit/architect": "0.1800.4", "@babel/core": "7.24.5", "@babel/helper-annotate-as-pure": "7.22.5", "@babel/helper-split-export-declaration": "7.24.5", @@ -798,14 +798,14 @@ } }, "node_modules/@angular/cli": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.0.2.tgz", - "integrity": "sha512-shrxMD1bcWWh7WpBN3KTV+Lt8E62gURSUFhs6kdGLepMDif8LPAv45+hpt8SBU9VfQuL6AHa4cW8uDL9BKGlYA==", - "dependencies": { - "@angular-devkit/architect": "0.1800.2", - "@angular-devkit/core": "18.0.2", - "@angular-devkit/schematics": "18.0.2", - "@schematics/angular": "18.0.2", + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.0.4.tgz", + "integrity": "sha512-i7DLVIc4HN0CFZZKbEeVeQSADRG1Dt2CwXh/wTUzglRLu/tE7Q+WMrqJ2+lGTT2edZp2KKysM4Gxp+ATAzP8AQ==", + "dependencies": { + "@angular-devkit/architect": "0.1800.4", + "@angular-devkit/core": "18.0.4", + "@angular-devkit/schematics": "18.0.4", + "@schematics/angular": "18.0.4", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.2", @@ -841,32 +841,32 @@ } }, "node_modules/@angular/common": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.0.1.tgz", - "integrity": "sha512-iADQC5m4fvk+VNXEoU1KR93b0eG218/GuNdzUNVJHcjxdFxPshKk5fiaGSosUCxXPRQOxDKzmS9EDang87E/Ew==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.0.3.tgz", + "integrity": "sha512-lmT9QbWHduqzpsB0osQFHeSwvQB1iUeNwTVUyMtcs6i46l4qOPtAt2/9DvHUWEUp01EBDxyi385ZI3vD+FHH/w==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.0.1", + "@angular/core": "18.0.3", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.0.1.tgz", - "integrity": "sha512-zyG/ifCtN0drAuwz0oV6LtzTiDREsM1Ay7eJW9wTvp3NCv06goHLtHXX12eFfZQWJViBv924lyRDSWdZN7r3GQ==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.0.3.tgz", + "integrity": "sha512-wrXxgBsZX4yTrj/oZ8PDGmvhqj9S2TZfcuivaUitprNC2uBWTVb1UcOS45Qw9YlLB0sYa2AmBudICDqYpb8lfw==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.0.1" + "@angular/core": "18.0.3" }, "peerDependenciesMeta": { "@angular/core": { @@ -875,12 +875,12 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.0.1.tgz", - "integrity": "sha512-Aoz70+/o8R2lG2EGDAYbj6yu2B7kqa/9loYEwG0fECJTtXoRBP+bEGpUxMmxOb59tMDnbIhBHmNPPEQVTXvgSQ==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.0.3.tgz", + "integrity": "sha512-mxwQEeP94YBM6C9A2YfkV7ug1sHgh0fU/TSBpQcm5ni4cZiVPu6q/+Ft7hyFTKe2p3tKQme33+xVjsWhtOCx0A==", "dev": true, "dependencies": { - "@babel/core": "7.24.4", + "@babel/core": "7.24.7", "@jridgewell/sourcemap-codec": "^1.4.14", "chokidar": "^3.0.0", "convert-source-map": "^1.5.1", @@ -895,22 +895,22 @@ "ngcc": "bundles/ngcc/index.js" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.0.1", + "@angular/compiler": "18.0.3", "typescript": ">=5.4 <5.5" } }, "node_modules/@angular/core": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.0.1.tgz", - "integrity": "sha512-Db1livvugoLdLsWww5IqUS5v+yUN7/5Rj0trZv9BgxIuoNtoipfLqKHwZWpumH3yI5Ucu+UH9zZ1mlGyF0Kexw==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.0.3.tgz", + "integrity": "sha512-376hijhEqNpeA+qKncpVTIaZXRdBT6RctEBnFhJ2l57aHPH5S3oaSBQu1k3TEi07FlKOD4XF1+NzX9dvdup1eg==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { "rxjs": "^6.5.3 || ^7.4.0", @@ -918,29 +918,29 @@ } }, "node_modules/@angular/forms": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.0.1.tgz", - "integrity": "sha512-j1nUzwnZHO/BRXK0joQbAV10JWxeRVKmPzIaDulY2o28Er1jVKyw2T8EwI+xSvBbAqyJyaAd+ysWUhm3FfH+GA==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.0.3.tgz", + "integrity": "sha512-+CjDiooUi5FkTP3YQmdO8YRbjZicgLGZonvCdz3mSucLrTY6w3oBocNs6+Kc7fLuO1NKSkFmAfYApBwK3fKBMg==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.0.1", - "@angular/core": "18.0.1", - "@angular/platform-browser": "18.0.1", + "@angular/common": "18.0.3", + "@angular/core": "18.0.3", + "@angular/platform-browser": "18.0.3", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.0.1.tgz", - "integrity": "sha512-T4ILrLJTnredemIDxkKiL0pD0OZFzXwX6tn/nem2RG9aV5UQWqitOjw1RNuWDbsNXX6vRZsL/nw9cwDpeZhebQ==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.0.3.tgz", + "integrity": "sha512-urENnMjhSO4Jia7CnbchqN236dOIU6TC3CazwsQoj1Odch9x+iSFkx9Y0jXsiR5r/suK4uqKpK5N8MJ1PxDG1g==", "dev": true, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" } }, "node_modules/@angular/material": { @@ -1022,19 +1022,19 @@ } }, "node_modules/@angular/platform-browser": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.0.1.tgz", - "integrity": "sha512-rQUsOxZxiwSPvyHdne60IKIGsvFoVc1rO4mDyXU+9sCCLmPKHzNyEzp7vybTZeiqa3k6v3sV/bfHWwrRzmvenw==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.0.3.tgz", + "integrity": "sha512-1fl/oJOca8BLxLxN0EjwxQZ3xzn3PCCN96ytM54bjdEMiELz+0AcQe5GNKcVjXlwMkibRLl1BP5GIdvnQYqJRA==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "18.0.1", - "@angular/common": "18.0.1", - "@angular/core": "18.0.1" + "@angular/animations": "18.0.3", + "@angular/common": "18.0.3", + "@angular/core": "18.0.3" }, "peerDependenciesMeta": { "@angular/animations": { @@ -1043,43 +1043,43 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.0.1.tgz", - "integrity": "sha512-lzjq7HjigGxO5oh5Sw0Vxa3mAVidYHpHFQr46/OSl9T5jLpStcjEqK0xcfQz9bf2hV+0qFfMqmd2k0XQl7feqg==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.0.3.tgz", + "integrity": "sha512-+kHMn7P552YKk1gkVQNO1QXzHVaIeFiVa1rV1MNvX4DvumKT3puknx1SzcmtxZTX+9ee22OuPuyLNSAKREDAQQ==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.0.1", - "@angular/compiler": "18.0.1", - "@angular/core": "18.0.1", - "@angular/platform-browser": "18.0.1" + "@angular/common": "18.0.3", + "@angular/compiler": "18.0.3", + "@angular/core": "18.0.3", + "@angular/platform-browser": "18.0.3" } }, "node_modules/@angular/router": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.0.1.tgz", - "integrity": "sha512-PapdvfATjRZI0cJ/RH8n/ixHDHa4HIBaOMwhgU73InU9t6NIhBXg6aRECYV2qGt7NtpLYSHmG5Z1Ws86rm5Tyw==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.0.3.tgz", + "integrity": "sha512-/cglLev0USxUNMc4M+EBFGrqw1EpKq87LUJL3+0Ztr012sVSeOU38ad41fs6pPcMBePBDZIw7KmSXypvUJJFMA==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.0.1", - "@angular/core": "18.0.1", - "@angular/platform-browser": "18.0.1", + "@angular/common": "18.0.3", + "@angular/core": "18.0.3", + "@angular/platform-browser": "18.0.3", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/service-worker": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-18.0.1.tgz", - "integrity": "sha512-jTYAeBUg1/4RtQgYerETn3EmOjZnjlhoJ4tXwk25LDEbqzA1HoNjL1R1ifC6sEX3zyOL1SEXp7sMSB1mqq3fJw==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-18.0.3.tgz", + "integrity": "sha512-/8BXh8VxkIAmdl6ftBUh2may6GRGANesvQor9yqH0ddCUpYeIafqqbwIMgHqxe4PJ3ApSkO2zcnXgoUZHL0a/A==", "dependencies": { "tslib": "^2.3.0" }, @@ -1087,37 +1087,37 @@ "ngsw-config": "ngsw-config.js" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.0.1", - "@angular/core": "18.0.1" + "@angular/common": "18.0.3", + "@angular/core": "18.0.3" } }, "node_modules/@angular/upgrade": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@angular/upgrade/-/upgrade-18.0.1.tgz", - "integrity": "sha512-xNd97cvtT6o6bGqBeYuoywaBTejPU7iVUS+WhNwUCvsaTnbFD4i6ySNtn3ZBThCaBxfa6+TKq9v/va4Tp8yUCA==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@angular/upgrade/-/upgrade-18.0.3.tgz", + "integrity": "sha512-zGTzS945PO/PmHNfTziFAMyPjMHkO2D5Ip8RRPTSAk0n30qgr9BCvf6Rm1OXcbwgmns2vRLsvvytRV/XD7FN2g==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^18.13.0 || >=20.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.0.1", - "@angular/core": "18.0.1", - "@angular/platform-browser": "18.0.1", - "@angular/platform-browser-dynamic": "18.0.1" + "@angular/compiler": "18.0.3", + "@angular/core": "18.0.3", + "@angular/platform-browser": "18.0.3", + "@angular/platform-browser-dynamic": "18.0.3" } }, "node_modules/@babel/code-frame": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", - "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.24.6", + "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" }, "engines": { @@ -1125,30 +1125,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz", - "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -1163,6 +1163,21 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/@babel/generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/core/node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -1218,13 +1233,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", - "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.24.6", - "@babel/helper-validator-option": "^7.24.6", + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -1353,34 +1368,37 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", - "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", - "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dev": true, "dependencies": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", - "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dev": true, "dependencies": { - "@babel/types": "^7.24.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1399,28 +1417,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", - "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.6" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", - "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-module-imports": "^7.24.6", - "@babel/helper-simple-access": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1430,12 +1449,12 @@ } }, "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", - "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1509,12 +1528,13 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", - "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, "dependencies": { - "@babel/types": "^7.24.6" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1545,27 +1565,27 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", - "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", - "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", - "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1586,26 +1606,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", - "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", "dev": true, "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", - "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -1615,9 +1634,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", - "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -2910,33 +2929,33 @@ } }, "node_modules/@babel/template": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", - "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", - "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/types": "^7.24.5", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2944,14 +2963,41 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", - "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6", + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -5335,9 +5381,9 @@ } }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", - "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", "cpu": [ "arm64" ], @@ -5348,9 +5394,9 @@ ] }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz", - "integrity": "sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", "cpu": [ "x64" ], @@ -5361,9 +5407,9 @@ ] }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz", - "integrity": "sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", "cpu": [ "arm" ], @@ -5374,9 +5420,9 @@ ] }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz", - "integrity": "sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", "cpu": [ "arm64" ], @@ -5387,9 +5433,9 @@ ] }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz", - "integrity": "sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", "cpu": [ "x64" ], @@ -5400,9 +5446,9 @@ ] }, "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz", - "integrity": "sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", "cpu": [ "x64" ], @@ -5421,9 +5467,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.0.2.tgz", - "integrity": "sha512-I+ZNFGBnykUWBwGPCXy6m9R2fIX/ovnAUHylvThYd/M+FUfc+Z/3DpKEUBYIOLVCLNZR5nuK0t9QLlazYhWFgg==", + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.0.4.tgz", + "integrity": "sha512-eWQkAuHEnLme01Ey4Z0FoG6upJHYhnJfsCTBnyEB2LTfdyBUk+PC0gwPXInK8oltWjFfiMnCwxrUQvQsvPW7Hg==", "dev": true, "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0", @@ -5897,10 +5943,88 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz", - "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", "cpu": [ "arm64" ], @@ -5911,9 +6035,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz", - "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", "cpu": [ "arm64" ], @@ -5923,6 +6047,110 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@scarf/scarf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.3.0.tgz", @@ -5930,12 +6158,12 @@ "hasInstallScript": true }, "node_modules/@schematics/angular": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.0.2.tgz", - "integrity": "sha512-qkJs1oxHtneJ6QxDKpxNyneXGDM9SKVj+Bgi8xUAU3FEzpsYmE/aW3MfwYHOZl0pDBO8c2raqLvlyl3dGP6/Gg==", + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.0.4.tgz", + "integrity": "sha512-fN4whuym9ZmcQFdTfwLZr4j+NcZ4LzbdLk8XYrYdxt1z8c9ujs5LqJYn0LYc3UWiYl7z2RVc9NOxzNrkiXdwlw==", "dependencies": { - "@angular-devkit/core": "18.0.2", - "@angular-devkit/schematics": "18.0.2", + "@angular-devkit/core": "18.0.4", + "@angular-devkit/schematics": "18.0.4", "jsonc-parser": "3.2.1" }, "engines": { @@ -18010,33 +18238,36 @@ } }, "node_modules/msgpackr-extract": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", - "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", "dev": true, "hasInstallScript": true, "optional": true, "dependencies": { - "node-gyp-build-optional-packages": "5.0.7" + "node-gyp-build-optional-packages": "5.2.2" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2" + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" } }, "node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", - "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", "dev": true, "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", @@ -22052,9 +22283,9 @@ } }, "node_modules/rollup": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz", - "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -22067,22 +22298,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.17.2", - "@rollup/rollup-android-arm64": "4.17.2", - "@rollup/rollup-darwin-arm64": "4.17.2", - "@rollup/rollup-darwin-x64": "4.17.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.17.2", - "@rollup/rollup-linux-arm-musleabihf": "4.17.2", - "@rollup/rollup-linux-arm64-gnu": "4.17.2", - "@rollup/rollup-linux-arm64-musl": "4.17.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2", - "@rollup/rollup-linux-riscv64-gnu": "4.17.2", - "@rollup/rollup-linux-s390x-gnu": "4.17.2", - "@rollup/rollup-linux-x64-gnu": "4.17.2", - "@rollup/rollup-linux-x64-musl": "4.17.2", - "@rollup/rollup-win32-arm64-msvc": "4.17.2", - "@rollup/rollup-win32-ia32-msvc": "4.17.2", - "@rollup/rollup-win32-x64-msvc": "4.17.2", + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", "fsevents": "~2.3.2" } }, @@ -25962,9 +26193,9 @@ } }, "node_modules/webpack-dev-server/node_modules/jackspeak": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz", - "integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" diff --git a/package.json b/package.json index cefc596960..7431b2a58c 100644 --- a/package.json +++ b/package.json @@ -26,20 +26,20 @@ "keywords": [], "author": "", "dependencies": { - "@angular/animations": "^18.0.1", + "@angular/animations": "^18.0.3", "@angular/cdk": "^18.0.1", - "@angular/cli": "^18.0.2", - "@angular/common": "^18.0.1", - "@angular/compiler": "^18.0.1", - "@angular/core": "^18.0.1", - "@angular/forms": "^18.0.1", + "@angular/cli": "^18.0.4", + "@angular/common": "^18.0.3", + "@angular/compiler": "^18.0.3", + "@angular/core": "^18.0.3", + "@angular/forms": "^18.0.3", "@angular/material": "^18.0.1", "@angular/material-moment-adapter": "^18.0.1", - "@angular/platform-browser": "^18.0.1", - "@angular/platform-browser-dynamic": "^18.0.1", - "@angular/router": "^18.0.1", - "@angular/service-worker": "^18.0.1", - "@angular/upgrade": "^18.0.1", + "@angular/platform-browser": "^18.0.3", + "@angular/platform-browser-dynamic": "^18.0.3", + "@angular/router": "^18.0.3", + "@angular/service-worker": "^18.0.3", + "@angular/upgrade": "^18.0.3", "@ctrl/ngx-emoji-mart": "^9.2.0", "@ngneat/hotkeys": "^4.0.0", "@uirouter/angular": "^13.0", @@ -92,14 +92,14 @@ "zone.js": "~0.14" }, "devDependencies": { - "@angular-devkit/build-angular": "^18.0.2", + "@angular-devkit/build-angular": "^18.0.4", "@angular-eslint/builder": "^17.3.0", "@angular-eslint/eslint-plugin": "^17.3.0", "@angular-eslint/eslint-plugin-template": "^17.3.0", "@angular-eslint/schematics": "^17.3.0", "@angular-eslint/template-parser": "^17.3.0", - "@angular/compiler-cli": "^18.0.1", - "@angular/language-service": "^18.0.1", + "@angular/compiler-cli": "^18.0.3", + "@angular/language-service": "^18.0.3", "@commitlint/cli": "^16.0.1", "@commitlint/config-conventional": "^17", "@types/angular": "1.5.11", From e1094bcf2468a939d6186dc769621a8dba5cfa0f Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Sat, 15 Jun 2024 00:57:06 +1000 Subject: [PATCH 0117/1531] build: upgrade eslint packages and flow --- .eslintrc.json | 91 - angular.json | 6 +- eslint.config.js | 62 + package-lock.json | 1812 ++++++++--------- package.json | 33 +- .../task-definition-upload.component.html | 59 +- .../task-definition-upload.component.ts | 12 +- .../states/portfolios/portfolios.tpl.html | 8 +- 8 files changed, 984 insertions(+), 1099 deletions(-) delete mode 100644 .eslintrc.json create mode 100644 eslint.config.js diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 9bf5e49a86..0000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "root": true, - "overrides": [ - { - "files": ["*.ts"], - "parserOptions": { - "project": ["tsconfig.*?.json"], - "createDefaultProgram": true - }, - "plugins": ["@typescript-eslint"], - "extends": [ - "plugin:@angular-eslint/recommended", - "plugin:@typescript-eslint/recommended", - "plugin:prettier/recommended" - ], - "env": { - "browser": true, - "jasmine": true - }, - "rules": { - "@typescript-eslint/no-unused-vars": [ - "warn", - { - "args": "all", - "argsIgnorePattern": "^_", - "caughtErrors": "all", - "caughtErrorsIgnorePattern": "^_", - "destructuredArrayIgnorePattern": "^_", - "varsIgnorePattern": "^_", - "ignoreRestSiblings": true - } - ], - "@angular-eslint/no-empty-lifecycle-method": "warn", - "@angular-eslint/component-class-suffix": "warn", - "@angular-eslint/no-output-on-prefix": "warn", - "@typescript-eslint/no-inferrable-types": "off", - "@angular-eslint/directive-selector": [ - "warn", - { - "type": "attribute", - "prefix": "f", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "warn", - { - "type": "element", - "prefix": "f", - "style": "kebab-case" - } - ], - "@typescript-eslint/ban-types": "warn", - "@typescript-eslint/no-empty-function": "warn", - "@typescript-eslint/no-inferrable-types": "off", - "@typescript-eslint/no-this-alias": "warn", - "no-dupe-class-members": "warn", - "no-prototype-builtins": "warn", - "no-unused-vars": "off", - "no-useless-escape": "warn", - "no-var": "warn", - "quotes": [ - "warn", - "single", - { - "allowTemplateLiterals": true - } - ], - "prefer-const": "warn", - "prettier/prettier": "warn" - } - }, - { - "files": ["*.component.html"], - "extends": ["plugin:@angular-eslint/template/recommended", "plugin:prettier/recommended"], - "rules": { - "max-len": [ - "warn", - { - "code": 140 - } - ], - "prettier/prettier": "warn" - } - }, - { - "files": ["*.component.ts"], - "extends": ["plugin:@angular-eslint/template/process-inline-templates"] - } - ] -} diff --git a/angular.json b/angular.json index 2c0b1f0b92..278de25b84 100644 --- a/angular.json +++ b/angular.json @@ -20,7 +20,9 @@ "outputPath": "dist", "index": "build/index.html", "browser": "src/main.ts", - "polyfills": ["src/polyfills.ts"], + "polyfills": [ + "src/polyfills.ts" + ], "tsConfig": "src/tsconfig.app.json", "assets": [ "src/assets", @@ -150,7 +152,7 @@ "options": { "lintFilePatterns": [ "src/**/*.ts", - "src/**/*.component.html" + "src/**/*.html" ] } }, diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000000..a327c5d852 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,62 @@ +// @ts-check + +// Allows us to bring in the recommended core rules from eslint itself +const eslint = require('@eslint/js'); + +// Allows us to use the typed utility for our config, and to bring in the recommended rules for TypeScript projects from typescript-eslint +const tseslint = require('typescript-eslint'); + +// Allows us to bring in the recommended rules for Angular projects from angular-eslint +const angular = require('angular-eslint'); + +// Export our config array, which is composed together thanks to the typed utility function from typescript-eslint +module.exports = tseslint.config( + { + // Everything in this config object targets our TypeScript files (Components, Directives, Pipes etc) + files: ['**/*.ts'], + extends: [ + // Apply the recommended core rules + eslint.configs.recommended, + // Apply the recommended TypeScript rules + ...tseslint.configs.recommended, + // Optionally apply stylistic rules from typescript-eslint that improve code consistency + ...tseslint.configs.stylistic, + // Apply the recommended Angular rules + ...angular.configs.tsRecommended, + ], + // Set the custom processor which will allow us to have our inline Component templates extracted + // and treated as if they are HTML files (and therefore have the .html config below applied to them) + processor: angular.processInlineTemplates, + // Override specific rules for TypeScript files (these will take priority over the extended configs above) + rules: { + '@angular-eslint/directive-selector': [ + 'error', + { + type: 'attribute', + prefix: 'f', + style: 'camelCase', + }, + ], + '@angular-eslint/component-selector': [ + 'error', + { + type: 'element', + prefix: 'f', + style: 'kebab-case', + }, + ], + }, + }, + { + // Everything in this config object targets our HTML files (external templates, + // and inline templates as long as we have the `processor` set on our TypeScript config above) + files: ['**/*component.html'], + extends: [ + // Apply the recommended Angular template rules + ...angular.configs.templateRecommended, + // Apply the Angular template rules which focus on accessibility of our apps + ...angular.configs.templateAccessibility, + ], + rules: {}, + }, +); diff --git a/package-lock.json b/package-lock.json index 085f5d6307..8702239d8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,13 +25,9 @@ "@angular/upgrade": "^18.0.3", "@ctrl/ngx-emoji-mart": "^9.2.0", "@ngneat/hotkeys": "^4.0.0", - "@uirouter/angular": "^13.0", - "@uirouter/angular-hybrid": "^17.1.0", - "@uirouter/angularjs": "^1.0.30", - "@uirouter/core": "^6.1.0", - "@uirouter/rx": "^1.0.0", "angular": "1.5.11", "angular-cookies": "1.5.11", + "angular-eslint": "^18.0.1", "angular-file-upload": "~1", "angular-filter": "0.5.17", "angular-local-storage": "0.7.1", @@ -65,22 +61,23 @@ "ng-flex-layout": "^17.3.7-beta.1", "ng2-pdf-viewer": "^10.2", "ngx-bootstrap": "^6.1.0", - "ngx-entity-service": "^0.0.38", + "ngx-entity-service": "^0.0.39", "ngx-lottie": "^11.0.2", "nvd3": "1.8.6", "rxjs": "~7.4.0", "ts-md5": "^1.3.1", "tslib": "^2.6.2", + "typescript-eslint": "^7.13.0", "underscore.string": "2.3.3", "zone.js": "~0.14" }, "devDependencies": { "@angular-devkit/build-angular": "^18.0.4", - "@angular-eslint/builder": "^17.3.0", - "@angular-eslint/eslint-plugin": "^17.3.0", - "@angular-eslint/eslint-plugin-template": "^17.3.0", - "@angular-eslint/schematics": "^17.3.0", - "@angular-eslint/template-parser": "^17.3.0", + "@angular-eslint/builder": "18.0.1", + "@angular-eslint/eslint-plugin": "18.0.1", + "@angular-eslint/eslint-plugin-template": "18.0.1", + "@angular-eslint/schematics": "18.0.1", + "@angular-eslint/template-parser": "18.0.1", "@angular/compiler-cli": "^18.0.3", "@angular/language-service": "^18.0.3", "@commitlint/cli": "^16.0.1", @@ -93,17 +90,12 @@ "@types/jasminewd2": "~2.0.3", "@types/lodash": "^4.14.115", "@types/node": "^20.9.0", - "@typescript-eslint/eslint-plugin": "^7.2.0", - "@typescript-eslint/parser": "^7.2.0", + "@typescript-eslint/eslint-plugin": "7.11.0", + "@typescript-eslint/parser": "7.11.0", "autoprefixer": "~6", "canonical-path": "0.0.2", "concurrently": "^3.2.0", - "eslint": "^8.57.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-import": "2.26.0", - "eslint-plugin-jsdoc": "39.3.6", - "eslint-plugin-prefer-arrow": "1.2.3", - "eslint-plugin-prettier": "^5.0.1", + "eslint": "8.57.0", "grunt": "^1.0.4", "grunt-bump": "0.8.0", "grunt-coffeelint": "0.0.16", @@ -137,7 +129,6 @@ "postcss": "^8.4.27", "postcss-scss": "^0.1.7", "prettier": "^3.1.0", - "protractor": "~7.0.0", "sass": "^1.48.0", "tailwindcss": "~3.3", "ts-node": "~10.9", @@ -428,18 +419,6 @@ "tslib": "^2.1.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@angular-devkit/build-webpack": { "version": "0.1800.4", "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1800.4.tgz", @@ -544,101 +523,94 @@ } }, "node_modules/@angular-eslint/builder": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-17.4.0.tgz", - "integrity": "sha512-+3ujbi+ar/iqAAwnJ2bTdWzQpHh9iVEPgjHUOeQhrEM8gcaOLnZXMlUyZL7D+NlXg7aDoEIxETb73dgbIBm55A==", - "dev": true, + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-18.0.1.tgz", + "integrity": "sha512-b/VUeTQznAmGdwP4OyPWyegqSRWub7E8/WXBqojrSFyLkFhpTiHpk/3/5G3LsgTb0zBfyAsqkA0yaadsHu9pjA==", "dependencies": { - "@nx/devkit": "^17.2.8 || ^18.0.0", - "nx": "^17.2.8 || ^18.0.0" + "@nx/devkit": "^19.0.6", + "nx": "^19.0.6" }, "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-17.4.0.tgz", - "integrity": "sha512-cYEJs4PO+QLDt1wfgWh9q8OjOphnoe1OTTFtMqm9lHl0AkBynPnFA6ghiiG5NaT03l7HXi2TQ23rLFlXl3JOBg==", - "dev": true + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-18.0.1.tgz", + "integrity": "sha512-lr4Ysoo28FBOKcJFQUGTMpbWDcak+gyuYvyggp37ERvazE6EDomPFxzEHNqVT9EI9sZ+GDBOoPR+EdFh0ALGNw==" }, "node_modules/@angular-eslint/eslint-plugin": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-17.4.0.tgz", - "integrity": "sha512-E+/O83PXttQUACurGEskLDU+wboBqMMVqvo4T8C/iMcpLx+01M5UBzqpCmfz6ri609G96Au7uDbUEedU1hwqmQ==", - "dev": true, + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-18.0.1.tgz", + "integrity": "sha512-pS3SYLa9DA+ENklGxEUlcw6/xCxgDk9fgjyaheuSjDxL3TIh1pTa4V2TptODdcPh7XCYXiVmy+e/w79mXlGzOw==", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "17.4.0", - "@angular-eslint/utils": "17.4.0", - "@typescript-eslint/utils": "7.8.0" + "@angular-eslint/bundled-angular-compiler": "18.0.1", + "@angular-eslint/utils": "18.0.1" }, "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0-alpha.20", + "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-17.4.0.tgz", - "integrity": "sha512-o1Vb7rt3TpPChVzaxswOKBDWRboMcpC4qUUyoHfeSYa7sDuQHMeIQlCS5QXuykR/RYnIQJSKd89FOd28nGmmRw==", - "dev": true, + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-18.0.1.tgz", + "integrity": "sha512-u/eov/CFBb8l35D8dW78Dx5fBLd8FZFibKN9XQknhzXnDMpISuUOMny5g5/wvYYjqLgqEySXMiHKEAxEup7xtA==", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "17.4.0", - "@angular-eslint/utils": "17.4.0", - "@typescript-eslint/type-utils": "7.8.0", - "@typescript-eslint/utils": "7.8.0", + "@angular-eslint/bundled-angular-compiler": "18.0.1", + "@angular-eslint/utils": "18.0.1", "aria-query": "5.3.0", "axobject-query": "4.0.0" }, "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0-alpha.20", + "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/schematics": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-17.4.0.tgz", - "integrity": "sha512-3WQQbwwBD1N3dZbbx1a1KY/jRujUQgz5778Ac21LU+AdCtvbjnmSpxRfsE3HH8MAreqr8Lv1kjLyiRzPTS5GQQ==", - "dev": true, + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-18.0.1.tgz", + "integrity": "sha512-G9PgFrjyvBaQR8enMnP2scnQDLk99GMpifh3voiOmdEkxaQHRWqhCWncV7GATwpXDzeyj9J9XT9iHGJjnZTpJQ==", "dependencies": { - "@angular-eslint/eslint-plugin": "17.4.0", - "@angular-eslint/eslint-plugin-template": "17.4.0", - "@nx/devkit": "^17.2.8 || ^18.0.0", + "@angular-eslint/eslint-plugin": "18.0.1", + "@angular-eslint/eslint-plugin-template": "18.0.1", + "@nx/devkit": "^19.0.6", "ignore": "5.3.1", - "nx": "^17.2.8 || ^18.0.0", - "strip-json-comments": "3.1.1", - "tmp": "0.2.3" + "nx": "^19.0.6", + "semver": "7.6.2", + "strip-json-comments": "3.1.1" }, "peerDependencies": { - "@angular/cli": ">= 17.0.0 < 18.0.0" + "@angular-devkit/core": ">= 18.0.0 < 19.0.0", + "@angular-devkit/schematics": ">= 18.0.0 < 19.0.0" } }, "node_modules/@angular-eslint/template-parser": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-17.4.0.tgz", - "integrity": "sha512-vT/Tg8dl6Uy++MS9lPS0l37SynH3EaMcggDiTJqn15pIb4ePO65fafOIIKKYG+BN6R6iFe/g9mH/9nb8ohlzdQ==", - "dev": true, + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-18.0.1.tgz", + "integrity": "sha512-22fKzkWo9Ts8aY/WHL1A6seS2tpltgRRXVfnZnnqvQRyRiuPnx1FC0ly7+QPZkThh8vdLwxU+BvtLq9Uiqh9OQ==", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "17.4.0", + "@angular-eslint/bundled-angular-compiler": "18.0.1", "eslint-scope": "^8.0.0" }, "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/utils": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-17.4.0.tgz", - "integrity": "sha512-lHgRXyT878fauDITygraICDM6RHLb51QAJ3gWNZLr7SXcywsZg5d3rxRPCjrCnjgdxNPU0fJ+VJZ5AMt5Ibn7w==", - "dev": true, + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-18.0.1.tgz", + "integrity": "sha512-Q9lCySqg+9h2cz08+SoWj48cY1i04tL1k3bsQJmF2TsylAw2mSsNGX2X3h9WkdxY7sUoY0mP7MVW1iU54Gobcg==", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "17.4.0", - "@typescript-eslint/utils": "7.8.0" + "@angular-eslint/bundled-angular-compiler": "18.0.1" }, "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0-alpha.20", + "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, @@ -769,18 +741,6 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "node_modules/@angular/build/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@angular/cdk": { "version": "18.0.1", "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.0.1.tgz", @@ -829,17 +789,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular/cli/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@angular/common": { "version": "18.0.3", "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.0.3.tgz", @@ -3570,20 +3519,6 @@ "node": ">=10.0.0" } }, - "node_modules/@es-joy/jsdoccomment": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.31.0.tgz", - "integrity": "sha512-tc1/iuQcnaiSIUVad72PBierDFpsxdUHtEF/OrfqvM1CBAsIoMP51j52jTMb3dXriwhieTo289InzZj72jL3EQ==", - "dev": true, - "dependencies": { - "comment-parser": "1.3.1", - "esquery": "^1.4.0", - "jsdoc-type-pratt-parser": "~3.1.0" - }, - "engines": { - "node": "^14 || ^16 || ^17 || ^18" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.3.tgz", @@ -3956,7 +3891,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -3971,7 +3905,6 @@ "version": "4.10.0", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -3980,7 +3913,6 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -4003,7 +3935,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4018,14 +3949,12 @@ "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4035,7 +3964,6 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -4050,7 +3978,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -4061,14 +3988,12 @@ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4080,7 +4005,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -4092,7 +4016,6 @@ "version": "8.57.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -4101,7 +4024,6 @@ "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^2.0.2", "debug": "^4.3.1", @@ -4115,7 +4037,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4125,7 +4046,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4137,7 +4057,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, "engines": { "node": ">=12.22" }, @@ -4149,8 +4068,7 @@ "node_modules/@humanwhocodes/object-schema": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==" }, "node_modules/@inquirer/figures": { "version": "1.0.3", @@ -4330,7 +4248,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, "dependencies": { "@sinclair/typebox": "^0.27.8" }, @@ -5486,7 +5403,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -5499,7 +5415,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "engines": { "node": ">= 8" } @@ -5508,7 +5423,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -5790,21 +5704,19 @@ } }, "node_modules/@nrwl/devkit": { - "version": "18.3.4", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-18.3.4.tgz", - "integrity": "sha512-Fty9Huqm12OYueU3uLJl3uvBUl5BvEyPfvw8+rLiNx9iftdEattM8C+268eAbIRRSLSOVXlWsJH4brlc6QZYYw==", - "dev": true, + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.3.0.tgz", + "integrity": "sha512-WRcph/7U37HkTLIRzQ2oburZVfEFkPHJUn7vmo46gCq+N2cAKy3qwONO0RbthhjFIsG94YPXqFWFlV6k4nXpxA==", "dependencies": { - "@nx/devkit": "18.3.4" + "@nx/devkit": "19.3.0" } }, "node_modules/@nrwl/tao": { - "version": "18.3.4", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-18.3.4.tgz", - "integrity": "sha512-+7KsDYmGj1cvNaXZcjSYOPN1h17hsGFBtVX7MqnpJLLkQTUhKg2rQxqyluzshJ+RoDUVtYPGyHg1AizlB66RIA==", - "dev": true, + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.3.0.tgz", + "integrity": "sha512-MyGYeHbh9O4Tv9xmz3Du+/leY5sKUHaPy4ancfNyShHgYi21hemX0/YYjzzoYHi44D8GzSc1XG2rAuwba7Kilw==", "dependencies": { - "nx": "18.3.4", + "nx": "19.3.0", "tslib": "^2.3.0" }, "bin": { @@ -5812,22 +5724,36 @@ } }, "node_modules/@nx/devkit": { - "version": "18.3.4", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-18.3.4.tgz", - "integrity": "sha512-M3htxl5WvlNKK5KNOndCAApbyBCZNTFFs+rtdwvudNZk5+84zAAPaWzSoX9C4XLAW78/f98LzF68/ch05aN12A==", - "dev": true, + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.3.0.tgz", + "integrity": "sha512-Natya5nzvHH0qTOIL1w/EZtwMgDx87Dgz0LgeY7te2fULaNFcj5fVrP+mUKEJZR+NccO7GPumT2RPhuEl9rPnQ==", "dependencies": { - "@nrwl/devkit": "18.3.4", + "@nrwl/devkit": "19.3.0", "ejs": "^3.1.7", "enquirer": "~2.3.6", "ignore": "^5.0.4", + "minimatch": "9.0.3", "semver": "^7.5.3", "tmp": "~0.2.1", "tslib": "^2.3.0", "yargs-parser": "21.1.1" }, "peerDependencies": { - "nx": ">= 16 <= 19" + "nx": ">= 17 <= 20" + } + }, + "node_modules/@nx/devkit/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@nx/nx-darwin-arm64": { @@ -5860,14 +5786,43 @@ "node": ">= 10" } }, + "node_modules/@nx/nx-freebsd-x64": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.3.0.tgz", + "integrity": "sha512-1ow7Xku1yyjHviCKsWiuHCAnTd3fD+5O5c+e4DXHVthT8wnadKSotvBIWf38DMbMthl7na82e72OzxcdSbrVqQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.3.0.tgz", + "integrity": "sha512-mYQMIUvNr2gww8vbg766uk/C1RxoC1fwioeP87bmV5NRUKSzJ8WEJVxAsqc9RGhAOUaNXOgEuKYrMcVhKyIKJQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "18.3.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-18.3.4.tgz", - "integrity": "sha512-g/2IaB2bZTKaBNPEf9LxtIXb1XHdhh3VO9PnePIrwkkixPMLN0dTxT5Sttt75lvLP3EU1AUR5w3Aaz2Q1mYtWA==", + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.3.0.tgz", + "integrity": "sha512-rHL3eQ0RHkeAXnhHHu/NIyouN/ykiXvgyNU3TuCd50+2MZcAbjB+Xq3mwL0MwiP+BQuptiE+snTuxFUJp4ZH6A==", "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5877,13 +5832,12 @@ } }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "18.3.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-18.3.4.tgz", - "integrity": "sha512-MgfKLoEF6I1cCS+0ooFLEjJSSVdCYyCT9Q96IHRJntAEL8u/0GR2OUoBoLC+q1lnbIkJr/uqTJxA2Jh+sJTIbA==", + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.3.0.tgz", + "integrity": "sha512-im0+OgOD6ShpTkI9ZRz7BjzxhQ/Lk3xjYmmCu+PFGmaybEnkNNDFwsgS0iEVKMdWZ/EQoQvJrqOYsX125iIBuQ==", "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5907,6 +5861,36 @@ "node": ">= 10" } }, + "node_modules/@nx/nx-linux-x64-musl": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.3.0.tgz", + "integrity": "sha512-sahEV99glBlpGKG1TIQ5PkJ0QvpHp69wWsBFK2DKtCETxOtsWqwvIjemxTCXRirTqeHiP7BiR6VWsf2YqqqBdw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.3.0.tgz", + "integrity": "sha512-w03gFwLijStmhUji70QJHYo/U16ovybNczxGO7+5TT330X8/y+ihw9FCGHiIcujAjTAE88h0DKGn05WlNqRmfg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@nx/nx-win32-x64-msvc": { "version": "18.3.4", "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-18.3.4.tgz", @@ -5931,18 +5915,6 @@ "node": ">=14" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.18.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", @@ -6243,8 +6215,7 @@ "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", @@ -6485,12 +6456,6 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, "node_modules/@types/lodash": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.1.tgz", @@ -6549,7 +6514,9 @@ "version": "0.0.32", "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", "integrity": "sha512-qYi3YV9inU/REEfxwVcGZzbS3KG/Xs90lv0Pr+lDtuVjBPGd1A+eciXzVSaRvLify132BfcvhvEjeVahrUl0Ug==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/@types/qs": { "version": "6.9.15", @@ -6573,13 +6540,9 @@ "version": "3.0.26", "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.26.tgz", "integrity": "sha512-dyIGFKXfUFiwkMfNGn1+F6b80ZjR3uSYv1j6xVJSDlft5waZ2cwkHW4e7zNzvq7hiEackcgvBpmnXZrI1GltPg==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/@types/send": { "version": "0.17.4", @@ -6630,21 +6593,19 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.8.0.tgz", - "integrity": "sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.11.0.tgz", + "integrity": "sha512-P+qEahbgeHW4JQ/87FuItjBj8O3MYv5gELDzr8QaQ7fsll1gSMTYb6j87MYyxwf3DtD7uGFB9ShwgmCJB5KmaQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/type-utils": "7.8.0", - "@typescript-eslint/utils": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", - "debug": "^4.3.4", + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/type-utils": "7.11.0", + "@typescript-eslint/utils": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.6.0", "ts-api-utils": "^1.3.0" }, "engines": { @@ -6664,16 +6625,38 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.11.0.tgz", + "integrity": "sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/typescript-estree": "7.11.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.8.0.tgz", - "integrity": "sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.11.0.tgz", + "integrity": "sha512-yimw99teuaXVWsBcPO1Ais02kwJ1jmNA1KxE7ng0aT7ndr1pT1wqj0OJnsYVGKKlc4QJai86l/025L6z8CljOg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/typescript-estree": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/typescript-estree": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0", "debug": "^4.3.4" }, "engines": { @@ -6693,13 +6676,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", - "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz", + "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0" + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -6710,13 +6693,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.8.0.tgz", - "integrity": "sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.11.0.tgz", + "integrity": "sha512-WmppUEgYy+y1NTseNMJ6mCFxt03/7jTOy08bcg7bxJJdsM4nuhnchyBbE8vryveaJUf62noH7LodPSo5Z0WUCg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.8.0", - "@typescript-eslint/utils": "7.8.0", + "@typescript-eslint/typescript-estree": "7.11.0", + "@typescript-eslint/utils": "7.11.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -6736,10 +6719,32 @@ } } }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.11.0.tgz", + "integrity": "sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/typescript-estree": "7.11.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, "node_modules/@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz", + "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -6750,13 +6755,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", - "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz", + "integrity": "sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -6778,18 +6783,14 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.8.0.tgz", - "integrity": "sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==", - "dev": true, + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz", + "integrity": "sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.15", - "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/typescript-estree": "7.8.0", - "semver": "^7.6.0" + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -6802,14 +6803,13 @@ "eslint": "^8.56.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", - "dev": true, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", + "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", "dependencies": { - "@typescript-eslint/types": "7.8.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -6819,73 +6819,82 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@uirouter/angular": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@uirouter/angular/-/angular-13.0.0.tgz", - "integrity": "sha512-T2aizSXzW+7eiXUmc0LiLH+I8ZBJvDr7OQmm/5WCcxVL2NfuIse7B1kpvfdh9PmBAqw8AY7S0NhrJgABfFJUnw==", - "dependencies": { - "tslib": "^2.3.0" - }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", + "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", "engines": { - "node": ">=6.0.0" + "node": "^18.18.0 || >=20.0.0" }, - "peerDependencies": { - "@angular/common": "^17.0.0", - "@angular/core": "^17.0.0", - "@uirouter/core": "^6.0.8", - "@uirouter/rx": "^1.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@uirouter/angular-hybrid": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@uirouter/angular-hybrid/-/angular-hybrid-17.1.0.tgz", - "integrity": "sha512-zUQ/b2BaEuODPOtDtxp2SpEifm/VHoLauPTXtZAfcHpDoty6DFbLyGCrA4ZI9lqyoACVxpOuUKjhTHLNE9SXTw==", + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", + "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", "dependencies": { - "tslib": "^2.3.0" + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, - "peerDependencies": { - "@angular/core": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", - "@angular/upgrade": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", - "@uirouter/angular": "^13.0.0", - "@uirouter/angularjs": "^1.0.30", - "@uirouter/core": "^6.1.0", - "angular": "^1.5.0" - } - }, - "node_modules/@uirouter/angularjs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.1.0.tgz", - "integrity": "sha512-AhgxXhMfN6FU2HxDQqwDPbzmd6kTgvYCgV/kgoCAXfxAH6cFQrifViToC90Wdg6djBynHwA3L/KYP+iOYHkw6A==", "engines": { - "node": ">=4.0.0" + "node": "^18.18.0 || >=20.0.0" }, - "peerDependencies": { - "@uirouter/core": "^6.0.8", - "angular": ">=1.2.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@uirouter/core": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.1.0.tgz", - "integrity": "sha512-WFYh5NPAqRX4L2qlI4k62tgR6pxoqOBSW1CM1uBWCau4mAmgasYd5etJ9RoSJrSnCpCQ2km2Jltf0n5ql684MQ==", + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", + "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", + "dependencies": { + "@typescript-eslint/types": "7.13.0", + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">=4.0.0" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@uirouter/rx": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@uirouter/rx/-/rx-1.0.0.tgz", - "integrity": "sha512-dqPmLFC+qqF6RIdJVKktXSON6WILy2oyLhADDk74F3GAUZ/VvOu3QSPLDtZEP3LMSo6vkGQvwcUdjgNVWL3YJA==", - "peerDependencies": { - "@uirouter/core": ">=6.0.1", - "rxjs": "^6.5.3 || ^7.4.0" + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz", + "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.11.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@vitejs/plugin-basic-ssl": { "version": "1.1.0", @@ -7066,7 +7075,6 @@ "version": "3.0.0-rc.46", "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", - "dev": true, "dependencies": { "js-yaml": "^3.10.0", "tslib": "^2.4.0" @@ -7076,10 +7084,9 @@ } }, "node_modules/@zkochan/js-yaml": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", - "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", - "dev": true, + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", + "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", "dependencies": { "argparse": "^2.0.1" }, @@ -7090,8 +7097,7 @@ "node_modules/@zkochan/js-yaml/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/abbrev": { "version": "1.1.1", @@ -7115,7 +7121,6 @@ "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -7159,7 +7164,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -7205,6 +7209,8 @@ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.12.tgz", "integrity": "sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=6.0" } @@ -7333,6 +7339,23 @@ "integrity": "sha512-WyUrigFcnxLZnzaupIAqOLrGXMCOcGz0L5O7OoaWKYGvEx2yNvGSNAGJCmOggGmaPEfIt6YMGTcbc4uwS6Srdw==", "deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward." }, + "node_modules/angular-eslint": { + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/angular-eslint/-/angular-eslint-18.0.1.tgz", + "integrity": "sha512-wZMLDDHLSWKce8uB4BXln2Rnfk8jxgj9WXcRNcPwS0IJhA2YgcGp4u4GIqqPc6y+U+5LmQc9pzBpETWUBDyfEw==", + "dependencies": { + "@angular-eslint/builder": "18.0.1", + "@angular-eslint/eslint-plugin": "18.0.1", + "@angular-eslint/eslint-plugin-template": "18.0.1", + "@angular-eslint/schematics": "18.0.1", + "@angular-eslint/template-parser": "18.0.1" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*", + "typescript-eslint": "^8.0.0-alpha.20" + } + }, "node_modules/angular-file-upload": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/angular-file-upload/-/angular-file-upload-1.1.6.tgz", @@ -8003,7 +8026,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -8012,7 +8034,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -8090,26 +8111,6 @@ "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -8123,7 +8124,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, "engines": { "node": ">=8" } @@ -8133,6 +8133,8 @@ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8146,24 +8148,6 @@ "node": ">=0.10.0" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", @@ -8207,6 +8191,8 @@ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "safer-buffer": "~2.1.0" } @@ -8216,6 +8202,8 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.8" } @@ -8250,8 +8238,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/atob": { "version": "2.1.2", @@ -8413,6 +8400,8 @@ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": "*" } @@ -8421,13 +8410,14 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/axios": { "version": "1.6.8", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", - "dev": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -8438,7 +8428,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", - "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -8683,6 +8672,8 @@ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "tweetnacl": "^0.14.3" } @@ -8733,6 +8724,8 @@ "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "minimist": "^1.2.0" }, @@ -8884,7 +8877,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "devOptional": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -8929,6 +8921,8 @@ "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.6.1.tgz", "integrity": "sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "https-proxy-agent": "^2.2.1" } @@ -8938,6 +8932,8 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "es6-promisify": "^5.0.0" }, @@ -8950,6 +8946,8 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "ms": "^2.1.1" } @@ -8959,6 +8957,8 @@ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "agent-base": "^4.3.0", "debug": "^3.1.0" @@ -9130,7 +9130,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -9239,7 +9238,9 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/center-align": { "version": "0.1.3", @@ -9693,7 +9694,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -9710,15 +9710,6 @@ "node": ">= 0.6.x" } }, - "node_modules/comment-parser": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", - "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==", - "dev": true, - "engines": { - "node": ">= 12.0.0" - } - }, "node_modules/common-path-prefix": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", @@ -9801,8 +9792,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "devOptional": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concurrently": { "version": "3.6.1", @@ -10413,6 +10403,8 @@ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "assert-plus": "^1.0.0" }, @@ -10574,8 +10566,7 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "node_modules/default-browser": { "version": "5.2.1", @@ -10648,7 +10639,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, "engines": { "node": ">=8" } @@ -10687,6 +10677,8 @@ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "integrity": "sha512-Z4fzpbIRjOu7lO5jCETSWoqUDVe0IPOlfugBsF6suen2LKDlVb4QZpKEM9P+buNJ4KI1eN7I083w/pbKUpsrWQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "globby": "^5.0.0", "is-path-cwd": "^1.0.0", @@ -10705,6 +10697,8 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "array-uniq": "^1.0.1" }, @@ -10717,6 +10711,8 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -10726,6 +10722,8 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "integrity": "sha512-HJRTIH2EeH44ka+LWig+EqT2ONSYpVlNfx6pyd592/VF1TbfljJ7elwie7oSwcViLGqOdWocSdu2txwBF9bjmQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "array-union": "^1.0.1", "arrify": "^1.0.0", @@ -10743,6 +10741,8 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -10752,6 +10752,8 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -10763,7 +10765,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -10787,7 +10788,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "engines": { "node": ">=6" } @@ -10851,7 +10851,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -10860,7 +10859,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, "dependencies": { "path-type": "^4.0.0" }, @@ -10890,7 +10888,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -10988,7 +10985,6 @@ "version": "16.3.2", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -11000,7 +10996,6 @@ "version": "10.0.0", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", - "dev": true, "engines": { "node": ">=12" } @@ -11008,8 +11003,7 @@ "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" }, "node_modules/eastasianwidth": { "version": "0.2.0", @@ -11021,6 +11015,8 @@ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -11030,7 +11026,9 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/ee-first": { "version": "1.1.1", @@ -11042,7 +11040,6 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dev": true, "dependencies": { "jake": "^10.8.5" }, @@ -11095,7 +11092,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "dependencies": { "once": "^1.4.0" } @@ -11147,7 +11143,6 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, "dependencies": { "ansi-colors": "^4.1.1" }, @@ -11328,15 +11323,6 @@ "node": ">= 0.4" } }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -11366,13 +11352,17 @@ "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "es6-promise": "^4.0.3" } @@ -11445,7 +11435,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -11454,7 +11443,6 @@ "version": "8.57.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -11505,217 +11493,10 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-config-prettier": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", - "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", - "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/eslint-plugin-jsdoc": { - "version": "39.3.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-39.3.6.tgz", - "integrity": "sha512-R6dZ4t83qPdMhIOGr7g2QII2pwCjYyKP+z0tPOfO1bbAbQyKC20Y2Rd6z1te86Lq3T7uM8bNo+VD9YFpE8HU/g==", - "dev": true, - "dependencies": { - "@es-joy/jsdoccomment": "~0.31.0", - "comment-parser": "1.3.1", - "debug": "^4.3.4", - "escape-string-regexp": "^4.0.0", - "esquery": "^1.4.0", - "semver": "^7.3.7", - "spdx-expression-parse": "^3.0.1" - }, - "engines": { - "node": "^14 || ^16 || ^17 || ^18" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-prefer-arrow": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.3.tgz", - "integrity": "sha512-J9I5PKCOJretVuiZRGvPQxCbllxGAV/viI20JO3LYblAodofBxyMnZAJ+WGeClHgANnSJberTNoFWWjrWKBuXQ==", - "dev": true, - "peerDependencies": { - "eslint": ">=2.0.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, "node_modules/eslint-scope": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -11731,7 +11512,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -11743,7 +11523,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -11759,7 +11538,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -11773,14 +11551,12 @@ "node_modules/eslint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11790,7 +11566,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11806,7 +11581,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -11817,14 +11591,12 @@ "node_modules/eslint/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -11836,7 +11608,6 @@ "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -11852,7 +11623,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -11864,7 +11634,6 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -11879,7 +11648,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -11888,7 +11656,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -11899,14 +11666,12 @@ "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -11918,7 +11683,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -11930,7 +11694,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -11942,7 +11705,6 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -11959,7 +11721,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -11972,7 +11733,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -11984,7 +11744,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -11996,7 +11755,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -12005,7 +11763,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -12349,24 +12106,19 @@ "dev": true, "engines": [ "node >=0.6.0" - ] + ], + "optional": true, + "peer": true }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -12381,20 +12133,17 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "dependencies": { "reusify": "^1.0.4" } @@ -12415,7 +12164,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -12430,7 +12178,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -12460,7 +12207,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, "dependencies": { "minimatch": "^5.0.1" } @@ -12469,7 +12215,6 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -12481,7 +12226,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "devOptional": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -12542,7 +12286,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -12598,7 +12341,6 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, "bin": { "flat": "cli.js" } @@ -12607,7 +12349,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -12620,14 +12361,12 @@ "node_modules/flatted": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "node_modules/follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, "funding": [ { "type": "individual", @@ -12712,6 +12451,8 @@ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": "*" } @@ -12720,7 +12461,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -12773,11 +12513,18 @@ "node": ">= 0.6" } }, + "node_modules/front-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", + "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", + "dependencies": { + "js-yaml": "^3.13.1" + } + }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "node_modules/fs-extra": { "version": "10.1.0", @@ -12807,8 +12554,7 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "devOptional": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { "version": "2.3.3", @@ -12997,6 +12743,8 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "assert-plus": "^1.0.0" } @@ -13024,7 +12772,6 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "devOptional": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -13044,7 +12791,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "devOptional": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -13062,7 +12808,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -13072,7 +12817,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -13175,7 +12919,6 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -13246,8 +12989,7 @@ "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, "node_modules/grunt": { "version": "1.6.1", @@ -14523,6 +14265,8 @@ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=4" } @@ -14533,6 +14277,8 @@ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "deprecated": "this library is no longer supported", "dev": true, + "optional": true, + "peer": true, "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -14546,6 +14292,8 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -14561,7 +14309,9 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/hard-rejection": { "version": "2.1.0", @@ -14572,15 +14322,6 @@ "node": ">=6" } }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -15007,6 +14748,8 @@ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -15119,7 +14862,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, "engines": { "node": ">= 4" } @@ -15152,7 +14894,9 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/immutable": { "version": "4.3.5", @@ -15164,7 +14908,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -15180,7 +14923,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "engines": { "node": ">=4" } @@ -15205,7 +14947,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "devOptional": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -15495,7 +15236,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, "bin": { "is-docker": "cli.js" }, @@ -15543,7 +15283,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -15560,7 +15299,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "devOptional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -15642,7 +15380,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "devOptional": true, "engines": { "node": ">=0.12.0" } @@ -15676,6 +15413,8 @@ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", "integrity": "sha512-cnS56eR9SPAscL77ik76ATVqoPARTqPIVkMDVxRaWH06zT+6+CzIroYRJ0VVvm0Z1zfAvxvz9i/D3Ppjaqt5Nw==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -15685,6 +15424,8 @@ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "is-path-inside": "^1.0.0" }, @@ -15697,6 +15438,8 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", "integrity": "sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "path-is-inside": "^1.0.1" }, @@ -15708,7 +15451,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -15860,7 +15602,9 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/is-unc-path": { "version": "1.0.0", @@ -15916,7 +15660,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -15960,7 +15703,9 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", @@ -16143,7 +15888,6 @@ "version": "10.9.1", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz", "integrity": "sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==", - "dev": true, "dependencies": { "async": "^3.2.3", "chalk": "^4.0.2", @@ -16161,7 +15905,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -16175,14 +15918,12 @@ "node_modules/jake/node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, "node_modules/jake/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -16192,7 +15933,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -16208,7 +15948,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -16219,14 +15958,12 @@ "node_modules/jake/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/jake/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -16235,7 +15972,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -16247,7 +15983,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -16260,6 +15995,8 @@ "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", "integrity": "sha512-KbdGQTf5jbZgltoHs31XGiChAPumMSY64OZMWLNYnEnMfG5uwGBhffePwuskexjT+/Jea/gU3qAU8344hNohSw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "exit": "^0.1.2", "glob": "^7.0.6", @@ -16297,13 +16034,17 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", "integrity": "sha512-SNkOkS+/jMZvLhuSx1fjhcNWUC/KG6oVyFUGkSBEr9n1axSNduWU8GlI7suaHXr4yxjet6KjrUZxUTE5WzzWwQ==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/jasminewd2": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", "integrity": "sha512-Rn0nZe4rfDhzA63Al3ZGh0E+JTmM6ESZYXJGKuqKGZObsAB9fwXPD03GjtIEvJBDOhN94T5MzbwZSqzFHSQPzg==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">= 6.9.x" } @@ -16312,7 +16053,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", @@ -16327,7 +16067,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -16342,7 +16081,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -16358,7 +16096,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -16369,14 +16106,12 @@ "node_modules/jest-diff/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/jest-diff/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -16385,7 +16120,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -16397,7 +16131,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -16477,7 +16210,6 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -16491,15 +16223,6 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" }, - "node_modules/jsdoc-type-pratt-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-3.1.0.tgz", - "integrity": "sha512-MgtD0ZiCDk9B+eI73BextfRrVQl0oyzRG8B2BjORts6jbunj4ScKPcyXGTbB6eXL4y9TzxCm6hyeLq/2ASzNdw==", - "dev": true, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -16667,8 +16390,7 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "node_modules/json-parse-better-errors": { "version": "1.0.2", @@ -16688,7 +16410,9 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/json-schema-traverse": { "version": "1.0.0", @@ -16698,20 +16422,20 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -16728,7 +16452,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, "dependencies": { "universalify": "^2.0.0" }, @@ -16765,6 +16488,8 @@ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -16791,6 +16516,8 @@ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", @@ -16802,13 +16529,17 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/jszip/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -16824,6 +16555,8 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -17089,7 +16822,6 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, "dependencies": { "json-buffer": "3.0.1" } @@ -17236,7 +16968,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -17267,6 +16998,8 @@ "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "immediate": "~3.0.5" } @@ -17318,7 +17051,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -17422,7 +17154,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -17453,8 +17184,7 @@ "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "node_modules/log-symbols": { "version": "4.1.0", @@ -17787,7 +17517,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "engines": { "node": ">= 8" } @@ -17805,7 +17534,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -17818,7 +17546,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -17842,7 +17569,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -17851,7 +17577,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -17932,7 +17657,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -18444,8 +18168,7 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "node_modules/needle": { "version": "3.3.1", @@ -18575,15 +18298,15 @@ } }, "node_modules/ngx-entity-service": { - "version": "0.0.38", - "resolved": "https://registry.npmjs.org/ngx-entity-service/-/ngx-entity-service-0.0.38.tgz", - "integrity": "sha512-QmzXwn2aAv+cMrp7qBFBAhf8eR9cjljPneJ2qXIYa5l/TUNH91RnlF60BKKj4c4uD66tesokUqXZEPVaes92Tg==", + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/ngx-entity-service/-/ngx-entity-service-0.0.39.tgz", + "integrity": "sha512-81DdRQxN7R2lELTiZkB5FkjeK147C8AUmyl52sxZgtYw/WiFay7iWk9KTSsZAJ8OhKKkmllXfMkOpQzvoYTafw==", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17", - "@angular/core": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17" + "@angular/common": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17 || ^18", + "@angular/core": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17 || ^18" } }, "node_modules/ngx-lottie": { @@ -18813,8 +18536,7 @@ "node_modules/node-machine-id": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", - "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", - "dev": true + "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==" }, "node_modules/node-releases": { "version": "2.0.14", @@ -19091,7 +18813,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -19139,16 +18860,15 @@ } }, "node_modules/nx": { - "version": "18.3.4", - "resolved": "https://registry.npmjs.org/nx/-/nx-18.3.4.tgz", - "integrity": "sha512-7rOHRyxpnZGJ3pHnwmpoAMHt9hNuwibWhOhPBJDhJVcbQJtGfwcWWyV/iSEnVXwKZ2lfHVE3TwE+gXFdT/GFiw==", - "dev": true, + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.0.tgz", + "integrity": "sha512-WILWiROUkZWwuPJ12tP24Z0NULPEhxFN9i55/fECuVXYaFtkg6FvEne9C4d4bRqhZPcbrz6WhHnzE3NhdjH7XQ==", "hasInstallScript": true, "dependencies": { - "@nrwl/tao": "18.3.4", + "@nrwl/tao": "19.3.0", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.6", + "@zkochan/js-yaml": "0.0.7", "axios": "^1.6.0", "chalk": "^4.1.0", "cli-cursor": "3.1.0", @@ -19159,10 +18879,10 @@ "enquirer": "~2.3.6", "figures": "3.2.0", "flat": "^5.0.2", + "front-matter": "^4.0.2", "fs-extra": "^11.1.0", "ignore": "^5.0.4", "jest-diff": "^29.4.1", - "js-yaml": "4.1.0", "jsonc-parser": "3.2.0", "lines-and-columns": "~2.0.3", "minimatch": "9.0.3", @@ -19185,16 +18905,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "18.3.4", - "@nx/nx-darwin-x64": "18.3.4", - "@nx/nx-freebsd-x64": "18.3.4", - "@nx/nx-linux-arm-gnueabihf": "18.3.4", - "@nx/nx-linux-arm64-gnu": "18.3.4", - "@nx/nx-linux-arm64-musl": "18.3.4", - "@nx/nx-linux-x64-gnu": "18.3.4", - "@nx/nx-linux-x64-musl": "18.3.4", - "@nx/nx-win32-arm64-msvc": "18.3.4", - "@nx/nx-win32-x64-msvc": "18.3.4" + "@nx/nx-darwin-arm64": "19.3.0", + "@nx/nx-darwin-x64": "19.3.0", + "@nx/nx-freebsd-x64": "19.3.0", + "@nx/nx-linux-arm-gnueabihf": "19.3.0", + "@nx/nx-linux-arm64-gnu": "19.3.0", + "@nx/nx-linux-arm64-musl": "19.3.0", + "@nx/nx-linux-x64-gnu": "19.3.0", + "@nx/nx-linux-x64-musl": "19.3.0", + "@nx/nx-win32-arm64-msvc": "19.3.0", + "@nx/nx-win32-x64-msvc": "19.3.0" }, "peerDependencies": { "@swc-node/register": "^1.8.0", @@ -19209,11 +18929,70 @@ } } }, + "node_modules/nx/node_modules/@nx/nx-darwin-arm64": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.3.0.tgz", + "integrity": "sha512-TMTxjrN7Y/UsKFjmz0YfhVItLTGWqvud8cmQchw5NEjdNakfjXk0mREufO5/5PwoiRIsen6MbThoTprLpjOUiQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-darwin-x64": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.3.0.tgz", + "integrity": "sha512-GH2L6ftnzdIs7JEdv7ZPCdbpAdB5sW6NijK07riYZSONzq5fEruD1yDWDkyZbYBb8RTxsparUWJnq8q1qxEPHQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.3.0.tgz", + "integrity": "sha512-k8q/d6WBSXOeUpBq6Mw69yMKL4n9LaX3o4LBNwBkVCEZ8p6s0njwKefLtjwnKlai0g/k5f0NcilU2zTwP/Ex8g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.3.0.tgz", + "integrity": "sha512-M7e2zXGfTjH8NLiwqKLdWC9VlfMSQDYlI4/SM4OSpPqhUTfPlRPa+wNKNTG7perKfDXxE9ei8yjocujknXJk/A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/nx/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -19224,17 +19003,10 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/nx/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/nx/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -19250,7 +19022,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -19261,14 +19032,12 @@ "node_modules/nx/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/nx/node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -19282,34 +19051,19 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } }, - "node_modules/nx/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/nx/node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" }, "node_modules/nx/node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -19324,7 +19078,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", - "dev": true, "dependencies": { "bl": "^4.0.3", "chalk": "^4.1.0", @@ -19346,7 +19099,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -19354,25 +19106,13 @@ "node": ">=8" } }, - "node_modules/nx/node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": "*" } @@ -19509,23 +19249,6 @@ "node": ">=0.10.0" } }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -19557,7 +19280,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "devOptional": true, "dependencies": { "wrappy": "1" } @@ -19580,7 +19302,6 @@ "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -19626,7 +19347,6 @@ "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -19777,7 +19497,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -19792,7 +19511,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -19885,7 +19603,9 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/param-case": { "version": "2.1.1", @@ -19900,7 +19620,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -20036,7 +19755,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -20045,7 +19763,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -20054,7 +19771,9 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/path-key": { "version": "3.1.1", @@ -20123,7 +19842,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -20153,7 +19871,9 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/picocolors": { "version": "1.0.0", @@ -20859,7 +20579,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -20891,23 +20610,10 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -20921,7 +20627,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, "engines": { "node": ">=10" }, @@ -20976,6 +20681,8 @@ "integrity": "sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==", "deprecated": "We have news to share - Protractor is deprecated and will reach end-of-life by Summer 2023. To learn more and find out about other options please refer to this post on the Angular blog. Thank you for using and contributing to Protractor. https://goo.gle/state-of-e2e-in-angular", "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/q": "^0.0.32", "@types/selenium-webdriver": "^3.0.0", @@ -21006,6 +20713,8 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -21015,6 +20724,8 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -21024,6 +20735,8 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", @@ -21040,6 +20753,8 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -21051,6 +20766,8 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -21060,6 +20777,8 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -21072,6 +20791,8 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -21085,6 +20806,8 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -21097,6 +20820,8 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "p-try": "^2.0.0" }, @@ -21112,6 +20837,8 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -21124,6 +20851,8 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", "integrity": "sha512-/CdEdaw49VZVmyIDGUQKDDT53c7qBkO6g5CefWz91Ae+l4+cRtcDYwMTXh6me4O8TMldeGHG3N2Bl84V78Ywbg==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.6.0", "teleport": ">=0.2.0" @@ -21134,6 +20863,8 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -21143,6 +20874,8 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "source-map": "^0.5.6" } @@ -21152,6 +20885,8 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "ansi-regex": "^2.0.0" }, @@ -21164,6 +20899,8 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.8.0" } @@ -21172,13 +20909,17 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/protractor/node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -21201,6 +20942,8 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -21234,8 +20977,7 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/prr": { "version": "1.0.1", @@ -21248,7 +20990,9 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/pug": { "version": "2.0.4", @@ -21509,7 +21253,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -21582,8 +21325,7 @@ "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/read-cache": { "version": "1.0.0", @@ -22025,6 +21767,8 @@ "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dev": true, + "optional": true, + "peer": true, "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -22056,6 +21800,8 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -22070,6 +21816,8 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.6" } @@ -22242,7 +21990,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -22271,7 +22018,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "devOptional": true, "dependencies": { "glob": "^7.1.3" }, @@ -22341,7 +22087,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -22507,6 +22252,8 @@ "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "https-proxy-agent": "^2.2.1" }, @@ -22519,6 +22266,8 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "es6-promisify": "^5.0.0" }, @@ -22531,6 +22280,8 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "ms": "^2.1.1" } @@ -22540,6 +22291,8 @@ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "agent-base": "^4.3.0", "debug": "^3.1.0" @@ -22552,7 +22305,8 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", - "dev": true + "dev": true, + "optional": true }, "node_modules/schema-utils": { "version": "4.2.0", @@ -22584,6 +22338,8 @@ "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "jszip": "^3.1.3", "rimraf": "^2.5.4", @@ -22599,6 +22355,8 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -22611,6 +22369,8 @@ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", "integrity": "sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "os-tmpdir": "~1.0.1" }, @@ -22632,12 +22392,9 @@ } }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "bin": { "semver": "bin/semver.js" }, @@ -22645,22 +22402,6 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -22887,7 +22628,9 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -23205,7 +22948,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, "engines": { "node": ">=8" } @@ -23633,14 +23375,15 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/sshpk": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -23665,7 +23408,9 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/ssri": { "version": "10.0.6", @@ -23919,7 +23664,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, "engines": { "node": ">=4" } @@ -23949,7 +23693,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -23961,7 +23704,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", - "dev": true, "dependencies": { "duplexer": "^0.1.1", "minimist": "^1.2.0", @@ -24064,22 +23806,6 @@ "node": ">=0.10" } }, - "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "dev": true, - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/tailwindcss": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.7.tgz", @@ -24158,7 +23884,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -24371,8 +24096,7 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, "node_modules/thenify": { "version": "3.3.1", @@ -24410,8 +24134,7 @@ "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, "node_modules/through2": { "version": "4.0.2", @@ -24455,7 +24178,6 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true, "engines": { "node": ">=14.14" } @@ -24512,7 +24234,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "devOptional": true, "dependencies": { "is-number": "^7.0.0" }, @@ -24592,6 +24313,8 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" @@ -24650,7 +24373,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, "engines": { "node": ">=16" }, @@ -24731,27 +24453,16 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", + "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">=6" } }, "node_modules/tslib": { @@ -24777,6 +24488,8 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -24788,13 +24501,14 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -24909,7 +24623,6 @@ "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -24918,6 +24631,187 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.13.0.tgz", + "integrity": "sha512-upO0AXxyBwJ4BbiC6CRgAJKtGYha2zw4m1g7TIVPSonwYEuf7vCicw3syjS1OxdDMTz96sZIXl3Jx3vWJLLKFw==", + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.13.0", + "@typescript-eslint/parser": "7.13.0", + "@typescript-eslint/utils": "7.13.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz", + "integrity": "sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/type-utils": "7.13.0", + "@typescript-eslint/utils": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.0.tgz", + "integrity": "sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==", + "dependencies": { + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", + "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", + "dependencies": { + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.0.tgz", + "integrity": "sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==", + "dependencies": { + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/utils": "7.13.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", + "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", + "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", + "dependencies": { + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", + "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", + "dependencies": { + "@typescript-eslint/types": "7.13.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/ua-parser-js": { "version": "0.7.37", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz", @@ -25111,7 +25005,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, "engines": { "node": ">= 10.0.0" } @@ -25278,6 +25171,8 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "dev": true, + "optional": true, + "peer": true, "bin": { "uuid": "bin/uuid" } @@ -25334,6 +25229,8 @@ "engines": [ "node >=0.6.0" ], + "optional": true, + "peer": true, "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -25851,6 +25748,8 @@ "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/selenium-webdriver": "^3.0.0", "selenium-webdriver": "^3.0.1" @@ -25864,6 +25763,8 @@ "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.9.tgz", "integrity": "sha512-Yl113uKm8z4m/KMUVWHq1Sjtla2uxEBtx2Ue3AmIlnlPAKloDn/Lvmy6pqWCUersVISpdMeVpAaGbNnvMuT2LQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "adm-zip": "^0.5.2", "chalk": "^1.1.1", @@ -25889,6 +25790,8 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -25898,6 +25801,8 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -25907,6 +25812,8 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", @@ -25922,13 +25829,17 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/webdriver-manager/node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -25941,6 +25852,8 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "optional": true, + "peer": true, "bin": { "semver": "bin/semver" } @@ -25950,6 +25863,8 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "ansi-regex": "^2.0.0" }, @@ -25962,6 +25877,8 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.8.0" } @@ -26526,7 +26443,6 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -26633,8 +26549,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "devOptional": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { "version": "8.11.0", @@ -26662,6 +26577,8 @@ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" @@ -26675,6 +26592,8 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=4.0" } @@ -26746,7 +26665,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 7431b2a58c..467afeb38c 100644 --- a/package.json +++ b/package.json @@ -42,13 +42,9 @@ "@angular/upgrade": "^18.0.3", "@ctrl/ngx-emoji-mart": "^9.2.0", "@ngneat/hotkeys": "^4.0.0", - "@uirouter/angular": "^13.0", - "@uirouter/angular-hybrid": "^17.1.0", - "@uirouter/angularjs": "^1.0.30", - "@uirouter/core": "^6.1.0", - "@uirouter/rx": "^1.0.0", "angular": "1.5.11", "angular-cookies": "1.5.11", + "angular-eslint": "^18.0.1", "angular-file-upload": "~1", "angular-filter": "0.5.17", "angular-local-storage": "0.7.1", @@ -82,22 +78,23 @@ "ng-flex-layout": "^17.3.7-beta.1", "ng2-pdf-viewer": "^10.2", "ngx-bootstrap": "^6.1.0", - "ngx-entity-service": "^0.0.38", + "ngx-entity-service": "^0.0.39", "ngx-lottie": "^11.0.2", "nvd3": "1.8.6", "rxjs": "~7.4.0", "ts-md5": "^1.3.1", "tslib": "^2.6.2", + "typescript-eslint": "^7.13.0", "underscore.string": "2.3.3", "zone.js": "~0.14" }, "devDependencies": { "@angular-devkit/build-angular": "^18.0.4", - "@angular-eslint/builder": "^17.3.0", - "@angular-eslint/eslint-plugin": "^17.3.0", - "@angular-eslint/eslint-plugin-template": "^17.3.0", - "@angular-eslint/schematics": "^17.3.0", - "@angular-eslint/template-parser": "^17.3.0", + "@angular-eslint/builder": "18.0.1", + "@angular-eslint/eslint-plugin": "18.0.1", + "@angular-eslint/eslint-plugin-template": "18.0.1", + "@angular-eslint/schematics": "18.0.1", + "@angular-eslint/template-parser": "18.0.1", "@angular/compiler-cli": "^18.0.3", "@angular/language-service": "^18.0.3", "@commitlint/cli": "^16.0.1", @@ -110,17 +107,12 @@ "@types/jasminewd2": "~2.0.3", "@types/lodash": "^4.14.115", "@types/node": "^20.9.0", - "@typescript-eslint/eslint-plugin": "^7.2.0", - "@typescript-eslint/parser": "^7.2.0", + "@typescript-eslint/eslint-plugin": "7.11.0", + "@typescript-eslint/parser": "7.11.0", "autoprefixer": "~6", "canonical-path": "0.0.2", "concurrently": "^3.2.0", - "eslint": "^8.57.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-import": "2.26.0", - "eslint-plugin-jsdoc": "39.3.6", - "eslint-plugin-prefer-arrow": "1.2.3", - "eslint-plugin-prettier": "^5.0.1", + "eslint": "8.57.0", "grunt": "^1.0.4", "grunt-bump": "0.8.0", "grunt-coffeelint": "0.0.16", @@ -154,7 +146,6 @@ "postcss": "^8.4.27", "postcss-scss": "^0.1.7", "prettier": "^3.1.0", - "protractor": "~7.0.0", "sass": "^1.48.0", "tailwindcss": "~3.3", "ts-node": "~10.9", @@ -167,4 +158,4 @@ "@nx/nx-linux-x64-gnu": "^18.0", "@nx/nx-win32-x64-msvc": "^18.0" } -} \ No newline at end of file +} diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html index fe96cfb2df..d53ee750f9 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html @@ -26,11 +26,11 @@
@@ -39,11 +39,11 @@ @@ -51,7 +51,12 @@ @@ -63,7 +68,9 @@ - + @@ -75,19 +82,19 @@
- Student + Student + - Name + Name + - Tutor + Tutor + Tutorial - + - Target + Target + Submitted as - + - Stats + Stats - Portfolio? + Portfolio? + - Grade + Grade +
{{student.hasPortfolio ? "Yes" : "No"}} + {{student.hasPortfolio ? "Yes" : "No"}} + {{student.grade}}
Check Similarity @if (upreq.type === 'document') { -TurnItIn -} + TurnItIn + } @if (upreq.type === 'code') { -Moss -} + Moss + } Flag At @if (upreq.type === 'document' && upreq.tiiCheck) { - - -  % - -} + + +  % + + } -
@if (taskDefinition.needsMoss) { -
- - Language used for Moss checks - - C - C# - C++ - Python - - - - Similarity percent to flag for Moss checks - - -
+
+ + Language used for Moss checks + + C + C# + C++ + Python + + + + Similarity percent to flag for Moss checks + + +
} diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts index a8915d843b..3e949c507a 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts @@ -1,7 +1,7 @@ -import { Component, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core'; -import { MatTable, MatTableDataSource } from '@angular/material/table'; -import { TaskDefinition, UploadRequirement } from 'src/app/api/models/task-definition'; -import { Unit } from 'src/app/api/models/unit'; +import {Component, Input, OnChanges, SimpleChanges, ViewChild} from '@angular/core'; +import {MatTable, MatTableDataSource} from '@angular/material/table'; +import {TaskDefinition, UploadRequirement} from 'src/app/api/models/task-definition'; +import {Unit} from 'src/app/api/models/unit'; @Component({ selector: 'f-task-definition-upload', @@ -10,7 +10,7 @@ import { Unit } from 'src/app/api/models/unit'; }) export class TaskDefinitionUploadComponent { @Input() public taskDefinition: TaskDefinition; - @ViewChild('upreqTable', { static: true }) table: MatTable; + @ViewChild('upreqTable', {static: true}) table: MatTable; public columns: string[] = ['file-name', 'file-type', 'tii-check', 'flag-pct', 'row-actions']; @@ -32,7 +32,7 @@ export class TaskDefinitionUploadComponent { public removeUpReq(upreq: UploadRequirement) { this.taskDefinition.uploadRequirements = this.taskDefinition.uploadRequirements.filter( - (anUpReq) => anUpReq.key != upreq.key + (anUpReq) => anUpReq.key != upreq.key, ); } } diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html index 2974d0719a..ef8d12efaa 100644 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ b/src/app/units/states/portfolios/portfolios.tpl.html @@ -51,7 +51,7 @@

Mark Portfolios

All @@ -278,11 +278,7 @@

Review Portfolio of {{selectedStudent.student.name}}

No Portfolio Submitted

- - +
From 59c769c1305cbc3b94fc3e50f105fc57d42ec185 Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Sat, 15 Jun 2024 19:30:07 +1000 Subject: [PATCH 0118/1531] build: upgrade packages --- package-lock.json | 67 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 13 ++++++--- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8702239d8b..d96368f91a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,11 @@ "@angular/upgrade": "^18.0.3", "@ctrl/ngx-emoji-mart": "^9.2.0", "@ngneat/hotkeys": "^4.0.0", + "@uirouter/angular": "^13.0", + "@uirouter/angular-hybrid": "^17.1.0", + "@uirouter/angularjs": "^1.0.30", + "@uirouter/core": "^6.1.0", + "@uirouter/rx": "^1.0.0", "angular": "1.5.11", "angular-cookies": "1.5.11", "angular-eslint": "^18.0.1", @@ -6891,6 +6896,68 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@uirouter/angular": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@uirouter/angular/-/angular-13.0.0.tgz", + "integrity": "sha512-T2aizSXzW+7eiXUmc0LiLH+I8ZBJvDr7OQmm/5WCcxVL2NfuIse7B1kpvfdh9PmBAqw8AY7S0NhrJgABfFJUnw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "@angular/common": "^17.0.0", + "@angular/core": "^17.0.0", + "@uirouter/core": "^6.0.8", + "@uirouter/rx": "^1.0.0" + } + }, + "node_modules/@uirouter/angular-hybrid": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@uirouter/angular-hybrid/-/angular-hybrid-17.1.0.tgz", + "integrity": "sha512-zUQ/b2BaEuODPOtDtxp2SpEifm/VHoLauPTXtZAfcHpDoty6DFbLyGCrA4ZI9lqyoACVxpOuUKjhTHLNE9SXTw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/core": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", + "@angular/upgrade": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", + "@uirouter/angular": "^13.0.0", + "@uirouter/angularjs": "^1.0.30", + "@uirouter/core": "^6.1.0", + "angular": "^1.5.0" + } + }, + "node_modules/@uirouter/angularjs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.1.0.tgz", + "integrity": "sha512-AhgxXhMfN6FU2HxDQqwDPbzmd6kTgvYCgV/kgoCAXfxAH6cFQrifViToC90Wdg6djBynHwA3L/KYP+iOYHkw6A==", + "engines": { + "node": ">=4.0.0" + }, + "peerDependencies": { + "@uirouter/core": "^6.0.8", + "angular": ">=1.2.0" + } + }, + "node_modules/@uirouter/core": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.1.0.tgz", + "integrity": "sha512-WFYh5NPAqRX4L2qlI4k62tgR6pxoqOBSW1CM1uBWCau4mAmgasYd5etJ9RoSJrSnCpCQ2km2Jltf0n5ql684MQ==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@uirouter/rx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@uirouter/rx/-/rx-1.0.0.tgz", + "integrity": "sha512-dqPmLFC+qqF6RIdJVKktXSON6WILy2oyLhADDk74F3GAUZ/VvOu3QSPLDtZEP3LMSo6vkGQvwcUdjgNVWL3YJA==", + "peerDependencies": { + "@uirouter/core": ">=6.0.1", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", diff --git a/package.json b/package.json index 467afeb38c..d92388b974 100644 --- a/package.json +++ b/package.json @@ -9,13 +9,13 @@ "node": ">=20.9.0" }, "scripts": { - "build": "run-s -l build:angular1 build:angular17", + "build": "run-s -l build:angular1 build:angular18", "build:angular1": "grunt build", - "build:angular17": "ng build", + "build:angular18": "ng build", "lint:fix": "ng lint --fix", "lint": "ng lint", - "serve:angular17": "export NODE_OPTIONS=--max_old_space_size=4096 && ng serve --configuration $NODE_ENV", - "start": "npm-run-all -l -s build:angular1 -p watch:angular1 serve:angular17", + "serve:angular18": "export NODE_OPTIONS=--max_old_space_size=4096 && ng serve --configuration $NODE_ENV", + "start": "npm-run-all -l -s build:angular1 -p watch:angular1 serve:angular18", "watch:angular1": "grunt delta", "deploy:build2api": "ng build --delete-output-path=true --optimization=true --configuration production --output-path dist", "deploy": "run-s -l build:angular1 deploy:build2api", @@ -42,6 +42,11 @@ "@angular/upgrade": "^18.0.3", "@ctrl/ngx-emoji-mart": "^9.2.0", "@ngneat/hotkeys": "^4.0.0", + "@uirouter/angular": "^13.0", + "@uirouter/angular-hybrid": "^17.1.0", + "@uirouter/angularjs": "^1.0.30", + "@uirouter/core": "^6.1.0", + "@uirouter/rx": "^1.0.0", "angular": "1.5.11", "angular-cookies": "1.5.11", "angular-eslint": "^18.0.1", From 110271cd7140a31e8dcfca377092ce46181164fc Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Sat, 15 Jun 2024 20:23:14 +1000 Subject: [PATCH 0119/1531] refactor: fix spacing in task scorm card --- .../task-scorm-card.component.html | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html index cec59fc939..81e11cf43c 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html @@ -17,17 +17,16 @@ } -

+

You have successfully completed this knowledge check. You can now proceed to submitting task files.

- - @@ -54,7 +53,7 @@ You have {{ attemptsLeft !== undefined ? attemptsLeft : 'unlimited' }} attempts left to complete this test.

-

+

There will be an increased time delay between test attempts. First 2 attempts will not have a time delay in between.

From 3b7576570394dc0122db73c7052dd5ed97bf0152 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Sat, 15 Jun 2024 20:25:41 +1000 Subject: [PATCH 0120/1531] refactor: add description for scorm time delay --- .../task-definition-scorm.component.html | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html index 5b3b54c111..5321600cf5 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html @@ -24,10 +24,7 @@
-
- - Enable incremental time delays between test attempts - +
Allow students to review completed test attempt @@ -44,5 +41,21 @@ />
+ +
+ + Enable incremental time delays between test attempts + + If enabled, first 2 attempts can be completed immediately. Subsequently, a time delay will + be added, increasing by 2 hours every attempt made. +
}
From ec86e4eca8e9c50ebdaf54c34c302da88dd44b31 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Sat, 15 Jun 2024 21:21:17 +1000 Subject: [PATCH 0121/1531] feat: prevent uploading files until scorm passed --- src/app/api/models/task-definition.ts | 1 + src/app/api/models/task.ts | 24 +++++++-- .../api/services/task-definition.service.ts | 1 + src/app/api/services/test-attempt.service.ts | 2 +- .../task-scorm-card.component.html | 9 ++-- .../task-scorm-card.component.ts | 54 +++++++------------ .../task-definition-scorm.component.html | 3 ++ 7 files changed, 50 insertions(+), 44 deletions(-) diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index ca2d188eb6..050466d740 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -34,6 +34,7 @@ export class TaskDefinition extends Entity { scormEnabled: boolean; hasScormData: boolean; scormAllowReview: boolean; + scormBypassTest: boolean; scormTimeDelayEnabled: boolean; scormAttemptLimit: number = 0; hasTaskAssessmentResources: boolean; diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index ba4bce8e04..2cadc79d72 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -512,9 +512,22 @@ export class Task extends Entity { } public get scormEnabled(): boolean { - return ( - this.definition.scormEnabled && this.definition.hasScormData - ); + return this.definition.scormEnabled && this.definition.hasScormData; + } + + public get scormPassed(): boolean { + if (this.latestCompletedTestAttempt) { + return this.latestCompletedTestAttempt.successStatus; + } + return false; + } + + public get isReadyForUpload(): boolean { + return !this.scormEnabled || this.definition.scormBypassTest || this.scormPassed; + } + + public get latestCompletedTestAttempt(): TestAttempt { + return this.testAttemptCache.currentValues.find((attempt) => attempt.terminated); } public submissionUrl(asAttachment: boolean = false): string { @@ -669,12 +682,15 @@ export class Task extends Entity { public triggerTransition(status: TaskStatusEnum): void { if (this.status === status) return; + const alerts: AlertService = AppInjector.get(AlertService); const requiresFileUpload = ['ready_for_feedback', 'need_help'].includes(status) && this.requiresFileUpload(); - if (requiresFileUpload) { + if (requiresFileUpload && this.isReadyForUpload) { this.presentTaskSubmissionModal(status); + } else if (requiresFileUpload && !this.isReadyForUpload) { + alerts.error('Complete Knowledge Check first to submit files', 6000); } else { this.updateTaskStatus(status); } diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 3776432fd8..9a4a1eeb59 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -96,6 +96,7 @@ export class TaskDefinitionService extends CachedEntityService { 'scormEnabled', 'hasScormData', 'scormAllowReview', + 'scormBypassTest', 'scormTimeDelayEnabled', 'scormAttemptLimit', 'isGraded', diff --git a/src/app/api/services/test-attempt.service.ts b/src/app/api/services/test-attempt.service.ts index df5654855f..3e2c461619 100644 --- a/src/app/api/services/test-attempt.service.ts +++ b/src/app/api/services/test-attempt.service.ts @@ -11,7 +11,7 @@ import {HttpClient} from '@angular/common/http'; @Injectable() export class TestAttemptService extends CachedEntityService { protected readonly endpointFormat = - '/projects/:project_id:/task_def_id/:task_def_id:/test_attempts'; + 'projects/:project_id:/task_def_id/:task_def_id:/test_attempts'; protected readonly latestCompletedEndpoint = this.endpointFormat + '/latest?completed=:completed:'; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html index 81e11cf43c..12df6a4936 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html @@ -1,6 +1,6 @@ @if (isPassed) { - @if (latestCompletedAttempt.scoreScaled === 1) { + @if (this.task.latestCompletedTestAttempt.scoreScaled === 1) { check @@ -8,7 +8,7 @@ > } - @if (latestCompletedAttempt.scoreScaled !== 1) { + @if (this.task.latestCompletedTestAttempt.scoreScaled !== 1) { check @@ -73,7 +73,10 @@ diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts index 25fc9e479a..9860d47741 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts @@ -1,11 +1,5 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; -import { - Task, - TestAttempt, - TestAttemptService, - User, - UserService, -} from 'src/app/api/models/doubtfire-model'; +import {Component, Input, OnChanges, SimpleChanges} from '@angular/core'; +import {Task, User, UserService} from 'src/app/api/models/doubtfire-model'; import {ScormExtensionModalService} from 'src/app/common/modals/scorm-extension-modal/scorm-extension-modal.service'; @Component({ @@ -13,51 +7,39 @@ import {ScormExtensionModalService} from 'src/app/common/modals/scorm-extension- templateUrl: './task-scorm-card.component.html', styleUrls: ['./task-scorm-card.component.scss'], }) -export class TaskScormCardComponent implements OnInit, OnChanges { +export class TaskScormCardComponent implements OnChanges { @Input() task: Task; attemptsLeft: number; isPassed: boolean; - latestCompletedAttempt: TestAttempt; user: User; constructor( private extensions: ScormExtensionModalService, - private testAttemptService: TestAttemptService, private userService: UserService, ) { this.user = this.userService.currentUser; } - ngOnInit() { - this.refreshAttemptData(); - } - ngOnChanges(changes: SimpleChanges) { - if (changes.task && changes.task.currentValue) { - this.refreshAttemptData(); - } - } - - refreshAttemptData(): void { - this.attemptsLeft = undefined; - this.isPassed = undefined; - this.latestCompletedAttempt = undefined; + if (changes.task && changes.task.currentValue && changes.task.currentValue.scormEnabled) { + this.attemptsLeft = undefined; + this.isPassed = undefined; - this.getAttemptsLeft(); - this.testAttemptService.getLatestCompletedAttempt(this.task).subscribe((attempt) => { - this.latestCompletedAttempt = attempt; - this.isPassed = attempt.successStatus; - }); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + this.task?.fetchTestAttempts().subscribe((_) => { + this.getAttemptsLeft(); + if (this.task.latestCompletedTestAttempt) this.isPassed = this.task.scormPassed; + }); + } } getAttemptsLeft(): void { if (this.task.definition.scormAttemptLimit != 0) { - this.task.fetchTestAttempts().subscribe((attempts) => { - let count = attempts.length; - if (count > 0 && attempts[0].terminated === false) count--; - this.attemptsLeft = - this.task.definition.scormAttemptLimit + this.task.scormExtensions - count; - }); + const attempts = this.task.testAttemptCache.currentValues; + let count = attempts.length; + if (count > 0 && attempts[0].terminated === false) count--; + this.attemptsLeft = + this.task.definition.scormAttemptLimit + this.task.scormExtensions - count; } } @@ -70,7 +52,7 @@ export class TaskScormCardComponent implements OnInit, OnChanges { reviewLatestCompletedAttempt(): void { window.open( - `#/task_def_id/${this.task.taskDefId}/scorm-player/review/${this.latestCompletedAttempt.id}`, + `#/task_def_id/${this.task.taskDefId}/scorm-player/review/${this.task.latestCompletedTestAttempt.id}`, '_blank', ); } diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html index 5321600cf5..c2b89f9d7b 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html @@ -28,6 +28,9 @@ Allow students to review completed test attempt + + Allow file upload regardless of test pass status +
Attempt limit From 20da0423450fe3b9b8006660bf6f5e06670f520c Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 18 Jun 2024 19:04:03 +1000 Subject: [PATCH 0122/1531] fix: change success status descriptions --- .../task-scorm-card/task-scorm-card.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html index 12df6a4936..ac1221f87f 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html @@ -4,7 +4,7 @@ check - Knowledge Check PassedKnowledge Check Passed Without Mistakes
} @@ -12,7 +12,7 @@ check - Knowledge Check Passed With MistakesKnowledge Check Passed } @@ -38,7 +38,7 @@ close - Knowledge Check FailedKnowledge Check Unsuccessful } From 14c66a7bc8c1d75f1736d4e1682e78dca1e365de Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Mon, 3 Jun 2024 23:20:12 +1000 Subject: [PATCH 0123/1531] build: upgrade pdf viewer --- package-lock.json | 388 ++++++++++++++++++++++++++++++++++++++++------ package.json | 4 +- 2 files changed, 340 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index f1bfcafa3d..92e5cafe0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,8 +62,8 @@ "moment": "^2.29.4", "ng-csv": "0.2.3", "ng-file-upload": "~5.0.9", - "ng-flex-layout": "^17.3.4-beta.1", - "ng2-pdf-viewer": "^10.0", + "ng-flex-layout": "^17.3.7-beta.1", + "ng2-pdf-viewer": "^10.2", "ngx-bootstrap": "^6.1.0", "ngx-entity-service": "^0.0.38", "ngx-lottie": "^11.0.2", @@ -3836,6 +3836,90 @@ "node": ">= 0.4" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "optional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "optional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@material/animation": { "version": "15.0.0-canary.7f224ddd4.0", "resolved": "https://registry.npmjs.org/@material/animation/-/animation-15.0.0-canary.7f224ddd4.0.tgz", @@ -6926,6 +7010,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -8134,6 +8238,21 @@ "integrity": "sha512-y8EIEvL+IW81S4hRQWCRFtly+g1cc1G+wxHpjhYR9jI2+JJjWiaKnkH8mmvNHOMOAd9fzgARDO3AEzjuR51qaA==", "dev": true }, + "node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/canvas-confetti": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.3.tgz", @@ -8573,6 +8692,15 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -8701,7 +8829,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "devOptional": true }, "node_modules/concurrently": { "version": "3.6.1", @@ -8805,6 +8933,12 @@ "date-now": "^0.1.4" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true + }, "node_modules/constantinople": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz", @@ -9452,6 +9586,18 @@ "node": ">=0.10" } }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "optional": true, + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -9620,6 +9766,12 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -9657,6 +9809,15 @@ "node": ">=0.10.0" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", @@ -9795,12 +9956,6 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/dommatrix": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dommatrix/-/dommatrix-1.0.3.tgz", - "integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww==", - "deprecated": "dommatrix is no longer maintained. Please use @thednp/dommatrix." - }, "node_modules/domutils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", @@ -11649,7 +11804,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "devOptional": true }, "node_modules/function-bind": { "version": "1.1.2", @@ -11686,6 +11841,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/gaze": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", @@ -11830,7 +12006,7 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, + "devOptional": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -11868,7 +12044,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "devOptional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11878,7 +12054,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, + "devOptional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -13455,6 +13631,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true + }, "node_modules/has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -13984,7 +14166,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, + "devOptional": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -16580,6 +16762,18 @@ "node": ">=6" } }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -16999,6 +17193,12 @@ "thenify-all": "^1.0.0" } }, + "node_modules/nan": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", + "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==", + "optional": true + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -17191,9 +17391,9 @@ "integrity": "sha512-298k/s42+cyHLFAWCtgmXHGOUFqAh5VviSbMuQAPfqAavK1h9ADU/A+gN7OLmgNhW9PM94bWSt22LpjO/cvKwA==" }, "node_modules/ng-flex-layout": { - "version": "17.3.4-beta.1", - "resolved": "https://registry.npmjs.org/ng-flex-layout/-/ng-flex-layout-17.3.4-beta.1.tgz", - "integrity": "sha512-MmXj7Cq9cBSDgJKT3vOok2YCq3OcUD4zhPaKup9V5lVJLZ38sHPgfPf5fFBjDZO7R6AD66wYPod0i4zW5LrrgA==", + "version": "17.3.7-beta.1", + "resolved": "https://registry.npmjs.org/ng-flex-layout/-/ng-flex-layout-17.3.7-beta.1.tgz", + "integrity": "sha512-MTjlQUldB/hEsn0DY/RoY2SKBQoyaKltlOOFjCjH2OfcYA3COHhkJS3PZe9NAjR7TBDb9Ve989m18bSucRzACQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -17206,15 +17406,12 @@ } }, "node_modules/ng2-pdf-viewer": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/ng2-pdf-viewer/-/ng2-pdf-viewer-10.0.0.tgz", - "integrity": "sha512-zEefcAsTpDoxFceQYs3ycPMaUAkt5UX4OcTstVQoNqRK6w+vOY+V8z8aFCuBwnt+7iN1EHaIpquOf4S9mWc04g==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/ng2-pdf-viewer/-/ng2-pdf-viewer-10.2.2.tgz", + "integrity": "sha512-GaKAvF0nXAiR9U4LFWuT54MM9nzp0ie8GGscp34W+lFsSOXdlwS0iFx5UPuVlODRm3YEUKx6xcK5oaJeBq0SAw==", "dependencies": { - "pdfjs-dist": "~2.16.105", + "pdfjs-dist": "^3.11.174", "tslib": "^2.3.0" - }, - "peerDependencies": { - "pdfjs-dist": "~2.16.105" } }, "node_modules/ngx-bootstrap": { @@ -17288,6 +17485,26 @@ "dev": true, "optional": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -17694,6 +17911,19 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -17963,7 +18193,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -18139,7 +18369,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, + "devOptional": true, "dependencies": { "wrappy": "1" } @@ -18617,7 +18847,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -18700,21 +18930,25 @@ "node": ">=8" } }, + "node_modules/path2d-polyfill": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz", + "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/pdfjs-dist": { - "version": "2.16.105", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz", - "integrity": "sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==", - "dependencies": { - "dommatrix": "^1.0.3", - "web-streams-polyfill": "^3.2.1" - }, - "peerDependencies": { - "worker-loader": "^3.0.8" + "version": "3.11.174", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz", + "integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==", + "engines": { + "node": ">=18" }, - "peerDependenciesMeta": { - "worker-loader": { - "optional": true - } + "optionalDependencies": { + "canvas": "^2.11.2", + "path2d-polyfill": "^2.0.1" } }, "node_modules/performance-now": { @@ -20919,7 +21153,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, + "devOptional": true, "dependencies": { "glob": "^7.1.3" }, @@ -21794,12 +22028,43 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true + }, "node_modules/simple-fmt": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/simple-fmt/-/simple-fmt-0.1.0.tgz", "integrity": "sha512-9a3zTDDh9LXbTR37qBhACWIQ/mP/ry5xtmbE98BJM8GR02sanCkfMzp7AdCTqYhkBZggK/w7hJtc8Pb9nmo16A==", "dev": true }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "optional": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/simple-is": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/simple-is/-/simple-is-0.2.0.tgz", @@ -23174,6 +23439,12 @@ "node": ">=0.8" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true + }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -24040,14 +24311,6 @@ "defaults": "^1.0.3" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "engines": { - "node": ">= 8" - } - }, "node_modules/webdriver-js-extender": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", @@ -24168,6 +24431,12 @@ "node": ">=0.8.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true + }, "node_modules/webpack": { "version": "5.90.3", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", @@ -24490,6 +24759,16 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -24544,6 +24823,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", @@ -24694,7 +24982,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "devOptional": true }, "node_modules/ws": { "version": "8.11.0", diff --git a/package.json b/package.json index 272c6019b9..3f95891a81 100644 --- a/package.json +++ b/package.json @@ -79,8 +79,8 @@ "moment": "^2.29.4", "ng-csv": "0.2.3", "ng-file-upload": "~5.0.9", - "ng-flex-layout": "^17.3.4-beta.1", - "ng2-pdf-viewer": "^10.0", + "ng-flex-layout": "^17.3.7-beta.1", + "ng2-pdf-viewer": "^10.2", "ngx-bootstrap": "^6.1.0", "ngx-entity-service": "^0.0.38", "ngx-lottie": "^11.0.2", From da376b9bc7905aadeb4d234cbb4f595e4c4424a1 Mon Sep 17 00:00:00 2001 From: jakerenzella Date: Sat, 15 Jun 2024 00:10:27 +1000 Subject: [PATCH 0124/1531] fix: fix pdf viewer for portfolios --- .../pdf-viewer/pdf-viewer.component.html | 41 +++++++--- .../common/pdf-viewer/pdf-viewer.component.ts | 9 +- .../units/states/portfolios/portfolios.coffee | 4 +- .../states/portfolios/portfolios.tpl.html | 82 +++++++++++++++---- 4 files changed, 107 insertions(+), 29 deletions(-) diff --git a/src/app/common/pdf-viewer/pdf-viewer.component.html b/src/app/common/pdf-viewer/pdf-viewer.component.html index 232c89d5ed..87dc97c996 100644 --- a/src/app/common/pdf-viewer/pdf-viewer.component.html +++ b/src/app/common/pdf-viewer/pdf-viewer.component.html @@ -3,25 +3,44 @@
search - + - -
@if (pdfBlobUrl) { - + } diff --git a/src/app/common/pdf-viewer/pdf-viewer.component.ts b/src/app/common/pdf-viewer/pdf-viewer.component.ts index 23d5029b2f..5cd893b5a9 100644 --- a/src/app/common/pdf-viewer/pdf-viewer.component.ts +++ b/src/app/common/pdf-viewer/pdf-viewer.component.ts @@ -7,6 +7,8 @@ import { SimpleChanges, OnChanges, ViewChild, + OnInit, + AfterViewInit, } from '@angular/core'; import {PdfViewerComponent} from 'ng2-pdf-viewer'; import {FileDownloaderService} from '../file-downloader/file-downloader.service'; @@ -17,7 +19,7 @@ import {AlertService} from '../services/alert.service'; templateUrl: './pdf-viewer.component.html', styleUrls: ['./pdf-viewer.component.scss'], }) -export class fPdfViewerComponent implements OnDestroy, OnChanges { +export class fPdfViewerComponent implements OnDestroy, OnChanges, AfterViewInit { private _pdfUrl: string; public pdfBlobUrl: string; @Input() pdfUrl: string; @@ -38,6 +40,11 @@ export class fPdfViewerComponent implements OnDestroy, OnChanges { } } + ngAfterViewInit(): void { + console.log("pdfUrl"); + console.log(this.pdfUrl); + } + ngOnChanges(changes: SimpleChanges): void { this.pdfUrlChanges(changes.pdfUrl.currentValue); } diff --git a/src/app/units/states/portfolios/portfolios.coffee b/src/app/units/states/portfolios/portfolios.coffee index 7e745b33d1..41d0b60797 100644 --- a/src/app/units/states/portfolios/portfolios.coffee +++ b/src/app/units/states/portfolios/portfolios.coffee @@ -122,7 +122,9 @@ angular.module('doubtfire.units.states.portfolios', []) $scope.selectedStudent = student $scope.project = null newProjectService.loadProject(student, $scope.unit).subscribe({ - next: (project) -> $scope.project = project + next: (project) -> + $scope.project = project + $scope.project.preloadedUrl = $scope.project.portfolioUrl() error: (message) -> alertService.error( message, 6000) }) ) diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html index 075680654c..2974d0719a 100644 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ b/src/app/units/states/portfolios/portfolios.tpl.html @@ -27,7 +27,11 @@

Mark Portfolios

>
@@ -39,7 +43,11 @@

Mark Portfolios

-
- +
@@ -172,7 +210,9 @@

Mark Portfolios

- + @@ -237,7 +277,13 @@

Review Portfolio of {{selectedStudent.student.name}}

No Portfolio Submitted

- +
+ + +
@@ -260,8 +306,12 @@

Grade for {{selectedStudent.student.name}}

ng-class="{'no-rationale': project.gradeRationale == null}" ng-hide="editingRationale" > - -
+ +
Click to add one
From a2e8a9c1bef2f2cbf3a32683ee84302c061b90ef Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:24:39 +1000 Subject: [PATCH 0125/1531] refactor: show consecutive scorm comments together --- .../api/models/task-comment/scorm-comment.ts | 3 ++ src/app/api/models/task.ts | 9 ++++ .../scorm-comment.component.html | 54 +++++++++++-------- .../scorm-comment.component.scss | 6 +-- .../scorm-comment/scorm-comment.component.ts | 4 -- 5 files changed, 44 insertions(+), 32 deletions(-) diff --git a/src/app/api/models/task-comment/scorm-comment.ts b/src/app/api/models/task-comment/scorm-comment.ts index 3356b62b93..b15a2c50c8 100644 --- a/src/app/api/models/task-comment/scorm-comment.ts +++ b/src/app/api/models/task-comment/scorm-comment.ts @@ -3,6 +3,9 @@ import {Task, TaskComment, TestAttempt} from '../doubtfire-model'; export class ScormComment extends TaskComment { testAttempt: TestAttempt; + // UI rendering data + lastInScormSeries: boolean = false; + constructor(task: Task) { super(task); } diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index 2cadc79d72..0643f99732 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -17,6 +17,7 @@ import { TaskSimilarityService, TestAttempt, TestAttemptService, + ScormComment, } from './doubtfire-model'; import {Grade} from './grade'; import {LOCALE_ID} from '@angular/core'; @@ -385,6 +386,14 @@ export class Task extends Entity { if (comments[i].replyToId) { comments[i].originalComment = comments.find((tc) => tc.id === comments[i].replyToId); } + + // Scorm series + if (comments[i].commentType === 'scorm') { + comments[i].firstInSeries = i === 0 || comments[i - 1].commentType !== 'scorm'; + (comments[i] as ScormComment).lastInScormSeries = + i + 1 === comments.length || comments[i + 1]?.commentType !== 'scorm'; + if (!comments[i].firstInSeries) comments[i].shouldShowTimestamp = false; + } } comments[comments.length - 1].shouldShowAvatar = true; diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html index c1dacaa788..edde1e057c 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html @@ -1,24 +1,32 @@ -
-
-
-
-
-
- - - -
-
-
-
+
+
+ +
+ + + + +
+
diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.scss b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.scss index 31df73023a..7bc5f74d91 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.scss +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.scss @@ -1,7 +1,3 @@ -div { - width: 100%; -} - p { color: #2c2c2c; text-align: center; @@ -14,7 +10,7 @@ hr { .hr-fade { background: linear-gradient(to right, transparent, #9696969d, transparent); width: 100%; - margin-top: 1px; + margin-top: 6px; } .hr-text { diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts index 87daf5b6ca..a16e397ad6 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts @@ -27,10 +27,6 @@ export class ScormCommentComponent { this.user = this.userService.currentUser; } - get canOverridePass(): boolean { - return this.user.isStaff && !this.comment.testAttempt.successStatus; - } - reviewScormTest() { window.open( `#/task_def_id/${this.task.taskDefId}/scorm-player/review/${this.comment.testAttempt.id}`, From b6887e85b7a06b166519924dd682ef57650a4e32 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:46:43 +1000 Subject: [PATCH 0126/1531] fix: delete comment as well as test attempt --- .../scorm-comment/scorm-comment.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts index a16e397ad6..d26b914f7e 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts @@ -50,6 +50,7 @@ export class ScormCommentComponent { 'Are you sure you want to delete this test attempt? This action is final and will delete information associated with this test attempt.', () => { this.testAttemptService.deleteAttempt(this.comment.testAttempt.id); + this.comment.delete(); }, ); } From fd916b94e9012c0909c5880f377f93d326c18e4d Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Thu, 20 Jun 2024 22:09:57 +1000 Subject: [PATCH 0127/1531] fix: ensure portfolio can get grades from strings --- src/app/common/grade-icon/grade-icon.coffee | 2 +- src/app/common/services/grade.service.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/common/grade-icon/grade-icon.coffee b/src/app/common/grade-icon/grade-icon.coffee index be0ed0b0c3..54480aff9f 100644 --- a/src/app/common/grade-icon/grade-icon.coffee +++ b/src/app/common/grade-icon/grade-icon.coffee @@ -9,7 +9,7 @@ angular.module('doubtfire.common.grade-icon', []) colorful: '=?' controller: ($scope, gradeService) -> $scope.$watch 'inputGrade', (newGrade) -> - $scope.grade = if _.isString($scope.inputGrade) then gradeService.grades.indexOf($scope.inputGrade) else $scope.inputGrade + $scope.grade = if _.isString($scope.inputGrade) then gradeService.stringToGrade($scope.inputGrade) else $scope.inputGrade $scope.gradeText = (grade) -> if $scope.grade? then gradeService.grades[$scope.grade] or "Grade" $scope.gradeLetter = (grade) -> diff --git a/src/app/common/services/grade.service.ts b/src/app/common/services/grade.service.ts index 619bad36f5..35e0f24f2a 100644 --- a/src/app/common/services/grade.service.ts +++ b/src/app/common/services/grade.service.ts @@ -16,6 +16,10 @@ export class GradeService { 3: 'High Distinction', }; + public stringToGrade(value: string): number { + return this.gradeViewData.find((grade) => grade.viewValue === value)?.value; + } + gradeViewData = [ {value: -1, viewValue: 'Fail'}, {value: 0, viewValue: 'Pass'}, From ce970f5fdc4f42708edc71c98dc9d869056e9e2c Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Fri, 21 Jun 2024 21:21:07 +1000 Subject: [PATCH 0128/1531] fix: ensure portfolio only shown when it exists --- src/app/units/states/portfolios/portfolios.tpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html index a51934b9a5..2b8a2277eb 100644 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ b/src/app/units/states/portfolios/portfolios.tpl.html @@ -277,7 +277,7 @@

Review Portfolio of {{selectedStudent.student.name}}

No Portfolio Submitted

-
+
Date: Fri, 21 Jun 2024 21:21:27 +1000 Subject: [PATCH 0129/1531] chore(release): 8.0.10 --- CHANGELOG.md | 326 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 4 +- package.json | 2 +- 3 files changed, 329 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ca7d64128..887dcb3746 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,332 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [8.0.10](https://github.com/macite/doubtfire-deploy/compare/v7.0.23...v8.0.10) (2024-06-21) + + +### Bug Fixes + +* ensure loading screen removed in sign in component ([729c438](https://github.com/macite/doubtfire-deploy/commit/729c438f7f6a988f5ff2fa4035493b5cae1c98f7)) +* ensure portfolio can get grades from strings ([fd916b9](https://github.com/macite/doubtfire-deploy/commit/fd916b94e9012c0909c5880f377f93d326c18e4d)) +* ensure portfolio only shown when it exists ([ce970f5](https://github.com/macite/doubtfire-deploy/commit/ce970f5fdc4f42708edc71c98dc9d869056e9e2c)) +* ensure tii open report alerts errors ([c5dd45c](https://github.com/macite/doubtfire-deploy/commit/c5dd45c57fd34e8373f11d065a0cd08edef0a794)) +* fix pdf viewer for portfolios ([da376b9](https://github.com/macite/doubtfire-deploy/commit/da376b9bc7905aadeb4d234cbb4f595e4c4424a1)) +* grade icon for portfolio page ([aab1b9c](https://github.com/macite/doubtfire-deploy/commit/aab1b9c3e7365cdf7dd64d767fdb6e5a9a2436a3)) +* show burndown and pie chart on portfolio page ([e70f4c7](https://github.com/macite/doubtfire-deploy/commit/e70f4c7cd1395eaab942ee389788f75f92e985c9)) + +### [8.0.9](https://github.com/macite/doubtfire-deploy/compare/v7.0.22...v8.0.9) (2024-05-31) + + +### Bug Fixes + +* comment out fix and complete hotkeys temporarily ([c1f623d](https://github.com/macite/doubtfire-deploy/commit/c1f623d17432f3563366ef32fc3da3b54dbef0b7)) + +### [8.0.8](https://github.com/macite/doubtfire-deploy/compare/v8.0.7...v8.0.8) (2024-05-30) + + +### Features + +* added percentage to tooltip when hovering student's task progress ([69ed613](https://github.com/macite/doubtfire-deploy/commit/69ed61380bd7681d4496cb109e628111873b6e82)) + + +### Bug Fixes + +* change from hiding element to not loading ([414da65](https://github.com/macite/doubtfire-deploy/commit/414da65fcef9b10367f53112239a60e1b271d475)) +* change grade values, change grade display ([081c35b](https://github.com/macite/doubtfire-deploy/commit/081c35ba0fbc7ab4ddb2fba3c58892d0e66f325c)) +* fix task inbox shortcuts ([9bc949f](https://github.com/macite/doubtfire-deploy/commit/9bc949fd6dcb71ea165e89de9a4ec9d9347e6562)) +* inbox search box width ([02a99a8](https://github.com/macite/doubtfire-deploy/commit/02a99a8f71033014b26260d3b0dbfca075ca7273)) +* remove pdf viewer on task view when no sheet ([f3e973d](https://github.com/macite/doubtfire-deploy/commit/f3e973dacc5b079ab58da239194d802c5586ca07)) +* revert index changes, html changes for grade ([8f41cd1](https://github.com/macite/doubtfire-deploy/commit/8f41cd1656971963c2035a9249acdde0a257766e)) +* task list scrolling ([0088e9e](https://github.com/macite/doubtfire-deploy/commit/0088e9e245dbd326dea4032239b53eee88754179)) +* use tailwind classes instead of css styling ([42434a5](https://github.com/macite/doubtfire-deploy/commit/42434a5fd4b866781da5d23ecdb0b9b4369aace1)) + +### [8.0.7](https://github.com/macite/doubtfire-deploy/compare/v8.0.6...v8.0.7) (2024-05-26) + + +### Bug Fixes + +* add task description editing ([ee0cfbf](https://github.com/macite/doubtfire-deploy/commit/ee0cfbf7ce804a1806ca5810bad138b97703ebfe)) + +### [8.0.6](https://github.com/macite/doubtfire-deploy/compare/v8.0.5...v8.0.6) (2024-05-25) + + +### Bug Fixes + +* ensure all admin units are fully loaded ([917325e](https://github.com/macite/doubtfire-deploy/commit/917325ed08b89690a7eea0716438673732ba1ec9)) + +### [8.0.5](https://github.com/macite/doubtfire-deploy/compare/v8.0.4...v8.0.5) (2024-05-25) + + +### Bug Fixes + +* ensure (click) is on button, not mat-icon ([99c717d](https://github.com/macite/doubtfire-deploy/commit/99c717d2333de0975da1b3f282195a0b3577a3f6)) + +### [8.0.4](https://github.com/macite/doubtfire-deploy/compare/v8.0.3...v8.0.4) (2024-05-25) + + +### Bug Fixes + +* fix various issues with admin unit list ([3720666](https://github.com/macite/doubtfire-deploy/commit/3720666fb4105bac274449eb468ce34e0f68bae7)) + +### [8.0.3](https://github.com/macite/doubtfire-deploy/compare/v8.0.2...v8.0.3) (2024-05-25) + + +### Features + +* add 4-character abbreviations ([eb62dfc](https://github.com/macite/doubtfire-deploy/commit/eb62dfc90db836870d6c396727fc43c149808e9d)) + +### [8.0.2](https://github.com/macite/doubtfire-deploy/compare/v8.0.1...v8.0.2) (2024-05-25) + + +### Bug Fixes + +* gradeservice bugs ([fd6eb1c](https://github.com/macite/doubtfire-deploy/commit/fd6eb1cd152b72cf297cbd6bd529579858afc543)) +* gradeservice bugs ([7545eb9](https://github.com/macite/doubtfire-deploy/commit/7545eb92b9353d99ac8d8d7d89982cdadf9688b1)) + +### [8.0.1](https://github.com/macite/doubtfire-deploy/compare/v8.0.0...v8.0.1) (2024-05-24) + + +### Features + +* implement live PDF search that updates dynamically as you type ([b9b9945](https://github.com/macite/doubtfire-deploy/commit/b9b9945346d55392e5ee9a6431d85ae92de1bde5)) + + +### Bug Fixes + +* fix critical bugs ([356846e](https://github.com/macite/doubtfire-deploy/commit/356846e5c385c484a6034553366965cde95ec78b)) +* fix splashscreen ([2692b7f](https://github.com/macite/doubtfire-deploy/commit/2692b7f4a3e1ca2a5bc4df3b82a9dfd4aa2ec68a)) + +## [8.0.0](https://github.com/macite/doubtfire-deploy/compare/v8.0.0-6...v8.0.0) (2024-05-23) + + +### Features + +* add multi-badge support ([44c1473](https://github.com/macite/doubtfire-deploy/commit/44c1473700a3d7a4a025d68acac5aa61189d8b52)) +* add synchronised multi-badge ([f70ebdc](https://github.com/macite/doubtfire-deploy/commit/f70ebdca92a05e5ca350d4062a8dc8efba9fd681)) +* add working unit-badge ([dd30247](https://github.com/macite/doubtfire-deploy/commit/dd302478e97228e6bfbfdbee0134abb3eabf2587)) +* add working unit-badge ([c7338ff](https://github.com/macite/doubtfire-deploy/commit/c7338ffd88edb457a3443b43ea21706c43231973)) +* qol improvements for unit codes ([f7f928e](https://github.com/macite/doubtfire-deploy/commit/f7f928e485448a69b054dca94f07d623f84e328f)) +* small fixes to home and unit code ([918e804](https://github.com/macite/doubtfire-deploy/commit/918e8047745b489aae1fafdc67720568dd8d829e)) + + +### Bug Fixes + +* add missing imports ([659b52c](https://github.com/macite/doubtfire-deploy/commit/659b52c82a26b9496a3dba81401b5147d05248ae)) +* change time exceeded to feedback exceeded ([673619d](https://github.com/macite/doubtfire-deploy/commit/673619d99f177d834fba3643171426092e0d05e0)) +* correct task resource upload actions ([5e9c9b1](https://github.com/macite/doubtfire-deploy/commit/5e9c9b1d05d6d6975fd4ba3a3176314ddd7d8514)) +* ensure loading state changed after projects and unit roles load ([9171d0c](https://github.com/macite/doubtfire-deploy/commit/9171d0c2c37c17d26f464f6aa0ba7c479851e6eb)) +* ensure staff task list checks unit exists ([dbb312d](https://github.com/macite/doubtfire-deploy/commit/dbb312dc3c5c9e2be24161914e8d95e1a5c1bc53)) +* ensure unit load updates unit object if it already exists ([e48ffad](https://github.com/macite/doubtfire-deploy/commit/e48ffadf63891212c3e40ab696d54a3935485b08)) +* hide overseer settings if automation disabled ([0c08fe3](https://github.com/macite/doubtfire-deploy/commit/0c08fe3e82a78dd1e91fb44ce6008fb5298c46ee)) +* slide unit code off left side ([8cd57b5](https://github.com/macite/doubtfire-deploy/commit/8cd57b589812fd59c6da4de02246791fb4410959)) +* sort units desc by start date ([9b78856](https://github.com/macite/doubtfire-deploy/commit/9b788561372a3ddf065d3b28e547a2194ef29655)) +* zip upload for overseer ([5ad2085](https://github.com/macite/doubtfire-deploy/commit/5ad2085b2d730235f61e7b7c603727d8b6736cf2)) + +## [8.0.0-6](https://github.com/macite/doubtfire-deploy/compare/v8.0.0-5...v8.0.0-6) (2024-05-13) + +## [8.0.0-5](https://github.com/macite/doubtfire-deploy/compare/v8.0.0-4...v8.0.0-5) (2024-05-13) + +## [8.0.0-4](https://github.com/macite/doubtfire-deploy/compare/v8.0.0-3...v8.0.0-4) (2024-05-11) + + +### Features + +* add task badge ([b48cd4c](https://github.com/macite/doubtfire-deploy/commit/b48cd4c99333e41c0c1d32531e571d32bb482a81)) + + +### Bug Fixes + +* (WIP) fix alert service migration ([3d9f4dc](https://github.com/macite/doubtfire-deploy/commit/3d9f4dc05e7a45884dc383e0f5ed4bdb09b0558d)) +* add max length validator and change reason field to text-area ([6227200](https://github.com/macite/doubtfire-deploy/commit/6227200566c3f608c279e92a3f255a7e94148c1d)) +* address linter issues in task.ts ([14e9699](https://github.com/macite/doubtfire-deploy/commit/14e9699bdfe336f1e3f3cce3d722c835d58f3cdb)) +* copy dist browser to nginx html ([08fa919](https://github.com/macite/doubtfire-deploy/commit/08fa91937e028cb3ee093709e5a31f94da44fc33)) +* correct filenames for grotesk fonts ([9bedd81](https://github.com/macite/doubtfire-deploy/commit/9bedd812b12628df9cb32e48cb91a88b5cdf69b1)) +* ensure eula state remains visible ([131540c](https://github.com/macite/doubtfire-deploy/commit/131540ca4b934773afd9f72aa2578579048ed6a2)) +* ensure unit admin shows all units ([02b7a15](https://github.com/macite/doubtfire-deploy/commit/02b7a15bbbd2306a61e344f995dffb72a3915498)) +* fix course progress bar on firefox ([ae5c1e0](https://github.com/macite/doubtfire-deploy/commit/ae5c1e0b5901bae0411cf7bbaa32ee8f340b908a)) +* fix incorrect projcets listed in dropdown ([6a7e478](https://github.com/macite/doubtfire-deploy/commit/6a7e4788b522e5af6331a82ed33e9c9137d2ca86)) +* fix margin issue on dropdown ([c8145f0](https://github.com/macite/doubtfire-deploy/commit/c8145f0972a03e52377e0203cabb2cf6353db8b3)) +* grade and quality point display on task-assessment-card ([7cba502](https://github.com/macite/doubtfire-deploy/commit/7cba502e002143e8255bf0d786551bd270f73f0e)) +* indicate mandatory fields in upload-submission-modal ([e8801e2](https://github.com/macite/doubtfire-deploy/commit/e8801e2a64fe15ad423d9017d10e5e23f6e00eda)) +* only check grade if it exists ([1c213c5](https://github.com/macite/doubtfire-deploy/commit/1c213c53571f79563e9a071e2dd9645598382522)) +* remove unused imports in extension-modal.service ([8081f51](https://github.com/macite/doubtfire-deploy/commit/8081f51b5f28ea511b9f76d026ae63f16153ae2c)) +* use tailwindcss classes ([8d7e160](https://github.com/macite/doubtfire-deploy/commit/8d7e160e2d40c42284ee0c1fc85d6d9e01166cda)) + +## [8.0.0-3](https://github.com/macite/doubtfire-deploy/compare/v8.0.0-2...v8.0.0-3) (2024-05-02) + + +### Bug Fixes + +* reenable eula html fetch ([cda9e52](https://github.com/macite/doubtfire-deploy/commit/cda9e52a259bfaa27e8252f40e579d11d1af280c)) + +## [8.0.0-2](https://github.com/macite/doubtfire-deploy/compare/v7.0.21...v8.0.0-2) (2024-05-01) + + +### Features + +* accept promela files ([df93a69](https://github.com/macite/doubtfire-deploy/commit/df93a69e45d2d9e41b9cf0802d521a3663d7a36c)) +* migrate unit list in all locations ([6651d00](https://github.com/macite/doubtfire-deploy/commit/6651d0011446fdde7179c5173f902ce2e4ea7545)) +* remove misleading progress statement ([63e276c](https://github.com/macite/doubtfire-deploy/commit/63e276c041f77d8b401d24a4f49896cfa2095442)) + + +### Bug Fixes + +* correct change detection on task def ([55daff2](https://github.com/macite/doubtfire-deploy/commit/55daff234441a242d96de097c2b2912df0c6c9a8)) +* correct npm install for dev container image ([5126c3b](https://github.com/macite/doubtfire-deploy/commit/5126c3ba7fed55217e88c54c25dc70595ec4c666)) +* ensure npm will force install ([f91751e](https://github.com/macite/doubtfire-deploy/commit/f91751eae788bc3f65d33b610ed80c96d3978974)) +* fix firefox-specific bug ([6b6054b](https://github.com/macite/doubtfire-deploy/commit/6b6054bd5c1104a96ccac413a7115009eeba8d2f)) +* remove ngClass ([d1d8c72](https://github.com/macite/doubtfire-deploy/commit/d1d8c72ace21551a68bd4d0a8ba88eabb2ebdb9d)) +* remove plagiarism checks ([21b02fb](https://github.com/macite/doubtfire-deploy/commit/21b02fb7cc616090f1fb2d26f65b336072f9105b)) +* remove the incorrect option from for scrollIntoView() ([9e752fe](https://github.com/macite/doubtfire-deploy/commit/9e752fe9d49df786ceb3e7007cbf0aad57809604)) +* remove unused loading from f-units ([c4c38fa](https://github.com/macite/doubtfire-deploy/commit/c4c38fad4fbdfe248e383cf247f949197ad0a047)) +* typo ([820c56f](https://github.com/macite/doubtfire-deploy/commit/820c56f3a1bc30b7637b98e6f80b406ca350b5b8)) + +## [8.0.0-1](https://github.com/macite/doubtfire-deploy/compare/v8.0.0-0...v8.0.0-1) (2024-03-21) + + +### Bug Fixes + +* update deploy dockerfile ([41a5161](https://github.com/macite/doubtfire-deploy/commit/41a5161b356931eafd8e4caf256f311f10bc8bb4)) + +## [8.0.0-0](https://github.com/macite/doubtfire-deploy/compare/v7.0.18...v8.0.0-0) (2024-03-21) + + +### Features + +* (wip) add similarities notification ([8e4a198](https://github.com/macite/doubtfire-deploy/commit/8e4a198a037de832bbebe96e309c4c8485d076cc)) +* add ability to accept tii eula to model ([0106b01](https://github.com/macite/doubtfire-deploy/commit/0106b01ed249139cbe06096f95a36b5d11bcd0ac)) +* add ability to accept turn it in eula ([380ad1e](https://github.com/macite/doubtfire-deploy/commit/380ad1e93252f8f928893626b65f4dab01813524)) +* add ability to open turnitin viewer ([5248e80](https://github.com/macite/doubtfire-deploy/commit/5248e80622e55b79ce4d7b35f8202ee8099c2dce)) +* add ability to update similarity flag ([de005ee](https://github.com/macite/doubtfire-deploy/commit/de005ee98a270998e2175109783cab72b92e36f3)) +* add dynamic footer ([3c62fe0](https://github.com/macite/doubtfire-deploy/commit/3c62fe06d009c3b752259f50887c625c98a371cd)) +* add empty pdf view to new task dashboard ([9c3cdfb](https://github.com/macite/doubtfire-deploy/commit/9c3cdfbb93711a6ae911ed461651200d8c75db48)) +* add file drop component ([c211003](https://github.com/macite/doubtfire-deploy/commit/c211003004ae6c7505158a65ce2006b219920827)) +* add footer content ([735c43b](https://github.com/macite/doubtfire-deploy/commit/735c43b5c2df7e8f367310ad92ef716fd5140375)) +* add link to student task from inbox ([d4301e0](https://github.com/macite/doubtfire-deploy/commit/d4301e0d1f2f6ec4c563801a7f0d1132884f9989)) +* add mobile inbox view ([56ded70](https://github.com/macite/doubtfire-deploy/commit/56ded707e638ae769665a863ce65acffea5a588a)) +* add multi-file support to f-upload ([d181969](https://github.com/macite/doubtfire-deploy/commit/d181969198e2b7611e3f0e330577b825e99a248f)) +* add new file upload component ([891ab20](https://github.com/macite/doubtfire-deploy/commit/891ab20eb6f1d545ff58d0157fdd9912b9546c9f)) +* add new inbox component ([ec0f62c](https://github.com/macite/doubtfire-deploy/commit/ec0f62c488ae3e99e9487ea1ab87f5bb2f1fbed7)) +* add new pdf-viewer ([617fbd2](https://github.com/macite/doubtfire-deploy/commit/617fbd24f8424541aeb87b16651f06737b570633)) +* add new similarity component ([48ba01c](https://github.com/macite/doubtfire-deploy/commit/48ba01c8d780a04a1f526f89fcd9bc63ef5d4aec)) +* add new task assessment card ([ac3b50f](https://github.com/macite/doubtfire-deploy/commit/ac3b50f29b8a2722d09ad94a2f82bb54c1c32da7)) +* add new task dashboard component ([dc841f9](https://github.com/macite/doubtfire-deploy/commit/dc841f9e7af811a3a56a0c21fd3b3968ec7aead9)) +* add new task due card ([3ade5ea](https://github.com/macite/doubtfire-deploy/commit/3ade5ea34eb3c2c756d7df0f7a6c250fa50290bb)) +* add new task due card content ([c43ea3e](https://github.com/macite/doubtfire-deploy/commit/c43ea3e27abdf253596bfedd5112f5ef7a7b929d)) +* add new task submission card ([6d27690](https://github.com/macite/doubtfire-deploy/commit/6d2769029413f84b73c7c825d16e9a3366142177)) +* add pdf search and zoom ([f83ce57](https://github.com/macite/doubtfire-deploy/commit/f83ce570e80dc20d118288c6d32c2d2a9ca263b5)) +* add resizable inbox panels ([4920e31](https://github.com/macite/doubtfire-deploy/commit/4920e31ce366c3dfb4340ab4da159b176381cf49)) +* add resizable panels to inbox ([5abda03](https://github.com/macite/doubtfire-deploy/commit/5abda039af5b2d3b5e2589c4864b2e1715c5e8c0)) +* add rest of layout to footer ([3b9de7c](https://github.com/macite/doubtfire-deploy/commit/3b9de7cc6d923a0e6431524f2967b5e3bc360a6f)) +* add selected task sheet url ([00a7fb5](https://github.com/macite/doubtfire-deploy/commit/00a7fb516d362d3725b915d012878a9ccf8ef009)) +* add selectedTask service ([02aa41a](https://github.com/macite/doubtfire-deploy/commit/02aa41a34232359d1366d841d1236a068a837ae5)) +* add similarities staff dashboard switch ([1ec0b72](https://github.com/macite/doubtfire-deploy/commit/1ec0b72c26cc27bd4d17376af5b47650d28bbc10)) +* add similarity flags to view ([8c7975c](https://github.com/macite/doubtfire-deploy/commit/8c7975cadd14e6d3390cfa9917983cd01498a69c)) +* add simple project progress bar ([73fda77](https://github.com/macite/doubtfire-deploy/commit/73fda776ee36c6574c1ddc0dc09b958d61de3000)) +* add start of new similarity view ([a1e51b6](https://github.com/macite/doubtfire-deploy/commit/a1e51b6bc7030086a1d7a4d715f23b3e76f7ddb3)) +* add task plagairism warning on inbox ([6bd8620](https://github.com/macite/doubtfire-deploy/commit/6bd8620f5473db4517e38fd0487ab5876f921a36)) +* add teaching period remove break function ([90c6a37](https://github.com/macite/doubtfire-deploy/commit/90c6a3730f84da9e64abec676bcdf66c10b7fc60)) +* add tii action log ([96d982d](https://github.com/macite/doubtfire-deploy/commit/96d982d5fb945bdbf9ea8b6d534a5dd18ab64ad7)) +* add unselected user icon badge in inbox ([794697b](https://github.com/macite/doubtfire-deploy/commit/794697b53d6ee81f57b37b173d03a0688c6993b5)) +* complete mobile task inbox view ([00a4b3f](https://github.com/macite/doubtfire-deploy/commit/00a4b3f1e8f52364a83b6affae34295da4a7af34)) +* disable hover on task inbox for mobile ([a59fd01](https://github.com/macite/doubtfire-deploy/commit/a59fd0153de8b1f9e9b9022d0f6df1032c92f8d1)) +* downgrade task due card ([c342ac2](https://github.com/macite/doubtfire-deploy/commit/c342ac2e3cc4213c2b92499bc4a191485184af37)) +* enhance task search with similarity flags ([65ad918](https://github.com/macite/doubtfire-deploy/commit/65ad91842882e76379033350f90b966d874c6ba4)) +* enhance ui/ux of task inbox screen ([6b275c3](https://github.com/macite/doubtfire-deploy/commit/6b275c3cd5d575a399e901d52a62808238c6d0e4)) +* expand new file uplaoder ([11d798d](https://github.com/macite/doubtfire-deploy/commit/11d798d6a6e5eca4555a7d141e1d11d2a862fcfe)) +* finish new alerts service ([3beb059](https://github.com/macite/doubtfire-deploy/commit/3beb05987e605c9f4270fc0d7bdd95f82bf64007)) +* make all datetime in aus format ([7a0f749](https://github.com/macite/doubtfire-deploy/commit/7a0f749a4328a44c1ffb5692017dfa39a061e1d5)) +* migrate new unit dialog ([0a2a1e9](https://github.com/macite/doubtfire-deploy/commit/0a2a1e9baca6b0553730c1a939b246bf1be178a3)) +* minor improvements to file-drop ([73139be](https://github.com/macite/doubtfire-deploy/commit/73139be83449f50036eedb3520ed2d8daa5da09c)) +* new footer component ([c3b4c18](https://github.com/macite/doubtfire-deploy/commit/c3b4c182921079d6ebc0851ec7e6515e65f1c15b)) +* new grade service ([31073e1](https://github.com/macite/doubtfire-deploy/commit/31073e1dbe963c1e0f2c84139a2c3f746cc31bbb)) +* new student user badge ([97c84d3](https://github.com/macite/doubtfire-deploy/commit/97c84d3016b0e322d54062fae0d46da112146d5d)) +* new task status card ([78218cf](https://github.com/macite/doubtfire-deploy/commit/78218cf6d45f5cac50203f96109d27400fa37686)) +* only download similarity resource on view ([563d102](https://github.com/macite/doubtfire-deploy/commit/563d1024ee7023e4228a9ceef9f556e48e7127d1)) +* progress redesigned inbox ([f1b672b](https://github.com/macite/doubtfire-deploy/commit/f1b672b7495a9086abb88f5e1991cb4c4f7b60c1)) +* register new inbox component ([3d79baa](https://github.com/macite/doubtfire-deploy/commit/3d79baae505e44c401179ae34de4804e8d90b7ba)) +* show TII accepted status in profile ([7b5c3e2](https://github.com/macite/doubtfire-deploy/commit/7b5c3e2c0fe9fcc30f9fffc73d9a942714db7cb2)) +* small change to task view ([f640920](https://github.com/macite/doubtfire-deploy/commit/f6409201e9d4af4f075b4db8559fc1e26f4a374f)) +* small changes to user table ([18957ac](https://github.com/macite/doubtfire-deploy/commit/18957acfc700e941ebb161d9ddb8f5e1ebe1beff)) +* trigger window resize when pdf loads ([044c170](https://github.com/macite/doubtfire-deploy/commit/044c170ebe05e7e3a368df2e8041884d2e23c752)) +* update file viewer to use file download and blobs ([8751123](https://github.com/macite/doubtfire-deploy/commit/87511232ca384a355ddfc5eb396186babd676f92)) +* wip add file uploader component ([48c73f5](https://github.com/macite/doubtfire-deploy/commit/48c73f547892ae3ce12fdac416bf93c3a2c72006)) + + +### Bug Fixes + +* add activeUntil date mapping to tps ([2cae20a](https://github.com/macite/doubtfire-deploy/commit/2cae20a6b3fa3e5ea8a001ffa40a87263c438b68)) +* add arbitrary task argument to `togglePin` in task inbox ([6e1784f](https://github.com/macite/doubtfire-deploy/commit/6e1784ff52a745330e57f2ccc2a55b3206d535d0)) +* add seperator to naviation on mobile ([fc4f052](https://github.com/macite/doubtfire-deploy/commit/fc4f0527b144fd8f3b6e98b335e629f85fe1bb3b)) +* add the correct enterkeyhint to the comment composer ([569db05](https://github.com/macite/doubtfire-deploy/commit/569db059fc9786363b1b62d7be72e44f711faba3)) +* add unloaded state to progressbar ([2c3a28e](https://github.com/macite/doubtfire-deploy/commit/2c3a28e9718879f55596221517db35bda8c09450)) +* adjust due card layout ([0360a6e](https://github.com/macite/doubtfire-deploy/commit/0360a6e0868e995d7ba5c9091be556dad4bfd474)) +* always display shortened task name in header ([a05c8ff](https://github.com/macite/doubtfire-deploy/commit/a05c8ffd9aef9c865f72458157b465f9de1e07f3)) +* center pins along items in new task inbox ([6b3c0d2](https://github.com/macite/doubtfire-deploy/commit/6b3c0d2b1d5541fe36c6fbd03dfc752f43d03e18)) +* center placeholder text in task inbox search bar & reduce padding on far-right ([ffec9b6](https://github.com/macite/doubtfire-deploy/commit/ffec9b6f4bfc9d2aee6aa762c41bcce1ed1823ba)) +* center student and task name on bottom left screen ([e986199](https://github.com/macite/doubtfire-deploy/commit/e9861992e9e5a40076973a2215bcc919c1777b5d)) +* center view all units button on home page ([9807dfd](https://github.com/macite/doubtfire-deploy/commit/9807dfd1f18e1efc9f882a67ef99f1d198a03ff7)) +* centering of Administration icons on home page ([1043f74](https://github.com/macite/doubtfire-deploy/commit/1043f74e2ca5d23cad8c4d890a202b20ddb4bc37)) +* change display name of student on bottom left screen from being nickname to full name ([5fe7790](https://github.com/macite/doubtfire-deploy/commit/5fe7790e23aec709f8be5a444bf84ebdf77c9ce5)) +* change shown name on messages in chat to be student's full name ([93636c4](https://github.com/macite/doubtfire-deploy/commit/93636c400c1850e20320a57be010347541c5137c)) +* chatbox spacing, placement of messages <> photos, distance between message & name ([dd9cb2a](https://github.com/macite/doubtfire-deploy/commit/dd9cb2ab3bdde886c2f297d8044986427febd366)) +* ensure accepted TII eula details are retained ([e60ae54](https://github.com/macite/doubtfire-deploy/commit/e60ae547121f33edd7cc8d8c5d4afd27a1f90e8c)) +* ensure blobs are freed on destroy ([ee017eb](https://github.com/macite/doubtfire-deploy/commit/ee017eb00a506c81a108ce6dec52f7f91064d350)) +* ensure font is set to roboto ([a6ff4ce](https://github.com/macite/doubtfire-deploy/commit/a6ff4cee9794e37a208af28d7d085182441fa555)) +* ensure loadedUnitRoles is public in global ([b92159f](https://github.com/macite/doubtfire-deploy/commit/b92159ff33cf9537c0ccec50d57a54636315bec4)) +* ensure logout in timeout always signs out ([3380075](https://github.com/macite/doubtfire-deploy/commit/33800759083156682014f0f63bc83a0283ae96fa)) +* ensure mat menu icons have correct tags ([f971ad1](https://github.com/macite/doubtfire-deploy/commit/f971ad1cf7fa56de0f4e97e9533a0567db897da4)) +* ensure only staff need to accept turn it in EULA ([029c40b](https://github.com/macite/doubtfire-deploy/commit/029c40b556bb1709e75547615b2d1a1109997a74)) +* ensure pdf actions loads after pdf loaded ([0425c54](https://github.com/macite/doubtfire-deploy/commit/0425c5465a678509e1a8d719fef39975c4d8e9e5)) +* ensure similarities without files still view ([5794e2f](https://github.com/macite/doubtfire-deploy/commit/5794e2fb345328396517a7d2f945cfabb1c37173)) +* ensure task pdf viewer works ([d3d1bf8](https://github.com/macite/doubtfire-deploy/commit/d3d1bf8564c6e6134130b44df90bef42430f4654)) +* ensure task submission status updated on init ([ca77c92](https://github.com/macite/doubtfire-deploy/commit/ca77c92d251bf4087964886579de642f6f300b9a)) +* ensure that timeout state not re-routed ([c16ee90](https://github.com/macite/doubtfire-deploy/commit/c16ee90c2c372ea1889d3470e2be510aefd2245f)) +* ensure welcome page still can go to timeout ([5253f2e](https://github.com/macite/doubtfire-deploy/commit/5253f2eb6fce1de1b6df585589f1cc2594ac87a8)) +* excessive spacing below unit tags on home page ([1bfaa21](https://github.com/macite/doubtfire-deploy/commit/1bfaa216440d880d82875f519e9b3f0f59ddcc23)) +* fix few type errors ([8a96e5b](https://github.com/macite/doubtfire-deploy/commit/8a96e5b33a095cd70222719b33d7dc853d67f347)) +* fix file drop to support click to upload ([599cd9e](https://github.com/macite/doubtfire-deploy/commit/599cd9e82c1518113374f0675fc54dd1483fcc85)) +* fix footer height not resetting on similarity ([19c43d7](https://github.com/macite/doubtfire-deploy/commit/19c43d7945c5848d1ca511e146fefdfa9735c49b)) +* fix incorrect closing tag ([ad28818](https://github.com/macite/doubtfire-deploy/commit/ad28818fba9dac552a2adf14785c5bbf98b4e206)) +* fix page height recalculation trigger ([8f219c3](https://github.com/macite/doubtfire-deploy/commit/8f219c31e9a3461626a9344352c4d7aa68c57c43)) +* fix various build issues ([8b947ae](https://github.com/macite/doubtfire-deploy/commit/8b947aeea1cb0dfa4bac8e22ff5bdb2a9a82ec49)) +* fix various task comment composer/display issues ([5670bf1](https://github.com/macite/doubtfire-deploy/commit/5670bf1dcd77e8010fe88bf24662ec96e4e29847)) +* hide extension for staff if can't apply ([1699e50](https://github.com/macite/doubtfire-deploy/commit/1699e50f2d7424361e0f7d5a173bdd9fffd87c24)) +* initialise inbox on return ([1249e96](https://github.com/macite/doubtfire-deploy/commit/1249e96f53ef9544cd81e3f2c3f1d5acf4a628f3)) +* initialise inbox view ([1ae4ac9](https://github.com/macite/doubtfire-deploy/commit/1ae4ac9b304348f5528368d87ded3c26e8e5cf40)) +* issues with UI in photo spacing and text alignment ([716ead3](https://github.com/macite/doubtfire-deploy/commit/716ead3497a8a2ecd1050484bd289c003a47dffa)) +* make photo in chatbox fall to bottom ([aa4e814](https://github.com/macite/doubtfire-deploy/commit/aa4e81446546f1e62b08fd74ba8ac1e563e5efc8)) +* make read receipt smaller to fix message alignment ([c869458](https://github.com/macite/doubtfire-deploy/commit/c869458cd45334e009ae83ab3c911033bc1987b9)) +* null input checks on migrated cards ([7a192af](https://github.com/macite/doubtfire-deploy/commit/7a192af22bf1eef026d05a16edcc3a97c6abbebf)) +* pass selected task to footer's user icon ([28782b1](https://github.com/macite/doubtfire-deploy/commit/28782b134cb03f5c334df48e8887f81393661bda)) +* photo from below message to being inline ([0e97a03](https://github.com/macite/doubtfire-deploy/commit/0e97a03a491f4137ec301dd18a42130a845ebe37)) +* reduce user badge clickable region ([7305f86](https://github.com/macite/doubtfire-deploy/commit/7305f866a9582e10dd870fad1861de4ce209a4e0)) +* regenerate user icons on input changes ([257ab4e](https://github.com/macite/doubtfire-deploy/commit/257ab4eb63ec15de545193f8b60176ac33e17b01)) +* remove call to teaching period name ([1e2e019](https://github.com/macite/doubtfire-deploy/commit/1e2e0198a32acd59c11932fde2a2f14a5bacf48f)) +* remove dupe case in transition hook ([9808798](https://github.com/macite/doubtfire-deploy/commit/98087981e06296a1eb9a17f527c49ab9b27caef3)) +* remove incorrect aria hidden tags ([46bfe21](https://github.com/macite/doubtfire-deploy/commit/46bfe2109e4b912a146201572671ff759fc02226)) +* remove no PDF text from overlapping with icon ([c6543cf](https://github.com/macite/doubtfire-deploy/commit/c6543cf2f9be9644b7382eeb64699e15e461447a)) +* remove old teaching periods from home ([4f4a617](https://github.com/macite/doubtfire-deploy/commit/4f4a6175f39ac9df75c7efe920ffcc15576cc98e)) +* remove pct copy data ([6bb96b4](https://github.com/macite/doubtfire-deploy/commit/6bb96b49f436a7d4bd6f5e587b30a8528e6d75b7)) +* remove user badge from old task panel ([9129956](https://github.com/macite/doubtfire-deploy/commit/9129956f41b78a8e3e84ffe9a124a7941d8905c1)) +* require eula for any user ([daf7ba9](https://github.com/macite/doubtfire-deploy/commit/daf7ba9d9056c262cafc871b623c59a0ef837274)) +* resolved issue with intelligent discussion ([18cd1fc](https://github.com/macite/doubtfire-deploy/commit/18cd1fc6f0443c353fc5f49c81dafd2428901cbc)) +* resolved issue with intelligent-discussion-dialog component rendering ([1efa758](https://github.com/macite/doubtfire-deploy/commit/1efa758fd813751788cc79fe30e01ca8a09013d8)) +* shrink header menu on small screens ([580445d](https://github.com/macite/doubtfire-deploy/commit/580445d25573bf00671246269c61685917c34867)) +* spacing (of own/person messaging) is now right/left aligned respectively ([7d10aa0](https://github.com/macite/doubtfire-deploy/commit/7d10aa0f58e2d7c8e8fd45439d8c464fabe3508c)) +* split header onto seperate lines on small screens ([d8a9016](https://github.com/macite/doubtfire-deploy/commit/d8a90168e58ef8d71f31f76d999d4f6a59232987)) +* switch max pct to similarity flag in project ([094b418](https://github.com/macite/doubtfire-deploy/commit/094b418c1bff709e755bf7c61207ebf22bfc6106)) +* task explorer 405 error ([7ea516c](https://github.com/macite/doubtfire-deploy/commit/7ea516ce8e346d46e8acf68c8b41fa81485515ba)) +* task submission pdf downloading ([b0becb4](https://github.com/macite/doubtfire-deploy/commit/b0becb4c76e4e45f10782561a6b53a322eb43665)) +* tweak theme.scss file ([393770b](https://github.com/macite/doubtfire-deploy/commit/393770b35d1688d27bce47e1d6b94735a1822494)) +* update package lock ([674f3c7](https://github.com/macite/doubtfire-deploy/commit/674f3c70bd0a4c8c33e25d34beeab76c29f56325)) +* use angular 15 ([d0104cc](https://github.com/macite/doubtfire-deploy/commit/d0104cc57edda68a1a165bdf1fd7cf75bd74ec68)) +* use correct task object in task pinning ([a5fceb0](https://github.com/macite/doubtfire-deploy/commit/a5fceb048b931dbd5ccc3ad5d4fd898b146284fb)) +* use correct theming import ([b0d3232](https://github.com/macite/doubtfire-deploy/commit/b0d3232eaed2096296cf025437dda26ddcd595e0)) +* use disabled blinding ([628ca55](https://github.com/macite/doubtfire-deploy/commit/628ca55b4e8f569f751b78ead7a50fa9e086ccec)) +* use new state name in task dropdown ([3c2fe44](https://github.com/macite/doubtfire-deploy/commit/3c2fe444d398bcedb5c998a47683d04279996680)) +* use onChanges rather than input setter ([8069c21](https://github.com/macite/doubtfire-deploy/commit/8069c21d9ecfc412dea37cade8e8a37e79730f01)) + ### [8.0.9](https://github.com/doubtfire-lms/doubtfire-deploy/compare/v8.0.8...v8.0.9) (2024-05-31) diff --git a/package-lock.json b/package-lock.json index 396f5fee98..5ec5842fc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "8.0.9", + "version": "8.0.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "8.0.9", + "version": "8.0.10", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 13d95e9bc7..a6af7f3bba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "8.0.9", + "version": "8.0.10", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 2f91e8fbba7902e1e22871cc82c87f4ff797b058 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 24 Jun 2024 13:28:40 +1000 Subject: [PATCH 0130/1531] fix: task date picker allows direct entry --- src/app/api/services/mapping-fn.ts | 39 ++++++++++++++++++----------- src/app/doubtfire-angular.module.ts | 18 ++++++++++++- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/app/api/services/mapping-fn.ts b/src/app/api/services/mapping-fn.ts index 7302bb387f..9124152095 100644 --- a/src/app/api/services/mapping-fn.ts +++ b/src/app/api/services/mapping-fn.ts @@ -1,23 +1,34 @@ +import moment from 'moment'; + export class MappingFunctions { - public static mapDateToEndOfDay(data, key, entity, params?) { + public static mapDateToEndOfDay(data, key, _entity, _params?) { const jsonDate = new Date(data[key]); - return new Date(jsonDate.getFullYear(), jsonDate.getMonth(), jsonDate.getDate(), 23, 59, 59, 999); + return new Date( + jsonDate.getFullYear(), + jsonDate.getMonth(), + jsonDate.getDate(), + 23, // all dates map to end of day + 59, + 59, + 999, + ); } - public static mapDateToDay(data, key, entity, params?) { + public static mapDateToDay(data, key: string, _entity, _params?) { const jsonDate = new Date(data[key]); return new Date(jsonDate.getFullYear(), jsonDate.getMonth(), jsonDate.getDate()); } - public static mapDate(data, key, entity, params?) { + public static mapDate(data, key: string, _entity, _params?) { return new Date(data[key]); } public static mapDayToJson(entity: T, key: string): string { if (entity[key]) { - const month = entity[key].getMonth() + 1; - const day = entity[key].getDate(); - return `${entity[key].getFullYear()}-${month < 10 ? '0' : ''}${month}-${day < 10 ? '0' : ''}${day}`; + const dateValue = moment.isMoment(entity[key]) ? entity[key].toDate() : entity[key]; + const month = dateValue.getMonth() + 1; + const day = dateValue.getDate(); + return `${dateValue.getFullYear()}-${month < 10 ? '0' : ''}${month}-${day < 10 ? '0' : ''}${day}`; } else { return undefined; } @@ -50,12 +61,12 @@ export class MappingFunctions { } /** - * Calculate the time between two dates - * - * @param date1 days from this date - * @param date2 to this date - * @returns the time from date1 to date2 - */ + * Calculate the time between two dates + * + * @param date1 days from this date + * @param date2 to this date + * @returns the time from date1 to date2 + */ public static timeBetween(date1: Date, date2: Date): number { return date2.getTime() - date1.getTime(); } @@ -67,7 +78,7 @@ export class MappingFunctions { * @param date2 to this date * @returns the days from date1 to date2 */ - public static daysBetween(date1: Date, date2: Date): number { + public static daysBetween(date1: Date, date2: Date): number { const diff = this.timeBetween(date1, date2); return Math.ceil(diff / (1000 * 3600 * 24)); } diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 9284745988..9be5408ace 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -95,8 +95,9 @@ import {ExtensionModalComponent} from './common/modals/extension-modal/extension import {CalendarModalComponent} from './common/modals/calendar-modal/calendar-modal.component'; import {MatRadioModule} from '@angular/material/radio'; import {MatButtonToggleModule} from '@angular/material/button-toggle'; -import {MAT_DATE_LOCALE, MatOptionModule} from '@angular/material/core'; +import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE, MatOptionModule} from '@angular/material/core'; import {MatDatepickerModule} from '@angular/material/datepicker'; +import {MomentDateAdapter} from '@angular/material-moment-adapter'; import {doubtfireStates} from './doubtfire.states'; import {MatTableModule} from '@angular/material/table'; import {MatTabsModule} from '@angular/material/tabs'; @@ -225,6 +226,19 @@ import {TasksViewerComponent} from './units/states/tasks/tasks-viewer/tasks-view import {UnitCodeComponent} from './common/unit-code/unit-code.component'; import {GradeService} from './common/services/grade.service'; +// See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 +const MY_DATE_FORMAT = { + parse: { + dateInput: 'DD/MM/YYYY', // this is how your date will be parsed from Input + }, + display: { + dateInput: 'DD/MM/YYYY', // this is how your date will get displayed on the Input + monthYearLabel: 'MMMM YYYY', + dateA11yLabel: 'LL', + monthYearA11yLabel: 'MMMM YYYY', + }, +}; + @NgModule({ // Components we declare declarations: [ @@ -369,6 +383,8 @@ import {GradeService} from './common/services/grade.service'; CsvUploadModalProvider, CsvResultModalProvider, {provide: MAT_DATE_LOCALE, useValue: 'en-AU'}, + {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]}, + {provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMAT}, UnitStudentEnrolmentModalProvider, TaskCommentService, AudioRecorderProvider, From 8a6424b6eecc08c4625e8fb36a85c79bc3a023dc Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 24 Jun 2024 13:30:10 +1000 Subject: [PATCH 0131/1531] chore: tidy up file downloader --- .../file-downloader/file-downloader.service.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/app/common/file-downloader/file-downloader.service.ts b/src/app/common/file-downloader/file-downloader.service.ts index 0ec8b90e34..681e4bde8e 100644 --- a/src/app/common/file-downloader/file-downloader.service.ts +++ b/src/app/common/file-downloader/file-downloader.service.ts @@ -3,13 +3,13 @@ import {Injectable} from '@angular/core'; import {AlertService} from '../services/alert.service'; interface FileDownloaderData { - url: string, - response: HttpResponse, - success: (url: string, response: HttpResponse) => void, + url: string; + response: HttpResponse; + success: (url: string, response: HttpResponse) => void; // eslint-disable-next-line @typescript-eslint/no-explicit-any - failure: (error: any) => void, + failure: (error: any) => void; // eslint-disable-next-line @typescript-eslint/no-explicit-any - binaryData: Blob[], + binaryData: Blob[]; } @Injectable({ @@ -100,7 +100,7 @@ export class FileDownloaderService { public downloadBlob( url: string, success: (url: string, response: HttpResponse) => void, - failure: (error: any) => void, + failure: (error) => void, ) { // Declare binary data outside of the subscription so that it can be accessed in the second requests when partial content is returned const binaryData = []; @@ -146,7 +146,7 @@ export class FileDownloaderService { downloadLink.click(); downloadLink.parentNode.removeChild(downloadLink); }, - (error: any) => { + (error) => { this.alerts.error(`Error downloading file - ${error}`); }, ); From 3a81688904159c8c9e3efdde8f3605aa5677630f Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 24 Jun 2024 13:39:53 +1000 Subject: [PATCH 0132/1531] fix: ensure turn it in only appears to task editor when enabled --- .../task-definition-upload.component.html | 10 +++++----- .../task-definition-upload.component.ts | 11 +++++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html index fe96cfb2df..8607e6c719 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html @@ -25,12 +25,12 @@
diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts index a8915d843b..a6d049446a 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts @@ -2,6 +2,7 @@ import { Component, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/ import { MatTable, MatTableDataSource } from '@angular/material/table'; import { TaskDefinition, UploadRequirement } from 'src/app/api/models/task-definition'; import { Unit } from 'src/app/api/models/unit'; +import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; @Component({ selector: 'f-task-definition-upload', @@ -10,10 +11,12 @@ import { Unit } from 'src/app/api/models/unit'; }) export class TaskDefinitionUploadComponent { @Input() public taskDefinition: TaskDefinition; - @ViewChild('upreqTable', { static: true }) table: MatTable; + @ViewChild('upreqTable', {static: true}) table: MatTable; public columns: string[] = ['file-name', 'file-type', 'tii-check', 'flag-pct', 'row-actions']; + constructor(private constants: DoubtfireConstants) {} + public get unit(): Unit { return this.taskDefinition?.unit; } @@ -30,9 +33,13 @@ export class TaskDefinitionUploadComponent { this.table.renderRows(); } + public tiiEnabled(): boolean { + return this.constants.IsTiiEnabled.value; + } + public removeUpReq(upreq: UploadRequirement) { this.taskDefinition.uploadRequirements = this.taskDefinition.uploadRequirements.filter( - (anUpReq) => anUpReq.key != upreq.key + (anUpReq) => anUpReq.key != upreq.key, ); } } From c7ae09170fdc43c21452e8b2665f0f36e480dd4d Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 24 Jun 2024 13:40:07 +1000 Subject: [PATCH 0133/1531] chore(release): 8.0.11 --- CHANGELOG.md | 15 +++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76d7c600ff..54ea56c57d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [8.0.11](https://github.com/macite/doubtfire-deploy/compare/v8.0.10...v8.0.11) (2024-06-24) + + +### Bug Fixes + +* ensure turn it in only appears to task editor when enabled ([3a81688](https://github.com/macite/doubtfire-deploy/commit/3a81688904159c8c9e3efdde8f3605aa5677630f)) +* task date picker allows direct entry ([2f91e8f](https://github.com/macite/doubtfire-deploy/commit/2f91e8fbba7902e1e22871cc82c87f4ff797b058)) + +### [7.0.24](https://github.com/macite/doubtfire-deploy/compare/v7.0.23...v7.0.24) (2024-06-05) + + +### Bug Fixes + +* ensure download blob supports 206 responses ([6445f9f](https://github.com/macite/doubtfire-deploy/commit/6445f9f998db70fbe9b9abf723dc17fd298b5d2f)) + ### [8.0.10](https://github.com/macite/doubtfire-deploy/compare/v7.0.23...v8.0.10) (2024-06-21) diff --git a/package-lock.json b/package-lock.json index 5ec5842fc2..691cb53755 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "8.0.10", + "version": "8.0.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "8.0.10", + "version": "8.0.11", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index a6af7f3bba..fe9cf8dc2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "8.0.10", + "version": "8.0.11", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 991230f7b527957116263b6abaa588ed43d3a787 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Tue, 25 Jun 2024 15:37:00 +1000 Subject: [PATCH 0134/1531] fix: reinstate unit import for teaching period --- .../teaching-period-list.component.html | 42 ++++++++++++++-- .../teaching-period-list.component.ts | 49 +++++++++++++++++-- src/app/doubtfire-angularjs.module.ts | 5 -- 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.html b/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.html index 5abff6ce87..5f009464f4 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.html +++ b/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.html @@ -2,9 +2,20 @@

Teaching periods

- +
-
- Student + Student + - Name + Name + - Tutor + Tutor + Tutorial - + - Target + Target + Submitted as - + - Stats + Stats - Portfolio? + Portfolio? + - Grade + Grade +
{{student.hasPortfolio ? "Yes" : "No"}} + {{student.hasPortfolio ? "Yes" : "No"}} + {{student.grade}}
Check Similarity - @if (upreq.type === 'document') { -TurnItIn -} + @if (upreq.type === 'document' && tiiEnabled()) { + TurnItIn + } @if (upreq.type === 'code') { -Moss -} + Moss + }
+
+ + + + + - +
Active @@ -32,6 +43,26 @@

Teaching periods

{{ element.activeUntil | date }} Actions +
+ + + + +
+
- + diff --git a/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.ts b/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.ts index 87be5fbef8..17dc7efdf9 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.ts +++ b/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.ts @@ -2,12 +2,13 @@ import { Component, Inject, OnInit, ViewChild } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog'; import { MatPaginator } from '@angular/material/paginator'; import { MatSnackBar } from '@angular/material/snack-bar'; -import { MatSort } from '@angular/material/sort'; +import { MatSort, Sort } from '@angular/material/sort'; import { MatTableDataSource } from '@angular/material/table'; import { TeachingPeriodBreak } from 'src/app/api/models/teaching-period'; import { TeachingPeriod } from 'src/app/api/models/teaching-period'; import { TeachingPeriodBreakService } from 'src/app/api/services/teaching-period-break.service'; import { TeachingPeriodService } from 'src/app/api/services/teaching-period.service'; +import { TeachingPeriodUnitImportService } from '../teaching-period-unit-import/teaching-period-unit-import.dialog'; @Component({ selector: 'f-teaching-period-list', @@ -20,8 +21,13 @@ export class TeachingPeriodListComponent implements OnInit { public dataSource = new MatTableDataSource(); - displayedColumns: string[] = ['active', 'name', 'startDate', 'endDate', 'activeUntil']; - constructor(private teachingPeriodsService: TeachingPeriodService, public dialog: MatDialog) {} + displayedColumns: string[] = ['active', 'name', 'startDate', 'endDate', 'activeUntil', 'actions']; + + constructor( + private teachingPeriodsService: TeachingPeriodService, + public dialog: MatDialog, + public teachingPeriodUnitImportService: TeachingPeriodUnitImportService, + ) {} ngOnInit(): void { // update the Teaching Periods @@ -35,6 +41,10 @@ export class TeachingPeriodListComponent implements OnInit { }); } + importUnits(teachingPeriod: TeachingPeriod) { + this.teachingPeriodUnitImportService.openImportUnitsDialog(teachingPeriod); + } + addTeachingPeriod() { this.dialog.open(NewTeachingPeriodDialogComponent, { data: {}, @@ -46,6 +56,39 @@ export class TeachingPeriodListComponent implements OnInit { this.dialog.open(NewTeachingPeriodDialogComponent, { data: { teachingPeriod: teachingPeriod } }); }); } + + /** + * Function used by implemented sortTableData to determine the order + * of values within the EntityForm once sorting has been triggered. + * + * @param aValue value to be compared against bValue. + * @param bValue value to be compared against aValue. + * + * @returns truthy comparison between aValue and bValue. + */ + protected sortCompare(aValue: number | string, bValue: number | string, isAsc: boolean) { + return (aValue < bValue ? -1 : 1) * (isAsc ? 1 : -1); + } + + // Sorting function to sort data when sort + // event is triggered + sortTableData(sort: Sort) { + if (!sort.active || sort.direction === '') { + return; + } + switch (sort.active) { + case 'active': + case 'name': + case 'startDate': + case 'endDate': + case 'activeUntil': + this.dataSource.data = this.dataSource.data.sort((a, b) => { + const isAsc = sort.direction === 'asc'; + return this.sortCompare(a[sort.active], b[sort.active], isAsc); + }); + return; + } + } } @Component({ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 868e381213..304e0bf747 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -213,7 +213,6 @@ import {InboxComponent} from './units/states/tasks/inbox/inbox.component'; import {TaskDefinitionEditorComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component'; import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-route.component'; import {UnitTaskEditorComponent} from './units/states/edit/directives/unit-tasks-editor/unit-task-editor.component'; -import {TeachingPeriodUnitImportService} from './admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog'; import {CreateNewUnitModal} from './admin/modals/create-new-unit-modal/create-new-unit-modal.component'; import {FUsersComponent} from './admin/states/f-users/f-users.component'; import {FUnitTaskListComponent} from './units/states/tasks/viewer/directives/f-unit-task-list/f-unit-task-list.component'; @@ -240,10 +239,6 @@ export const DoubtfireAngularJSModule = angular.module('doubtfire', [ // Downgrade angular modules that we need... // factory -> service DoubtfireAngularJSModule.factory('AboutDoubtfireModal', downgradeInjectable(AboutDoubtfireModal)); -DoubtfireAngularJSModule.factory( - 'TeachingPeriodUnitImportService', - downgradeInjectable(TeachingPeriodUnitImportService), -); DoubtfireAngularJSModule.factory('DoubtfireConstants', downgradeInjectable(DoubtfireConstants)); DoubtfireAngularJSModule.factory('ExtensionModal', downgradeInjectable(ExtensionModalService)); DoubtfireAngularJSModule.factory('Marked', downgradeInjectable(MarkedPipe)); From 32046e89eaaf2a9b36e88f078a7b695b1506886d Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Tue, 25 Jun 2024 20:05:16 +1000 Subject: [PATCH 0135/1531] fix: ensure null fields will not break in entity mapping --- src/app/api/models/task-definition.ts | 2 +- src/app/api/services/project.service.ts | 20 +++++++++++-------- src/app/api/services/task-comment.service.ts | 4 ++-- .../api/services/task-definition.service.ts | 14 +++++++++---- src/app/api/services/unit.service.ts | 8 ++++---- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index 1b49a2e856..0766f85eb6 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -21,7 +21,7 @@ export class TaskDefinition extends Entity { targetDate: Date; dueDate: Date; startDate: Date; - uploadRequirements: UploadRequirement[]; + uploadRequirements: UploadRequirement[] = []; tutorialStream: TutorialStream = null; plagiarismChecks: SimilarityCheck[] = []; plagiarismReportUrl: string; diff --git a/src/app/api/services/project.service.ts b/src/app/api/services/project.service.ts index e9ffc791ed..6bb50481a3 100644 --- a/src/app/api/services/project.service.ts +++ b/src/app/api/services/project.service.ts @@ -143,7 +143,7 @@ export class ProjectService extends CachedEntityService { keys: 'tutorialEnrolments', toEntityOp: (data: object, key: string, project: Project, params?: any) => { const unit: Unit = project.unit; - data[key].forEach((tutorialEnrolment: { tutorial_id: number; }) => { + data[key]?.forEach((tutorialEnrolment: {tutorial_id: number}) => { if (tutorialEnrolment.tutorial_id) { const tutorial = unit.tutorialsCache.get(tutorialEnrolment.tutorial_id); project.tutorialEnrolmentsCache.add(tutorial); @@ -154,12 +154,16 @@ export class ProjectService extends CachedEntityService { { keys: 'groups', toEntityOp: (data: object, key: string, project: Project, params?: any) => { - data[key].forEach((group) => { - const theGroup = project.unit.groupSetsCache.get(group.group_set_id).groupsCache.getOrCreate(group.id, this.groupService, group, {constructorParams: project.unit}); + data[key]?.forEach((group) => { + const theGroup = project.unit.groupSetsCache + .get(group.group_set_id) + .groupsCache.getOrCreate(group.id, this.groupService, group, { + constructorParams: project.unit, + }); project.groupCache.add(theGroup); theGroup.projectsCache.add(project); - }) + }); }, toJsonFn: (entity: Project, key: string) => { return entity.unit?.id; @@ -169,7 +173,7 @@ export class ProjectService extends CachedEntityService { keys: 'tasks', toEntityOp: (data: object, key: string, project: Project, params?: any) => { // create tasks from json - data['tasks'].forEach(taskData => { + data['tasks']?.forEach((taskData) => { project.taskCache.getOrCreate(taskData['id'], this.taskService, taskData, {constructorParams: project}); }); @@ -179,14 +183,14 @@ export class ProjectService extends CachedEntityService { { keys: 'taskOutcomeAlignments', toEntityOp: (data: object, key: string, project: Project, params?: any) => { - data[key].forEach(alignment => { + data[key]?.forEach((alignment) => { project.taskOutcomeAlignmentsCache.getOrCreate( alignment['id'], taskOutcomeAlignmentService, alignment, { - constructorParams: project - } + constructorParams: project, + }, ); }); } diff --git a/src/app/api/services/task-comment.service.ts b/src/app/api/services/task-comment.service.ts index 9e646be77d..7fdf94bc88 100644 --- a/src/app/api/services/task-comment.service.ts +++ b/src/app/api/services/task-comment.service.ts @@ -41,7 +41,7 @@ export class TaskCommentService extends CachedEntityService { { keys: 'author', toEntityFn: (data: object, key: string, comment: TaskComment) => { - const user = this.userService.cache.getOrCreate(data[key].id, userService, data[key]); + const user = this.userService.cache.getOrCreate(data[key]?.id, userService, data[key]); comment.initials = `${user.firstName[0]}${user.lastName[0]}`.toUpperCase(); return user; } @@ -49,7 +49,7 @@ export class TaskCommentService extends CachedEntityService { { keys: 'recipient', toEntityFn: (data: object, key: string, comment: TaskComment) => { - return this.userService.cache.getOrCreate(data[key].id, userService, data[key]); + return this.userService.cache.getOrCreate(data[key]?.id, userService, data[key]); } }, 'recipientReadTime', diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 13a1dd2797..b2499251ea 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -41,7 +41,7 @@ export class TaskDefinitionService extends CachedEntityService { keys: 'uploadRequirements', toJsonFn: (taskDef: TaskDefinition, key: string) => { return JSON.stringify( - taskDef.uploadRequirements.map((upreq) => { + taskDef.uploadRequirements?.map((upreq) => { return { key: upreq.key, name: upreq.name, @@ -49,13 +49,19 @@ export class TaskDefinitionService extends CachedEntityService { tii_check: upreq.tiiCheck, tii_pct: upreq.tiiPct, }; - }) + }), ); }, toEntityFn: (data: object, key: string, taskDef: TaskDefinition, params?: any) => { return ( - data[key] as Array<{ key: string; name: string; type: string; tii_check: boolean; tii_pct: number }> - ).map((upreq) => { + data[key] as Array<{ + key: string; + name: string; + type: string; + tii_check: boolean; + tii_pct: number; + }> + )?.map((upreq) => { return { key: upreq.key, name: upreq.name, diff --git a/src/app/api/services/unit.service.ts b/src/app/api/services/unit.service.ts index 740e9b6cc1..4f6e896495 100644 --- a/src/app/api/services/unit.service.ts +++ b/src/app/api/services/unit.service.ts @@ -58,7 +58,7 @@ export class UnitService extends CachedEntityService { const unitRoleService = AppInjector.get(UnitRoleService); // Add staff entity.staffCache.clear(); - data[key].forEach(staff => { + data[key]?.forEach(staff => { entity.staffCache.add(unitRoleService.buildInstance(staff)); }); } @@ -133,7 +133,7 @@ export class UnitService extends CachedEntityService { { keys: 'ilos', toEntityOp: (data: object, key: string, unit: Unit) => { - data[key].forEach(ilo => { + data[key]?.forEach(ilo => { unit.learningOutcomesCache.getOrCreate(ilo['id'], this.learningOutcomeService, ilo); }); } @@ -160,7 +160,7 @@ export class UnitService extends CachedEntityService { { keys: 'groupSets', toEntityOp: (data, key, unit) => { - data[key].forEach((groupSetJson: object) => { + data[key]?.forEach((groupSetJson: object) => { unit.groupSetsCache.add(this.groupSetService.buildInstance(groupSetJson, {constructorParams: unit})); }); } @@ -168,7 +168,7 @@ export class UnitService extends CachedEntityService { { keys: 'groups', toEntityOp: (data, key, unit) => { - data[key].forEach((groupJson: object) => { + data[key]?.forEach((groupJson: object) => { const group = this.groupService.buildInstance(groupJson, {constructorParams: unit}); group.groupSet.groupsCache.add(group); }); From 0bb4869aafb633a74b417e6c5b0d819d99dc60aa Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Tue, 25 Jun 2024 20:25:35 +1000 Subject: [PATCH 0136/1531] chore(release): 8.0.12 --- CHANGELOG.md | 8 ++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54ea56c57d..cae648d1cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [8.0.12](https://github.com/macite/doubtfire-deploy/compare/v8.0.11...v8.0.12) (2024-06-25) + + +### Bug Fixes + +* ensure null fields will not break in entity mapping ([32046e8](https://github.com/macite/doubtfire-deploy/commit/32046e89eaaf2a9b36e88f078a7b695b1506886d)) +* reinstate unit import for teaching period ([991230f](https://github.com/macite/doubtfire-deploy/commit/991230f7b527957116263b6abaa588ed43d3a787)) + ### [8.0.11](https://github.com/macite/doubtfire-deploy/compare/v8.0.10...v8.0.11) (2024-06-24) diff --git a/package-lock.json b/package-lock.json index 691cb53755..5ba9364f0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "8.0.11", + "version": "8.0.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "8.0.11", + "version": "8.0.12", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index fe9cf8dc2a..0492d4a2db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "8.0.11", + "version": "8.0.12", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 8fe2f9e9ca60c02e55c24d0f2bb3eb6dbea8217c Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Thu, 27 Jun 2024 02:13:51 +1000 Subject: [PATCH 0137/1531] feat: get unique token for scorm asset retrieval --- src/app/api/models/user/user.ts | 1 + src/app/api/services/authentication.service.ts | 18 ++++++++++++++++++ .../scorm-player/scorm-player.component.ts | 18 ++++++++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/app/api/models/user/user.ts b/src/app/api/models/user/user.ts index 10357a1898..552066cfd1 100644 --- a/src/app/api/models/user/user.ts +++ b/src/app/api/models/user/user.ts @@ -22,6 +22,7 @@ export class User extends Entity { receiveFeedbackNotifications: boolean; hasRunFirstTimeSetup: boolean; authenticationToken: string; + scormAuthenticationToken: string; pronouns: string | null; acceptedTiiEula: boolean; diff --git a/src/app/api/services/authentication.service.ts b/src/app/api/services/authentication.service.ts index b2cb12f402..fe2b8d0b1c 100644 --- a/src/app/api/services/authentication.service.ts +++ b/src/app/api/services/authentication.service.ts @@ -191,4 +191,22 @@ export class AuthenticationService { setTimeout(() => this.router.stateService.go('timeout'), 500); } } + + public getScormToken(): Observable { + return this.httpClient.get(this.AUTH_URL + '/scorm').pipe( + map((response) => { + this.userService.currentUser.scormAuthenticationToken = response['scorm_auth_token']; + localStorage.setItem(this.USERNAME_KEY, JSON.stringify(this.userService.currentUser)); + + // Token expires after 2 hours + setTimeout( + () => { + this.userService.currentUser.scormAuthenticationToken = ''; + localStorage.setItem(this.USERNAME_KEY, JSON.stringify(this.userService.currentUser)); + }, + 1000 * 60 * 60 * 2, + ); + }), + ); + } } diff --git a/src/app/common/scorm-player/scorm-player.component.ts b/src/app/common/scorm-player/scorm-player.component.ts index 4a32eb0ac7..b7f9b1b5a6 100644 --- a/src/app/common/scorm-player/scorm-player.component.ts +++ b/src/app/common/scorm-player/scorm-player.component.ts @@ -1,6 +1,10 @@ import {Component, OnInit, Input, HostListener} from '@angular/core'; import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser'; -import {ScormPlayerContext} from 'src/app/api/models/doubtfire-model'; +import { + AuthenticationService, + ScormPlayerContext, + UserService, +} from 'src/app/api/models/doubtfire-model'; import {ScormAdapterService} from 'src/app/api/services/scorm-adapter.service'; import {AppInjector} from 'src/app/app-injector'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; @@ -37,6 +41,8 @@ export class ScormPlayerComponent implements OnInit { constructor( private globalState: GlobalStateService, private scormAdapter: ScormAdapterService, + private userService: UserService, + private authService: AuthenticationService, private sanitizer: DomSanitizer, ) {} @@ -44,6 +50,14 @@ export class ScormPlayerComponent implements OnInit { this.globalState.setView(ViewType.OTHER); this.globalState.hideHeader(); + if (this.userService.currentUser.scormAuthenticationToken) { + this.setupScorm(); + } else { + this.authService.getScormToken().subscribe(() => this.setupScorm()); + } + } + + setupScorm(): void { this.scormAdapter.mode = this.mode; if (this.mode === 'normal') { this.scormAdapter.projectId = this.projectId; @@ -64,7 +78,7 @@ export class ScormPlayerComponent implements OnInit { }; this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl( - `${AppInjector.get(DoubtfireConstants).API_URL}/scorm/${this.taskDefId}/index.html`, + `${AppInjector.get(DoubtfireConstants).API_URL}/scorm/${this.taskDefId}/${this.userService.currentUser.username}/${this.userService.currentUser.scormAuthenticationToken}/index.html`, ); } From 7b5d35c89a577d0408a51d8390400f44615591eb Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Thu, 27 Jun 2024 14:51:01 +1000 Subject: [PATCH 0138/1531] fix: update discuss text to promote use --- src/app/api/models/task-status.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/app/api/models/task-status.ts b/src/app/api/models/task-status.ts index 0ab0f8f2d9..7470b9b143 100644 --- a/src/app/api/models/task-status.ts +++ b/src/app/api/models/task-status.ts @@ -287,17 +287,18 @@ export class TaskStatus { [ 'discuss', { - detail: "You're almost complete!", - reason: 'Your work looks good and your tutor believes it is complete.', - action: 'To mark as complete, attend class and discuss it with your tutor.', + detail: 'Your work needs to be discussed further.', + reason: 'Your work looks good and your tutor believes it is on track.', + action: 'For this to be marked as complete, attend class and discuss it with your tutor.', }, ], [ 'demonstrate', { - detail: "You're almost complete!", - reason: 'Your work looks good and your tutor believes it is complete.', - action: 'To mark as complete, attend class and demonstrate how your submission works to your tutor.', + detail: 'Your work needs to be demonstrated.', + reason: 'Your work looks good and your tutor believes it is on track.', + action: + 'For this to be marked as complete you need to attend class and demonstrate how your submission works for your tutor.', }, ], [ From dbb3a682639c959e946e1f3273d9e5f2996683db Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Thu, 27 Jun 2024 15:17:57 +1000 Subject: [PATCH 0139/1531] chore(release): 8.0.13 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cae648d1cf..fed8da62dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [8.0.13](https://github.com/macite/doubtfire-deploy/compare/v8.0.12...v8.0.13) (2024-06-27) + + +### Bug Fixes + +* update discuss text to promote use ([7b5d35c](https://github.com/macite/doubtfire-deploy/commit/7b5d35c89a577d0408a51d8390400f44615591eb)) + ### [8.0.12](https://github.com/macite/doubtfire-deploy/compare/v8.0.11...v8.0.12) (2024-06-25) diff --git a/package-lock.json b/package-lock.json index 5ba9364f0e..351f4d773e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "8.0.12", + "version": "8.0.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "8.0.12", + "version": "8.0.13", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 0492d4a2db..3ade29c77a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "8.0.12", + "version": "8.0.13", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 01013d3d16ab5b704acc589d34975693030def0b Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Thu, 27 Jun 2024 22:37:17 +1000 Subject: [PATCH 0140/1531] fix: ensure unit import allows unit code change --- .../teaching-period-unit-import.dialog.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts b/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts index 2925b4b59e..1a89a5538d 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts +++ b/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts @@ -126,6 +126,10 @@ export class TeachingPeriodUnitImportDialogComponent implements OnInit { public codeChange(code: string, value: UnitImportData) { value.relatedUnits = this.relatedUnits(code); + // add source unit to realted units - so that it is retained on code change + if (value.sourceUnit && !value.relatedUnits.find((u) => u.value.id === value.sourceUnit.id)) { + value.relatedUnits.unshift({value: value.sourceUnit, text: value.sourceUnit.codeAndPeriod}); + } value.sourceUnit = value.relatedUnits.length > 0 ? value.relatedUnits[0].value : null; } From 4c966245d270af46107aae94bdd38e84b2188b65 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Thu, 27 Jun 2024 22:37:37 +1000 Subject: [PATCH 0141/1531] fix: ensure unit load sets main convenor user in all cases --- src/app/api/services/unit.service.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/api/services/unit.service.ts b/src/app/api/services/unit.service.ts index 4f6e896495..c3c38c7406 100644 --- a/src/app/api/services/unit.service.ts +++ b/src/app/api/services/unit.service.ts @@ -66,7 +66,9 @@ export class UnitService extends CachedEntityService { { keys: ['mainConvenor', 'main_convenor_id'], toEntityFn: (data, key, entity) => { - return entity.staffCache.get(data[key]); + let result = entity.staffCache.get(data[key]); + entity.mainConvenorUser = result?.user; + return result; }, toJsonFn: (unit: Unit, key: string) => { return unit.mainConvenor?.id; From 1dc58ce230e67c4a682600fb4b8153fc82586461 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Thu, 27 Jun 2024 22:46:27 +1000 Subject: [PATCH 0142/1531] chore(release): 8.0.14 --- CHANGELOG.md | 8 ++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fed8da62dd..9081badf55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [8.0.14](https://github.com/macite/doubtfire-deploy/compare/v8.0.13...v8.0.14) (2024-06-27) + + +### Bug Fixes + +* ensure unit import allows unit code change ([01013d3](https://github.com/macite/doubtfire-deploy/commit/01013d3d16ab5b704acc589d34975693030def0b)) +* ensure unit load sets main convenor user in all cases ([4c96624](https://github.com/macite/doubtfire-deploy/commit/4c966245d270af46107aae94bdd38e84b2188b65)) + ### [8.0.13](https://github.com/macite/doubtfire-deploy/compare/v8.0.12...v8.0.13) (2024-06-27) diff --git a/package-lock.json b/package-lock.json index 351f4d773e..56e93ef1bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "8.0.13", + "version": "8.0.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "8.0.13", + "version": "8.0.14", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 3ade29c77a..c1de295951 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "8.0.13", + "version": "8.0.14", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 1857bdc708c81dc39d467f42c9e316a8664dc080 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Fri, 28 Jun 2024 19:06:54 +1000 Subject: [PATCH 0143/1531] fix: ensure zip uploads work on windows --- .../task-definition-overseer.component.html | 14 +++++++++++-- .../task-definition-overseer.component.ts | 4 +++- .../task-definition-resources.component.ts | 4 ++-- .../unit-task-editor.component.html | 21 ------------------- 4 files changed, 17 insertions(+), 26 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html index 92ef121ff3..31c683077f 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html @@ -1,5 +1,10 @@
- + Automation Enabled @@ -13,7 +18,12 @@ Docker image for Overseer - +
-
From a5690871a448f5b3aeb442df47a410ee2e3ca1a0 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Fri, 28 Jun 2024 19:07:01 +1000 Subject: [PATCH 0144/1531] chore(release): 8.0.15 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9081badf55..362eaeac79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [8.0.15](https://github.com/macite/doubtfire-deploy/compare/v8.0.14...v8.0.15) (2024-06-28) + + +### Bug Fixes + +* ensure zip uploads work on windows ([1857bdc](https://github.com/macite/doubtfire-deploy/commit/1857bdc708c81dc39d467f42c9e316a8664dc080)) + ### [8.0.14](https://github.com/macite/doubtfire-deploy/compare/v8.0.13...v8.0.14) (2024-06-27) diff --git a/package-lock.json b/package-lock.json index 56e93ef1bd..1bcdf3b7fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "8.0.14", + "version": "8.0.15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "8.0.14", + "version": "8.0.15", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index c1de295951..fb492d216c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "8.0.14", + "version": "8.0.15", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From f0505d7b62b97f1b821b19b1c4178973503789da Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Fri, 28 Jun 2024 19:31:49 +1000 Subject: [PATCH 0145/1531] fix: ensure drop works on task resource upload in windows --- .../task-definition-resources.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.html index 82ae176482..51bf4db54f 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.html @@ -19,7 +19,7 @@ @if (taskDefinition.hasTaskResources) { From 576076f1a7871f458526253ab18eade70fbd316a Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Fri, 28 Jun 2024 19:31:58 +1000 Subject: [PATCH 0146/1531] chore(release): 8.0.16 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 362eaeac79..0ccd7cdc27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [8.0.16](https://github.com/macite/doubtfire-deploy/compare/v8.0.15...v8.0.16) (2024-06-28) + + +### Bug Fixes + +* ensure drop works on task resource upload in windows ([f0505d7](https://github.com/macite/doubtfire-deploy/commit/f0505d7b62b97f1b821b19b1c4178973503789da)) + ### [8.0.15](https://github.com/macite/doubtfire-deploy/compare/v8.0.14...v8.0.15) (2024-06-28) diff --git a/package-lock.json b/package-lock.json index 1bcdf3b7fe..53a1fccd78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "8.0.15", + "version": "8.0.16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "8.0.15", + "version": "8.0.16", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index fb492d216c..254a8eb450 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "8.0.15", + "version": "8.0.16", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 2394efb07c03da18fb8114d87b0c89e68bf7fd2d Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 1 Jul 2024 17:04:31 +1000 Subject: [PATCH 0147/1531] fix: switch date formats to date-fns Issues with moment caused failure to load task edit page. --- package-lock.json | 52 +++++++++++++------ package.json | 6 ++- src/app/doubtfire-angular.module.ts | 20 ++++--- .../unit-task-editor.component.ts | 3 +- 4 files changed, 55 insertions(+), 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index 53a1fccd78..f31a23897f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,8 +16,8 @@ "@angular/compiler": "^17.3.6", "@angular/core": "^17.3.6", "@angular/forms": "^17.3.6", - "@angular/material": "^17.3.6", - "@angular/material-moment-adapter": "^17.3.6", + "@angular/material": "^17.3.10", + "@angular/material-date-fns-adapter": "^17.3.10", "@angular/platform-browser": "^17.3.6", "@angular/platform-browser-dynamic": "^17.3.6", "@angular/router": "^17.3.6", @@ -52,6 +52,7 @@ "codemirror": "5.65.0", "core-js": "^3.21.1", "d3": "3.5.17", + "date-fns": "^3.6.0", "es5-shim": "^4.5.12", "file-saver": "^2.0.5", "font-awesome": "~4.7.0", @@ -604,8 +605,9 @@ } }, "node_modules/@angular/cdk": { - "version": "17.3.8", - "license": "MIT", + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-17.3.10.tgz", + "integrity": "sha512-b1qktT2c1TTTe5nTji/kFAVW92fULK0YhYAvJ+BjZTPKu2FniZNe8o4qqQ0pUuvtMu+ZQxp/QqFYoidIVCjScg==", "dependencies": { "tslib": "^2.3.0" }, @@ -790,8 +792,9 @@ } }, "node_modules/@angular/material": { - "version": "17.3.8", - "license": "MIT", + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-17.3.10.tgz", + "integrity": "sha512-hHMQES0tQPH5JW33W+mpBPuM8ybsloDTqFPuRV8cboDjosAWfJhzAKF3ozICpNlUrs62La/2Wu/756GcQrxebg==", "dependencies": { "@material/animation": "15.0.0-canary.7f224ddd4.0", "@material/auto-init": "15.0.0-canary.7f224ddd4.0", @@ -844,7 +847,7 @@ }, "peerDependencies": { "@angular/animations": "^17.0.0 || ^18.0.0", - "@angular/cdk": "17.3.8", + "@angular/cdk": "17.3.10", "@angular/common": "^17.0.0 || ^18.0.0", "@angular/core": "^17.0.0 || ^18.0.0", "@angular/forms": "^17.0.0 || ^18.0.0", @@ -852,16 +855,17 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@angular/material-moment-adapter": { - "version": "17.3.8", - "license": "MIT", + "node_modules/@angular/material-date-fns-adapter": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/material-date-fns-adapter/-/material-date-fns-adapter-17.3.10.tgz", + "integrity": "sha512-Q4QAPGImZTjKW9ZhLSTkBeQX21I0dtak3JbexYx4CN/pHxKRpen6KaVAEqiORqq6vNUP2Kwb7cZznQyj6L7oQw==", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/core": "^17.0.0 || ^18.0.0", - "@angular/material": "17.3.8", - "moment": "^2.18.1" + "@angular/material": "17.3.10", + "date-fns": ">2.20.0 <4.0" } }, "node_modules/@angular/platform-browser": { @@ -8067,6 +8071,12 @@ "node": ">=4.0.0" } }, + "node_modules/concurrently/node_modules/date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, "node_modules/concurrently/node_modules/has-flag": { "version": "1.0.0", "dev": true, @@ -8651,9 +8661,13 @@ } }, "node_modules/date-fns": { - "version": "1.30.1", - "dev": true, - "license": "MIT" + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } }, "node_modules/date-format": { "version": "4.0.14", @@ -12917,6 +12931,14 @@ "tslib": "^2.1.0" } }, + "node_modules/install": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/install/-/install-0.13.0.tgz", + "integrity": "sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/internal-slot": { "version": "1.0.7", "dev": true, diff --git a/package.json b/package.json index 254a8eb450..df30c7bebd 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "@angular/compiler": "^17.3.6", "@angular/core": "^17.3.6", "@angular/forms": "^17.3.6", - "@angular/material": "^17.3.6", - "@angular/material-moment-adapter": "^17.3.6", + "@angular/material": "^17.3.10", + "@angular/material-date-fns-adapter": "^17.3.10", "@angular/platform-browser": "^17.3.6", "@angular/platform-browser-dynamic": "^17.3.6", "@angular/router": "^17.3.6", @@ -69,9 +69,11 @@ "codemirror": "5.65.0", "core-js": "^3.21.1", "d3": "3.5.17", + "date-fns": "^3.6.0", "es5-shim": "^4.5.12", "file-saver": "^2.0.5", "font-awesome": "~4.7.0", + "install": "^0.13.0", "jquery": "2.1.4", "lodash": "~4.17", "lottie-web": "^5.12.2", diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 9be5408ace..69acaf196e 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -97,7 +97,11 @@ import {MatRadioModule} from '@angular/material/radio'; import {MatButtonToggleModule} from '@angular/material/button-toggle'; import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE, MatOptionModule} from '@angular/material/core'; import {MatDatepickerModule} from '@angular/material/datepicker'; -import {MomentDateAdapter} from '@angular/material-moment-adapter'; + +import { DateFnsAdapter, MAT_DATE_FNS_FORMATS } from '@angular/material-date-fns-adapter'; +import { enAU } from 'date-fns/locale'; + + import {doubtfireStates} from './doubtfire.states'; import {MatTableModule} from '@angular/material/table'; import {MatTabsModule} from '@angular/material/tabs'; @@ -229,13 +233,13 @@ import {GradeService} from './common/services/grade.service'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { parse: { - dateInput: 'DD/MM/YYYY', // this is how your date will be parsed from Input + dateInput: 'dd/MM/yyyy', // this is how your date will be parsed from Input }, display: { - dateInput: 'DD/MM/YYYY', // this is how your date will get displayed on the Input - monthYearLabel: 'MMMM YYYY', - dateA11yLabel: 'LL', - monthYearA11yLabel: 'MMMM YYYY', + dateInput: 'dd/MM/yyyy', // this is how your date will get displayed on the Input + monthYearLabel: 'MMMM yyyy', + dateA11yLabel: 'do MMMM yyyy', + monthYearA11yLabel: 'MMMM yyyy', }, }; @@ -382,8 +386,8 @@ const MY_DATE_FORMAT = { dateServiceProvider, CsvUploadModalProvider, CsvResultModalProvider, - {provide: MAT_DATE_LOCALE, useValue: 'en-AU'}, - {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]}, + {provide: MAT_DATE_LOCALE, useValue: enAU}, + {provide: DateAdapter, useClass: DateFnsAdapter, deps: [MAT_DATE_LOCALE]}, {provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMAT}, UnitStudentEnrolmentModalProvider, TaskCommentService, diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts index ee0f135c26..72c309371d 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts @@ -8,6 +8,7 @@ import { TaskDefinition } from 'src/app/api/models/task-definition'; import { Unit } from 'src/app/api/models/unit'; import { TaskDefinitionService } from 'src/app/api/services/task-definition.service'; import { AlertService } from 'src/app/common/services/alert.service'; +import { addWeeks } from 'date-fns'; @Component({ selector: 'f-unit-task-editor', @@ -183,7 +184,7 @@ export class UnitTaskEditorComponent implements AfterViewInit { task.abbreviation = abbr; task.description = 'New Description'; task.startDate = new Date(); - task.targetDate = new Date(); + task.targetDate = addWeeks(new Date(), 2); task.uploadRequirements = []; task.weighting = 4; task.targetGrade = 0; From 4d81fa1fabb07e40d0d42068f23b8e756f4cdf4b Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 1 Jul 2024 17:08:20 +1000 Subject: [PATCH 0148/1531] fix: correct broken template in activities list --- .../activity-type-list.component.html | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.html b/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.html index 9b294d5597..9c91b329f7 100644 --- a/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.html +++ b/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.html @@ -15,27 +15,10 @@

Activities

{{ activityType.name }} } @else { - -
- - - - - -
- - } - - + } @@ -52,12 +35,11 @@

Activities

{{ activityType.abbreviation }}
- } @else { #edit| } - + } @else { - + } @@ -76,8 +58,7 @@

Activities

edit - } @else { #edit| } - + } @else {
-
+ }
From 17958955f65bab2b268826f2a7e19f311071615b Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 1 Jul 2024 17:11:09 +1000 Subject: [PATCH 0149/1531] fix: correct campus list templates --- .../campus-list/campus-list.component.html | 63 +++++++------------ 1 file changed, 21 insertions(+), 42 deletions(-) diff --git a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html index a97dcd2e16..3fe38272ec 100644 --- a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html +++ b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html @@ -11,31 +11,14 @@

Campuses

Name @if (!editing(campus)) { -
- {{ campus.name }} -
+
+ {{ campus.name }} +
} @else { - -
- - - - - -
- - } - - + } @@ -49,15 +32,14 @@

Campuses

Abbreviation @if (!editing(campus)) { -
- {{ campus.abbreviation }} -
- } @else { #edit| } - +
+ {{ campus.abbreviation }} +
+ } @else { -
+ } @@ -71,11 +53,10 @@

Campuses

Default Sync Mode @if (!editing(campus)) { -
- {{ campus.mode | titlecase }} -
- } @else { #edit| } - +
+ {{ campus.mode | titlecase }} +
+ } @else { Default Sync Mode @@ -86,7 +67,7 @@

Campuses

}
-
+ } @@ -107,13 +88,12 @@

Campuses

Active @if (!editing(campus)) { -
- -
- } @else { #edit| } - +
+ +
+ } @else { -
+ } @@ -135,8 +115,7 @@

Campuses

- } @else { #edit| } - + } @else {
-
+ }
From a2c5a4490224ab49cfb4ff966e86bb3dd44afaf5 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 1 Jul 2024 17:11:32 +1000 Subject: [PATCH 0150/1531] chore(release): 8.0.17 --- CHANGELOG.md | 9 +++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ccd7cdc27..b578191a4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [8.0.17](https://github.com/macite/doubtfire-deploy/compare/v8.0.16...v8.0.17) (2024-07-01) + + +### Bug Fixes + +* correct broken template in activities list ([4d81fa1](https://github.com/macite/doubtfire-deploy/commit/4d81fa1fabb07e40d0d42068f23b8e756f4cdf4b)) +* correct campus list templates ([1795895](https://github.com/macite/doubtfire-deploy/commit/17958955f65bab2b268826f2a7e19f311071615b)) +* switch date formats to date-fns ([2394efb](https://github.com/macite/doubtfire-deploy/commit/2394efb07c03da18fb8114d87b0c89e68bf7fd2d)) + ### [8.0.16](https://github.com/macite/doubtfire-deploy/compare/v8.0.15...v8.0.16) (2024-06-28) diff --git a/package-lock.json b/package-lock.json index f31a23897f..8236e0d60d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "8.0.16", + "version": "8.0.17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "8.0.16", + "version": "8.0.17", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index df30c7bebd..47e0c6b97a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "8.0.16", + "version": "8.0.17", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 1b1710f5015456cefad1d74617305981a22962ad Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Wed, 3 Jul 2024 12:47:16 +1000 Subject: [PATCH 0151/1531] refactor: center scorm comments if no review button --- .../scorm-comment/scorm-comment.component.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html index edde1e057c..0c44be728c 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html @@ -8,7 +8,11 @@ > Review -
+ @if (!user.isStaff && !task.definition.scormAllowReview) { +
+ } @else { +
+ }
- -
-
diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.scss b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.scss index 05e8bffddc..82dc723d88 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.scss +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.scss @@ -8,3 +8,8 @@ .form-group { } + +#task-def-head { + background-color: white; + z-index: 10; +} diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html index a479f20ce3..634c71a98c 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html @@ -18,7 +18,7 @@
- Maximum Score + Quality Stars - Provide a score alongside the task status. We recommend avoiding this practice. + Provide a number of stars alongside the task status. Make sure you have a clear reason for + each star within your task description.
From f5388e45715597f0c92f252f721cf274bb8de0d5 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Wed, 10 Jul 2024 17:03:45 +1000 Subject: [PATCH 0157/1531] fix: ensure pdf is visible in task viewer mobile/narrow --- .../units/states/tasks/tasks-viewer/tasks-viewer.component.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.html b/src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.html index 845e7203a5..56e528f29e 100644 --- a/src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.html +++ b/src/app/units/states/tasks/tasks-viewer/tasks-viewer.component.html @@ -36,5 +36,6 @@
+ From e9046400e827481e09492bcb458b00b4e3aca347 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Wed, 10 Jul 2024 17:04:29 +1000 Subject: [PATCH 0158/1531] feat: add ability to minimise task details in task viewer --- .../f-task-details-view.component.html | 14 +++++++++++++- .../f-task-details-view.component.ts | 4 +++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/app/units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component.html b/src/app/units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component.html index 2ee4198b7c..5ca7a38d06 100644 --- a/src/app/units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component.html +++ b/src/app/units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component.html @@ -1,6 +1,18 @@
- + + + Task Details + + {{ panelOpenState() ? 'Hide' : 'Show' }} task details + + + +
diff --git a/src/app/units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component.ts b/src/app/units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component.ts index 57ea0b7993..8940b75542 100644 --- a/src/app/units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component.ts +++ b/src/app/units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, signal } from '@angular/core'; import { TaskDefinition } from 'src/app/api/models/task-definition'; import { Unit } from 'src/app/api/models/unit'; import { TasksViewerService } from '../../../tasks-viewer.service'; @@ -19,4 +19,6 @@ export class FTaskDetailsViewComponent implements OnInit { this.taskDef = taskDef; }); } + + public readonly panelOpenState = signal(false); } From 71df80b88ca626776e8e41d6530fbad6fe1355ec Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Wed, 10 Jul 2024 22:14:30 +1000 Subject: [PATCH 0159/1531] chore(release): 8.0.19 --- CHANGELOG.md | 13 +++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f108796bd4..c73daa7f9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [8.0.19](https://github.com/macite/doubtfire-deploy/compare/v8.0.18...v8.0.19) (2024-07-10) + + +### Features + +* add ability to minimise task details in task viewer ([e904640](https://github.com/macite/doubtfire-deploy/commit/e9046400e827481e09492bcb458b00b4e3aca347)) + + +### Bug Fixes + +* ensure pdf is visible in task viewer mobile/narrow ([f5388e4](https://github.com/macite/doubtfire-deploy/commit/f5388e45715597f0c92f252f721cf274bb8de0d5)) +* task def editor so save is not over fields and header visible for task being edited ([22a2616](https://github.com/macite/doubtfire-deploy/commit/22a26165c9f2ef634b3e79d1e5d5d6b74e6f2731)) + ### [8.0.18](https://github.com/macite/doubtfire-deploy/compare/v8.0.17...v8.0.18) (2024-07-03) diff --git a/package-lock.json b/package-lock.json index 52445d86a0..4571e71e31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "8.0.18", + "version": "8.0.19", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "8.0.18", + "version": "8.0.19", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 8529506a2d..6237d6dae1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "8.0.18", + "version": "8.0.19", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 3d44c115b498366b80e5b8b99ccd3eaa660ff613 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 15 Jul 2024 19:51:28 +1000 Subject: [PATCH 0160/1531] fix: ensure turn it in eula is accessible by all --- src/app/doubtfire.states.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index b9f95e88af..c578d87b26 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -225,8 +225,8 @@ const EulaState: NgHybridStateDeclaration = { }, }, data: { - pageTitle: 'Teaching Periods', - roleWhitelist: ['Convenor', 'Admin'], + pageTitle: 'End User License Agreement', + roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin', 'Auditor'], }, }; From f4360977d42466dcf2706c487b7648cd0faa409b Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 15 Jul 2024 19:51:43 +1000 Subject: [PATCH 0161/1531] chore(release): 8.0.20 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c73daa7f9c..a5fe9f894e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [8.0.20](https://github.com/macite/doubtfire-deploy/compare/v8.0.19...v8.0.20) (2024-07-15) + + +### Bug Fixes + +* ensure turn it in eula is accessible by all ([3d44c11](https://github.com/macite/doubtfire-deploy/commit/3d44c115b498366b80e5b8b99ccd3eaa660ff613)) + ### [8.0.19](https://github.com/macite/doubtfire-deploy/compare/v8.0.18...v8.0.19) (2024-07-10) diff --git a/package-lock.json b/package-lock.json index 4571e71e31..d176f2345c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "8.0.19", + "version": "8.0.20", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "8.0.19", + "version": "8.0.20", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 6237d6dae1..762969722e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "8.0.19", + "version": "8.0.20", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 9436f57e327eaee86b192a7adccbe43d800d3146 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Sat, 20 Jul 2024 14:37:39 +1000 Subject: [PATCH 0162/1531] refactor: create initial files for migration of comments-modal --- .../comments-modal/comments-modal.component.html | 0 .../comments-modal/comments-modal.component.scss | 0 .../modals/comments-modal/comments-modal.component.ts | 10 ++++++++++ 3 files changed, 10 insertions(+) create mode 100644 src/app/common/modals/comments-modal/comments-modal.component.html create mode 100644 src/app/common/modals/comments-modal/comments-modal.component.scss create mode 100644 src/app/common/modals/comments-modal/comments-modal.component.ts diff --git a/src/app/common/modals/comments-modal/comments-modal.component.html b/src/app/common/modals/comments-modal/comments-modal.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/common/modals/comments-modal/comments-modal.component.scss b/src/app/common/modals/comments-modal/comments-modal.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/common/modals/comments-modal/comments-modal.component.ts b/src/app/common/modals/comments-modal/comments-modal.component.ts new file mode 100644 index 0000000000..993f67ce00 --- /dev/null +++ b/src/app/common/modals/comments-modal/comments-modal.component.ts @@ -0,0 +1,10 @@ +import {Component, Input, Inject} from '@angular/core'; + +@Component({ + selector: 'comments-modal', + templateUrl: 'comments-modal.component.html', + styleUrls: ['comments-modal.component.scss'], +}) +export class CommentsModalComponent { + constructor() {} +} From 152b2fb30a6cbf0eaa9225bf04049b78c6161c4a Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Sat, 20 Jul 2024 15:18:37 +1000 Subject: [PATCH 0163/1531] refactor: create service file for migration of comments-modal --- src/app/common/modals/comments-modal/comments-modal.service.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/app/common/modals/comments-modal/comments-modal.service.ts diff --git a/src/app/common/modals/comments-modal/comments-modal.service.ts b/src/app/common/modals/comments-modal/comments-modal.service.ts new file mode 100644 index 0000000000..e69de29bb2 From 13710e2fa17419f5c22940af87091d9c55dc0a87 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Sat, 20 Jul 2024 20:53:31 +1000 Subject: [PATCH 0164/1531] refactor: migrate comments-modal --- .../comments-modal.component.html | 7 +++++++ .../comments-modal.component.scss | 17 +++++++++++++++++ .../comments-modal.component.ts | 19 ++++++++++++++----- .../comments-modal/comments-modal.service.ts | 18 ++++++++++++++++++ src/app/common/modals/modals.coffee | 1 - src/app/doubtfire-angular.module.ts | 2 ++ src/app/doubtfire-angularjs.module.ts | 5 +++-- 7 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/app/common/modals/comments-modal/comments-modal.component.html b/src/app/common/modals/comments-modal/comments-modal.component.html index e69de29bb2..888da289d2 100644 --- a/src/app/common/modals/comments-modal/comments-modal.component.html +++ b/src/app/common/modals/comments-modal/comments-modal.component.html @@ -0,0 +1,7 @@ + diff --git a/src/app/common/modals/comments-modal/comments-modal.component.scss b/src/app/common/modals/comments-modal/comments-modal.component.scss index e69de29bb2..76d21e070f 100644 --- a/src/app/common/modals/comments-modal/comments-modal.component.scss +++ b/src/app/common/modals/comments-modal/comments-modal.component.scss @@ -0,0 +1,17 @@ +.modal-comment { + padding: 15px; + + .image-comment { + width: 100%; + height: 100%; + align-content: center; + border-radius: 5px; + padding: 0; + border: none; + } + .pdf-comment { + width: 100%; + height: 80vh; + align-content: center; + } +} diff --git a/src/app/common/modals/comments-modal/comments-modal.component.ts b/src/app/common/modals/comments-modal/comments-modal.component.ts index 993f67ce00..6fa5e57b01 100644 --- a/src/app/common/modals/comments-modal/comments-modal.component.ts +++ b/src/app/common/modals/comments-modal/comments-modal.component.ts @@ -1,10 +1,19 @@ -import {Component, Input, Inject} from '@angular/core'; +import {Component, Input, Inject, OnInit} from '@angular/core'; +import {MAT_DIALOG_DATA} from '@angular/material/dialog'; @Component({ selector: 'comments-modal', - templateUrl: 'comments-modal.component.html', - styleUrls: ['comments-modal.component.scss'], + templateUrl: './comments-modal.component.html', + styleUrls: ['./comments-modal.component.scss'], }) -export class CommentsModalComponent { - constructor() {} +export class CommentsModalComponent implements OnInit { + @Input() commentType: string; + @Input() commentResourceUrl: string; + + constructor(@Inject(MAT_DIALOG_DATA) public data: any) {} + + ngOnInit(): void { + this.commentType = this.data.commentType; + this.commentResourceUrl = this.data.commentResourceUrl; + } } diff --git a/src/app/common/modals/comments-modal/comments-modal.service.ts b/src/app/common/modals/comments-modal/comments-modal.service.ts index e69de29bb2..d81a678160 100644 --- a/src/app/common/modals/comments-modal/comments-modal.service.ts +++ b/src/app/common/modals/comments-modal/comments-modal.service.ts @@ -0,0 +1,18 @@ +import {Injectable} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import {CommentsModalComponent} from './comments-modal.component'; + +@Injectable({ + providedIn: 'root', +}) +export class CommentsModalService { + constructor(public dialog: MatDialog) {} + + public show(commentResourceUrl: string, commentType: string) { + this.dialog.open(CommentsModalComponent, { + data: {commentResourceUrl, commentType}, + width: '100%', + maxWidth: '800px', + }); + } +} diff --git a/src/app/common/modals/modals.coffee b/src/app/common/modals/modals.coffee index 16d2be1ec8..003a522629 100644 --- a/src/app/common/modals/modals.coffee +++ b/src/app/common/modals/modals.coffee @@ -1,5 +1,4 @@ angular.module("doubtfire.common.modals", [ 'doubtfire.common.modals.csv-result-modal' 'doubtfire.common.modals.confirmation-modal' - 'doubtfire.common.modals.comments-modal' ]) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 9284745988..58dc8baa67 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -224,6 +224,7 @@ import {FTaskSheetViewComponent} from './units/states/tasks/viewer/directives/f- import {TasksViewerComponent} from './units/states/tasks/tasks-viewer/tasks-viewer.component'; import {UnitCodeComponent} from './common/unit-code/unit-code.component'; import {GradeService} from './common/services/grade.service'; +import {CommentsModalComponent} from './common/modals/comments-modal/comments-modal.component'; @NgModule({ // Components we declare @@ -325,6 +326,7 @@ import {GradeService} from './common/services/grade.service'; FUsersComponent, FTaskBadgeComponent, FUnitsComponent, + CommentsModalComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 868e381213..d58937e8ad 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -119,7 +119,6 @@ import 'build/src/app/units/states/analytics/analytics.js'; import 'build/src/app/common/filters/filters.js'; import 'build/src/app/common/content-editable/content-editable.js'; import 'build/src/app/common/modals/confirmation-modal/confirmation-modal.js'; -import 'build/src/app/common/modals/comments-modal/comments-modal.js'; import 'build/src/app/common/modals/csv-result-modal/csv-result-modal.js'; import 'build/src/app/common/modals/modals.js'; import 'build/src/app/common/grade-icon/grade-icon.js'; @@ -220,11 +219,12 @@ import {FUnitTaskListComponent} from './units/states/tasks/viewer/directives/f-u import {FTaskDetailsViewComponent} from './units/states/tasks/viewer/directives/f-task-details-view/f-task-details-view.component'; import {FTaskSheetViewComponent} from './units/states/tasks/viewer/directives/f-task-sheet-view/f-task-sheet-view.component'; import {TasksViewerComponent} from './units/states/tasks/tasks-viewer/tasks-viewer.component'; - import {FUnitsComponent} from './admin/states/f-units/f-units.component'; import {MarkedPipe} from './common/pipes/marked.pipe'; import {AlertService} from './common/services/alert.service'; import {GradeService} from './common/services/grade.service'; +import {CommentsModalService} from './common/modals/comments-modal/comments-modal.service'; + export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', 'doubtfire.sessions', @@ -306,6 +306,7 @@ DoubtfireAngularJSModule.factory( downgradeInjectable(EditProfileDialogService), ); DoubtfireAngularJSModule.factory('CreateNewUnitModal', downgradeInjectable(CreateNewUnitModal)); +DoubtfireAngularJSModule.factory('CommentsModal', downgradeInjectable(CommentsModalService)); // directive -> component DoubtfireAngularJSModule.directive( From 4400a027d5388d2b14ae6e314d3fc973cd8012eb Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Sat, 20 Jul 2024 20:56:57 +1000 Subject: [PATCH 0165/1531] refactor: remove old comments-modal files --- .../comments-modal/comments-modal.coffee | 32 ------------------- .../modals/comments-modal/comments-modal.scss | 15 --------- .../comments-modal/comments-modal.tpl.html | 10 ------ 3 files changed, 57 deletions(-) delete mode 100644 src/app/common/modals/comments-modal/comments-modal.coffee delete mode 100644 src/app/common/modals/comments-modal/comments-modal.scss delete mode 100644 src/app/common/modals/comments-modal/comments-modal.tpl.html diff --git a/src/app/common/modals/comments-modal/comments-modal.coffee b/src/app/common/modals/comments-modal/comments-modal.coffee deleted file mode 100644 index 59874c47e1..0000000000 --- a/src/app/common/modals/comments-modal/comments-modal.coffee +++ /dev/null @@ -1,32 +0,0 @@ -angular.module("doubtfire.common.modals.comments-modal", []) -# -# Modal to contain an image used in user comments. -# -.factory("CommentsModal", ($modal) -> - CommentsModal = {} - CommentsModal.show = (commentResourceUrl, commentType) -> - $modal.open - templateUrl: 'common/modals/comments-modal/comments-modal.tpl.html' - controller: 'CommentsModalCtrl' - size: 'lg' - resolve: - commentResourceUrl: -> commentResourceUrl - commentType: -> commentType - CommentsModal -) -.controller("CommentsModalCtrl", ($scope, $modalInstance, $sce, commentResourceUrl, commentType, alertService, fileDownloaderService) -> - # $scope.commentResourceUrl = $sce.trustAsResourceUrl(commentResourceUrl) - $scope.commentType = commentType - $scope.close = -> - fileDownloaderService.releaseBlob($scope.rawResourceUrl) - $modalInstance.dismiss() - - fileDownloaderService.downloadBlob( - commentResourceUrl, - (url, response) -> - $scope.rawResourceUrl = url - $scope.commentResourceUrl = $sce.trustAsResourceUrl(url) - (error) -> - alertService.error( "Error downloading comment: #{error}") - ) -) diff --git a/src/app/common/modals/comments-modal/comments-modal.scss b/src/app/common/modals/comments-modal/comments-modal.scss deleted file mode 100644 index 22ccacf4f8..0000000000 --- a/src/app/common/modals/comments-modal/comments-modal.scss +++ /dev/null @@ -1,15 +0,0 @@ -.modal-comment { - .image-comment { - width: 100%; - height: 100%; - align-content: center; - border-radius: 5px; - padding: 0; - border: none; - } - .pdf-comment { - width: 100%; - height: 80vh; - align-content: center; - } -} \ No newline at end of file diff --git a/src/app/common/modals/comments-modal/comments-modal.tpl.html b/src/app/common/modals/comments-modal/comments-modal.tpl.html deleted file mode 100644 index 59985945ff..0000000000 --- a/src/app/common/modals/comments-modal/comments-modal.tpl.html +++ /dev/null @@ -1,10 +0,0 @@ -
diff --git a/src/app/projects/states/project-root-state.component.ts b/src/app/projects/states/project-root-state.component.ts index 53de8a52b5..a8e026d5ac 100644 --- a/src/app/projects/states/project-root-state.component.ts +++ b/src/app/projects/states/project-root-state.component.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import {Component, Input} from '@angular/core'; -import {Observable, first} from 'rxjs'; +import {AsyncSubject, Observable, Subscriber, first} from 'rxjs'; import {Project, ProjectService} from 'src/app/api/models/doubtfire-model'; import {AppInjector} from 'src/app/app-injector'; import {NgHybridStateDeclaration} from '@uirouter/angular-hybrid'; @@ -32,19 +32,25 @@ export const ProjectRootState: NgHybridStateDeclaration = { project$: function ($stateParams) { const projectService = AppInjector.get(ProjectService); const globalState = AppInjector.get(GlobalStateService); + const projectId = parseInt($stateParams.projectId); - return new Observable((observer) => { - const projectId = parseInt($stateParams.projectId); + const result = new AsyncSubject(); - globalState.onLoad(() => { - projectService.get({id: projectId}, {cacheBehaviourOnGet: 'cacheQuery'}).subscribe({ - next: (project: Project) => { - observer.next(project); - observer.complete(); - }, - }); + const mappingCompleteCallback = (entity: Project) => { + result.next(entity); + result.complete(); + } + + // Async call to load the project + globalState.onLoad(() => { + projectService.get({id: projectId}, {cacheBehaviourOnGet: 'cacheQuery', mappingCompleteCallback: mappingCompleteCallback}).subscribe({ + next: (_project: Project) => { + // Do nothing - the mappingCompleteCallback will be called when complete + }, }); - }).pipe(first()); + }); + + return result; }, }, }; diff --git a/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.ts b/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.ts index 2fe29d2658..4c1920154a 100644 --- a/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.ts +++ b/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.ts @@ -1,16 +1,16 @@ -import { Component, OnInit, Input, SimpleChanges, LOCALE_ID } from '@angular/core'; +import { Component, OnInit, Input, SimpleChanges, LOCALE_ID, ViewContainerRef } from '@angular/core'; import { Project, Unit } from 'src/app/api/models/doubtfire-model'; import { formatDate } from '@angular/common'; import { MappingFunctions } from 'src/app/api/services/mapping-fn'; import { AppInjector } from 'src/app/app-injector'; +import { ChartBaseComponent } from 'src/app/common/chart-base/chart-base-component/chart-base-component.component'; @Component({ selector: 'f-progress-burndown-chart', templateUrl: './progressburndownchart.component.html', styleUrls: ['./progressburndownchart.component.scss'] }) - -export class ProgressBurndownChartComponent implements OnInit { +export class ProgressBurndownChartComponent extends ChartBaseComponent implements OnInit { @Input() project: Project; @Input() unit: Unit; @Input() grade: any; @@ -32,12 +32,16 @@ export class ProgressBurndownChartComponent implements OnInit { private seriesVisibility: { [key: string]: boolean } = {}; - constructor() { + constructor(public viewContainerRef: ViewContainerRef) { + super(viewContainerRef); this.data = []; this.temp = []; } ngOnInit(): void { + console.log('ProgressBurndownChartComponent: ngOnInit'); + console.log(this.project); + this.project.refreshBurndownChartData(); this.updateData(); this.data.forEach((item) => { @@ -53,8 +57,8 @@ export class ProgressBurndownChartComponent implements OnInit { } generateDates() { - const startDate: Date = this.unit.startDate; - const endDate: Date = this.unit.endDate; + const startDate: Date = this.project.unit.startDate; + const endDate: Date = this.project.unit.endDate; const locale: string = AppInjector.get(LOCALE_ID); const numberPoints = 10; // Get the number of days between dates diff --git a/src/app/visualisations/task-visualisation/taskvisualisation.component.html b/src/app/visualisations/task-visualisation/taskvisualisation.component.html index 891df20e2a..07c117cac4 100644 --- a/src/app/visualisations/task-visualisation/taskvisualisation.component.html +++ b/src/app/visualisations/task-visualisation/taskvisualisation.component.html @@ -1,7 +1,7 @@ diff --git a/src/app/visualisations/task-visualisation/taskvisualisation.component.ts b/src/app/visualisations/task-visualisation/taskvisualisation.component.ts index 9fa6ff4dec..bdca532a38 100644 --- a/src/app/visualisations/task-visualisation/taskvisualisation.component.ts +++ b/src/app/visualisations/task-visualisation/taskvisualisation.component.ts @@ -1,27 +1,23 @@ import { Component, OnInit, Input, SimpleChanges } from '@angular/core'; -import { TaskStatus } from 'src/app/api/models/task-status'; -import * as moment from 'moment'; - +import { Color } from 'd3'; +import { Project, TaskStatus, TaskStatusEnum } from 'src/app/api/models/doubtfire-model'; @Component({ - selector: 'app-task-visualisation', + selector: 'f-task-visualisation', templateUrl: './taskvisualisation.component.html', styleUrls: ['./taskvisualisation.component.scss'] }) export class TaskVisualisationComponent implements OnInit { - @Input() project: any; - @Input() grade: any; + @Input() project: Project; + @Input() grade: number; - data: any[] = []; - colors: any[] = []; + data: {name: string, value: number}[] = []; + colors: {name: string, value: string}[]; + view: number[] = [700, 400]; // options textColor: string = '#F5F5F5'; - constructor() { - this.data = []; - this.colors = []; - } ngOnInit(): void { this.updateData(); @@ -48,7 +44,7 @@ export class TaskVisualisationComponent implements OnInit { this.data = Array.from(taskCounts) .map(([status, count]) => { return { - name: this.formatTaskStatus(status), + name: TaskStatus.STATUS_LABELS.get(status), value: count, }; }) @@ -60,10 +56,11 @@ export class TaskVisualisationComponent implements OnInit { bIndex = bIndex === -1 ? sortOrder.length : bIndex; return aIndex - bIndex; - }); + }) + .filter((task) => task.value > 0); this.colors = Array.from(TaskStatus.STATUS_COLORS).map(([status, color]) => { - return { status: status, color: color }; + return { name: TaskStatus.STATUS_LABELS.get(status), value: color }; }); console.log('Data:', this.data); @@ -71,28 +68,6 @@ export class TaskVisualisationComponent implements OnInit { } } - getTaskChartColors(): any[] { - const customColors = this.colors.map((colorMapping) => { - const task = this.data.find( - (task) => this.formatTaskStatus(task.name) === this.formatTaskStatus(colorMapping.status) - ); - - const color = task && task.value > 0 ? colorMapping.color : '#EEEEEE'; - - return { - name: this.formatTaskStatus(colorMapping.status), - value: color, - }; - }); - return customColors; - } - - // to perform parsing of task labels.. - formatTaskStatus(status: string): string { - const words = status.replace(/[^a-zA-Z ]/g, ' ').split(' '); - return words.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' '); - } - onSelect(event) { console.log(event); } From 475c3165db099e1412e30fb6cf18bbaddd516e75 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Fri, 1 Nov 2024 21:25:05 +1100 Subject: [PATCH 0213/1531] feat: improve look of task status count --- src/app/api/models/task-status.ts | 3 ++- .../task-visualisation/taskvisualisation.component.ts | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/app/api/models/task-status.ts b/src/app/api/models/task-status.ts index 5068c0b7e5..f42850f430 100644 --- a/src/app/api/models/task-status.ts +++ b/src/app/api/models/task-status.ts @@ -151,7 +151,7 @@ export class TaskStatus { ]); public static readonly STATUS_LABELS = new Map([ - ['ready_for_feedback', 'Ready for Feedback'], + ['ready_for_feedback', 'Awaiting Feedback'], ['not_started', 'Not Started'], ['working_on_it', 'Working On It'], ['need_help', 'Need Help'], @@ -167,6 +167,7 @@ export class TaskStatus { public static readonly STATUS_NAME_TO_KEY = new Map([ ['Ready for Feedback', 'ready_for_feedback'], + ['Awaiting Feedback', 'ready_for_feedback'], ['Not Started', 'not_started'], ['Working On It', 'working_on_it'], ['Need Help', 'need_help'], diff --git a/src/app/visualisations/task-visualisation/taskvisualisation.component.ts b/src/app/visualisations/task-visualisation/taskvisualisation.component.ts index bdca532a38..8b5c1e1f50 100644 --- a/src/app/visualisations/task-visualisation/taskvisualisation.component.ts +++ b/src/app/visualisations/task-visualisation/taskvisualisation.component.ts @@ -39,7 +39,7 @@ export class TaskVisualisationComponent implements OnInit { } }); - const sortOrder = ['Complete', 'Not Started', 'Working On It']; + const sortOrder = ['Complete', 'Discuss', 'Awaiting Feedback', 'Working On It', 'Not Started']; this.data = Array.from(taskCounts) .map(([status, count]) => { @@ -48,6 +48,7 @@ export class TaskVisualisationComponent implements OnInit { value: count, }; }) + .filter((task) => task.value > 0 || sortOrder.includes(task.name)) .sort((a, b) => { let aIndex = sortOrder.indexOf(a.name); let bIndex = sortOrder.indexOf(b.name); @@ -56,15 +57,14 @@ export class TaskVisualisationComponent implements OnInit { bIndex = bIndex === -1 ? sortOrder.length : bIndex; return aIndex - bIndex; - }) - .filter((task) => task.value > 0); + }); this.colors = Array.from(TaskStatus.STATUS_COLORS).map(([status, color]) => { return { name: TaskStatus.STATUS_LABELS.get(status), value: color }; }); - console.log('Data:', this.data); - console.log('Colors:', this.colors); + // console.log('Data:', this.data); + // console.log('Colors:', this.colors); } } From e9cf3ecace83e2a742f7f34940bedc03babf62e9 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh <81244246+PrabhKamboj@users.noreply.github.com> Date: Sun, 3 Nov 2024 20:03:10 +1100 Subject: [PATCH 0214/1531] Migrate/project tasks list (#867) * feat: create initial files for migration of project-tasks-list * feat: create initial files for migration of project-tasks-list * Revert "feat: create initial files for migration of project-tasks-list" This reverts commit 3d047b35da48b4eaf73cb551b308dbba2883a88d. * refactor: migrate project-tasks-list component to TypeScript * chore: update Angular module files for project-tasks-list migration * fix: update project progress dashboard template * chore: update tasks CoffeeScript file * style: update task status colors generator mixin * feat: add order-by and tasks-for-group-set pipes * fix: address layout and styling issues in project-tasks-list - Ensure task boxes are consistent in size - Align layout to match the original design for row consistency - Correct hover effect to include bold styling for 'Assignment #' using a tooltip component and change color to black - Add blue outline on task box click - Update Angular module file - Update global styles * chore: remove deprecated CoffeeScript and template files for project-tasks-list * style: update styles for project-tasks-list component * style: update outline and styles for project-tasks-list component * fix: minor fixes for project tasks list --------- Co-authored-by: Andrew Cain --- src/app/api/models/doubtfire-model.ts | 1 + src/app/common/filters/order-by.pipe.ts | 28 ++++ .../filters/tasks-for-group-set.pipe.ts | 15 +++ src/app/doubtfire-angular.module.ts | 6 + src/app/doubtfire-angularjs.module.ts | 7 +- .../project-progress-dashboard.tpl.html | 124 +++++++++++------- .../project-tasks-list.coffee | 59 --------- .../project-tasks-list.component.html | 22 ++++ .../project-tasks-list.component.scss | 25 ++++ .../project-tasks-list.component.ts | 69 ++++++++++ .../project-tasks-list.scss | 26 ---- .../project-tasks-list.tpl.html | 10 -- src/app/tasks/tasks.coffee | 1 - src/styles.scss | 1 + .../mixins/task-status-colors-generator.scss | 4 +- 15 files changed, 255 insertions(+), 143 deletions(-) create mode 100644 src/app/common/filters/order-by.pipe.ts create mode 100644 src/app/common/filters/tasks-for-group-set.pipe.ts delete mode 100644 src/app/tasks/project-tasks-list/project-tasks-list.coffee create mode 100644 src/app/tasks/project-tasks-list/project-tasks-list.component.html create mode 100644 src/app/tasks/project-tasks-list/project-tasks-list.component.scss create mode 100644 src/app/tasks/project-tasks-list/project-tasks-list.component.ts delete mode 100644 src/app/tasks/project-tasks-list/project-tasks-list.scss delete mode 100644 src/app/tasks/project-tasks-list/project-tasks-list.tpl.html diff --git a/src/app/api/models/doubtfire-model.ts b/src/app/api/models/doubtfire-model.ts index fffc361a4e..05ac017fc2 100644 --- a/src/app/api/models/doubtfire-model.ts +++ b/src/app/api/models/doubtfire-model.ts @@ -61,4 +61,5 @@ export * from '../services/teaching-period-break.service'; export * from '../services/learning-outcome.service'; export * from '../services/group-set.service'; export * from '../services/task-similarity.service'; +export * from '../../common/services/grade.service'; export * from '../services/test-attempt.service'; diff --git a/src/app/common/filters/order-by.pipe.ts b/src/app/common/filters/order-by.pipe.ts new file mode 100644 index 0000000000..b22c5db7ea --- /dev/null +++ b/src/app/common/filters/order-by.pipe.ts @@ -0,0 +1,28 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'orderBy' +}) +export class OrderByPipe implements PipeTransform { + transform(array: any[], field: string, reverse: boolean = false): any[] { + if (!array || !field) { + return array; + } + + const sortedArray = [...array].sort((a, b) => { + if (a[field] < b[field]) { + return -1; + } + if (a[field] > b[field]) { + return 1; + } + return 0; + }); + + if (reverse) { + return sortedArray.reverse(); + } + + return sortedArray; + } +} diff --git a/src/app/common/filters/tasks-for-group-set.pipe.ts b/src/app/common/filters/tasks-for-group-set.pipe.ts new file mode 100644 index 0000000000..5e1832eaff --- /dev/null +++ b/src/app/common/filters/tasks-for-group-set.pipe.ts @@ -0,0 +1,15 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { Task, GroupSet } from 'src/app/api/models/doubtfire-model'; + +@Pipe({ + name: 'tasksForGroupset' +}) +export class TasksForGroupsetPipe implements PipeTransform { + transform(tasks: Task[], groupSet: GroupSet): Task[] { + if (!tasks) return tasks; + + return tasks.filter(task => { + return (task.definition.groupSet === groupSet) || (!task.definition.groupSet && !groupSet); + }); + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index b297b7643e..f74990816c 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -75,6 +75,7 @@ import { uploadSubmissionModalProvider, ConfirmationModalProvider, } from './ajs-upgraded-providers'; +import {ProjectTasksListComponent} from './tasks/project-tasks-list/project-tasks-list.component'; import { TaskCommentComposerComponent, DiscussionComposerDialog, @@ -140,6 +141,8 @@ import {TasksInTutorialsPipe} from './common/filters/tasks-in-tutorials.pipe'; import {TasksForInboxSearchPipe} from './common/filters/tasks-for-inbox-search.pipe'; import {StatusIconComponent} from './common/status-icon/status-icon.component'; import {ScrollingModule} from '@angular/cdk/scrolling'; +import {TasksForGroupsetPipe} from './common/filters/tasks-for-group-set.pipe'; +import {OrderByPipe} from './common/filters/order-by.pipe'; import {CheckForUpdateService} from './sessions/service-worker-updater/check-for-update.service'; import { ActivityTypeService, @@ -266,6 +269,7 @@ const MY_DATE_FORMAT = { AlertComponent, AboutDoubtfireModalContent, TeachingPeriodUnitImportDialogComponent, + ProjectTasksListComponent, TaskCommentComposerComponent, AudioCommentRecorderComponent, MicrophoneTesterComponent, @@ -318,6 +322,8 @@ const MY_DATE_FORMAT = { PdfViewerPanelComponent, StaffTaskListComponent, TaskSimilarityViewComponent, + TasksForGroupsetPipe, + OrderByPipe, FiltersPipe, TasksOfTaskDefinitionPipe, TasksInTutorialsPipe, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 1507d28f32..c662225b34 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -46,7 +46,6 @@ import 'build/src/app/tasks/modals/upload-submission-modal/upload-submission-mod import 'build/src/app/tasks/modals/grade-task-modal/grade-task-modal.js'; import 'build/src/app/tasks/modals/modals.js'; import 'build/src/app/tasks/tasks.js'; -import 'build/src/app/tasks/project-tasks-list/project-tasks-list.js'; import 'build/src/app/tasks/task-ilo-alignment/task-ilo-alignment.js'; import 'build/src/app/tasks/task-ilo-alignment/task-ilo-alignment-rater/task-ilo-alignment-rater.js'; import 'build/src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment.js'; @@ -145,6 +144,7 @@ import 'build/src/i18n/resources-locale_en-GB.js'; //#endregion import {AboutDoubtfireModal} from 'src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.component'; +import {ProjectTasksListComponent} from './tasks/project-tasks-list/project-tasks-list.component'; import {TaskCommentComposerComponent} from 'src/app/tasks/task-comment-composer/task-comment-composer.component'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {IntelligentDiscussionPlayerComponent} from './tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-player.component'; @@ -223,6 +223,7 @@ import { TaskVisualisationComponent } from './visualisations/task-visualisation/ import {FUnitsComponent} from './admin/states/units/units.component'; import {MarkedPipe} from './common/pipes/marked.pipe'; import {AlertService} from './common/services/alert.service'; + import {GradeService} from './common/services/grade.service'; import {TaskScormCardComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component'; @@ -305,6 +306,10 @@ DoubtfireAngularJSModule.factory( DoubtfireAngularJSModule.factory('CreateNewUnitModal', downgradeInjectable(CreateNewUnitModal)); // directive -> component +DoubtfireAngularJSModule.directive( + 'fProjectTasksList', + downgradeComponent({component: ProjectTasksListComponent}), +); DoubtfireAngularJSModule.directive( 'taskCommentComposer', downgradeComponent({component: TaskCommentComposerComponent}), diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html b/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html index 5dc40dc5b0..00d9887624 100644 --- a/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html +++ b/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html @@ -1,60 +1,95 @@
-
-
-
-
-
-
-

Task List

+
+
+
+
+
+
+

Task List

+
+
+
+ +
+
+
+
+
+
+

Target Grade

+ Select the grade you wish to achieve in the unit. +
+
+

+ +

-
- -
-
+
-
-
-
-

Target Grade

- Select the grade you wish to achieve in the unit. +
+ +
+
+
+
+
+

Burndown Chart

+ The Burndown chart shows how much work remains for you to achieve your target grade. +
+
+

Task Summary Chart

+ Summary of each of your task statuses +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ +

-
-
-
-
-
-
-
-
-
-
-

Burndown Chart

- The Burndown chart shows how much work remains for you to achieve your target grade.
+
+ -
-
-
- - -
+
+ Aim to keep your + Complete + line close to or ahead of the + Target + line to keep on track.
+
@@ -80,8 +115,9 @@

Task Summary Chart

line close to or ahead of the Target line to keep on track. +
-
-
-
+
+
+ \ No newline at end of file diff --git a/src/app/tasks/project-tasks-list/project-tasks-list.coffee b/src/app/tasks/project-tasks-list/project-tasks-list.coffee deleted file mode 100644 index 5e1dc4fd56..0000000000 --- a/src/app/tasks/project-tasks-list/project-tasks-list.coffee +++ /dev/null @@ -1,59 +0,0 @@ -angular.module('doubtfire.tasks.project-tasks-list', []) - -# -# Displays the tasks associated with a student's project which -# when a task is clicked will automatically jump to the task viewer -# of the task that was clicked -# -.directive('projectTasksList', -> - replace: true - restrict: 'E' - templateUrl: 'tasks/project-tasks-list/project-tasks-list.tpl.html' - scope: - unit: "=" - project: "=" - onSelect: "=" - inMenu: '@' - - controller: ($scope, $modal, newTaskService, analyticsService, gradeService) -> - analyticsService.event 'Student Project View', "Showed Task Button List" - - $scope.groupTasks = [] - - $scope.groupTasks.push.apply $scope.groupTasks, $scope.unit.groupSets.map (gs) -> - { - groupSet: gs, - name: gs.name - } - - $scope.groupTasks.push {groupSet: null, name: 'Individual Work'} - - # functions from task service - $scope.statusClass = newTaskService.statusClass - $scope.statusText = newTaskService.statusText - - $scope.taskDisabled = (task) -> - task.definition.targetGrade > $scope.project.targetGrade - - $scope.groupSetName = (id) -> - $scope.unit.groupSetsCache.get(id)?.name || "Individual Work" - - $scope.hideGroupSetName = $scope.unit.groupSets.length is 0 - - $scope.taskText = (task) -> - result = task.definition.abbreviation - - if task.definition.isGraded - if task.grade? - result += " (" + gradeService.gradeAcronyms[task.grade] + ")" - else - result += " (?)" - - if task.definition.maxQualityPts > 0 - if task.qualityPts? - result += " (" + task.qualityPts + "/" + task.definition.maxQualityPts + ")" - else - result += " (?/" + task.definition.maxQualityPts + ")" - - result -) diff --git a/src/app/tasks/project-tasks-list/project-tasks-list.component.html b/src/app/tasks/project-tasks-list/project-tasks-list.component.html new file mode 100644 index 0000000000..b4d993d733 --- /dev/null +++ b/src/app/tasks/project-tasks-list/project-tasks-list.component.html @@ -0,0 +1,22 @@ +
    +
    +
    {{ grouping.name }}
    +
    + + + + {{ + taskText(task) + }} +
    +
    +
diff --git a/src/app/tasks/project-tasks-list/project-tasks-list.component.scss b/src/app/tasks/project-tasks-list/project-tasks-list.component.scss new file mode 100644 index 0000000000..36bd44ade0 --- /dev/null +++ b/src/app/tasks/project-tasks-list/project-tasks-list.component.scss @@ -0,0 +1,25 @@ +.project-tasks-list { + .chip { + border-radius: 4px; + ::ng-deep .mdc-evolution-chip__text-label { + color: inherit !important; + } + } + + .group-set-name { + color: #777; + text-align: center; + font-size: 1em; + font-weight: bold; + } + + .mat-chip-clicked { + outline: #007bff auto 1px !important; + } + + .task-status { + ::ng-deep .mdc-evolution-chip__cell { + justify-content: center !important; + } + } +} diff --git a/src/app/tasks/project-tasks-list/project-tasks-list.component.ts b/src/app/tasks/project-tasks-list/project-tasks-list.component.ts new file mode 100644 index 0000000000..9e785100b8 --- /dev/null +++ b/src/app/tasks/project-tasks-list/project-tasks-list.component.ts @@ -0,0 +1,69 @@ +import {Component, OnInit, Input, Inject, Output, EventEmitter} from '@angular/core'; +import {analyticsService} from 'src/app/ajs-upgraded-providers'; +import {Project, Unit, Task, TaskService, TaskStatusEnum, GradeService} from 'src/app/api/models/doubtfire-model'; + +@Component({ + selector: 'f-project-tasks-list', + templateUrl: './project-tasks-list.component.html', + styleUrls: ['./project-tasks-list.component.scss'], +}) +export class ProjectTasksListComponent implements OnInit { + @Input() unit?: Unit; + @Input() project?: Project; + @Output() selectTask = new EventEmitter(); + selectedTask: Task | null = null; + + groupTasks = []; + + constructor( + private newTaskService: TaskService, + @Inject(analyticsService) private AnalyticsService, + public gradeService: GradeService, + ) {} + + ngOnInit(): void { + this.AnalyticsService.event('Student Project View', 'Showed Task Button List'); + this.groupTasks.push( + ...this.unit.groupSets.map((gs) => ({ + groupSet: gs, + name: gs.name, + })), + ); + this.groupTasks.push({groupSet: null, name: 'Individual Work'}); + } + + statusClass(status: TaskStatusEnum): string { + return this.newTaskService.statusClass(status); + } + + statusText(status: TaskStatusEnum): string { + return this.newTaskService.statusText(status); + } + + get hideGroupSetName(): boolean { + return this.unit.groupSets.length === 0; + } + + taskText(task: Task): string { + let result = task.definition.abbreviation; + if (task.definition.isGraded) { + if (task.grade) { + result += ` (${this.gradeService.gradeAcronyms[task.grade]})`; + } else { + result += ' (?)'; + } + } + if (task.definition.maxQualityPts > 0) { + if (task.qualityPts) { + result += ` (${task.qualityPts}/${task.definition.maxQualityPts})`; + } else { + result += ` (?/${task.definition.maxQualityPts})`; + } + } + return result; + } + + selectChip(task: Task): void { + this.selectedTask = task; + } +} diff --git a/src/app/tasks/project-tasks-list/project-tasks-list.scss b/src/app/tasks/project-tasks-list/project-tasks-list.scss deleted file mode 100644 index 4f94364fad..0000000000 --- a/src/app/tasks/project-tasks-list/project-tasks-list.scss +++ /dev/null @@ -1,26 +0,0 @@ -.project-tasks-list { - @include remove-list-padding; - text-align: center; - - .groupset-name { - color: #777; - text-align: center; - font-size: 1em; - font-weight: bold; - } - - li { - display: inline; - padding: 2px; - } - - .groupset-tasks:first-child .groupset-name { - margin-top: 0; - } - - // As a dropdown menu - &.dropdown-menu { - padding: 15px; - width: 400px; - } -} diff --git a/src/app/tasks/project-tasks-list/project-tasks-list.tpl.html b/src/app/tasks/project-tasks-list/project-tasks-list.tpl.html deleted file mode 100644 index ee9b845aed..0000000000 --- a/src/app/tasks/project-tasks-list/project-tasks-list.tpl.html +++ /dev/null @@ -1,10 +0,0 @@ -
    -
    -
    {{grouping.name}}
    -
  • - -
  • -
    -
diff --git a/src/app/tasks/tasks.coffee b/src/app/tasks/tasks.coffee index 5144dc6667..fedd49fc17 100644 --- a/src/app/tasks/tasks.coffee +++ b/src/app/tasks/tasks.coffee @@ -1,5 +1,4 @@ angular.module('doubtfire.tasks', [ 'doubtfire.tasks.modals' 'doubtfire.tasks.task-ilo-alignment' - 'doubtfire.tasks.project-tasks-list' ]) diff --git a/src/styles.scss b/src/styles.scss index f8ab056beb..0df654e6ba 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -63,3 +63,4 @@ $main-view-max-height: calc((var(--vh, 1vh) * (100)) - 85px); } } } + diff --git a/src/styles/mixins/task-status-colors-generator.scss b/src/styles/mixins/task-status-colors-generator.scss index e37542874a..9f473d74a7 100644 --- a/src/styles/mixins/task-status-colors-generator.scss +++ b/src/styles/mixins/task-status-colors-generator.scss @@ -14,9 +14,9 @@ } @mixin task-status-color($status) { - color: task-status-color($status, fore); + color: task-status-color($status, fore) !important; $base-color: task-status-color($status); - background-color: $base-color; + background-color: $base-color !important; @if $status == 'complete' { $lighter-color: task-status-color($status, light); @include gradient-vertical($lighter-color, $base-color); From eaa40e7f433156f11beec2dbec874df87690cf03 Mon Sep 17 00:00:00 2001 From: Leo Luong <65574142+leocomsci@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:16:09 +1100 Subject: [PATCH 0215/1531] Migrate:grade task modal (#564) * fix: ensure test dependencies are compatible This commit fixes dependencies issues that causes - `npm install` fails - `ng test` does not pick up any specs * test: add test command and doc * fix: add missing dependencies in component tests This commits ensure the unit tests are setup with correct dependencies. * fix: disable incomplete user service tests * ci: run unit tests in GitHub CI We use 2 Karma configurations to regulate how tests are run locally and in CI. - In development, the server runs forever with watch mode, using Chrome browser - In CI, the service runs once, using Chrome headless * refactor: remove task sheet viewer component * new: create inital files for grade-icon migration * refactor: unlink old component, add in new and downgrade * migrate: complete grade-icon component migration * refactor: remove old grade-icon component * refactor: update all usages of component * refactor: improve component styling * test: add unit tests for grade-icon component * docs: update Thoth Tech build badge reference * refactor: remove duplicate line in scss files * refactor: use prettier on migrated component * feat: format code using ESLint and Prettier This adds ability to format code using both ESLint and Prettier rules. * fix: include angular relevant lint rules * fix: address minor eslint issues * fix: report all lint issues as warning There are a large number of violations in the code base. We will need to incrementally address them in future pull requests. * docs: update formatting instructions * ci: use same lint command for development and CI * fix: escape dashes in unicode regex This fixes 'Range out of order in character class' error when trying to parse regex marked with `/u` unicode flag. * new: create initial files for migration of grade-task-modal * new: create service to show grade-task-modal * refactor: add and downgrade service to angularjs module * refactor: unlink old component and add in new * refactor: update task service to call migrated component * migrate: complete migration for rating quality-point tasks * refactor: add ability to grade tasks, tidy up component * refactor: prevent negative ratings * test: add unit tests * refactor: remove old component files * fix: buttons alignment in safari * refactor: add spacing between rating and grading * refactor: ran prettier * refactor: append df prefix to component selector * refactor: remove br and add spacing with ngstyle * style: remove inline style and create class * refactor: perform rating calculation in ts file * refactor: allow mat-slider to begin at 0 * refactor: replace buttons style with align * style: replace margin with padding * test: fix test to reflect rating of 0 * test: add test for rating label * refactor: remove console logging * fix: fix some minor error * chore: change welcome component name --------- Co-authored-by: Tan Le Co-authored-by: Perry Rose Co-authored-by: PerryRose <49971210+PerryRose@users.noreply.github.com> Co-authored-by: Andrew Cain Co-authored-by: A Luan Luong --- README.md | 13 +- src/app/api/models/task.ts | 41 ++--- src/app/common/common.coffee | 1 - src/app/common/grade-icon/grade-icon.coffee | 16 -- .../grade-icon/grade-icon.component.html | 3 + .../grade-icon/grade-icon.component.scss | 13 ++ .../grade-icon/grade-icon.component.spec.ts | 86 +++++++++ .../common/grade-icon/grade-icon.component.ts | 25 +++ src/app/common/grade-icon/grade-icon.scss | 48 ----- src/app/common/grade-icon/grade-icon.tpl.html | 8 - src/app/doubtfire-angular.module.ts | 4 + src/app/doubtfire-angularjs.module.ts | 10 +- ...roup-member-contribution-assigner.tpl.html | 24 +-- .../group-member-list.tpl.html | 2 +- .../project-progress-dashboard.tpl.html | 7 +- .../portfolio-grade-select-step.coffee | 5 +- .../portfolio-grade-select-step.tpl.html | 4 +- .../grade-task-modal/grade-task-modal.coffee | 41 ----- .../grade-task-modal.component.html | 68 +++++++ .../grade-task-modal.component.scss | 36 ++++ .../grade-task-modal.component.spec.ts | 169 ++++++++++++++++++ .../grade-task-modal.component.ts | 77 ++++++++ .../grade-task-modal/grade-task-modal.scss | 19 -- .../grade-task-modal.service.ts | 28 +++ .../grade-task-modal.tpl.html | 27 --- src/app/tasks/modals/modals.coffee | 1 - .../units/states/portfolios/portfolios.scss | 14 ++ .../states/portfolios/portfolios.tpl.html | 7 +- .../students-list/students-list.tpl.html | 4 +- src/app/welcome/welcome.component.ts | 5 +- 30 files changed, 587 insertions(+), 219 deletions(-) delete mode 100644 src/app/common/grade-icon/grade-icon.coffee create mode 100644 src/app/common/grade-icon/grade-icon.component.html create mode 100644 src/app/common/grade-icon/grade-icon.component.scss create mode 100644 src/app/common/grade-icon/grade-icon.component.spec.ts create mode 100644 src/app/common/grade-icon/grade-icon.component.ts delete mode 100644 src/app/common/grade-icon/grade-icon.scss delete mode 100644 src/app/common/grade-icon/grade-icon.tpl.html delete mode 100644 src/app/tasks/modals/grade-task-modal/grade-task-modal.coffee create mode 100644 src/app/tasks/modals/grade-task-modal/grade-task-modal.component.html create mode 100644 src/app/tasks/modals/grade-task-modal/grade-task-modal.component.scss create mode 100644 src/app/tasks/modals/grade-task-modal/grade-task-modal.component.spec.ts create mode 100644 src/app/tasks/modals/grade-task-modal/grade-task-modal.component.ts delete mode 100644 src/app/tasks/modals/grade-task-modal/grade-task-modal.scss create mode 100644 src/app/tasks/modals/grade-task-modal/grade-task-modal.service.ts delete mode 100644 src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html diff --git a/README.md b/README.md index b213dcce33..3e5b0546e5 100644 --- a/README.md +++ b/README.md @@ -227,11 +227,14 @@ TODO: ## Table of Contents -1. [Getting Started](#getting-started) -2. [Resources](#resources) -3. [Contributing](#contributing) -4. [Deployment](#deployment) -5. [License](#license) +- [Doubtfire Web ![CI](https://github.com/doubtfire-lms/doubtfire-web/actions/workflows/nodejs-ci.yml)](#doubtfire-web-) + - [Migration Progress](#migration-progress) + - [Table of Contents](#table-of-contents) + - [Getting Started](#getting-started) + - [Deployment](#deployment) + - [Resources](#resources) + - [Contributing](#contributing) + - [License](#license) ## Getting Started diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index 553eb500cc..af279dd6c7 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -23,9 +23,10 @@ import {Grade} from './grade'; import {LOCALE_ID} from '@angular/core'; import { HttpClient } from '@angular/common/http'; import {Observable, map} from 'rxjs'; -import {gradeTaskModal, uploadSubmissionModal} from 'src/app/ajs-upgraded-providers'; +import {uploadSubmissionModal} from 'src/app/ajs-upgraded-providers'; import {AlertService} from 'src/app/common/services/alert.service'; import {MappingFunctions} from '../services/mapping-fn'; +import { GradeTaskModalService } from 'src/app/tasks/modals/grade-task-modal/grade-task-modal.service'; export class Task extends Entity { id: number; @@ -670,28 +671,22 @@ export class Task extends Entity { }); }; // end update function - // Must provide grade if graded and in a final complete state - if ( - (this.definition.isGraded || this.definition.maxQualityPts > 0) && - TaskStatus.GRADEABLE_STATUSES.includes(status) - ) { - const gradeModal: any = AppInjector.get(gradeTaskModal); - const modal = gradeModal.show(this); - if (modal) { - modal.result.then( - // Grade was selected (modal closed with result) - (response) => { - this.grade = response.selectedGrade; - this.qualityPts = response.qualityPts; - updateFunc(); - }, - // Grade was not selected (modal was dismissed) - () => { - this.status = oldStatus; - alerts.message('Status reverted, as no grade was specified', 6000); - }, - ); - } + // Must provide grade if graded and in a final complete state - so use callback to run update function + if ((this.definition.isGraded || this.definition.maxQualityPts > 0) && TaskStatus.GRADEABLE_STATUSES.includes(status)) { + const gradeModal: GradeTaskModalService = AppInjector.get(GradeTaskModalService); + gradeModal.show(this, + // Grade was selected (modal closed with result) + (response) => { + this.grade = response.grade; + this.qualityPts = response.qualityPts; + updateFunc(); + }, + // Grade was not selected (modal was dismissed) + () => { + this.status = oldStatus; + alerts.message('Status reverted, as no grade was specified', 6000); + }, + ); } else { updateFunc(); } diff --git a/src/app/common/common.coffee b/src/app/common/common.coffee index e5bbea48a2..f330d8f6ac 100644 --- a/src/app/common/common.coffee +++ b/src/app/common/common.coffee @@ -3,6 +3,5 @@ angular.module("doubtfire.common", [ 'doubtfire.common.filters' 'doubtfire.common.modals' 'doubtfire.common.file-uploader' - 'doubtfire.common.grade-icon' 'doubtfire.common.content-editable' ]) diff --git a/src/app/common/grade-icon/grade-icon.coffee b/src/app/common/grade-icon/grade-icon.coffee deleted file mode 100644 index f35f7fbfa4..0000000000 --- a/src/app/common/grade-icon/grade-icon.coffee +++ /dev/null @@ -1,16 +0,0 @@ -angular.module('doubtfire.common.grade-icon', []) - -.directive 'gradeIcon', -> - restrict: 'E' - replace: true - templateUrl: 'common/grade-icon/grade-icon.tpl.html' - scope: - inputGrade: '=?grade' - colorful: '=?' - controller: ($scope, gradeService) -> - $scope.$watch 'inputGrade', (newGrade) -> - $scope.grade = if _.isString($scope.inputGrade) then gradeService.stringToGrade($scope.inputGrade) else $scope.inputGrade - $scope.gradeText = (grade) -> - if grade? then gradeService.grades[grade] or "Grade" - $scope.gradeLetter = (grade) -> - gradeService.gradeAcronyms[grade] or 'G' diff --git a/src/app/common/grade-icon/grade-icon.component.html b/src/app/common/grade-icon/grade-icon.component.html new file mode 100644 index 0000000000..0b1f23bec2 --- /dev/null +++ b/src/app/common/grade-icon/grade-icon.component.html @@ -0,0 +1,3 @@ + + {{ gradeLetter }} + diff --git a/src/app/common/grade-icon/grade-icon.component.scss b/src/app/common/grade-icon/grade-icon.component.scss new file mode 100644 index 0000000000..3b67a46b27 --- /dev/null +++ b/src/app/common/grade-icon/grade-icon.component.scss @@ -0,0 +1,13 @@ +.grade-icon { + color: #fff; + font-size: 1em; + border-radius: 100%; + width: 2.25em; + height: 2.25em; + font-weight: 100; + margin: 0 auto; + display: flex; + align-items: center; + justify-content: center; + background-color: #333333; +} diff --git a/src/app/common/grade-icon/grade-icon.component.spec.ts b/src/app/common/grade-icon/grade-icon.component.spec.ts new file mode 100644 index 0000000000..f1c6f74d9f --- /dev/null +++ b/src/app/common/grade-icon/grade-icon.component.spec.ts @@ -0,0 +1,86 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { GradeIconComponent } from './grade-icon.component'; +import { gradeService } from 'src/app/ajs-upgraded-providers'; + +describe('GradeIconComponent', () => { + let component: GradeIconComponent; + let fixture: ComponentFixture; + let gradeServiceStub: jasmine.SpyObj; + + beforeEach( + waitForAsync(() => { + gradeServiceStub = { + grades: ['Pass', 'Credit', 'Distinction', 'High Distinction'], + gradeAcronyms: { + Fail: 'F', + Pass: 'P', + Credit: 'C', + Distinction: 'D', + 'High Distinction': 'HD', + 0: 'P', + 1: 'C', + 2: 'D', + 3: 'HD', + }, + }; + + gradeServiceStub.grades[-1] = 'Fail'; + gradeServiceStub.gradeAcronyms[-1] = 'F'; + + TestBed.configureTestingModule({ + declarations: [GradeIconComponent], + providers: [{ provide: gradeService, useValue: gradeServiceStub }], + }).compileComponents(); + }) + ); + + beforeEach(() => { + fixture = TestBed.createComponent(GradeIconComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should set the index value when undefined', () => { + component.index = undefined; + component.ngOnInit(); + + expect(component.index).toEqual(-1); + }); + + it('should set the grade to Fail when given invalid input', () => { + component.index = undefined; + component.grade = 'Tomato'; + component.ngOnInit(); + + expect(component.index).toEqual(-1); + expect(component.gradeText).toEqual('Fail'); + expect(component.gradeLetter).toEqual('F'); + }); + + it('should appropriate set the grade when passed a grade value', () => { + gradeServiceStub.grades.forEach((grade: string) => { + component.grade = grade; + component.index = undefined; + component.ngOnInit(); + + expect(component.index).toEqual(gradeServiceStub.grades.indexOf(grade)); + expect(component.gradeText).toEqual(grade); + expect(component.gradeLetter).toEqual(gradeServiceStub.gradeAcronyms[grade]); + }); + }); + + it('should appropriate set the grade when passed a grade index', () => { + gradeServiceStub.grades.forEach((_, index: number) => { + component.index = index - 1; + component.ngOnInit(); + + expect(component.index).toEqual(index - 1); + expect(component.gradeText).toEqual(gradeServiceStub.grades[component.index]); + expect(component.gradeLetter).toEqual(gradeServiceStub.gradeAcronyms[component.gradeText]); + }); + }); +}); diff --git a/src/app/common/grade-icon/grade-icon.component.ts b/src/app/common/grade-icon/grade-icon.component.ts new file mode 100644 index 0000000000..0a283c0d0c --- /dev/null +++ b/src/app/common/grade-icon/grade-icon.component.ts @@ -0,0 +1,25 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { GradeService } from '../services/grade.service'; + +@Component({ + selector: 'grade-icon', + templateUrl: 'grade-icon.component.html', + styleUrls: ['grade-icon.component.scss'], +}) +export class GradeIconComponent implements OnInit { + @Input() grade: string | number = 'F'; + @Input() index: number; + + gradeText: string; + gradeLetter: string; + + constructor(private gradeService: GradeService) {} + + ngOnInit(): void { + if (this.index == undefined) { + this.index = this.gradeService.gradeNumbers[this.grade] || this.grade; + } + this.gradeText = this.gradeService.grades[this.index]; + this.gradeLetter = this.gradeService.gradeAcronyms[this.gradeText]; + } +} diff --git a/src/app/common/grade-icon/grade-icon.scss b/src/app/common/grade-icon/grade-icon.scss deleted file mode 100644 index 08db661a8b..0000000000 --- a/src/app/common/grade-icon/grade-icon.scss +++ /dev/null @@ -1,48 +0,0 @@ -.grade-icon.text-muted { - background-color: $text-muted; -} -.grade-icon.text-primary { - background-color: $brand-primary; -} -.grade-icon.text-success { - background-color: $brand-success; -} -.grade-icon.text-danger { - background-color: $brand-danger; -} -.grade-icon.text-info { - background-color: $brand-info; -} -.grade-icon.text-warning { - background-color: $brand-warning; -} -a .grade-icon:hover { - background-color: $link-hover-color; -} -.grade-icon { - color: #fff; - font-size: 1em; - background-color: $text-color; - border-radius: 100%; - width: 2.25em; - height: 2.25em; - font-weight: 100; - font-size: 1em; - @include no-select; - margin: 0 auto; - display: flex; - align-items: center; - justify-content: center; -} -.grade-icon.colorful { - &.grade-0 { background-color: $grade-color-p; } - &.grade-1 { background-color: $grade-color-c; } - &.grade-2 { background-color: $grade-color-d; } - &.grade-3 { background-color: $grade-color-hd; } -} -.text-left .grade-icon { - margin-left: 0; -} -.text-right .grade-icon { - margin-right: 0; -} diff --git a/src/app/common/grade-icon/grade-icon.tpl.html b/src/app/common/grade-icon/grade-icon.tpl.html deleted file mode 100644 index 1939b21361..0000000000 --- a/src/app/common/grade-icon/grade-icon.tpl.html +++ /dev/null @@ -1,8 +0,0 @@ -
- - {{gradeLetter(grade)}} - -
diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index f74990816c..a9d165749c 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -249,6 +249,8 @@ import {TaskScormCardComponent} from './projects/states/dashboard/directives/tas import {TestAttemptService} from './api/services/test-attempt.service'; import {ScormExtensionCommentComponent} from './tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component'; import {ScormExtensionModalComponent} from './common/modals/scorm-extension-modal/scorm-extension-modal.component'; +import { GradeIconComponent } from './common/grade-icon/grade-icon.component'; +import { GradeTaskModalComponent } from './tasks/modals/grade-task-modal/grade-task-modal.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -337,6 +339,8 @@ const MY_DATE_FORMAT = { TaskDropdownComponent, SplashScreenComponent, ProjectDashboardComponent, + GradeIconComponent, + GradeTaskModalComponent, ObjectSelectComponent, WelcomeComponent, AcceptEulaComponent, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index c662225b34..650fa27fcd 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -43,7 +43,6 @@ import 'build/src/app/visualisations/achievement-custom-bar-chart.js'; import 'build/src/app/visualisations/alignment-bar-chart.js'; import 'build/src/app/visualisations/achievement-box-plot.js'; import 'build/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.js'; -import 'build/src/app/tasks/modals/grade-task-modal/grade-task-modal.js'; import 'build/src/app/tasks/modals/modals.js'; import 'build/src/app/tasks/tasks.js'; import 'build/src/app/tasks/task-ilo-alignment/task-ilo-alignment.js'; @@ -119,7 +118,6 @@ import 'build/src/app/common/modals/confirmation-modal/confirmation-modal.js'; import 'build/src/app/common/modals/comments-modal/comments-modal.js'; import 'build/src/app/common/modals/csv-result-modal/csv-result-modal.js'; import 'build/src/app/common/modals/modals.js'; -import 'build/src/app/common/grade-icon/grade-icon.js'; import 'build/src/app/common/file-uploader/file-uploader.js'; import 'build/src/app/common/common.js'; import 'build/src/app/common/services/listener-service.js'; @@ -195,6 +193,8 @@ import { HeaderComponent } from './common/header/header.component'; import { SplashScreenComponent } from './home/splash-screen/splash-screen.component'; import { GlobalStateService } from './projects/states/index/global-state.service'; import { TransitionHooksService } from './sessions/transition-hooks.service'; +import { GradeIconComponent } from './common/grade-icon/grade-icon.component'; +import { GradeTaskModalService } from './tasks/modals/grade-task-modal/grade-task-modal.service'; import { AuthenticationService } from './api/services/authentication.service'; import { ProjectService } from './api/services/project.service'; import { ObjectSelectComponent } from './common/obect-select/object-select.component'; @@ -211,7 +211,6 @@ import { InboxComponent } from './units/states/tasks/inbox/inbox.component'; import { TaskDefinitionEditorComponent } from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component'; import { UnitAnalyticsComponent } from './units/states/analytics/unit-analytics-route.component'; import { UnitTaskEditorComponent } from './units/states/edit/directives/unit-tasks-editor/unit-task-editor.component'; -import { TeachingPeriodUnitImportService } from './admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog'; import { CreateNewUnitModal } from './admin/modals/create-new-unit-modal/create-new-unit-modal.component'; import { FUsersComponent } from './admin/states/users/users.component'; import { FUnitTaskListComponent } from './units/task-viewer/directives/unit-task-list/unit-task-list.component'; @@ -304,12 +303,17 @@ DoubtfireAngularJSModule.factory( downgradeInjectable(EditProfileDialogService), ); DoubtfireAngularJSModule.factory('CreateNewUnitModal', downgradeInjectable(CreateNewUnitModal)); +DoubtfireAngularJSModule.factory('GradeTaskModal', downgradeInjectable(GradeTaskModalService)); // directive -> component DoubtfireAngularJSModule.directive( 'fProjectTasksList', downgradeComponent({component: ProjectTasksListComponent}), ); +DoubtfireAngularJSModule.directive( + 'gradeIcon', + downgradeComponent({component: GradeIconComponent}), +); DoubtfireAngularJSModule.directive( 'taskCommentComposer', downgradeComponent({component: TaskCommentComposerComponent}), diff --git a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html index 4caab308f5..1fa8194d11 100644 --- a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html +++ b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html @@ -8,29 +8,29 @@ - - {{contrib.project.student.name}} + + {{member.student_name}} - + - - {{contrib.percent}} % effort + class="label {{percentClass(member.percent)}}" + ng-show="member.overStar"> + + {{member.percent}} % effort - + No effort diff --git a/src/app/groups/group-member-list/group-member-list.tpl.html b/src/app/groups/group-member-list/group-member-list.tpl.html index f483b4acbd..8c3b3c2dc5 100644 --- a/src/app/groups/group-member-list/group-member-list.tpl.html +++ b/src/app/groups/group-member-list/group-member-list.tpl.html @@ -38,7 +38,7 @@

No members in group

{{member.student.username || "N/A"}} {{member.student.name}} - +

+ + @@ -30,7 +34,7 @@

Target Grade

- +
@@ -120,4 +124,3 @@

Task Summary Chart

- \ No newline at end of file diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee index d29d0f65da..3a7ee7f2a4 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee @@ -9,7 +9,10 @@ angular.module('doubtfire.projects.states.portfolio.directives.portfolio-grade-s replace: true templateUrl: 'projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html' controller: ($scope, newProjectService, gradeService) -> - $scope.grades = gradeService.grades + if ! $scope.project.submittedGrade + $scope.project.submittedGrade = 0 + $scope.grades = gradeService.gradeValues + $scope.gradeName = (grade) -> gradeService.grades[grade] $scope.agreedToAssessmentCriteria = $scope.projectHasLearningSummaryReport() $scope.chooseGrade = (idx) -> $scope.project.submittedGrade = idx diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html index 244c110857..097b685e35 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html @@ -35,14 +35,14 @@

Grade Application

btn-radio="{{$index}}" >

Make sure your Learning Summary Report justifies how your portfolio demonstrates you have - met all unit learning outcomes to a {{targetGrade}} level + met all unit learning outcomes to a {{gradeName(project.submittedGrade)}} level

diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.coffee b/src/app/tasks/modals/grade-task-modal/grade-task-modal.coffee deleted file mode 100644 index 057dffee92..0000000000 --- a/src/app/tasks/modals/grade-task-modal/grade-task-modal.coffee +++ /dev/null @@ -1,41 +0,0 @@ -angular.module('doubtfire.tasks.modals.grade-task-modal', []) - -# -# A modal to grade a graded task -# -.factory('GradeTaskModal', ($modal) -> - GradeTaskModal = {} - - # - # Open a grade task modal with the provided task - # - GradeTaskModal.show = (task) -> - $modal.open - templateUrl: 'tasks/modals/grade-task-modal/grade-task-modal.tpl.html' - controller: 'GradeTaskModal' - resolve: - task: -> task - - GradeTaskModal -) -.controller('GradeTaskModal', ($scope, $modalInstance, gradeService, task) -> - $scope.task = task - $scope.data = { desiredGrade: task.grade, rating: task.qualityPts || 1, overStar: 0, confRating: 0 } - $scope.gradeValues = gradeService.allGradeValues - $scope.grades = gradeService.grades - $scope.dismiss = $modalInstance.dismiss - $scope.numStars = task.definition.maxQualityPts || 5 - $scope.close = -> - $modalInstance.close { qualityPts: $scope.data.rating, selectedGrade: $scope.data.desiredGrade} - - $scope.hoveringOver = (value) -> - $scope.data.overStar = value - - $scope.checkClearRating = -> - if $scope.data.confRating == 1 && $scope.data.rating == 1 && $scope.data.overStar == 1 - $scope.data.rating = 0 - else if $scope.data.confRating == 1 && $scope.data.overStar == 1 && $scope.data.rating == 0 - $scope.data.rating = 1 - - $scope.data.confRating = $scope.data.rating -) diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.html b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.html new file mode 100644 index 0000000000..ca25990989 --- /dev/null +++ b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.html @@ -0,0 +1,68 @@ + + Assess Task Quality + + +
+

+ Please provide a grade for task + + {{ task.definition.abbreviation }} + +

+
+ + + + + +
+
+ +
+

+ Please provide a quality rating for task + + {{ task.definition.abbreviation }} + +

+ + + +
+

Rating: {{ rating }} / {{totalRating}}

+
+
+
+ + + + + +
diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.scss b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.scss new file mode 100644 index 0000000000..ac4c1a21bf --- /dev/null +++ b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.scss @@ -0,0 +1,36 @@ +.grade-task-modal { + width: 450px; + padding-left: 2rem; + padding-right: 2rem; +} + +.slider { + width: 100%; +} + +.task-label { + background-color: #3939ff; + color: white; + padding: 0 0.75rem; + border-radius: 0.75rem; + margin-left: 0.5rem; + font-size: small; +} + +.label-rating { + display: flex; + justify-content: end; +} + +.grade-toggle-group { + display: flex; + justify-content: center; +} + +.grade-toggle { + padding: 0.5rem 0; +} + +.grade-task-item + .grade-task-item { + padding-top: 2rem; +} diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.spec.ts b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.spec.ts new file mode 100644 index 0000000000..32c6681f80 --- /dev/null +++ b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.spec.ts @@ -0,0 +1,169 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { GradeTaskModalComponent } from './grade-task-modal.component'; +import { gradeService } from 'src/app/ajs-upgraded-providers'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +describe('GradeTaskModalComponent', () => { + let component: GradeTaskModalComponent; + let fixture: ComponentFixture; + let gradeServiceStub: jasmine.SpyObj; + let dialogRefMock: jasmine.SpyObj; + let dialogDataStub: jasmine.SpyObj; + + beforeEach( + waitForAsync(() => { + gradeServiceStub = { + grades: ['Pass', 'Credit', 'Distinction', 'High Distinction'], + gradeAcronyms: { + Fail: 'F', + Pass: 'P', + Credit: 'C', + Distinction: 'D', + 'High Distinction': 'HD', + 0: 'P', + 1: 'C', + 2: 'D', + 3: 'HD', + }, + allGradeValues: [-1, 0, 1, 2, 3], + }; + gradeServiceStub.grades[-1] = 'Fail'; + gradeServiceStub.gradeAcronyms[-1] = 'F'; + + dialogDataStub = { + task: { + grade: undefined, + quality_pts: undefined, + definition: { + max_quality_pts: undefined, + }, + }, + }; + + dialogRefMock = { + close: () => {}, + }; + + TestBed.configureTestingModule({ + declarations: [GradeTaskModalComponent], + providers: [ + { provide: gradeService, useValue: gradeServiceStub }, + { provide: MatDialogRef, useValue: dialogRefMock }, + { provide: MAT_DIALOG_DATA, useValue: dialogDataStub }, + ], + }).compileComponents(); + }) + ); + + beforeEach(() => { + fixture = TestBed.createComponent(GradeTaskModalComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should return rating & grade when closed', () => { + spyOn(component.dialogRef, 'close'); + + component.rating = 5; + component.selectedGrade = 2; + component.close(); + + expect(component.dialogRef.close).toHaveBeenCalledWith({ + qualityPts: 5, + selectedGrade: 2, + }); + }); + + it('should dismiss', () => { + spyOn(component.dialogRef, 'close'); + component.dismiss(); + expect(component.dialogRef.close).toHaveBeenCalled(); + }); + + /** + * For Rating tasks + */ + it('should accept a new task object', () => { + const newRatingTask = { + grade: undefined, + quality_pts: 5, + definition: { + max_quality_pts: 10, + }, + }; + dialogDataStub.task = newRatingTask; + + component.ngOnInit(); + expect(component.task).toEqual(newRatingTask); + expect(component.rating).toEqual(newRatingTask.quality_pts); + expect(component.selectedGrade).toEqual(newRatingTask.grade); + expect(component.totalRating).toEqual(newRatingTask.definition.max_quality_pts); + }); + + it('should not allow a rating higher than the max rating', () => { + component.ngOnInit(); + component.rating = 1; + component.totalRating = 10; + component.updateRating(20); + + expect(component.rating).toEqual(1); + expect(component.totalRating).toEqual(10); + }); + + it('should not allow a rating lower than 0', () => { + component.ngOnInit(); + component.totalRating = 10; + component.updateRating(-10); + + expect(component.rating).toEqual(0); + expect(component.totalRating).toEqual(10); + }); + + it('should accept a new valid rating', () => { + component.ngOnInit(); + component.totalRating = 10; + component.updateRating(9); + + expect(component.rating).toEqual(9); + expect(component.totalRating).toEqual(10); + }); + + it('should reflect the rating in the rating label', () => { + component.ngOnInit(); + expect(component.ratingLabel).toEqual('0 / 5'); + + component.updateRating(-1); + expect(component.ratingLabel).toEqual('0 / 5'); + + component.updateRating(12); + expect(component.ratingLabel).toEqual('0 / 5'); + + component.updateRating(2); + expect(component.ratingLabel).toEqual('2 / 5'); + + component.updateRating(5); + expect(component.ratingLabel).toEqual('5 / 5'); + }); + + /** + * For Graded Tasks + */ + it('should accept a new valid grade', () => { + component.ngOnInit(); + component.updateGrade(3); + expect(component.selectedGrade).toEqual(3); + }); + + it('should not accept a new invalid grade', () => { + component.ngOnInit(); + component.updateGrade(10); + expect(component.selectedGrade).toEqual(undefined); + + component.updateGrade(-10); + expect(component.selectedGrade).toEqual(undefined); + }); +}); diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.ts b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.ts new file mode 100644 index 0000000000..1239308a3a --- /dev/null +++ b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.ts @@ -0,0 +1,77 @@ +import { Component, OnInit, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Task, GradeService } from 'src/app/api/models/doubtfire-model'; + +@Component({ + selector: 'grade-task-modal', + templateUrl: './grade-task-modal.component.html', + styleUrls: ['./grade-task-modal.component.scss'], +}) +export class GradeTaskModalComponent implements OnInit { + task: Task; + gradeValues: number[]; + + // Task Rating + totalRating: number; + rating: number; + ratingLabel: string; + + // Grade Select + selectedGrade: number; + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public dialogData: {task: Task}, + private gradeService: GradeService + ) {} + + ngOnInit(): void { + this.task = this.dialogData.task; + this.rating = this.task.qualityPts || 0; + this.selectedGrade = this.task.grade || 0; + this.totalRating = this.task.definition.maxQualityPts || 5; + this.gradeValues = this.gradeService.allGradeValues; + this.updateRatingLabel(); + } + + gradeName(grade: number): string { + return this.gradeService.grades[grade]; + } + + dismiss(): void { + this.dialogRef.close(); + } + + close(): void { + // Pass values back to service + this.dialogRef.close({ + qualityPts: this.rating, + selectedGrade: this.selectedGrade, + }); + } + + isValid() { + return ( + (this.task.definition.isGraded && this.selectedGrade) || + (this.task.definition.maxQualityPts > 0 && this.rating) + ); + } + + updateRating(value: number): void { + if (value >= 0 && value <= this.totalRating) { + this.rating = value; + this.updateRatingLabel(); + } + } + + updateRatingLabel(): void { + this.ratingLabel = `${this.rating} / ${this.totalRating}`; + } + + updateGrade(grade: number | string): void { + const gradeValue = Number(grade) + if (this.gradeValues.includes(gradeValue)) { + this.selectedGrade = gradeValue; + } + } +} diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.scss b/src/app/tasks/modals/grade-task-modal/grade-task-modal.scss deleted file mode 100644 index 29e7941885..0000000000 --- a/src/app/tasks/modals/grade-task-modal/grade-task-modal.scss +++ /dev/null @@ -1,19 +0,0 @@ -.grade-task-modal { - .task-quality-rating { - &:focus { - outline: none; - } - i { - font-size: 2em; - cursor: pointer; - } - .icon-colorful { - color: rgb(255, 247, 141); - -webkit-text-stroke-width: 1px; - -webkit-text-stroke-color: orange; - } - .icon-disable { - color: #ccc; - } - } -} diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.service.ts b/src/app/tasks/modals/grade-task-modal/grade-task-modal.service.ts new file mode 100644 index 0000000000..ee2e0fad56 --- /dev/null +++ b/src/app/tasks/modals/grade-task-modal/grade-task-modal.service.ts @@ -0,0 +1,28 @@ +import { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { GradeTaskModalComponent } from './grade-task-modal.component'; +import { Task } from 'src/app/api/models/doubtfire-model'; + +@Injectable({ + providedIn: 'root', +}) +export class GradeTaskModalService { + constructor(public dialog: MatDialog) {} + + public show(task: Task, successCallback: (response: {grade: number, qualityPts: number}) => void, errorCallback: () => void): void { + this.dialog + .open(GradeTaskModalComponent, { + data: { + task: task + }, + }) + .afterClosed() + .subscribe((result) => { + if (result) { + successCallback(result); + } else { + errorCallback(); + } + }); + } +} diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html b/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html deleted file mode 100644 index 0906d7b593..0000000000 --- a/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html +++ /dev/null @@ -1,27 +0,0 @@ -
- - - -
diff --git a/src/app/tasks/modals/modals.coffee b/src/app/tasks/modals/modals.coffee index 9dcd33874f..fae9a50a86 100644 --- a/src/app/tasks/modals/modals.coffee +++ b/src/app/tasks/modals/modals.coffee @@ -1,4 +1,3 @@ angular.module('doubtfire.tasks.modals', [ - 'doubtfire.tasks.modals.grade-task-modal' 'doubtfire.tasks.modals.upload-submission-modal' ]) diff --git a/src/app/units/states/portfolios/portfolios.scss b/src/app/units/states/portfolios/portfolios.scss index 704ea095ff..0e1e97b594 100644 --- a/src/app/units/states/portfolios/portfolios.scss +++ b/src/app/units/states/portfolios/portfolios.scss @@ -10,3 +10,17 @@ } } } + +.grade-icon { + color: #fff; + font-size: 1em; + border-radius: 100%; + width: 2.25em; + height: 2.25em; + font-weight: 100; + margin: 0 auto; + display: flex; + align-items: center; + justify-content: center; + background-color: #333333; +} diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html index 89247569ca..75b9a955ee 100644 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ b/src/app/units/states/portfolios/portfolios.tpl.html @@ -65,10 +65,9 @@

Mark Portfolios

btn-radio="{{$index}}" >
@@ -194,10 +193,10 @@

Mark Portfolios

{{student.tutorNames()}} {{student.shortTutorialDescription()}} - + - + diff --git a/src/app/units/states/students-list/students-list.tpl.html b/src/app/units/states/students-list/students-list.tpl.html index 929cefe386..2ff4736816 100644 --- a/src/app/units/states/students-list/students-list.tpl.html +++ b/src/app/units/states/students-list/students-list.tpl.html @@ -84,7 +84,7 @@

No students found

Stats - + Flags - + diff --git a/src/app/welcome/welcome.component.ts b/src/app/welcome/welcome.component.ts index f6aaafb270..351b4839db 100644 --- a/src/app/welcome/welcome.component.ts +++ b/src/app/welcome/welcome.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; @Component({ @@ -6,9 +6,8 @@ import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants templateUrl: './welcome.component.html', styleUrls: ['./welcome.component.scss'], }) -export class WelcomeComponent implements OnInit { +export class WelcomeComponent { constructor(private constants: DoubtfireConstants) {} - ngOnInit(): void {} public externalName = this.constants.ExternalName; } From deaa1e940f8295ff962c111f1dbac75ed5ff51fa Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Mon, 4 Nov 2024 21:28:25 +1100 Subject: [PATCH 0216/1531] fix: ensure authorisation active in angular --- src/app/doubtfire.states.ts | 54 +++++-------------- .../states/dashboard/dashboard.coffee | 1 - src/app/projects/states/groups/groups.coffee | 1 - src/app/projects/states/index/index.coffee | 1 - .../projects/states/outcomes/outcomes.coffee | 1 - .../states/portfolio/portfolio.coffee | 1 - .../states/project-root-state.component.ts | 1 - .../states/tutorials/tutorials.coffee | 1 - src/app/sessions/transition-hooks.service.ts | 15 +++++- src/app/units/states/index/index.coffee | 2 +- src/app/units/states/tasks/inbox/inbox.coffee | 2 +- .../task-viewer-state.component.ts | 2 +- src/app/units/unit-root-state.component.ts | 2 +- 13 files changed, 31 insertions(+), 53 deletions(-) diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index ab4a95ff22..7baa910f57 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -4,17 +4,11 @@ import {HomeComponent} from './home/states/home/home.component'; import {WelcomeComponent} from './welcome/welcome.component'; import {SignInComponent} from './sessions/states/sign-in/sign-in.component'; import {EditProfileComponent} from './account/edit-profile/edit-profile.component'; -import {TeachingPeriodListComponent} from './admin/states/teaching-periods/teaching-period-list/teaching-period-list.component'; import {AcceptEulaComponent} from './eula/accept-eula/accept-eula.component'; import { UnauthorisedComponent } from './errors/states/unauthorised/unauthorised.component'; import {FUsersComponent} from './admin/states/users/users.component'; import {FUnitsComponent} from './admin/states/units/units.component'; import {ProjectDashboardComponent} from './projects/states/dashboard/project-dashboard/project-dashboard.component'; -import {AppInjector} from './app-injector'; -import {ProjectService} from './api/services/project.service'; -import {Observable, first} from 'rxjs'; -import {GlobalStateService} from './projects/states/index/global-state.service'; -import {Project} from './api/models/project'; import {UnitRootState} from './units/unit-root-state.component'; import {ProjectRootState} from './projects/states/project-root-state.component'; import { TaskViewerState } from './units/task-viewer/task-viewer-state.component'; @@ -39,7 +33,7 @@ const institutionSettingsState: NgHybridStateDeclaration = { }, data: { pageTitle: 'Institution Settings', - roleWhiteList: ['Admin'], + roleWhitelist: ['Admin'], }, }; @@ -54,7 +48,7 @@ const usersState: NgHybridStateDeclaration = { }, data: { pageTitle: 'Administer users', - roleWhiteList: ['Admin'], + roleWhitelist: ['Admin'], }, }; @@ -70,8 +64,7 @@ const HomeState: NgHybridStateDeclaration = { }, }, data: { - pageTitle: 'Home Page', - roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin', 'Auditor'], + pageTitle: 'Home Page' }, }; @@ -176,8 +169,7 @@ const WelcomeState: NgHybridStateDeclaration = { }, }, data: { - pageTitle: 'Welcome', - roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin', 'Auditor'], + pageTitle: 'Welcome' }, }; @@ -209,22 +201,7 @@ const EditProfileState: NgHybridStateDeclaration = { }, }, data: { - pageTitle: 'Edit Profile', - roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin', 'Auditor'], - }, -}; - -const TeachingPeriodsState: NgHybridStateDeclaration = { - name: 'teaching_periods', - url: '/admin/teachingperiods', - views: { - main: { - component: TeachingPeriodListComponent, - }, - }, - data: { - pageTitle: 'Teaching Periods', - roleWhitelist: ['Convenor', 'Admin'], + pageTitle: 'Edit Profile' }, }; @@ -237,8 +214,7 @@ const EulaState: NgHybridStateDeclaration = { }, }, data: { - pageTitle: 'End User License Agreement', - roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin', 'Auditor'], + pageTitle: 'End User License Agreement' }, }; @@ -256,8 +232,7 @@ const ViewAllProjectsState: NgHybridStateDeclaration = { }, }, data: { - pageTitle: 'Teaching Periods', - roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin'], + pageTitle: 'All Units' }, }; @@ -277,7 +252,7 @@ const AdministerUnits: NgHybridStateDeclaration = { }, data: { pageTitle: 'Administer units', - roleWhiteList: ['Admin'], + roleWhitelist: ['Admin', 'Convenor', 'Auditor'], }, }; @@ -292,8 +267,7 @@ const ProjectDashboardState: NgHybridStateDeclaration = { }, }, data: { - pageTitle: 'Project Dashboard', - roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin'], + pageTitle: 'Unit Dashboard', }, }; @@ -312,9 +286,9 @@ const ViewAllUnits: NgHybridStateDeclaration = { }, }, data: { - pageTitle: 'Teaching Periods', + pageTitle: 'View Units', mode: 'tutor', - roleWhitelist: ['Tutor', 'Convenor', 'Admin'], + roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor'], }, }; @@ -335,8 +309,7 @@ const UnauthoriedState: NgHybridStateDeclaration = { }, data: { // Add data used by header - pageTitle: 'Unauthorised', - roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin'], + pageTitle: 'Unauthorised' }, }; /** @@ -409,7 +382,7 @@ const ScormPlayerStudentReviewState: NgHybridStateDeclaration = { }, data: { pageTitle: 'Review Knowledge Check', - roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin'], + roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin', 'Auditor'], }, }; @@ -443,7 +416,6 @@ const ScormPlayerReviewState: NgHybridStateDeclaration = { */ export const doubtfireStates = [ institutionSettingsState, - TeachingPeriodsState, HomeState, WelcomeState, SignInState, diff --git a/src/app/projects/states/dashboard/dashboard.coffee b/src/app/projects/states/dashboard/dashboard.coffee index d4d073c8ad..9e86c3b6a9 100644 --- a/src/app/projects/states/dashboard/dashboard.coffee +++ b/src/app/projects/states/dashboard/dashboard.coffee @@ -16,7 +16,6 @@ angular.module('doubtfire.projects.states.dashboard', [ data: task: "Dashboard" pageTitle: "_Home_" - roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Student', 'Auditor'] } ) diff --git a/src/app/projects/states/groups/groups.coffee b/src/app/projects/states/groups/groups.coffee index a20d2c0d8c..52fb04d9e1 100644 --- a/src/app/projects/states/groups/groups.coffee +++ b/src/app/projects/states/groups/groups.coffee @@ -12,7 +12,6 @@ angular.module('doubtfire.projects.states.groups', []) data: task: "Groups List" pageTitle: "_Home_" - roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Student', 'Auditor'] } ) diff --git a/src/app/projects/states/index/index.coffee b/src/app/projects/states/index/index.coffee index 0b9744b957..d77b2be900 100644 --- a/src/app/projects/states/index/index.coffee +++ b/src/app/projects/states/index/index.coffee @@ -13,7 +13,6 @@ angular.module('doubtfire.projects.states.index', []) templateUrl: "units/states/index/index.tpl.html" # We can re-use unit's index here data: pageTitle: "_Home_" - roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin', 'Auditor'] } ) diff --git a/src/app/projects/states/outcomes/outcomes.coffee b/src/app/projects/states/outcomes/outcomes.coffee index 5c5d610928..cc6cd7487b 100644 --- a/src/app/projects/states/outcomes/outcomes.coffee +++ b/src/app/projects/states/outcomes/outcomes.coffee @@ -12,7 +12,6 @@ angular.module('doubtfire.projects.states.outcomes', []) data: task: "Learning Outcomes" pageTitle: "_Home_" - roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Student', 'Auditor'] } ) diff --git a/src/app/projects/states/portfolio/portfolio.coffee b/src/app/projects/states/portfolio/portfolio.coffee index 4257ab1757..bed3cbd94b 100644 --- a/src/app/projects/states/portfolio/portfolio.coffee +++ b/src/app/projects/states/portfolio/portfolio.coffee @@ -14,7 +14,6 @@ angular.module('doubtfire.projects.states.portfolio', [ data: task: "Portfolio Creation" pageTitle: "_Home_" - roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Student', 'Auditor'] } ) diff --git a/src/app/projects/states/project-root-state.component.ts b/src/app/projects/states/project-root-state.component.ts index a8e026d5ac..53325cb784 100644 --- a/src/app/projects/states/project-root-state.component.ts +++ b/src/app/projects/states/project-root-state.component.ts @@ -21,7 +21,6 @@ export const ProjectRootState: NgHybridStateDeclaration = { abstract: true, data: { pageTitle: 'Unit Studied', - roleWhiteList: ['Student', 'Tutor', 'Convenor', 'Admin', 'Auditor'], }, views: { main: { diff --git a/src/app/projects/states/tutorials/tutorials.coffee b/src/app/projects/states/tutorials/tutorials.coffee index 06c8d3d531..5c22b609e3 100644 --- a/src/app/projects/states/tutorials/tutorials.coffee +++ b/src/app/projects/states/tutorials/tutorials.coffee @@ -12,7 +12,6 @@ angular.module('doubtfire.projects.states.tutorials', []) data: task: "Tutorial List" pageTitle: "_Home_" - roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Student', 'Auditor'] } ) diff --git a/src/app/sessions/transition-hooks.service.ts b/src/app/sessions/transition-hooks.service.ts index 834d0a886d..1215c3e6b7 100644 --- a/src/app/sessions/transition-hooks.service.ts +++ b/src/app/sessions/transition-hooks.service.ts @@ -4,6 +4,7 @@ import { UserService } from '../api/services/user.service'; import { DoubtfireAngularModule } from '../doubtfire-angular.module'; import { GlobalStateService } from '../projects/states/index/global-state.service'; import { DoubtfireConstants } from '../config/constants/doubtfire-constants'; +import { AuthenticationService } from '../api/services/authentication.service'; /** * The TransitionHooksService is responsible for intercepting transitions between states. @@ -20,7 +21,8 @@ export class TransitionHooksService { private userService: UserService, private transitions: TransitionService, private globalState: GlobalStateService, - private constants: DoubtfireConstants + private constants: DoubtfireConstants, + private authenticationService: AuthenticationService, ) { // Get the tii settings... this.constants.IsTiiEnabled.subscribe((enabled) => { @@ -35,6 +37,7 @@ export class TransitionHooksService { // Where is the transition coming from and going to? const toState = transition.to().name; + const toStateData = transition.to().data; // const fromState = transition.from().name; // Setup the global state @@ -44,6 +47,16 @@ export class TransitionHooksService { this.globalState.setNotInboxState(); } + // Check authorization whitelist + if (toStateData.roleWhitelist && !this.authenticationService.isAuthorised(toStateData.roleWhitelist)) { + if (authenticationService.isAuthenticated()) { + return transition.router.stateService.target("unauthorised"); + } else if (toState !== "sign_in") { + return transition.router.stateService.target("sign_in"); + } + return false; + } + // Adjust settings such as headers switch (toState) { case 'timeout': diff --git a/src/app/units/states/index/index.coffee b/src/app/units/states/index/index.coffee index 88d118d1c8..69b9888ea5 100644 --- a/src/app/units/states/index/index.coffee +++ b/src/app/units/states/index/index.coffee @@ -13,7 +13,7 @@ angular.module('doubtfire.units.states.index', []) templateUrl: "units/states/index/index.tpl.html" data: pageTitle: "_Home_" - roleWhitelist: ['Student', 'Tutor', 'Convenor', 'Admin', 'Auditor'] + roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor'] } ) diff --git a/src/app/units/states/tasks/inbox/inbox.coffee b/src/app/units/states/tasks/inbox/inbox.coffee index 9f04950ca0..1be9546765 100644 --- a/src/app/units/states/tasks/inbox/inbox.coffee +++ b/src/app/units/states/tasks/inbox/inbox.coffee @@ -14,7 +14,7 @@ angular.module('doubtfire.units.states.tasks.inbox', []) data: task: "Task Inbox" pageTitle: "_Home_" - roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor', 'Auditor'] + roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor'] } ) diff --git a/src/app/units/task-viewer/task-viewer-state.component.ts b/src/app/units/task-viewer/task-viewer-state.component.ts index 833647f4cb..08fdcf38a6 100644 --- a/src/app/units/task-viewer/task-viewer-state.component.ts +++ b/src/app/units/task-viewer/task-viewer-state.component.ts @@ -39,7 +39,7 @@ export const TaskViewerState: NgHybridStateDeclaration = { parent: 'unit-root-state', data: { pageTitle: 'Unit Tasks', - roleWhiteList: ['Tutor', 'Convenor', 'Admin', 'Auditor'], + roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor'], }, views: { unitView: { diff --git a/src/app/units/unit-root-state.component.ts b/src/app/units/unit-root-state.component.ts index 8a6109121f..cd239a61a5 100644 --- a/src/app/units/unit-root-state.component.ts +++ b/src/app/units/unit-root-state.component.ts @@ -34,7 +34,7 @@ export const UnitRootState: NgHybridStateDeclaration = { abstract: true, data: { pageTitle: 'Unit Root State', - roleWhiteList: ['Tutor', 'Convenor', 'Admin', 'Auditor'], + roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor'], }, views: { main: { From efa89c344069d386f2411a417e570d4158af91b9 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Tue, 5 Nov 2024 14:12:35 +1100 Subject: [PATCH 0217/1531] fix: complete student enrolment modal --- src/app/api/models/unit.ts | 24 +++++++- src/app/common/header/header.component.ts | 4 +- src/app/doubtfire-angular.module.ts | 1 + src/app/doubtfire-angularjs.module.ts | 1 - ...nit-student-enrolment-modal.component.html | 14 ++--- .../unit-student-enrolment-modal.component.ts | 57 ++++++++----------- .../unit-student-enrolment-modal.service.ts | 10 ++-- 7 files changed, 63 insertions(+), 48 deletions(-) diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index b27159832e..9d8ed9fa3f 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -22,6 +22,7 @@ import { Project, TutorialStreamService, UnitRoleService, + Campus, } from './doubtfire-model'; import {LearningOutcome} from './learning-outcome'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -78,7 +79,7 @@ export class Unit extends Entity { public readonly groupSetsCache: EntityCache = new EntityCache(); - groupMemberships: Array; + groupMemberships: GroupMembership[]; readonly studentCache: EntityCache = new EntityCache(); @@ -150,6 +151,27 @@ export class Unit extends Entity { return this.findStudent(id)?.enrolled; } + /** + * Enrol a student within the unit. + * + * @param idOrEmail The student id or email of the student to enrol. + * @param campus The student's campus + * @returns an observer of the post with the student project. + */ + public enrolStudent(idOrEmail: string, campus: Campus): Observable { + const projectService = AppInjector.get(ProjectService); + + return projectService.create( + { + unit_id: this.id, + student_num: idOrEmail, + campus_id: campus.id }, + { + cache: this.studentCache + } + ); + } + public get currentUserIsStaff(): boolean { return this.myRole !== 'Student'; } diff --git a/src/app/common/header/header.component.ts b/src/app/common/header/header.component.ts index a07349c94e..b5e1960c8a 100644 --- a/src/app/common/header/header.component.ts +++ b/src/app/common/header/header.component.ts @@ -71,8 +71,8 @@ export class HeaderComponent implements OnInit, OnDestroy { this.subscriptions.push( this.globalState.projectsSubject.subscribe({ next: (projects) => { - if (projects == null) return; - this.projects = projects.filter((project) => project.unit.myRole === 'Student'); + if (!projects) return; + this.projects = projects.filter((project) => project?.unit?.myRole === 'Student'); }, error: (err) => {}, }), diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 6967a7df3f..a81a58f0bb 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -271,6 +271,7 @@ import { UnitStudentEnrolmentModalComponent } from './units/modals/unit-student- // Components we declare declarations: [ AlertComponent, + UnitStudentEnrolmentModalComponent, AboutDoubtfireModalContent, TeachingPeriodUnitImportDialogComponent, ProjectTasksListComponent, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 29a1b8b68d..1aee534ad4 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -90,7 +90,6 @@ import 'build/src/app/groups/groups.js'; import 'build/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.js'; import 'build/src/app/groups/group-member-list/group-member-list.js'; import 'build/src/app/groups/group-set-selector/group-set-selector.js'; -import 'build/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.js'; import 'build/src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.js'; import 'build/src/app/units/modals/modals.js'; import 'build/src/app/units/units.js'; diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html index 7b25032b56..e3668f2b9b 100644 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html @@ -1,4 +1,4 @@ - - Student ID - + Student ID or Email + Select Campus - - {{ campus.name }} + + {{ campus.name }} @@ -29,6 +29,6 @@ - + - + diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts index c58d56df74..09e1b2cf86 100644 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts @@ -1,56 +1,49 @@ -import { Component, Inject } from '@angular/core'; +import { Component, Inject, OnInit } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { alertService, CampusService, Project } from 'src/app/ajs-upgraded-providers'; +import { Campus, Project, Unit } from 'src/app/api/models/doubtfire-model'; +import { CampusService } from 'src/app/api/services/campus.service'; +import { AlertService } from 'src/app/common/services/alert.service'; @Component({ - selector: 'unit-student-enrolment-modal', + selector: 'f-unit-student-enrolment-modal', templateUrl: 'unit-student-enrolment-modal.component.html', styleUrls: ['unit-student-enrolment-modal.component.scss'], }) -export class UnitStudentEnrolmentModalComponent { - unit: any; - campuses: any = []; - projects: any; - student_id: string; - campus_id: any; +export class UnitStudentEnrolmentModalComponent implements OnInit { + unit: Unit; + campuses: Campus[]; + studentIdOrEmail: string; + selectedCampus: Campus; constructor( public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any, - @Inject(alertService) public alert: any, - @Inject(CampusService) public campusService: any, - @Inject(Project) private project: any + @Inject(MAT_DIALOG_DATA) public data: {unit: Unit}, + public alertService: AlertService, + public campusService: CampusService, ) {} ngOnInit() { this.unit = this.data.unit; - this.projects = this.data.unit.students; - this.campusService.query().subscribe((campuses: any) => { + this.campusService.query().subscribe((campuses: Campus[]) => { this.campuses = campuses; }); - console.log(this.unit); - console.log(this.projects); } - enrolStudent(student_id, campus_id) { - console.log(this.unit.id, student_id, campus_id); - if (campus_id == null) { - this.alert.add('danger', 'Campus missing. Please indicate student campus', 5000); + enrolStudent(studentIdOrEmail: string, campus: Campus) { + if (!campus) { + this.alertService.error('Campus missing. Please indicate student campus', 5000); return; } - this.project.create( - { unit_id: this.unit.id, student_num: student_id, campus_id: campus_id }, - (project) => { - if (!this.unit.studentEnrolled(project.project_id)) { - this.unit.addStudent(project); - this.alert.add('success', 'Student enrolled', 2000); + this.unit.enrolStudent(studentIdOrEmail, campus). + subscribe({ + next: (_: Project) => { + this.alertService.success('Student enrolled', 2000); this.dialogRef.close(); - } else { - this.alert.add('danger', 'Student is already enrolled', 2000); + }, + error: (response: string) => { + this.alertService.error(`Error enrolling student: ${response}`, 6000); } - }, - (response: { data: { error } }) => - this.alert.add('danger', `Error enrolling student: ${response.data.error}`, 6000) + } ); } } diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts index 5ecec93bc9..c7d5ac81bf 100644 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; -import { MatDialogRef, MatDialog } from '@angular/material/dialog'; +import { MatDialog } from '@angular/material/dialog'; import { UnitStudentEnrolmentModalComponent } from './unit-student-enrolment-modal.component'; +import { Unit } from 'src/app/api/models/doubtfire-model'; @Injectable({ providedIn: 'root', @@ -8,11 +9,10 @@ import { UnitStudentEnrolmentModalComponent } from './unit-student-enrolment-mod export class UnitStudentEnrolmentModalService { constructor(public dialog: MatDialog) {} - public show(unit: any) { - let dialogRef: MatDialogRef; - dialogRef = this.dialog.open(UnitStudentEnrolmentModalComponent, { + public show(unit: Unit) { + this.dialog.open(UnitStudentEnrolmentModalComponent, { data: { - unit, + unit: unit, }, }); } From 1de217c0bc19b8dbedb21cf2e89e195772ae2a02 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Tue, 5 Nov 2024 15:08:04 +1100 Subject: [PATCH 0218/1531] fix: remove markdown filter from learning outcomes --- src/app/config/privacy-policy/privacy-policy.ts | 17 ++++++++--------- src/app/doubtfire-angularjs.module.ts | 2 -- .../upload-submission-modal.tpl.html | 4 ++-- .../task-ilo-alignment-modal.tpl.html | 2 +- .../task-ilo-alignment-viewer.tpl.html | 4 ++-- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/app/config/privacy-policy/privacy-policy.ts b/src/app/config/privacy-policy/privacy-policy.ts index 8142d8b08c..ebfe968cd2 100644 --- a/src/app/config/privacy-policy/privacy-policy.ts +++ b/src/app/config/privacy-policy/privacy-policy.ts @@ -10,7 +10,6 @@ interface Response { @Injectable({ providedIn: 'root' }) - export class PrivacyPolicy { privacy = ''; plagiarism = ''; @@ -22,12 +21,12 @@ export class PrivacyPolicy { const url: string = `${this.API_URL}/settings/privacy`; - this.http - .get(url) - .subscribe(response => { - this.privacy = response.privacy; - this.plagiarism = response.plagiarism; - this.loaded = true; - }); + this.http.get(url) + .subscribe(response => { + this.privacy = response.privacy; + this.plagiarism = response.plagiarism; + this.loaded = true; + } + ); } -} \ No newline at end of file +} diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 68c662043e..d9dc6955d5 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -218,7 +218,6 @@ import { ProgressBurndownChartComponent } from './visualisations/progress-burndo import { TaskVisualisationComponent } from './visualisations/task-visualisation/taskvisualisation.component'; import {FUnitsComponent} from './admin/states/units/units.component'; -import {MarkedPipe} from './common/pipes/marked.pipe'; import {AlertService} from './common/services/alert.service'; import {GradeService} from './common/services/grade.service'; @@ -243,7 +242,6 @@ export const DoubtfireAngularJSModule = angular.module('doubtfire', [ DoubtfireAngularJSModule.factory('AboutDoubtfireModal', downgradeInjectable(AboutDoubtfireModal)); DoubtfireAngularJSModule.factory('DoubtfireConstants', downgradeInjectable(DoubtfireConstants)); DoubtfireAngularJSModule.factory('ExtensionModal', downgradeInjectable(ExtensionModalService)); -DoubtfireAngularJSModule.factory('Marked', downgradeInjectable(MarkedPipe)); DoubtfireAngularJSModule.factory('CalendarModal', downgradeInjectable(CalendarModalService)); DoubtfireAngularJSModule.factory('TaskCommentService', downgradeInjectable(TaskCommentService)); DoubtfireAngularJSModule.factory('alertService', downgradeInjectable(AlertService)); diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html index 9caab7897e..92070ac30f 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html @@ -167,9 +167,9 @@

@@ -194,10 +194,10 @@

Mark Portfolios

{{student.tutorNames()}} {{student.shortTutorialDescription()}} - + - + diff --git a/src/app/units/states/students-list/students-list.tpl.html b/src/app/units/states/students-list/students-list.tpl.html index d81fdb4cd6..830d0a4c3f 100644 --- a/src/app/units/states/students-list/students-list.tpl.html +++ b/src/app/units/states/students-list/students-list.tpl.html @@ -130,7 +130,7 @@

No students found

- + From 3da7a4b54a5892ea99cd365ae439677b0f52ed6f Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:40:38 +1100 Subject: [PATCH 0221/1531] feat: add editor for task feedback templates --- src/app/api/models/doubtfire-model.ts | 2 +- src/app/api/models/feedback-template.ts | 78 +++++++++ src/app/api/models/task-definition.ts | 7 +- .../api/services/feedback-template.service.ts | 28 +++ src/app/doubtfire-angular.module.ts | 4 + .../task-definition-editor.component.html | 21 ++- .../task-definition-feedback.component.html | 127 ++++++++++++++ .../task-definition-feedback.component.scss | 0 .../task-definition-feedback.component.ts | 163 ++++++++++++++++++ 9 files changed, 426 insertions(+), 4 deletions(-) create mode 100644 src/app/api/models/feedback-template.ts create mode 100644 src/app/api/services/feedback-template.service.ts create mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.html create mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.scss create mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.ts diff --git a/src/app/api/models/doubtfire-model.ts b/src/app/api/models/doubtfire-model.ts index fffc361a4e..38b886a2ae 100644 --- a/src/app/api/models/doubtfire-model.ts +++ b/src/app/api/models/doubtfire-model.ts @@ -37,6 +37,7 @@ export * from './scorm-player-context'; export * from './test-attempt'; export * from './task-comment/scorm-comment'; export * from './task-comment/scorm-extension-comment'; +export * from './feedback-template'; // Users -- are students or staff export * from './user/user'; @@ -44,7 +45,6 @@ export * from './user/user'; // WebCal -- calendars used to track task due dates export * from './webcal/webcal'; - export * from '../services/authentication.service'; export * from '../services/unit.service'; export * from '../services/project.service'; diff --git a/src/app/api/models/feedback-template.ts b/src/app/api/models/feedback-template.ts new file mode 100644 index 0000000000..85da6af509 --- /dev/null +++ b/src/app/api/models/feedback-template.ts @@ -0,0 +1,78 @@ +import {Entity, EntityMapping} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; +import {AppInjector} from 'src/app/app-injector'; +import {TaskDefinition} from './task-definition'; +import {FeedbackTemplateService} from '../services/feedback-template.service'; + +export class FeedbackTemplate extends Entity { + id: number; + learningOutcome: string; + chipText: string; + description: string; + commentText: string; + summaryText: string; + + readonly taskDefinition: TaskDefinition; + + constructor(taskDef: TaskDefinition) { + super(); + this.taskDefinition = taskDef; + } + + public toJson(mappingData: EntityMapping, ignoreKeys?: string[]): object { + return { + feedback_template: super.toJson(mappingData, ignoreKeys), + }; + } + + public save(): Observable { + const svc = AppInjector.get(FeedbackTemplateService); + + if (this.isNew) { + return svc.create( + { + taskDefId: this.taskDefinition.id, + }, + { + entity: this, + cache: this.taskDefinition.feedbackTemplateCache, + constructorParams: this.taskDefinition, + }, + ); + } else { + return svc.update( + { + taskDefId: this.taskDefinition.id, + id: this.id, + }, + {entity: this}, + ); + } + } + + private originalSaveData: string; + + public get hasOriginalSaveData(): boolean { + return this.originalSaveData !== undefined && this.originalSaveData !== null; + } + + public setOriginalSaveData(mapping: EntityMapping) { + this.originalSaveData = JSON.stringify(this.toJson(mapping)); + } + + public hasChanges(mapping: EntityMapping): boolean { + if (!this.originalSaveData) { + return false; + } + + return this.originalSaveData != JSON.stringify(this.toJson(mapping)); + } + + public get isNew(): boolean { + return !this.id; + } + + public get taskDefId(): number { + return this.taskDefinition.id; + } +} diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index b848686768..2e17ac6cda 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -1,9 +1,9 @@ import { HttpClient } from '@angular/common/http'; -import { Entity, EntityMapping } from 'ngx-entity-service'; +import { Entity, EntityCache, EntityMapping } from 'ngx-entity-service'; import { Observable, tap } from 'rxjs'; import { AppInjector } from 'src/app/app-injector'; import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; -import { Grade, GroupSet, TutorialStream, Unit } from './doubtfire-model'; +import { FeedbackTemplate, Grade, GroupSet, TutorialStream, Unit } from './doubtfire-model'; import { TaskDefinitionService } from '../services/task-definition.service'; export type UploadRequirement = { key: string; name: string; type: string; tiiCheck?: boolean; tiiPct?: number }; @@ -44,6 +44,9 @@ export class TaskDefinition extends Entity { assessmentEnabled: boolean; mossLanguage: string = 'moss c'; + public readonly feedbackTemplateCache: EntityCache = + new EntityCache(); + readonly unit: Unit; constructor(unit: Unit) { diff --git a/src/app/api/services/feedback-template.service.ts b/src/app/api/services/feedback-template.service.ts new file mode 100644 index 0000000000..4d0bef50de --- /dev/null +++ b/src/app/api/services/feedback-template.service.ts @@ -0,0 +1,28 @@ +import {Injectable} from '@angular/core'; +import {CachedEntityService} from 'ngx-entity-service'; +import {FeedbackTemplate} from '../models/feedback-template'; +import {HttpClient} from '@angular/common/http'; +import API_URL from 'src/app/config/constants/apiURL'; +import {TaskDefinition} from '../models/task-definition'; + +@Injectable() +export class FeedbackTemplateService extends CachedEntityService { + protected readonly endpointFormat = 'feedback_templates/'; + + constructor(httpClient: HttpClient) { + super(httpClient, API_URL); + + this.mapping.addKeys( + 'id', + 'learningOutcome', + 'chipText', + 'description', + 'commentText', + 'summaryText', + ); + } + + public override createInstanceFrom(json: object, other?: any): FeedbackTemplate { + return new FeedbackTemplate(other as TaskDefinition); + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 991ac397b4..fe50c5a40b 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -207,6 +207,7 @@ import {TaskDefinitionDatesComponent} from './units/states/edit/directives/unit- import {TaskDefinitionUploadComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component'; import {TaskDefinitionOptionsComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component'; import {TaskDefinitionResourcesComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component'; +import {TaskDefinitionFeedbackComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component'; import {TaskDefinitionOverseerComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component'; import {TaskDefinitionScormComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component'; import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-route.component'; @@ -237,6 +238,7 @@ import {TaskScormCardComponent} from './projects/states/dashboard/directives/tas import {TestAttemptService} from './api/services/test-attempt.service'; import {ScormExtensionCommentComponent} from './tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component'; import {ScormExtensionModalComponent} from './common/modals/scorm-extension-modal/scorm-extension-modal.component'; +import {FeedbackTemplateService} from './api/services/feedback-template.service'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -287,6 +289,7 @@ const MY_DATE_FORMAT = { TaskDefinitionUploadComponent, TaskDefinitionOptionsComponent, TaskDefinitionResourcesComponent, + TaskDefinitionFeedbackComponent, TaskDefinitionOverseerComponent, TaskDefinitionScormComponent, UnitAnalyticsComponent, @@ -435,6 +438,7 @@ const MY_DATE_FORMAT = { provideLottieOptions({ player: () => player, }), + FeedbackTemplateService, ], imports: [ FlexLayoutModule, diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html index 7d6224f343..e33ba9297f 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html @@ -133,6 +133,25 @@

7 +
+

Task feedback templates

+

+ Upload feedback templates for tutors +

+
+ +
+
+ + +
+
+
+ 8 +
+

SCORM test

@@ -149,7 +168,7 @@

SCORM test

- 8 + 9
diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.html new file mode 100644 index 0000000000..8cdecc7f46 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.html @@ -0,0 +1,127 @@ +
+
+ Enable feedback templates + +
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Learning Outcome + {{ feedbackTemplate.learningOutcome }} + Chip Text + {{ feedbackTemplate.chipText }} + Description + {{ feedbackTemplate.description }} + Comment Text + {{ feedbackTemplate.commentText }} + Summary Text + {{ feedbackTemplate.summaryText }} + + @if (feedbackTemplateHasChanges(feedbackTemplate)) { + + } + +
+ + + + + + + + + +
diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.scss b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.ts new file mode 100644 index 0000000000..7036148564 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.ts @@ -0,0 +1,163 @@ +import {AfterViewInit, Component, Inject, Input, ViewChild} from '@angular/core'; +import {MatTable, MatTableDataSource} from '@angular/material/table'; +import {MatPaginator} from '@angular/material/paginator'; +import {TaskDefinition, FeedbackTemplate, Unit} from 'src/app/api/models/doubtfire-model'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {MatSort, Sort} from '@angular/material/sort'; +import { + confirmationModal, + csvResultModalService, + csvUploadModalService, +} from 'src/app/ajs-upgraded-providers'; +import {Subscription} from 'rxjs'; +import {FeedbackTemplateService} from 'src/app/api/services/feedback-template.service'; + +@Component({ + selector: 'f-task-definition-feedback', + templateUrl: 'task-definition-feedback.component.html', + styleUrls: ['task-definition-feedback.component.scss'], +}) +export class TaskDefinitionFeedbackComponent implements AfterViewInit { + @ViewChild(MatTable, {static: false}) table: MatTable; + @ViewChild(MatSort, {static: false}) sort: MatSort; + @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; + + @Input() taskDefinition: TaskDefinition; + + public feedbackTemplateSource: MatTableDataSource; + public columns: string[] = [ + 'learningOutcome', + 'chipText', + 'description', + 'commentText', + 'summaryText', + 'feedbackTemplateAction', + ]; + public filter: string; + public selectedFeedbackTemplate: FeedbackTemplate; + + constructor( + private alerts: AlertService, + private taskDefinitionService: TaskDefinitionService, + private feedbackTemplateService: FeedbackTemplateService, + @Inject(csvResultModalService) private csvResultModalService: any, + @Inject(csvUploadModalService) private csvUploadModal: any, + @Inject(confirmationModal) private confirmationModal: any, + ) {} + + public get unit(): Unit { + return this.taskDefinition?.unit; + } + + ngAfterViewInit(): void { + this.subscriptions.push( + this.taskDefinition.feedbackTemplateCache.values.subscribe((feedbackTemplates) => { + this.feedbackTemplateSource = new MatTableDataSource(feedbackTemplates); + this.feedbackTemplateSource.paginator = this.paginator; + this.feedbackTemplateSource.sort = this.sort; + this.feedbackTemplateSource.filterPredicate = (data: any, filter: string) => + data.matches(filter); + }), + ); + } + + public saveFeedbackTemplate(feedbackTemplate: FeedbackTemplate) { + feedbackTemplate.save().subscribe(() => { + this.alerts.success('Template saved'); + feedbackTemplate.setOriginalSaveData(this.feedbackTemplateService.mapping); + }); + } + + private subscriptions: Subscription[] = []; + ngOnDestroy(): void { + this.subscriptions.forEach((s) => s.unsubscribe()); + } + + public selectFeedbackTemplate(feedbackTemplate: FeedbackTemplate) { + if (this.selectedFeedbackTemplate === feedbackTemplate) { + this.selectedFeedbackTemplate = null; + } else { + this.selectedFeedbackTemplate = feedbackTemplate; + + if (!this.selectedFeedbackTemplate.hasOriginalSaveData) { + this.selectedFeedbackTemplate.setOriginalSaveData(this.feedbackTemplateService.mapping); + } + } + } + + public sortData(sort: Sort) { + const data = this.feedbackTemplateSource.data; + + if (!sort.active || sort.direction === '') { + this.feedbackTemplateSource.data = data; + return; + } + + this.feedbackTemplateSource.data = data.sort((a, b) => { + const isAsc = sort.direction === 'asc'; + switch (sort.active) { + case 'learningOutcome': + return this.compare(a.learningOutcome, b.learningOutcome, isAsc); + case 'chipText': + return this.compare(a.chipText, b.chipText, isAsc); + case 'description': + return this.compare(a.description, b.description, isAsc); + case 'commentText': + return this.compare(a.commentText, b.commentText, isAsc); + case 'summaryText': + return this.compare(a.summaryText, b.summaryText, isAsc); + default: + return 0; + } + }); + } + + public compare(a: number | string, b: number | string, isAsc: boolean): number { + return (a < b ? -1 : 1) * (isAsc ? 1 : -1); + } + + applyFilter(filterValue: string) { + this.feedbackTemplateSource.filter = filterValue.trim().toLowerCase(); + + if (this.feedbackTemplateSource.paginator) { + this.feedbackTemplateSource.paginator.firstPage(); + } + } + + public feedbackTemplateHasChanges(feedbackTemplate: FeedbackTemplate): boolean { + return feedbackTemplate.hasChanges(this.feedbackTemplateService.mapping); + } + + public deleteFeedbackTemplate(feedbackTemplate: FeedbackTemplate) { + this.confirmationModal.show( + 'Delete feedback template', + 'Are you sure you want to delete this template? This action is final.', + () => { + this.alerts.success('Task deleted'); + }, + ); + } + + public uploadFeedbackTemplatesCsv() { + this.csvUploadModal.show( + 'Upload Feedback Templates as CSV', + 'Test message', + {file: {name: 'Feedback Template CSV Data', type: 'csv'}}, + this.unit.getTaskDefinitionBatchUploadUrl(), + (response: any) => {}, + ); + } + + public createFeedbackTemplate() { + const feedbackTemplate = new FeedbackTemplate(this.taskDefinition); + + feedbackTemplate.learningOutcome = 'TLO'; + feedbackTemplate.chipText = 'lorem'; + feedbackTemplate.description = 'Lorem ipsum dolor'; + feedbackTemplate.commentText = 'Lorem dolor'; + feedbackTemplate.summaryText = 'Lorem ipsum'; + + this.selectedFeedbackTemplate = feedbackTemplate; + } +} From c12536bc4375b1ae5f19d4e54d0783b6948921eb Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Wed, 20 Nov 2024 22:19:56 +1100 Subject: [PATCH 0222/1531] feat: combine outcome and template editor --- .../feedback-template-editor.component.html | 258 +++++++++++++++++ .../feedback-template-editor.component.ts | 270 ++++++++++++++++++ src/app/doubtfire-angular.module.ts | 4 +- .../task-definition-editor.component.html | 44 ++- .../task-definition-feedback.component.html | 127 -------- .../task-definition-feedback.component.scss | 0 .../task-definition-feedback.component.ts | 163 ----------- 7 files changed, 551 insertions(+), 315 deletions(-) create mode 100644 src/app/common/feedback-template/feedback-template-editor.component.html create mode 100644 src/app/common/feedback-template/feedback-template-editor.component.ts delete mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.html delete mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.scss delete mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.ts diff --git a/src/app/common/feedback-template/feedback-template-editor.component.html b/src/app/common/feedback-template/feedback-template-editor.component.html new file mode 100644 index 0000000000..6922dab4ed --- /dev/null +++ b/src/app/common/feedback-template/feedback-template-editor.component.html @@ -0,0 +1,258 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Number + {{ learningOutcome.iloNumber }} + Abbreviation + {{ learningOutcome.abbreviation }} + Name + {{ learningOutcome.name }} + Description + {{ learningOutcome.description }} + + @if (learningOutcomeHasChanges(learningOutcome)) { + + } + +
+ +
+ + + +
+ + + + + + + +
+ @if (selectedOutcome) { +
+ + Outcome Number + + + + + Abbreviation + + + + + Name + + +
+ + + Description + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Learning Outcome + {{ feedbackTemplate.learningOutcome }} + Chip Text + {{ feedbackTemplate.chipText }} + Description + {{ feedbackTemplate.description }} + Comment Text + {{ feedbackTemplate.commentText }} + Summary Text + {{ feedbackTemplate.summaryText }} + + @if (feedbackTemplateHasChanges(feedbackTemplate)) { + + } + +
+ +
+ + + +
+ + + + + + + +
+
+ } +
diff --git a/src/app/common/feedback-template/feedback-template-editor.component.ts b/src/app/common/feedback-template/feedback-template-editor.component.ts new file mode 100644 index 0000000000..b5a94b3e91 --- /dev/null +++ b/src/app/common/feedback-template/feedback-template-editor.component.ts @@ -0,0 +1,270 @@ +import {AfterViewInit, Component, Inject, Input, ViewChild} from '@angular/core'; +import {MatTable, MatTableDataSource} from '@angular/material/table'; +import {MatPaginator} from '@angular/material/paginator'; +import {TaskDefinition, Unit, LearningOutcome, LearningOutcomeService, FeedbackTemplate} from 'src/app/api/models/doubtfire-model'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {MatSort, Sort} from '@angular/material/sort'; +import { + confirmationModal, + csvResultModalService, + csvUploadModalService, +} from 'src/app/ajs-upgraded-providers'; +import {Subscription} from 'rxjs'; +import {FeedbackTemplateService} from 'src/app/api/services/feedback-template.service'; + +@Component({ + selector: 'f-feedback-template-editor', + templateUrl: 'feedback-template-editor.component.html', +}) +export class FeedbackTemplateEditorComponent implements AfterViewInit { + @Input() taskDefinition: TaskDefinition; + + @ViewChild(MatTable, {static: false}) outcomeTable: MatTable; + @ViewChild(MatSort, {static: false}) outcomeSort: MatSort; + @ViewChild(MatPaginator, {static: false}) outcomePaginator: MatPaginator; + + public outcomeSource: MatTableDataSource; + public outcomeColumns: string[] = [ + 'number', + 'abbreviation', + 'name', + 'description', + 'learningOutcomeAction', + ]; + public outcomeFilter: string; + public selectedOutcome: LearningOutcome; + + @ViewChild(MatTable, {static: false}) templateTable: MatTable; + @ViewChild(MatSort, {static: false}) templateSort: MatSort; + @ViewChild(MatPaginator, {static: false}) templatePaginator: MatPaginator; + + public templateSource: MatTableDataSource; + public templateColumns: string[] = [ + 'learningOutcome', + 'chipText', + 'description', + 'commentText', + 'summaryText', + 'feedbackTemplateAction', + ]; + public templateFilter: string; + public selectedTemplate: FeedbackTemplate; + + constructor( + private alerts: AlertService, + private taskDefinitionService: TaskDefinitionService, + private learningOutcomeService: LearningOutcomeService, + private feedbackTemplateService: FeedbackTemplateService, + @Inject(csvResultModalService) private csvResultModalService: any, + @Inject(csvUploadModalService) private csvUploadModal: any, + @Inject(confirmationModal) private confirmationModal: any, + ) {} + + public get unit(): Unit { + return this.taskDefinition?.unit; + } + + ngAfterViewInit(): void { + this.subscriptions.push( + this.unit.learningOutcomesCache.values.subscribe((learningOutcomes) => { + this.outcomeSource = new MatTableDataSource(learningOutcomes); + this.outcomeSource.paginator = this.outcomePaginator; + this.outcomeSource.sort = this.outcomeSort; + this.outcomeSource.filterPredicate = (data: any, filter: string) => data.matches(filter); + }), + this.taskDefinition.feedbackTemplateCache.values.subscribe((feedbackTemplates) => { + this.templateSource = new MatTableDataSource(feedbackTemplates); + this.templateSource.paginator = this.templatePaginator; + this.templateSource.sort = this.templateSort; + this.templateSource.filterPredicate = (data: any, filter: string) => data.matches(filter); + }), + ); + } + + public saveLearningOutcome(learningOutcome: LearningOutcome) { + // learningOutcome.save().subscribe(() => { + // this.alerts.success('Outcome saved'); + // learningOutcome.setOriginalSaveData(this.learningOutcomeService.mapping); + // }); + } + + public saveFeedbackTemplate(feedbackTemplate: FeedbackTemplate) { + feedbackTemplate.save().subscribe(() => { + this.alerts.success('Template saved'); + feedbackTemplate.setOriginalSaveData(this.feedbackTemplateService.mapping); + }); + } + + private subscriptions: Subscription[] = []; + ngOnDestroy(): void { + this.subscriptions.forEach((s) => s.unsubscribe()); + } + + public selectLearningOutcome(learningOutcome: LearningOutcome) { + if (this.selectedOutcome === learningOutcome) { + this.selectedOutcome = null; + } else { + this.selectedOutcome = learningOutcome; + + // if (!this.selectedFeedbackTemplate.hasOriginalSaveData) { + // this.selectedFeedbackTemplate.setOriginalSaveData(this.feedbackTemplateService.mapping); + // } + } + } + + public selectFeedbackTemplate(feedbackTemplate: FeedbackTemplate) { + if (this.selectedTemplate === feedbackTemplate) { + this.selectedTemplate = null; + } else { + this.selectedTemplate = feedbackTemplate; + + if (!this.selectedTemplate.hasOriginalSaveData) { + this.selectedTemplate.setOriginalSaveData(this.feedbackTemplateService.mapping); + } + } + } + + public sortOutcomeData(sort: Sort) { + const data = this.outcomeSource.data; + + if (!sort.active || sort.direction === '') { + this.outcomeSource.data = data; + return; + } + + this.outcomeSource.data = data.sort((a, b) => { + const isAsc = sort.direction === 'asc'; + switch (sort.active) { + case 'number': + return this.compare(a.iloNumber, b.iloNumber, isAsc); + case 'abbreviation': + return this.compare(a.abbreviation, b.abbreviation, isAsc); + case 'name': + return this.compare(a.name, b.name, isAsc); + case 'description': + return this.compare(a.description, b.description, isAsc); + default: + return 0; + } + }); + } + + public sortTemplateData(sort: Sort) { + const data = this.templateSource.data; + + if (!sort.active || sort.direction === '') { + this.templateSource.data = data; + return; + } + + this.templateSource.data = data.sort((a, b) => { + const isAsc = sort.direction === 'asc'; + switch (sort.active) { + case 'learningOutcome': + return this.compare(a.learningOutcome, b.learningOutcome, isAsc); + case 'chipText': + return this.compare(a.chipText, b.chipText, isAsc); + case 'description': + return this.compare(a.description, b.description, isAsc); + case 'commentText': + return this.compare(a.commentText, b.commentText, isAsc); + case 'summaryText': + return this.compare(a.summaryText, b.summaryText, isAsc); + default: + return 0; + } + }); + } + + public compare(a: number | string, b: number | string, isAsc: boolean): number { + return (a < b ? -1 : 1) * (isAsc ? 1 : -1); + } + + applyOutcomeFilter(filterValue: string) { + this.outcomeSource.filter = filterValue.trim().toLowerCase(); + + if (this.outcomeSource.paginator) { + this.outcomeSource.paginator.firstPage(); + } + } + + applyTemplateFilter(filterValue: string) { + this.templateSource.filter = filterValue.trim().toLowerCase(); + + if (this.templateSource.paginator) { + this.templateSource.paginator.firstPage(); + } + } + + public learningOutcomeHasChanges(learningOutcome: LearningOutcome): boolean { + return learningOutcome.hasChanges(this.learningOutcomeService.mapping); + } + + public feedbackTemplateHasChanges(feedbackTemplate: FeedbackTemplate): boolean { + return feedbackTemplate.hasChanges(this.feedbackTemplateService.mapping); + } + + public deleteLearningOutcome(learningOutcome: LearningOutcome) { + this.confirmationModal.show( + 'Delete learning outcome', + 'Are you sure you want to delete this outcome? This action is final.', + () => { + this.alerts.success('Outcome deleted'); + }, + ); + } + + public deleteFeedbackTemplate(feedbackTemplate: FeedbackTemplate) { + this.confirmationModal.show( + 'Delete feedback template', + 'Are you sure you want to delete this template? This action is final.', + () => { + this.alerts.success('Template deleted'); + }, + ); + } + + public uploadLearningOutcomesCsv() { + this.csvUploadModal.show( + 'Upload Learning Outcomes as CSV', + 'Test message', + {file: {name: 'Learning Outcome CSV Data', type: 'csv'}}, + this.unit.getTaskDefinitionBatchUploadUrl(), + (response: any) => {}, + ); + } + + public uploadFeedbackTemplatesCsv() { + this.csvUploadModal.show( + 'Upload Feedback Templates as CSV', + 'Test message', + {file: {name: 'Feedback Template CSV Data', type: 'csv'}}, + this.unit.getTaskDefinitionBatchUploadUrl(), + (response: any) => {}, + ); + } + + public createLearningOutcome() { + const learningOutcome = new LearningOutcome(); + + learningOutcome.iloNumber = 1; + learningOutcome.abbreviation = 'lm'; + learningOutcome.name = 'lorem'; + learningOutcome.description = 'Lorem ipsum dolor'; + + this.selectedOutcome = learningOutcome; + } + + public createFeedbackTemplate() { + const feedbackTemplate = new FeedbackTemplate(this.taskDefinition); + + feedbackTemplate.learningOutcome = 'TLO'; + feedbackTemplate.chipText = 'lorem'; + feedbackTemplate.description = 'Lorem ipsum dolor'; + feedbackTemplate.commentText = 'Lorem dolor'; + feedbackTemplate.summaryText = 'Lorem ipsum'; + + this.selectedTemplate = feedbackTemplate; + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index fe50c5a40b..07961095af 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -207,7 +207,6 @@ import {TaskDefinitionDatesComponent} from './units/states/edit/directives/unit- import {TaskDefinitionUploadComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component'; import {TaskDefinitionOptionsComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component'; import {TaskDefinitionResourcesComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component'; -import {TaskDefinitionFeedbackComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component'; import {TaskDefinitionOverseerComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component'; import {TaskDefinitionScormComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component'; import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-route.component'; @@ -239,6 +238,7 @@ import {TestAttemptService} from './api/services/test-attempt.service'; import {ScormExtensionCommentComponent} from './tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component'; import {ScormExtensionModalComponent} from './common/modals/scorm-extension-modal/scorm-extension-modal.component'; import {FeedbackTemplateService} from './api/services/feedback-template.service'; +import {FeedbackTemplateEditorComponent} from './common/feedback-template/feedback-template-editor.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -289,7 +289,6 @@ const MY_DATE_FORMAT = { TaskDefinitionUploadComponent, TaskDefinitionOptionsComponent, TaskDefinitionResourcesComponent, - TaskDefinitionFeedbackComponent, TaskDefinitionOverseerComponent, TaskDefinitionScormComponent, UnitAnalyticsComponent, @@ -360,6 +359,7 @@ const MY_DATE_FORMAT = { TaskScormCardComponent, ScormExtensionCommentComponent, ScormExtensionModalComponent, + FeedbackTemplateEditorComponent, ], // Services we provide providers: [ diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html index e33ba9297f..c56b29c055 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html @@ -30,6 +30,23 @@

Task details

+
+

Task Learning Outcomes

+

Add learning outcomes for this task

+
+ +
+
+ + +
+
+
+ 3 +
+

Inbox

@@ -47,7 +64,7 @@

Inbox

- 3 + 4
@@ -65,7 +82,7 @@

Due dates

- 4 + 5
@@ -83,7 +100,7 @@

Upload requirem
- 5 + 6
@@ -105,7 +122,7 @@

- 6 + 7
@@ -125,25 +142,6 @@

-
-
-
- 7 -
-
-
-

Task feedback templates

-

- Upload feedback templates for tutors -

-
- -
-
-
-
-
- Enable feedback templates - -
- - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Learning Outcome - {{ feedbackTemplate.learningOutcome }} - Chip Text - {{ feedbackTemplate.chipText }} - Description - {{ feedbackTemplate.description }} - Comment Text - {{ feedbackTemplate.commentText }} - Summary Text - {{ feedbackTemplate.summaryText }} - - @if (feedbackTemplateHasChanges(feedbackTemplate)) { - - } - -
- - - - - - - - - -
diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.scss b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.ts deleted file mode 100644 index 7036148564..0000000000 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-feedback/task-definition-feedback.component.ts +++ /dev/null @@ -1,163 +0,0 @@ -import {AfterViewInit, Component, Inject, Input, ViewChild} from '@angular/core'; -import {MatTable, MatTableDataSource} from '@angular/material/table'; -import {MatPaginator} from '@angular/material/paginator'; -import {TaskDefinition, FeedbackTemplate, Unit} from 'src/app/api/models/doubtfire-model'; -import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; -import {AlertService} from 'src/app/common/services/alert.service'; -import {MatSort, Sort} from '@angular/material/sort'; -import { - confirmationModal, - csvResultModalService, - csvUploadModalService, -} from 'src/app/ajs-upgraded-providers'; -import {Subscription} from 'rxjs'; -import {FeedbackTemplateService} from 'src/app/api/services/feedback-template.service'; - -@Component({ - selector: 'f-task-definition-feedback', - templateUrl: 'task-definition-feedback.component.html', - styleUrls: ['task-definition-feedback.component.scss'], -}) -export class TaskDefinitionFeedbackComponent implements AfterViewInit { - @ViewChild(MatTable, {static: false}) table: MatTable; - @ViewChild(MatSort, {static: false}) sort: MatSort; - @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; - - @Input() taskDefinition: TaskDefinition; - - public feedbackTemplateSource: MatTableDataSource; - public columns: string[] = [ - 'learningOutcome', - 'chipText', - 'description', - 'commentText', - 'summaryText', - 'feedbackTemplateAction', - ]; - public filter: string; - public selectedFeedbackTemplate: FeedbackTemplate; - - constructor( - private alerts: AlertService, - private taskDefinitionService: TaskDefinitionService, - private feedbackTemplateService: FeedbackTemplateService, - @Inject(csvResultModalService) private csvResultModalService: any, - @Inject(csvUploadModalService) private csvUploadModal: any, - @Inject(confirmationModal) private confirmationModal: any, - ) {} - - public get unit(): Unit { - return this.taskDefinition?.unit; - } - - ngAfterViewInit(): void { - this.subscriptions.push( - this.taskDefinition.feedbackTemplateCache.values.subscribe((feedbackTemplates) => { - this.feedbackTemplateSource = new MatTableDataSource(feedbackTemplates); - this.feedbackTemplateSource.paginator = this.paginator; - this.feedbackTemplateSource.sort = this.sort; - this.feedbackTemplateSource.filterPredicate = (data: any, filter: string) => - data.matches(filter); - }), - ); - } - - public saveFeedbackTemplate(feedbackTemplate: FeedbackTemplate) { - feedbackTemplate.save().subscribe(() => { - this.alerts.success('Template saved'); - feedbackTemplate.setOriginalSaveData(this.feedbackTemplateService.mapping); - }); - } - - private subscriptions: Subscription[] = []; - ngOnDestroy(): void { - this.subscriptions.forEach((s) => s.unsubscribe()); - } - - public selectFeedbackTemplate(feedbackTemplate: FeedbackTemplate) { - if (this.selectedFeedbackTemplate === feedbackTemplate) { - this.selectedFeedbackTemplate = null; - } else { - this.selectedFeedbackTemplate = feedbackTemplate; - - if (!this.selectedFeedbackTemplate.hasOriginalSaveData) { - this.selectedFeedbackTemplate.setOriginalSaveData(this.feedbackTemplateService.mapping); - } - } - } - - public sortData(sort: Sort) { - const data = this.feedbackTemplateSource.data; - - if (!sort.active || sort.direction === '') { - this.feedbackTemplateSource.data = data; - return; - } - - this.feedbackTemplateSource.data = data.sort((a, b) => { - const isAsc = sort.direction === 'asc'; - switch (sort.active) { - case 'learningOutcome': - return this.compare(a.learningOutcome, b.learningOutcome, isAsc); - case 'chipText': - return this.compare(a.chipText, b.chipText, isAsc); - case 'description': - return this.compare(a.description, b.description, isAsc); - case 'commentText': - return this.compare(a.commentText, b.commentText, isAsc); - case 'summaryText': - return this.compare(a.summaryText, b.summaryText, isAsc); - default: - return 0; - } - }); - } - - public compare(a: number | string, b: number | string, isAsc: boolean): number { - return (a < b ? -1 : 1) * (isAsc ? 1 : -1); - } - - applyFilter(filterValue: string) { - this.feedbackTemplateSource.filter = filterValue.trim().toLowerCase(); - - if (this.feedbackTemplateSource.paginator) { - this.feedbackTemplateSource.paginator.firstPage(); - } - } - - public feedbackTemplateHasChanges(feedbackTemplate: FeedbackTemplate): boolean { - return feedbackTemplate.hasChanges(this.feedbackTemplateService.mapping); - } - - public deleteFeedbackTemplate(feedbackTemplate: FeedbackTemplate) { - this.confirmationModal.show( - 'Delete feedback template', - 'Are you sure you want to delete this template? This action is final.', - () => { - this.alerts.success('Task deleted'); - }, - ); - } - - public uploadFeedbackTemplatesCsv() { - this.csvUploadModal.show( - 'Upload Feedback Templates as CSV', - 'Test message', - {file: {name: 'Feedback Template CSV Data', type: 'csv'}}, - this.unit.getTaskDefinitionBatchUploadUrl(), - (response: any) => {}, - ); - } - - public createFeedbackTemplate() { - const feedbackTemplate = new FeedbackTemplate(this.taskDefinition); - - feedbackTemplate.learningOutcome = 'TLO'; - feedbackTemplate.chipText = 'lorem'; - feedbackTemplate.description = 'Lorem ipsum dolor'; - feedbackTemplate.commentText = 'Lorem dolor'; - feedbackTemplate.summaryText = 'Lorem ipsum'; - - this.selectedFeedbackTemplate = feedbackTemplate; - } -} From db2d2bc32b19165bac8ff6ba0282a16adffbb815 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Fri, 22 Nov 2024 19:04:02 +1100 Subject: [PATCH 0223/1531] feat: add field to connect outcomes --- .../feedback-template-editor.component.html | 48 +++++++++-- .../feedback-template-editor.component.ts | 81 +++++++++++++++++-- 2 files changed, 114 insertions(+), 15 deletions(-) diff --git a/src/app/common/feedback-template/feedback-template-editor.component.html b/src/app/common/feedback-template/feedback-template-editor.component.html index 6922dab4ed..51af89539a 100644 --- a/src/app/common/feedback-template/feedback-template-editor.component.html +++ b/src/app/common/feedback-template/feedback-template-editor.component.html @@ -16,8 +16,8 @@ {{ learningOutcome.iloNumber }} - - Abbreviation + + Tag + + Connected Learning Outcomes + + @for (outcome of connectedOutcomes(); track $index) { + + {{ outcome }} + + + } + + + + @for (outcome of filteredOutcomes(); track outcome) { + {{ outcome }} + } + + +
- - + + @@ -241,7 +270,10 @@ /> - + - + } diff --git a/src/app/common/feedback-template/feedback-template-editor.component.ts b/src/app/common/feedback-template/feedback-template-editor.component.ts index b5a94b3e91..fa8a82df27 100644 --- a/src/app/common/feedback-template/feedback-template-editor.component.ts +++ b/src/app/common/feedback-template/feedback-template-editor.component.ts @@ -1,7 +1,23 @@ -import {AfterViewInit, Component, Inject, Input, ViewChild} from '@angular/core'; +import { + AfterViewInit, + Component, + computed, + inject, + Inject, + Input, + model, + signal, + ViewChild, +} from '@angular/core'; import {MatTable, MatTableDataSource} from '@angular/material/table'; import {MatPaginator} from '@angular/material/paginator'; -import {TaskDefinition, Unit, LearningOutcome, LearningOutcomeService, FeedbackTemplate} from 'src/app/api/models/doubtfire-model'; +import { + TaskDefinition, + Unit, + LearningOutcome, + LearningOutcomeService, + FeedbackTemplate, +} from 'src/app/api/models/doubtfire-model'; import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {MatSort, Sort} from '@angular/material/sort'; @@ -12,6 +28,10 @@ import { } from 'src/app/ajs-upgraded-providers'; import {Subscription} from 'rxjs'; import {FeedbackTemplateService} from 'src/app/api/services/feedback-template.service'; +import {COMMA, ENTER} from '@angular/cdk/keycodes'; +import {LiveAnnouncer} from '@angular/cdk/a11y'; +import {MatChipInputEvent} from '@angular/material/chips'; +import {MatAutocompleteSelectedEvent} from '@angular/material/autocomplete'; @Component({ selector: 'f-feedback-template-editor', @@ -27,7 +47,7 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { public outcomeSource: MatTableDataSource; public outcomeColumns: string[] = [ 'number', - 'abbreviation', + 'tag', 'name', 'description', 'learningOutcomeAction', @@ -41,7 +61,7 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { public templateSource: MatTableDataSource; public templateColumns: string[] = [ - 'learningOutcome', + 'number', 'chipText', 'description', 'commentText', @@ -138,7 +158,7 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { switch (sort.active) { case 'number': return this.compare(a.iloNumber, b.iloNumber, isAsc); - case 'abbreviation': + case 'tag': return this.compare(a.abbreviation, b.abbreviation, isAsc); case 'name': return this.compare(a.name, b.name, isAsc); @@ -161,8 +181,8 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { this.templateSource.data = data.sort((a, b) => { const isAsc = sort.direction === 'asc'; switch (sort.active) { - case 'learningOutcome': - return this.compare(a.learningOutcome, b.learningOutcome, isAsc); + case 'number': + return this.compare(a.id, b.id, isAsc); case 'chipText': return this.compare(a.chipText, b.chipText, isAsc); case 'description': @@ -259,7 +279,7 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { public createFeedbackTemplate() { const feedbackTemplate = new FeedbackTemplate(this.taskDefinition); - feedbackTemplate.learningOutcome = 'TLO'; + feedbackTemplate.id = 0; feedbackTemplate.chipText = 'lorem'; feedbackTemplate.description = 'Lorem ipsum dolor'; feedbackTemplate.commentText = 'Lorem dolor'; @@ -267,4 +287,49 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { this.selectedTemplate = feedbackTemplate; } + + readonly separatorKeysCodes: number[] = [ENTER, COMMA]; + readonly currentConnectedOutcome = model(''); + readonly connectedOutcomes = signal([]); + readonly allOutcomes: string[] = ['TLO1', 'TLO2', 'TLO3', 'ULO1', 'ULO2']; + readonly filteredOutcomes = computed(() => { + const currentOutcome = this.currentConnectedOutcome().toLowerCase(); + return currentOutcome + ? this.allOutcomes.filter((outcome) => outcome.toLowerCase().includes(currentOutcome)) + : this.allOutcomes.slice(); + }); + + readonly announcer = inject(LiveAnnouncer); + + add(event: MatChipInputEvent): void { + const value = (event.value || '').trim(); + + if (value) { + this.connectedOutcomes.update((connectedOutcomes) => [...connectedOutcomes, value]); + } + + this.currentConnectedOutcome.set(''); + } + + remove(outcome: string): void { + this.connectedOutcomes.update((connectedOutcomes) => { + const index = connectedOutcomes.indexOf(outcome); + if (index < 0) { + return connectedOutcomes; + } + + connectedOutcomes.splice(index, 1); + this.announcer.announce(`Removed ${outcome}`); + return [...connectedOutcomes]; + }); + } + + selected(event: MatAutocompleteSelectedEvent): void { + this.connectedOutcomes.update((connectedOutcomes) => [ + ...connectedOutcomes, + event.option.viewValue, + ]); + this.currentConnectedOutcome.set(''); + event.option.deselect(); + } } From 9acc36502dc3fd2365817f73ccc742dd3947e293 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Fri, 22 Nov 2024 19:05:33 +1100 Subject: [PATCH 0224/1531] feat: add feedback template picker to comment composer --- src/app/doubtfire-angular.module.ts | 2 + .../task-comment-composer.component.html | 16 +++ .../task-comment-composer.component.scss | 7 ++ .../task-comment-composer.component.ts | 2 + .../task-feedback-templates.component.html | 103 ++++++++++++++++++ .../task-feedback-templates.component.ts | 58 ++++++++++ 6 files changed, 188 insertions(+) create mode 100644 src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.html create mode 100644 src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 07961095af..21b56cc9e8 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -239,6 +239,7 @@ import {ScormExtensionCommentComponent} from './tasks/task-comments-viewer/scorm import {ScormExtensionModalComponent} from './common/modals/scorm-extension-modal/scorm-extension-modal.component'; import {FeedbackTemplateService} from './api/services/feedback-template.service'; import {FeedbackTemplateEditorComponent} from './common/feedback-template/feedback-template-editor.component'; +import {TaskFeedbackTemplatesComponent} from './tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -360,6 +361,7 @@ const MY_DATE_FORMAT = { ScormExtensionCommentComponent, ScormExtensionModalComponent, FeedbackTemplateEditorComponent, + TaskFeedbackTemplatesComponent, ], // Services we provide providers: [ diff --git a/src/app/tasks/task-comment-composer/task-comment-composer.component.html b/src/app/tasks/task-comment-composer/task-comment-composer.component.html index 448f88f46c..db1cc099ee 100644 --- a/src/app/tasks/task-comment-composer/task-comment-composer.component.html +++ b/src/app/tasks/task-comment-composer/task-comment-composer.component.html @@ -1,3 +1,8 @@ + + +
+ + task +
diff --git a/src/app/tasks/task-comment-composer/task-comment-composer.component.scss b/src/app/tasks/task-comment-composer/task-comment-composer.component.scss index a79e6a5be4..d17c924344 100644 --- a/src/app/tasks/task-comment-composer/task-comment-composer.component.scss +++ b/src/app/tasks/task-comment-composer/task-comment-composer.component.scss @@ -95,6 +95,13 @@ $emoji-color: lighten( border-color: darken($color: white, $amount: 10); } +.feedback-template-picker { + z-index: 1060; + position: absolute; + right: 26px; + bottom: 150px; +} + #replyContainer { margin: 0.4em 1em -0.2em 1em; font-size: 14px; diff --git a/src/app/tasks/task-comment-composer/task-comment-composer.component.ts b/src/app/tasks/task-comment-composer/task-comment-composer.component.ts index 9a4a3297ea..ca4319969d 100644 --- a/src/app/tasks/task-comment-composer/task-comment-composer.component.ts +++ b/src/app/tasks/task-comment-composer/task-comment-composer.component.ts @@ -82,6 +82,7 @@ export class TaskCommentComposerComponent implements DoCheck { emojiRegex: RegExp = /(?:\:)(.*?)(?=\:|$)/; emojiSearchResults: EmojiData[] = []; emojiMatch: string; + showFeedbackTemplatePicker: boolean = false; recording = false; cagStartWidth: number; @@ -155,6 +156,7 @@ export class TaskCommentComposerComponent implements DoCheck { e.preventDefault(); this.emojiSearchMode = false; this.showEmojiPicker = false; + this.showFeedbackTemplatePicker = false; if (this.input.first.nativeElement.innerText.trim() !== '') { this.addComment(); } diff --git a/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.html b/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.html new file mode 100644 index 0000000000..f92a30ec03 --- /dev/null +++ b/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.html @@ -0,0 +1,103 @@ + diff --git a/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts b/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts new file mode 100644 index 0000000000..6a2ea98608 --- /dev/null +++ b/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts @@ -0,0 +1,58 @@ +import {Component, ElementRef, ViewChild} from '@angular/core'; + +@Component({ + selector: 'f-task-feedback-templates', + templateUrl: './task-feedback-templates.component.html', +}) +export class TaskFeedbackTemplatesComponent { + searchTerm: string = ''; + hoveredTemplate: string = ''; + + categories = [ + {name: 'TLO', templates: ['Template A1', 'Template A2', 'Template A3', 'Template A4']}, + {name: 'ULO', templates: ['Template B1', 'Template B2', 'Template B3', 'Template B4']}, + {name: 'CLO', templates: ['Template C1', 'Template C2', 'Template C3', 'Template C4']}, + {name: 'GLO', templates: ['Template D1', 'Template D2', 'Template D3', 'Template D4']}, + {name: 'Section', templates: ['Template E1', 'Template E2', 'Template E3', 'Template E4']}, + ]; + + filteredCategories = [...this.categories]; + + filterTemplates() { + this.filteredCategories = this.categories.map((category) => ({ + ...category, + templates: category.templates.filter((template) => + template.toLowerCase().includes(this.searchTerm.toLowerCase()), + ), + })); + } + + @ViewChild('tloSection') tloSection!: ElementRef; + @ViewChild('uloSection') uloSection!: ElementRef; + @ViewChild('cloSection') cloSection!: ElementRef; + @ViewChild('gloSection') gloSection!: ElementRef; + @ViewChild('sectionSection') sectionSection!: ElementRef; + + scrollToSection(event: any) { + const sections = [ + this.tloSection, + this.uloSection, + this.cloSection, + this.gloSection, + this.sectionSection, + ]; + const selectedSection = sections[event.index]; + + if (selectedSection) { + selectedSection.nativeElement.scrollIntoView({behavior: 'smooth', block: 'start'}); + } + } + + selectTemplate(template: string) { + console.log('Selected template:', template); + } + + onHoverTemplate(template: string) { + this.hoveredTemplate = template; + } +} From e3fdd3b0fafe1988e1f19346b11b18a5b4274072 Mon Sep 17 00:00:00 2001 From: ShounakB <65479699+Shounaks@users.noreply.github.com> Date: Sat, 23 Nov 2024 00:46:19 +1100 Subject: [PATCH 0225/1531] Fixing updateGrade Method --- src/app/common/grade-icon/grade-icon.component.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/app/common/grade-icon/grade-icon.component.ts b/src/app/common/grade-icon/grade-icon.component.ts index d90bc6298c..5f8f31c7bc 100644 --- a/src/app/common/grade-icon/grade-icon.component.ts +++ b/src/app/common/grade-icon/grade-icon.component.ts @@ -11,7 +11,7 @@ export class GradeIconComponent implements OnInit, OnChanges { @Input() grade?: number | string; @Input() colorful: boolean = false; - gradeText: number | string = 'Grade'; + gradeText: string = 'Grade'; gradeLetter: string = 'G'; constructor(private gradeService: GradeService) {} @@ -27,10 +27,9 @@ export class GradeIconComponent implements OnInit, OnChanges { } private updateGrade(): void { - this.gradeText = - typeof this.grade === 'string' - ? this.gradeService.stringToGrade(this.grade) - : this.gradeService.grades[this.grade] || 'Grade'; - this.gradeLetter = this.gradeService.gradeAcronyms[this.grade] || 'G'; + const grade: number = + typeof this.grade === 'string' ? this.gradeService.stringToGrade(this.grade) : this.grade; + this.gradeText = this.gradeService.grades[grade] || 'Grade'; + this.gradeLetter = this.gradeService.gradeAcronyms[grade] || 'G'; } } From a42f177f61b3f7166edf3b9c93dfd2dcd3949df7 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 26 Nov 2024 01:21:41 +1100 Subject: [PATCH 0226/1531] feat: make template editor reusable across contexts --- src/app/api/models/feedback-template.ts | 20 +- src/app/api/models/task-definition.ts | 27 +- src/app/api/models/unit.ts | 7 + .../api/services/feedback-template.service.ts | 9 +- .../api/services/task-definition.service.ts | 35 +- src/app/api/services/unit.service.ts | 16 +- .../feedback-template-editor.component.html | 384 ++++++++++-------- .../feedback-template-editor.component.ts | 123 ++++-- src/app/doubtfire-angularjs.module.ts | 5 + .../task-definition-editor.component.html | 2 +- src/app/units/states/edit/edit.tpl.html | 2 +- 11 files changed, 395 insertions(+), 235 deletions(-) diff --git a/src/app/api/models/feedback-template.ts b/src/app/api/models/feedback-template.ts index 85da6af509..f0679a611f 100644 --- a/src/app/api/models/feedback-template.ts +++ b/src/app/api/models/feedback-template.ts @@ -1,7 +1,7 @@ import {Entity, EntityMapping} from 'ngx-entity-service'; import {Observable} from 'rxjs'; import {AppInjector} from 'src/app/app-injector'; -import {TaskDefinition} from './task-definition'; +import {TaskDefinition, Unit} from './doubtfire-model'; import {FeedbackTemplateService} from '../services/feedback-template.service'; export class FeedbackTemplate extends Entity { @@ -12,11 +12,11 @@ export class FeedbackTemplate extends Entity { commentText: string; summaryText: string; - readonly taskDefinition: TaskDefinition; + readonly context: TaskDefinition | Unit; - constructor(taskDef: TaskDefinition) { + constructor(context: TaskDefinition | Unit) { super(); - this.taskDefinition = taskDef; + this.context = context; } public toJson(mappingData: EntityMapping, ignoreKeys?: string[]): object { @@ -31,18 +31,18 @@ export class FeedbackTemplate extends Entity { if (this.isNew) { return svc.create( { - taskDefId: this.taskDefinition.id, + contextId: this.context.id, }, { entity: this, - cache: this.taskDefinition.feedbackTemplateCache, - constructorParams: this.taskDefinition, + cache: this.context.feedbackTemplateCache, + constructorParams: this.context, }, ); } else { return svc.update( { - taskDefId: this.taskDefinition.id, + contextId: this.context.id, id: this.id, }, {entity: this}, @@ -72,7 +72,7 @@ export class FeedbackTemplate extends Entity { return !this.id; } - public get taskDefId(): number { - return this.taskDefinition.id; + public getContextId(): number { + return this.context.id; } } diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index 2e17ac6cda..a2e9b85e73 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -3,8 +3,9 @@ import { Entity, EntityCache, EntityMapping } from 'ngx-entity-service'; import { Observable, tap } from 'rxjs'; import { AppInjector } from 'src/app/app-injector'; import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; -import { FeedbackTemplate, Grade, GroupSet, TutorialStream, Unit } from './doubtfire-model'; +import { FeedbackTemplate, Grade, GroupSet, LearningOutcome, TutorialStream, Unit } from './doubtfire-model'; import { TaskDefinitionService } from '../services/task-definition.service'; +import { AlertService } from 'src/app/common/services/alert.service'; export type UploadRequirement = { key: string; name: string; type: string; tiiCheck?: boolean; tiiPct?: number }; @@ -44,6 +45,8 @@ export class TaskDefinition extends Entity { assessmentEnabled: boolean; mossLanguage: string = 'moss c'; + public readonly learningOutcomesCache: EntityCache = + new EntityCache(); public readonly feedbackTemplateCache: EntityCache = new EntityCache(); @@ -114,6 +117,18 @@ export class TaskDefinition extends Entity { return this.originalSaveData != JSON.stringify(this.toJson(mapping)); } + public refresh(): void { + const alerts = AppInjector.get(AlertService); + AppInjector.get(TaskDefinitionService) + .fetch(this.id) + .subscribe({ + next: (taskDefinition) => { + console.log(taskDefinition.name); + }, + error: (message) => alerts.error(message, 6000), + }); + } + public get isNew(): boolean { return !this.id; } @@ -168,6 +183,16 @@ export class TaskDefinition extends Entity { }`; } + public getOutcomeBatchUploadUrl(): string { + const constants = AppInjector.get(DoubtfireConstants); + return `${constants.API_URL}/units/${this.unit.id}/task_definitions/${this.id}/outcomes/csv`; + } + + public getFeedbackTemplateBatchUploadUrl(): string { + const constants = AppInjector.get(DoubtfireConstants); + return `${constants.API_URL}/units/${this.unit.id}/task_definitions/${this.id}/feedback_templates/csv`; + } + /** * Open the SCORM test in a new tab - using preview mode. */ diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index b27159832e..a57f3c7db3 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -22,6 +22,7 @@ import { Project, TutorialStreamService, UnitRoleService, + FeedbackTemplate, } from './doubtfire-model'; import {LearningOutcome} from './learning-outcome'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -73,6 +74,8 @@ export class Unit extends Entity { new EntityCache(); public readonly taskOutcomeAlignmentsCache: EntityCache = new EntityCache(); + public readonly feedbackTemplateCache: EntityCache = + new EntityCache(); readonly staffCache: EntityCache = new EntityCache(); @@ -388,6 +391,10 @@ export class Unit extends Entity { return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.id}/outcomes/csv`; } + public getFeedbackTemplateBatchUploadUrl(): string { + return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.id}/feedback_templates/csv`; + } + public hasStreams(): boolean { return this.tutorialStreamsCache.size > 1; } diff --git a/src/app/api/services/feedback-template.service.ts b/src/app/api/services/feedback-template.service.ts index 4d0bef50de..0c10e6debc 100644 --- a/src/app/api/services/feedback-template.service.ts +++ b/src/app/api/services/feedback-template.service.ts @@ -3,7 +3,7 @@ import {CachedEntityService} from 'ngx-entity-service'; import {FeedbackTemplate} from '../models/feedback-template'; import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiURL'; -import {TaskDefinition} from '../models/task-definition'; +import {TaskDefinition, Unit} from '../models/doubtfire-model'; @Injectable() export class FeedbackTemplateService extends CachedEntityService { @@ -22,7 +22,10 @@ export class FeedbackTemplateService extends CachedEntityService { protected readonly endpointFormat = 'units/:unitId:/task_definitions/:id:'; - constructor(httpClient: HttpClient) { + constructor( + httpClient: HttpClient, + private learningOutcomeService: LearningOutcomeService, + private feedbackTemplateService: FeedbackTemplateService, + ) { super(httpClient, API_URL); this.mapping.addKeys( @@ -108,7 +113,31 @@ export class TaskDefinitionService extends CachedEntityService { 'isGraded', 'maxQualityPts', 'overseerImageId', - 'assessmentEnabled' + 'assessmentEnabled', + { + keys: 'tlos', + toEntityOp: (data: object, key: string, taskDefinition: TaskDefinition) => { + data[key]?.forEach((tlo) => { + taskDefinition.learningOutcomesCache.getOrCreate( + tlo['id'], + this.learningOutcomeService, + tlo, + ); + }); + }, + }, + { + keys: 'feedbackTemplates', + toEntityOp: (data: object, key: string, taskDefinition: TaskDefinition) => { + data[key]?.forEach((template) => { + taskDefinition.feedbackTemplateCache.getOrCreate( + template['id'], + this.feedbackTemplateService, + template, + ); + }); + }, + }, ); this.mapping.mapAllKeysToJsonExcept( diff --git a/src/app/api/services/unit.service.ts b/src/app/api/services/unit.service.ts index c3c38c7406..cd4eee6abb 100644 --- a/src/app/api/services/unit.service.ts +++ b/src/app/api/services/unit.service.ts @@ -9,6 +9,7 @@ import { TaskDefinitionService } from './task-definition.service'; import { GroupService } from './group.service'; import { Observable } from 'rxjs'; import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; +import { FeedbackTemplateService } from './feedback-template.service'; export type IloStats = { median: number; @@ -32,7 +33,8 @@ export class UnitService extends CachedEntityService { private taskDefinitionService: TaskDefinitionService, private taskOutcomeAlignmentService: TaskOutcomeAlignmentService, private groupSetService: GroupSetService, - private groupService: GroupService + private groupService: GroupService, + private feedbackTemplateService: FeedbackTemplateService, ) { super(httpClient, API_URL); @@ -210,6 +212,18 @@ export class UnitService extends CachedEntityService { }); } }, + { + keys: 'feedbackTemplates', + toEntityOp: (data: object, key: string, unit: Unit) => { + data[key]?.forEach((template) => { + unit.feedbackTemplateCache.getOrCreate( + template['id'], + this.feedbackTemplateService, + template, + ); + }); + }, + }, // 'groupMemberships', - map to group memberships ); diff --git a/src/app/common/feedback-template/feedback-template-editor.component.html b/src/app/common/feedback-template/feedback-template-editor.component.html index 51af89539a..fd4cccc16c 100644 --- a/src/app/common/feedback-template/feedback-template-editor.component.html +++ b/src/app/common/feedback-template/feedback-template-editor.component.html @@ -91,202 +91,246 @@ - - @if (selectedOutcome) { -
- - Outcome Number - - +
+
+

Edit Outcome

+ - - Abbreviation - - +
+ + Tag + + - - Name - - -
+ + Name + + +
- - Description - - + + Description + + - - Connected Learning Outcomes - - @for (outcome of connectedOutcomes(); track $index) { - - {{ outcome }} - - - } - - - - @for (outcome of filteredOutcomes(); track outcome) { - {{ outcome }} - } - - + + Connected Learning Outcomes + + @for (outcome of connectedOutcomes(); track $index) { + + {{ outcome }} + + + } + + + + @for (outcome of filteredOutcomes(); track outcome) { + {{ outcome }} + } + + -
-
Learning OutcomeNumber - {{ feedbackTemplate.learningOutcome }} + {{ feedbackTemplate.id }}
- - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - + @if (selectedTemplate) { +
+

Edit Template

+ -
- -
Number - {{ feedbackTemplate.id }} - Chip Text - {{ feedbackTemplate.chipText }} - Description - {{ feedbackTemplate.description }} - Comment Text - {{ feedbackTemplate.commentText }} - Summary Text - {{ feedbackTemplate.summaryText }} - + + + + + +
+

Edit Feedback Templates

+ + +
+ - @if (feedbackTemplateHasChanges(feedbackTemplate)) { - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Number - save - - } - Chip Text + {{ feedbackTemplate.chipText }} + Description + {{ feedbackTemplate.description }} + Comment Text + {{ feedbackTemplate.commentText }} + Summary Text + {{ feedbackTemplate.summaryText }} + + @if (feedbackTemplateHasChanges(feedbackTemplate)) { + + } + +
+ +
+ + + +
+ + + + + -
- -
- - - +
+ + Chip Text + + + + + Summary Text + + +
+ + + Comment Text + + + + + Description + + + +
+ + +
+
+ }
- - - - - - - - +
} diff --git a/src/app/common/feedback-template/feedback-template-editor.component.ts b/src/app/common/feedback-template/feedback-template-editor.component.ts index fa8a82df27..ddf0334e54 100644 --- a/src/app/common/feedback-template/feedback-template-editor.component.ts +++ b/src/app/common/feedback-template/feedback-template-editor.component.ts @@ -32,13 +32,14 @@ import {COMMA, ENTER} from '@angular/cdk/keycodes'; import {LiveAnnouncer} from '@angular/cdk/a11y'; import {MatChipInputEvent} from '@angular/material/chips'; import {MatAutocompleteSelectedEvent} from '@angular/material/autocomplete'; +import {FileDownloaderService} from '../file-downloader/file-downloader.service'; @Component({ selector: 'f-feedback-template-editor', templateUrl: 'feedback-template-editor.component.html', }) export class FeedbackTemplateEditorComponent implements AfterViewInit { - @Input() taskDefinition: TaskDefinition; + @Input() context: TaskDefinition | Unit; @ViewChild(MatTable, {static: false}) outcomeTable: MatTable; @ViewChild(MatSort, {static: false}) outcomeSort: MatSort; @@ -52,7 +53,6 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { 'description', 'learningOutcomeAction', ]; - public outcomeFilter: string; public selectedOutcome: LearningOutcome; @ViewChild(MatTable, {static: false}) templateTable: MatTable; @@ -68,7 +68,6 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { 'summaryText', 'feedbackTemplateAction', ]; - public templateFilter: string; public selectedTemplate: FeedbackTemplate; constructor( @@ -76,28 +75,42 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { private taskDefinitionService: TaskDefinitionService, private learningOutcomeService: LearningOutcomeService, private feedbackTemplateService: FeedbackTemplateService, + private fileDownloaderService: FileDownloaderService, @Inject(csvResultModalService) private csvResultModalService: any, @Inject(csvUploadModalService) private csvUploadModal: any, @Inject(confirmationModal) private confirmationModal: any, ) {} - public get unit(): Unit { - return this.taskDefinition?.unit; - } - ngAfterViewInit(): void { this.subscriptions.push( - this.unit.learningOutcomesCache.values.subscribe((learningOutcomes) => { + this.context.learningOutcomesCache.values.subscribe((learningOutcomes) => { this.outcomeSource = new MatTableDataSource(learningOutcomes); this.outcomeSource.paginator = this.outcomePaginator; this.outcomeSource.sort = this.outcomeSort; - this.outcomeSource.filterPredicate = (data: any, filter: string) => data.matches(filter); + this.outcomeSource.filterPredicate = (data: LearningOutcome, filter: string) => { + const filterValue = filter.trim().toLowerCase(); + return ( + data.iloNumber.toString().includes(filterValue) || + data.abbreviation.toLowerCase().includes(filterValue) || + data.name.toLowerCase().includes(filterValue) || + data.description.toLowerCase().includes(filterValue) + ); + }; }), - this.taskDefinition.feedbackTemplateCache.values.subscribe((feedbackTemplates) => { + this.context.feedbackTemplateCache.values.subscribe((feedbackTemplates) => { this.templateSource = new MatTableDataSource(feedbackTemplates); this.templateSource.paginator = this.templatePaginator; this.templateSource.sort = this.templateSort; - this.templateSource.filterPredicate = (data: any, filter: string) => data.matches(filter); + this.templateSource.filterPredicate = (data: FeedbackTemplate, filter: string) => { + const filterValue = filter.trim().toLowerCase(); + return ( + data.id.toString().includes(filterValue) || + data.chipText.toLowerCase().includes(filterValue) || + data.commentText.toLowerCase().includes(filterValue) || + data.summaryText.toLowerCase().includes(filterValue) || + data.description.toLowerCase().includes(filterValue) + ); + }; }), ); } @@ -201,19 +214,17 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { return (a < b ? -1 : 1) * (isAsc ? 1 : -1); } - applyOutcomeFilter(filterValue: string) { - this.outcomeSource.filter = filterValue.trim().toLowerCase(); - - if (this.outcomeSource.paginator) { - this.outcomeSource.paginator.firstPage(); - } - } - - applyTemplateFilter(filterValue: string) { - this.templateSource.filter = filterValue.trim().toLowerCase(); - - if (this.templateSource.paginator) { - this.templateSource.paginator.firstPage(); + applyFilter(filterValue: string, table: string) { + if (table === 'outcome') { + this.outcomeSource.filter = filterValue; + if (this.outcomeSource.paginator) { + this.outcomeSource.paginator.firstPage(); + } + } else if (table === 'template') { + this.templateSource.filter = filterValue; + if (this.templateSource.paginator) { + this.templateSource.paginator.firstPage(); + } } } @@ -230,6 +241,15 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { 'Delete learning outcome', 'Are you sure you want to delete this outcome? This action is final.', () => { + this.learningOutcomeService + .delete( + {id: learningOutcome.id, unitId: this.context.id}, + {entity: learningOutcome, cache: this.context.learningOutcomesCache}, + ) + .subscribe({ + next: () => this.alerts.success('Learning outcome deleted'), + error: () => this.alerts.error('Failed to delete learning outcome. Please try again.'), + }); this.alerts.success('Outcome deleted'); }, ); @@ -245,45 +265,58 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { ); } - public uploadLearningOutcomesCsv() { + public uploadCsv(type: 'Learning Outcomes' | 'Feedback Templates') { + const url = + type === 'Learning Outcomes' + ? this.context.getOutcomeBatchUploadUrl() + : this.context.getFeedbackTemplateBatchUploadUrl(); + this.csvUploadModal.show( - 'Upload Learning Outcomes as CSV', + `Upload ${type} as CSV`, 'Test message', - {file: {name: 'Learning Outcome CSV Data', type: 'csv'}}, - this.unit.getTaskDefinitionBatchUploadUrl(), - (response: any) => {}, + {file: {name: `${type} CSV Data`, type: 'csv'}}, + url, + (response: any) => { + this.csvResultModalService.show(`${type} CSV Upload Results`, response); + if (response.success.length > 0) { + this.context.refresh(); + } + }, ); } - public uploadFeedbackTemplatesCsv() { - this.csvUploadModal.show( - 'Upload Feedback Templates as CSV', - 'Test message', - {file: {name: 'Feedback Template CSV Data', type: 'csv'}}, - this.unit.getTaskDefinitionBatchUploadUrl(), - (response: any) => {}, - ); + public downloadCsv(type: 'learning-outcomes' | 'feedback-templates') { + let name: string = ''; + if (this.context instanceof TaskDefinition) name = this.context.abbreviation; + else if (this.context instanceof Unit) name = this.context.code; + + const url = + type === 'learning-outcomes' + ? this.context.getOutcomeBatchUploadUrl() + : this.context.getFeedbackTemplateBatchUploadUrl(); + + this.fileDownloaderService.downloadFile(url, `${name}-${type}.csv`); } public createLearningOutcome() { const learningOutcome = new LearningOutcome(); learningOutcome.iloNumber = 1; - learningOutcome.abbreviation = 'lm'; - learningOutcome.name = 'lorem'; - learningOutcome.description = 'Lorem ipsum dolor'; + learningOutcome.abbreviation = ''; + learningOutcome.name = ''; + learningOutcome.description = ''; this.selectedOutcome = learningOutcome; } public createFeedbackTemplate() { - const feedbackTemplate = new FeedbackTemplate(this.taskDefinition); + const feedbackTemplate = new FeedbackTemplate(this.context); feedbackTemplate.id = 0; - feedbackTemplate.chipText = 'lorem'; - feedbackTemplate.description = 'Lorem ipsum dolor'; - feedbackTemplate.commentText = 'Lorem dolor'; - feedbackTemplate.summaryText = 'Lorem ipsum'; + feedbackTemplate.chipText = ''; + feedbackTemplate.description = ''; + feedbackTemplate.commentText = ''; + feedbackTemplate.summaryText = ''; this.selectedTemplate = feedbackTemplate; } diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index e14fdbb545..c227a43c05 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -225,6 +225,7 @@ import {MarkedPipe} from './common/pipes/marked.pipe'; import {AlertService} from './common/services/alert.service'; 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 {FeedbackTemplateEditorComponent} from './common/feedback-template/feedback-template-editor.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -463,6 +464,10 @@ DoubtfireAngularJSModule.directive( 'statusIcon', downgradeComponent({component: StatusIconComponent}), ); +DoubtfireAngularJSModule.directive( + 'fFeedbackTemplateEditor', + downgradeComponent({component: FeedbackTemplateEditorComponent}), +); DoubtfireAngularJSModule.directive('newFUnits', downgradeComponent({component: FUnitsComponent})); // Global configuration diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html index c56b29c055..59adc0f043 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html @@ -34,7 +34,7 @@

Task detailsTask Learning Outcomes

Add learning outcomes for this task

- +
diff --git a/src/app/units/states/edit/edit.tpl.html b/src/app/units/states/edit/edit.tpl.html index 3ba73129a5..c2db43e07f 100644 --- a/src/app/units/states/edit/edit.tpl.html +++ b/src/app/units/states/edit/edit.tpl.html @@ -5,7 +5,7 @@ - + From 5494384f1a4becf462dd031e89fae2734ed46e55 Mon Sep 17 00:00:00 2001 From: satikaj <117552851+satikaj@users.noreply.github.com> Date: Tue, 26 Nov 2024 15:29:16 +1100 Subject: [PATCH 0227/1531] fix: remove selected outcomes from dropdown --- .../feedback-template-editor.component.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/common/feedback-template/feedback-template-editor.component.ts b/src/app/common/feedback-template/feedback-template-editor.component.ts index ddf0334e54..38358b0eab 100644 --- a/src/app/common/feedback-template/feedback-template-editor.component.ts +++ b/src/app/common/feedback-template/feedback-template-editor.component.ts @@ -327,9 +327,12 @@ export class FeedbackTemplateEditorComponent implements AfterViewInit { readonly allOutcomes: string[] = ['TLO1', 'TLO2', 'TLO3', 'ULO1', 'ULO2']; readonly filteredOutcomes = computed(() => { const currentOutcome = this.currentConnectedOutcome().toLowerCase(); - return currentOutcome - ? this.allOutcomes.filter((outcome) => outcome.toLowerCase().includes(currentOutcome)) - : this.allOutcomes.slice(); + return this.allOutcomes.filter((outcome) => { + return ( + !this.connectedOutcomes().includes(outcome) && + (!currentOutcome || outcome.toLowerCase().includes(currentOutcome)) + ); + }); }); readonly announcer = inject(LiveAnnouncer); From 9d017fbfaa1d5bae7f43da37ec7ae43e1dfafa8f Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Fri, 6 Dec 2024 10:25:51 +1100 Subject: [PATCH 0228/1531] feat: switch to html5 mode --- src/app/doubtfire-angularjs.module.ts | 4 +++- src/index.html | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index e14fdbb545..2f12cc2b57 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -236,7 +236,9 @@ export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.projects', 'doubtfire.groups', 'doubtfire.visualisations', -]); +]).config(['$locationProvider', ($locationProvider) => { + $locationProvider.html5Mode(true); +}]); // Downgrade angular modules that we need... // factory -> service diff --git a/src/index.html b/src/index.html index 54fed2d067..2e715e206f 100644 --- a/src/index.html +++ b/src/index.html @@ -1,6 +1,7 @@ + -
-
-

Modify Unit Staff

- Add staff members to the unit, assigning them a convenor or tutor role. -
-
-
-
This unit has no staff assigned
-
- - - - - - - - - - - - - - - - - - -
NameRoleMain ConvenorActions
- - {{staff.user.name}} -
- - -
-
- - - -
-
-
-
- -
- diff --git a/src/app/units/states/edit/edit.tpl.html b/src/app/units/states/edit/edit.tpl.html index 3ba73129a5..a49ba3561d 100644 --- a/src/app/units/states/edit/edit.tpl.html +++ b/src/app/units/states/edit/edit.tpl.html @@ -6,7 +6,7 @@ - + From 49fcba6bdfb9b83ead231114045c31583643b003 Mon Sep 17 00:00:00 2001 From: Jason Vellucci Date: Mon, 22 Sep 2025 11:18:15 +1000 Subject: [PATCH 0640/1531] refactor: migrate/unit staff editor 9.x (#933) * chore: migrate/unit-staff-editor - delete old Coffeescript file - delete old template - remove reference to old Coffeescript file - link new component - downgrade new component * chore: migrate/unit-staff-editor - port `unit-staff-editor-component` to Typescript from Coffeescript - port `unit-staff-editor` template to Angular template syntax w/ Angular Material - adjust parent component `Inputs` and attribute bindings * Update README.md * Update README.md --------- Co-authored-by: Boink <40929320+b0ink@users.noreply.github.com> --- README.md | 2 +- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 11 +- .../states/edit/directives/directives.coffee | 1 - .../unit-staff-editor.component.html | 116 +++++++++++++++ .../unit-staff-editor.component.ts | 135 ++++++++++++++++++ .../unit-staff-editor.tpl.html | 101 ------------- src/app/units/states/edit/edit.tpl.html | 2 +- 8 files changed, 264 insertions(+), 106 deletions(-) create mode 100644 src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html create mode 100644 src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts delete mode 100644 src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.tpl.html diff --git a/README.md b/README.md index e748a9393b..5f4e969966 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ MIGRATED: - [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.ts - [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.ts - [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts +- [x] ./src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts - [x] ./src/app/units/states/analytics/unit-analytics-route.component.ts - [x] ./src/app/common/footer/footer.component.ts - [x] ./src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.ts @@ -189,7 +190,6 @@ TODO: - [ ] ./src/app/units/states/edit/directives/directives.coffee - [ ] ./src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.coffee - [ ] ./src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.coffee -- [ ] ./src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.coffee - [ ] ./src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.coffee - [ ] ./src/app/units/states/edit/edit.coffee - [ ] ./src/app/units/states/rollover/directives/directives.coffee diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index e20c993667..0e370154ff 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -286,6 +286,7 @@ import {TaskPrerequisiteService} from './api/services/task-prerequisite.service' // import { GradeIconComponent } from './common/grade-icon/grade-icon.component'; // import { GradeTaskModalComponent } from './tasks/modals/grade-task-modal/grade-task-modal.component'; // import { PrivacyPolicy } from './config/privacy-policy/privacy-policy'; +import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 @@ -435,6 +436,7 @@ const MY_DATE_FORMAT = { LtiUnitLinkComponent, TaskDefinitionPrerequisitesComponent, TaskPrerequisitesCardComponent, + UnitStaffEditorComponent, GroupSetSelectorComponent, ], // Services we provide diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 7ce8c29c3d..223544d7bf 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -101,7 +101,6 @@ import 'build/src/app/units/states/groups/groups.js'; import 'build/src/app/units/states/states.js'; import 'build/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.js'; import 'build/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.js'; -import 'build/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.js'; import 'build/src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.js'; import 'build/src/app/units/states/edit/directives/directives.js'; import 'build/src/app/units/states/edit/edit.js'; @@ -229,6 +228,7 @@ import {SidekiqProgressModalService} from './common/modals/sidekiq-progress-moda import {TaskPrerequisitesCardComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-prerequisites-card/task-prerequisites-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 {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; export const DoubtfireAngularJSModule = angular @@ -342,7 +342,10 @@ DoubtfireAngularJSModule.directive( 'objectSelect', downgradeComponent({component: ObjectSelectComponent}), ); -DoubtfireAngularJSModule.directive('fGradeIcon', downgradeComponent({component: GradeIconComponent})); +DoubtfireAngularJSModule.directive( + 'fGradeIcon', + downgradeComponent({component: GradeIconComponent}), +); DoubtfireAngularJSModule.directive('appHeader', downgradeComponent({component: HeaderComponent})); DoubtfireAngularJSModule.directive( 'splashScreen', @@ -499,6 +502,10 @@ DoubtfireAngularJSModule.directive( ); DoubtfireAngularJSModule.directive('newFUnits', downgradeComponent({component: FUnitsComponent})); +DoubtfireAngularJSModule.directive( + 'unitStaffEditor', + downgradeComponent({component: UnitStaffEditorComponent}), +); DoubtfireAngularJSModule.directive( 'fTaskIlosCard', downgradeComponent({component: TaskIlosCardComponent}), diff --git a/src/app/units/states/edit/directives/directives.coffee b/src/app/units/states/edit/directives/directives.coffee index bfb12ed317..fe06bf4510 100644 --- a/src/app/units/states/edit/directives/directives.coffee +++ b/src/app/units/states/edit/directives/directives.coffee @@ -2,5 +2,4 @@ angular.module('doubtfire.units.states.edit.directives', [ 'doubtfire.units.states.edit.directives.unit-details-editor' 'doubtfire.units.states.edit.directives.unit-group-set-editor' 'doubtfire.units.states.edit.directives.unit-ilo-editor' - 'doubtfire.units.states.edit.directives.unit-staff-editor' ]) diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html new file mode 100644 index 0000000000..84aa983f0a --- /dev/null +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html @@ -0,0 +1,116 @@ +
+ + + + + + + + +
+
+

Modify Unit Staff

+

Add staff members to the unit, assigning them a convenor or tutor role.

+
+ +
+
+ +
+ This unit has no staff assigned. +
+ + +
+ + + + + + + + + + + + + + + + + + +
NameRoleMain ConvenorActions
+ + {{ staff.user.name }} +
+ + +
+
+ + + +
+
+
+
+ +
+
diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts new file mode 100644 index 0000000000..167ed3210f --- /dev/null +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts @@ -0,0 +1,135 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {UnitRoleService} from 'src/app/api/services/unit-role.service'; +import {Unit} from 'src/app/api/models/unit'; +import {User} from 'src/app/api/models/doubtfire-model'; +import {UnitRole} from 'src/app/api/models/unit-role'; + +@Component({ + selector: 'unit-staff-editor', + templateUrl: 'unit-staff-editor.component.html', +}) +export class UnitStaffEditorComponent implements OnInit { + @Input() unit: Unit; + @Input() staff: User[]; + + temp = []; + users = []; + unitStaff: UnitRole[]; + filteredStaff: User[] = []; // Filtered staff members + searchTerm: string = ''; // Search term entered by the user + + // Inject services here + constructor( + private alertService: AlertService, + private unitRoleService: UnitRoleService, + ) {} + + ngOnInit(): void { + // Subscribe to staff cache + this.unit.staffCache.values.subscribe((staff: UnitRole[]) => { + this.unitStaff = staff; + }); + } + + /** + * Changes the role of a staff member. + * + * @param UnitRole unitRole + * @param number role_id + * + * @returns void + */ + changeRole(unitRole: UnitRole, role_id: number) { + unitRole.roleId = role_id; + this.unitRoleService.update(unitRole).subscribe({ + next: (response) => this.alertService.success('Role changed', 2000), + error: (response) => this.alertService.error(response, 6000), + }); + } + + /** + * Changes who the `Main Convenor` of the unit is. + * + * @param UnitRole staff + * + * @returns void + */ + changeMainConvenor(staff: UnitRole) { + this.unit.changeMainConvenor(staff).subscribe({ + next: (response) => this.alertService.success('Main convenor changed', 2000), + error: (response) => this.alertService.error(response, 6000), + }); + } + + /** + * Adds a staff member to the unit. + * + * @param User selectedStaff + * + * @returns void + */ + addSelectedStaff(selectedStaff: User) { + if (selectedStaff?.id) { + this.unit.addStaff(selectedStaff).subscribe({ + next: () => { + this.alertService.success('Staff member added', 2000); + this.searchTerm = ''; // Clear the input field + this.filterStaffList(); // Refilter the list + }, + error: (response) => this.alertService.error(response, 6000), + }); + } else { + this.alertService.error( + 'Unable to add staff member. Ensure they have a tutor or convenor account in User admin first', + ); + } + } + + /** + * Used in filtering the staff list. The `searchTerm` is bound to the auto-complete input in this class's template. + * + * @returns void + */ + filterStaffList(): void { + // `this.searchTerm` holds the selected staff member object from the dropdown OR the auto-complete input searchTerm (never at the same time). + // Thus, check the type here and exit early if string filtering is not needed. + if (typeof this.searchTerm !== 'string') { + return; + } + this.filteredStaff = this.staff.filter( + (staff) => + staff.name.toLowerCase().includes(this.searchTerm.toLowerCase()) && // Find by name + !this.unit.staff.find((listStaff) => staff.id === listStaff.user.id), // Not already assigned to the unit + ); + } + + /** + * Generates a human-readable name made up of the passed-in staff member's `first` and `last` names. + * + * @param User staff + * + * @returns void + */ + displayStaffName(staff: User): string { + return staff ? staff.name : ''; + } + + /** + * Removes a staff member from the unit. + * + * @param UnitRole staff + * + * @returns void + */ + removeStaff(staff: UnitRole) { + this.unitRoleService.delete(staff, {cache: this.unit.staffCache}).subscribe({ + next: (response) => this.alertService.success('Staff member removed', 2000), + error: (response) => this.alertService.error(response, 6000), + }); + } + + groupSetName(id: number) { + this.unit.groupSetsCache.get(id).name || 'Individual Work'; + } +} diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.tpl.html b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.tpl.html deleted file mode 100644 index f8b38cecb0..0000000000 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.tpl.html +++ /dev/null @@ -1,101 +0,0 @@ -
- -
-
-

Modify Unit Staff

- Add staff members to the unit, assigning them a convenor or tutor role. -
-
-
-
This unit has no staff assigned
-
- - - - - - - - - - - - - - - - - - -
NameRoleMain ConvenorActions
- - {{staff.user.name}} -
- - -
-
- - - -
-
-
-
- -
-
diff --git a/src/app/units/states/edit/edit.tpl.html b/src/app/units/states/edit/edit.tpl.html index 2c9699e496..4df8bf3d09 100644 --- a/src/app/units/states/edit/edit.tpl.html +++ b/src/app/units/states/edit/edit.tpl.html @@ -6,7 +6,7 @@ - + From 943e3bf761ab210e68d69982ccf91c0d093a836e Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 22 Sep 2025 12:44:53 +1000 Subject: [PATCH 0641/1531] refactor: unit staff editor material ui (#1001) * fix: revert staff role on error * fix: ensure full search for unit role * chore: fix casing * refactor: use mat table for staff editor * chore: remove unused variables * fix: null check * refactor: use icon button * chore: remove unit staff editor coffeescript file * chore: add back staff editor tooltips --- src/app/common/header/header.component.ts | 3 +- .../unit-staff-editor.coffee | 58 ------ .../unit-staff-editor.component.html | 197 ++++++++---------- .../unit-staff-editor.component.ts | 51 ++++- 4 files changed, 127 insertions(+), 182 deletions(-) delete mode 100644 src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.coffee diff --git a/src/app/common/header/header.component.ts b/src/app/common/header/header.component.ts index 8d9e8f6a11..4601057b15 100644 --- a/src/app/common/header/header.component.ts +++ b/src/app/common/header/header.component.ts @@ -173,8 +173,7 @@ export class HeaderComponent implements OnInit, OnDestroy { } isUniqueRole = (unit) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const units = this.unitRoles.filter((role: any) => role.unit.id === unit.unit.id); + const units = this.unitRoles.filter((role: UnitRole) => role.unit?.id === unit.unit?.id); return units.length == 1 || unit.role == 'Tutor'; }; diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.coffee b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.coffee deleted file mode 100644 index 3856daefe5..0000000000 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.coffee +++ /dev/null @@ -1,58 +0,0 @@ -angular.module('doubtfire.units.states.edit.directives.unit-staff-editor', []) - -# -# Editor for adding new staff to a unit and assigning those staff -# members new unit roles within the unit -# -.directive('unitStaffEditor', -> - replace: true - restrict: 'E' - templateUrl: 'units/states/edit/directives/unit-staff-editor/unit-staff-editor.tpl.html' - controller: ($scope, $rootScope, alertService, newUnitService, newUnitRoleService) -> - temp = [] - users = [] - - $scope.unit.staffCache.values.subscribe( (staff) -> $scope.unitStaff = staff ) - - $scope.changeRole = (unitRole, role_id) -> - unitRole.roleId = role_id - newUnitRoleService.update(unitRole).subscribe({ - next: (response) -> alertService.success( "Role changed", 2000) - error: (response) -> alertService.error( response, 6000) - }) - - $scope.changeMainConvenor = (staff) -> - $scope.unit.changeMainConvenor(staff).subscribe({ - next: (response) -> - alertService.success( "Main convenor changed", 2000) - error: (response) -> - alertService.error( response, 6000) - }) - - $scope.addSelectedStaff = -> - staff = $scope.selectedStaff - $scope.selectedStaff = null - $scope.unit.staff = [] unless $scope.unit.staff - - if staff.id? - $scope.unit.addStaff(staff).subscribe({ - next: (response) -> alertService.success( "Staff member added", 2000) - error: (response) -> alertService.error( response, 6000) - }) - else - alertService.error( "Unable to add staff member. Ensure they have a tutor or convenor account in User admin first.", 6000) - - # Used in the typeahead to filter staff already in unit - $scope.filterStaff = (staff) -> - not _.find($scope.unit.staff, (listStaff) -> staff.id == listStaff.user.id) - - $scope.removeStaff = (staff) -> - newUnitRoleService.delete(staff, {cache: $scope.unit.staffCache}).subscribe({ - next: (response) -> alertService.success( "Staff member removed", 2000) - error: (response) -> alertService.error( response, 6000) - }) - - $scope.groupSetName = (id) -> - $scope.unit.groupSetsCache.get(id)?.name || "Individual Work" - -) diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html index 84aa983f0a..82938cde3f 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html @@ -1,116 +1,89 @@ -
- - - - - - - - -
-
-

Modify Unit Staff

-

Add staff members to the unit, assigning them a convenor or tutor role.

-
- -
-
- -
- This unit has no staff assigned. -
+
+
+

Unit Staff

+

Manage unit staff by adding members and assigning them as convenors or tutors.

+
+ + + - -
-
Name
- - - - - - - - - - - - - - - - - -
NameRoleMain ConvenorActions
- - {{ staff.user.name }} -
- - -
-
- - - -
+ +
+ {{ unitRole.user.name }}
-
-
- -
+ Convenor + + + + + Main Convenor + + @if (unitRole?.role === 'Convenor') { + + } + + + + Actions + + + + + + + + + + + + {{ staff.name }} + + +
diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts index 167ed3210f..7c53a04671 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts @@ -4,6 +4,9 @@ import {UnitRoleService} from 'src/app/api/services/unit-role.service'; import {Unit} from 'src/app/api/models/unit'; import {User} from 'src/app/api/models/doubtfire-model'; import {UnitRole} from 'src/app/api/models/unit-role'; +import {MatTableDataSource} from '@angular/material/table'; +import {MatButtonToggleChange} from '@angular/material/button-toggle'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; @Component({ selector: 'unit-staff-editor', @@ -19,19 +22,32 @@ export class UnitStaffEditorComponent implements OnInit { filteredStaff: User[] = []; // Filtered staff members searchTerm: string = ''; // Search term entered by the user + displayedColumns: string[] = ['name', 'role', 'main-convenor', 'actions']; + dataSource = new MatTableDataSource(); + // Inject services here constructor( private alertService: AlertService, private unitRoleService: UnitRoleService, + private confirmationModalService: ConfirmationModalService, ) {} ngOnInit(): void { // Subscribe to staff cache this.unit.staffCache.values.subscribe((staff: UnitRole[]) => { this.unitStaff = staff; + this.dataSource.data = staff; }); } + onRoleChange(unitRole: UnitRole, event: MatButtonToggleChange) { + const role = event.value; + if (role !== 'Tutor' && role !== 'Convenor') { + return; + } + const roleId = role === 'Tutor' ? 2 : 3; // map however you like + this.changeRole(unitRole, roleId, role); + } /** * Changes the role of a staff member. * @@ -40,11 +56,20 @@ export class UnitStaffEditorComponent implements OnInit { * * @returns void */ - changeRole(unitRole: UnitRole, role_id: number) { - unitRole.roleId = role_id; + changeRole(unitRole: UnitRole, roleId: number, role: string) { + const previousRoleId = unitRole.roleId; + const previousRole = unitRole.role; + + unitRole.roleId = roleId; + unitRole.role = role; this.unitRoleService.update(unitRole).subscribe({ - next: (response) => this.alertService.success('Role changed', 2000), - error: (response) => this.alertService.error(response, 6000), + next: () => this.alertService.success('Role changed', 2000), + error: (response) => { + // Revert changes on error + unitRole.roleId = previousRoleId; + unitRole.role = previousRole; + this.alertService.error(response, 6000); + }, }); } @@ -56,10 +81,16 @@ export class UnitStaffEditorComponent implements OnInit { * @returns void */ changeMainConvenor(staff: UnitRole) { - this.unit.changeMainConvenor(staff).subscribe({ - next: (response) => this.alertService.success('Main convenor changed', 2000), - error: (response) => this.alertService.error(response, 6000), - }); + this.confirmationModalService.show( + 'Set Main Convenor', + `Do you want to make ${staff.user.name} the main convenor for this unit?`, + () => { + this.unit.changeMainConvenor(staff).subscribe({ + next: (_response) => this.alertService.success('Main convenor changed', 2000), + error: (response) => this.alertService.error(response, 6000), + }); + }, + ); } /** @@ -99,7 +130,7 @@ export class UnitStaffEditorComponent implements OnInit { } this.filteredStaff = this.staff.filter( (staff) => - staff.name.toLowerCase().includes(this.searchTerm.toLowerCase()) && // Find by name + staff.matches(this.searchTerm.toLowerCase()) && // Find by name !this.unit.staff.find((listStaff) => staff.id === listStaff.user.id), // Not already assigned to the unit ); } @@ -124,7 +155,7 @@ export class UnitStaffEditorComponent implements OnInit { */ removeStaff(staff: UnitRole) { this.unitRoleService.delete(staff, {cache: this.unit.staffCache}).subscribe({ - next: (response) => this.alertService.success('Staff member removed', 2000), + next: () => this.alertService.success('Staff member removed', 2000), error: (response) => this.alertService.error(response, 6000), }); } From d510b3b54340c225abb4db51b06bddc4404b9306 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 22 Sep 2025 12:44:53 +1000 Subject: [PATCH 0642/1531] refactor: unit staff editor material ui (#1001) * fix: revert staff role on error * fix: ensure full search for unit role * chore: fix casing * refactor: use mat table for staff editor * chore: remove unused variables * fix: null check * refactor: use icon button * chore: remove unit staff editor coffeescript file * chore: add back staff editor tooltips --- src/app/common/header/header.component.ts | 3 +- .../unit-staff-editor.coffee | 58 ------ .../unit-staff-editor.component.html | 197 ++++++++---------- .../unit-staff-editor.component.ts | 51 ++++- 4 files changed, 127 insertions(+), 182 deletions(-) delete mode 100644 src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.coffee diff --git a/src/app/common/header/header.component.ts b/src/app/common/header/header.component.ts index b5e1960c8a..842287b92e 100644 --- a/src/app/common/header/header.component.ts +++ b/src/app/common/header/header.component.ts @@ -104,8 +104,7 @@ export class HeaderComponent implements OnInit, OnDestroy { } isUniqueRole = (unit) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const units = this.unitRoles.filter((role: any) => role.unit.id === unit.unit.id); + const units = this.unitRoles.filter((role: UnitRole) => role.unit?.id === unit.unit?.id); return units.length == 1 || unit.role == 'Tutor'; }; diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.coffee b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.coffee deleted file mode 100644 index 3856daefe5..0000000000 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.coffee +++ /dev/null @@ -1,58 +0,0 @@ -angular.module('doubtfire.units.states.edit.directives.unit-staff-editor', []) - -# -# Editor for adding new staff to a unit and assigning those staff -# members new unit roles within the unit -# -.directive('unitStaffEditor', -> - replace: true - restrict: 'E' - templateUrl: 'units/states/edit/directives/unit-staff-editor/unit-staff-editor.tpl.html' - controller: ($scope, $rootScope, alertService, newUnitService, newUnitRoleService) -> - temp = [] - users = [] - - $scope.unit.staffCache.values.subscribe( (staff) -> $scope.unitStaff = staff ) - - $scope.changeRole = (unitRole, role_id) -> - unitRole.roleId = role_id - newUnitRoleService.update(unitRole).subscribe({ - next: (response) -> alertService.success( "Role changed", 2000) - error: (response) -> alertService.error( response, 6000) - }) - - $scope.changeMainConvenor = (staff) -> - $scope.unit.changeMainConvenor(staff).subscribe({ - next: (response) -> - alertService.success( "Main convenor changed", 2000) - error: (response) -> - alertService.error( response, 6000) - }) - - $scope.addSelectedStaff = -> - staff = $scope.selectedStaff - $scope.selectedStaff = null - $scope.unit.staff = [] unless $scope.unit.staff - - if staff.id? - $scope.unit.addStaff(staff).subscribe({ - next: (response) -> alertService.success( "Staff member added", 2000) - error: (response) -> alertService.error( response, 6000) - }) - else - alertService.error( "Unable to add staff member. Ensure they have a tutor or convenor account in User admin first.", 6000) - - # Used in the typeahead to filter staff already in unit - $scope.filterStaff = (staff) -> - not _.find($scope.unit.staff, (listStaff) -> staff.id == listStaff.user.id) - - $scope.removeStaff = (staff) -> - newUnitRoleService.delete(staff, {cache: $scope.unit.staffCache}).subscribe({ - next: (response) -> alertService.success( "Staff member removed", 2000) - error: (response) -> alertService.error( response, 6000) - }) - - $scope.groupSetName = (id) -> - $scope.unit.groupSetsCache.get(id)?.name || "Individual Work" - -) diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html index 84aa983f0a..82938cde3f 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html @@ -1,116 +1,89 @@ -
- - - - - - - - -
-
-

Modify Unit Staff

-

Add staff members to the unit, assigning them a convenor or tutor role.

-
- -
-
- -
- This unit has no staff assigned. -
+
+
+

Unit Staff

+

Manage unit staff by adding members and assigning them as convenors or tutors.

+
+ + + - -
-
Name
- - - - - - - - - - - - - - - - - -
NameRoleMain ConvenorActions
- - {{ staff.user.name }} -
- - -
-
- - - -
+ +
+ {{ unitRole.user.name }}
-
-
- -
+ Convenor + + + + + Main Convenor + + @if (unitRole?.role === 'Convenor') { + + } + + + + Actions + + + + + + + + + + + + {{ staff.name }} + + +
diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts index 167ed3210f..7c53a04671 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts @@ -4,6 +4,9 @@ import {UnitRoleService} from 'src/app/api/services/unit-role.service'; import {Unit} from 'src/app/api/models/unit'; import {User} from 'src/app/api/models/doubtfire-model'; import {UnitRole} from 'src/app/api/models/unit-role'; +import {MatTableDataSource} from '@angular/material/table'; +import {MatButtonToggleChange} from '@angular/material/button-toggle'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; @Component({ selector: 'unit-staff-editor', @@ -19,19 +22,32 @@ export class UnitStaffEditorComponent implements OnInit { filteredStaff: User[] = []; // Filtered staff members searchTerm: string = ''; // Search term entered by the user + displayedColumns: string[] = ['name', 'role', 'main-convenor', 'actions']; + dataSource = new MatTableDataSource(); + // Inject services here constructor( private alertService: AlertService, private unitRoleService: UnitRoleService, + private confirmationModalService: ConfirmationModalService, ) {} ngOnInit(): void { // Subscribe to staff cache this.unit.staffCache.values.subscribe((staff: UnitRole[]) => { this.unitStaff = staff; + this.dataSource.data = staff; }); } + onRoleChange(unitRole: UnitRole, event: MatButtonToggleChange) { + const role = event.value; + if (role !== 'Tutor' && role !== 'Convenor') { + return; + } + const roleId = role === 'Tutor' ? 2 : 3; // map however you like + this.changeRole(unitRole, roleId, role); + } /** * Changes the role of a staff member. * @@ -40,11 +56,20 @@ export class UnitStaffEditorComponent implements OnInit { * * @returns void */ - changeRole(unitRole: UnitRole, role_id: number) { - unitRole.roleId = role_id; + changeRole(unitRole: UnitRole, roleId: number, role: string) { + const previousRoleId = unitRole.roleId; + const previousRole = unitRole.role; + + unitRole.roleId = roleId; + unitRole.role = role; this.unitRoleService.update(unitRole).subscribe({ - next: (response) => this.alertService.success('Role changed', 2000), - error: (response) => this.alertService.error(response, 6000), + next: () => this.alertService.success('Role changed', 2000), + error: (response) => { + // Revert changes on error + unitRole.roleId = previousRoleId; + unitRole.role = previousRole; + this.alertService.error(response, 6000); + }, }); } @@ -56,10 +81,16 @@ export class UnitStaffEditorComponent implements OnInit { * @returns void */ changeMainConvenor(staff: UnitRole) { - this.unit.changeMainConvenor(staff).subscribe({ - next: (response) => this.alertService.success('Main convenor changed', 2000), - error: (response) => this.alertService.error(response, 6000), - }); + this.confirmationModalService.show( + 'Set Main Convenor', + `Do you want to make ${staff.user.name} the main convenor for this unit?`, + () => { + this.unit.changeMainConvenor(staff).subscribe({ + next: (_response) => this.alertService.success('Main convenor changed', 2000), + error: (response) => this.alertService.error(response, 6000), + }); + }, + ); } /** @@ -99,7 +130,7 @@ export class UnitStaffEditorComponent implements OnInit { } this.filteredStaff = this.staff.filter( (staff) => - staff.name.toLowerCase().includes(this.searchTerm.toLowerCase()) && // Find by name + staff.matches(this.searchTerm.toLowerCase()) && // Find by name !this.unit.staff.find((listStaff) => staff.id === listStaff.user.id), // Not already assigned to the unit ); } @@ -124,7 +155,7 @@ export class UnitStaffEditorComponent implements OnInit { */ removeStaff(staff: UnitRole) { this.unitRoleService.delete(staff, {cache: this.unit.staffCache}).subscribe({ - next: (response) => this.alertService.success('Staff member removed', 2000), + next: () => this.alertService.success('Staff member removed', 2000), error: (response) => this.alertService.error(response, 6000), }); } From e3c4e8cb61739b43f4a7f4a33972e9ac17e10d38 Mon Sep 17 00:00:00 2001 From: Andrew Cain Date: Thu, 3 Apr 2025 17:38:51 +1100 Subject: [PATCH 0643/1531] Merge branch 'migrate/confirmation-modal' of https://github.com/b0ink/doubtfire-web into b0ink-migrate/confirmation-modal --- .../confirmation-modal.coffee | 35 -------------- .../confirmation-modal.component.html | 20 ++++++++ .../confirmation-modal.component.scss | 0 .../confirmation-modal.component.ts | 47 +++++++++++++++++++ .../confirmation-modal.scss | 3 -- .../confirmation-modal.service.ts | 26 ++++++++++ .../confirmation-modal.tpl.html | 22 --------- src/app/common/modals/modals.coffee | 1 - src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 3 +- .../unit-task-editor.component.ts | 4 +- 11 files changed, 98 insertions(+), 65 deletions(-) delete mode 100644 src/app/common/modals/confirmation-modal/confirmation-modal.coffee create mode 100644 src/app/common/modals/confirmation-modal/confirmation-modal.component.html create mode 100644 src/app/common/modals/confirmation-modal/confirmation-modal.component.scss create mode 100644 src/app/common/modals/confirmation-modal/confirmation-modal.component.ts delete mode 100644 src/app/common/modals/confirmation-modal/confirmation-modal.scss create mode 100644 src/app/common/modals/confirmation-modal/confirmation-modal.service.ts delete mode 100644 src/app/common/modals/confirmation-modal/confirmation-modal.tpl.html diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.coffee b/src/app/common/modals/confirmation-modal/confirmation-modal.coffee deleted file mode 100644 index c7999098cf..0000000000 --- a/src/app/common/modals/confirmation-modal/confirmation-modal.coffee +++ /dev/null @@ -1,35 +0,0 @@ -angular.module("doubtfire.common.modals.confirmation-modal", []) - -.factory("ConfirmationModal", ($modal) -> - ConfirmationModal = {} - - # - # Show a modal asking the user to confirm their indicated action. - # - ConfirmationModal.show = (title, message, action) -> - modalInstance = $modal.open - templateUrl: 'common/modals/confirmation-modal/confirmation-modal.tpl.html' - controller: 'ConfirmationModalCtrl' - resolve: - title: -> title - message: -> message - action: -> action - - ConfirmationModal -) - -# -# Controller for confirmation modal -# -.controller('ConfirmationModalCtrl', ($scope, $modalInstance, title, message, action, alertService) -> - $scope.title = title - $scope.message = message - - $scope.confirmAction = -> - action() - $modalInstance.dismiss() - - $scope.cancelAction = -> - alertService.message "#{title} action cancelled", 3000 - $modalInstance.dismiss() -) diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.component.html b/src/app/common/modals/confirmation-modal/confirmation-modal.component.html new file mode 100644 index 0000000000..3ec07fc729 --- /dev/null +++ b/src/app/common/modals/confirmation-modal/confirmation-modal.component.html @@ -0,0 +1,20 @@ +
+

+
+ +
+
{{ title }}
+ Please confirm that you want to perform this action. +
+
+

+ + {{ message }} + + + + + +
diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.component.scss b/src/app/common/modals/confirmation-modal/confirmation-modal.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts b/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts new file mode 100644 index 0000000000..f9506e5b8b --- /dev/null +++ b/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts @@ -0,0 +1,47 @@ +import {Component, OnInit, Input, Inject} from '@angular/core'; +import {AlertService} from '../../services/alert.service'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; + +export interface ConfirmationModalData { + title: string; + message: string; + action?: any; +} + +@Component({ + selector: 'confirmation-modal', + templateUrl: './confirmation-modal.component.html', + styleUrls: ['./confirmation-modal.component.scss'], +}) +export class ConfirmationModalComponent implements OnInit { + @Input() title: string; + @Input() message: string; + @Input() action: () => void; + + constructor( + @Inject(AlertService) private alertService: AlertService, + @Inject(MAT_DIALOG_DATA) public data: ConfirmationModalData, + + public dialogRef: MatDialogRef, + ) {} + + ngOnInit(): void { + this.title = this.data.title; + this.message = this.data.message; + this.action = this.data.action; + } + + public confirmAction() { + if (typeof this.action === 'function') { + this.action(); + } else { + this.alertService.error(`${this.title} action failed.`); + } + this.dialogRef.close(); + } + + public cancelAction() { + this.alertService.success(`${this.title} action cancelled.`); + this.dialogRef.close(); + } +} diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.scss b/src/app/common/modals/confirmation-modal/confirmation-modal.scss deleted file mode 100644 index f30b0e345c..0000000000 --- a/src/app/common/modals/confirmation-modal/confirmation-modal.scss +++ /dev/null @@ -1,3 +0,0 @@ -.confirmation-modal .modal-body { - font-size: 1.5em; -} diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.service.ts b/src/app/common/modals/confirmation-modal/confirmation-modal.service.ts new file mode 100644 index 0000000000..6257277eff --- /dev/null +++ b/src/app/common/modals/confirmation-modal/confirmation-modal.service.ts @@ -0,0 +1,26 @@ +import {Injectable} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import {ConfirmationModalComponent, ConfirmationModalData} from './confirmation-modal.component'; + +@Injectable({ + providedIn: 'root', +}) +export class ConfirmationModalService { + constructor(public dialog: MatDialog) {} + + public show(title: string, message: string, action?: any) { + this.dialog.open( + ConfirmationModalComponent, + { + data: { + title, + message, + action, + }, + position: {top: '2.5%'}, + width: '100%', + maxWidth: '650px', + }, + ); + } +} diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.tpl.html b/src/app/common/modals/confirmation-modal/confirmation-modal.tpl.html deleted file mode 100644 index 4bd87f6868..0000000000 --- a/src/app/common/modals/confirmation-modal/confirmation-modal.tpl.html +++ /dev/null @@ -1,22 +0,0 @@ -
- - - -
diff --git a/src/app/common/modals/modals.coffee b/src/app/common/modals/modals.coffee index 16d2be1ec8..73aae8685b 100644 --- a/src/app/common/modals/modals.coffee +++ b/src/app/common/modals/modals.coffee @@ -1,5 +1,4 @@ angular.module("doubtfire.common.modals", [ 'doubtfire.common.modals.csv-result-modal' - 'doubtfire.common.modals.confirmation-modal' 'doubtfire.common.modals.comments-modal' ]) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 338e6591f4..88c2206141 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -97,6 +97,7 @@ import {ExtensionCommentComponent} from './tasks/task-comments-viewer/extension- import {CampusListComponent} from './admin/institution-settings/campuses/campus-list/campus-list.component'; import {ExtensionModalComponent} from './common/modals/extension-modal/extension-modal.component'; import {CalendarModalComponent} from './common/modals/calendar-modal/calendar-modal.component'; +import { ConfirmationModalComponent } from './common/modals/confirmation-modal/confirmation-modal.component'; import {MatRadioModule} from '@angular/material/radio'; import {MatButtonToggleModule} from '@angular/material/button-toggle'; import { @@ -301,6 +302,7 @@ import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-char OverseerImageListComponent, ExtensionModalComponent, CalendarModalComponent, + ConfirmationModalComponent, InstitutionSettingsComponent, HomeComponent, CommentBubbleActionComponent, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index bd638cbea8..76ae8c64c5 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -107,7 +107,6 @@ import 'build/src/app/units/states/students-list/students-list.js'; import 'build/src/app/units/states/analytics/analytics.js'; import 'build/src/app/common/filters/filters.js'; import 'build/src/app/common/content-editable/content-editable.js'; -import 'build/src/app/common/modals/confirmation-modal/confirmation-modal.js'; import 'build/src/app/common/modals/comments-modal/comments-modal.js'; import 'build/src/app/common/modals/csv-result-modal/csv-result-modal.js'; import 'build/src/app/common/modals/modals.js'; @@ -140,6 +139,7 @@ import {ExtensionCommentComponent} from './tasks/task-comments-viewer/extension- import {TaskAssessmentCommentComponent} from './tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component'; import {ExtensionModalService} from './common/modals/extension-modal/extension-modal.service'; import {CalendarModalService} from './common/modals/calendar-modal/calendar-modal.service'; +import { ConfirmationModalService } from './common/modals/confirmation-modal/confirmation-modal.service'; import {CampusListComponent} from './admin/institution-settings/campuses/campus-list/campus-list.component'; import {ActivityTypeListComponent} from './admin/institution-settings/activity-type-list/activity-type-list.component'; import {InstitutionSettingsComponent} from './admin/institution-settings/institution-settings.component'; @@ -241,6 +241,7 @@ DoubtfireAngularJSModule.factory('AboutDoubtfireModal', downgradeInjectable(Abou DoubtfireAngularJSModule.factory('DoubtfireConstants', downgradeInjectable(DoubtfireConstants)); DoubtfireAngularJSModule.factory('ExtensionModal', downgradeInjectable(ExtensionModalService)); DoubtfireAngularJSModule.factory('CalendarModal', downgradeInjectable(CalendarModalService)); +DoubtfireAngularJSModule.factory('ConfirmationModal', downgradeInjectable(ConfirmationModalService)); DoubtfireAngularJSModule.factory('TaskCommentService', downgradeInjectable(TaskCommentService)); DoubtfireAngularJSModule.factory('alertService', downgradeInjectable(AlertService)); DoubtfireAngularJSModule.factory('tutorialService', downgradeInjectable(TutorialService)); diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts index 72c309371d..bf4c3b626b 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts @@ -138,9 +138,7 @@ export class UnitTaskEditorComponent implements AfterViewInit { () => { this.unit.deleteTaskDefinition(taskDefinition); //TODO: reinstate ProgressModal.show "Deleting Task #{task.abbreviation}", 'Please wait while student projects are updated.', promise - - this.alerts.success('Task deleted'); - } + }, ); } From d9560c3b68df0a09f577cdab990d252b5cd24c58 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 22 Sep 2025 13:45:33 +1000 Subject: [PATCH 0644/1531] fix: check for valid unit --- .../unit-staff-editor/unit-staff-editor.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html index 82938cde3f..9f3a65b727 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html @@ -45,13 +45,13 @@

Unit Staff

@if (unitRole?.role === 'Convenor') { } From bfae1ad69bb767cdad47dd8fac35cc84e5134534 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 22 Sep 2025 13:45:33 +1000 Subject: [PATCH 0645/1531] fix: check for valid unit --- .../unit-staff-editor/unit-staff-editor.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html index 82938cde3f..9f3a65b727 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html @@ -45,13 +45,13 @@

Unit Staff

@if (unitRole?.role === 'Convenor') { } From bfbcee98cfa4888241c5956372d004ec1cd813cb Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 22 Sep 2025 14:49:36 +1000 Subject: [PATCH 0646/1531] feat: add observer only ui --- src/app/api/models/unit-role.ts | 1 + src/app/api/services/unit-role.service.ts | 3 ++- .../unit-staff-editor.component.html | 13 +++++++++++++ .../unit-staff-editor.component.ts | 16 +++++++++++++++- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/app/api/models/unit-role.ts b/src/app/api/models/unit-role.ts index 5868fa2f05..63bf9852de 100644 --- a/src/app/api/models/unit-role.ts +++ b/src/app/api/models/unit-role.ts @@ -11,6 +11,7 @@ export class UnitRole extends Entity { role: string; user: User; unit: Unit; + observerOnly: boolean; /** * The id for updated roles - but we need to move away from this to the role string... diff --git a/src/app/api/services/unit-role.service.ts b/src/app/api/services/unit-role.service.ts index 0100bb78ce..71cb194422 100644 --- a/src/app/api/services/unit-role.service.ts +++ b/src/app/api/services/unit-role.service.ts @@ -62,9 +62,10 @@ export class UnitRoleService extends CachedEntityService { return entity.unit?.id; }, }, + 'observerOnly', ); - this.mapping.addJsonKey('roleId', 'userId', 'unitId', 'role'); + this.mapping.addJsonKey('roleId', 'userId', 'unitId', 'role', 'observerOnly'); } public createInstanceFrom(json: any, other?: any): UnitRole { diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html index 9f3a65b727..ae0ca0114d 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html @@ -57,6 +57,19 @@

Unit Staff

} + + + Observer Only + + + + Actions diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts index 7c53a04671..f64d62d921 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts @@ -22,7 +22,7 @@ export class UnitStaffEditorComponent implements OnInit { filteredStaff: User[] = []; // Filtered staff members searchTerm: string = ''; // Search term entered by the user - displayedColumns: string[] = ['name', 'role', 'main-convenor', 'actions']; + displayedColumns: string[] = ['name', 'role', 'main-convenor', 'observer-only', 'actions']; dataSource = new MatTableDataSource(); // Inject services here @@ -73,6 +73,20 @@ export class UnitStaffEditorComponent implements OnInit { }); } + toggleObserverOnly(unitRole: UnitRole) { + const previousValue = unitRole.observerOnly; + unitRole.observerOnly = !unitRole.observerOnly; + unitRole.roleId = unitRole.role === 'Tutor' ? 2 : 3; + this.unitRoleService.update(unitRole).subscribe({ + next: () => this.alertService.success('Observer status updated', 2000), + error: (response) => { + // Revert changes on error + unitRole.observerOnly = previousValue; + this.alertService.error(response, 6000); + }, + }); + } + /** * Changes who the `Main Convenor` of the unit is. * From 75feec9c436a852c5e6ea69c93ae300d59cdaf38 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 22 Sep 2025 15:46:50 +1000 Subject: [PATCH 0647/1531] chore(release): 10.0.0-45 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45aefeb73a..755a8eecd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-45](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-44...v10.0.0-45) (2025-09-22) + + +### Bug Fixes + +* check for valid unit ([bfae1ad](https://github.com/b0ink/doubtfire-deploy/commit/bfae1ad69bb767cdad47dd8fac35cc84e5134534)) + ## [10.0.0-44](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-43...v10.0.0-44) (2025-09-18) ## [10.0.0-43](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-42...v10.0.0-43) (2025-09-17) diff --git a/package-lock.json b/package-lock.json index 3500ef85ca..a8b02747b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-44", + "version": "10.0.0-45", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-44", + "version": "10.0.0-45", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 6ba1706bec..1f9c61185e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-44", + "version": "10.0.0-45", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 01db5769b77ba2d6b8a3242935ba73481f16bf00 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 24 Sep 2025 09:13:32 +1000 Subject: [PATCH 0648/1531] refactor: use students preferred name in greeting chip --- src/app/api/models/user/user.ts | 9 +++++++++ .../task-feedback-templates.component.ts | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/app/api/models/user/user.ts b/src/app/api/models/user/user.ts index 4fc56c9349..03a281bf12 100644 --- a/src/app/api/models/user/user.ts +++ b/src/app/api/models/user/user.ts @@ -53,6 +53,15 @@ export class User extends Entity { return `${fn} ${sn}${nn}`; } + public get preferredName(): string { + const nickname = this.nickname.trim(); + const firstName = this.firstName.trim(); + if (nickname) { + return nickname; + } + return firstName; + } + public matches(text: string): boolean { return ( this.studentId?.toLowerCase().indexOf(text) >= 0 || diff --git a/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts b/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts index ae3453dbaf..696e5ecca9 100644 --- a/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts +++ b/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts @@ -191,7 +191,7 @@ export class TaskFeedbackTemplatesComponent implements OnInit, OnChanges { selectTemplate(template: FeedbackTemplate) { if (template.type === 'template') { if (template.chipText === 'Greeting') { - template.commentText = `Hi ${this.task.project.student.firstName}. `; + template.commentText = `Hi ${this.task.project.student.preferredName}. `; } else if (template.chipText === 'Summarise feedback') { if (!this.selectedTemplates || this.selectedTemplates.length < 1) return; template.commentText = 'Summary of the given feedback:'; From 568cb0e5730c9931225e750950506f42f6e6b4f8 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:06:49 +1000 Subject: [PATCH 0649/1531] chore: format --- .../task-due-card.component.html | 133 +++++++++--------- 1 file changed, 70 insertions(+), 63 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html index 28baa761d9..24a8d8c1c7 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html @@ -1,15 +1,19 @@ -@if ( (!task?.inFinalState() || (task?.inTimeExceeded() && !task?.isPastDeadline())) && !task?.inAwaitingFeedbackState() +@if ( + (!task?.inFinalState() || (task?.inTimeExceeded() && !task?.isPastDeadline())) && + !task?.inAwaitingFeedbackState() ) { -
- - @if (task?.isDueSoon() && !task?.isPastDueDate()) { - - - - Aim To Complete Soon - Due in {{ task?.timeUntilDueDateDescription() }} - - - +
+ + @if (task?.isDueSoon() && !task?.isPastDueDate()) { + + + + Aim To Complete Soon - Due in {{ task?.timeUntilDueDateDescription() }} + + + @if (flexibleDatesEnabled) {

Your target due date for this task is @@ -22,9 +26,9 @@ >. You should aim to complete this task before then to keep your progress on track.

} -
- - + + + @if (flexibleDatesEnabled) {

This target due date for this task is {{ task?.localDueDateString() }} } - - } + + } - - @if (task?.betweenDueDateAndDeadlineDate()) { + + @if (task?.betweenDueDateAndDeadlineDate()) { } - - - + + + @if (flexibleDatesEnabled) {

You should have completed this task by @@ -97,52 +101,54 @@

} @else {

- You should have completed this task by {{ task?.localDueDateString() }}. Make sure to discuss this task with your tutor as soon as possible. If this task remains on this state for an - extended period, it will be marked as Time Exceeded. + You should have completed this task by + {{ task?.localDueDateString() }}. Make sure to discuss this task with your tutor as soon as possible. If this task + remains on this state for an extended period, it will be marked as Time Exceeded.

- Tasks are only considered completed once your tutor has discussed your work - with you. + Tasks are only considered completed once your tutor has + discussed your work with you.

} +
+
+ } - - - } - - - @if (task?.isPastDeadline()) { - - - error - Passed Due Date By {{ task?.timePastDueDateDescription() }} - - - -

- You should have completed this task by {{ task?.localDueDateString() }}. This task is now past the deadline and will be marked as Time Exceeded when submitted. You should - consult with the unit assessment details to determine the impact of failing to complete this task within the - allocated time. -

-
- - -

- You should have completed this task by {{ task?.localDueDateString() }}. Make sure to discuss this task with your tutor as soon as possible. -

-

- Tasks are only considered Completed once it demonstrates the required standard, and it is - discussed with your tutor. -

-
-
- } -
+ + @if (task?.isPastDeadline()) { + + + error + Passed Due Date By {{ task?.timePastDueDateDescription() }} + + + +

+ You should have completed this task by {{ task?.localDueDateString() }}. This task is now past the deadline and will be marked as Time Exceeded when + submitted. You should consult with the unit assessment details to determine the impact + of failing to complete this task within the allocated time. +

+
+ + +

+ You should have completed this task by {{ task?.localDueDateString() }}. Make sure to discuss this task with your tutor as soon as possible. +

+

+ Tasks are only considered Completed once it demonstrates the required + standard, and it is discussed with your tutor. +

+
+
+ } +
} @@ -154,7 +160,8 @@

You have submitted this task and should now wait for feedback from your tutor. Do not re-upload new files at this time as the status will be changed to Time Exceeded.Do not re-upload new files at this time as the status will be changed to + Time Exceeded.

From 3bf25e77fb9d64fb1ef9801967d69357ff209354 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:23:27 +1000 Subject: [PATCH 0650/1531] refactor: change overdue task wording for assess in portfolio states --- .../task-due-card/task-due-card.component.html | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html index 24a8d8c1c7..83bc582179 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html @@ -129,10 +129,20 @@

- You should have completed this task by {{ task?.localDueDateString() }}. This task is now past the deadline and will be marked as Time Exceeded when - submitted. You should consult with the unit assessment details to determine the impact - of failing to complete this task within the allocated time. + @if (task?.taskDefinition?.unit.markLateSubmissionsAsAssessInPortfolio) { + You should have completed this task by + {{ task?.localDueDateString() }}. This task is now past the deadline and can only be submitted directly for your + portfolio without feedback. You should consult with the unit assessment details to + determine the impact of failing to complete this task within the allocated time. + } @else { + You should have completed this task by + {{ task?.localDueDateString() }}. This task is now past the deadline and will be marked as + Time Exceeded when submitted. You should consult with the unit assessment + details to determine the impact of failing to complete this task within the allocated + time. + }

From e5b15713c1d133d4e8a55c70249fcbf28294530b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 24 Sep 2025 12:31:04 +1000 Subject: [PATCH 0651/1531] chore: return confirmation modal reference --- .../confirmation-modal/confirmation-modal.service.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.service.ts b/src/app/common/modals/confirmation-modal/confirmation-modal.service.ts index 6257277eff..660ddec60c 100644 --- a/src/app/common/modals/confirmation-modal/confirmation-modal.service.ts +++ b/src/app/common/modals/confirmation-modal/confirmation-modal.service.ts @@ -1,5 +1,5 @@ import {Injectable} from '@angular/core'; -import {MatDialog} from '@angular/material/dialog'; +import {MatDialog, MatDialogRef} from '@angular/material/dialog'; import {ConfirmationModalComponent, ConfirmationModalData} from './confirmation-modal.component'; @Injectable({ @@ -8,8 +8,12 @@ import {ConfirmationModalComponent, ConfirmationModalData} from './confirmation- export class ConfirmationModalService { constructor(public dialog: MatDialog) {} - public show(title: string, message: string, action?: any) { - this.dialog.open( + public show( + title: string, + message: string, + action?: any, + ): MatDialogRef { + return this.dialog.open( ConfirmationModalComponent, { data: { From 75172ba67d3eb5f83c7421fec7464298efb7c8ee Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 24 Sep 2025 12:31:33 +1000 Subject: [PATCH 0652/1531] refactor: require confirmation for enabling assess in portfolio for late submissions --- .../unit-details-editor.coffee | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.coffee b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.coffee index a93c83b0ed..8049804f32 100644 --- a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.coffee +++ b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.coffee @@ -8,7 +8,7 @@ angular.module('doubtfire.units.states.edit.directives.unit-details-editor', []) replace: true restrict: 'E' templateUrl: 'units/states/edit/directives/unit-details-editor/unit-details-editor.tpl.html' - controller: ($scope, $state, $rootScope, DoubtfireConstants, newUnitService, alertService, newTeachingPeriodService, TaskSubmission, D2lUnitDetailsModal) -> + controller: ($scope, $timeout, $state, $rootScope, DoubtfireConstants, newUnitService, alertService, newTeachingPeriodService, TaskSubmission, D2lUnitDetailsModal, ConfirmationModal) -> $scope.overseerEnabled = DoubtfireConstants.IsOverseerEnabled $scope.calOptions = { @@ -83,6 +83,28 @@ angular.module('doubtfire.units.states.edit.directives.unit-details-editor', []) $scope.d2lEnabled = -> DoubtfireConstants.IsD2LEnabled.value + updatingAssessInPortfolio = false + $scope.$watch 'unit.markLateSubmissionsAsAssessInPortfolio', (newVal, oldVal) -> + return if newVal is oldVal or newVal == false or updatingAssessInPortfolio + updatingAssessInPortfolio = true + $scope.unit.markLateSubmissionsAsAssessInPortfolio = false + modal = ConfirmationModal.show( + 'Enable Assess in Portfolio?', + """ + Are you sure you want to enable "Assess in Portfolio" for late submissions? + This will update any existing Time/Feedback Exceeded tasks to the "Assess in Portfolio" state. + You will not be able to disable this setting while any tasks remain in the "Assess in Portfolio" state. + """ + () -> + $scope.unit.markLateSubmissionsAsAssessInPortfolio = true + $timeout -> + updatingAssessInPortfolio = false + ) + + modal.afterClosed().subscribe(() -> + $timeout -> + updatingAssessInPortfolio = false + ) ) From 29fffd36c437218491ef0bdffc4eb4969f5d4357 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 24 Sep 2025 14:38:38 +1000 Subject: [PATCH 0653/1531] chore: reword automated assess in portfolio message --- src/app/common/footer/footer.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/common/footer/footer.component.ts b/src/app/common/footer/footer.component.ts index 6d712f071c..a53bc9700e 100644 --- a/src/app/common/footer/footer.component.ts +++ b/src/app/common/footer/footer.component.ts @@ -78,7 +78,7 @@ export class FooterComponent implements OnInit { return; } task.addComment( - `**Automated Message:** Task "${task.definition.abbreviation} ${task.definition.name}" will be graded during portfolio assessment only. You must now submit it directly for portfolio assessment before the portfolio deadline.`, + `**Automated Message:** Task "${task.definition.abbreviation} ${task.definition.name}" will be graded during portfolio assessment only. You can keep submitting it for feedback before the task deadline, but you must still submit it directly for portfolio assessment before the portfolio deadline.`, ); setTimeout(() => { task.updateTaskStatus('working_on_it'); From e59e56f290d457ebb5c5c577128aeb9001942269 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 24 Sep 2025 14:49:33 +1000 Subject: [PATCH 0654/1531] chore: remove sentence regarding impact of late submission --- .../directives/task-due-card/task-due-card.component.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html index 83bc582179..3f3d5c6c6b 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html @@ -133,8 +133,7 @@ You should have completed this task by {{ task?.localDueDateString() }}. This task is now past the deadline and can only be submitted directly for your - portfolio without feedback. You should consult with the unit assessment details to - determine the impact of failing to complete this task within the allocated time. + portfolio without feedback. } @else { You should have completed this task by {{ task?.localDueDateString() }} Date: Wed, 24 Sep 2025 14:52:52 +1000 Subject: [PATCH 0655/1531] chore(release): 10.0.0-46 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 755a8eecd9..a02838d827 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-46](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-45...v10.0.0-46) (2025-09-24) + ## [10.0.0-45](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-44...v10.0.0-45) (2025-09-22) diff --git a/package-lock.json b/package-lock.json index a8b02747b3..199a950d63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-45", + "version": "10.0.0-46", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-45", + "version": "10.0.0-46", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 1f9c61185e..12ccc6d73b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-45", + "version": "10.0.0-46", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From e122a6464b89ee8a5f2a17b2ff4c8e0bd5947fe7 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 24 Sep 2025 17:08:12 +1000 Subject: [PATCH 0656/1531] chore: require confirmation for assess in portfolio only option --- .../task-definition-options.component.html | 6 ++++- .../task-definition-options.component.ts | 27 ++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html index b846a681a5..6ef203ae27 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html @@ -10,7 +10,11 @@
- Assess in Portfolio Only diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts index 7fc62fa813..80a26895c1 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts @@ -1,6 +1,7 @@ -import { Component, Input } from '@angular/core'; -import { TaskDefinition } from 'src/app/api/models/task-definition'; -import { Unit } from 'src/app/api/models/unit'; +import {Component, Input} from '@angular/core'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {Unit} from 'src/app/api/models/unit'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; @Component({ selector: 'f-task-definition-options', @@ -9,8 +10,28 @@ import { Unit } from 'src/app/api/models/unit'; }) export class TaskDefinitionOptionsComponent { @Input() taskDefinition: TaskDefinition; + constructor(private confirmationModal: ConfirmationModalService) {} public get unit(): Unit { return this.taskDefinition?.unit; } + + public onToggleAssessInPortfolioOnly() { + if (!this.taskDefinition.assessInPortfolioOnly) { + return; + } + + setTimeout(() => { + this.taskDefinition.assessInPortfolioOnly = false; + console.log(this.taskDefinition.assessInPortfolioOnly); + + this.confirmationModal.show( + `Enable Assess in Portfolio Only?`, + `Enabling Assess in Portfolio Only will update all overdue tasks for ${this.taskDefinition.name} to the Assess in Portfolio state`, + () => { + this.taskDefinition.assessInPortfolioOnly = true; + }, + ); + }); + } } From db1ad9b8b6bde544d1e1dfc9cbe3fe3b5c79fff5 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:42:34 +1000 Subject: [PATCH 0657/1531] refactor: migrate unit details editor (#1007) * refactor: init unit details editor migration * refactor: migrate unit details editor * refactor: migrate assess in portfolio confirmation * refactor: display teaching period dates when selected * refactor: add draft learning summary hint * chore: remove old unit details editor files * chore: remove debug logs --- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 7 +- .../states/edit/directives/directives.coffee | 1 - .../unit-details-editor.coffee | 112 ---- .../unit-details-editor.component.html | 212 ++++++++ .../unit-details-editor.component.scss | 0 .../unit-details-editor.component.ts | 109 ++++ .../unit-details-editor.tpl.html | 501 ------------------ src/app/units/states/edit/edit.tpl.html | 2 +- 9 files changed, 330 insertions(+), 616 deletions(-) delete mode 100644 src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.coffee create mode 100644 src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html create mode 100644 src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.scss create mode 100644 src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts delete mode 100644 src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.tpl.html diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 0e370154ff..cfea5a77ad 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -288,6 +288,7 @@ import {TaskPrerequisiteService} from './api/services/task-prerequisite.service' // import { PrivacyPolicy } from './config/privacy-policy/privacy-policy'; import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; +import {UnitDetailsEditorComponent} from './units/states/edit/directives/unit-details-editor/unit-details-editor.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -438,6 +439,7 @@ const MY_DATE_FORMAT = { TaskPrerequisitesCardComponent, UnitStaffEditorComponent, GroupSetSelectorComponent, + UnitDetailsEditorComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 223544d7bf..abf5a9ff2f 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -100,7 +100,6 @@ import 'build/src/app/units/states/portfolios/portfolios.js'; import 'build/src/app/units/states/groups/groups.js'; import 'build/src/app/units/states/states.js'; import 'build/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.js'; -import 'build/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.js'; import 'build/src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.js'; import 'build/src/app/units/states/edit/directives/directives.js'; import 'build/src/app/units/states/edit/edit.js'; @@ -230,6 +229,7 @@ import {TaskPrerequisitesCardComponent} from './projects/states/dashboard/direct // import { PrivacyPolicy } from './config/privacy-policy/privacy-policy'; import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; +import {UnitDetailsEditorComponent} from './units/states/edit/directives/unit-details-editor/unit-details-editor.component'; export const DoubtfireAngularJSModule = angular .module('doubtfire', [ @@ -520,6 +520,11 @@ DoubtfireAngularJSModule.directive( downgradeComponent({component: TaskPrerequisitesCardComponent}), ); +DoubtfireAngularJSModule.directive( + 'unitDetailsEditor', + downgradeComponent({component: UnitDetailsEditorComponent}), +); + // Global configuration // If the user enters a URL that doesn't match any known URL (state), send them to `/home` diff --git a/src/app/units/states/edit/directives/directives.coffee b/src/app/units/states/edit/directives/directives.coffee index fe06bf4510..4da41cacfb 100644 --- a/src/app/units/states/edit/directives/directives.coffee +++ b/src/app/units/states/edit/directives/directives.coffee @@ -1,5 +1,4 @@ angular.module('doubtfire.units.states.edit.directives', [ - 'doubtfire.units.states.edit.directives.unit-details-editor' 'doubtfire.units.states.edit.directives.unit-group-set-editor' 'doubtfire.units.states.edit.directives.unit-ilo-editor' ]) diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.coffee b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.coffee deleted file mode 100644 index 8049804f32..0000000000 --- a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.coffee +++ /dev/null @@ -1,112 +0,0 @@ -angular.module('doubtfire.units.states.edit.directives.unit-details-editor', []) - -# -# Editor for the basic details of a unit, such as the name, code -# start and end dates etc. -# -.directive('unitDetailsEditor', -> - replace: true - restrict: 'E' - templateUrl: 'units/states/edit/directives/unit-details-editor/unit-details-editor.tpl.html' - controller: ($scope, $timeout, $state, $rootScope, DoubtfireConstants, newUnitService, alertService, newTeachingPeriodService, TaskSubmission, D2lUnitDetailsModal, ConfirmationModal) -> - $scope.overseerEnabled = DoubtfireConstants.IsOverseerEnabled - - $scope.calOptions = { - startOpened: false - endOpened: false - portfolioAutoGenerationOpened: false - } - - # Get docker images available for automated task assessment for the unit. - TaskSubmission.getDockerImagesAsPromise().then (images) -> - $scope.dockerImages = images - - # Get the confugurable, external name of Doubtfire - $scope.externalName = DoubtfireConstants.ExternalName - - # get the teaching periods- gets an object with the loaded teaching periods - newTeachingPeriodService.query().subscribe((periods) -> - $scope.teachingPeriods = periods - $scope.teachingPeriodValues = [{value: undefined, text: "None"}] - other = _.map periods, (p) -> {value: p, text: "#{p.year} #{p.period}"} - _.each other, (d) -> $scope.teachingPeriodValues.push(d) - ) - - $scope.teachingPeriodSelected = ($event) -> - $scope.unit.teachingPeriod = $event - - $scope.unit.taskDefinitionCache.values.subscribe( - (taskDefs) -> - $scope.taskDefinitionValues = [{value: undefined, text: "None"}] - other = _.map taskDefs, (td) -> {value: td, text: "#{td.abbreviation}-#{td.name}"} - _.each other, (d) -> $scope.taskDefinitionValues.push(d) - ) - - $scope.draftTaskDefSelected = ($event) -> - $scope.unit.draftTaskDefinition = $event - - # Datepicker opener - $scope.open = ($event, pickerData) -> - $event.preventDefault() - $event.stopPropagation() - - if pickerData == 'start' - $scope.calOptions.startOpened = ! $scope.calOptions.startOpened - $scope.calOptions.endOpened = false - $scope.calOptions.portfolioAutoGenerationOpened = false - else if pickerData == 'end' - $scope.calOptions.startOpened = false - $scope.calOptions.endOpened = ! $scope.calOptions.endOpened - $scope.calOptions.portfolioAutoGenerationOpened = false - else if pickerData == 'autogen' - $scope.calOptions.startOpened = false - $scope.calOptions.endOpened = false - $scope.calOptions.portfolioAutoGenerationOpened = ! $scope.calOptions.portfolioAutoGenerationOpened - - $scope.dateOptions = { - formatYear: 'yy', - startingDay: 1 - } - $scope.studentSearch = "" - - $scope.saveUnit = -> - newUnitService.update($scope.unit).subscribe({ - next: (unit) -> - alertService.success( "Unit updated.", 2000) - error: (response) -> - alertService.error( "Failed to update unit. #{response}", 6000) - }) - - $scope.addD2lData = -> - D2lUnitDetailsModal.open($scope.unit) - - $scope.d2lEnabled = -> - DoubtfireConstants.IsD2LEnabled.value - - updatingAssessInPortfolio = false - $scope.$watch 'unit.markLateSubmissionsAsAssessInPortfolio', (newVal, oldVal) -> - return if newVal is oldVal or newVal == false or updatingAssessInPortfolio - updatingAssessInPortfolio = true - $scope.unit.markLateSubmissionsAsAssessInPortfolio = false - modal = ConfirmationModal.show( - 'Enable Assess in Portfolio?', - """ - Are you sure you want to enable "Assess in Portfolio" for late submissions? - This will update any existing Time/Feedback Exceeded tasks to the "Assess in Portfolio" state. - You will not be able to disable this setting while any tasks remain in the "Assess in Portfolio" state. - """ - () -> - $scope.unit.markLateSubmissionsAsAssessInPortfolio = true - $timeout -> - updatingAssessInPortfolio = false - ) - - modal.afterClosed().subscribe(() -> - $timeout -> - updatingAssessInPortfolio = false - ) -) - - - - diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html new file mode 100644 index 0000000000..7ee30534e9 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html @@ -0,0 +1,212 @@ +
+
+

Unit Details

+

Edit and configure all details and settings for this unit.

+
+ + + Code + + + + + Name + + + + + Description + + + + + + + Teaching Period + + None + @for (period of teachingPeriods; track period) { + {{ period.name }} + } + + + +
+ @if (!unit.teachingPeriod) { + + Start Date + + + + + + End Date + + + + + } @else { + + {{ unit.teachingPeriod.name }} Start Date + + + + {{ unit.teachingPeriod.name }} End Date + + + } +
+ + + Portfolio Auto-Generation Date + + + + + + + Draft Learning Summary + + None + @for (td of taskDefinitions; track td) { + {{ td.abbreviation }} - {{ td.name }} + } + + + When a draft learning summary task is selected, this will ensure a students uploaded draft + is automatically added to the students portfolio. + + + + + Extension duration onresubmit + + + When tutors request resubmission of a task, this setting determines how many weeks the task + will be extended to allow students to fix and resubmit their work. + + +
+ + +
+ Allow flexible dates +

Allows students to set planned due dates, without using extensions.

+
+ +
+ Allow student extensions +

When false only staff can request extensions on behalf of students.

+
+ +
+ Auto apply extensions +

+ When true, extensions will be automatically applied when they result in a date that is + between the task's due date and deadline. +

+
+ +
+ Has tasks assessed in portfolio +

+ When enabled, late submissions will not be automatically marked as "Time Exceeded" or + "Feedback Exceeded", and will instead appear as "Assess in Portfolio". Tutors can still sign + off tasks as complete unless the task definition has the "Assess in Portfolio Only" option + enabled. +

+
+ +
+ Allow students to change tutorial +

When false only staff can change student tutorials.

+
+ +
+ Send notification emails +

+ When true, emails will be set to students each week to indicate progress and suggest future + tasks for them to work on. +

+
+ +
+ Synchronise enrolments +

+ When true student enrolments will be synchronised with other systems where this is possible. +

+
+ +
+ Synchronise timetable +

+ When true timetable data will be synchronised with other systems where this is possible. +

+
+ +
+ Active +

Set to false to hide unit from students and tutors.

+
+
+ + @if (overseerEnabled.value) { + +
+ Overseer assessment +

If true, unit tasks will be able to make use of Overseer automated checking.

+
+ + + Overseer Docker Image + + @for (image of dockerImages; track image) { + {{ image.description }} + } + + Use this to select the default container used to check tasks with Overseer. + +
+ } + +
+ + + +
+
diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.scss b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts new file mode 100644 index 0000000000..0ea300bf8e --- /dev/null +++ b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts @@ -0,0 +1,109 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {MatSlideToggleChange} from '@angular/material/slide-toggle'; +import {OverseerImage, UnitService} from 'src/app/api/models/doubtfire-model'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {TeachingPeriod} from 'src/app/api/models/teaching-period'; +import {Unit} from 'src/app/api/models/unit'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {TeachingPeriodService} from 'src/app/api/services/teaching-period.service'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {TaskSubmissionService} from 'src/app/common/services/task-submission.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {D2lUnitDetailsModal} from './d2l-details-form/d2l-unit-details-form.component'; + +@Component({ + selector: 'f-unit-details-editor', + templateUrl: 'unit-details-editor.component.html', + styleUrls: ['unit-details-editor.component.scss'], +}) +export class UnitDetailsEditorComponent implements OnInit { + @Input() unit: Unit; + + constructor( + private teachingPeriodService: TeachingPeriodService, + private taskDefinitionService: TaskDefinitionService, + private doubtfireConstants: DoubtfireConstants, + private taskSubmissionService: TaskSubmissionService, + private d2lUnitDetailsModal: D2lUnitDetailsModal, + private unitService: UnitService, + private alertsService: AlertService, + private confirmationModal: ConfirmationModalService, + ) {} + + public teachingPeriods: TeachingPeriod[]; + public taskDefinitions: TaskDefinition[]; + public dockerImages: OverseerImage[]; + + public get overseerEnabled() { + return this.doubtfireConstants.IsOverseerEnabled; + } + + public get d2lEnabled() { + return this.doubtfireConstants.IsD2LEnabled; + } + + ngOnInit(): void { + this.teachingPeriodService.query().subscribe((periods) => { + this.teachingPeriods = periods; + }); + + this.unit.taskDefinitionCache.values.subscribe((taskDefs) => { + this.taskDefinitions = taskDefs; + }); + + this.taskSubmissionService.getDockerImagesAsPromise().then((images) => { + this.dockerImages = images; + }); + } + + addD2lData() { + this.d2lUnitDetailsModal.open(this.unit); + } + + saveUnit() { + this.unitService.update(this.unit).subscribe({ + next: (_unit) => { + this.alertsService.success('Unit updated.', 2000); + }, + error: (response) => { + this.alertsService.error(`Failed to update unit. ${response}`, 6000); + }, + }); + } + + private updatingAssessInPortfolio: boolean = false; + + onToggleAssessInPortfolio(event: MatSlideToggleChange) { + if (!event.checked || this.updatingAssessInPortfolio) { + return false; + } + + if (this.updatingAssessInPortfolio) { + return; + } + + this.updatingAssessInPortfolio = true; + + setTimeout(() => { + this.unit.markLateSubmissionsAsAssessInPortfolio = false; + const modal = this.confirmationModal.show( + 'Enable Assess in Portfolio?', + `Are you sure you want to enable "Assess in Portfolio" for late submissions? + This will update any existing Time/Feedback Exceeded tasks to the "Assess in Portfolio" state. + You will not be able to disable this setting while any tasks remain in the "Assess in Portfolio" state.`, + () => { + this.unit.markLateSubmissionsAsAssessInPortfolio = true; + setTimeout(() => { + this.updatingAssessInPortfolio = false; + }); + }, + ); + modal.afterClosed().subscribe(() => { + setTimeout(() => { + this.updatingAssessInPortfolio = false; + }); + }); + }); + } +} diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.tpl.html b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.tpl.html deleted file mode 100644 index 5de919ee03..0000000000 --- a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.tpl.html +++ /dev/null @@ -1,501 +0,0 @@ -
-
-
-

Create Unit

- Create a new unit with all overview unit details here. -
-
-

Update Unit

- Update overview details of the unit below. -
-
-
-
- -
- -
-
- - -
- -
- -
-
- - -
- -
- -
-
- - -
- -
- -
-
- - -
- -
- - - - When a draft learning summary task is selected, this will ensure a students uploaded draft is - automatically added to the students portfolio. - -
-
- - -
- -
-
- - - - - -
-
-
- - -
- -
-
- - - - - -
-
-
- - -
- -
-
- - - - -
-
-
- - -
- -
-
- - -
- Allows students to set planned due dates, without using extensions. -
-
- - -
- -
-
- - -
- When false only staff can request extensions on behalf of students. -
-
- - -
- -
- - - When tutors request resubmission of a task, this setting determines how many weeks the task will be - extended to allow students to fix and resubmit their work. - -
-
- - -
- -
-
- - -
- - When true, extensions will be automatically applied when they result in a date that is between the task's - due date and deadline. - -
-
- - -
- -
-
- - -
- - When enabled, late submissions will not be automatically marked as "Time Exceeded" or - "Feedback Exceeded", and will instead appear as "Assess in Portfolio". Tutors can - still sign off tasks as complete unless the task definition has the "Assess in - Portfolio Only" option enabled. - -
-
- - -
- -
-
- - -
- When false only staff can change student tutorials. -
-
- - -
- -
-
- - -
- - When true, emails will be set to students each week to indicate progress and suggest future tasks for them - to work on. - -
-
- - -
- -
-
- - -
- - When true student enrolments will be synchronised with other systems where this is possible. - -
-
- - -
- -
-
- - -
- - When true timetable data will be synchronised with other systems where this is possible. - -
-
- - -
- -
-
- - -
- - If true, unit tasks will be able to make use of Overseer automated checking. - -
-
- -
- -
- -
-
- -
-
diff --git a/src/app/units/states/edit/edit.tpl.html b/src/app/units/states/edit/edit.tpl.html index 4df8bf3d09..8a0dc37d52 100644 --- a/src/app/units/states/edit/edit.tpl.html +++ b/src/app/units/states/edit/edit.tpl.html @@ -4,7 +4,7 @@ {{tab.title}} - + From 04d3178e2e37a64c14109deaacb188056e07f225 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 25 Sep 2025 15:13:29 +1000 Subject: [PATCH 0658/1531] chore(release): 10.0.0-47 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a02838d827..ae329af052 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-47](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-46...v10.0.0-47) (2025-09-25) + + +### Features + +* add observer only ui ([bfbcee9](https://github.com/b0ink/doubtfire-deploy/commit/bfbcee98cfa4888241c5956372d004ec1cd813cb)) + ## [10.0.0-46](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-45...v10.0.0-46) (2025-09-24) ## [10.0.0-45](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-44...v10.0.0-45) (2025-09-22) diff --git a/package-lock.json b/package-lock.json index 199a950d63..4b1491ce8c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-46", + "version": "10.0.0-47", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-46", + "version": "10.0.0-47", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 12ccc6d73b..056ce41ad1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-46", + "version": "10.0.0-47", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 10e8ab033469c2dd4e78d125cb8fcfe0127cbf88 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Fri, 3 Oct 2025 14:55:31 +1000 Subject: [PATCH 0659/1531] refactor: migrate portfolio grade select step (#1014) * Frontend migration of portfolio-grade-select-step to Angular 17 component * Addressed review comments in portfolio-grade-select-step component * Implement OnInit in PortfolioGradeSelectStepComponent * replaced bootsrap UI component with Angular material * chore: bring back deleted lines * refactor: replace css with tailwind * chore: revert import order * chore: revert import order * chore: revert import order * chore: revert order * refactor: simplify grade changing --------- Co-authored-by: Pasindu Fernando <116358471+Pasindufdo98@users.noreply.github.com> --- src/app/doubtfire-angular.module.ts | 7 +- src/app/doubtfire-angularjs.module.ts | 7 +- .../portfolio/directives/directives.coffee | 1 - .../portfolio-grade-select-step.coffee | 19 ---- ...portfolio-grade-select-step.component.html | 96 +++++++++++++++++++ ...portfolio-grade-select-step.component.scss | 0 .../portfolio-grade-select-step.component.ts | 57 +++++++++++ .../portfolio-grade-select-step.scss | 10 -- .../portfolio-grade-select-step.tpl.html | 60 ------------ .../states/portfolio/portfolio.tpl.html | 6 +- 10 files changed, 168 insertions(+), 95 deletions(-) delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee create mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html create mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.scss create mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.scss delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index cfea5a77ad..369039dfbc 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -283,12 +283,12 @@ import {LtiService} from './api/services/lti.service'; import {TaskDefinitionPrerequisitesComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component'; import {TaskPrerequisitesCardComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-prerequisites-card/task-prerequisites-card.component'; import {TaskPrerequisiteService} from './api/services/task-prerequisite.service'; -// import { GradeIconComponent } from './common/grade-icon/grade-icon.component'; -// import { GradeTaskModalComponent } from './tasks/modals/grade-task-modal/grade-task-modal.component'; -// import { PrivacyPolicy } from './config/privacy-policy/privacy-policy'; +// import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; +// import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; import {UnitDetailsEditorComponent} from './units/states/edit/directives/unit-details-editor/unit-details-editor.component'; +import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -440,6 +440,7 @@ const MY_DATE_FORMAT = { UnitStaffEditorComponent, GroupSetSelectorComponent, UnitDetailsEditorComponent, + PortfolioGradeSelectStepComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index abf5a9ff2f..963bf7d209 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -72,7 +72,6 @@ import 'build/src/app/projects/states/outcomes/outcomes.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.js'; -import 'build/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.js'; import 'build/src/app/projects/states/portfolio/directives/directives.js'; @@ -230,6 +229,7 @@ import {TaskPrerequisitesCardComponent} from './projects/states/dashboard/direct import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; import {UnitDetailsEditorComponent} from './units/states/edit/directives/unit-details-editor/unit-details-editor.component'; +import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; export const DoubtfireAngularJSModule = angular .module('doubtfire', [ @@ -525,6 +525,11 @@ DoubtfireAngularJSModule.directive( downgradeComponent({component: UnitDetailsEditorComponent}), ); +DoubtfireAngularJSModule.directive( + 'fPortfolioGradeSelectStep', + downgradeComponent({component: PortfolioGradeSelectStepComponent}), +); + // Global configuration // If the user enters a URL that doesn't match any known URL (state), send them to `/home` diff --git a/src/app/projects/states/portfolio/directives/directives.coffee b/src/app/projects/states/portfolio/directives/directives.coffee index 8ce9be0be3..661acd16e7 100644 --- a/src/app/projects/states/portfolio/directives/directives.coffee +++ b/src/app/projects/states/portfolio/directives/directives.coffee @@ -1,6 +1,5 @@ angular.module('doubtfire.projects.states.portfolio.directives', [ 'doubtfire.projects.states.portfolio.directives.portfolio-add-extra-files-step' - 'doubtfire.projects.states.portfolio.directives.portfolio-grade-select-step' 'doubtfire.projects.states.portfolio.directives.portfolio-learning-summary-report-step' 'doubtfire.projects.states.portfolio.directives.portfolio-review-step' 'doubtfire.projects.states.portfolio.directives.portfolio-tasks-step' diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee deleted file mode 100644 index d29d0f65da..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee +++ /dev/null @@ -1,19 +0,0 @@ -angular.module('doubtfire.projects.states.portfolio.directives.portfolio-grade-select-step', []) - -# -# Allows students to select the target grade they are hoping -# to achieve with their portfolio -# -.directive('portfolioGradeSelectStep', -> - restrict: 'E' - replace: true - templateUrl: 'projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html' - controller: ($scope, newProjectService, gradeService) -> - $scope.grades = gradeService.grades - $scope.agreedToAssessmentCriteria = $scope.projectHasLearningSummaryReport() - $scope.chooseGrade = (idx) -> - $scope.project.submittedGrade = idx - newProjectService.update($scope.project).subscribe((project) -> - $scope.project.refreshBurndownChartData() - ) -) diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html new file mode 100644 index 0000000000..63385d6e5d --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html @@ -0,0 +1,96 @@ +
+ + + + +

Select Grade

+
+
+ + +

+ In preparing your portfolio, you need to undertake a self-assessment. Use the unit's + assessment criteria to determine the grade your portfolio should be awarded. +

+ + + + + + warning + Read the assessment criteria + + + + +

+ Make sure that you have reviewed the Assessment Criteria for the grade you are applying + for. Each grade will have a list of criteria that you can use to determine if you meet + the requirements to achieve that grade. +

+
+ + + + I have read the Assessment Criteria for this unit + + +
+ + + + @if (agreedToAssessmentCriteria) { + + + + Grade Application + + + + +

+ Select the grade you are applying for {{ unit.code }} + {{ unit.name }} below. +

+
+ + + + @for (grade of gradeValues; track grade) { + + + + } + + +

+ Make sure your Learning Summary Report justifies how your portfolio + demonstrates you have + met all unit learning outcomes to a {{ targetGrade }} level +

+
+
+ } +
+ + + + + + +
+
diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.scss b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts new file mode 100644 index 0000000000..cce8ee1748 --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts @@ -0,0 +1,57 @@ +import {Component, Injector, Input} from '@angular/core'; +import {Project, Unit} from 'src/app/api/models/doubtfire-model'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {GradeService} from 'src/app/common/services/grade.service'; + +@Component({ + selector: 'f-portfolio-grade-select-step', + templateUrl: 'portfolio-grade-select-step.component.html', + styleUrls: ['portfolio-grade-select-step.component.scss'], +}) +export class PortfolioGradeSelectStepComponent { + @Input() project: Project; + @Input() unit: Unit; + + public agreedToAssessmentCriteria: boolean = false; + + constructor( + private gradeService: GradeService, + private injector: Injector, + private projectService: ProjectService, + ) { + this.$scope = this.injector.get('$scope'); + } + + public get gradeValues() { + return this.gradeService.gradeValues; + } + + updateSubmittedGrade(newGrade: number): void { + const previousSubmittedGrade = this.project.submittedGrade; + this.project.submittedGrade = newGrade; + + this.projectService.update(this.project).subscribe( + (project) => { + project.refreshBurndownChartData?.(); + }, + (error) => { + this.project.submittedGrade = previousSubmittedGrade; + console.error('Error updating target grade:', error); + }, + ); + } + + // TODO: remove this once parent component has been migrated + private $scope: any; + goToNextStep(): void { + if (typeof this.$scope?.advanceActiveTab === 'function') { + this.$scope.advanceActiveTab(1); + } + } + + goToPreviousStep(): void { + if (typeof this.$scope?.advanceActiveTab === 'function') { + this.$scope.advanceActiveTab(-1); + } + } +} diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.scss b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.scss deleted file mode 100644 index bfc229c4b1..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.scss +++ /dev/null @@ -1,10 +0,0 @@ -.project-portfolio-wizard .portfolio-grade-select-step { - .confirm-read-assessment-criteria { - font-size: 1.2em; - } - .select-the-grade { - .btn { - padding: 1em; - } - } -} diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html deleted file mode 100644 index 5e512edf25..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html +++ /dev/null @@ -1,60 +0,0 @@ -
-
-

Select Grade

-
-
-

- In preparing your portfolio, you need to undertake a self assessment. Use the unit's assessment criteria to - determine the grade your portfolio should be awarded. -

-
-
-

Read the assessment criteria

- Make sure that you have reviewed the Assessment Criteria for the grade you are applying for. Each grade will - have a list of criteria that you can use to determine if you meet the requirements to achieve that grade. -
-
- - -
-
- -
-
-

Grade Application

- Select the grade you are applying for {{unit.name}} below. -
-
-
- -
-

- Make sure your Learning Summary Report justifies how your portfolio demonstrates you have - met all unit learning outcomes to a {{targetGrade}} level -

-
-
- -
- - -
diff --git a/src/app/projects/states/portfolio/portfolio.tpl.html b/src/app/projects/states/portfolio/portfolio.tpl.html index be61edec29..934f90e76f 100644 --- a/src/app/projects/states/portfolio/portfolio.tpl.html +++ b/src/app/projects/states/portfolio/portfolio.tpl.html @@ -7,7 +7,11 @@ - + + From 373cd1eef326a528e1dd4546777a939c0db24d22 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Fri, 3 Oct 2025 14:55:31 +1000 Subject: [PATCH 0660/1531] refactor: migrate portfolio grade select step (#1014) * Frontend migration of portfolio-grade-select-step to Angular 17 component * Addressed review comments in portfolio-grade-select-step component * Implement OnInit in PortfolioGradeSelectStepComponent * replaced bootsrap UI component with Angular material * chore: bring back deleted lines * refactor: replace css with tailwind * chore: revert import order * chore: revert import order * chore: revert import order * chore: revert order * refactor: simplify grade changing --------- Co-authored-by: Pasindu Fernando <116358471+Pasindufdo98@users.noreply.github.com> --- src/app/doubtfire-angular.module.ts | 14 ++- src/app/doubtfire-angularjs.module.ts | 31 ++++-- .../portfolio/directives/directives.coffee | 1 - .../portfolio-grade-select-step.coffee | 22 ----- ...portfolio-grade-select-step.component.html | 96 +++++++++++++++++++ ...portfolio-grade-select-step.component.scss | 0 .../portfolio-grade-select-step.component.ts | 57 +++++++++++ .../portfolio-grade-select-step.scss | 10 -- .../portfolio-grade-select-step.tpl.html | 60 ------------ .../states/portfolio/portfolio.tpl.html | 6 +- 10 files changed, 189 insertions(+), 108 deletions(-) delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee create mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html create mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.scss create mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.scss delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 88c2206141..e65faa1d11 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -97,7 +97,7 @@ import {ExtensionCommentComponent} from './tasks/task-comments-viewer/extension- import {CampusListComponent} from './admin/institution-settings/campuses/campus-list/campus-list.component'; import {ExtensionModalComponent} from './common/modals/extension-modal/extension-modal.component'; import {CalendarModalComponent} from './common/modals/calendar-modal/calendar-modal.component'; -import { ConfirmationModalComponent } from './common/modals/confirmation-modal/confirmation-modal.component'; +import {ConfirmationModalComponent} from './common/modals/confirmation-modal/confirmation-modal.component'; import {MatRadioModule} from '@angular/material/radio'; import {MatButtonToggleModule} from '@angular/material/button-toggle'; import { @@ -256,11 +256,14 @@ import {TaskScormCardComponent} from './projects/states/dashboard/directives/tas import {TestAttemptService} from './api/services/test-attempt.service'; import {ScormExtensionCommentComponent} from './tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component'; import {ScormExtensionModalComponent} from './common/modals/scorm-extension-modal/scorm-extension-modal.component'; -import { GradeIconComponent } from './common/grade-icon/grade-icon.component'; -import { GradeTaskModalComponent } from './tasks/modals/grade-task-modal/grade-task-modal.component'; -import { PrivacyPolicy } from './config/privacy-policy/privacy-policy'; -import { UnitStaffEditorComponent } from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; +import {GradeIconComponent} from './common/grade-icon/grade-icon.component'; +import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; +import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; +// import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; +// import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; +import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; +import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -403,6 +406,7 @@ import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-char ScormExtensionModalComponent, UnitStaffEditorComponent, GroupSetSelectorComponent, + PortfolioGradeSelectStepComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 76ae8c64c5..0a48a0b2b7 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -71,7 +71,6 @@ import 'build/src/app/projects/states/outcomes/outcomes.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.js'; -import 'build/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.js'; import 'build/src/app/projects/states/portfolio/directives/directives.js'; @@ -139,7 +138,7 @@ import {ExtensionCommentComponent} from './tasks/task-comments-viewer/extension- import {TaskAssessmentCommentComponent} from './tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component'; import {ExtensionModalService} from './common/modals/extension-modal/extension-modal.service'; import {CalendarModalService} from './common/modals/calendar-modal/calendar-modal.service'; -import { ConfirmationModalService } from './common/modals/confirmation-modal/confirmation-modal.service'; +import {ConfirmationModalService} from './common/modals/confirmation-modal/confirmation-modal.service'; import {CampusListComponent} from './admin/institution-settings/campuses/campus-list/campus-list.component'; import {ActivityTypeListComponent} from './admin/institution-settings/activity-type-list/activity-type-list.component'; import {InstitutionSettingsComponent} from './admin/institution-settings/institution-settings.component'; @@ -212,16 +211,19 @@ import {FTaskSheetViewComponent} from './units/task-viewer/directives/task-sheet import {ProgressBurndownChartComponent} from './visualisations/progress-burndown-chart/progressburndownchart.component'; import {TaskVisualisationComponent} from './visualisations/task-visualisation/taskvisualisation.component'; import {ProgressDashboardComponent} from './projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component'; - import {FUnitsComponent} from './admin/states/units/units.component'; import {AlertService} from './common/services/alert.service'; - 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 { UnitStaffEditorComponent } from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; + +// import { UnitStudentEnrolmentModalService } from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service'; +// import { PrivacyPolicy } from './config/privacy-policy/privacy-policy'; +import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; +import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; + +import {UnitStudentEnrolmentModalService} from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service'; +import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -241,7 +243,10 @@ DoubtfireAngularJSModule.factory('AboutDoubtfireModal', downgradeInjectable(Abou DoubtfireAngularJSModule.factory('DoubtfireConstants', downgradeInjectable(DoubtfireConstants)); DoubtfireAngularJSModule.factory('ExtensionModal', downgradeInjectable(ExtensionModalService)); DoubtfireAngularJSModule.factory('CalendarModal', downgradeInjectable(CalendarModalService)); -DoubtfireAngularJSModule.factory('ConfirmationModal', downgradeInjectable(ConfirmationModalService)); +DoubtfireAngularJSModule.factory( + 'ConfirmationModal', + downgradeInjectable(ConfirmationModalService), +); DoubtfireAngularJSModule.factory('TaskCommentService', downgradeInjectable(TaskCommentService)); DoubtfireAngularJSModule.factory('alertService', downgradeInjectable(AlertService)); DoubtfireAngularJSModule.factory('tutorialService', downgradeInjectable(TutorialService)); @@ -481,12 +486,20 @@ DoubtfireAngularJSModule.directive( ); DoubtfireAngularJSModule.directive('newFUnits', downgradeComponent({component: FUnitsComponent})); -DoubtfireAngularJSModule.directive('unitStaffEditor', downgradeComponent({ component: UnitStaffEditorComponent })); +DoubtfireAngularJSModule.directive( + 'unitStaffEditor', + downgradeComponent({component: UnitStaffEditorComponent}), +); DoubtfireAngularJSModule.directive( 'unauthorised', downgradeComponent({component: UnauthorisedComponent}), ); +DoubtfireAngularJSModule.directive( + 'fPortfolioGradeSelectStep', + downgradeComponent({component: PortfolioGradeSelectStepComponent}), +); + // Global configuration // If the user enters a URL that doesn't match any known URL (state), send them to `/home` diff --git a/src/app/projects/states/portfolio/directives/directives.coffee b/src/app/projects/states/portfolio/directives/directives.coffee index 8ce9be0be3..661acd16e7 100644 --- a/src/app/projects/states/portfolio/directives/directives.coffee +++ b/src/app/projects/states/portfolio/directives/directives.coffee @@ -1,6 +1,5 @@ angular.module('doubtfire.projects.states.portfolio.directives', [ 'doubtfire.projects.states.portfolio.directives.portfolio-add-extra-files-step' - 'doubtfire.projects.states.portfolio.directives.portfolio-grade-select-step' 'doubtfire.projects.states.portfolio.directives.portfolio-learning-summary-report-step' 'doubtfire.projects.states.portfolio.directives.portfolio-review-step' 'doubtfire.projects.states.portfolio.directives.portfolio-tasks-step' diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee deleted file mode 100644 index 3a7ee7f2a4..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee +++ /dev/null @@ -1,22 +0,0 @@ -angular.module('doubtfire.projects.states.portfolio.directives.portfolio-grade-select-step', []) - -# -# Allows students to select the target grade they are hoping -# to achieve with their portfolio -# -.directive('portfolioGradeSelectStep', -> - restrict: 'E' - replace: true - templateUrl: 'projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html' - controller: ($scope, newProjectService, gradeService) -> - if ! $scope.project.submittedGrade - $scope.project.submittedGrade = 0 - $scope.grades = gradeService.gradeValues - $scope.gradeName = (grade) -> gradeService.grades[grade] - $scope.agreedToAssessmentCriteria = $scope.projectHasLearningSummaryReport() - $scope.chooseGrade = (idx) -> - $scope.project.submittedGrade = idx - newProjectService.update($scope.project).subscribe((project) -> - $scope.project.refreshBurndownChartData() - ) -) diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html new file mode 100644 index 0000000000..ad2c4c4f0c --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html @@ -0,0 +1,96 @@ +
+ + + + +

Select Grade

+
+
+ + +

+ In preparing your portfolio, you need to undertake a self-assessment. Use the unit's + assessment criteria to determine the grade your portfolio should be awarded. +

+ + + + + + warning + Read the assessment criteria + + + + +

+ Make sure that you have reviewed the Assessment Criteria for the grade you are applying + for. Each grade will have a list of criteria that you can use to determine if you meet + the requirements to achieve that grade. +

+
+ + + + I have read the Assessment Criteria for this unit + + +
+ + + + @if (agreedToAssessmentCriteria) { + + + + Grade Application + + + + +

+ Select the grade you are applying for {{ unit.code }} + {{ unit.name }} below. +

+
+ + + + @for (grade of gradeValues; track grade) { + + + + } + + +

+ Make sure your Learning Summary Report justifies how your portfolio + demonstrates you have + met all unit learning outcomes to a {{ targetGrade }} level +

+
+
+ } +
+ + + + + + +
+
diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.scss b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts new file mode 100644 index 0000000000..cce8ee1748 --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts @@ -0,0 +1,57 @@ +import {Component, Injector, Input} from '@angular/core'; +import {Project, Unit} from 'src/app/api/models/doubtfire-model'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {GradeService} from 'src/app/common/services/grade.service'; + +@Component({ + selector: 'f-portfolio-grade-select-step', + templateUrl: 'portfolio-grade-select-step.component.html', + styleUrls: ['portfolio-grade-select-step.component.scss'], +}) +export class PortfolioGradeSelectStepComponent { + @Input() project: Project; + @Input() unit: Unit; + + public agreedToAssessmentCriteria: boolean = false; + + constructor( + private gradeService: GradeService, + private injector: Injector, + private projectService: ProjectService, + ) { + this.$scope = this.injector.get('$scope'); + } + + public get gradeValues() { + return this.gradeService.gradeValues; + } + + updateSubmittedGrade(newGrade: number): void { + const previousSubmittedGrade = this.project.submittedGrade; + this.project.submittedGrade = newGrade; + + this.projectService.update(this.project).subscribe( + (project) => { + project.refreshBurndownChartData?.(); + }, + (error) => { + this.project.submittedGrade = previousSubmittedGrade; + console.error('Error updating target grade:', error); + }, + ); + } + + // TODO: remove this once parent component has been migrated + private $scope: any; + goToNextStep(): void { + if (typeof this.$scope?.advanceActiveTab === 'function') { + this.$scope.advanceActiveTab(1); + } + } + + goToPreviousStep(): void { + if (typeof this.$scope?.advanceActiveTab === 'function') { + this.$scope.advanceActiveTab(-1); + } + } +} diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.scss b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.scss deleted file mode 100644 index bfc229c4b1..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.scss +++ /dev/null @@ -1,10 +0,0 @@ -.project-portfolio-wizard .portfolio-grade-select-step { - .confirm-read-assessment-criteria { - font-size: 1.2em; - } - .select-the-grade { - .btn { - padding: 1em; - } - } -} diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html deleted file mode 100644 index 097b685e35..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.tpl.html +++ /dev/null @@ -1,60 +0,0 @@ -
-
-

Select Grade

-
-
-

- In preparing your portfolio, you need to undertake a self assessment. Use the unit's assessment criteria to - determine the grade your portfolio should be awarded. -

-
-
-

Read the assessment criteria

- Make sure that you have reviewed the Assessment Criteria for the grade you are applying for. Each grade will - have a list of criteria that you can use to determine if you meet the requirements to achieve that grade. -
-
- - -
-
- -
-
-

Grade Application

- Select the grade you are applying for {{unit.name}} below. -
-
-
- -
-

- Make sure your Learning Summary Report justifies how your portfolio demonstrates you have - met all unit learning outcomes to a {{gradeName(project.submittedGrade)}} level -

-
-
- -
- - -
diff --git a/src/app/projects/states/portfolio/portfolio.tpl.html b/src/app/projects/states/portfolio/portfolio.tpl.html index 1c009b47ab..ae536e081f 100644 --- a/src/app/projects/states/portfolio/portfolio.tpl.html +++ b/src/app/projects/states/portfolio/portfolio.tpl.html @@ -7,7 +7,11 @@ - + + From 8d36c94f03563a0924cfeb7d2d9e8dd911b65960 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 8 Oct 2025 09:22:49 +1100 Subject: [PATCH 0661/1531] fix: add assess in portfolio tasks as completed tasks in burndown chart --- src/app/api/models/project.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/models/project.ts b/src/app/api/models/project.ts index 167aeb1ec5..1064fb3c5b 100644 --- a/src/app/api/models/project.ts +++ b/src/app/api/models/project.ts @@ -413,7 +413,7 @@ export class Project extends Entity { const tasks = this.tasks; const readyOrCompleteTasks = tasks.filter((task) => - ['ready_for_feedback', 'discuss', 'demonstrate', 'complete'].includes(task.status), + ['ready_for_feedback', 'discuss', 'demonstrate', 'complete', 'assess_in_portfolio'].includes(task.status), ); let lastTargetDate: Date; From 95402a6f6678d9bad066386b60f0ce5a3b3766aa Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 8 Oct 2025 09:31:06 +1100 Subject: [PATCH 0662/1531] refactor: migrate/tutorials (#934) (#1013) * refactor: migrate/tutorials (#934) * chore: migrate tutorials - unlink old component - link new component - delete old files - add UI-router state declaration - remove reference to old state * chore: migrate tutorials - delete old files * chore: migrate tutorials - declare and define `tutorials` Typescript class - define `tutorials` markup in Angular and Angular material - add stylesheet * chore: migrate tutorials - delete old template * chore: amend file name - change template file name to adhere to styling convention - add `todo` comment to Typescript file --------- Co-authored-by: Boink <40929320+b0ink@users.noreply.github.com> * fix: map unit staff - 9.x api currently exposes :staff instead of :unit_roles * fix: accurately check for tutorial enrolment * fix: ensure tutorial for current enrolment is displayed * refactor: use mat table * refactor: improve tutorials component and add sorting - fetch unit to ensure tutorials are loaded correctly - add table sorting * chore: format * chore: remove styling * chore: remove unused class * chore: reword description --------- Co-authored-by: Jason Vellucci --- src/app/api/models/project.ts | 2 +- src/app/api/services/unit.service.ts | 3 +- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 11 +- src/app/doubtfire.states.ts | 20 +++ src/app/projects/states/states.coffee | 1 - .../states/tutorials/tutorials.coffee | 23 --- .../states/tutorials/tutorials.component.html | 104 ++++++++++++ .../states/tutorials/tutorials.component.scss | 0 .../states/tutorials/tutorials.component.ts | 149 ++++++++++++++++++ .../projects/states/tutorials/tutorials.scss | 10 -- .../states/tutorials/tutorials.tpl.html | 71 --------- 12 files changed, 285 insertions(+), 111 deletions(-) delete mode 100644 src/app/projects/states/tutorials/tutorials.coffee create mode 100644 src/app/projects/states/tutorials/tutorials.component.html create mode 100644 src/app/projects/states/tutorials/tutorials.component.scss create mode 100644 src/app/projects/states/tutorials/tutorials.component.ts delete mode 100644 src/app/projects/states/tutorials/tutorials.scss delete mode 100644 src/app/projects/states/tutorials/tutorials.tpl.html diff --git a/src/app/api/models/project.ts b/src/app/api/models/project.ts index 380c62d199..3c154842e2 100644 --- a/src/app/api/models/project.ts +++ b/src/app/api/models/project.ts @@ -347,7 +347,7 @@ export class Project extends Entity { } public isEnrolledIn(tutorial: Tutorial): boolean { - return this.tutorials.includes(tutorial); + return this.tutorials.some((t) => t.id === tutorial.id); } public updateUnitEnrolment(): void { diff --git a/src/app/api/services/unit.service.ts b/src/app/api/services/unit.service.ts index e04d3bec82..42c8211ab8 100644 --- a/src/app/api/services/unit.service.ts +++ b/src/app/api/services/unit.service.ts @@ -53,7 +53,8 @@ export class UnitService extends CachedEntityService { }, }, { - keys: 'unitRoles', + // keys: 'unitRoles', + keys: 'staff', toEntityOp: (data, key, entity) => { const unitRoleService = AppInjector.get(UnitRoleService); // Add staff diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index e65faa1d11..5396335ffe 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -277,6 +277,7 @@ const MY_DATE_FORMAT = { monthYearA11yLabel: 'MMMM yyyy', }, }; +import {TutorialsComponent} from './projects/states/tutorials/tutorials.component'; import {UnitStudentEnrolmentModalComponent} from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component'; import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-chart/taskstatuspiechart.component'; @@ -404,6 +405,7 @@ import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-char TaskScormCardComponent, ScormExtensionCommentComponent, ScormExtensionModalComponent, + TutorialsComponent, UnitStaffEditorComponent, GroupSetSelectorComponent, PortfolioGradeSelectStepComponent, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 0a48a0b2b7..ade3d4e6d3 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -76,7 +76,6 @@ import 'build/src/app/projects/states/portfolio/directives/portfolio-tasks-step/ import 'build/src/app/projects/states/portfolio/directives/directives.js'; import 'build/src/app/projects/states/portfolio/portfolio.js'; import 'build/src/app/projects/states/index/index.js'; -import 'build/src/app/projects/states/tutorials/tutorials.js'; import 'build/src/app/projects/project-outcome-alignment/project-outcome-alignment.js'; import 'build/src/app/admin/modals/modals.js'; import 'build/src/app/groups/group-selector/group-selector.js'; @@ -210,11 +209,14 @@ import {FTaskDetailsViewComponent} from './units/task-viewer/directives/task-det import {FTaskSheetViewComponent} from './units/task-viewer/directives/task-sheet-view/task-sheet-view.component'; import {ProgressBurndownChartComponent} from './visualisations/progress-burndown-chart/progressburndownchart.component'; import {TaskVisualisationComponent} from './visualisations/task-visualisation/taskvisualisation.component'; +import {TutorialsComponent} from './projects/states/tutorials/tutorials.component'; import {ProgressDashboardComponent} from './projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component'; import {FUnitsComponent} from './admin/states/units/units.component'; import {AlertService} from './common/services/alert.service'; 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 { UnitStudentEnrolmentModalService } from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service'; // import { PrivacyPolicy } from './config/privacy-policy/privacy-policy'; @@ -222,9 +224,6 @@ import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staf import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; -import {UnitStudentEnrolmentModalService} from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.service'; -import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; - export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', 'doubtfire.sessions', @@ -486,6 +485,10 @@ DoubtfireAngularJSModule.directive( ); DoubtfireAngularJSModule.directive('newFUnits', downgradeComponent({component: FUnitsComponent})); +DoubtfireAngularJSModule.directive( + 'fTutorials', + downgradeComponent({component: TutorialsComponent}), +); DoubtfireAngularJSModule.directive( 'unitStaffEditor', downgradeComponent({component: UnitStaffEditorComponent}), diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index 7baa910f57..d2a7226cb2 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -14,6 +14,7 @@ import {ProjectRootState} from './projects/states/project-root-state.component'; import { TaskViewerState } from './units/task-viewer/task-viewer-state.component'; import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; import { Ng2ViewDeclaration } from '@uirouter/angular'; +import { TutorialsComponent } from './projects/states/tutorials/tutorials.component'; /* * Use this file to store any states that are sourced by angular components. @@ -411,6 +412,24 @@ const ScormPlayerReviewState: NgHybridStateDeclaration = { }, }; +const TutorialState: NgHybridStateDeclaration = { + name: 'projects/tutorials', + url: '/tutorials/project/:projectId', + views: { + main: { + component: TutorialsComponent, // Link to the Angular component + }, + }, + resolve: { + projectId: ['$stateParams', ($stateParams) => $stateParams.projectId], // Resolve the project object + }, + data: { + task: 'Tutorial List', + pageTitle: '_Home_', + roleWhiteList: ['Tutor', 'Convenor', 'Admin', 'Student', 'Auditor'], // Roles allowed to access this state + }, +}; + /** * Export the list of states we have created in angular */ @@ -433,4 +452,5 @@ export const doubtfireStates = [ ScormPlayerNormalState, ScormPlayerReviewState, ScormPlayerStudentReviewState, + TutorialState, ]; diff --git a/src/app/projects/states/states.coffee b/src/app/projects/states/states.coffee index 01b9d42dd4..a2a24c4bc4 100644 --- a/src/app/projects/states/states.coffee +++ b/src/app/projects/states/states.coffee @@ -1,7 +1,6 @@ angular.module('doubtfire.projects.states', [ 'doubtfire.projects.states.index' 'doubtfire.projects.states.dashboard' - 'doubtfire.projects.states.tutorials' 'doubtfire.projects.states.portfolio' 'doubtfire.projects.states.groups' 'doubtfire.projects.states.outcomes' diff --git a/src/app/projects/states/tutorials/tutorials.coffee b/src/app/projects/states/tutorials/tutorials.coffee deleted file mode 100644 index 5c22b609e3..0000000000 --- a/src/app/projects/states/tutorials/tutorials.coffee +++ /dev/null @@ -1,23 +0,0 @@ -angular.module('doubtfire.projects.states.tutorials', []) - -# -# Tasks state for projects -# -.config(($stateProvider) -> - $stateProvider.state 'projects/tutorials', { - parent: 'projects/index' - url: '/tutorials' - controller: 'ProjectsTutorialsStateCtrl' - templateUrl: 'projects/states/tutorials/tutorials.tpl.html' - data: - task: "Tutorial List" - pageTitle: "_Home_" - } -) - -.controller("ProjectsTutorialsStateCtrl", ($scope) -> - if $scope.unit.tutorialStreamsCache.size > 0 - $scope.sortOrder = 'tutorialStream.name' - else - $scope.sortOrder = 'abbreviation' -) diff --git a/src/app/projects/states/tutorials/tutorials.component.html b/src/app/projects/states/tutorials/tutorials.component.html new file mode 100644 index 0000000000..39ec57fbf8 --- /dev/null +++ b/src/app/projects/states/tutorials/tutorials.component.html @@ -0,0 +1,104 @@ +
+
+

Tutorials

+

+ View available tutorials and manage your enrolment. Note that availability is subject to + capacity. If you are unable to enrol in a tutorial, please contact your unit coordinator. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Stream + @if (unit.tutorialStreamsCache.size > 0) { +
{{ tutorial.tutorialStream?.name || 'All' }}
+ } @else { +
N/A
+ } +
Campus + {{ tutorial.campus?.name || 'All' }} + Code + {{ tutorial.abbreviation }} + Day + {{ tutorial.meetingDay }} + Time + {{ shortTime(tutorial.meetingTime) }} + Room + {{ tutorial.meetingLocation }} + Tutor + {{ tutorial.tutorName }} + Actions + @if (project.isEnrolledIn(tutorial)) { + @if (unit.allowStudentChangeTutorial) { + + } @else { +
+ Enrolled +
+ } + } @else if (unit.allowStudentChangeTutorial) { + + } @else { +
+ + } +
+
diff --git a/src/app/projects/states/tutorials/tutorials.component.scss b/src/app/projects/states/tutorials/tutorials.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/tutorials/tutorials.component.ts b/src/app/projects/states/tutorials/tutorials.component.ts new file mode 100644 index 0000000000..6a28239240 --- /dev/null +++ b/src/app/projects/states/tutorials/tutorials.component.ts @@ -0,0 +1,149 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {Sort} from '@angular/material/sort'; +import {MatTableDataSource} from '@angular/material/table'; +import {Tutorial, UnitService} from 'src/app/api/models/doubtfire-model'; +import {Project} from 'src/app/api/models/project'; +import {Unit} from 'src/app/api/models/unit'; +import {ProjectService} from 'src/app/api/services/project.service'; + +@Component({ + selector: 'f-tutorials', + templateUrl: './tutorials.component.html', + styleUrls: ['./tutorials.component.scss'], +}) +export class TutorialsComponent implements OnInit { + @Input() projectId: number; + + filteredTutorials: Tutorial[] = []; + + project: Project; + unit: Unit; + + displayedColumns: string[] = [ + 'stream', + 'campus', + 'code', + 'day', + 'time', + 'room', + 'tutor', + 'actions', + ]; + + dataSource = new MatTableDataSource([]); + + constructor( + private projectService: ProjectService, + private unitService: UnitService, + ) {} + + ngOnInit(): void { + this.projectService.fetch(this.projectId).subscribe({ + next: (project) => { + this.unitService.get(project.unit.id).subscribe({ + next: (unit) => { + this.unit = unit; + this.project = project; + this.filteredTutorials = this.tutorialCampusFilter([...unit.tutorials], this.project); + this.dataSource.data = this.filteredTutorials; + }, + error: (error) => { + console.error('Error fetching unit:', error); + }, + }); + }, + error: (error) => { + console.error('Error fetching project:', error); + }, + }); + } + + /** + * Switches to the passed-in tutorial. + * + * @param tutorial + * + * @returns void + */ + switchToTutorial(tutorial: Tutorial): void { + this.project.switchToTutorial(tutorial); + } + + /** + * Filters a collection of passed-in tutorials based on the campus_id of the passed-in project. + * + * @param tutorials + * @param project + * + * @returns Tutorial[] + */ + tutorialCampusFilter(tutorials: Tutorial[], project: Project): Tutorial[] { + if (!project) { + return tutorials; + } + return tutorials.filter((tutorial) => { + return ( + !project.campus?.id || + !tutorial.campus || + tutorial.campus.id === project.campus.id || + project.isEnrolledIn(tutorial) + ); + }); + } + + /** + * Formats the passed-in time string to the format of: HH:mm + * Todo: Add date validation + * @param meetingTime + * + * @returns string + */ + shortTime(meetingTime: string): string { + const [hours, minutes] = meetingTime.split(':'); + const formattedHours = hours.padStart(2, '0'); + const formattedMinutes = minutes.padStart(2, '0'); + + return `${formattedHours}:${formattedMinutes}`; + } + + private sortCompare(aValue: number | string, bValue: number | string, isAsc: boolean) { + return (aValue < bValue ? -1 : 1) * (isAsc ? 1 : -1); + } + + sortTableData(sort: Sort) { + if (!sort.active || sort.direction === '') { + return; + } + this.dataSource.data = this.dataSource.data.sort((a, b) => { + switch (sort.active) { + case 'stream': + return this.sortCompare( + a.tutorialStream?.name, + b.tutorialStream?.name, + sort.direction === 'asc', + ); + case 'campus': + return this.sortCompare(a.campus?.name, b.campus?.name, sort.direction === 'asc'); + case 'code': + return this.sortCompare(a.abbreviation, b.abbreviation, sort.direction === 'asc'); + case 'day': { + return this.sortCompare(a.meetingDay, b.meetingDay, sort.direction === 'asc'); + } + case 'time': { + return this.sortCompare( + this.shortTime(a.meetingTime), + this.shortTime(b.meetingTime), + sort.direction === 'asc', + ); + } + case 'room': { + return this.sortCompare(a.meetingLocation, b.meetingLocation, sort.direction === 'asc'); + } + case 'tutor': + return this.sortCompare(a.tutorName, b.tutorName, sort.direction === 'asc'); + default: + return 0; + } + }); + } +} diff --git a/src/app/projects/states/tutorials/tutorials.scss b/src/app/projects/states/tutorials/tutorials.scss deleted file mode 100644 index d402eae6a6..0000000000 --- a/src/app/projects/states/tutorials/tutorials.scss +++ /dev/null @@ -1,10 +0,0 @@ -#tutorials-state table { - th.stream { width: 10%; } - th.campus { width: 20%; } - th.code { width: 10%; } - th.day { width: 10%; } - th.time { width: 10%; } - th.room { width: 10%; } - th.tutor { width: 15%; } - th.actions { width: 15%; } -} diff --git a/src/app/projects/states/tutorials/tutorials.tpl.html b/src/app/projects/states/tutorials/tutorials.tpl.html deleted file mode 100644 index fae91d6ae3..0000000000 --- a/src/app/projects/states/tutorials/tutorials.tpl.html +++ /dev/null @@ -1,71 +0,0 @@ -
-
-
-

Select a Tutorial

-
-
-

- Click the plus on the specific tutorial to enrol in that tutorial, or click the minus icon to withdraw from your - current tutorial. -

-
- - - - - - - - - - - - - - - - - - - - - - - - - -
- Stream - - Campus - - Code - - Day - - Time - - Room - - Tutor - Actions
{{tutorial.tutorialStream.name || 'All'}}{{tutorial.campus ? tutorial.campus.name : 'All'}}{{tutorial.abbreviation}}{{tutorial.meetingDay}}{{tutorial.meetingTime | date: 'shortTime'}}{{tutorial.meetingLocation}}{{tutorial.tutorName}} - - -
-
-
From 2b4afe24e3f8139fec23337facc7656eec9a9d3a Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 13 Oct 2025 10:21:09 +1100 Subject: [PATCH 0663/1531] feat: add tutor times summary download (#1015) * feat: add tutor times summary download * fix: typo * feat: add calendar view of marking sessions * refactor: simplify date in filename * refactor: remove get tutors call * refactor: custom number of days visible, show today at the end * refactor: date pickers to filter sessions * refactor: clean up ui * refactor: create tutor times analytics component * refactor: add loading spinner * refactor: fix timezone issues * refactor: improve ui * chore: update endpoint * feat: toggle hide sessions during tutorials * chore: remove button * refactor: implement marking session entity * chore: remove unused code * chore: remove comment --- package-lock.json | 64 +++++ package.json | 1 + src/app/api/models/marking-session.ts | 40 +++ src/app/api/models/unit.ts | 59 +++- .../api/services/marking-session.service.ts | 39 +++ src/app/doubtfire-angular.module.ts | 7 + .../analytics-tutor-times.component.html | 97 +++++++ .../analytics-tutor-times.component.scss | 0 .../analytics-tutor-times.component.ts | 253 ++++++++++++++++++ .../unit-analytics-route.component.html | 34 ++- .../unit-analytics-route.component.ts | 11 +- src/styles.scss | 6 + 12 files changed, 596 insertions(+), 15 deletions(-) create mode 100644 src/app/api/models/marking-session.ts create mode 100644 src/app/api/services/marking-session.service.ts create mode 100644 src/app/units/states/analytics/directives/analytics-tutor-times.component.html create mode 100644 src/app/units/states/analytics/directives/analytics-tutor-times.component.scss create mode 100644 src/app/units/states/analytics/directives/analytics-tutor-times.component.ts diff --git a/package-lock.json b/package-lock.json index 4b1491ce8c..cd419cdb8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "@uirouter/core": "^6.1.0", "@uirouter/rx": "^1.0.0", "angular": "1.5.11", + "angular-calendar": "^0.31.1", "angular-filter": "0.5.17", "angular-markdown-filter": "1.3.2", "angular-md5": "0.1.10", @@ -4632,6 +4633,12 @@ "tslib": "^2.1.0" } }, + "node_modules/@mattlewis92/dom-autoscroller": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@mattlewis92/dom-autoscroller/-/dom-autoscroller-2.4.2.tgz", + "integrity": "sha512-YbrUWREPGEjE/FU6foXcAT1YbVwqD/jkYnY1dFb0o4AxtP3s4xKBthlELjndZih8uwsDWgQZx1eNskRNe2BgZQ==", + "license": "MIT" + }, "node_modules/@ngneat/hotkeys": { "version": "4.0.0", "license": "MIT", @@ -6410,6 +6417,39 @@ "version": "1.5.11", "license": "MIT" }, + "node_modules/angular-calendar": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/angular-calendar/-/angular-calendar-0.31.1.tgz", + "integrity": "sha512-pjSIpoAaUzS/gx+14eOr4hPZhlQ8HxpiZypCSGqJNptq5PD+vOdVQ3h/Aaqnk86GraVcAQPXqfu64MtdKwTVNw==", + "license": "MIT", + "dependencies": { + "@scarf/scarf": "^1.1.1", + "angular-draggable-droppable": "^8.0.0", + "angular-resizable-element": "^7.0.0", + "calendar-utils": "^0.10.4", + "positioning": "^2.0.1", + "tslib": "^2.4.1" + }, + "funding": { + "url": "https://github.com/sponsors/mattlewis92" + }, + "peerDependencies": { + "@angular/core": ">=15.0.0" + } + }, + "node_modules/angular-draggable-droppable": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/angular-draggable-droppable/-/angular-draggable-droppable-8.0.0.tgz", + "integrity": "sha512-+gpSNBbygjV1pxTxsM3UPJKcXHXJabYoTtKcgQe74rGnb1umKc07XCBD1qDzvlG/kocthvhQ12qfYOYzHnE3ZA==", + "license": "MIT", + "dependencies": { + "@mattlewis92/dom-autoscroller": "^2.4.2", + "tslib": "^2.4.1" + }, + "peerDependencies": { + "@angular/core": ">=15.0.0" + } + }, "node_modules/angular-filter": { "version": "0.5.17", "license": "MIT", @@ -6443,6 +6483,18 @@ "nvd3": "^1.7.1" } }, + "node_modules/angular-resizable-element": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/angular-resizable-element/-/angular-resizable-element-7.0.2.tgz", + "integrity": "sha512-/BGuNiA38n9klexHO1xgnsA3VYigj9v+jUGjKtBRgfB26bCxZKsNWParSu2k3EqbATrfAJC4Nl8f7cORpJFf4w==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/core": ">=15.0.0" + } + }, "node_modules/angular-resource": { "version": "1.5.11", "license": "MIT" @@ -7573,6 +7625,12 @@ "node": ">=0.10.0" } }, + "node_modules/calendar-utils": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/calendar-utils/-/calendar-utils-0.10.4.tgz", + "integrity": "sha512-gBK4xCJ42yjaUKwuUha6cZOfxAmGzvSgbdAaX3xLRioeKbYoOK1x1qeD6dch72rsMZlTgATPbBBx42bnkStqgQ==", + "license": "MIT" + }, "node_modules/call-bind": { "version": "1.0.7", "license": "MIT", @@ -17668,6 +17726,12 @@ "npm": ">=1.0.0" } }, + "node_modules/positioning": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/positioning/-/positioning-2.0.1.tgz", + "integrity": "sha512-DsAgM42kV/ObuwlRpAzDTjH9E8fGKkMDJHWFX+kfNXSxh7UCCQxEmdjv/Ws5Ft1XDnt3JT8fIDYeKNSE2TbttA==", + "license": "MIT" + }, "node_modules/posix-character-classes": { "version": "0.1.1", "dev": true, diff --git a/package.json b/package.json index 056ce41ad1..f9eb667eef 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "@uirouter/core": "^6.1.0", "@uirouter/rx": "^1.0.0", "angular": "1.5.11", + "angular-calendar": "^0.31.1", "angular-filter": "0.5.17", "angular-markdown-filter": "1.3.2", "angular-md5": "0.1.10", diff --git a/src/app/api/models/marking-session.ts b/src/app/api/models/marking-session.ts new file mode 100644 index 0000000000..8bfbe3a446 --- /dev/null +++ b/src/app/api/models/marking-session.ts @@ -0,0 +1,40 @@ +import {Entity, EntityMapping} from 'ngx-entity-service'; +import {User} from './doubtfire-model'; +import {Unit} from './unit'; + +export class MarkingSession extends Entity { + id: number; + + // Marking tutor + user: User; + + unit: Unit; + + startTime: Date; + endTime: Date; + duringTutorial: boolean; + durationMinutes: number; + + // Aggregated session activities count + commentsAdded: number; + assessments: number; + submissionsOpened: number; + + constructor(data?: Unit) { + super(); + if (data) { + this.unit = data; + } else { + console.error('Failed to get unit'); + } + } + + public override toJson( + mappingData: EntityMapping, + ignoreKeys?: string[], + ): object { + return { + markingSession: super.toJson(mappingData, ignoreKeys), + }; + } +} diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index 6f4a2b0622..b144a53bb3 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -30,8 +30,10 @@ import {LearningOutcome} from './learning-outcome'; import {AlertService} from 'src/app/common/services/alert.service'; import {D2lAssessmentMapping} from './d2l/d2l_assessment_mapping'; import {SidekiqJob} from './sidekiq-job'; -import {HttpClient} from '@angular/common/http'; +import {HttpClient, HttpParams} from '@angular/common/http'; import {TaskPrerequisiteService} from '../services/task-prerequisite.service'; +import {MarkingSession} from './marking-session'; +import {MarkingSessionService} from '../services/marking-session.service'; export class Unit extends Entity { id: number; @@ -603,6 +605,61 @@ export class Unit extends Entity { ); } + public getUserMarkingSessions(startDate?: Date, endDate?: Date): Observable { + let params = new HttpParams(); + if (startDate) { + params = params.set( + 'start_date', + `${startDate.getFullYear()}-${(startDate.getMonth() + 1).toString().padStart(2, '0')}-${startDate.getDate().toString().padStart(2, '0')}`, + ); + } + + if (endDate) { + params = params.set( + 'end_date', + `${endDate.getFullYear()}-${(endDate.getMonth() + 1).toString().padStart(2, '0')}-${endDate.getDate().toString().padStart(2, '0')}`, + ); + } + + // TODO: we should cache the data by the same start/end date + const markingSessionService = AppInjector.get(MarkingSessionService); + return markingSessionService.fetchAll( + { + unitId: this.id, + }, + {params, constructorParams: this}, + ); + } + + public downloadTutorTimesSummaryCsv( + startDate?: Date, + endDate?: Date, + ignoreSessionsDuringTutorials?: boolean, + ): Observable { + let params = new HttpParams(); + + if (startDate) { + params = params.set( + 'start_date', + `${startDate.getFullYear()}-${(startDate.getMonth() + 1).toString().padStart(2, '0')}-${startDate.getDate().toString().padStart(2, '0')}`, + ); + } + + if (endDate) { + params = params.set( + 'end_date', + `${endDate.getFullYear()}-${(endDate.getMonth() + 1).toString().padStart(2, '0')}-${endDate.getDate().toString().padStart(2, '0')}`, + ); + } + + params = params.set('ignore_sessions_during_tutorials', ignoreSessionsDuringTutorials ?? false); + + return AppInjector.get(HttpClient).get( + `${AppInjector.get(DoubtfireConstants).API_URL}/csv/units/${this.id}/tutor_times_summary`, + {params}, + ); + } + public hasD2lMapping(): boolean { const doubtfireConstants = AppInjector.get(DoubtfireConstants); return ( diff --git a/src/app/api/services/marking-session.service.ts b/src/app/api/services/marking-session.service.ts new file mode 100644 index 0000000000..f1ce830a02 --- /dev/null +++ b/src/app/api/services/marking-session.service.ts @@ -0,0 +1,39 @@ +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {CachedEntityService} from 'ngx-entity-service'; +import {Unit} from 'src/app/api/models/doubtfire-model'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {MarkingSession} from '../models/marking-session'; + +@Injectable() +export class MarkingSessionService extends CachedEntityService { + protected readonly endpointFormat = 'units/:unitId:/marking_sessions/:id:'; + + constructor(httpClient: HttpClient) { + super(httpClient, API_URL); + + this.mapping.addKeys( + 'id', + 'startTime', + 'endTime', + 'duringTutorial', + 'durationMinutes', + + 'commentsAdded', + 'assessments', + 'submissionsOpened', + + { + keys: ['user', 'user_id'], + toEntityFn: (data: object, _key: string, markingSession: MarkingSession) => { + const userRole = markingSession.unit.staff.find((s) => s.user.id === data['user_id']); + return userRole.user; + }, + }, + ); + } + + public createInstanceFrom(json: object, other?: Unit): MarkingSession { + return new MarkingSession(other); + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 369039dfbc..47e4679234 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -111,6 +111,8 @@ import {MatDatepickerModule} from '@angular/material/datepicker'; import {DateFnsAdapter, MAT_DATE_FNS_FORMATS} from '@angular/material-date-fns-adapter'; import {enAU} from 'date-fns/locale'; +import {CalendarModule, DateAdapter as CalendarDateAdapter} from 'angular-calendar'; +import {adapterFactory} from 'angular-calendar/date-adapters/date-fns'; import {doubtfireStates} from './doubtfire.states'; import {MatTableModule} from '@angular/material/table'; @@ -289,6 +291,8 @@ import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staf import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; import {UnitDetailsEditorComponent} from './units/states/edit/directives/unit-details-editor/unit-details-editor.component'; import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; +import {AnalyticsTutorTimesComponent} from './units/states/analytics/directives/analytics-tutor-times.component'; +import {MarkingSessionService} from './api/services/marking-session.service'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -441,6 +445,7 @@ const MY_DATE_FORMAT = { GroupSetSelectorComponent, UnitDetailsEditorComponent, PortfolioGradeSelectStepComponent, + AnalyticsTutorTimesComponent, ], // Services we provide providers: [ @@ -529,6 +534,7 @@ const MY_DATE_FORMAT = { SidekiqJobService, LtiService, TaskPrerequisiteService, + MarkingSessionService, ], imports: [ FlexLayoutModule, @@ -590,6 +596,7 @@ const MY_DATE_FORMAT = { MatDatepickerModule, MatNativeDateModule, MatDialogModuleNew, + CalendarModule.forRoot({provide: CalendarDateAdapter, useFactory: adapterFactory}), ], }) diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html new file mode 100644 index 0000000000..faef0eaab1 --- /dev/null +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html @@ -0,0 +1,97 @@ + + + +

Tutor Times Session Summary

+
+ + +
+ +
+
+ + + +
+
+ + Choose a date + + Sessions from this day onward + + + + + + Choose a date + + Sessions up to this day + + + +
+
+ Hide sessions during tutorials +
+
+ + +
+ {{ event.name }} ({{ event.duration }} minutes) + {{ event.duringTutorial ? 'T' : '' }}
+ Assessments: {{ event.assessments || 0 }}
+ Comments: {{ event.comments_added || 0 }}
+ Submissions opened: {{ event.submissions_opened || 0 }}
+ During Tutorial?: {{ event.duringTutorial ? 'yes' : 'no' }} +
+
+ +
+ @if (isLoading) { + + + } + + +
+
diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.scss b/src/app/units/states/analytics/directives/analytics-tutor-times.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts new file mode 100644 index 0000000000..19735552cc --- /dev/null +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts @@ -0,0 +1,253 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {MatDatepickerInputEvent} from '@angular/material/datepicker'; +import {CalendarEvent} from 'angular-calendar'; +import {Observable} from 'rxjs'; +import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; +import {Unit} from 'src/app/api/models/unit'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-analytics-tutor-times', + templateUrl: 'analytics-tutor-times.component.html', + styleUrls: ['analytics-tutor-times.component.scss'], +}) +export class AnalyticsTutorTimesComponent implements OnInit { + @Input() unit: Unit; + + @Input() downloadCsvFn!: ( + newJob: Observable, + title: string, + filename: string, + ) => void; + + selectedUserId: number | null = null; + + viewDate = new Date(); + events = []; + filteredEvents = []; + + tutorTimeSummaryStartDate: Date; + tutorTimeSummaryEndDate: Date; + daysInWeek: number = 7; + + hideSessionsDuringTutorials: boolean = false; + + public canLoadSessions: boolean = false; + public isLoading: boolean = false; + + constructor( + private alertService: AlertService, + private sidekiqProgressModalService: SidekiqProgressModalService, + private fileDownloaderService: FileDownloaderService, + ) {} + + ngOnInit(): void { + if (!this.sidekiqProgressModalService || !this.fileDownloaderService) { + // NOTE: Our `downloadCsvFn` callback requires these services because it calls `this` context + console.error('Failed to load tutor times analytics'); + } + + this.tutorTimeSummaryEndDate = new Date(); + this.tutorTimeSummaryEndDate.setHours(0, 0, 0, 0); + + this.tutorTimeSummaryStartDate = new Date(this.tutorTimeSummaryEndDate); + this.tutorTimeSummaryStartDate.setDate(this.tutorTimeSummaryEndDate.getDate() - 7); + + const startOfWeek = new Date(this.viewDate); + startOfWeek.setDate(this.viewDate.getDate() - this.daysInWeek + 1); + + this.viewDate = startOfWeek; + + this.canLoadSessions = true; + this.getMarkingSesssions(); + } + + goPreviousWeek() { + this.canLoadSessions = true; + this.viewDate = new Date(this.viewDate.getTime() - this.daysInWeek * 24 * 60 * 60 * 1000); + } + + goNextWeek() { + this.canLoadSessions = true; + this.viewDate = new Date(this.viewDate.getTime() + this.daysInWeek * 24 * 60 * 60 * 1000); + } + + goTodayWeek() { + this.canLoadSessions = true; + + this.tutorTimeSummaryEndDate = new Date(); + this.tutorTimeSummaryStartDate = new Date( + this.tutorTimeSummaryEndDate.getTime() - 7 * 24 * 60 * 60 * 1000, + ); + this.daysInWeek = 7; + + this.viewDate = new Date(); + const startOfWeek = new Date(); + startOfWeek.setDate(this.viewDate.getDate() - this.daysInWeek + 1); + + this.viewDate = startOfWeek; + } + + public onToggleChangeHideSessionsDuringTutorial() { + setTimeout(() => { + this.applyFilters(); + }); + } + + applyFilters() { + this.filteredEvents = this.events.filter( + (e) => + (this.selectedUserId === null || e['user_id'] === this.selectedUserId) && + (!this.hideSessionsDuringTutorials || !e['duringTutorial']), + ); + } + + onDateChange(_event: MatDatepickerInputEvent) { + if (!this.tutorTimeSummaryStartDate || !this.tutorTimeSummaryEndDate) { + return; + } + + // Includes both the selected start & end days + const diffDays = + Math.floor( + (this.tutorTimeSummaryEndDate.getTime() - this.tutorTimeSummaryStartDate.getTime()) / + (1000 * 60 * 60 * 24), + ) + 1; + + if (diffDays > 366) { + this.alertService.error('You cannot select more than a year', 3000); + return; + } + console.log('diff days', diffDays); + if (diffDays < 1) { + this.tutorTimeSummaryStartDate = this.tutorTimeSummaryEndDate; + this.alertService.error('End date must be on or after the start date'); + return; + } + this.canLoadSessions = true; + this.daysInWeek = diffDays; + this.viewDate = new Date(this.tutorTimeSummaryStartDate); + } + + beforeViewRender(event): void { + console.log(event.period.start); + console.log(event.period.end); + + this.tutorTimeSummaryStartDate = event.period.start; + this.tutorTimeSummaryEndDate = event.period.end; + + this.getMarkingSesssions(); + } + + public getTutorTimesSummary() { + const start = `${this.tutorTimeSummaryStartDate.getFullYear()}-${(this.tutorTimeSummaryStartDate.getMonth() + 1).toString().padStart(2, '0')}-${this.tutorTimeSummaryStartDate.getDate().toString().padStart(2, '0')}`; + const end = `${this.tutorTimeSummaryEndDate.getFullYear()}-${(this.tutorTimeSummaryEndDate.getMonth() + 1).toString().padStart(2, '0')}-${this.tutorTimeSummaryEndDate.getDate().toString().padStart(2, '0')}`; + + this.downloadCsvFn( + this.unit.downloadTutorTimesSummaryCsv( + this.tutorTimeSummaryStartDate, + this.tutorTimeSummaryEndDate, + this.hideSessionsDuringTutorials, + ), + 'Tutor Times Summary CSV', + `${this.unit.code}-tutor-times-summary-${start}-to-${end}-${!this.hideSessionsDuringTutorials ? 'incl-tutorials' : ''}.csv`, + ); + } + + public getMarkingSesssions() { + if (!this.canLoadSessions) { + return; + } + + this.canLoadSessions = false; + this.isLoading = true; + this.unit + .getUserMarkingSessions(this.tutorTimeSummaryStartDate, this.tutorTimeSummaryEndDate) + .subscribe({ + next: (data) => { + this.isLoading = false; + this.canLoadSessions = false; + this.events = data.map((session) => { + const tutor = this.unit.staff.find((t) => t.user.id === session.user.id); + + const primary = this.stringToHexColor(tutor.user.firstName); + const secondary = this.stringToHexColor(tutor.user.firstName); + return { + start: new Date(session.startTime), + end: new Date(session.endTime), + title: `${tutor?.user.firstName} (${session.durationMinutes}m) ${session.duringTutorial ? '(T)' : ''}`, + color: {primary: secondary, secondary: primary}, + user_id: session.user.id, + comments_added: session.commentsAdded, + assessments: session.assessments, + submissions_opened: session.submissionsOpened, + duration: session.durationMinutes, + duringTutorial: session.duringTutorial, + name: tutor?.user.firstName, + }; + }); + + this.filteredEvents = this.events.filter( + (row) => this.selectedUserId === null || row['user_id'] === this.selectedUserId, + ); + + console.log(data); + }, + error: (error) => { + this.canLoadSessions = false; + + console.error(error); + }, + }); + } + + eventClicked({event}: {event: CalendarEvent}): void { + if (event['user_id'] !== undefined) { + if (this.selectedUserId === null) { + this.selectedUserId = Number(event['user_id']); + } else { + this.selectedUserId = null; + } + this.applyFilters(); + } + } + + private stringToHexColor( + name: string, + opts?: {hue?: [number, number]; sat?: [number, number]; lit?: [number, number]}, + ): string { + const options = { + hue: opts?.hue || [0, 360], + sat: opts?.sat || [40, 70], // lower saturation → softer color + lit: opts?.lit || [75, 90], // higher lightness → pastel tone + }; + + const range = (hash: number, min: number, max: number) => { + const diff = max - min; + const x = ((hash % diff) + diff) % diff; + return x + min; + }; + + let hash = 0; + for (let i = 0; i < name.length; i++) { + hash = name.charCodeAt(i) + ((hash << 5) - hash); + hash = hash & hash; + } + + const h = range(hash, options.hue[0], options.hue[1]); + const s = range(hash, options.sat[0], options.sat[1]) / 100; + const l = range(hash, options.lit[0], options.lit[1]) / 100; + + const a = s * Math.min(l, 1 - l); + const f = (n: number) => { + const k = (n + h / 30) % 12; + const color = l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1)); + return Math.round(255 * color); + }; + + const toHex = (c: number) => c.toString(16).padStart(2, '0'); + return `#${toHex(f(0))}${toHex(f(8))}${toHex(f(4))}`; + } +} diff --git a/src/app/units/states/analytics/unit-analytics-route.component.html b/src/app/units/states/analytics/unit-analytics-route.component.html index 361c9ce18c..9388fae8d0 100644 --- a/src/app/units/states/analytics/unit-analytics-route.component.html +++ b/src/app/units/states/analytics/unit-analytics-route.component.html @@ -1,16 +1,24 @@

Unit Statistics

-
- - - - +
+ + + + + + + + + + @if (role === 'Convenor') { + + }
diff --git a/src/app/units/states/analytics/unit-analytics-route.component.ts b/src/app/units/states/analytics/unit-analytics-route.component.ts index 12e4770d84..73419c4dfe 100644 --- a/src/app/units/states/analytics/unit-analytics-route.component.ts +++ b/src/app/units/states/analytics/unit-analytics-route.component.ts @@ -1,7 +1,10 @@ -import {Component, Input} from '@angular/core'; +import {Component, Input, OnInit} from '@angular/core'; +import {MatDatepickerInputEvent} from '@angular/material/datepicker'; +import {CalendarEvent} from 'angular-calendar'; import {Observable} from 'rxjs'; import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; import {Unit} from 'src/app/api/models/unit'; +import {UserService} from 'src/app/api/services/user.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -18,8 +21,14 @@ export class UnitAnalyticsComponent { private sidekiqProgressModalService: SidekiqProgressModalService, private alertsService: AlertService, private fileDownloaderService: FileDownloaderService, + private userService: UserService, + private alertService: AlertService, ) {} + get role() { + return this.unit.staff.find((s) => s.user.id === this.userService.currentUser.id)?.role; + } + public getTaskCompletionCsv() { this.downloadCsv( this.unit.downloadTaskCompletionCsv(), diff --git a/src/styles.scss b/src/styles.scss index b0756f5acd..7eec75221c 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -4,6 +4,7 @@ @include mat.core(); @import './theme.scss'; +@import '../node_modules/angular-calendar/css/angular-calendar.css'; @tailwind base; @tailwind components; @@ -35,3 +36,8 @@ } } } + +.mat-mdc-progress-spinner circle, +.mat-spinner circle { + stroke: #ddd !important; +} From 376dad3125ed6757b997ef25e5866a43cb7919d0 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 13 Oct 2025 10:22:11 +1100 Subject: [PATCH 0664/1531] chore(release): 10.0.0-48 --- CHANGELOG.md | 12 ++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae329af052..f2b6a8e01e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-48](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-47...v10.0.0-48) (2025-10-12) + + +### Features + +* add tutor times summary download ([#1015](https://github.com/b0ink/doubtfire-deploy/issues/1015)) ([2b4afe2](https://github.com/b0ink/doubtfire-deploy/commit/2b4afe24e3f8139fec23337facc7656eec9a9d3a)) + + +### Bug Fixes + +* add assess in portfolio tasks as completed tasks in burndown chart ([8d36c94](https://github.com/b0ink/doubtfire-deploy/commit/8d36c94f03563a0924cfeb7d2d9e8dd911b65960)) + ## [10.0.0-47](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-46...v10.0.0-47) (2025-09-25) diff --git a/package-lock.json b/package-lock.json index cd419cdb8b..df15a9fd8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-47", + "version": "10.0.0-48", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-47", + "version": "10.0.0-48", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index f9eb667eef..f481fc788f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-47", + "version": "10.0.0-48", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From bb548b92d04bb7b8665444e7935317bc4b6a0981 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 13 Oct 2025 10:42:50 +1100 Subject: [PATCH 0665/1531] feat: display session start and end time --- .../directives/analytics-tutor-times.component.html | 1 + .../directives/analytics-tutor-times.component.ts | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html index faef0eaab1..2a8dccf5e1 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html @@ -66,6 +66,7 @@

Tutor Times Session Summary

>{{ event.name }} ({{ event.duration }} minutes) {{ event.duringTutorial ? 'T' : '' }}
+ {{ event.startHour }} — {{ event.endHour }}
Assessments: {{ event.assessments || 0 }}
Comments: {{ event.comments_added || 0 }}
Submissions opened: {{ event.submissions_opened || 0 }}
diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts index 19735552cc..a21aa9d230 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts @@ -177,6 +177,16 @@ export class AnalyticsTutorTimesComponent implements OnInit { return { start: new Date(session.startTime), end: new Date(session.endTime), + startHour: new Date(session.startTime).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + hour12: false, + }), + endHour: new Date(session.endTime).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + hour12: false, + }), title: `${tutor?.user.firstName} (${session.durationMinutes}m) ${session.duringTutorial ? '(T)' : ''}`, color: {primary: secondary, secondary: primary}, user_id: session.user.id, From a251c4f024b6dd9fa17b87cbafe3e0903dc18372 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 13 Oct 2025 10:44:02 +1100 Subject: [PATCH 0666/1531] chore(release): 10.0.0-49 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2b6a8e01e..0f0f746ac0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-49](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-48...v10.0.0-49) (2025-10-12) + + +### Features + +* display session start and end time ([bb548b9](https://github.com/b0ink/doubtfire-deploy/commit/bb548b92d04bb7b8665444e7935317bc4b6a0981)) + ## [10.0.0-48](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-47...v10.0.0-48) (2025-10-12) diff --git a/package-lock.json b/package-lock.json index df15a9fd8a..df3e8388b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-48", + "version": "10.0.0-49", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-48", + "version": "10.0.0-49", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index f481fc788f..2d1bf66d8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-48", + "version": "10.0.0-49", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 9a7a860fe799e351831e2a3f9701792792b76b38 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:44:54 +1100 Subject: [PATCH 0667/1531] feat: jplag base code (#1010) * feat: jplag base code * chore: reword base code description --- src/app/api/models/task-definition.ts | 1 + src/app/api/services/task-definition.service.ts | 1 + .../task-definition-upload.component.html | 13 +++++++++++++ 3 files changed, 15 insertions(+) diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index 0810326cdd..30aff474bf 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -54,6 +54,7 @@ export class TaskDefinition extends Entity { similarityLanguage: string = 'c'; hasJplagReport: boolean; assessInPortfolioOnly: boolean; + useResourcesForJplagBaseCode: boolean; public readonly taskPrerequisitesCache: EntityCache = new EntityCache(); diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 7692ab936b..63708814f8 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -136,6 +136,7 @@ export class TaskDefinitionService extends CachedEntityService { }); }, }, + 'useResourcesForJplagBaseCode', ); this.mapping.mapAllKeysToJsonExcept( diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html index 48d7fd0080..28015f48b3 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html @@ -113,4 +113,17 @@
+
+
+ + Use Task Resources for JPlag Base Code +

+ Base code is a common framework included in all submissions. When enabled, student code + matching this base code will be ignored during JPlag similarity checks. The base code will + be automatically extracted from the task resources. +

+
+
+
} From 059d54f5450da29b3e21a2b893116decd8df1879 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:45:26 +1100 Subject: [PATCH 0668/1531] chore(release): 10.0.0-50 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f0f746ac0..28de2191c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-50](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-49...v10.0.0-50) (2025-10-13) + + +### Features + +* jplag base code ([#1010](https://github.com/b0ink/doubtfire-deploy/issues/1010)) ([9a7a860](https://github.com/b0ink/doubtfire-deploy/commit/9a7a860fe799e351831e2a3f9701792792b76b38)) + ## [10.0.0-49](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-48...v10.0.0-49) (2025-10-12) diff --git a/package-lock.json b/package-lock.json index df3e8388b7..19dd45e590 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-49", + "version": "10.0.0-50", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-49", + "version": "10.0.0-50", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 2d1bf66d8f..dcc5e480c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-49", + "version": "10.0.0-50", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 173d8c25375e231b25e64a04c1e3d2aedf741300 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 14 Oct 2025 18:00:11 +1100 Subject: [PATCH 0669/1531] fix: unlock tasks when prerequisite requires rff and task is in aip state --- src/app/api/models/task-prerequisite.ts | 1 + .../task-definition-prerequisites.component.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/app/api/models/task-prerequisite.ts b/src/app/api/models/task-prerequisite.ts index 43450deedf..510d6ce3b6 100644 --- a/src/app/api/models/task-prerequisite.ts +++ b/src/app/api/models/task-prerequisite.ts @@ -21,6 +21,7 @@ export class TaskPrerequisite extends Entity { public readonly STATES: Partial> = { ready_for_feedback: 1, + assess_in_portfolio: 1, discuss: 2, demonstrate: 2, complete: 3, diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts index 1e11eed7ff..eff30b4bd3 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts @@ -35,6 +35,7 @@ export class TaskDefinitionPrerequisitesComponent implements OnInit, OnChanges { public readonly STATES: Partial> = { ready_for_feedback: 1, + assess_in_portfolio: 1, discuss: 2, demonstrate: 2, complete: 3, From 267fa1b27515184149543afdb2e87fbe9c915ef8 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 14 Oct 2025 18:03:40 +1100 Subject: [PATCH 0670/1531] chore(release): 10.0.0-51 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 6 +++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28de2191c2..08159fda97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-51](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-50...v10.0.0-51) (2025-10-14) + + +### Bug Fixes + +* unlock tasks when prerequisite requires rff and task is in aip state ([173d8c2](https://github.com/b0ink/doubtfire-deploy/commit/173d8c25375e231b25e64a04c1e3d2aedf741300)) + ## [10.0.0-50](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-49...v10.0.0-50) (2025-10-13) diff --git a/package-lock.json b/package-lock.json index 19dd45e590..38c5bd3f5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-50", + "version": "10.0.0-51", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-50", + "version": "10.0.0-51", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index dcc5e480c8..d45df0c039 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-50", + "version": "10.0.0-51", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", @@ -16,8 +16,8 @@ "lint": "ng lint", "serve:angular17": "export NODE_OPTIONS=--max_old_space_size=4096 && ng serve --poll=2000 --configuration $NODE_ENV --proxy-config proxy.conf.json", "serve:angular17-compose": "export NODE_OPTIONS=--max_old_space_size=4096 && ng serve --configuration $NODE_ENV --proxy-config proxy-compose.conf.json", - "start": "npm-run-all -l -s build:angular1 serve:angular17", - "start-compose": "npm-run-all -l -s build:angular1 serve:angular17-compose", + "start": "npm-run-all -l -s build:angular1 -p watch:angular1 serve:angular17", + "start-compose": "npm-run-all -l -s build:angular1 -p watch:angular1 serve:angular17-compose", "watch:angular1": "grunt delta", "deploy:build2api": "ng build --delete-output-path=true --optimization=true --configuration production --output-path dist", "deploy": "run-s -l build:angular1 deploy:build2api", From 5c0b528d774cac7d73de28e6e9ec16c9d109e955 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 15 Oct 2025 10:03:30 +1100 Subject: [PATCH 0671/1531] chore: filter out sessions with less than 1 minute duration --- .../analytics-tutor-times.component.ts | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts index a21aa9d230..3572e946ea 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts @@ -8,6 +8,25 @@ import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloa import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; +interface SessionEvent { + start: Date; + end: Date; + startHour: string; + endHour: string; + title: string; + color: { + primary: string; + secondary: string; + }; + userId: number; + commentsAdded: number; + assessments: number; + submissionsOpened: number; + duration: number; + duringTutorial: boolean; + tutorName: string; +} + @Component({ selector: 'f-analytics-tutor-times', templateUrl: 'analytics-tutor-times.component.html', @@ -25,7 +44,7 @@ export class AnalyticsTutorTimesComponent implements OnInit { selectedUserId: number | null = null; viewDate = new Date(); - events = []; + events: SessionEvent[] = []; filteredEvents = []; tutorTimeSummaryStartDate: Date; @@ -100,7 +119,8 @@ export class AnalyticsTutorTimesComponent implements OnInit { this.filteredEvents = this.events.filter( (e) => (this.selectedUserId === null || e['user_id'] === this.selectedUserId) && - (!this.hideSessionsDuringTutorials || !e['duringTutorial']), + (!this.hideSessionsDuringTutorials || !e['duringTutorial']) && + e.duration >= 1, ); } @@ -120,7 +140,6 @@ export class AnalyticsTutorTimesComponent implements OnInit { this.alertService.error('You cannot select more than a year', 3000); return; } - console.log('diff days', diffDays); if (diffDays < 1) { this.tutorTimeSummaryStartDate = this.tutorTimeSummaryEndDate; this.alertService.error('End date must be on or after the start date'); @@ -189,21 +208,17 @@ export class AnalyticsTutorTimesComponent implements OnInit { }), title: `${tutor?.user.firstName} (${session.durationMinutes}m) ${session.duringTutorial ? '(T)' : ''}`, color: {primary: secondary, secondary: primary}, - user_id: session.user.id, - comments_added: session.commentsAdded, + userId: session.user.id, + commentsAdded: session.commentsAdded, assessments: session.assessments, - submissions_opened: session.submissionsOpened, + submissionsOpened: session.submissionsOpened, duration: session.durationMinutes, duringTutorial: session.duringTutorial, - name: tutor?.user.firstName, + tutorName: tutor?.user.firstName, }; }); - this.filteredEvents = this.events.filter( - (row) => this.selectedUserId === null || row['user_id'] === this.selectedUserId, - ); - - console.log(data); + this.applyFilters(); }, error: (error) => { this.canLoadSessions = false; From 5c0c9974569e720a6c95aa8333c2a38d0ab4a1b0 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 15 Oct 2025 11:40:19 +1100 Subject: [PATCH 0672/1531] fix: filter out students from unit staff editor (#1018) --- .../unit-staff-editor/unit-staff-editor.component.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts index f64d62d921..f161c384aa 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts @@ -145,7 +145,10 @@ export class UnitStaffEditorComponent implements OnInit { this.filteredStaff = this.staff.filter( (staff) => staff.matches(this.searchTerm.toLowerCase()) && // Find by name - !this.unit.staff.find((listStaff) => staff.id === listStaff.user.id), // Not already assigned to the unit + !this.unit.staff.find((listStaff) => staff.id === listStaff.user.id) && // Not already assigned to the unit + // Filter out students from the staff search + // NOTE: This is a hotfix to an issue where loading the inbox populates this.staff with students... + staff.isStaff, ); } From 4487865ed551af44adcad8de01f062cdc258dc11 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 15 Oct 2025 14:45:35 +1100 Subject: [PATCH 0673/1531] refactor: send timezone of client to the api (#1019) --- src/app/api/models/unit.ts | 11 ++++++++++- .../directives/analytics-tutor-times.component.ts | 11 ++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index b144a53bb3..37b27568a4 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -605,7 +605,11 @@ export class Unit extends Entity { ); } - public getUserMarkingSessions(startDate?: Date, endDate?: Date): Observable { + public getUserMarkingSessions( + startDate?: Date, + endDate?: Date, + timezone?: string, + ): Observable { let params = new HttpParams(); if (startDate) { params = params.set( @@ -621,6 +625,8 @@ export class Unit extends Entity { ); } + params = params.set('timezone', timezone); + // TODO: we should cache the data by the same start/end date const markingSessionService = AppInjector.get(MarkingSessionService); return markingSessionService.fetchAll( @@ -634,6 +640,7 @@ export class Unit extends Entity { public downloadTutorTimesSummaryCsv( startDate?: Date, endDate?: Date, + timezone?: string, ignoreSessionsDuringTutorials?: boolean, ): Observable { let params = new HttpParams(); @@ -652,6 +659,8 @@ export class Unit extends Entity { ); } + params = params.set('timezone', timezone); + params = params.set('ignore_sessions_during_tutorials', ignoreSessionsDuringTutorials ?? false); return AppInjector.get(HttpClient).get( diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts index 3572e946ea..dc6aa29351 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts @@ -164,14 +164,17 @@ export class AnalyticsTutorTimesComponent implements OnInit { const start = `${this.tutorTimeSummaryStartDate.getFullYear()}-${(this.tutorTimeSummaryStartDate.getMonth() + 1).toString().padStart(2, '0')}-${this.tutorTimeSummaryStartDate.getDate().toString().padStart(2, '0')}`; const end = `${this.tutorTimeSummaryEndDate.getFullYear()}-${(this.tutorTimeSummaryEndDate.getMonth() + 1).toString().padStart(2, '0')}-${this.tutorTimeSummaryEndDate.getDate().toString().padStart(2, '0')}`; + const tz = Intl.DateTimeFormat().resolvedOptions().timeZone; + this.downloadCsvFn( this.unit.downloadTutorTimesSummaryCsv( this.tutorTimeSummaryStartDate, this.tutorTimeSummaryEndDate, + tz, this.hideSessionsDuringTutorials, ), 'Tutor Times Summary CSV', - `${this.unit.code}-tutor-times-summary-${start}-to-${end}-${!this.hideSessionsDuringTutorials ? 'incl-tutorials' : ''}.csv`, + `${this.unit.code}-tutor-times-summary-${start}-to-${end}-${tz}-${!this.hideSessionsDuringTutorials ? 'incl-tutorials' : ''}.csv`, ); } @@ -180,10 +183,12 @@ export class AnalyticsTutorTimesComponent implements OnInit { return; } + const tz = Intl.DateTimeFormat().resolvedOptions().timeZone; + this.canLoadSessions = false; this.isLoading = true; this.unit - .getUserMarkingSessions(this.tutorTimeSummaryStartDate, this.tutorTimeSummaryEndDate) + .getUserMarkingSessions(this.tutorTimeSummaryStartDate, this.tutorTimeSummaryEndDate, tz) .subscribe({ next: (data) => { this.isLoading = false; @@ -222,7 +227,7 @@ export class AnalyticsTutorTimesComponent implements OnInit { }, error: (error) => { this.canLoadSessions = false; - + this.alertService.error(`Failed to load sessions: ${error}`, 6000); console.error(error); }, }); From e3fbe4404661eb16b9c0e5ba19a1369dac1fb5b0 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 15 Oct 2025 16:11:24 +1100 Subject: [PATCH 0674/1531] feat: download marking sessions for tutor --- src/app/api/models/unit.ts | 29 +++++++++++++++++++ .../analytics-tutor-times.component.html | 29 +++++++++++++------ .../analytics-tutor-times.component.ts | 19 ++++++++++++ 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index 37b27568a4..8306a94f12 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -669,6 +669,35 @@ export class Unit extends Entity { ); } + public downloadMyTutorTimeSessionsCsv( + startDate?: Date, + endDate?: Date, + timezone?: string, + ): Observable { + let params = new HttpParams(); + + if (startDate) { + params = params.set( + 'start_date', + `${startDate.getFullYear()}-${(startDate.getMonth() + 1).toString().padStart(2, '0')}-${startDate.getDate().toString().padStart(2, '0')}`, + ); + } + + if (endDate) { + params = params.set( + 'end_date', + `${endDate.getFullYear()}-${(endDate.getMonth() + 1).toString().padStart(2, '0')}-${endDate.getDate().toString().padStart(2, '0')}`, + ); + } + + params = params.set('timezone', timezone); + + return AppInjector.get(HttpClient).get( + `${AppInjector.get(DoubtfireConstants).API_URL}/csv/units/${this.id}/my_marking_sessions`, + {params}, + ); + } + public hasD2lMapping(): boolean { const doubtfireConstants = AppInjector.get(DoubtfireConstants); return ( diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html index 2a8dccf5e1..ba944fc26c 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html @@ -4,15 +4,26 @@

Tutor Times Session Summary

- +
+ + +
diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts index dc6aa29351..7e99793801 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts @@ -4,6 +4,7 @@ import {CalendarEvent} from 'angular-calendar'; import {Observable} from 'rxjs'; import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; import {Unit} from 'src/app/api/models/unit'; +import {UserService} from 'src/app/api/services/user.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -60,6 +61,7 @@ export class AnalyticsTutorTimesComponent implements OnInit { private alertService: AlertService, private sidekiqProgressModalService: SidekiqProgressModalService, private fileDownloaderService: FileDownloaderService, + private userService: UserService, ) {} ngOnInit(): void { @@ -178,6 +180,23 @@ export class AnalyticsTutorTimesComponent implements OnInit { ); } + public getMyTutorTimesSessions() { + const start = `${this.tutorTimeSummaryStartDate.getFullYear()}-${(this.tutorTimeSummaryStartDate.getMonth() + 1).toString().padStart(2, '0')}-${this.tutorTimeSummaryStartDate.getDate().toString().padStart(2, '0')}`; + const end = `${this.tutorTimeSummaryEndDate.getFullYear()}-${(this.tutorTimeSummaryEndDate.getMonth() + 1).toString().padStart(2, '0')}-${this.tutorTimeSummaryEndDate.getDate().toString().padStart(2, '0')}`; + + const tz = Intl.DateTimeFormat().resolvedOptions().timeZone; + + this.downloadCsvFn( + this.unit.downloadMyTutorTimeSessionsCsv( + this.tutorTimeSummaryStartDate, + this.tutorTimeSummaryEndDate, + tz, + ), + 'My Marking Sessions CSV', + `${this.unit.code}-${this.userService.currentUser.name}-sessions-${start}-to-${end}-${tz}}.csv`, + ); + } + public getMarkingSesssions() { if (!this.canLoadSessions) { return; From 89560205d7316c53d77f376b5f7cfff5bf99e9c6 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 15 Oct 2025 16:23:36 +1100 Subject: [PATCH 0675/1531] fix: display tutor name --- .../analytics/directives/analytics-tutor-times.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html index ba944fc26c..717fac9603 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html @@ -74,7 +74,7 @@

Tutor Times Session Summary

{{ event.name }} ({{ event.duration }} minutes) + >{{ event.tutorName }} ({{ event.duration }} minutes) {{ event.duringTutorial ? 'T' : '' }}
{{ event.startHour }} — {{ event.endHour }}
From 4435fea9daaa3566ec9f1fb86aea9caad7645ce0 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 15 Oct 2025 16:25:16 +1100 Subject: [PATCH 0676/1531] refactor: expand hour segments ui --- .../analytics/directives/analytics-tutor-times.component.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html index 717fac9603..e2123b30c3 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html @@ -100,8 +100,10 @@

Tutor Times Session Summary

(eventClicked)="eventClicked($event)" [tooltipTemplate]="eventTooltipTemplate" [hourDuration]="60" - [hourSegments]="1" + [hourSegments]="4" [weekStartsOn]="0" + [hourSegmentHeight]="15" + [minimumEventHeight]="5" [daysInWeek]="daysInWeek" (beforeViewRender)="beforeViewRender($event)" /> From 697daf26693f20f61dcfbbeb0597a02715c9512d Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 15 Oct 2025 16:41:55 +1100 Subject: [PATCH 0677/1531] fix: re-enable user filtering on click --- .../directives/analytics-tutor-times.component.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts index 7e99793801..a60a756699 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts @@ -120,8 +120,8 @@ export class AnalyticsTutorTimesComponent implements OnInit { applyFilters() { this.filteredEvents = this.events.filter( (e) => - (this.selectedUserId === null || e['user_id'] === this.selectedUserId) && - (!this.hideSessionsDuringTutorials || !e['duringTutorial']) && + (this.selectedUserId === null || e.userId === this.selectedUserId) && + (!this.hideSessionsDuringTutorials || !e.duringTutorial) && e.duration >= 1, ); } @@ -252,10 +252,10 @@ export class AnalyticsTutorTimesComponent implements OnInit { }); } - eventClicked({event}: {event: CalendarEvent}): void { - if (event['user_id'] !== undefined) { + eventClicked({event}: {event: SessionEvent}): void { + if (event.userId !== undefined) { if (this.selectedUserId === null) { - this.selectedUserId = Number(event['user_id']); + this.selectedUserId = Number(event.userId); } else { this.selectedUserId = null; } From 85518268d0720f88ed7844c9af4bf187a3c49a60 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 15 Oct 2025 16:52:45 +1100 Subject: [PATCH 0678/1531] refactor: migrate group members list (#1017) * refactor: init group members list migration * refactor: migrate group members list * chore: update loading text * chore: remove old component files --- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 7 +- .../group-member-list.coffee | 58 ---------------- .../group-member-list.component.html | 55 +++++++++++++++ .../group-member-list.component.scss | 0 .../group-member-list.component.ts | 68 +++++++++++++++++++ .../group-member-list/group-member-list.scss | 6 -- .../group-member-list.tpl.html | 55 --------------- .../group-set-manager.tpl.html | 14 ++-- src/app/groups/groups.coffee | 1 - 10 files changed, 138 insertions(+), 128 deletions(-) delete mode 100644 src/app/groups/group-member-list/group-member-list.coffee create mode 100644 src/app/groups/group-member-list/group-member-list.component.html create mode 100644 src/app/groups/group-member-list/group-member-list.component.scss create mode 100644 src/app/groups/group-member-list/group-member-list.component.ts delete mode 100644 src/app/groups/group-member-list/group-member-list.scss delete mode 100644 src/app/groups/group-member-list/group-member-list.tpl.html diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 5396335ffe..ff8b001f19 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -280,6 +280,7 @@ const MY_DATE_FORMAT = { import {TutorialsComponent} from './projects/states/tutorials/tutorials.component'; import {UnitStudentEnrolmentModalComponent} from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component'; import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-chart/taskstatuspiechart.component'; +import {GroupMemberListComponent} from './groups/group-member-list/group-member-list.component'; @NgModule({ // Components we declare @@ -409,6 +410,7 @@ import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-char UnitStaffEditorComponent, GroupSetSelectorComponent, PortfolioGradeSelectStepComponent, + GroupMemberListComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index ade3d4e6d3..c3fe30e065 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -82,7 +82,6 @@ import 'build/src/app/groups/group-selector/group-selector.js'; import 'build/src/app/groups/group-set-manager/group-set-manager.js'; import 'build/src/app/groups/groups.js'; import 'build/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.js'; -import 'build/src/app/groups/group-member-list/group-member-list.js'; import 'build/src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.js'; import 'build/src/app/units/modals/modals.js'; import 'build/src/app/units/units.js'; @@ -223,6 +222,7 @@ import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; +import {GroupMemberListComponent} from './groups/group-member-list/group-member-list.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -530,3 +530,8 @@ DoubtfireAngularJSModule.directive( 'groupSetSelector', downgradeComponent({component: GroupSetSelectorComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fGroupMemberList', + downgradeComponent({component: GroupMemberListComponent}), +); diff --git a/src/app/groups/group-member-list/group-member-list.coffee b/src/app/groups/group-member-list/group-member-list.coffee deleted file mode 100644 index ddb80ece67..0000000000 --- a/src/app/groups/group-member-list/group-member-list.coffee +++ /dev/null @@ -1,58 +0,0 @@ -angular.module('doubtfire.groups.group-member-list', []) - -# -# Lists members in a group -# -.directive('groupMemberList', -> - restrict: 'E' - templateUrl: 'groups/group-member-list/group-member-list.tpl.html' - scope: - unit: '=' - project: '=' - unitRole: '=' - selectedGroup: '=' - onMembersLoaded: '=?' - controller: ($scope, $timeout, gradeService, alertService, listenerService) -> - # Cleanup - listeners = listenerService.listenTo($scope) - - # Initial sort orders - $scope.tableSort = - order: 'student_name' - reverse: false - - # Table sorting - $scope.sortTableBy = (column) -> - $scope.tableSort.order = column - $scope.tableSort.reverse = !$scope.tableSort.reverse - - # Loading - startLoading = -> $scope.loaded = false - finishLoading = -> $timeout(-> - $scope.loaded = true - $scope.onMembersLoaded?() - , 500) - - # Initially not loaded - $scope.loaded = false - - # Remove group members - $scope.removeMember = (member) -> - $scope.selectedGroup.removeMember(member) - - # Listen for changes to group - listeners.push $scope.$watch "selectedGroup.id", (newGroupId) -> - return unless newGroupId? - startLoading() - $scope.canRemoveMembers = $scope.unitRole || ($scope.selectedGroup.groupSet.allowStudentsToManageGroups && !$scope.selectedGroup.locked) - - $scope.selectedGroup.getMembers().subscribe({ - next: (members) -> - finishLoading() - error: (failure) -> - $timeout((-> - alertService.error( "Unauthorised to view members in this group", 3000) - $scope.selectedGroup = null - ), 1000) - }) -) diff --git a/src/app/groups/group-member-list/group-member-list.component.html b/src/app/groups/group-member-list/group-member-list.component.html new file mode 100644 index 0000000000..8d334d5640 --- /dev/null +++ b/src/app/groups/group-member-list/group-member-list.component.html @@ -0,0 +1,55 @@ +@if (loading) { +
+ Loading members... +
+} @else if (selectedGroup.members.length === 0) { +
+ group_off +

There are no members in this group

+
+} @else { + + + + + + + + + + + + + + + + + + + + + + + +
{{ unitRole ? 'Student ID' : '' }} + @if (unitRole) { + {{ member.student.username || 'N/A' }} + } + Name + {{ member.student.name }} + {{ unitRole ? 'Target Grade' : '' }} + @if (unitRole) { + + } + {{ canRemoveMembers ? 'Actions' : '' }} + @if (canRemoveMembers) { + @if (!project && unitRole) { + + } @else if (project && project.id === member.id) { + + } + } +
+} diff --git a/src/app/groups/group-member-list/group-member-list.component.scss b/src/app/groups/group-member-list/group-member-list.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/groups/group-member-list/group-member-list.component.ts b/src/app/groups/group-member-list/group-member-list.component.ts new file mode 100644 index 0000000000..e7f0e9f312 --- /dev/null +++ b/src/app/groups/group-member-list/group-member-list.component.ts @@ -0,0 +1,68 @@ +import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import {MatTableDataSource} from '@angular/material/table'; +import {Subscription} from 'rxjs'; +import {Group, UnitRole} from 'src/app/api/models/doubtfire-model'; +import {Project} from 'src/app/api/models/project'; +import {Unit} from 'src/app/api/models/unit'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-group-member-list', + templateUrl: './group-member-list.component.html', + styleUrls: ['./group-member-list.component.scss'], +}) +export class GroupMemberListComponent implements OnInit, OnChanges { + @Input() unit: Unit; + @Input() unitRole: UnitRole; + @Input() project: Project; + @Input() selectedGroup: Group; + @Input() onMembersLoaded: () => void; + + loading = false; + + canRemoveMembers = false; + + displayedColumns: string[] = ['student_id', 'name', 'target_grade', 'actions']; + groupMembers: Project[] = []; + dataSource = new MatTableDataSource(); + + private groupMembersSub?: Subscription; + + constructor(private alertService: AlertService) {} + + ngOnInit() { + this.groupMembersSub = this.selectedGroup.projectsCache.values.subscribe((values) => { + this.dataSource.data = values; + }); + } + + public removeMember(member: Project) { + this.selectedGroup.removeMember(member); + } + + ngOnChanges(changes: SimpleChanges) { + if (changes['selectedGroup'] && this.selectedGroup) { + this.loading = true; + this.selectedGroup.getMembers().subscribe({ + next: (members) => { + this.loading = false; + this.onMembersLoaded(); + this.canRemoveMembers = + !!this.unitRole || + (this.selectedGroup.groupSet.allowStudentsToManageGroups && !this.selectedGroup.locked); + + this.dataSource.data = members; + + this.groupMembersSub?.unsubscribe(); + this.groupMembersSub = this.selectedGroup.projectsCache.values.subscribe((values) => { + this.dataSource.data = values; + }); + }, + error: (error) => { + this.alertService.error(`Failed to fetch group members: ${error}`, 6000); + this.selectedGroup = null; + }, + }); + } + } +} diff --git a/src/app/groups/group-member-list/group-member-list.scss b/src/app/groups/group-member-list/group-member-list.scss deleted file mode 100644 index 75fb259794..0000000000 --- a/src/app/groups/group-member-list/group-member-list.scss +++ /dev/null @@ -1,6 +0,0 @@ -group-member-list table { - th.student-id { width: 25%; } - th.student-name { width: 50%; } - th.actions { width: 25%; } - th.student-grade { width: 50%; } -} diff --git a/src/app/groups/group-member-list/group-member-list.tpl.html b/src/app/groups/group-member-list/group-member-list.tpl.html deleted file mode 100644 index 8c3b3c2dc5..0000000000 --- a/src/app/groups/group-member-list/group-member-list.tpl.html +++ /dev/null @@ -1,55 +0,0 @@ -
- Loading Members... -
-
-
-

No members in group

-

There are no members in this group

-
-
- - - - - - - - - - - - - - - - - -
- - Student ID - - - - - Name - - - - - Target Grade - - - - Actions -
{{member.student.username || "N/A"}}{{member.student.name}} - - - - -
diff --git a/src/app/groups/group-set-manager/group-set-manager.tpl.html b/src/app/groups/group-set-manager/group-set-manager.tpl.html index 09386b1daa..da022a0b37 100644 --- a/src/app/groups/group-set-manager/group-set-manager.tpl.html +++ b/src/app/groups/group-set-manager/group-set-manager.tpl.html @@ -56,13 +56,13 @@

- - +
diff --git a/src/app/groups/groups.coffee b/src/app/groups/groups.coffee index 391a78d492..3d4534d754 100644 --- a/src/app/groups/groups.coffee +++ b/src/app/groups/groups.coffee @@ -1,6 +1,5 @@ angular.module('doubtfire.groups', [ 'doubtfire.groups.group-member-contribution-assigner' - 'doubtfire.groups.group-member-list' 'doubtfire.groups.group-selector' 'doubtfire.groups.group-set-manager' ]) From 7ea20939f45b013a56cc3405faaf0855ebe9926a Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Thu, 16 Oct 2025 15:18:48 +1100 Subject: [PATCH 0679/1531] refactor: collapse related tutorial list --- .../task-definition-who.component.html | 37 ++++++++++++++++--- .../task-definition-who.component.ts | 5 +++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html index 814e814197..5d93345d7f 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html @@ -13,7 +13,11 @@
Tutorial Stream - Which tutor provides feedback? - + @for (stream of unit.tutorialStreams; track stream) { {{ stream.name }} } @@ -23,11 +27,32 @@ Related tutorials
    - @for (tutorial of taskDefinition.tutorialStream?.tutorialsIn(unit); track tutorial) { -
  • - {{ tutorial?.abbreviation }} {{ tutorial.tutor?.name }} -
  • -} + @for ( + tutorial of taskDefinition.tutorialStream?.tutorialsIn(unit) + | slice: 0 : (showAllTutorials ? undefined : 3); + track tutorial + ) { +
  • {{ tutorial?.abbreviation }} {{ tutorial.tutor?.name }}
  • + } + + @if (!showAllTutorials && taskDefinition.tutorialStream?.tutorialsIn(unit)?.length > 3) { +
  • + +{{ taskDefinition.tutorialStream.tutorialsIn(unit).length - 3 }} more tutorials +
  • + } + @if (taskDefinition.tutorialStream?.tutorialsIn(unit).length > 3) { +
    + @if (!showAllTutorials) { + + } @else { + + } +
    + }
diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts index 9732998592..53c87c7bf1 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts @@ -10,7 +10,12 @@ import { Unit } from 'src/app/api/models/unit'; export class TaskDefinitionWhoComponent { @Input() taskDefinition: TaskDefinition; + showAllTutorials: boolean = false; public get unit(): Unit { return this.taskDefinition?.unit; } + + onTutorialStreamChange() { + this.showAllTutorials = false; + } } From 4384b376eaedf8ab66febec4c0ada53111311ff0 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Fri, 17 Oct 2025 09:38:43 +1100 Subject: [PATCH 0680/1531] feat: campus timezone (#1022) --- .../campus-list/campus-list.component.html | 24 +++++++++++++++++++ .../campus-list/campus-list.component.ts | 4 +++- src/app/api/models/campus/campus.ts | 1 + src/app/api/services/campus.service.ts | 2 +- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html index 3fe38272ec..6fed39bc24 100644 --- a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html +++ b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html @@ -83,6 +83,30 @@

Campuses

+ + + Timezone + + @if (!editing(campus)) { +
+ {{ campus.timezone }} +
+ } @else { + + Timezone + + + + } + + + + Timezone + + + +
+ Active diff --git a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts index 3ab6b9e71e..1fa8871cc3 100644 --- a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts +++ b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts @@ -18,7 +18,7 @@ export class CampusListComponent extends EntityFormComponent { syncModes = ['timetable', 'automatic', 'manual']; // Set up the table - columns: string[] = ['name', 'abbreviation', 'mode', 'active', 'options']; + columns: string[] = ['name', 'abbreviation', 'mode', 'timezone', 'active', 'options']; campuses: Campus[] = new Array(); dataSource = new MatTableDataSource(this.campuses); @@ -33,6 +33,7 @@ export class CampusListComponent extends EntityFormComponent { abbreviation: new UntypedFormControl('', [Validators.required]), name: new UntypedFormControl('', [Validators.required]), mode: new UntypedFormControl('', [Validators.required]), + timezone: new UntypedFormControl('', [Validators.required]), active: new UntypedFormControl(false), }, 'Campus', @@ -91,6 +92,7 @@ export class CampusListComponent extends EntityFormComponent { case 'name': case 'abbreviation': case 'mode': + case 'timezone': case 'active': return super.sortTableData(sort); } diff --git a/src/app/api/models/campus/campus.ts b/src/app/api/models/campus/campus.ts index 164b3704f6..9491e29e53 100644 --- a/src/app/api/models/campus/campus.ts +++ b/src/app/api/models/campus/campus.ts @@ -7,6 +7,7 @@ export class Campus extends Entity { name: string; mode: campusModes; abbreviation: string; + timezone: string; public override toJson(mappingData: EntityMapping, ignoreKeys?: string[]): object { return { diff --git a/src/app/api/services/campus.service.ts b/src/app/api/services/campus.service.ts index ddf3e95942..d46d793cc3 100644 --- a/src/app/api/services/campus.service.ts +++ b/src/app/api/services/campus.service.ts @@ -11,7 +11,7 @@ export class CampusService extends CachedEntityService { constructor(httpClient: HttpClient) { super(httpClient, API_URL); - this.mapping.addKeys('id', 'name', 'mode', 'abbreviation', 'active'); + this.mapping.addKeys('id', 'name', 'mode', 'abbreviation', 'active', 'timezone'); this.mapping.mapAllKeysToJsonExcept('id'); } From 1b08535443ffc7723d018c518cf7d77b12920a0e Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 17 Oct 2025 10:08:20 +1100 Subject: [PATCH 0681/1531] refactor: enable marking sessions calendar for tutors --- .../analytics-tutor-times.component.html | 21 +++++++++++-------- .../analytics-tutor-times.component.ts | 4 ++++ .../unit-analytics-route.component.html | 4 +--- .../unit-analytics-route.component.ts | 2 +- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html index e2123b30c3..d826a68de2 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html @@ -5,15 +5,18 @@

Tutor Times Session Summary

- + @if (role === 'Convenor') { + + } +
diff --git a/src/app/units/states/analytics/unit-analytics-route.component.ts b/src/app/units/states/analytics/unit-analytics-route.component.ts index 73419c4dfe..4c8e068722 100644 --- a/src/app/units/states/analytics/unit-analytics-route.component.ts +++ b/src/app/units/states/analytics/unit-analytics-route.component.ts @@ -61,7 +61,7 @@ export class UnitAnalyticsComponent { ); } - private downloadCsv(newJob: Observable, title: string, filename: string) { + public downloadCsv(newJob: Observable, title: string, filename: string) { newJob.subscribe({ next: (job) => { if (!job || !job.id) { From b972dde2047172cc45f1756d866e07f54c8a355d Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 17 Oct 2025 12:00:03 +1100 Subject: [PATCH 0682/1531] chore(release): 10.0.0-52 --- CHANGELOG.md | 15 +++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08159fda97..e1c0f0d73d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-52](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-51...v10.0.0-52) (2025-10-17) + + +### Features + +* campus timezone ([#1022](https://github.com/b0ink/doubtfire-deploy/issues/1022)) ([4384b37](https://github.com/b0ink/doubtfire-deploy/commit/4384b376eaedf8ab66febec4c0ada53111311ff0)) +* download marking sessions for tutor ([e3fbe44](https://github.com/b0ink/doubtfire-deploy/commit/e3fbe4404661eb16b9c0e5ba19a1369dac1fb5b0)) + + +### Bug Fixes + +* display tutor name ([8956020](https://github.com/b0ink/doubtfire-deploy/commit/89560205d7316c53d77f376b5f7cfff5bf99e9c6)) +* filter out students from unit staff editor ([#1018](https://github.com/b0ink/doubtfire-deploy/issues/1018)) ([5c0c997](https://github.com/b0ink/doubtfire-deploy/commit/5c0c9974569e720a6c95aa8333c2a38d0ab4a1b0)) +* re-enable user filtering on click ([697daf2](https://github.com/b0ink/doubtfire-deploy/commit/697daf26693f20f61dcfbbeb0597a02715c9512d)) + ## [10.0.0-51](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-50...v10.0.0-51) (2025-10-14) diff --git a/package-lock.json b/package-lock.json index 38c5bd3f5f..5a2e04aac3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-51", + "version": "10.0.0-52", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-51", + "version": "10.0.0-52", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index d45df0c039..3356d560a7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-51", + "version": "10.0.0-52", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 3b684a3395c9ccdfb412ff439a08e2ab88f808d7 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Fri, 17 Oct 2025 13:50:45 +1100 Subject: [PATCH 0683/1531] refactor: include all submitted tasks in portfolio task list (#1023) * refactor: include all submitted tasks in portfolio task list * refactor: fetch tasks included in portfolio from api * refactor: reword * refactor: reword * refactor: show warning if no tasks found * refactor: wording * refactor: add error alert --- src/app/api/models/project.ts | 9 +++++ src/app/doubtfire-angular.module.ts | 2 ++ src/app/doubtfire-angularjs.module.ts | 6 ++++ .../portfolio-included-tasks.component.html | 26 ++++++++++++++ .../portfolio-included-tasks.component.scss | 0 .../portfolio-included-tasks.component.ts | 36 +++++++++++++++++++ .../portfolio-review-step.tpl.html | 22 +++++------- .../states/portfolio/portfolio.coffee | 2 +- 8 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.html create mode 100644 src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.scss create mode 100644 src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.ts diff --git a/src/app/api/models/project.ts b/src/app/api/models/project.ts index 1064fb3c5b..df3c3cda26 100644 --- a/src/app/api/models/project.ts +++ b/src/app/api/models/project.ts @@ -528,4 +528,13 @@ export class Project extends Entity { }), ); } + + public tasksIncludedInPortfolioUrl(): string { + return `${AppInjector.get(DoubtfireConstants).API_URL}/projects/${this.id}/portfolio_tasks`; + } + + public getTasksIncludedInPortfolio(): Observable { + const httpClient = AppInjector.get(HttpClient); + return httpClient.get(this.tasksIncludedInPortfolioUrl()); + } } diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 47e4679234..12f65dc8a5 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -293,6 +293,7 @@ import {UnitDetailsEditorComponent} from './units/states/edit/directives/unit-de import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; import {AnalyticsTutorTimesComponent} from './units/states/analytics/directives/analytics-tutor-times.component'; import {MarkingSessionService} from './api/services/marking-session.service'; +import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -446,6 +447,7 @@ const MY_DATE_FORMAT = { UnitDetailsEditorComponent, PortfolioGradeSelectStepComponent, AnalyticsTutorTimesComponent, + PortfolioIncludedTasksComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 963bf7d209..886886135c 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -230,6 +230,7 @@ import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staf import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-selector.component'; import {UnitDetailsEditorComponent} from './units/states/edit/directives/unit-details-editor/unit-details-editor.component'; import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; +import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component'; export const DoubtfireAngularJSModule = angular .module('doubtfire', [ @@ -557,3 +558,8 @@ DoubtfireAngularJSModule.directive( 'groupSetSelector', downgradeComponent({component: GroupSetSelectorComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fPortfolioIncludedTasks', + downgradeComponent({component: PortfolioIncludedTasksComponent}), +); diff --git a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.html b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.html new file mode 100644 index 0000000000..7444d7176c --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.html @@ -0,0 +1,26 @@ +@if (loading) { +
+
Loading tasks...
+ +
+} @else { + @if (tasksInPortfolio.length === 0) { +
+ assignment_late +

No tasks found

+
+ } @else { +
    + @for (task of tasksInPortfolio; track task) { +
  1. +
    +
    +
    {{ task.definition.abbreviation }} — {{ task.definition.name }}
    +
    + +
    +
  2. + } +
+ } +} diff --git a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.scss b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.ts b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.ts new file mode 100644 index 0000000000..e425d93976 --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.ts @@ -0,0 +1,36 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {Project} from 'src/app/api/models/project'; +import {Task} from 'src/app/api/models/task'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-portfolio-included-tasks', + templateUrl: 'portfolio-included-tasks.component.html', + styleUrls: ['portfolio-included-tasks.component.scss'], +}) +export class PortfolioIncludedTasksComponent implements OnInit { + @Input() project: Project; + + constructor(private alertService: AlertService) {} + + loading: boolean = false; + + tasksInPortfolio: Task[] = []; + ngOnInit() { + this.loading = true; + this.project.getTasksIncludedInPortfolio().subscribe({ + next: (tasks) => { + for (const taskId of tasks) { + const task = this.project.tasks.find((t) => t.id === taskId); + if (task) { + this.tasksInPortfolio.push(task); + } + } + this.loading = false; + }, + error: (error) => { + this.alertService.error(`Failed to get tasks for portfolio: ${error}`, 6000); + }, + }); + } +} diff --git a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.tpl.html b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.tpl.html index ba23ed6f53..00dffc0906 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.tpl.html +++ b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.tpl.html @@ -51,19 +51,15 @@

Portfolio Processing

  • {{file.name}}
  • -
    -

    - You have included {{selectedTasks().length}} tasks in your portfolio. If you wish to add or - remove some of these tasks, please review the Select Tasks step to adjust your alignments of each - task to the unit's learning outcomes. Each task will be attached in the order below: -

    -
      -
    1. - - {{task.definition.name}} -
    2. -
    -
    +

    + Only submitted tasks will be included in your portfolio. If a task is missing from the list, + ensure that you have submitted it before compiling your portfolio. All feedback and comments + for each task will appear in the final portfolio, so you can add any additional comments now + if there's something you'd like to address. +

    The following tasks will be included + automatically in this order:

    +

    +
    diff --git a/src/app/projects/states/portfolio/portfolio.coffee b/src/app/projects/states/portfolio/portfolio.coffee index 63e93ea961..01b6bf8972 100644 --- a/src/app/projects/states/portfolio/portfolio.coffee +++ b/src/app/projects/states/portfolio/portfolio.coffee @@ -82,7 +82,7 @@ angular.module('doubtfire.projects.states.portfolio', [ # Gets selected tasks in the task selector $scope.selectedTasks = -> # Filter by included in portfolio - tasks = _.filter $scope.project.tasks, (t) -> t.includeInPortfolio + tasks = $scope.project.tasks tasks = _.filter tasks, (t) -> !_.includes(newTaskService.toBeWorkedOn, t.status) _.sortBy tasks, (t) -> t.definition.seq From ea42bd63d82f082689bc860b53f43b4ffb5f50e8 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 17 Oct 2025 13:52:04 +1100 Subject: [PATCH 0684/1531] chore(release): 10.0.0-53 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1c0f0d73d..0d250861d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-53](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-52...v10.0.0-53) (2025-10-17) + ## [10.0.0-52](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-51...v10.0.0-52) (2025-10-17) diff --git a/package-lock.json b/package-lock.json index 5a2e04aac3..e94c4152ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-52", + "version": "10.0.0-53", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-52", + "version": "10.0.0-53", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 3356d560a7..52bf9d5075 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-52", + "version": "10.0.0-53", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From b67810743c18b4f178a07421f0c9acde6b8b989a Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 17 Oct 2025 14:20:52 +1100 Subject: [PATCH 0685/1531] refactor: number list --- .../portfolio-welcome-step/portfolio-welcome-step.tpl.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html index 524101329b..51297a7060 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html +++ b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html @@ -4,10 +4,9 @@

    Portfolio Preparation

    Preparing your portfolio involves 5 steps:

    -
      +
      1. Select your Grade you are applying for
      2. Upload your Learning Summary Report
      3. -
      4. Select the Tasks you want included
      5. Upload any Other Resources you want to add
      6. Compile your resources into your portfolio and review
      From 2eec7ce1ecc229f672e7f02a27c76ffce4f45291 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:10:13 +1100 Subject: [PATCH 0686/1531] chore: add margin --- .../portfolio-welcome-step/portfolio-welcome-step.tpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html index 51297a7060..cb062284f1 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html +++ b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html @@ -4,7 +4,7 @@

      Portfolio Preparation

    Preparing your portfolio involves 5 steps:

    -
      +
      1. Select your Grade you are applying for
      2. Upload your Learning Summary Report
      3. Upload any Other Resources you want to add
      4. From 3b225388981272f14ab2f2f17af1df8be10ecbcc Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:11:05 +1100 Subject: [PATCH 0687/1531] chore(release): 10.0.0-54 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d250861d3..f710943bd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-54](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-53...v10.0.0-54) (2025-10-17) + ## [10.0.0-53](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-52...v10.0.0-53) (2025-10-17) ## [10.0.0-52](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-51...v10.0.0-52) (2025-10-17) diff --git a/package-lock.json b/package-lock.json index e94c4152ee..7b09dfd70d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-53", + "version": "10.0.0-54", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-53", + "version": "10.0.0-54", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 52bf9d5075..6eb504c354 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-53", + "version": "10.0.0-54", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 8a1dd1ac806c5acbbf8d1ccf7bdcb6af1c68dd14 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:23:49 +1100 Subject: [PATCH 0688/1531] fix: typo --- .../analytics/directives/analytics-tutor-times.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts index b8d6ac3574..b9606b7fc7 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts @@ -197,7 +197,7 @@ export class AnalyticsTutorTimesComponent implements OnInit { tz, ), 'My Marking Sessions CSV', - `${this.unit.code}-${this.userService.currentUser.name}-sessions-${start}-to-${end}-${tz}}.csv`, + `${this.unit.code}-${this.userService.currentUser.name}-sessions-${start}-to-${end}-${tz}.csv`, ); } From c49ffeddedb2b79c39252770692e7df9dcd97bfc Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Sun, 19 Oct 2025 13:02:30 +1100 Subject: [PATCH 0689/1531] fix: display correct marking session details --- .../analytics/directives/analytics-tutor-times.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html index d826a68de2..dbd2f4302a 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html @@ -82,8 +82,8 @@

        Tutor Times Session Summary

        >
        {{ event.startHour }} — {{ event.endHour }}
        Assessments: {{ event.assessments || 0 }}
        - Comments: {{ event.comments_added || 0 }}
        - Submissions opened: {{ event.submissions_opened || 0 }}
        + Comments: {{ event.commentsAdded || 0 }}
        + Submissions opened: {{ event.submissionsOpened || 0 }}
        During Tutorial?: {{ event.duringTutorial ? 'yes' : 'no' }}
    From 3858e3792fef3f0542d954e213987484ac97a990 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 20 Oct 2025 13:06:08 +1100 Subject: [PATCH 0690/1531] feat: display task count in inbox (#1025) * feat: display number of tasks in inbox * chore: only display task count if not empty --- .../directives/staff-task-list/staff-task-list.component.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html index 2291a5e7a6..2a36a9704f 100644 --- a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html +++ b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html @@ -200,6 +200,9 @@ @if (filteredTasks) { + @if (filteredTasks.length) { +
    {{ filteredTasks.length }} Tasks
    + } Date: Mon, 20 Oct 2025 16:22:26 +1100 Subject: [PATCH 0691/1531] refactor: scrollable calendar (#1027) --- .../analytics-tutor-times.component.scss | 16 ++++++++++++++++ .../analytics-tutor-times.component.ts | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.scss b/src/app/units/states/analytics/directives/analytics-tutor-times.component.scss index e69de29bb2..2ce45fc98d 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.scss +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.scss @@ -0,0 +1,16 @@ +.cal-week-view { + position: relative; + max-height: 750px; + overflow-y: scroll; + overscroll-behavior: contain; +} + +.cal-day-headers { + position: sticky; + top: 0; + right: 0; + z-index: 2; + background-color: white; + width: 100%; + min-height: 35px; +} diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts index b9606b7fc7..9b65234bbd 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts @@ -1,6 +1,5 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {Component, Input, OnInit, ViewEncapsulation} from '@angular/core'; import {MatDatepickerInputEvent} from '@angular/material/datepicker'; -import {CalendarEvent} from 'angular-calendar'; import {Observable} from 'rxjs'; import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; import {Unit} from 'src/app/api/models/unit'; @@ -32,6 +31,7 @@ interface SessionEvent { selector: 'f-analytics-tutor-times', templateUrl: 'analytics-tutor-times.component.html', styleUrls: ['analytics-tutor-times.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class AnalyticsTutorTimesComponent implements OnInit { @Input() unit: Unit; From f751ef30a66f4ff3638252443737767441795e1e Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 20 Oct 2025 17:32:47 +1100 Subject: [PATCH 0692/1531] chore(release): 10.0.0-55 --- CHANGELOG.md | 13 +++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f710943bd7..22fec1df51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-55](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-54...v10.0.0-55) (2025-10-20) + + +### Features + +* display task count in inbox ([#1025](https://github.com/b0ink/doubtfire-deploy/issues/1025)) ([3858e37](https://github.com/b0ink/doubtfire-deploy/commit/3858e3792fef3f0542d954e213987484ac97a990)) + + +### Bug Fixes + +* display correct marking session details ([c49ffed](https://github.com/b0ink/doubtfire-deploy/commit/c49ffeddedb2b79c39252770692e7df9dcd97bfc)) +* typo ([8a1dd1a](https://github.com/b0ink/doubtfire-deploy/commit/8a1dd1ac806c5acbbf8d1ccf7bdcb6af1c68dd14)) + ## [10.0.0-54](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-53...v10.0.0-54) (2025-10-17) ## [10.0.0-53](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-52...v10.0.0-53) (2025-10-17) diff --git a/package-lock.json b/package-lock.json index 7b09dfd70d..1a5c744864 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-54", + "version": "10.0.0-55", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-54", + "version": "10.0.0-55", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 6eb504c354..d9ba47fd69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-54", + "version": "10.0.0-55", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From a4aa3525d07868d6085f331adbac481a86313291 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Tue, 21 Oct 2025 13:16:52 +1100 Subject: [PATCH 0693/1531] refactor: require comment for assess in portfolio tasks submitting for feedback (#1026) * refactor: require comment for assess in portfolio tasks submitting for feedback * chore: fix comment * chore: fix indentation * fix: condition * chore: update character count text color * chore: add tooltip --- .../upload-submission-modal.coffee | 10 ++++---- .../upload-submission-modal.tpl.html | 24 ++++++++++--------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee index 486ae9bcbb..b6bcd6b50e 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee @@ -70,6 +70,8 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) $scope.uploader.payload.contributions = mapTeamToPayload() if _.includes(states.shown, 'group') $scope.uploader.payload.trigger = 'need_help' if $scope.submissionType == 'need_help' $scope.uploader.payload.trigger = 'assess_in_portfolio' if $scope.submissionType == 'assess_in_portfolio' || $scope.task.status == 'assess_in_portfolio' + if $scope.comment? and $scope.comment.trim() isnt '' + $scope.uploader.payload.comment = $scope.comment onSuccess: (response) -> # Ensure our response contains the data we're expecting if typeof response is 'object' and response? and response.id? and response.project_id? and response.status? @@ -88,9 +90,9 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) onComplete: -> return unless $scope.uploader.response? and $scope.uploader.response.id? $modalInstance.close(task) - unless $scope.task.isTestSubmission + # unless $scope.task.isTestSubmission # Add comment if requested - task.addComment($scope.comment) if $scope.comment.trim().length > 0 + # task.addComment($scope.comment) if $scope.comment.trim().length > 0 # Broadcast that upload is complete $rootScope.$broadcast('TaskSubmissionUploadComplete', task) # Perform as timeout to show 'Upload Complete' @@ -176,8 +178,8 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) back: -> false submit: -> - # Disable if no comment is supplied with need_help - !$scope.uploader.isReady || ($scope.comment.trim().length == 0 && $scope.submissionType == 'need_help') + # Disable if no comment is supplied with need_help, or if submitting for feedback and task is assess in portfolio only + !$scope.uploader.isReady or ($scope.comment.trim().length < 25 && ($scope.submissionType == 'ready_for_feedback' && $scope.task.definition.assessInPortfolioOnly) || $scope.submissionType == 'need_help') cancel: -> # Can't cancel whilst uploading $scope.uploader.isUploading diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html index 89067b9b11..49fb538af6 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html @@ -83,23 +83,25 @@

    ng-class="{'state-hidden-left': isHidden('comments').left, 'state-hidden-right': isHidden('comments').right}">
    -
    -

    - What do you need help with? -

    -

    - Final comments -

    - +
    +

    What do you need help with?

    + Supply a comment on what you would like help on for this task so your tutor can assist you. - +
    +
    +

    Final comments

    + + Please supply a comment specifying which areas of your submission you would like feedback on. + + Supply an optional comment about this submission for your tutor to read as they assess.
    - +
    Character count: {{comment.length}} (Min. 25)
    @@ -138,7 +140,7 @@

    Plagiarism and Collusion

    - From 32e03d111e61df42a9c67cb9e68d271f9300d5bc Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 23 Oct 2025 22:12:12 +1100 Subject: [PATCH 0694/1531] fix: ensure grade has been selected --- .../portfolio-grade-select-step.component.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html index 63385d6e5d..575a9f5faf 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html @@ -86,7 +86,11 @@

    Select Grade

    +
    + } +
    + @if (unitRole) { +
    + + All Tutorials + My Tutorials + +
    + } +

    + + + @if (selectedGroupSet && selectedGroupSet.groups.length === 0) { +
    + group_off +

    There are no groups in this set

    +
    + } @else { + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Name + @if (editing(group)) { + + + + } @else { + {{ group.name || 'Not set' }} + } + Tutorial + @if (editing(group)) { + + + @for (tutorial of unit.tutorials; track tutorial) { + {{ tutorial.abbreviation }} + } + + + } @else { + {{ group.tutorial.abbreviation }} + } + + @if (unitRole) { + Capacity Adjustment + } + + @if (unitRole) { + @if (editing(group)) { + + + + } @else { + {{ group.capacityAdjustment }} + } + } + Capacity + @if (group.hasSpace()) { + Available + } @else { + Full + } + + @if (unitRole || (project && selectedGroupSet.allowStudentsToManageGroups)) { + Actions + } + + @if (project && group.hasSpace() && selectedGroupSet.allowStudentsToManageGroups) { +
    + @if (!group.locked && !selectedGroupSet.locked) { + + } @else { + lock + } +
    + } + @if (unitRole) { +
    + @if (editing(group)) { +
    + + +
    + } @else { + + + + } +
    + } +
    + + } + + @if (selectedGroupSet.keepGroupsInSameClass && selectedGroupSet.groups.length > 0 && !unitRole) { +

    + Can't see the group you need to join? Groups shown are limited to those in your allocated + tutorials. Use the + Tutorial List to check and update + your tutorial enrolment if needed. +

    + } + diff --git a/src/app/groups/group-selector/group-selector.component.scss b/src/app/groups/group-selector/group-selector.component.scss new file mode 100644 index 0000000000..200fdfce50 --- /dev/null +++ b/src/app/groups/group-selector/group-selector.component.scss @@ -0,0 +1,9 @@ +.mat-mdc-row .mat-mdc-cell { + border-bottom: 1px solid transparent; + border-top: 1px solid transparent; + cursor: pointer; +} + +.mat-mdc-row:hover { + background-color: #eee; +} diff --git a/src/app/groups/group-selector/group-selector.component.ts b/src/app/groups/group-selector/group-selector.component.ts new file mode 100644 index 0000000000..f0fc2b3615 --- /dev/null +++ b/src/app/groups/group-selector/group-selector.component.ts @@ -0,0 +1,264 @@ +import { + AfterViewInit, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, + ViewChild, +} from '@angular/core'; +import {UntypedFormControl, Validators} from '@angular/forms'; +import {MatButtonToggleChange} from '@angular/material/button-toggle'; +import {MatPaginator} from '@angular/material/paginator'; +import {MatTableDataSource} from '@angular/material/table'; +import {Subscription} from 'rxjs'; +import {Group, GroupSet, UnitRole, UserService} from 'src/app/api/models/doubtfire-model'; +import {Project} from 'src/app/api/models/project'; +import {Unit} from 'src/app/api/models/unit'; +import {GroupService} from 'src/app/api/services/group.service'; +import {EntityFormComponent} from 'src/app/common/entity-form/entity-form.component'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-group-selector', + templateUrl: './group-selector.component.html', + styleUrls: ['./group-selector.component.scss'], +}) +export class GroupSelectorComponent + extends EntityFormComponent + implements OnInit, OnChanges, AfterViewInit +{ + @Input() unit: Unit; + @Input() unitRole: UnitRole; + @Input() project: Project; + @Input() selectedGroup: Group; + @Input() selectedGroupSet: GroupSet; + @Input() onSelect: (group: Group) => void; + + @ViewChild(MatPaginator) paginator!: MatPaginator; + displayedColumns: string[] = ['name', 'tutorial', 'capacity_adjustment', 'capacity', 'actions']; + public groups: Group[] = []; + + public newGroupName: string; + public staffTutorialFilter: 'all' | 'mine' = 'all'; + + private groupsSub?: Subscription; + + constructor( + private userService: UserService, + private groupService: GroupService, + private alertService: AlertService, + ) { + super( + { + name: new UntypedFormControl('', [Validators.required]), + tutorial: new UntypedFormControl(null, [Validators.required]), + capacityAdjustment: new UntypedFormControl('', [Validators.required]), + }, + 'Group', + ); + } + + public get showGroupSetSelector() { + return this.unit.groupSets.length > 1; + } + + ngOnInit(): void { + if (this.unit.groupSets.length > 0) { + this.selectedGroupSet = this.unit.groupSets[0]; + } + } + + selectGroupSet(groupSet: GroupSet) { + this.selectedGroupSet = groupSet; + this.refreshGroups(); + } + + ngAfterViewInit() { + this.dataSource = new MatTableDataSource(); + this.dataSource.paginator = this.paginator; + + if (this.unit.groupSets.length > 0) { + this.selectedGroupSet = this.unit.groupSets[0]; + } + + this.refreshGroups(); + } + + refreshGroups() { + this.groupsSub?.unsubscribe(); + this.groupsSub = this.selectedGroupSet.groupsCache.values.subscribe((values) => { + this.groups = [...values]; + }); + this.applyFilters(); + } + + onGroupNameChange() { + this.applyFilters(); + } + + applyFilters() { + const filteredGroups = this.groups + .filter( + (g) => + this.staffTutorialFilter === 'all' || + (this.unitRole && g.tutorial.tutor.id === this.unitRole.user.id), + ) + .filter( + (g) => !this.newGroupName || g.name.toLowerCase().includes(this.newGroupName.toLowerCase()), + ); + + this.dataSource.data = filteredGroups.sort((a, b) => a.name.localeCompare(b.name)); + } + + ngOnChanges(changes: SimpleChanges) { + if (changes['selectedGroupSet'] && this.selectedGroupSet) { + if (!this.dataSource) { + this.dataSource = new MatTableDataSource(); + } + this.refreshGroups(); + } + } + + onTutorialFilterChange(event: MatButtonToggleChange) { + this.staffTutorialFilter = event.value; + this.applyFilters(); + } + + addGroup(name: string) { + if (this.unit.tutorials.length == 0) { + this.alertService.error( + `Please ensure there is at least one tutorial before groups are created`, + 6000, + ); + return; + } + let tutorialId = -1; + if (this.project) { + tutorialId = this.project.tutorials[0].id || this.unit.tutorials[0].id; + } else { + const tutorName = this.unitRole?.user.name || this.userService.currentUser.name; + tutorialId = + this.unit.tutorials.find((t) => t.tutor?.name === tutorName)?.id ?? + this.unit.tutorials[0].id; + } + + this.groupService + .create( + { + unitId: this.unit.id, + groupSetId: this.selectedGroupSet.id, + }, + { + cache: this.selectedGroupSet.groupsCache, + constructorParams: this.unit, + body: { + group: { + name, + tutorial_id: tutorialId, + }, + }, + }, + ) + .subscribe({ + next: (group) => { + this.alertService.success('Successfully created group', 3000); + this.selectedGroup = group; + this.newGroupName = ''; + this.applyFilters(); + }, + error: (error) => { + this.alertService.error(`Failed to create group: ${error}`); + }, + }); + } + + isPartOfGroup(project: Project, group: Group) { + return project.inGroup(group); + } + + joinGroup(group: Group) { + if (!this.project) { + return; + } + + if (this.isPartOfGroup(this.project, group)) { + this.alertService.error('You are already member of this group'); + return; + } + + group.addMember(this.project, () => { + this.selectedGroup = group; + this.selectGroup(group); + }); + } + + selectGroup(group: Group) { + if (this.project && !this.project.inGroup(group)) { + // Return because we're in the student view + return; + } + + if (this.editing(group)) { + return; + } + + this.selectedGroup = group; + this.onSelect(group); + } + + deleteGroup(event: Event, group: Group) { + event.stopPropagation(); + + this.groupService.delete(group, {cache: this.selectedGroupSet.groupsCache}).subscribe({ + next: () => { + this.alertService.success('Deleted group', 3000); + if (group.id === this.selectedGroup?.id) { + this.selectedGroup = null; + this.selectGroup(null); + } + }, + error: (error) => { + this.alertService.error(`Failed to delete group: ${error}`, 6000); + }, + }); + } + + toggleLocked(event: Event, group: Group) { + event.stopPropagation(); + + const originalLockedState = group.locked; + group.locked = !group.locked; + + this.groupService.update(group).subscribe({ + next: (success) => { + group.locked = success.locked; + this.alertService.success(`Group has been ${!group.locked ? 'un' : ''}locked`, 3000); + }, + error: (error) => { + this.alertService.error(`Failed to ${!group.locked ? 'un' : ''}lock group: ${error}`, 6000); + group.locked = originalLockedState; + }, + }); + } + + startEditGroup(event: Event, group: Group) { + event.stopPropagation(); + this.flagEdit(group); + } + + cancelEditGroup(event: Event) { + event.stopPropagation(); + this.cancelEdit(); + } + + saveEdit(event: Event) { + event.stopPropagation(); + super.submit(this.groupService, this.alertService, this.onSuccess.bind(this)); + this.cancelEdit(); + } + + onSuccess(): void { + this.refreshGroups(); + } +} diff --git a/src/app/groups/group-selector/group-selector.scss b/src/app/groups/group-selector/group-selector.scss deleted file mode 100644 index c176bf951a..0000000000 --- a/src/app/groups/group-selector/group-selector.scss +++ /dev/null @@ -1,45 +0,0 @@ -group-selector { - display: block; -} -group-selector table { - th.name { - width: 25%; - } - th.tutorial { - width: 15%; - } - th.capacity_adjustment { - width: 15%; - } - th.capacity { - width: 15%; - } - th.actions { - width: 25%; - } -} -group-selector .panel-title > group-set-selector { - display: inline-block; - max-width: 50%; - padding-left: 1ex; -} -@media (max-width: $screen-md) { - group-selector .input-group.staff-filter { - margin-bottom: 1em; - &, - .btn-group { - width: 100%; - } - .btn { - width: 50%; - } - } -} - -.lockButton { - width: 70px; -} - -.joinButton { - width: 70px; -} diff --git a/src/app/groups/group-selector/group-selector.tpl.html b/src/app/groups/group-selector/group-selector.tpl.html deleted file mode 100644 index e0a9446a14..0000000000 --- a/src/app/groups/group-selector/group-selector.tpl.html +++ /dev/null @@ -1,220 +0,0 @@ -
    -

    - Groups for - {{selectedGroupSet.name}} - - -

    -
    - -
    -
    -
    -
    - - -
    -
    - -
    - - - - -
    - -
    -
    - -
    Loading Groups...
    - -
    -
    -

    No Groups To Show

    -

    - There are no groups available for {{selectedGroupSet.name}}{{staffFilter == 'mine' || - selectedGroupSet.keepGroupsInSameClass ? " in your tutorials." : ""}}{{newGroupName.length > 0 ? " with name " + newGroupName + "." : "."}} -

    -

    - Please make sure that you are enrolled in the correct tutorial. You can only join a group that is running in your - allocated tutorial. Use the Tutorial List to - check and update your tutorial enrolment. -

    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - Name - - - - Tutorial - - - - - Capacity Adjustment - - - - - Capacity - - - - Actions -
    - - {{ group.name || 'Not Set' }} - - - - - {{group.tutorial.abbreviation}} - - - - - {{group.capacityAdjustment}} - - - Available - Full - -
    - - - - -
    -
    -
    - - -
    - - -
    -
    - diff --git a/src/app/groups/group-set-manager/group-set-manager.coffee b/src/app/groups/group-set-manager/group-set-manager.coffee index 5e8506f7cb..91d1d81c1c 100644 --- a/src/app/groups/group-set-manager/group-set-manager.coffee +++ b/src/app/groups/group-set-manager/group-set-manager.coffee @@ -17,7 +17,8 @@ angular.module('doubtfire.groups.group-set-manager', []) if !$scope.unitRole? && !$scope.project? throw Error "Group set group manager must have exactly one unit role or project" # Reset member panel toolbar visibility - $scope.newGroupSelected = -> + $scope.newGroupSelected = (group) -> + $scope.selectedGroup = group $scope.showMemberPanelToolbar = false if $scope.unitRole? $scope.groupMembersLoaded = -> $scope.showMemberPanelToolbar = true if $scope.unitRole? diff --git a/src/app/groups/group-set-manager/group-set-manager.tpl.html b/src/app/groups/group-set-manager/group-set-manager.tpl.html index da022a0b37..8b99425cb0 100644 --- a/src/app/groups/group-set-manager/group-set-manager.tpl.html +++ b/src/app/groups/group-set-manager/group-set-manager.tpl.html @@ -1,14 +1,13 @@ - - +
    diff --git a/src/app/groups/group-set-selector/group-set-selector.component.html b/src/app/groups/group-set-selector/group-set-selector.component.html deleted file mode 100644 index 46486cf3f8..0000000000 --- a/src/app/groups/group-set-selector/group-set-selector.component.html +++ /dev/null @@ -1,10 +0,0 @@ - - - @for (gs of unit.groupSets; track gs.id) { - {{gs.name}} - } - - diff --git a/src/app/groups/group-set-selector/group-set-selector.component.scss b/src/app/groups/group-set-selector/group-set-selector.component.scss deleted file mode 100644 index 6dee9e802c..0000000000 --- a/src/app/groups/group-set-selector/group-set-selector.component.scss +++ /dev/null @@ -1,7 +0,0 @@ -.groupset-selector .dropdown { - cursor: pointer; -} - -.lockButton { - width: 70px; -} diff --git a/src/app/groups/group-set-selector/group-set-selector.component.ts b/src/app/groups/group-set-selector/group-set-selector.component.ts deleted file mode 100644 index 60ece272be..0000000000 --- a/src/app/groups/group-set-selector/group-set-selector.component.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core'; -import { Unit, GroupSet } from 'src/app/api/models/doubtfire-model'; - -@Component({ - selector: 'group-set-selector', - templateUrl: './group-set-selector.component.html', - styleUrls: ['./group-set-selector.component.scss'] -}) -export class GroupSetSelectorComponent implements OnInit { - @Input() unit: Unit; - @Input() selectedGroupSet: GroupSet; - @Output() selectedGroupSetChange = new EventEmitter(); - - ngOnInit(): void { - if (!this.unit) { - throw new Error('Unit not supplied to group set selector'); - } - } - - /** - * Emits the selected group set and updates the parent component. - * - * Also updates the local state. - * - * @param {GroupSet} groupSet - */ - selectGroupSet(groupSet: GroupSet): void { - this.selectedGroupSet = groupSet; - this.selectedGroupSetChange.emit(this.selectedGroupSet); - } -} diff --git a/src/app/groups/groups.coffee b/src/app/groups/groups.coffee index 3d4534d754..5f95e962e9 100644 --- a/src/app/groups/groups.coffee +++ b/src/app/groups/groups.coffee @@ -1,5 +1,4 @@ angular.module('doubtfire.groups', [ 'doubtfire.groups.group-member-contribution-assigner' - 'doubtfire.groups.group-selector' 'doubtfire.groups.group-set-manager' ]) From 7b3759ca0e302598cbd0db1e17e696706ab3f784 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Tue, 28 Oct 2025 08:59:15 +1100 Subject: [PATCH 0700/1531] refactor: use students preferred name in task comments (#1028) * refactor: use students preferred name in task comments * refactor: use users preferred name --- src/app/api/services/task-comment.service.ts | 2 +- .../projects/states/staff-notes/staff-notes.component.html | 4 ++-- .../task-comments-viewer/task-comments-viewer.component.html | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/api/services/task-comment.service.ts b/src/app/api/services/task-comment.service.ts index afeb1f38ca..b804b164b4 100644 --- a/src/app/api/services/task-comment.service.ts +++ b/src/app/api/services/task-comment.service.ts @@ -57,7 +57,7 @@ export class TaskCommentService extends CachedEntityService { keys: 'author', toEntityFn: (data: object, key: string, comment: TaskComment) => { const user = this.userService.cache.getOrCreate(data[key]?.id, userService, data[key]); - comment.initials = `${user.firstName[0]}${user.lastName[0]}`.toUpperCase(); + comment.initials = `${user.preferredName[0]}${user.lastName[0]}`.toUpperCase(); return user; }, }, diff --git a/src/app/projects/states/staff-notes/staff-notes.component.html b/src/app/projects/states/staff-notes/staff-notes.component.html index 4d1b6fb978..9c89b3a391 100644 --- a/src/app/projects/states/staff-notes/staff-notes.component.html +++ b/src/app/projects/states/staff-notes/staff-notes.component.html @@ -1,7 +1,7 @@
    @if (!loadingStaffNotes && project?.staffNoteCount === 0) {
    - No staff notes for {{ project.student.firstName }} {{ project.student.lastName }} + No staff notes for {{ project.student.preferredName }} {{ project.student.lastName }}
    }
    @@ -20,7 +20,7 @@
    @if (note.replyTo) { - Replying to {{ note.replyTo.user.firstName }} + Replying to {{ note.replyTo.user.preferredName }} {{ note.replyTo.user.lastName }} ({{ note.replyTo.user.nickname }}) {{ note.replyTo.note }} diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html index ff7197b321..e0c2b036de 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html @@ -38,7 +38,7 @@ *ngIf="comment.shouldShowTimestamp" [ngClass]="{own: comment.authorIsMe}" > - {{ comment.author.firstName }} {{ comment.author.lastName }} + {{ comment.author.preferredName }} {{ comment.author.lastName }} {{ comment.createdAt | humanizedDate }}

    -
    Date: Wed, 29 Oct 2025 09:54:36 +1100 Subject: [PATCH 0701/1531] fix: typo --- .../directives/task-due-card/task-due-card.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html index 3f3d5c6c6b..9b40ddb5d6 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html @@ -129,7 +129,7 @@

    - @if (task?.taskDefinition?.unit.markLateSubmissionsAsAssessInPortfolio) { + @if (task?.definition?.unit.markLateSubmissionsAsAssessInPortfolio) { You should have completed this task by {{ task?.localDueDateString() }}. This task is now past the deadline and can only be submitted directly for your From 10711a468effe77f33125ac1ba164a8b4a349c1d Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:05:04 +1100 Subject: [PATCH 0702/1531] chore: update task status from latest submission details (#1031) --- src/app/api/models/task.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index 63843d7b88..c920e985a7 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -570,6 +570,9 @@ export class Task extends Entity { this.hasPdf = response['has_pdf']; this.processingPdf = response['processing_pdf']; this.submissionDate = MappingFunctions.mapDate(response, 'submission_date', this); + if (response['task_status'] && TaskStatus.STATUS_KEYS.includes(response['task_status'])) { + this.status = response['task_status']; + } return this; }), ); From 07de5b1e34f78f83c1418399f45e8c754aea530a Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:05:17 +1100 Subject: [PATCH 0703/1531] fix: enable submission button for 'need help' trigger (#1034) --- .../upload-submission-modal/upload-submission-modal.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee index b6bcd6b50e..961c65be99 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee @@ -179,7 +179,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) false submit: -> # Disable if no comment is supplied with need_help, or if submitting for feedback and task is assess in portfolio only - !$scope.uploader.isReady or ($scope.comment.trim().length < 25 && ($scope.submissionType == 'ready_for_feedback' && $scope.task.definition.assessInPortfolioOnly) || $scope.submissionType == 'need_help') + !$scope.uploader.isReady or ($scope.comment.trim().length < 25 && (($scope.submissionType == 'ready_for_feedback' && $scope.task.definition.assessInPortfolioOnly) || $scope.submissionType == 'need_help') ) cancel: -> # Can't cancel whilst uploading $scope.uploader.isUploading From f682901287ddf087e91db732cb91749718d36a25 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:09:43 +1100 Subject: [PATCH 0704/1531] refactor: replace task definition editor with vertical stepper (#1032) * refactor: replace task def editor with vertical stepper * chore: capitalise labels * fix: typo * fix: typo --- .../task-definition-editor.component.html | 282 ++++++------------ 1 file changed, 84 insertions(+), 198 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html index 75b9583484..7744269ca5 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html @@ -2,218 +2,104 @@

    Details for {{ taskDefinition.abbreviation }} - {{ taskDefinition.name }}

    -
    -
    -
    -
    -
    - 1 -
    -
    -
    -

    Task details

    -

    Name the task and set target grade

    -
    - -
    -
    + + + Task Details +
    +

    Name the task and set target grade

    +
    +
    -
    -
    -
    - 2 -
    -
    -
    -

    Task Learning Outcomes

    -

    Add learning outcomes for this task

    -
    - -
    -
    + + Task Learning Outcomes +
    +

    Add learning outcomes for this task

    +
    - -
    -
    -
    - 3 -
    -
    - -
    -

    Inbox

    -

    - Who assesses {{ unit.hasGroupwork() ? 'and submits ' : '' }}this task? -

    -
    - -
    -
    + + + + Inbox +
    +

    + Who assesses {{ unit.hasGroupwork() ? 'and submits ' : '' }}this task? +

    +
    +
    -
    -
    -
    - 4 -
    -
    - -
    -

    Due dates

    -

    When is this task due?

    -
    - -
    -
    + + Due Dates +
    +

    When is the task due?

    +
    +
    -
    -
    -
    - 5 -
    -
    - -
    -

    Upload requirements

    -

    What do students need to upload?

    -
    - -
    -
    + + Upload Requirements +
    +

    What do students need to upload?

    +
    +
    -
    -
    -
    - 6 -
    -
    - -
    -

    - Task description and resources -

    -

    Upload task descriptions and resources

    -
    - -
    -
    + + Task Resources +
    +

    Upload task descriptions and resources

    +
    - -
    -
    -
    - 7 -
    -
    -
    -

    Prerequisite Tasks

    -

    - Select which tasks need to be submitted before - {{ taskDefinition.abbreviation }} {{ taskDefinition.name }} - can be submitted -

    -
    - - -
    -
    -
    - -
    -
    -
    - 8 -
    -
    - -
    -

    - Task assessment automation -

    -

    Automation is not enabled

    -

    - Configure automated assessment -

    -
    - -
    -
    + + + + Prerequisite Tasks +
    +

    + Select which tasks need to be submitted before + {{ taskDefinition.abbreviation }} {{ taskDefinition.name }} + can be submitted +

    + + +
    - -
    -
    -
    - 9 -
    -
    -
    -

    SCORM test

    -

    - Upload the corresponding SCORM 2004 test (e.g. Numbas) -

    -
    - -
    -
    + + + @if (overseerEnabled) { + + Task Assessment Automation +
    +

    Configure automated assessment

    + +
    +
    + } + + + SCORM Test +
    +

    + Upload the corresponding SCORM 2004 test (e.g. Numbas) +

    +
    +
    -
    -
    -
    - 10 -
    -
    - -
    -

    Optional settings

    -

    Apply other options

    -
    - - - Options - - - -
    -
    - -
    -
    - -
    -
    + + Optional Settings +
    +

    Apply other options

    +
    +
    + +
    +
    +
    From ec0af0cbe47392d6542d9741e1131954195d407f Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:52:19 +1100 Subject: [PATCH 0705/1531] feat: open similarities from project dashboard (#1035) * feat: open similarities from project dashboard * chore: add task similarity view component --- src/app/doubtfire-angularjs.module.ts | 6 ++++++ .../directives/task-dashboard/task-dashboard.coffee | 2 +- .../directives/task-dashboard/task-dashboard.tpl.html | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 886886135c..ab7736ca88 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -231,6 +231,7 @@ import {GroupSetSelectorComponent} from './groups/group-set-selector/group-set-s import {UnitDetailsEditorComponent} from './units/states/edit/directives/unit-details-editor/unit-details-editor.component'; import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component'; +import {TaskSimilarityViewComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component'; export const DoubtfireAngularJSModule = angular .module('doubtfire', [ @@ -563,3 +564,8 @@ DoubtfireAngularJSModule.directive( 'fPortfolioIncludedTasks', downgradeComponent({component: PortfolioIncludedTasksComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fTaskSimilarityView', + downgradeComponent({component: TaskSimilarityViewComponent}), +); diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee index 8fe60b7574..f70113800c 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee @@ -25,7 +25,7 @@ angular.module('doubtfire.projects.states.dashboard.directives.task-dashboard', # Is the current user a tutor? $scope.tutor = $stateParams.tutor # the ways in which the dashboard can be viewed - $scope.dashboardViews = ["details", "submission", "task"] + $scope.dashboardViews = ["details", "submission", "task", "similarities"] # set the current dashboard view to details by default updateCurrentView = -> diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html index d845a5bcd9..16d998bc0a 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html @@ -22,6 +22,9 @@
  • View Task Sheet
  • +
  • + View Similarities +
  • Download Submission PDF @@ -88,6 +91,9 @@
  • +
    + +
    From fa722e6b6dedb140ebbd411ce41745a9b9e81859 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 30 Oct 2025 11:00:51 +1100 Subject: [PATCH 0706/1531] chore(release): 10.0.0-57 --- CHANGELOG.md | 13 +++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a671c033c..e80c7c93d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-57](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-56...v10.0.0-57) (2025-10-30) + + +### Features + +* open similarities from project dashboard ([#1035](https://github.com/b0ink/doubtfire-deploy/issues/1035)) ([ec0af0c](https://github.com/b0ink/doubtfire-deploy/commit/ec0af0cbe47392d6542d9741e1131954195d407f)) + + +### Bug Fixes + +* enable submission button for 'need help' trigger ([#1034](https://github.com/b0ink/doubtfire-deploy/issues/1034)) ([07de5b1](https://github.com/b0ink/doubtfire-deploy/commit/07de5b1e34f78f83c1418399f45e8c754aea530a)) +* typo ([2712a68](https://github.com/b0ink/doubtfire-deploy/commit/2712a68f6031794c571a7ee5866c653bf67de1dd)) + ## [10.0.0-56](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-55...v10.0.0-56) (2025-10-23) diff --git a/package-lock.json b/package-lock.json index 237e8df708..c74890a9cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-56", + "version": "10.0.0-57", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-56", + "version": "10.0.0-57", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 212482a3f5..bfd5a18315 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-56", + "version": "10.0.0-57", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From a48c7d6f58d2367677aa6c1c5c5bd43195730ec2 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:26:19 +1100 Subject: [PATCH 0707/1531] refactor: group set manager migration (#1036) * refactor: init group set manager migration * refactor: allow editable group name * chore: display locked icon * refactor: replace with new component * refactor: shorten create group button * refactor: remove old component * chore: cleanup * refactor: hide search bar for students * refactor: remove css --- README.md | 2 +- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 7 +- .../group-selector.component.html | 2 +- .../group-set-manager.coffee | 45 ------- .../group-set-manager.component.html | 76 ++++++++++++ .../group-set-manager.component.scss | 0 .../group-set-manager.component.ts | 115 ++++++++++++++++++ .../group-set-manager/group-set-manager.scss | 6 - .../group-set-manager.tpl.html | 67 ---------- src/app/groups/groups.coffee | 1 - .../projects/states/groups/groups.tpl.html | 10 +- .../unit-group-set-editor.tpl.html | 25 ++-- src/app/units/states/groups/groups.tpl.html | 13 +- 14 files changed, 224 insertions(+), 147 deletions(-) delete mode 100644 src/app/groups/group-set-manager/group-set-manager.coffee create mode 100644 src/app/groups/group-set-manager/group-set-manager.component.html create mode 100644 src/app/groups/group-set-manager/group-set-manager.component.scss create mode 100644 src/app/groups/group-set-manager/group-set-manager.component.ts delete mode 100644 src/app/groups/group-set-manager/group-set-manager.scss delete mode 100644 src/app/groups/group-set-manager/group-set-manager.tpl.html diff --git a/README.md b/README.md index 77fafe2a61..7885b47a9b 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,7 @@ MIGRATED: - [x] ./src/app/common/modals/confirmation-modal/confirmation-modal.coffee - [x] ./src/app/common/modals/comments-modal/comments-modal.coffee (IN 10.0.x) - [x] ./src/app/groups/group-selector/group-selector.coffee +- [x] ./src/app/groups/group-set-manager/group-set-manager.coffee TODO: @@ -193,7 +194,6 @@ TODO: - [ ] ./src/app/projects/project-outcome-alignment/project-outcome-alignment.coffee - [ ] ./src/app/projects/states/tutorials/tutorials.coffee - [ ] ./src/app/admin/modals/modals.coffee -- [ ] ./src/app/groups/group-set-manager/group-set-manager.coffee - [ ] ./src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee - [ ] ./src/app/groups/tutor-group-manager/tutor-group-manager.coffee - [ ] ./src/app/groups/groups.coffee diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 61b1586d71..4bf79b47d1 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -281,6 +281,7 @@ import {UnitStudentEnrolmentModalComponent} from './units/modals/unit-student-en import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-chart/taskstatuspiechart.component'; import {GroupMemberListComponent} from './groups/group-member-list/group-member-list.component'; import {GroupSelectorComponent} from './groups/group-selector/group-selector.component'; +import {GroupSetManagerComponent} from './groups/group-set-manager/group-set-manager.component'; @NgModule({ // Components we declare @@ -411,6 +412,7 @@ import {GroupSelectorComponent} from './groups/group-selector/group-selector.com PortfolioGradeSelectStepComponent, GroupMemberListComponent, GroupSelectorComponent, + GroupSetManagerComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 29ec49ed15..ba04e6285a 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -78,7 +78,6 @@ import 'build/src/app/projects/states/portfolio/portfolio.js'; import 'build/src/app/projects/states/index/index.js'; import 'build/src/app/projects/project-outcome-alignment/project-outcome-alignment.js'; import 'build/src/app/admin/modals/modals.js'; -import 'build/src/app/groups/group-set-manager/group-set-manager.js'; import 'build/src/app/groups/groups.js'; import 'build/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.js'; import 'build/src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.js'; @@ -222,6 +221,7 @@ import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staf import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; import {GroupMemberListComponent} from './groups/group-member-list/group-member-list.component'; import {GroupSelectorComponent} from './groups/group-selector/group-selector.component'; +import {GroupSetManagerComponent} from './groups/group-set-manager/group-set-manager.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -534,3 +534,8 @@ DoubtfireAngularJSModule.directive( 'fGroupSelector', downgradeComponent({component: GroupSelectorComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fGroupSetManager', + downgradeComponent({component: GroupSetManagerComponent}), +); diff --git a/src/app/groups/group-selector/group-selector.component.html b/src/app/groups/group-selector/group-selector.component.html index 857f840a64..0bf47af51e 100644 --- a/src/app/groups/group-selector/group-selector.component.html +++ b/src/app/groups/group-selector/group-selector.component.html @@ -31,7 +31,7 @@ />
    } diff --git a/src/app/groups/group-set-manager/group-set-manager.coffee b/src/app/groups/group-set-manager/group-set-manager.coffee deleted file mode 100644 index 91d1d81c1c..0000000000 --- a/src/app/groups/group-set-manager/group-set-manager.coffee +++ /dev/null @@ -1,45 +0,0 @@ -angular.module('doubtfire.groups.group-set-manager', []) - -# -# Manager directive for tutors to add and remove group -# members from a group within a group set context -# -.directive('groupSetManager', -> - restrict: 'E' - templateUrl: 'groups/group-set-manager/group-set-manager.tpl.html' - scope: - unit: '=' - unitRole: '=' - project: '=' - selectedGroupSet: '=' - showGroupSetSelector: '=?' - controller: ($scope, newGroupService, gradeService, alertService) -> - if !$scope.unitRole? && !$scope.project? - throw Error "Group set group manager must have exactly one unit role or project" - # Reset member panel toolbar visibility - $scope.newGroupSelected = (group) -> - $scope.selectedGroup = group - $scope.showMemberPanelToolbar = false if $scope.unitRole? - $scope.groupMembersLoaded = -> - $scope.showMemberPanelToolbar = true if $scope.unitRole? - - # Add new member to the group - $scope.addMember = (member) -> - $scope.selectedGroup.addMember(member) - $scope.selectedStudent = null - - # Update name of group - $scope.updateGroup = (data) -> - newGroupService.update({ - unitId: $scope.unit.id, - groupSetId: $scope.selectedGroupSet.id, - id: $scope.selectedGroup.id, - }, { - entity: data - }).subscribe({ - next: (response) -> - alertService.success( "Group changed", 2000) - error: (response) -> - alertService.error( response, 6000) - }) -) diff --git a/src/app/groups/group-set-manager/group-set-manager.component.html b/src/app/groups/group-set-manager/group-set-manager.component.html new file mode 100644 index 0000000000..08b85bf29d --- /dev/null +++ b/src/app/groups/group-set-manager/group-set-manager.component.html @@ -0,0 +1,76 @@ +
    + + + + @if (selectedGroup) { + + + Members of + @if (!editingGroupName) { + {{ selectedGroup?.name }} + @if (unitRole || selectedGroup.groupSet?.allowStudentsToManageGroups) { + + } + } @else { + @if (unitRole || selectedGroup.groupSet?.allowStudentsToManageGroups) { + + + + + + } + } + + @if (selectedGroup.locked) { + lock + } + + + + + @if (unitRole) { + + + + + @for (project of filteredProjects | async; track project) { + {{ project.student.name }} + } + + + + } + + } +
    diff --git a/src/app/groups/group-set-manager/group-set-manager.component.scss b/src/app/groups/group-set-manager/group-set-manager.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/groups/group-set-manager/group-set-manager.component.ts b/src/app/groups/group-set-manager/group-set-manager.component.ts new file mode 100644 index 0000000000..ae3873315b --- /dev/null +++ b/src/app/groups/group-set-manager/group-set-manager.component.ts @@ -0,0 +1,115 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {FormControl} from '@angular/forms'; +import {map, Observable, startWith} from 'rxjs'; +import {Group, GroupSet, Project, Unit, UnitRole} from 'src/app/api/models/doubtfire-model'; +import {GroupService} from 'src/app/api/services/group.service'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-group-set-manager', + templateUrl: './group-set-manager.component.html', + styleUrls: ['./group-set-manager.component.scss'], +}) +export class GroupSetManagerComponent implements OnInit { + @Input() project: Project; + @Input() unit: Unit; + @Input() selectedGroupSet: GroupSet; + @Input() showGroupSetSelector: boolean; + @Input() unitRole: UnitRole; + + public selectedGroup: Group; + + editingGroupName = false; + + control = new FormControl(''); + projects: Project[] = []; + filteredProjects: Observable; + + constructor( + private groupService: GroupService, + private alertService: AlertService, + ) {} + + ngOnInit(): void { + this.filteredProjects = this.control.valueChanges.pipe( + startWith(''), + map((value) => this._filter(value)), + ); + } + + get groupSelectHandler() { + return (group: Group) => this.newGroupSelected(group); + } + + displayFn(project: Project): string { + return project && project.student.name ? project.student.name : ''; + } + + newGroupSelected(group: Group) { + if (this.selectedGroup) { + this.selectedGroup.name = this.originalGroupName; + } + this.editingGroupName = false; + this.selectedGroup = group; + + const students = this.unit.studentsForGroupTypeAhead(group) || []; + this.projects = students.filter((project) => !group.projects.find((p) => project.id === p.id)); + + this.originalGroupName = group.name; + } + + private _filter(value: string | Project): Project[] { + if (typeof value !== 'string') { + return; + } + + const filterValue = value.toLowerCase(); + return this.projects.filter( + (project) => + project.student.name.toLowerCase().includes(filterValue.toLowerCase()) && // Find by name + !this.selectedGroup.projects.find((p) => project.id === p.id), // Not already assigned to the group + ); + } + + groupMembersLoaded() {} + + addMember(project: Project) { + this.selectedGroup.addMember(project); + this.control.setValue(''); + } + + private originalGroupName: string; + startEditingGroupName() { + this.originalGroupName = this.selectedGroup.name; + this.editingGroupName = true; + } + + stopEditinGroupName() { + this.selectedGroup.name = this.originalGroupName; + this.editingGroupName = false; + } + + updateGroup() { + this.editingGroupName = false; + this.groupService + .update( + { + unitId: this.unit.id, + groupSetId: this.selectedGroup.groupSet.id, + id: this.selectedGroup.id, + }, + { + entity: this.selectedGroup, + }, + ) + .subscribe({ + next: () => { + this.alertService.success('Successfully updated group', 3000); + }, + error: (error) => { + this.selectedGroup.name = this.originalGroupName; + this.alertService.error(`Failed to update gorup: ${error}`, 6000); + }, + }); + } +} diff --git a/src/app/groups/group-set-manager/group-set-manager.scss b/src/app/groups/group-set-manager/group-set-manager.scss deleted file mode 100644 index b65662abca..0000000000 --- a/src/app/groups/group-set-manager/group-set-manager.scss +++ /dev/null @@ -1,6 +0,0 @@ -@media (min-width: $screen-lg) { - group-set-manager { - display: block; - @include panel-row; - } -} diff --git a/src/app/groups/group-set-manager/group-set-manager.tpl.html b/src/app/groups/group-set-manager/group-set-manager.tpl.html deleted file mode 100644 index 8b99425cb0..0000000000 --- a/src/app/groups/group-set-manager/group-set-manager.tpl.html +++ /dev/null @@ -1,67 +0,0 @@ - - -
    -
    -
    -
    -

    - Members of - {{selectedGroup.name}} -

    -
    -
    - -
    -
    -
    - -
    -
    - -
    - -
    -
    -
    - - - -
    - diff --git a/src/app/groups/groups.coffee b/src/app/groups/groups.coffee index 5f95e962e9..feae90ec11 100644 --- a/src/app/groups/groups.coffee +++ b/src/app/groups/groups.coffee @@ -1,4 +1,3 @@ angular.module('doubtfire.groups', [ 'doubtfire.groups.group-member-contribution-assigner' - 'doubtfire.groups.group-set-manager' ]) diff --git a/src/app/projects/states/groups/groups.tpl.html b/src/app/projects/states/groups/groups.tpl.html index e5086ab3c6..804d268d35 100644 --- a/src/app/projects/states/groups/groups.tpl.html +++ b/src/app/projects/states/groups/groups.tpl.html @@ -1,10 +1,8 @@
    - - -
    + + +
    +
    diff --git a/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.tpl.html b/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.tpl.html index db550ef42d..c83b2d5fd7 100644 --- a/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.tpl.html +++ b/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.tpl.html @@ -123,18 +123,21 @@

    No Group Sets Created

    New Group Set -
    -
    -
    -
    - +
    + +
    +
    + + + +

    diff --git a/src/app/units/states/groups/groups.tpl.html b/src/app/units/states/groups/groups.tpl.html index 319f46e08f..6d79bdb9a3 100644 --- a/src/app/units/states/groups/groups.tpl.html +++ b/src/app/units/states/groups/groups.tpl.html @@ -1,11 +1,8 @@ -
    - - -
    +
    + + +
    +
    From 560394c4705a5db03b10aeb50556e88086f6d144 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:31:10 +1100 Subject: [PATCH 0708/1531] chore: display joined status --- src/app/groups/group-selector/group-selector.component.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/groups/group-selector/group-selector.component.html b/src/app/groups/group-selector/group-selector.component.html index 0bf47af51e..b0984e69f3 100644 --- a/src/app/groups/group-selector/group-selector.component.html +++ b/src/app/groups/group-selector/group-selector.component.html @@ -129,7 +129,9 @@ } - @if (project && group.hasSpace() && selectedGroupSet.allowStudentsToManageGroups) { + @if (isPartOfGroup(project, group)) { +
    Joined
    + } @else if (project && group.hasSpace() && selectedGroupSet.allowStudentsToManageGroups) {
    @if (!group.locked && !selectedGroupSet.locked) {
    From 58ec499a8d59c7202f591de661551d8a32c37527 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 4 Nov 2025 00:47:50 +1100 Subject: [PATCH 0715/1531] fix: require comment for new evidence --- .../upload-submission-modal/upload-submission-modal.tpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html index 7cc0372a34..65695e16ec 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html @@ -140,7 +140,7 @@

    Plagiarism and Collusion

    - From 8f599725d670f37d50d015692be7d58f163eab8d Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 4 Nov 2025 21:57:19 +1100 Subject: [PATCH 0716/1531] chore(release): 10.0.0-59 --- CHANGELOG.md | 8 ++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb40436959..d8a6450419 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-59](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-58...v10.0.0-59) (2025-11-04) + + +### Bug Fixes + +* require comment for new evidence ([58ec499](https://github.com/b0ink/doubtfire-deploy/commit/58ec499a8d59c7202f591de661551d8a32c37527)) +* require comment for new evidence ([c5397fc](https://github.com/b0ink/doubtfire-deploy/commit/c5397fc5c444e76b431aa5d6487553c60e711c2e)) + ## [10.0.0-58](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-57...v10.0.0-58) (2025-11-01) ## [10.0.0-57](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-56...v10.0.0-57) (2025-10-30) diff --git a/package-lock.json b/package-lock.json index 52d3b0a995..19cbbb3eb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-58", + "version": "10.0.0-59", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-58", + "version": "10.0.0-59", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 830c9eee29..c3df336ac0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-58", + "version": "10.0.0-59", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From c67ceaa84d02bb71626890fc28bb4aaea164b952 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 5 Nov 2025 16:34:31 +1100 Subject: [PATCH 0717/1531] feat: upload grades csv (#1038) * feat: upload grades csv * chore: remove debug --- src/app/api/models/unit.ts | 4 ++ src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 6 ++ .../states/portfolios/portfolios.tpl.html | 1 + .../upload-grades.component.html | 3 + .../upload-grades.component.scss | 0 .../upload-grades/upload-grades.component.ts | 55 +++++++++++++++++++ 7 files changed, 71 insertions(+) create mode 100644 src/app/units/states/portfolios/upload-grades/upload-grades.component.html create mode 100644 src/app/units/states/portfolios/upload-grades/upload-grades.component.scss create mode 100644 src/app/units/states/portfolios/upload-grades/upload-grades.component.ts diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index 8306a94f12..0caa668085 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -414,6 +414,10 @@ export class Unit extends Entity { }/learning_alignments/csv.json`; } + public get gradesCSVUploadUrl(): string { + return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.id}/grades/csv`; + } + public taskStatusFactor(td: TaskDefinition): number { return 1; } diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 12f65dc8a5..ee3dcd3889 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -294,6 +294,7 @@ import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/dir import {AnalyticsTutorTimesComponent} from './units/states/analytics/directives/analytics-tutor-times.component'; import {MarkingSessionService} from './api/services/marking-session.service'; import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component'; +import {UploadGradesComponent} from './units/states/portfolios/upload-grades/upload-grades.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -448,6 +449,7 @@ const MY_DATE_FORMAT = { PortfolioGradeSelectStepComponent, AnalyticsTutorTimesComponent, PortfolioIncludedTasksComponent, + UploadGradesComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index ab7736ca88..8187457400 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -232,6 +232,7 @@ import {UnitDetailsEditorComponent} from './units/states/edit/directives/unit-de import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component'; import {TaskSimilarityViewComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component'; +import {UploadGradesComponent} from './units/states/portfolios/upload-grades/upload-grades.component'; export const DoubtfireAngularJSModule = angular .module('doubtfire', [ @@ -569,3 +570,8 @@ DoubtfireAngularJSModule.directive( 'fTaskSimilarityView', downgradeComponent({component: TaskSimilarityViewComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fUploadGrades', + downgradeComponent({component: UploadGradesComponent}), +); diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html index 98a6c019f7..376277513e 100644 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ b/src/app/units/states/portfolios/portfolios.tpl.html @@ -240,6 +240,7 @@

    Mark Portfolios

    + diff --git a/src/app/units/states/portfolios/upload-grades/upload-grades.component.html b/src/app/units/states/portfolios/upload-grades/upload-grades.component.html new file mode 100644 index 0000000000..c63db48f51 --- /dev/null +++ b/src/app/units/states/portfolios/upload-grades/upload-grades.component.html @@ -0,0 +1,3 @@ + diff --git a/src/app/units/states/portfolios/upload-grades/upload-grades.component.scss b/src/app/units/states/portfolios/upload-grades/upload-grades.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts b/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts new file mode 100644 index 0000000000..5d8e9a0020 --- /dev/null +++ b/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts @@ -0,0 +1,55 @@ +import {Component, Inject, Input, OnInit} from '@angular/core'; +import {csvResultModalService, csvUploadModalService} from 'src/app/ajs-upgraded-providers'; +import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; +import {Unit} from 'src/app/api/models/unit'; +import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-upload-grades', + templateUrl: 'upload-grades.component.html', + styleUrl: 'upload-grades.component.scss', +}) +export class UploadGradesComponent implements OnInit { + @Input() unit: Unit; + + constructor( + @Inject(csvUploadModalService) private csvUploadModal: any, + private sidekiqModalService: SidekiqProgressModalService, + @Inject(csvResultModalService) private csvResultModal: any, + private alertService: AlertService, + ) {} + + public ngOnInit(): void { + if (!this.unit) { + return console.error(`Invalid unit`); + } + } + + public uploadGradesCSV() { + this.csvUploadModal.show( + 'Upload Student Grades as CSV', + 'Import student grades', + { + file: {name: 'Feedback Templates CSV Data', type: 'csv'}, + }, + this.unit.gradesCSVUploadUrl, + (response: SidekiqJob) => { + if (!response) { + this.alertService.error('Failed to import grades', 6000); + return; + } + + this.sidekiqModalService.show('Import student grades', response.id).subscribe({ + next: (job) => { + this.csvResultModal.show('Student grade import results', JSON.parse(job.result)); + }, + error: (error) => { + console.error(error); + this.alertService.error('Failed to import grades', 6000); + }, + }); + }, + ); + } +} From dd2582e2b418318dec015c715086cbfc679b48ac Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 5 Nov 2025 16:36:07 +1100 Subject: [PATCH 0718/1531] chore(release): 10.0.0-60 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8a6450419..4650b3c42e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-60](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-59...v10.0.0-60) (2025-11-05) + + +### Features + +* upload grades csv ([#1038](https://github.com/b0ink/doubtfire-deploy/issues/1038)) ([c67ceaa](https://github.com/b0ink/doubtfire-deploy/commit/c67ceaa84d02bb71626890fc28bb4aaea164b952)) + ## [10.0.0-59](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-58...v10.0.0-59) (2025-11-04) diff --git a/package-lock.json b/package-lock.json index 19cbbb3eb4..a2fb633540 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-59", + "version": "10.0.0-60", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-59", + "version": "10.0.0-60", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index c3df336ac0..be72c68d67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-59", + "version": "10.0.0-60", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 8bcffda3dfb73873c48d68fcce4e82920be19b4f Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:26:35 +1100 Subject: [PATCH 0719/1531] refactor: overseer sidekiq (#1029) * refactor: use sidekiq jobs for pulling overseer images * refactor: overseer execution script editor * chore: remove overseer view * refactor: increase size of script editor * chore: add icon for incomplete overseer runs * chore: add typing * refactor: format assessment comment layout * refactor: enable test submissions if script exists --- .../overseer-image-list.component.html | 35 +++++++++--- .../overseer-image-list.component.ts | 30 +++++++++-- .../models/overseer/overseer-assessment.ts | 28 +++++----- src/app/api/models/task-definition.ts | 1 + .../services/overseer-assessment.service.ts | 5 +- .../api/services/overseer-image.service.ts | 15 ++---- .../api/services/task-definition.service.ts | 1 + src/app/common/footer/footer.component.html | 4 ++ src/app/common/footer/footer.component.ts | 6 +++ src/app/doubtfire-angular.module.ts | 7 ++- .../task-assessment-comment.component.html | 19 ++++--- .../task-comments-viewer.component.html | 5 +- .../task-submission-history.component.html | 53 +++++++++++------- ...verseer-script-editor-modal.component.html | 14 +++++ ...verseer-script-editor-modal.component.scss | 0 .../overseer-script-editor-modal.component.ts | 54 +++++++++++++++++++ .../overseer-script-editor-modal.service.ts | 28 ++++++++++ .../task-definition-overseer.component.html | 21 +++----- .../task-definition-overseer.component.ts | 27 ++++++---- 19 files changed, 260 insertions(+), 93 deletions(-) create mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html create mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.scss create mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts create mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.service.ts diff --git a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html index d2e70e730d..bf6ca86233 100644 --- a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html +++ b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html @@ -1,3 +1,9 @@ + + +
    {{ data.text }}
    +
    +
    +
    @@ -5,7 +11,13 @@

    Overseer Images

    Add new image or modify existing ones used for automated task analysis

    - +
    @@ -51,7 +63,9 @@

    Overseer Images

    @@ -62,7 +76,7 @@

    Overseer Images

    @@ -80,10 +94,10 @@

    Overseer Images

    overseerImage.pulledImageStatus === 'success' ? 'green' : overseerImage.pulledImageStatus === 'loading' - ? 'orange' - : overseerImage.pulledImageStatus === 'failed' - ? 'red' - : '' + ? 'orange' + : overseerImage.pulledImageStatus === 'failed' + ? 'red' + : '' }" > @@ -113,7 +128,11 @@

    Overseer Images

    +
    Name
    - +
    Last Pulled
    - {{ overseerImage.lastPulledDate }} + {{ overseerImage.lastPulledDate | humanizedDate }}
    - diff --git a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts index 703054827e..526660962d 100644 --- a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts +++ b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts @@ -1,17 +1,24 @@ -import {Component, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, TemplateRef, ViewChild} from '@angular/core'; import {MatTableDataSource, MatTable} from '@angular/material/table'; import {OverseerImage, OverseerImageService} from 'src/app/api/models/doubtfire-model'; import {EntityFormComponent} from 'src/app/common/entity-form/entity-form.component'; import {UntypedFormControl, Validators} from '@angular/forms'; import {MatSort, Sort} from '@angular/material/sort'; import {AlertService} from 'src/app/common/services/alert.service'; +import {MatDialog} from '@angular/material/dialog'; +import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; @Component({ selector: 'overseer-image-list', templateUrl: 'overseer-image-list.component.html', styleUrls: ['overseer-image-list.component.scss'], }) -export class OverseerImageListComponent extends EntityFormComponent { +export class OverseerImageListComponent + extends EntityFormComponent + implements AfterViewInit +{ + @ViewChild('textDialog') textDialog!: TemplateRef; + @ViewChild(MatTable, {static: true}) table: MatTable; @ViewChild(MatSort, {static: true}) sort: MatSort; @@ -26,6 +33,8 @@ export class OverseerImageListComponent extends EntityFormComponent { - this.loading = false; + this.overseerImageService.pullDockerImage(image).subscribe((job) => { + this.sidekiqProgressModalService + .show(`Pulling image ${image.name} (${image.tag})`, job.id) + .subscribe((_job) => { + this.overseerImageService.fetch(image.id).subscribe((newImage) => { + console.log(newImage); + this.loading = false; + }); + }); }); } @@ -96,4 +112,10 @@ export class OverseerImageListComponent extends EntityFormComponent(mappingData: EntityMapping, ignoreKeys?: string[]): object { + public override toJson( + mappingData: EntityMapping, + ignoreKeys?: string[], + ): object { return { - overseer_assessment: super.toJson(mappingData, ignoreKeys) + overseer_assessment: super.toJson(mappingData, ignoreKeys), }; } } diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index 30aff474bf..e82ae135f0 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -47,6 +47,7 @@ export class TaskDefinition extends Entity { scormTimeDelayEnabled: boolean; scormAttemptLimit: number = 0; hasTaskAssessmentResources: boolean; + hasTaskAssessmentScript: boolean; isGraded: boolean; maxQualityPts: number; overseerImageId: number; diff --git a/src/app/api/services/overseer-assessment.service.ts b/src/app/api/services/overseer-assessment.service.ts index cfb21c8879..2226887caf 100644 --- a/src/app/api/services/overseer-assessment.service.ts +++ b/src/app/api/services/overseer-assessment.service.ts @@ -4,6 +4,7 @@ import {Observable} from 'rxjs'; import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiUrl'; import {OverseerAssessment} from '../models/overseer/overseer-assessment'; +import {Task} from '../models/doubtfire-model'; @Injectable() export class OverseerAssessmentService extends EntityService { @@ -37,13 +38,13 @@ export class OverseerAssessmentService extends EntityService return new OverseerAssessment(other); } - public queryForTask(task: any): Observable { + public queryForTask(task: Task): Observable { const pathIds = { project_id: task.project.id, td_id: task.definition.id, }; - return this.query(pathIds, task); + return this.query(pathIds); } public triggerOverseer(assessment: OverseerAssessment): Observable { diff --git a/src/app/api/services/overseer-image.service.ts b/src/app/api/services/overseer-image.service.ts index ebb5558b3a..7edc65932f 100644 --- a/src/app/api/services/overseer-image.service.ts +++ b/src/app/api/services/overseer-image.service.ts @@ -4,6 +4,7 @@ import {OverseerImage} from 'src/app/api/models/doubtfire-model'; import {Injectable} from '@angular/core'; import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiUrl'; +import {SidekiqJob} from '../models/sidekiq-job'; @Injectable() export class OverseerImageService extends CachedEntityService { @@ -25,16 +26,10 @@ export class OverseerImageService extends CachedEntityService { this.mapping.mapAllKeysToJsonExcept('id'); } - public pullDockerImage(image: OverseerImage): Observable { - return super - .put(image, { - endpointFormat: this.pullImageEndpointFormat, - }) - .pipe( - switchMap((response) => { - return super.update(image); - }), - ); + public pullDockerImage(image: OverseerImage): Observable { + return super.put(image, { + endpointFormat: this.pullImageEndpointFormat, + }); } public createInstanceFrom(json: object, other?: any): OverseerImage { diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 63708814f8..06bea8da49 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -114,6 +114,7 @@ export class TaskDefinitionService extends CachedEntityService { 'hasTaskSheet', 'hasTaskResources', 'hasTaskAssessmentResources', + 'hasTaskAssessmentScript', 'scormEnabled', 'hasScormData', 'scormAllowReview', diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index 6fa4a27af5..8fd9e50a33 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -188,6 +188,10 @@ crisis_alert View similarities + -
    -
    - } @else { - -
    + @if (comment.assessment_result && comment.assessment_result.is_successful) { +
    +
    +
    {{ comment.text }}
    + +
    +
    + } @else { +
    } diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html index e0c2b036de..8cbc442d50 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html @@ -127,7 +127,10 @@
    -
    +
    -
    -
    -
    Submissions
    - +
    +
    +
    +
    Submissions
    + @for (tab of tabs; track tab) { - -
    {{tab.timestamp | date: 'dd/MM/yy, hh:mm a'}}
    -   -
    -} + +
    +
    + {{ tab.timestamp | humanizedDate }} +
    + @if (tab.status === 'pre_queued') { + schedule + } @else { + + } +
    +
    + }
    -
    +
    @for (selTab of selectedTab.content; track selTab) { - -
    {{selTab.result}} 
    - -
    -} + +
    {{ selTab.result }} 
    + +
    + }
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html new file mode 100644 index 0000000000..1d6a563570 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html @@ -0,0 +1,14 @@ +
    +
    +

    {{ data.taskDefinition.abbreviation }} {{ data.taskDefinition.name }}

    +

    Overseer script

    +
    +
    + +
    + @if (!loading) { + + } +
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.scss b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts new file mode 100644 index 0000000000..f64d3b4763 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts @@ -0,0 +1,54 @@ +import {HttpClient} from '@angular/common/http'; +import {Component, Inject, OnInit} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {CodeModel} from '@ngstack/code-editor'; +import {AppInjector} from 'src/app/app-injector'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {OverseerScriptEditorModalData} from './overseer-script-editor-modal.service'; + +@Component({ + selector: 'f-overseer-script-editor-modal', + templateUrl: './overseer-script-editor-modal.component.html', + styleUrls: ['./overseer-script-editor-modal.component.scss'], +}) +export class OverseerScriptEditorModalComponent implements OnInit { + constructor( + @Inject(MAT_DIALOG_DATA) public data: OverseerScriptEditorModalData, + public dialogRef: MatDialogRef, + private httpClient: HttpClient, + ) {} + + public model: CodeModel = { + language: 'shell', + uri: 'run.sh', + value: '', + }; + + scriptContent: string; + + loading: boolean = false; + ngOnInit() { + this.loading = true; + // TODO: move to taskDefinition model + const url = `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.data.taskDefinition.unit.id}/task_definitions/${this.data.taskDefinition.id}/overseer_script`; + this.httpClient.get(url).subscribe((data: string) => { + this.model.value = data; + this.loading = false; + }); + } + + save() { + console.log(this.model.value); + const url = `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.data.taskDefinition.unit.id}/task_definitions/${this.data.taskDefinition.id}/overseer_script`; + + this.httpClient.put(url, {script_content: this.model.value}).subscribe({ + next: (result) => { + console.log(result); + this.dialogRef.close(); + }, + error: (error) => { + console.error(error); + }, + }); + } +} diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.service.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.service.ts new file mode 100644 index 0000000000..c238db3eaf --- /dev/null +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.service.ts @@ -0,0 +1,28 @@ +import {Injectable} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import {OverseerScriptEditorModalComponent} from './overseer-script-editor-modal.component'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; + +export interface OverseerScriptEditorModalData { + taskDefinition: TaskDefinition; +} + +@Injectable({ + providedIn: 'root', +}) +export class OverseerScriptEditorModalService { + constructor(public dialog: MatDialog) {} + + public show(taskDefinition: TaskDefinition) { + const _dialogRef = this.dialog.open< + OverseerScriptEditorModalComponent, + OverseerScriptEditorModalData + >(OverseerScriptEditorModalComponent, { + data: { + taskDefinition: taskDefinition, + }, + width: '100%', + maxWidth: '1200px', + }); + } +} diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html index bf187030aa..0e5c521bcb 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html @@ -18,6 +18,10 @@ Docker image for Overseer + + @if (taskDefinition.hasTaskAssessmentResources) {
    - -
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts index 597296d707..ea0f92ba89 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts @@ -1,5 +1,5 @@ -import { Component, Input, OnChanges } from '@angular/core'; -import { Observable } from 'rxjs'; +import {Component, Input, OnChanges} from '@angular/core'; +import {Observable} from 'rxjs'; import { OverseerAssessment, OverseerImage, @@ -8,13 +8,14 @@ import { User, UserService, } from 'src/app/api/models/doubtfire-model'; -import { TaskDefinition } from 'src/app/api/models/task-definition'; -import { Unit } from 'src/app/api/models/unit'; -import { TaskDefinitionService } from 'src/app/api/services/task-definition.service'; -import { FileDownloaderService } from 'src/app/common/file-downloader/file-downloader.service'; -import { TaskAssessmentModalService } from 'src/app/common/modals/task-assessment-modal/task-assessment-modal.service'; -import { AlertService } from 'src/app/common/services/alert.service'; -import { TaskSubmissionService } from 'src/app/common/services/task-submission.service'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {Unit} from 'src/app/api/models/unit'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {TaskAssessmentModalService} from 'src/app/common/modals/task-assessment-modal/task-assessment-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {TaskSubmissionService} from 'src/app/common/services/task-submission.service'; +import {OverseerScriptEditorModalService} from './overseer-script-editor-modal/overseer-script-editor-modal.service'; @Component({ selector: 'f-task-definition-overseer', @@ -34,6 +35,7 @@ export class TaskDefinitionOverseerComponent implements OnChanges { private userService: UserService, private taskDefinitionService: TaskDefinitionService, private fileDownloaderService: FileDownloaderService, + private overseerScriptEditorModal: OverseerScriptEditorModalService, ) {} public get overseerEnabled(): boolean { @@ -73,6 +75,10 @@ export class TaskDefinitionOverseerComponent implements OnChanges { this.currentUserTask.presentTaskSubmissionModal(this.currentUserTask.status, false, true); } + editScript() { + this.overseerScriptEditorModal.show(this.taskDefinition); + } + testSubmissionHistory() { this.modalService.show(this.currentUserTask); } @@ -93,7 +99,7 @@ export class TaskDefinitionOverseerComponent implements OnChanges { next: () => { this.alerts.success('Deleted Overseer Resources', 2000); this.taskDefinition.hasTaskAssessmentResources = false; - } + }, }); } @@ -104,7 +110,6 @@ export class TaskDefinitionOverseerComponent implements OnChanges { ); } - public uploadOverseerResources(files: FileList) { const validFiles = Array.from(files as ArrayLike).filter( (f) => f.type === 'application/zip' || f.type === 'application/x-zip-compressed', From 1a4a3f6c64743f7fd7e9d96697bdfa4cdb792c8e Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:36:36 +1100 Subject: [PATCH 0720/1531] chore(release): 10.0.0-61 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4650b3c42e..c2462bcfcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-61](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-60...v10.0.0-61) (2025-11-06) + ## [10.0.0-60](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-59...v10.0.0-60) (2025-11-05) diff --git a/package-lock.json b/package-lock.json index a2fb633540..0f3a3c3b45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-60", + "version": "10.0.0-61", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-60", + "version": "10.0.0-61", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index be72c68d67..09053700c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-60", + "version": "10.0.0-61", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 29fbc1498b0d48811cb59c5f2a66871fbac06849 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:59:27 +1100 Subject: [PATCH 0721/1531] feat: restrict assessments to tutors in the same tutorial stream (#1033) * feat: restrict assessments to tutors in the same tutorial stream * refactor: unselect tasks that are locked to a tutorial stream --- src/app/api/models/task-definition.ts | 1 + src/app/api/services/task-definition.service.ts | 1 + .../tutor-discussion.component.html | 6 +++++- .../tutor-discussion/tutor-discussion.component.ts | 14 ++++++++++++++ .../task-definition-who.component.html | 6 ++++++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index e82ae135f0..1560b94909 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -56,6 +56,7 @@ export class TaskDefinition extends Entity { hasJplagReport: boolean; assessInPortfolioOnly: boolean; useResourcesForJplagBaseCode: boolean; + lockAssessmentsToTutorialStream: boolean; public readonly taskPrerequisitesCache: EntityCache = new EntityCache(); diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 06bea8da49..cb36d3cc32 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -138,6 +138,7 @@ export class TaskDefinitionService extends CachedEntityService { }, }, 'useResourcesForJplagBaseCode', + 'lockAssessmentsToTutorialStream', ); this.mapping.mapAllKeysToJsonExcept( diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html index 0c669784dd..89cf35865f 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html @@ -81,7 +81,11 @@ class="clearfix w-full" style="padding: 0; height: 60px" togglePosition="before" - [selected]="task.status === 'discuss' || attendance" + [selected]=" + (task.status === 'discuss' || attendance) && + (!task.definition.lockAssessmentsToTutorialStream || + currentUserTutorsInStream(task.definition.tutorialStream)) + " > @if (task) {
    diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts index 445eb16cc3..567988d53d 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts @@ -12,6 +12,7 @@ import { TaskDefinition, TaskService, TaskStatusEnum, + TutorialStream, Unit, UnitService, UserService, @@ -69,6 +70,19 @@ export class TutorDiscussionComponent implements AfterViewInit { private taskService: TaskService, ) {} + public currentUserTutorsInStream(tutorialStream: TutorialStream): boolean { + const user = this.userService.currentUser; + const tutorials = this.unit.tutorials.filter( + (t) => + t.tutorialStream.abbreviation === tutorialStream.abbreviation && + t.tutorialStream.name === tutorialStream.name, + ); + if (tutorials.some((t) => t.tutor.id === user.id)) { + return true; + } + return false; + } + onTabChange(event: MatTabChangeEvent): void { if (event.index === 0) { this.showComments(); diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html index 5d93345d7f..f36a92f380 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html @@ -56,3 +56,9 @@
    + +
    + Only allow tutors in this tutorial stream to assess this task +
    From 8a56b651ec2f032585de734d8e5f66908fa7098a Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 6 Nov 2025 16:28:29 +1100 Subject: [PATCH 0722/1531] chore(release): 10.0.0-62 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2462bcfcf..7fde181cd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-62](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-61...v10.0.0-62) (2025-11-06) + + +### Features + +* restrict assessments to tutors in the same tutorial stream ([#1033](https://github.com/b0ink/doubtfire-deploy/issues/1033)) ([29fbc14](https://github.com/b0ink/doubtfire-deploy/commit/29fbc1498b0d48811cb59c5f2a66871fbac06849)) + ## [10.0.0-61](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-60...v10.0.0-61) (2025-11-06) ## [10.0.0-60](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-59...v10.0.0-60) (2025-11-05) diff --git a/package-lock.json b/package-lock.json index 0f3a3c3b45..8087a7e128 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-61", + "version": "10.0.0-62", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-61", + "version": "10.0.0-62", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 09053700c4..21346adcca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-61", + "version": "10.0.0-62", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 24f358ecae920e3eeb2f8b50e181be0ae68afde2 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 30 Sep 2025 13:39:20 +1000 Subject: [PATCH 0723/1531] refactor: replace range datepickers with three separate datepickers --- .../task-definition-dates.component.html | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.html index a2285a0969..c6a3eb74c6 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.html @@ -1,43 +1,43 @@
    - - Start date to suggested completion date - - - - - - - + + Start Date + + + + Suggested date for students to begin the task. - - Suggestion completion date to final feedback - - - - + + Target Date + + + + Recommended target date for students to complete the task. + - - + + Final Feedback Date + + + + Final deadline for receiving feedback.
    From 6c4931bd40e94b9a2fbafe3b0b6c9d8670564c74 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 7 Nov 2025 15:17:53 +1100 Subject: [PATCH 0724/1531] chore: replace doubtfire with ontrack --- src/app/common/file-uploader/file-uploader.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/common/file-uploader/file-uploader.coffee b/src/app/common/file-uploader/file-uploader.coffee index c492dac115..89c0c17755 100644 --- a/src/app/common/file-uploader/file-uploader.coffee +++ b/src/app/common/file-uploader/file-uploader.coffee @@ -263,7 +263,7 @@ angular.module('doubtfire.common.file-uploader', ["ngFileUpload"]) response = JSON.parse xhr.responseText catch e if xhr.status is 0 - response = { error: 'Could not connect to the Doubtfire server' } + response = { error: 'Could not connect to the OnTrack server' } else response = xhr.responseText # Success (20x success range) From 5b4b097a9b189e5a816695cce7438104f1144283 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:21:56 +1100 Subject: [PATCH 0725/1531] feat: open project dashboard from portfolios view (#1040) --- src/app/units/states/portfolios/portfolios.coffee | 4 ++++ src/app/units/states/portfolios/portfolios.tpl.html | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/src/app/units/states/portfolios/portfolios.coffee b/src/app/units/states/portfolios/portfolios.coffee index e87a17027d..d13cca4433 100644 --- a/src/app/units/states/portfolios/portfolios.coffee +++ b/src/app/units/states/portfolios/portfolios.coffee @@ -149,4 +149,8 @@ angular.module('doubtfire.units.states.portfolios', []) $scope.transferToD2L = -> D2lTransferModal.open($scope.unit) + + $scope.openProject = ($event, project) -> + $event.stopPropagation() + window.open("/projects/#{project.id}/dashboard/?tutor=true", "_blank") ) diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html index 376277513e..34d00d5d7f 100644 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ b/src/app/units/states/portfolios/portfolios.tpl.html @@ -214,6 +214,13 @@

    Mark Portfolios

    {{student.hasPortfolio ? "Yes" : "No"}}
    {{student.grade}} + +
    From 770b1718f307f6dbb835bef706bff1aa46bb68d5 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:23:30 +1100 Subject: [PATCH 0726/1531] chore(release): 10.0.0-63 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fde181cd4..25972b520c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-63](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-62...v10.0.0-63) (2025-11-10) + + +### Features + +* open project dashboard from portfolios view ([5b4b097](https://github.com/b0ink/doubtfire-deploy/commit/5b4b097a9b189e5a816695cce7438104f1144283)), closes [#1040](https://github.com/b0ink/doubtfire-deploy/issues/1040) + ## [10.0.0-62](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-61...v10.0.0-62) (2025-11-06) diff --git a/package-lock.json b/package-lock.json index 8087a7e128..ac840fcd6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-62", + "version": "10.0.0-63", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-62", + "version": "10.0.0-63", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 21346adcca..47621b97b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-62", + "version": "10.0.0-63", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 9ab015d168cf7e421500910766b9e6fb0bf907f5 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:49:02 +1100 Subject: [PATCH 0727/1531] fix: avoid calling window to open project in new tab --- src/app/units/states/portfolios/portfolios.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/units/states/portfolios/portfolios.coffee b/src/app/units/states/portfolios/portfolios.coffee index d13cca4433..62c70a04f3 100644 --- a/src/app/units/states/portfolios/portfolios.coffee +++ b/src/app/units/states/portfolios/portfolios.coffee @@ -152,5 +152,9 @@ angular.module('doubtfire.units.states.portfolios', []) $scope.openProject = ($event, project) -> $event.stopPropagation() - window.open("/projects/#{project.id}/dashboard/?tutor=true", "_blank") + # HACK: avoids using window.open() to prevent AngularJS error + link = document.createElement('a') + link.href = "/projects/#{project.id}/dashboard/?tutor=true" + link.target = '_blank' + link.click() ) From 7d1dbc33476cd669ab5217cfd70a53017c557d6e Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:04:28 +1100 Subject: [PATCH 0728/1531] refactor: move overseer script url to task definition model --- src/app/api/models/task-definition.ts | 4 ++ .../overseer-script-editor-modal.component.ts | 40 +++++++++---------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index 1560b94909..814c7a9c53 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -276,6 +276,10 @@ export class TaskDefinition extends Entity { }/task_assessment_resources.json`; } + public get taskOverseerExecutionScriptUrl() { + return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.unit.id}/task_definitions/${this.id}/overseer_script`; + } + public getJplagReportUrl() { return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.unit.id}/task_definitions/${this.id}/jplag_report`; } diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts index f64d3b4763..ddcf7c1d40 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts @@ -2,8 +2,7 @@ import {HttpClient} from '@angular/common/http'; import {Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {CodeModel} from '@ngstack/code-editor'; -import {AppInjector} from 'src/app/app-injector'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {AlertService} from 'src/app/common/services/alert.service'; import {OverseerScriptEditorModalData} from './overseer-script-editor-modal.service'; @Component({ @@ -16,6 +15,7 @@ export class OverseerScriptEditorModalComponent implements OnInit { @Inject(MAT_DIALOG_DATA) public data: OverseerScriptEditorModalData, public dialogRef: MatDialogRef, private httpClient: HttpClient, + private alertService: AlertService, ) {} public model: CodeModel = { @@ -29,26 +29,26 @@ export class OverseerScriptEditorModalComponent implements OnInit { loading: boolean = false; ngOnInit() { this.loading = true; - // TODO: move to taskDefinition model - const url = `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.data.taskDefinition.unit.id}/task_definitions/${this.data.taskDefinition.id}/overseer_script`; - this.httpClient.get(url).subscribe((data: string) => { - this.model.value = data; - this.loading = false; - }); + this.httpClient + .get(this.data.taskDefinition.taskOverseerExecutionScriptUrl) + .subscribe((data: string) => { + this.model.value = data; + this.loading = false; + }); } save() { - console.log(this.model.value); - const url = `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.data.taskDefinition.unit.id}/task_definitions/${this.data.taskDefinition.id}/overseer_script`; - - this.httpClient.put(url, {script_content: this.model.value}).subscribe({ - next: (result) => { - console.log(result); - this.dialogRef.close(); - }, - error: (error) => { - console.error(error); - }, - }); + this.httpClient + .put(this.data.taskDefinition.taskOverseerExecutionScriptUrl, { + script_content: this.model.value, + }) + .subscribe({ + next: (_result) => { + this.dialogRef.close(); + }, + error: (error) => { + this.alertService.error(`Failed to save script: ${error}`, 6000); + }, + }); } } From 8eaffbcb65b835d615646d4c9560cbf1881deeb9 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:17:16 +1100 Subject: [PATCH 0729/1531] refactor: base64 encode overseer script before sending to server --- .../overseer-script-editor-modal.component.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts index ddcf7c1d40..128e2410f0 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts @@ -38,9 +38,12 @@ export class OverseerScriptEditorModalComponent implements OnInit { } save() { + const scriptOriginal = this.model.value; + const scriptEncoded = this.base64UrlEncode(scriptOriginal); + this.httpClient .put(this.data.taskDefinition.taskOverseerExecutionScriptUrl, { - script_content: this.model.value, + script_content: scriptEncoded, }) .subscribe({ next: (_result) => { @@ -51,4 +54,8 @@ export class OverseerScriptEditorModalComponent implements OnInit { }, }); } + + private base64UrlEncode(str) { + return btoa(str).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); + } } From 40f2640e6579536cef8e82e9476733083b82bac1 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Thu, 13 Nov 2025 08:15:27 +1100 Subject: [PATCH 0730/1531] fix: use new google fonts api for proper weight loading (#1039) --- src/index.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/index.html b/src/index.html index 2e715e206f..af609f230c 100644 --- a/src/index.html +++ b/src/index.html @@ -18,7 +18,10 @@ href="https://fonts.googleapis.com/icon?family=Material+Icons|Material+Icons+Outlined" rel="stylesheet" /> - + Loading... From 5aef6cfddaf61408e6f3169002f9b8ce00b7dfac Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 13 Nov 2025 15:09:02 +1100 Subject: [PATCH 0731/1531] chore: specify only time exceeded tasks are updated --- .../unit-details-editor/unit-details-editor.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts index 0ea300bf8e..7ac7161a73 100644 --- a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts @@ -90,7 +90,7 @@ export class UnitDetailsEditorComponent implements OnInit { const modal = this.confirmationModal.show( 'Enable Assess in Portfolio?', `Are you sure you want to enable "Assess in Portfolio" for late submissions? - This will update any existing Time/Feedback Exceeded tasks to the "Assess in Portfolio" state. + This will update any existing Time Exceeded tasks to the "Assess in Portfolio" state. You will not be able to disable this setting while any tasks remain in the "Assess in Portfolio" state.`, () => { this.unit.markLateSubmissionsAsAssessInPortfolio = true; From 223f4ea3711fcbd6f3b1353f8d896df000e4f09c Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 17 Nov 2025 12:59:54 +1100 Subject: [PATCH 0732/1531] chore: disable no inferrable types rule --- eslint.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/eslint.config.js b/eslint.config.js index a327c5d852..a519ed7891 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -29,6 +29,7 @@ module.exports = tseslint.config( processor: angular.processInlineTemplates, // Override specific rules for TypeScript files (these will take priority over the extended configs above) rules: { + '@typescript-eslint/no-inferrable-types': 'off', '@angular-eslint/directive-selector': [ 'error', { From 572f104c3c9659ea1a176fa862e5dec66f82fa8b Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 17 Nov 2025 13:09:34 +1100 Subject: [PATCH 0733/1531] refactor: migrate file uploader (#1043) * chore: init file uploader migration * refactor: clean up ui and reset uploader after completion * chore: use external name on error * refactor: migrate remaining file uploaders * refactor: center error size * refactor: ensure uploader is hidden but remains in dom * refactor: remove logs * refactor: improve type safety * chore: typo --- package-lock.json | 16 + package.json | 1 + src/app/common/common.coffee | 1 - .../file-uploader.component.html | 164 +++++++++ .../file-uploader.component.scss | 16 + .../file-uploader/file-uploader.component.ts | 325 ++++++++++++++++++ .../csv-upload-modal.tpl.html | 2 +- src/app/doubtfire-angular.module.ts | 4 + src/app/doubtfire-angularjs.module.ts | 7 +- .../portfolio-add-extra-files-step.tpl.html | 16 +- ...olio-learning-summary-report-step.tpl.html | 10 +- .../upload-submission-modal.coffee | 6 + .../upload-submission-modal.tpl.html | 29 +- .../task-ilo-alignment-editor.tpl.html | 13 +- .../unit-group-set-editor.tpl.html | 36 +- .../unit-ilo-editor/unit-ilo-editor.tpl.html | 6 +- 16 files changed, 598 insertions(+), 54 deletions(-) create mode 100644 src/app/common/file-uploader/file-uploader.component.html create mode 100644 src/app/common/file-uploader/file-uploader.component.scss create mode 100644 src/app/common/file-uploader/file-uploader.component.ts diff --git a/package-lock.json b/package-lock.json index c3968a6562..f95bc84f0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "@angular/service-worker": "^18.0", "@angular/upgrade": "^18.0", "@ctrl/ngx-emoji-mart": "^9.2.0", + "@iplab/ngx-file-upload": "^18.0.0", "@ngneat/hotkeys": "^4.0.0", "@swimlane/ngx-charts": "^20.5.0", "@uirouter/angular": "^14.0", @@ -4534,6 +4535,21 @@ "node": ">=18" } }, + "node_modules/@iplab/ngx-file-upload": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@iplab/ngx-file-upload/-/ngx-file-upload-18.0.0.tgz", + "integrity": "sha512-Uz+011ZOGtVeFAPuOcFHBB/hyLZrV3RNOqT21J13YMqWr5jadba0t67towrQ7VTHLMYt1Du/UHDmv5wV/h7/sg==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/animations": "^18.0.0", + "@angular/common": "^18.0.0", + "@angular/core": "^18.0.0", + "@angular/forms": "^18.0.0", + "rxjs": "^7.0.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "dev": true, diff --git a/package.json b/package.json index e3ad87adbc..506258d1be 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "@angular/service-worker": "^18.0", "@angular/upgrade": "^18.0", "@ctrl/ngx-emoji-mart": "^9.2.0", + "@iplab/ngx-file-upload": "^18.0.0", "@ngneat/hotkeys": "^4.0.0", "@uirouter/angular": "^14.0", "@uirouter/angular-hybrid": "^18.0", diff --git a/src/app/common/common.coffee b/src/app/common/common.coffee index f330d8f6ac..6710f40ec4 100644 --- a/src/app/common/common.coffee +++ b/src/app/common/common.coffee @@ -2,6 +2,5 @@ angular.module("doubtfire.common", [ 'doubtfire.common.services' 'doubtfire.common.filters' 'doubtfire.common.modals' - 'doubtfire.common.file-uploader' 'doubtfire.common.content-editable' ]) diff --git a/src/app/common/file-uploader/file-uploader.component.html b/src/app/common/file-uploader/file-uploader.component.html new file mode 100644 index 0000000000..54dc30d842 --- /dev/null +++ b/src/app/common/file-uploader/file-uploader.component.html @@ -0,0 +1,164 @@ + + + @if (!showUploader) { + + } + +
    + @if (showUploader && uploadingInfo === null && shownUploadZones.length) { +
    + @for (upload of shownUploadZones; track upload) { + @if (!singleDropZone && showName) { +
    + {{ uploadZones.length === 1 ? '' : $index + 1 + ' - ' }} + {{ upload.display.name }} +
    + } + + @if (singleDropZone && showName) { +
    Select {{ upload.display.name }}
    + } + +
    + + +
    + @if (!upload.display.error) { + {{ upload.display.icon }} + @if (dropSupported) { +

    + Drop {{ upload.display.type }} file here
    or click to select +

    + } @else { +

    Click to select {{ upload.display.type }} file

    + } + } @else { +
    + block +

    Invalid file provided

    + Accepted: {{ upload.accept.split(',').join(', ') }} +
    + } +
    +
    + + Browse for file +
    +
    + + @if (!singleDropZone && upload.model?.length > 0) { +
    + {{ upload.display.icon }} + {{ upload.model[0].name }} + +
    + } + } +
    + } + + @if (showUploader && singleDropZone && uploadingInfo === null) { +
    +
    Upload Summary
    + + @for (upload of uploadZones; track upload) { +
    +
    + {{ upload.display.icon }} + {{ upload.display.name }} +
    + + @if (upload.model?.length > 0) { + {{ upload.model[0].name }} + + } @else { + File Pending + } +
    + } +
    + } +
    + + @if (showUploader && !isUploading) { +
    + @if (showUploadButton && readyToUpload() && uploadingInfo === null) { + + } + + @if (asButton) { + + } +
    + } + + @if (showUploader && readyToUpload() && isUploading) { + @if (!uploadingInfo?.complete) { +
    +
    + @for (upload of uploadZones; track upload) { + {{ upload.display.icon }} + } + arrow_right_alt + +
    + + + +
    + } + + @if (uploadingInfo?.complete) { +
    +
    + + {{ uploadingInfo.success ? 'check_circle' : 'cancel' }} + + + + File Upload {{ uploadingInfo.success ? 'Successful' : 'Failed' }} + +
    + + @if (!uploadingInfo.success) { +
    +
    +

    Error Message: {{ uploadingInfo.error }}

    + +
    + + +
    +
    + } +
    + } + } +
    +
    diff --git a/src/app/common/file-uploader/file-uploader.component.scss b/src/app/common/file-uploader/file-uploader.component.scss new file mode 100644 index 0000000000..6809e06815 --- /dev/null +++ b/src/app/common/file-uploader/file-uploader.component.scss @@ -0,0 +1,16 @@ +file-upload .mat-icon, +.complete .mat-icon { + font-size: 50px; + height: 50px; + width: 50px; +} + +.uploading .mat-icon { + font-size: 75px; + height: 75px; + width: 75px; +} + +::ng-deep file-upload .upload-input { + width: 100%; +} diff --git a/src/app/common/file-uploader/file-uploader.component.ts b/src/app/common/file-uploader/file-uploader.component.ts new file mode 100644 index 0000000000..877eddc9cd --- /dev/null +++ b/src/app/common/file-uploader/file-uploader.component.ts @@ -0,0 +1,325 @@ +import { + Component, + EventEmitter, + Input, + OnChanges, + OnInit, + Output, + SimpleChanges, +} from '@angular/core'; +import {FileUploadControl} from '@iplab/ngx-file-upload'; +import {UserService} from 'src/app/api/services/user.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; + +interface File { + name: string; + type: string; +} + +interface UploadDisplay { + name: string; + icon: string; + type: string; + error: boolean; +} +interface UploadZone { + name: string; + model: any; + accept: string; + accepts: string[]; + rejects: string[]; + display: UploadDisplay; +} + +interface UploadingInfo { + progress: number; + success: boolean; + error: string; + complete: boolean; +} + +export const ACCEPTED_TYPES = { + document: { + extensions: ['pdf', 'ps'], + // icon: 'fa-file-pdf-o', + icon: 'article_outlined', + name: 'PDF', + }, + csv: { + extensions: ['csv', 'xls', 'xlsx'], + icon: 'insert_chart_outlined', + name: 'CSV', + }, + code: { + // prettier-ignore + extensions: [ + 'pas', 'cpp', 'c', 'cs', 'csv', 'h', 'hpp', 'java', 'py', 'js', 'html', 'coffee', 'rb', 'css', + 'scss', 'yaml', 'yml', 'xml', 'json', 'ts', 'r', 'rmd', 'rnw', 'rhtml', 'rpres', 'tex', + 'vb', 'sql', 'txt', 'md', 'jack', 'hack', 'asm', 'hdl', 'tst', 'out', 'cmp', 'vm', 'sh', 'bat', + 'dat', 'ipynb', 'pml', 'vue' + ], + // icon: 'fa-file-code-o', + // icon: 'code', + icon: 'integration_instructions_outlined', + name: 'code', + }, + image: { + extensions: ['png', 'bmp', 'tiff', 'tif', 'jpeg', 'jpg', 'gif'], + // icon: 'fa-file-image-o', + icon: 'image_outlined', + name: 'image', + }, + zip: { + extensions: ['zip', 'tar.gz', 'tar'], + // icon: 'fa-file-zip-o', + icon: 'zip_outlined', + name: 'archive', + }, +} as const; + +@Component({ + selector: 'f-file-uploader', + templateUrl: './file-uploader.component.html', + styleUrls: ['./file-uploader.component.scss'], +}) +export class FileUploaderComponent implements OnInit, OnChanges { + @Input() files: File[]; + @Input() url: string; + @Input() method = 'POST'; + @Input() payload?: any; + + @Input() onBeforeUpload?: () => void; + @Input() onSuccess?: (response: any) => void; + @Input() onFailure?: (response: any) => void; + @Input() onComplete?: () => void; + @Input() onClickFailureCancel?: () => void; + + @Input() isUploading: boolean; + @Input() isReady: boolean; + @Input() showName: boolean = true; + @Input() asButton: boolean = false; + @Input() singleDropZone: boolean = false; + @Input() showUploadButton: boolean = true; + @Input() resetAfterUpload: boolean = true; + + @Input() initiateUpload?: () => void; + + // HACK: workaround for TypeScript -> Coffeescript communication + // Once all parent components such as upload-submission-modal are migrated.. + // .. these *wont* be necessary anymore + // Parent components should declare the file-uploader using @ViewChild() and directly call initiateUpload() + @Output() isReadyChange = new EventEmitter(); + @Output() uploadReady = new EventEmitter<() => void>(); + + public readonly ACCEPTED_TYPES = ACCEPTED_TYPES; + + public showUploader: boolean = false; + public uploadingInfo: UploadingInfo = null; + + public fileUploadControl = new FileUploadControl({listVisible: false, discardInvalid: true}); + public shownUploadZones: UploadZone[] = []; + public uploadZones: UploadZone[] = []; + public dropSupported: boolean = true; + + constructor( + private userService: UserService, + private constants: DoubtfireConstants, + ) {} + + private externalName: string = 'OnTrack'; + + ngOnInit(): void { + this.showUploader = !this.asButton; + this.createUploadZones(this.files); + + this.fileUploadControl.valueChanges.subscribe(() => { + setTimeout(() => { + this.validateFiles(); + }); + }); + + this.uploadReady.emit(this.initiateUploadInternal.bind(this)); + + if (!this.onClickFailureCancel) { + this.onClickFailureCancel = this.resetUploader; + } + + this.resetUploader(); + + this.constants.ExternalName.subscribe((name) => { + this.externalName = name; + }); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes['files']) { + this.createUploadZones(changes.files.currentValue); + } + } + + public backToUpload() { + this.isUploading = false; + this.uploadingInfo = null; + } + + validateFiles() { + for (const upload of this.shownUploadZones) { + if (upload.model?.length) { + const name: string = upload.model[0].name.toLowerCase(); + const accepts: string[] = upload.accepts.map((ext: string) => ext.toLowerCase()); + const valid = accepts.some((ext) => name.endsWith(ext)); + if (!valid) { + upload.model = null; + upload.display.error = true; + setTimeout(() => { + upload.display.error = null; + }, 5000); + } + } + } + this.refreshShownUploadZones(); + } + + clearEnqueuedUpload(upload: UploadZone) { + upload.model = null; + this.refreshShownUploadZones(); + } + + readyToUpload(): boolean { + const allSelected = this.uploadZones.every((zone) => zone.model?.length); + this.updateReadyState(allSelected); + return allSelected; + } + + updateReadyState(ready: boolean) { + this.isReady = ready; + this.isReadyChange.emit(ready); + } + + resetUploader() { + this.uploadingInfo = null; + this.isUploading = false; + this.showUploader = !this.asButton; + for (const upload of this.uploadZones) { + this.clearEnqueuedUpload(upload); + } + } + + initiateUploadInternal() { + if (!this.readyToUpload()) { + return; + } + if (this.onBeforeUpload) { + this.onBeforeUpload(); + } + + this.uploadingInfo = { + progress: 5, + success: null, + error: null, + complete: false, + }; + + this.isUploading = true; + + const xhr = new XMLHttpRequest(); + const form = new FormData(); + + // Append files + for (const zone of this.uploadZones) { + if (zone.model?.length) { + form.append(zone.name, zone.model[0]); + } + } + + // Append payload + if (this.payload) { + for (const [key, value] of Object.entries(this.payload)) { + let v = value; + if (typeof v === 'object') v = JSON.stringify(v); + form.append(key, v as any); + } + } + + xhr.upload.onprogress = (event) => { + if (event.total) { + this.uploadingInfo.progress = Math.floor((event.loaded / event.total) * 100); + } + }; + + xhr.onreadystatechange = () => { + if (xhr.readyState === 4) { + setTimeout(() => { + this.uploadingInfo.complete = true; + let response: any = null; + try { + response = JSON.parse(xhr.responseText); + } catch (_e) { + if (xhr.status === 0) { + response = {error: `Could not connect to ${this.externalName} the server`}; + } else { + response = xhr.responseText; + } + } + + if (xhr.status >= 200 && xhr.status < 300) { + this.onSuccess?.(response); + this.uploadingInfo.success = true; + setTimeout(() => { + this.onComplete?.(); + if (this.resetAfterUpload) { + this.resetUploader(); + } + }, 2500); + } else { + this.onFailure?.(response); + this.uploadingInfo.success = false; + this.uploadingInfo.error = (response?.error ?? 'Unknown error') as string; + } + }, 2000); + } + }; + const method = this.method ?? 'POST'; + xhr.open(method, this.url, true); + + xhr.setRequestHeader('Auth-Token', this.userService.currentUser.authenticationToken); + xhr.setRequestHeader('Username', this.userService.currentUser.username); + + xhr.send(form); + } + + // onClickFailureCancelInternal() { + // console.log('onClickFailureCancelInternal'); + // } + + refreshShownUploadZones = () => { + if (this.singleDropZone) { + const firstEmpty = this.uploadZones.find((z) => !z.model || z.model.length === 0); + this.shownUploadZones = firstEmpty ? [firstEmpty] : []; + } + }; + + createUploadZones(files: File[]) { + const zones = Object.entries(files).map(([uploadName, uploadData]) => { + const typeData = ACCEPTED_TYPES[uploadData.type]; + if (!typeData) throw new Error(`Invalid type provided to File Uploader ${uploadData.type}`); + + return { + name: uploadName, + model: null, + accept: `.${typeData.extensions.join(',.')}`, + accepts: typeData.extensions, + rejects: null, + display: { + name: uploadData.name, + icon: typeData.icon, + type: typeData.name, + error: false, + }, + }; + }); + + this.shownUploadZones = this.singleDropZone ? [zones[0]] : zones; + this.uploadZones = zones; + } +} diff --git a/src/app/common/modals/csv-result-modal/csv-upload-modal.tpl.html b/src/app/common/modals/csv-result-modal/csv-upload-modal.tpl.html index 6112f50c7e..5f94b642fe 100644 --- a/src/app/common/modals/csv-result-modal/csv-upload-modal.tpl.html +++ b/src/app/common/modals/csv-result-modal/csv-upload-modal.tpl.html @@ -7,7 +7,7 @@
    - - + +
    diff --git a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.tpl.html b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.tpl.html index 960c0014ab..b190d6f35c 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.tpl.html +++ b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.tpl.html @@ -55,11 +55,11 @@

    you have achieved a {{targetGrade}} in {{unit.name}}.

    - +
    diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee index b9c9ebd2b9..7646c70ff4 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee @@ -55,6 +55,12 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) $scope.submissionTypes = submissionTypes + $scope.isReadyChange = (ready) -> + $scope.uploader.isReady = ready + + $scope.uploadIsReady = (callback) -> + $scope.uploader.start = callback + # Upload files $scope.uploader = { # url: Task.generateSubmissionUrl($scope.task.project, $scope.task) diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html index 92070ac30f..9b96abcd0b 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html @@ -60,20 +60,21 @@

    - +
    diff --git a/src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.tpl.html b/src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.tpl.html index e95245bd46..20f3664c5c 100644 --- a/src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.tpl.html +++ b/src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.tpl.html @@ -105,12 +105,13 @@

    Import Task Outcome Alignments

    Import links between tasks and outcomes from a CSV containing: unit_code, learning_outcome, task_abbr, rating.
    - +

    Export Task Outcome Alignments

    diff --git a/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.tpl.html b/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.tpl.html index c83b2d5fd7..90313b86b6 100644 --- a/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.tpl.html +++ b/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.tpl.html @@ -162,14 +162,14 @@

    Import Groups for {{selectedGroupSet.name}} Download CSV
    - - + +

    @@ -195,15 +195,17 @@

    Download CSV
    - - -

    + + +
    +
    diff --git a/src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.tpl.html b/src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.tpl.html index 3ce30ff314..84bd7ef0ab 100644 --- a/src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.tpl.html +++ b/src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.tpl.html @@ -54,7 +54,11 @@

    Batch Upload Outcome Definitions

    description.
    - +
    From db32f072fa912ee648c636f64e4a26ed10e5e35b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 17 Nov 2025 13:19:48 +1100 Subject: [PATCH 0734/1531] chore: remove any types --- .../file-uploader/file-uploader.component.ts | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/app/common/file-uploader/file-uploader.component.ts b/src/app/common/file-uploader/file-uploader.component.ts index 877eddc9cd..85eb85e792 100644 --- a/src/app/common/file-uploader/file-uploader.component.ts +++ b/src/app/common/file-uploader/file-uploader.component.ts @@ -11,7 +11,7 @@ import {FileUploadControl} from '@iplab/ngx-file-upload'; import {UserService} from 'src/app/api/services/user.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; -interface File { +interface FileData { name: string; type: string; } @@ -24,7 +24,7 @@ interface UploadDisplay { } interface UploadZone { name: string; - model: any; + model: File[]; accept: string; accepts: string[]; rejects: string[]; @@ -83,14 +83,14 @@ export const ACCEPTED_TYPES = { styleUrls: ['./file-uploader.component.scss'], }) export class FileUploaderComponent implements OnInit, OnChanges { - @Input() files: File[]; + @Input() files: FileData[]; @Input() url: string; @Input() method = 'POST'; - @Input() payload?: any; + @Input() payload?: unknown; @Input() onBeforeUpload?: () => void; - @Input() onSuccess?: (response: any) => void; - @Input() onFailure?: (response: any) => void; + @Input() onSuccess?: (response) => void; + @Input() onFailure?: (response) => void; @Input() onComplete?: () => void; @Input() onClickFailureCancel?: () => void; @@ -237,7 +237,7 @@ export class FileUploaderComponent implements OnInit, OnChanges { for (const [key, value] of Object.entries(this.payload)) { let v = value; if (typeof v === 'object') v = JSON.stringify(v); - form.append(key, v as any); + form.append(key, v); } } @@ -251,10 +251,11 @@ export class FileUploaderComponent implements OnInit, OnChanges { if (xhr.readyState === 4) { setTimeout(() => { this.uploadingInfo.complete = true; - let response: any = null; + let response = null; try { response = JSON.parse(xhr.responseText); - } catch (_e) { + } catch (e) { + console.error(e); if (xhr.status === 0) { response = {error: `Could not connect to ${this.externalName} the server`}; } else { @@ -299,7 +300,7 @@ export class FileUploaderComponent implements OnInit, OnChanges { } }; - createUploadZones(files: File[]) { + createUploadZones(files: FileData[]) { const zones = Object.entries(files).map(([uploadName, uploadData]) => { const typeData = ACCEPTED_TYPES[uploadData.type]; if (!typeData) throw new Error(`Invalid type provided to File Uploader ${uploadData.type}`); From 37e109a9fffa0e2d71143afabb9423b5511cf2fd Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 17 Nov 2025 13:29:14 +1100 Subject: [PATCH 0735/1531] chore: remove old file uploader component --- .../common/file-uploader/file-uploader.coffee | 298 ------------------ .../common/file-uploader/file-uploader.scss | 139 -------- .../file-uploader/file-uploader.tpl.html | 104 ------ 3 files changed, 541 deletions(-) delete mode 100644 src/app/common/file-uploader/file-uploader.coffee delete mode 100644 src/app/common/file-uploader/file-uploader.scss delete mode 100644 src/app/common/file-uploader/file-uploader.tpl.html diff --git a/src/app/common/file-uploader/file-uploader.coffee b/src/app/common/file-uploader/file-uploader.coffee deleted file mode 100644 index c492dac115..0000000000 --- a/src/app/common/file-uploader/file-uploader.coffee +++ /dev/null @@ -1,298 +0,0 @@ -angular.module('doubtfire.common.file-uploader', ["ngFileUpload"]) - -.directive 'fileUploader', -> - restrict: 'E' - replace: true - templateUrl: 'common/file-uploader/file-uploader.tpl.html' - scope: - # Files map a key (file name to be uploaded) to a value (containing a - # a display name, and the type of file that is to be accepted, where - # type is one of [document, csv, archive, code, image] - # E.g.: - # { file0: { name: 'Silly Name Code', type: 'code' }, - # fileX: { name: 'Silly name Shot', type: 'image' } ... } - files: '=' - # URL to where image is to be uploaded - url: '=' - # Optional HTTP method used to post data (defaults to POST) - method: '@' - # Other payload data to pass in the upload - # E.g.: - # { unit_id: 10, other: { key: data, with: [array, of, stuff] } ... } - payload: '=?' - # Optional function to notify just prior to upload, enables injection of payload for example - onBeforeUpload: '=?' - # Optional function to perform on success (with one response parameter) - onSuccess: '=?' - # Optional function to perform on failure (with one response parameter) - onFailure: '=?' - # Optional function to perform when the upload is successful and about - # to go back into its default state - onComplete: '=?' - # This value is bound to whether or not the uploader is currently uploading - isUploading: '=?' - # This value is bound to whether or not the uploader is ready to upload - isReady: '=?' - # Shows the names of files to be uploaded (defaults to true) - showName: '=?' - # Shows initially as button - asButton: '=?' - # Exposed files that are in the zone - filesSelected: '=?' - # Whether we have one or many drop zones (default is false) - singleDropZone: '=?' - # Whether or not we show the upload button or do we hide it allowing an - # external trigger to upload (default is true) - showUploadButton: '=?' - # Sets this scope variable to a function that can then be triggered externally - # from outside the scope - initiateUpload: '=?' - # What happens when we click cancel on failure - onClickFailureCancel: '=?' - # Whether we should reset after upload - resetAfterUpload: '=?' - controller: ($scope, $timeout, newUserService) -> - # - # Accepted upload types with associated data - # - ACCEPTED_TYPES = - document: - extensions: ['pdf', 'ps'] - icon: 'fa-file-pdf-o' - name: 'PDF' - csv: - extensions: ['csv','xls','xlsx'] - icon: 'fa-file-excel-o' - name: 'CSV' - code: - extensions: ['pas', 'cpp', 'c', 'cs', 'csv', 'h', 'hpp', 'java', 'py', 'js', 'html', 'coffee', 'rb', 'css', - 'scss', 'yaml', 'yml', 'xml', 'json', 'ts', 'r', 'rmd', 'rnw', 'rhtml', 'rpres', 'tex', - 'vb', 'sql', 'txt', 'md', 'jack', 'hack', 'asm', 'hdl', 'tst', 'out', 'cmp', 'vm', 'sh', 'bat', - 'dat', 'ipynb', 'pml', 'vue'] - icon: 'fa-file-code-o' - name: 'code' - image: - extensions: ['png', 'bmp', 'tiff', 'tif', 'jpeg', 'jpg', 'gif'] - name: 'image' - icon: 'fa-file-image-o' - zip: - extensions: ['zip', 'tar.gz', 'tar'] - name: 'archive' - icon: 'fa-file-zip-o' - - # - # Error handling; check if empty files - # - throw Error "No files provided to uploader" if $scope.files?.length is 0 - - # - # Whether or not clearEnqueuedFiles is enabled - # - $scope.clearEnqueuedUpload = (upload) -> - upload.model = null - refreshShownUploadZones() - - # - # Default showName - # - $scope.showName ?= true - - # - # Default singleDropZone - # - $scope.singleDropZone ?= false - - # - # Default asButton - # - $scope.asButton ?= false - - # - # Only initially show uploader if not presenting as button - # - $scope.showUploader = !$scope.asButton - - # - # Default show upload button - # - $scope.showUploadButton ?= true - - # - # Default resetAfterUpload to true - # - $scope.resetAfterUpload ?= true - - # - # When a file is dropped, if there has been rejected files - # warn the user that that file is not okay - # - checkForError = (upload) -> - if upload.rejects?.length > 0 - upload.display.error = yes - upload.rejects = null - $timeout (-> upload.display.error = no), 4000 - return true - false - - # Called when the model has changed - $scope.modelChanged = (newFiles, upload) -> - return unless newFiles.length > 0 || upload.rejects.length > 0 - gotError = checkForError(upload) - unless gotError - $scope.filesSelected = _.flatten(_.map($scope.uploadZones, 'model')) - if $scope.singleDropZone - $scope.selectedFiles = $scope.uploadZones - refreshShownUploadZones() - - # - # Will refresh which shown drop zones are shown - # Only changes if showing one drop zone - # - refreshShownUploadZones = -> - if $scope.singleDropZone - # Find the first-most empty model in each zone - firstEmptyZone = _.find($scope.uploadZones, (zone) -> !zone.model? || zone.model.length == 0) - if firstEmptyZone? - $scope.shownUploadZones = [firstEmptyZone] - else - $scope.shownUploadZones = [] - - # - # Whether or not drop is supported by this browser - assume - # true initially, but the drop zone will alter this - # - $scope.dropSupported = true - - # - # Data required for each upload zone - # - createUploadZones = (files) -> - zones = _.map(files, (uploadData, uploadName) -> - type = uploadData.type - typeData = ACCEPTED_TYPES[type] - # No typeData found? - unless typeData? - throw Error "Invalid type provided to File Uploader #{type}" - zone = - name: uploadName - model: null - accept: "'." + typeData.extensions.join(',.') + "'" - # Rejected files - rejects: null - display: - name: uploadData.name - # Font awesome supports PDF (from Document), - # CSV, Code and Image icons - icon: typeData.icon - type: typeData.name - # Whether or not a reject error is shown - error: false - zone - ) - # Remove all but the active drop zone - if $scope.singleDropZone - $scope.shownUploadZones = [_.first(zones)] - else - $scope.shownUploadZones = zones - $scope.uploadZones = zones - createUploadZones($scope.files) - - # - # Watch for changes in the files, and recreate the zones when - # they do change - # - $scope.$watch 'files', (files, oldFiles) -> - createUploadZones(files) - - # - # Checks if okay to upload (i.e., file models exist for each drop zone) - # - $scope.readyToUpload = -> - $scope.isReady = _.compact(_.flatten (upload.model for upload in $scope.uploadZones)).length is _.keys($scope.files).length - - # - # Resets the uploader and call it - # - $scope.resetUploader = -> - # No upload info and we're not uploading - $scope.uploadingInfo = null - $scope.isUploading = false - $scope.showUploader = !$scope.asButton - for upload in $scope.uploadZones - $scope.clearEnqueuedUpload(upload) - $scope.resetUploader() - - # - # Override on click failure cancel if not set to just reset uploader - # - $scope.onClickFailureCancel ?= $scope.resetUploader - - - # - # Initiates the upload - # - $scope.initiateUpload = -> - return unless $scope.readyToUpload() - $scope.onBeforeUpload?() - - xhr = new XMLHttpRequest() - form = new FormData() - # Append data - files = ({ name: zone.name; data: zone.model[0] } for zone in $scope.uploadZones) - form.append file.name, file.data for file in files - # Append payload - payload = ({ key: k; value: v } for k, v of $scope.payload) - for payloadItem in payload - payloadItem.value = JSON.stringify(payloadItem.value) if _.isObject payloadItem.value - form.append payloadItem.key, payloadItem.value - # Set the percent - $scope.uploadingInfo = - progress: 5 - success: null - error: null - complete: false - $scope.isUploading = true - # Callbacks - xhr.onreadystatechange = -> - if xhr.readyState is 4 - $timeout (-> - # Upload is now complete - $scope.uploadingInfo.complete = true - response = null - try - response = JSON.parse xhr.responseText - catch e - if xhr.status is 0 - response = { error: 'Could not connect to the Doubtfire server' } - else - response = xhr.responseText - # Success (20x success range) - if xhr.status >= 200 and xhr.status < 300 - $scope.onSuccess?(response) - $scope.uploadingInfo.success = true - $timeout((-> - $scope.onComplete?() - if $scope.resetAfterUpload - $scope.resetUploader() - ), 2500) - # Fail - else - $scope.onFailure?(response) - $scope.uploadingInfo.success = false - $scope.uploadingInfo.error = response.error or "Unknown error" - $scope.$apply() - ), 2000 - xhr.upload.onprogress = (event) -> - $scope.uploadingInfo.progress = parseInt(100.0 * event.position / event.totalSize) - $scope.$apply() - # Default the method to POST if it was not defined - $scope.method = 'POST' unless $scope.method? - - # Send it - xhr.open $scope.method, $scope.url, true - - # Add auth details - xhr.setRequestHeader('Auth-Token', newUserService.currentUser.authenticationToken) - xhr.setRequestHeader('Username', newUserService.currentUser.username) - - xhr.send form diff --git a/src/app/common/file-uploader/file-uploader.scss b/src/app/common/file-uploader/file-uploader.scss deleted file mode 100644 index 4ca5cb6988..0000000000 --- a/src/app/common/file-uploader/file-uploader.scss +++ /dev/null @@ -1,139 +0,0 @@ -.file-uploader { - display: block; - // Add some margin like a

    - margin: 2.5em 0; - - // Colors to make it easy to understand - $hover-color: $brand-primary; - $accept-color: $brand-success; - $reject-color: $brand-danger; - - // Extra additional icons - $ban-icon: $fa-var-ban; - $download-icon: $fa-var-download; - - .upload-commit-actions { - margin-top: 1em; - .btn-upload { - margin-right: 1.5ex; - } - } - - .well.drop { - border: 2px #bbb dotted; - font-size: larger; - font-weight: bold; - color: #aaa; - text-align: center; - &, i { - @include transition(all 0.25s ease); - } - p small { - display: block; - } - &:hover { - cursor: pointer; - border-color: $hover-color; - color: $hover-color; - p small { - text-decoration: underline; - } - } - } - - // Wells which have file over - .well.drop.file-over { - cursor: copy; - border-color: $accept-color; - color: $accept-color; - // Switch the icon over - p.fa::before { - content: $download-icon; - } - } - // Rejected file over - .well.drop.file-rejected { - border-color: $reject-color; - color: $reject-color; - // Switch the icon over - p.fa::before { - content: $ban-icon; - } - } - - // File header - .selected-files { - &:not(.list-group) { - display: inline-block; - } - .selected-file { - display: block; - font-size: 1.2em; - i.file-type { - margin-right: 1ex; - font-size: 1.2em; - } - &.highlight { - animation: highlight-selected-file-animation; - animation-duration: 0.75s; - @keyframes highlight-selected-file-animation { - 0% { background: rgba(33, 150, 243, 0.4); } - 0% { box-shadow: 0 0 6px rgba(33, 150, 243, 1); } - 100% { box-shadow: 0 0 0px rgba(255, 255, 255, 0); } - } - } - } - } - a.clear-upload { - margin-left: 1ex; - &:hover i { - font-size: 1.15em; - color: $reject-color; - } - display: inline-block; - } - // Upload area/result - .upload-area { - .progress-area { - .progress { - margin-bottom: 0; - } - .icons { - width: 100%; - display: flex; - justify-content: center; - } - i.fa-arrow-right { - @include animation-wobble(); - } - i { - flex-basis: auto !important; - margin-right: 1ex; - font-size: 2em; - margin-bottom: 0.5em; - } - } - .result-area { - .result-text { - margin-bottom: 0; - display: flex; - justify-content: center; - align-items: center; - min-height: 34px; - } - i { - font-size: 2em; - @include animation-grow; - margin-right: 1ex; - } - .retry-options { - font-weight: bolder; - font-size: 1.2em; - a:first-child { - display: inline-block; - margin-right: 2ex; - } - } - } - } -} diff --git a/src/app/common/file-uploader/file-uploader.tpl.html b/src/app/common/file-uploader/file-uploader.tpl.html deleted file mode 100644 index 368f53380c..0000000000 --- a/src/app/common/file-uploader/file-uploader.tpl.html +++ /dev/null @@ -1,104 +0,0 @@ -

    -
    - -
    -
    -
    -
    - {{uploadZones.length == 1 ? '' : $index + 1 + ' -'}} {{upload.display.name}} -
    -
    - Select {{upload.display.name}} -
    -
    -

    -

    - Invalid file provided - Accepted files: {{upload.accept.split(',').join(', ')}} -

    -

    - Drop {{upload.display.type}} file here - or click to select one -

    -

    - Click to select {{upload.display.type}} file -

    -
    -
    - - - {{upload.model[0].name}} - - - - -
    -
    -
    -
    Upload Summary
    -
    -
    -
    - - {{upload.display.name}} -
    -
    - {{upload.model[0].name}} - File Pending - - - -
    -
    -
    -
    -
    -
    - - -
    -
    -
    -
    - - - -
    - -
    -
    -

    - - File Upload {{uploadingInfo.success === true ? 'Successful' : 'Failed'}} -

    -
    -
    -

    - Error Message: - {{uploadingInfo.error}} -

    -

    - Retry Upload - Cancel -

    -
    -
    -
    -
    From c7bcc89d799e1827096ca37e937ac1468070bbdd Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 17 Nov 2025 13:32:45 +1100 Subject: [PATCH 0736/1531] chore: update migration progress --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7885b47a9b..a754982870 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,10 @@ MIGRATED: - [x] ./src/app/common/modals/comments-modal/comments-modal.coffee (IN 10.0.x) - [x] ./src/app/groups/group-selector/group-selector.coffee - [x] ./src/app/groups/group-set-manager/group-set-manager.coffee +- [x] ./src/app/common/file-uploader/file-uploader.coffee +- [x] ./src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee +- [x] ./src/app/sessions/auth/http-auth-injector.coffee +- [x] ./src/app/sessions/sessions.coffee TODO: @@ -187,7 +191,6 @@ TODO: - [ ] ./src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.coffee -- [ ] ./src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.coffee - [ ] ./src/app/projects/states/portfolio/portfolio.coffee - [ ] ./src/app/projects/states/index/index.coffee @@ -217,7 +220,6 @@ TODO: - [ ] ./src/app/units/states/students-list/students-list.coffee - [ ] ./src/app/common/modals/modals.coffee - [ ] ./src/app/common/modals/csv-result-modal/csv-result-modal.coffee -- [ ] ./src/app/common/file-uploader/file-uploader.coffee - [ ] ./src/app/common/common.coffee - [ ] ./src/app/common/content-editable/content-editable.coffee - [ ] ./src/app/common/services/media-service.coffee @@ -227,8 +229,6 @@ TODO: - [ ] ./src/app/common/services/services.coffee - [ ] ./src/app/common/services/date-service.coffee - [ ] ./src/app/common/services/analytics-service.coffee -- [ ] ./src/app/sessions/auth/http-auth-injector.coffee -- [ ] ./src/app/sessions/sessions.coffee - [ ] ./src/app/errors/errors.coffee - [ ] ./src/app/errors/states/states.coffee - [ ] ./src/app/errors/states/timeout/timeout.coffee From ec6c2ee621f95e23036fcf94ae92908761be5e22 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 17 Nov 2025 13:37:59 +1100 Subject: [PATCH 0737/1531] chore: remove unused files (#1044) --- src/app/doubtfire-angularjs.module.ts | 3 -- .../sessions/auth/http-auth-injector.coffee | 37 ------------------- src/app/sessions/sessions.coffee | 3 -- src/app/sessions/states/states.coffee | 0 4 files changed, 43 deletions(-) delete mode 100644 src/app/sessions/auth/http-auth-injector.coffee delete mode 100644 src/app/sessions/sessions.coffee delete mode 100644 src/app/sessions/states/states.coffee diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index c7c44c76e3..78bf107b5b 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -111,8 +111,6 @@ import 'build/src/app/common/services/outcome-service.js'; import 'build/src/app/common/services/services.js'; import 'build/src/app/common/services/recorder-service.js'; import 'build/src/app/common/services/analytics-service.js'; -import 'build/src/app/sessions/auth/http-auth-injector.js'; -import 'build/src/app/sessions/sessions.js'; import 'build/src/app/errors/errors.js'; import 'build/src/app/errors/states/timeout/timeout.js'; import 'build/src/app/errors/states/states.js'; @@ -225,7 +223,6 @@ import {FileUploaderComponent} from './common/file-uploader/file-uploader.compon export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', - 'doubtfire.sessions', 'doubtfire.common', 'doubtfire.errors', 'doubtfire.units', diff --git a/src/app/sessions/auth/http-auth-injector.coffee b/src/app/sessions/auth/http-auth-injector.coffee deleted file mode 100644 index 56ef98961e..0000000000 --- a/src/app/sessions/auth/http-auth-injector.coffee +++ /dev/null @@ -1,37 +0,0 @@ -angular.module("doubtfire.sessions.auth.http-auth-injector", []) -# -# This module is responsible for injecting the auth credentials to -# all -# -.config(($httpProvider) -> - $httpProvider.interceptors.push ($q, $rootScope, DoubtfireConstants, newUserService) -> - # - # Inject authentication token for requests - # - injectAuthForRequest = (request) -> - # Intercept API requests and inject the auth token. - if _.startsWith(request.url, DoubtfireConstants.API_URL) and newUserService.currentUser.authenticationToken? - request.headers = {} unless _.has(request, "headers") - request.headers.Auth_Token = newUserService.currentUser.authenticationToken - request.headers.Username = newUserService.currentUser.username - request or $q.when request - - # - # Inject handlers for 419 and 401 response errors - # - injectAuthForResponseWithError = (response) -> - # Intercept unauthorised API responses and fire an event. - if response.config && response.config.url and _.startsWith(response.config.url, DoubtfireConstants.API_URL) - # Timeout? - if response.status is 419 - $rootScope.$broadcast "tokenTimeout" - # Unauthorised? - else if response.status is 401 - $rootScope.$broadcast "unauthorisedRequestIntercepted" - $q.reject response - - { - request: injectAuthForRequest - responseError: injectAuthForResponseWithError - } -) diff --git a/src/app/sessions/sessions.coffee b/src/app/sessions/sessions.coffee deleted file mode 100644 index ccf6e6b5f1..0000000000 --- a/src/app/sessions/sessions.coffee +++ /dev/null @@ -1,3 +0,0 @@ -angular.module('doubtfire.sessions', [ - "doubtfire.sessions.auth.http-auth-injector" -]) diff --git a/src/app/sessions/states/states.coffee b/src/app/sessions/states/states.coffee deleted file mode 100644 index e69de29bb2..0000000000 From a8a29fae3f5bb0a47ba2d13e225f339fe2756dd0 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 17 Nov 2025 18:20:33 +1100 Subject: [PATCH 0738/1531] refactor: portfolio welcome step migration (#1045) * refactor: init portfolio welcome step migration * chore: remove old portfolio welcome step component * chore: remove whitespace * chore: add todo * chore: increase padding --- src/app/doubtfire-angular.module.ts | 2 ++ src/app/doubtfire-angularjs.module.ts | 7 ++++- .../portfolio/directives/directives.coffee | 1 - .../portfolio-welcome-step.coffee | 10 ------- .../portfolio-welcome-step.component.html | 24 +++++++++++++++++ .../portfolio-welcome-step.component.scss | 0 .../portfolio-welcome-step.component.ts | 27 +++++++++++++++++++ .../portfolio-welcome-step.tpl.html | 21 --------------- .../states/portfolio/portfolio.tpl.html | 2 +- 9 files changed, 60 insertions(+), 34 deletions(-) delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.coffee create mode 100644 src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.html create mode 100644 src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.scss create mode 100644 src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.ts delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 2456aef045..9f40010a1b 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -284,6 +284,7 @@ import {GroupMemberListComponent} from './groups/group-member-list/group-member- import {GroupSelectorComponent} from './groups/group-selector/group-selector.component'; import {GroupSetManagerComponent} from './groups/group-set-manager/group-set-manager.component'; import {FileUploaderComponent} from './common/file-uploader/file-uploader.component'; +import {PortfolioWelcomeStepComponent} from './projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component'; @NgModule({ // Components we declare @@ -416,6 +417,7 @@ import {FileUploaderComponent} from './common/file-uploader/file-uploader.compon GroupSelectorComponent, GroupSetManagerComponent, FileUploaderComponent, + PortfolioWelcomeStepComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 78bf107b5b..70c45bfc8e 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -71,7 +71,6 @@ import 'build/src/app/projects/states/outcomes/outcomes.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.js'; -import 'build/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.js'; import 'build/src/app/projects/states/portfolio/directives/directives.js'; import 'build/src/app/projects/states/portfolio/portfolio.js'; @@ -220,6 +219,7 @@ import {GroupMemberListComponent} from './groups/group-member-list/group-member- import {GroupSelectorComponent} from './groups/group-selector/group-selector.component'; import {GroupSetManagerComponent} from './groups/group-set-manager/group-set-manager.component'; import {FileUploaderComponent} from './common/file-uploader/file-uploader.component'; +import {PortfolioWelcomeStepComponent} from './projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -541,3 +541,8 @@ DoubtfireAngularJSModule.directive( 'fFileUploader', downgradeComponent({component: FileUploaderComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fPortfolioWelcomeStep', + downgradeComponent({component: PortfolioWelcomeStepComponent}), +); diff --git a/src/app/projects/states/portfolio/directives/directives.coffee b/src/app/projects/states/portfolio/directives/directives.coffee index 661acd16e7..d8ee720f68 100644 --- a/src/app/projects/states/portfolio/directives/directives.coffee +++ b/src/app/projects/states/portfolio/directives/directives.coffee @@ -3,5 +3,4 @@ angular.module('doubtfire.projects.states.portfolio.directives', [ 'doubtfire.projects.states.portfolio.directives.portfolio-learning-summary-report-step' 'doubtfire.projects.states.portfolio.directives.portfolio-review-step' 'doubtfire.projects.states.portfolio.directives.portfolio-tasks-step' - 'doubtfire.projects.states.portfolio.directives.portfolio-welcome-step' ]) diff --git a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.coffee b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.coffee deleted file mode 100644 index c34f31b354..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.coffee +++ /dev/null @@ -1,10 +0,0 @@ -angular.module('doubtfire.projects.states.portfolio.directives.portfolio-welcome-step', []) - -# -# Welcome introductory step -# -.directive('portfolioWelcomeStep', -> - restrict: 'E' - replace: true - templateUrl: 'projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html' -) diff --git a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.html new file mode 100644 index 0000000000..c5fd1a5cf8 --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.html @@ -0,0 +1,24 @@ + + + Portfolio Preparation + + +

    Preparing your portfolio involves 5 steps:

    +
      +
    1. Select your Grade you are applying for
    2. +
    3. Upload your Learning Summary Report
    4. +
    5. Select the Tasks you want included
    6. +
    7. Upload any Other Resources you want to add
    8. +
    9. Compile your resources into your portfolio and review
    10. +
    +

    + Once you have completed all of these steps, your portfolio will be prepared by + {{ externalName }} and you will be notified when it is ready. You can then check your work, + and if you want to make any corrections repeat these steps to create a new version of your + portfolio. +

    +
    + + + +
    diff --git a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.scss b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.ts new file mode 100644 index 0000000000..41f953ea73 --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.ts @@ -0,0 +1,27 @@ +import {Component, OnInit, Injector} from '@angular/core'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; + +@Component({ + selector: 'f-portfolio-welcome-step', + templateUrl: 'portfolio-welcome-step.component.html', + styleUrls: ['portfolio-welcome-step.component.scss'], +}) +export class PortfolioWelcomeStepComponent implements OnInit { + public externalName: string = 'OnTrack'; + + constructor( + private constants: DoubtfireConstants, + private injector: Injector, + ) {} + + ngOnInit(): void { + this.constants.ExternalName.subscribe((name) => { + this.externalName = name; + }); + } + + goNextStep() { + // TODO: remove this once parent component is migrated + this.injector.get('$scope').advanceActiveTab(1); + } +} diff --git a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html deleted file mode 100644 index 524101329b..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.tpl.html +++ /dev/null @@ -1,21 +0,0 @@ -
    -
    -

    Portfolio Preparation

    -
    -
    -

    Preparing your portfolio involves 5 steps:

    -
      -
    1. Select your Grade you are applying for
    2. -
    3. Upload your Learning Summary Report
    4. -
    5. Select the Tasks you want included
    6. -
    7. Upload any Other Resources you want to add
    8. -
    9. Compile your resources into your portfolio and review
    10. -
    -

    - Once you have completed all of these steps, your portfolio will be prepared by {{externalName.value}} and you will be notified when it is ready. You can then check your work, and if you want to make any corrections repeat these steps to create a new version of your portfolio. -

    -
    - -
    diff --git a/src/app/projects/states/portfolio/portfolio.tpl.html b/src/app/projects/states/portfolio/portfolio.tpl.html index ae536e081f..e6a7bee0da 100644 --- a/src/app/projects/states/portfolio/portfolio.tpl.html +++ b/src/app/projects/states/portfolio/portfolio.tpl.html @@ -6,7 +6,7 @@ - + Date: Tue, 18 Nov 2025 11:46:05 +1100 Subject: [PATCH 0739/1531] refactor: migrate portfolio learning summary report step (#1046) * refactor: migrate portfolio learning summary report step * fix: typo * refactor: remove unused code * chore: update placeholder * refactor: check if draft task definition was submitted * chore: add type * refactor: add caption * refactor: add warning to ensure justification * chore: remove old learning summary report step component * chore: unlink old learning summary report step component * docs: update migration progress * chore: add typing --- README.md | 2 +- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 7 +- .../portfolio/directives/directives.coffee | 1 - ...tfolio-learning-summary-report-step.coffee | 29 ------ ...earning-summary-report-step.component.html | 91 +++++++++++++++++++ ...earning-summary-report-step.component.scss | 5 + ...-learning-summary-report-step.component.ts | 67 ++++++++++++++ ...olio-learning-summary-report-step.tpl.html | 73 --------------- .../states/portfolio/portfolio.tpl.html | 2 +- 10 files changed, 173 insertions(+), 106 deletions(-) delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.coffee create mode 100644 src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html create mode 100644 src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.scss create mode 100644 src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.ts delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.tpl.html diff --git a/README.md b/README.md index a754982870..c7e9ed92e3 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,7 @@ MIGRATED: - [x] ./src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee - [x] ./src/app/sessions/auth/http-auth-injector.coffee - [x] ./src/app/sessions/sessions.coffee +- [x] ./src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.coffee TODO: @@ -188,7 +189,6 @@ TODO: - [ ] ./src/app/projects/states/outcomes/outcomes.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/directives.coffee -- [ ] ./src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.coffee diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 9f40010a1b..470dc35f8c 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -285,6 +285,7 @@ import {GroupSelectorComponent} from './groups/group-selector/group-selector.com import {GroupSetManagerComponent} from './groups/group-set-manager/group-set-manager.component'; import {FileUploaderComponent} from './common/file-uploader/file-uploader.component'; import {PortfolioWelcomeStepComponent} from './projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component'; +import {PortfolioLearningSummaryReportStepComponent} from './projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component'; @NgModule({ // Components we declare @@ -418,6 +419,7 @@ import {PortfolioWelcomeStepComponent} from './projects/states/portfolio/directi GroupSetManagerComponent, FileUploaderComponent, PortfolioWelcomeStepComponent, + PortfolioLearningSummaryReportStepComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 70c45bfc8e..f7335be1fa 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -69,7 +69,6 @@ import 'build/src/app/projects/states/dashboard/directives/task-dashboard/task-d import 'build/src/app/projects/states/dashboard/dashboard.js'; import 'build/src/app/projects/states/outcomes/outcomes.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.js'; -import 'build/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.js'; import 'build/src/app/projects/states/portfolio/directives/directives.js'; @@ -220,6 +219,7 @@ import {GroupSelectorComponent} from './groups/group-selector/group-selector.com import {GroupSetManagerComponent} from './groups/group-set-manager/group-set-manager.component'; import {FileUploaderComponent} from './common/file-uploader/file-uploader.component'; import {PortfolioWelcomeStepComponent} from './projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component'; +import {PortfolioLearningSummaryReportStepComponent} from './projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -546,3 +546,8 @@ DoubtfireAngularJSModule.directive( 'fPortfolioWelcomeStep', downgradeComponent({component: PortfolioWelcomeStepComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fPortfolioLearningSummaryReportStep', + downgradeComponent({component: PortfolioLearningSummaryReportStepComponent}), +); diff --git a/src/app/projects/states/portfolio/directives/directives.coffee b/src/app/projects/states/portfolio/directives/directives.coffee index d8ee720f68..a20b4f1dde 100644 --- a/src/app/projects/states/portfolio/directives/directives.coffee +++ b/src/app/projects/states/portfolio/directives/directives.coffee @@ -1,6 +1,5 @@ angular.module('doubtfire.projects.states.portfolio.directives', [ 'doubtfire.projects.states.portfolio.directives.portfolio-add-extra-files-step' - 'doubtfire.projects.states.portfolio.directives.portfolio-learning-summary-report-step' 'doubtfire.projects.states.portfolio.directives.portfolio-review-step' 'doubtfire.projects.states.portfolio.directives.portfolio-tasks-step' ]) diff --git a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.coffee b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.coffee deleted file mode 100644 index f2f27caaf7..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.coffee +++ /dev/null @@ -1,29 +0,0 @@ -angular.module('doubtfire.projects.states.portfolio.directives.portfolio-learning-summary-report-step', []) - -# -# Step to justify the portfolio with a Learning Summary Report -# -.directive('portfolioLearningSummaryReportStep', -> - restrict: 'E' - replace: true - templateUrl: 'projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.tpl.html' - controller: ($scope) -> - $scope.forceLSRSubmit = false - $scope.acceptUploadNewLearningSummary = false - - $scope.learningSummaryReportFileUploadData = { - type: { - file0: { name: "Learning Summary Report", type: "document" } - }, - payload: { - name: "LearningSummaryReport" # DO NOT MODIFY - case senstitive on API - kind: "document" - } - } - - $scope.addNewFile = (newFile) -> - $scope.addNewFilesToPortfolio(newFile) - $scope.projectHasDraftLearningSummaryReport = false - $scope.acceptUploadNewLearningSummary = false - $scope.forceLSRSubmit = false -) diff --git a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html new file mode 100644 index 0000000000..3ef553e787 --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html @@ -0,0 +1,91 @@ + + + Learning Summary Report + + +

    + Upload the Learning Summary Report, the primary porfolio document which justifies your desired + grade. +

    +

    + Your Learning Summary Report is a + summary of what you have learnt in this unit. It consists of two sections: +

    + +
      +
    1. a self-assessment, and
    2. +
    3. your reflections on the unit.
    4. +
    + +

    + The self-assessment indicates how your portfolio aligns with the assessment + criteria, and which grade you are applying for. +

    + +

    + Your reflections are a personal comment on what you have learnt in the unit, + and how your knowledge and skills have developed. +

    + + @if ( + projectHasDraftLearningSummaryReport && !forceLSRSubmit && !acceptUploadNewLearningSummary + ) { +
    + + @if (draftTaskDefinitionWasUsed()) { +
    + Your learning summary report was automatically submitted from your + {{ unit.draftTaskDefinition.abbreviation }} {{ unit.draftTaskDefinition.name }} + submission. +
    + } + + + +
    + } +
    +
    + warning + + Remember to provide a justification for why you believe you have achieved a + {{ targetGradeLabel }} in {{ unit.code }} {{ unit.name }}. +
    + +
    +
    + + +
    + @if (!projectHasDraftLearningSummaryReport) { +
    + You're missing a Learning Summary Report. Upload one to continue. +
    + } + +
    +
    +
    diff --git a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.scss b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.scss new file mode 100644 index 0000000000..fde6acc603 --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.scss @@ -0,0 +1,5 @@ +.submitted .mat-icon { + font-size: 50px; + width: 50px; + height: 50px; +} diff --git a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.ts new file mode 100644 index 0000000000..2f7744af06 --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.ts @@ -0,0 +1,67 @@ +import {Component, Injector, Input} from '@angular/core'; +import {Project} from 'src/app/api/models/project'; +import {Unit} from 'src/app/api/models/unit'; +import {GradeService} from 'src/app/common/services/grade.service'; + +@Component({ + selector: 'f-portfolio-learning-summary-report-step', + templateUrl: 'portfolio-learning-summary-report-step.component.html', + styleUrls: ['portfolio-learning-summary-report-step.component.scss'], +}) +export class PortfolioLearningSummaryReportStepComponent { + @Input() unit: Unit; + @Input() project: Project; + + public learningSummaryReportFileUploadData = { + type: { + file0: {name: 'Learning Summary Report', type: 'document'}, + }, + payload: { + name: 'LearningSummaryReport', // DO NOT MODIFY - case sensitive on API + kind: 'document', + }, + }; + + public forceLSRSubmit: boolean = false; + public acceptUploadNewLearningSummary: boolean = false; + + constructor( + private injector: Injector, + private gradeService: GradeService, + ) {} + + public get projectHasDraftLearningSummaryReport() { + return ( + this.project?.usesDraftLearningSummary || + this.project?.portfolioFiles.find((f) => f.idx === 0) + ); + } + + public get targetGradeLabel(): string { + return this.gradeService.grades[this.project.targetGrade]; + } + + // TODO: remove this once parent component is migrated + advanceActiveTab(index: 1 | -1) { + this.injector.get('$scope').advanceActiveTab(index); + } + + addNewFile(newFile: {kind: string; name: string; idx: number}) { + this.project.portfolioFiles.push(newFile); + this.acceptUploadNewLearningSummary = false; + this.forceLSRSubmit = false; + } + + draftTaskDefinitionWasUsed(): boolean { + const draftTaskDef = this.unit.draftTaskDefinition; + if (draftTaskDef) { + const task = this.project.findTaskForDefinition(draftTaskDef.id); + if (task && task.inSubmittedState()) { + return true; + } + } + return false; + } + + // downloadLearningSummaryReport(){} +} diff --git a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.tpl.html b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.tpl.html deleted file mode 100644 index b190d6f35c..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.tpl.html +++ /dev/null @@ -1,73 +0,0 @@ -
    -
    -

    - {{activeTab.title}} -

    -
    -
    -

    - Upload the Learning Summary Report, the primary porfolio document which - justifies your desired grade. -

    -

    - Your Learning Summary Report is a summary of what you have learnt in this unit. - It consists of two sections: -

      -
    1. a self-assessment, and
    2. -
    3. your reflections on the unit.
    4. -
    -

    -

    - The self-assessment indicates how your portfolio aligns - with the assessment criteria, and which grade you are applying for. -

    -

    - Your reflections are a personal comment on what you have - learnt in the unit, and how your knowledge and skills have developed. -

    -
    -
    -

    - Before you submit your portfolio... -

    - Your draft learning summary has already been copied over, - it is advised you upload a revised copy. -
    -
    - - -
    -
    - -
    -
    -

    - Learning Summary Report Submitted -

    - Click here to re-upload a new Learning Summary Report -
    - -
    -

    - Before you submit the Learning Summary Report... -

    - Remember to provide a justification for why you believe - you have achieved a {{targetGrade}} in {{unit.name}}. -
    -
    - -
    -
    -
    - -
    diff --git a/src/app/projects/states/portfolio/portfolio.tpl.html b/src/app/projects/states/portfolio/portfolio.tpl.html index e6a7bee0da..d60898e344 100644 --- a/src/app/projects/states/portfolio/portfolio.tpl.html +++ b/src/app/projects/states/portfolio/portfolio.tpl.html @@ -12,7 +12,7 @@ [unit]="unit" ng-if="activeTab == tabs.gradeStep">
    - + From a0f3a73e130de7615a3de399a0951ca588ae00b6 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Tue, 18 Nov 2025 13:27:56 +1100 Subject: [PATCH 0740/1531] refactor: migrate portfolio add extra files step component (#1047) * refactor: migrate portfolio add extra files step component * chore: cleanup whitespace * chore: remove unused class * chore: remove debug * chore: remove old portfolio add extra files step component * chore: update migration progress --- README.md | 2 +- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 7 +- .../portfolio/directives/directives.coffee | 1 - .../portfolio-add-extra-files-step.coffee | 25 ----- ...tfolio-add-extra-files-step.component.html | 51 ++++++++++ ...tfolio-add-extra-files-step.component.scss | 0 ...ortfolio-add-extra-files-step.component.ts | 96 +++++++++++++++++++ .../portfolio-add-extra-files-step.scss | 10 -- .../portfolio-add-extra-files-step.tpl.html | 58 ----------- .../states/portfolio/portfolio.tpl.html | 2 +- 11 files changed, 157 insertions(+), 97 deletions(-) delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee create mode 100644 src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html create mode 100644 src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.scss create mode 100644 src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.scss delete mode 100644 src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.tpl.html diff --git a/README.md b/README.md index c7e9ed92e3..04c76a2b2e 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,7 @@ MIGRATED: - [x] ./src/app/sessions/auth/http-auth-injector.coffee - [x] ./src/app/sessions/sessions.coffee - [x] ./src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.coffee +- [x] ./src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee TODO: @@ -189,7 +190,6 @@ TODO: - [ ] ./src/app/projects/states/outcomes/outcomes.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/directives.coffee -- [ ] ./src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.coffee - [ ] ./src/app/projects/states/portfolio/portfolio.coffee diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 470dc35f8c..cd3886f895 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -286,6 +286,7 @@ import {GroupSetManagerComponent} from './groups/group-set-manager/group-set-man import {FileUploaderComponent} from './common/file-uploader/file-uploader.component'; import {PortfolioWelcomeStepComponent} from './projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component'; import {PortfolioLearningSummaryReportStepComponent} from './projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component'; +import {PortfolioAddExtraFilesStepComponent} from './projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component'; @NgModule({ // Components we declare @@ -420,6 +421,7 @@ import {PortfolioLearningSummaryReportStepComponent} from './projects/states/por FileUploaderComponent, PortfolioWelcomeStepComponent, PortfolioLearningSummaryReportStepComponent, + PortfolioAddExtraFilesStepComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index f7335be1fa..9bac403698 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -69,7 +69,6 @@ import 'build/src/app/projects/states/dashboard/directives/task-dashboard/task-d import 'build/src/app/projects/states/dashboard/dashboard.js'; import 'build/src/app/projects/states/outcomes/outcomes.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.js'; -import 'build/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.js'; import 'build/src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.js'; import 'build/src/app/projects/states/portfolio/directives/directives.js'; import 'build/src/app/projects/states/portfolio/portfolio.js'; @@ -220,6 +219,7 @@ import {GroupSetManagerComponent} from './groups/group-set-manager/group-set-man import {FileUploaderComponent} from './common/file-uploader/file-uploader.component'; import {PortfolioWelcomeStepComponent} from './projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component'; import {PortfolioLearningSummaryReportStepComponent} from './projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component'; +import {PortfolioAddExtraFilesStepComponent} from './projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -551,3 +551,8 @@ DoubtfireAngularJSModule.directive( 'fPortfolioLearningSummaryReportStep', downgradeComponent({component: PortfolioLearningSummaryReportStepComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fPortfolioAddExtraFilesStep', + downgradeComponent({component: PortfolioAddExtraFilesStepComponent}), +); diff --git a/src/app/projects/states/portfolio/directives/directives.coffee b/src/app/projects/states/portfolio/directives/directives.coffee index a20b4f1dde..239280567d 100644 --- a/src/app/projects/states/portfolio/directives/directives.coffee +++ b/src/app/projects/states/portfolio/directives/directives.coffee @@ -1,5 +1,4 @@ angular.module('doubtfire.projects.states.portfolio.directives', [ - 'doubtfire.projects.states.portfolio.directives.portfolio-add-extra-files-step' 'doubtfire.projects.states.portfolio.directives.portfolio-review-step' 'doubtfire.projects.states.portfolio.directives.portfolio-tasks-step' ]) diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee deleted file mode 100644 index f62984ff63..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee +++ /dev/null @@ -1,25 +0,0 @@ -angular.module('doubtfire.projects.states.portfolio.directives.portfolio-add-extra-files-step', []) - -# -# Allow students to add additional files to the end of their portfolio -# They can choose any file they want to upload -# -.directive('portfolioAddExtraFilesStep', -> - restrict: 'E' - replace: true - templateUrl: 'projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.tpl.html' - controller: ($scope) -> - otherFileFileUploadData = (type) -> - type: { - file0: { name: "Other", type: type } - }, - payload: { - name: "Other" - kind: type - } - - $scope.uploadType = 'document' - $scope.$watch 'uploadType', (newType) -> - return unless newType? - $scope.uploadFileData = otherFileFileUploadData newType -) diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html new file mode 100644 index 0000000000..53707b6891 --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html @@ -0,0 +1,51 @@ + + + Upload Other Files + + +

    + Now is your chance to upload any extra files to include in your portfolio. They'll appear at + the very top of your portfolio, before your tasks. +

    +
    +
      + @for (file of extraFiles; track file) { +
    1. +
      + {{ icons[file.kind] }} + {{ file.name }} +
      + +
    2. + } @empty { +

      If you do not have any files to add, you can skip this step.

      + } +
    +
    +
    + + Select type of file: + + Document File + Code File + Image File + + +
    + + +
    + + + + +
    diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.scss b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts new file mode 100644 index 0000000000..93b49f47a1 --- /dev/null +++ b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts @@ -0,0 +1,96 @@ +import {Component, Injector, Input, OnInit} from '@angular/core'; +import {MatSelectChange} from '@angular/material/select'; +import {Project} from 'src/app/api/models/project'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-portfolio-add-extra-files-step', + templateUrl: 'portfolio-add-extra-files-step.component.html', + styleUrls: ['portfolio-add-extra-files-step.component.scss'], +}) +export class PortfolioAddExtraFilesStepComponent implements OnInit { + @Input() project: Project; + + public uploadType: 'document' | 'code' | 'image' = 'document'; + + public isUploading: boolean; + + public uploadFileType = { + file0: { + name: 'Other', + type: 'document', + }, + }; + + public uploadFilePayload = { + name: 'Other', + kind: 'document', + }; + + constructor( + private injector: Injector, + private alertService: AlertService, + ) {} + + public readonly icons = { + document: 'article_outlined', + code: 'integration_instructions_outlined', + image: 'image_outlined', + zip: 'zip_outlined', + }; + + ngOnInit(): void { + this.uploadType = 'document'; + + this.uploadFileType = { + file0: { + name: 'Other', + type: 'document', + }, + }; + + this.uploadFilePayload = { + name: 'Other', + kind: 'document', + }; + } + onTypeChange(event: MatSelectChange) { + console.log('on type change', event); + this.uploadFileType = { + file0: { + name: 'Other', + type: event.value, + }, + }; + + this.uploadFilePayload = { + name: 'Other', + kind: event.value, + }; + } + + public get extraFiles() { + // If file.idx === 0, then it's the Learning Summary Report, so we ignore it here + return this.project?.portfolioFiles.filter((file) => file.idx !== 0); + } + + deleteFileFromPortfolio(file: {idx: number; kind: string; name: string}) { + this.project.deleteFileFromPortfolio(file).subscribe({ + next: () => { + this.alertService.success('Succesfully delete file', 3000); + }, + error: (error) => { + this.alertService.error(`Failed to delete file: ${error}`, 6000); + }, + }); + } + + // TODO: remove this once parent component is migrated + advanceActiveTab(index: 1 | -1) { + this.injector.get('$scope').advanceActiveTab(index); + } + + addNewFilesToPortfolio(newFile: {kind: string; name: string; idx: number}) { + this.project.portfolioFiles.push(newFile); + } +} diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.scss b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.scss deleted file mode 100644 index 47c481a372..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.scss +++ /dev/null @@ -1,10 +0,0 @@ -.portfolio-add-extra-files-step { - a.clear-upload { - margin-left: 1ex; - &:hover i { - font-size: 1.15em; - color: $brand-danger; - } - display: inline-block; - } -} diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.tpl.html b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.tpl.html deleted file mode 100644 index 136b5f5330..0000000000 --- a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.tpl.html +++ /dev/null @@ -1,58 +0,0 @@ -
    -
    -

    {{activeTab.title}}

    -
    -
    -

    - Now is your chance to upload extra files to include in your portfolio. - These files will be added at to your portfolio before your selected tasks - from the previous step. -

    -
    -
    -

    No files to add?

    -

    If you do not have any files to add you can skip this step.

    -
    -
    -

    Extra file{{extraFiles().length > 1 ? 's' : ''}} added

    -

    - {{extraFiles().length > 1 ? 'The files you add will appear in the portfolio in the order shown below.' : ''}} - If you want to delete a file, click the cross beside the file's name. -

    -
      -
    1. - {{file.name}} - - - -
    2. -
    -
    -
    -
    - -
    - -
    -
    - - -
    -
    -
    - -
    diff --git a/src/app/projects/states/portfolio/portfolio.tpl.html b/src/app/projects/states/portfolio/portfolio.tpl.html index d60898e344..2cc7b69080 100644 --- a/src/app/projects/states/portfolio/portfolio.tpl.html +++ b/src/app/projects/states/portfolio/portfolio.tpl.html @@ -14,6 +14,6 @@ - +
    From b04ee273aa17ef037ee580bacc80e7870c82aa3a Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 19 Nov 2025 16:44:41 +1100 Subject: [PATCH 0741/1531] refactor: unit portfolios state migration (#1048) * chore: init unit portfolios state migration * chore: init portfolios directives * refactor: init tab view * refactor: migrate select student portfolio list * refactor: hook student selection * chore: ensure pdf viewer takes up screen * chore: init project progress dashboard * chore: view progress on project selection * refactor: impove project progress layout * refactor: init portfolio assessment view * refactor: portfolio list pagination * fix: prevent vertical in tab groups * refactor: add padding in child components * refactor: add target and submitted grade card ui * refactor: improve assessment layout * refactor: add student search and filtering * feat: add tab headings * fix: set correct tutorial filter * chore: change paginator options * fix: distribute layout evenly * chore: add loading text * chore: remove todo * feat: download grades button * chore: add placeholders todo * fix: update method call * refactor: improve graph layout * refactor: add route error handling * chore: update todo * chore: update todos * feat: has portfolio column * feat: view project in new tab * chore: add todo * refactor: display no portfolio if doesnt exist * fix: typo * chore: consistent gap * chore: remove old portfolios component * chore: update task stats on grade change * chore: remove old project progress dashboard * chore: display error alert * chore: remove old project progress dashboard * chore: update migration progress * refactor: improve assessment scores responsiveness --- README.md | 4 +- src/app/common/header/header.component.ts | 24 +- src/app/doubtfire-angular.module.ts | 10 + src/app/doubtfire-angularjs.module.ts | 2 - src/app/doubtfire.states.ts | 26 ++ .../project-progress-dashboard.coffee | 46 --- .../project-progress-dashboard.tpl.html | 126 ------- src/app/projects/projects.coffee | 1 - .../portfolios-assessment.component.html | 40 +++ .../portfolios-assessment.component.scss | 0 .../portfolios-assessment.component.ts | 42 +++ .../portfolios-list.component.html | 210 ++++++++++++ .../portfolios-list.component.scss | 0 .../portfolios-list.component.ts | 211 ++++++++++++ .../portfolios-portfolio-view.component.html | 14 + .../portfolios-portfolio-view.component.scss | 0 .../portfolios-portfolio-view.component.ts | 11 + ...portfolios-project-progress.component.html | 100 ++++++ ...portfolios-project-progress.component.scss | 0 .../portfolios-project-progress.component.ts | 82 +++++ .../units/states/portfolios/portfolios.coffee | 129 ------- .../portfolios/portfolios.component.html | 39 +++ .../portfolios/portfolios.component.scss | 0 .../states/portfolios/portfolios.component.ts | 71 ++++ .../units/states/portfolios/portfolios.scss | 26 -- .../states/portfolios/portfolios.tpl.html | 319 ------------------ src/app/units/states/states.coffee | 1 - .../progressburndownchart.component.html | 3 +- .../taskstatuspiechart.component.html | 4 +- 29 files changed, 884 insertions(+), 657 deletions(-) delete mode 100644 src/app/projects/project-progress-dashboard/project-progress-dashboard.coffee delete mode 100644 src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html create mode 100644 src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.html create mode 100644 src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.scss create mode 100644 src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.ts create mode 100644 src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html create mode 100644 src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.scss create mode 100644 src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts create mode 100644 src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html create mode 100644 src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.scss create mode 100644 src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts create mode 100644 src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html create mode 100644 src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.scss create mode 100644 src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts delete mode 100644 src/app/units/states/portfolios/portfolios.coffee create mode 100644 src/app/units/states/portfolios/portfolios.component.html create mode 100644 src/app/units/states/portfolios/portfolios.component.scss create mode 100644 src/app/units/states/portfolios/portfolios.component.ts delete mode 100644 src/app/units/states/portfolios/portfolios.scss delete mode 100644 src/app/units/states/portfolios/portfolios.tpl.html diff --git a/README.md b/README.md index 04c76a2b2e..3dfbd9c89c 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,8 @@ MIGRATED: - [x] ./src/app/sessions/sessions.coffee - [x] ./src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.coffee - [x] ./src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee +- [x] ./src/app/projects/project-progress-dashboard/project-progress-dashboard.coffee +- [x] ./src/app/units/states/portfolios/portfolios.coffee TODO: @@ -179,7 +181,6 @@ TODO: - [ ] ./src/app/config/routing/routing.coffee - [ ] ./src/app/config/analytics/analytics.coffee - [ ] ./src/app/projects/projects.coffee -- [ ] ./src/app/projects/project-progress-dashboard/project-progress-dashboard.coffee - [ ] ./src/app/projects/states/states.coffee - [ ] ./src/app/projects/states/groups/groups.coffee - [ ] ./src/app/projects/states/feedback/feedback.coffee @@ -208,7 +209,6 @@ TODO: - [ ] ./src/app/units/states/states.coffee - [ ] ./src/app/units/states/tasks/tasks.coffee - [ ] ./src/app/units/states/tasks/definition/definition.coffee -- [ ] ./src/app/units/states/portfolios/portfolios.coffee - [ ] ./src/app/units/states/analytics/analytics.coffee - [ ] ./src/app/units/states/edit/directives/directives.coffee - [ ] ./src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.coffee diff --git a/src/app/common/header/header.component.ts b/src/app/common/header/header.component.ts index 842287b92e..7d1fb3bc65 100644 --- a/src/app/common/header/header.component.ts +++ b/src/app/common/header/header.component.ts @@ -87,14 +87,20 @@ export class HeaderComponent implements OnInit, OnDestroy { if (this.currentView == ViewType.PROJECT) { this.updateSelectedProject(currentViewAndEntity.entity as Project); } else if (this.currentView == ViewType.UNIT) { - this.updateSelectedUnitRole(currentViewAndEntity.entity as UnitRole); + if (currentViewAndEntity.entity instanceof UnitRole) { + this.updateSelectedUnitRole(currentViewAndEntity.entity as UnitRole); + } else if (currentViewAndEntity.entity instanceof Unit) { + this.updateSelectedUnit(currentViewAndEntity.entity as Unit); + } } else { this.currentUnit = null; this.currentProject = null; } }, // eslint-disable-next-line @typescript-eslint/no-unused-vars - error: (_err) => {}, + error: (_err) => { + console.error(_err); + }, }), ); } @@ -122,6 +128,20 @@ export class HeaderComponent implements OnInit, OnDestroy { this.currentUnit = unitRole.unit; } + updateSelectedUnit(unit: Unit): void { + this.currentUnit = unit; + this.currentProject = null; + + this.currentUnitRole = unit.staff.find( + (ur) => ur.user?.id === this.userService.currentUser?.id, + ); + + if (this.currentUnitRole) { + // Re-map Unit onto UnitRole object + this.currentUnitRole.unit = unit; + } + } + update(): void { this.checkForUpdateService.checkForUpdate(); } diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index cd3886f895..939c0a9c83 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -287,6 +287,11 @@ import {FileUploaderComponent} from './common/file-uploader/file-uploader.compon import {PortfolioWelcomeStepComponent} from './projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component'; import {PortfolioLearningSummaryReportStepComponent} from './projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component'; import {PortfolioAddExtraFilesStepComponent} from './projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component'; +import {PortfoliosComponent} from './units/states/portfolios/portfolios.component'; +import {PortfoliosListComponent} from './units/states/portfolios/directives/portfolios-list/portfolios-list.component'; +import {PortfoliosProjectProgressComponent} from './units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component'; +import {PortfoliosPortfolioViewComponent} from './units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component'; +import {PortfoliosAssessmentComponent} from './units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component'; @NgModule({ // Components we declare @@ -422,6 +427,11 @@ import {PortfolioAddExtraFilesStepComponent} from './projects/states/portfolio/d PortfolioWelcomeStepComponent, PortfolioLearningSummaryReportStepComponent, PortfolioAddExtraFilesStepComponent, + PortfoliosComponent, + PortfoliosListComponent, + PortfoliosProjectProgressComponent, + PortfoliosPortfolioViewComponent, + PortfoliosAssessmentComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 9bac403698..0a40d4e43e 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -59,7 +59,6 @@ import 'build/src/app/config/routing/routing.js'; import 'build/src/app/config/vendor-dependencies/vendor-dependencies.js'; import 'build/src/app/config/analytics/analytics.js'; import 'build/src/app/projects/projects.js'; -import 'build/src/app/projects/project-progress-dashboard/project-progress-dashboard.js'; import 'build/src/app/projects/states/groups/groups.js'; import 'build/src/app/projects/states/feedback/feedback.js'; import 'build/src/app/projects/states/states.js'; @@ -83,7 +82,6 @@ import 'build/src/app/units/units.js'; import 'build/src/app/units/states/tasks/inbox/inbox.js'; import 'build/src/app/units/states/tasks/tasks.js'; import 'build/src/app/units/states/tasks/definition/definition.js'; -import 'build/src/app/units/states/portfolios/portfolios.js'; import 'build/src/app/units/states/groups/groups.js'; import 'build/src/app/units/states/states.js'; import 'build/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.js'; diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index d2a7226cb2..28da9ec3aa 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -15,6 +15,7 @@ import { TaskViewerState } from './units/task-viewer/task-viewer-state.component import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; import { Ng2ViewDeclaration } from '@uirouter/angular'; import { TutorialsComponent } from './projects/states/tutorials/tutorials.component'; +import {PortfoliosComponent} from './units/states/portfolios/portfolios.component'; /* * Use this file to store any states that are sourced by angular components. @@ -430,6 +431,30 @@ const TutorialState: NgHybridStateDeclaration = { }, }; +// TODO 10.0.x: this will need to go under the unit parent state +const PortfoliosState: NgHybridStateDeclaration = { + name: 'units/students/portfolios', + url: '/units/:unitId/students/portfolios', + resolve: { + unitId: [ + '$stateParams', + function ($stateParams) { + return $stateParams.unitId; + }, + ], + }, + views: { + main: { + component: PortfoliosComponent, + }, + }, + data: { + task: 'Student Portfolios', + pageTitle: 'Student Portfolios', + roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor'], + }, +}; + /** * Export the list of states we have created in angular */ @@ -453,4 +478,5 @@ export const doubtfireStates = [ ScormPlayerReviewState, ScormPlayerStudentReviewState, TutorialState, + PortfoliosState, ]; diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.coffee b/src/app/projects/project-progress-dashboard/project-progress-dashboard.coffee deleted file mode 100644 index d28a0d31b5..0000000000 --- a/src/app/projects/project-progress-dashboard/project-progress-dashboard.coffee +++ /dev/null @@ -1,46 +0,0 @@ -angular.module('doubtfire.projects.project-progress-dashboard',[]) - -# -# Progress tab for the student's project -# -# Basically a dashboard where students can see everything about their -# project in one area including burndown chart, tasks to work on -# and their target grade -# -.directive('projectProgressDashboard', -> - restrict: 'E' - templateUrl: 'projects/project-progress-dashboard/project-progress-dashboard.tpl.html' - controller: ($scope, $state, $rootScope, $stateParams, newProjectService, alertService, gradeService, newTaskService, listenerService) -> - if $stateParams.projectId? - $scope.studentProjectId = $stateParams.projectId - else if $scope.project? - $scope.studentProjectId = $scope.project.id - - $scope.grades = gradeService.grades - - $scope.currentVisualisation = 'burndown' - - $scope.chooseGrade = (idx) -> - $scope.project.targetGrade = idx - newProjectService.update($scope.project).subscribe( - (response) -> - alertService.success( "Target updated") - ) - updateTaskCompletionStats() - - $scope.taskCount = -> - $scope.unit.taskDefinitionCount - - $scope.taskStats = {} - - # Update move to task and project... - updateTaskCompletionStats = -> - $scope.taskStats.numberOfTasksCompleted = $scope.project.tasksByStatus(newTaskService.completeStatus).length - $scope.taskStats.numberOfTasksRemaining = $scope.project.activeTasks().length - $scope.taskStats.numberOfTasksCompleted - - $scope.$on 'TaskStatusUpdated', -> - updateTaskCompletionStats() - - - updateTaskCompletionStats() -) diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html b/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html deleted file mode 100644 index 1c28a9eb6f..0000000000 --- a/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html +++ /dev/null @@ -1,126 +0,0 @@ -
    -
    -
    -
    -
    -
    -
    -

    Task List

    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -

    Target Grade

    - Select the grade you wish to achieve in the unit. -
    -
    -

    - - - -

    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -

    Burndown Chart

    - The Burndown chart shows how much work remains for you to achieve your target grade. -
    -
    -

    Task Summary Chart

    - Summary of each of your task statuses -
    -
    -
    -
    -
    - - -
    -
    -
    -
    -
    -
    - -
    -
    - - -
    -

    - -

    - -
    -
    - -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    diff --git a/src/app/projects/projects.coffee b/src/app/projects/projects.coffee index 8499f03af4..1874378696 100644 --- a/src/app/projects/projects.coffee +++ b/src/app/projects/projects.coffee @@ -1,5 +1,4 @@ angular.module('doubtfire.projects', [ 'doubtfire.projects.states' 'doubtfire.projects.project-outcome-alignment' - 'doubtfire.projects.project-progress-dashboard' ]) diff --git a/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.html b/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.html new file mode 100644 index 0000000000..79a17e8cdb --- /dev/null +++ b/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.html @@ -0,0 +1,40 @@ +
    +

    Grade for {{ project.student.name }}

    +

    Assign grade for this project.

    + + Rationale + + + @for (group of gradeResults; track group) { +
    +
    + {{ group.name }} +
    + +
    + @for (score of group.scores; track score) { + + } +
    +
    + } +
    + +
    +
    diff --git a/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.scss b/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.ts b/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.ts new file mode 100644 index 0000000000..5cb990243d --- /dev/null +++ b/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.ts @@ -0,0 +1,42 @@ +import {Component, Input} from '@angular/core'; +import {Project} from 'src/app/api/models/project'; +import {Unit} from 'src/app/api/models/unit'; + +@Component({ + selector: 'f-portfolios-assessment', + templateUrl: './portfolios-assessment.component.html', + styleUrl: './portfolios-assessment.component.scss', +}) +export class PortfoliosAssessmentComponent { + @Input() project: Project; + @Input() unit: Unit; + + public gradeResults = [ + { + name: 'Fail', + scores: [0, 10, 20, 30, 40, 44], + }, + { + name: 'Pass', + scores: [50, 53, 55, 57], + }, + { + name: 'Credit', + scores: [60, 63, 65, 67], + }, + { + name: 'Distinction', + scores: [70, 73, 75, 77], + }, + { + name: 'High Distinction', + scores: [80, 83, 85, 87], + }, + { + name: 'High Distinction', + scores: [90, 93, 95, 97, 100], + }, + ]; + + public maxScoresPerRow = Math.max(...this.gradeResults.map((g) => g.scores.length)); +} diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html new file mode 100644 index 0000000000..ad42aac12f --- /dev/null +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html @@ -0,0 +1,210 @@ +
    +

    Mark portfolios

    +

    Assess student portfolios

    +
    +
    + + + + + @if (hasD2lMapping()) { + + } +
    +
    + + Filter + + + + public + menu_book + + + + account_balance + edit + + + + + All + + @for (grade of gradeValues; track grade) { + + + + } + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Student + {{ project.student.studentId || project.student.username }} + Name + {{ project.student.name }} + Tutor + {{ project.tutorNames() }} + Tutorial + {{ project.shortTutorialDescription() }} + Target + + Submitted as + + Has Portfolio + {{ project.hasPortfolio ? 'Yes' : 'No' }} + Stats +
    + @for (bar of project.taskStats; track bar) { +
    + @if (bar.key === 'not_started') { + {{ bar.value }}% + } + @if (bar.key === 'complete') { + {{ bar.value }}% + } +
    + } +
    +
    Grade + {{ project.grade }} + View + +
    No students found
    + + +
    diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.scss b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts new file mode 100644 index 0000000000..28062f9372 --- /dev/null +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts @@ -0,0 +1,211 @@ +import { + AfterViewInit, + Component, + EventEmitter, + Input, + OnInit, + Output, + ViewChild, +} from '@angular/core'; +import {MatButtonToggleChange} from '@angular/material/button-toggle'; +import {MatPaginator} from '@angular/material/paginator'; +import {MatSort, Sort} from '@angular/material/sort'; +import {MatTableDataSource} from '@angular/material/table'; +import {Project} from 'src/app/api/models/project'; +import {TaskStatusEnum} from 'src/app/api/models/task-status'; +import {Unit} from 'src/app/api/models/unit'; +import {TaskService} from 'src/app/api/services/task.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {GradeService} from 'src/app/common/services/grade.service'; + +@Component({ + selector: 'f-portfolios-list', + templateUrl: './portfolios-list.component.html', + styleUrl: './portfolios-list.component.scss', +}) +export class PortfoliosListComponent implements OnInit, AfterViewInit { + @Input() unit: Unit; + + @Output() + public studentSelected = new EventEmitter(); + + displayedColumns: string[] = []; + + @ViewChild(MatPaginator) paginator!: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + + dataSource = new MatTableDataSource([]); + + public portfolioFilter: 'all' | 'submitted_only' = 'submitted_only'; + public tutorialFilter: 'all' | 'mine' = 'all'; + public gradeFilter: number | null = null; + + constructor( + private taskService: TaskService, + private userService: UserService, + private gradeService: GradeService, + private fileDownloaderService: FileDownloaderService, + ) {} + + ngAfterViewInit() { + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + } + + ngOnInit(): void { + this.updateDataSource(); + } + + openProject(event: Event, project: Project) { + event.stopPropagation(); + window.open(`/#/projects/${project.id}/dashboard/?tutor=true`, '_blank'); + } + + downloadGrades() { + this.fileDownloaderService.downloadFile(this.unit.gradesUrl, `${this.unit.code}-grades.csv`); + } + + downloadPortfolios() { + // TODO 10.0.x: Download portfolios via sidekiq job + } + + public hasD2lMapping() { + // TODO 10.0.x: fetch this.unit.hasD2lMapping() + return false; + } + + transferToD2l() { + // TODO 10.0.x: Open D2lTransferModal for this.unit + } + + public get gradeValues() { + return this.gradeService.gradeValues; + } + + public gradeLabel(grade) { + return this.gradeService.grades[grade]; + } + + updateDataSource() { + const currentUser = this.userService.currentUser; + + const students = this.unit.students + .filter((p) => (this.portfolioFilter === 'submitted_only' ? p.hasPortfolio : true)) + .filter((p) => (this.tutorialFilter === 'mine' ? p.hasTutor(currentUser) : true)) + .filter((p) => (this.gradeFilter !== null ? p.submittedGrade === this.gradeFilter : true)); + + this.displayedColumns = [ + 'student', + 'name', + 'tutor', + 'tutorial', + 'target', + 'submitted-as', + ...(this.portfolioFilter === 'all' ? ['has-portfolio'] : []), + 'stats', + 'grade', + 'actions', + ]; + + this.dataSource.data = students; + this.dataSource.paginator?.firstPage(); + } + + onPortfolioFilterChange(event: MatButtonToggleChange) { + this.portfolioFilter = event.value; + this.updateDataSource(); + } + + onTutorialFilterChange(event: MatButtonToggleChange) { + this.tutorialFilter = event.value; + this.updateDataSource(); + } + + onGradeFilterChange(event: MatButtonToggleChange) { + this.gradeFilter = event.value; + this.updateDataSource(); + } + + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.dataSource.filter = filterValue.trim().toLowerCase(); + + if (this.dataSource.paginator) { + this.dataSource.paginator.firstPage(); + } + + this.dataSource.filterPredicate = (project, filter) => { + const text = [ + project.student.studentId, + project.student.username, + project.student.name, + project.tutorNames(), + project.shortTutorialDescription(), + String(project.grade), + ] + .join(' ') + .toLowerCase(); + + return text.includes(filter); + }; + } + + selectStudent(project: Project) { + this.studentSelected.emit(project); + } + + public statusColor(status: TaskStatusEnum): string { + return this.taskService.statusColors.get(status); + } + + public statusLabel(status: TaskStatusEnum): string { + return this.taskService.statusLabels.get(status); + } + + private sortCompare(aValue: number | string, bValue: number | string, isAsc: boolean) { + return (aValue < bValue ? -1 : 1) * (isAsc ? 1 : -1); + } + + sortTableData(sort: Sort) { + if (!sort.active || sort.direction === '') { + return; + } + this.dataSource.data = this.dataSource.data.sort((a, b) => { + switch (sort.active) { + case 'student': + return this.sortCompare( + a.student.studentId || a.student.username, + b.student.studentId || b.student.username, + sort.direction === 'asc', + ); + case 'name': + return this.sortCompare(a.student?.name, b.student?.name, sort.direction === 'asc'); + case 'tutor': { + return this.sortCompare(a.tutorNames(), b.tutorNames(), sort.direction === 'asc'); + } + case 'tutorial': + return this.sortCompare( + a.shortTutorialDescription(), + b.shortTutorialDescription(), + sort.direction === 'asc', + ); + + case 'target': + return this.sortCompare(a.targetGrade, b.targetGrade, sort.direction === 'asc'); + case 'submitted-as': + return this.sortCompare(a.submittedGrade, b.submittedGrade, sort.direction === 'asc'); + case 'has-portfolio': + return this.sortCompare( + a.hasPortfolio.toString(), + b.hasPortfolio.toString(), + sort.direction === 'asc', + ); + case 'grade': + return this.sortCompare(a.grade, b.grade, sort.direction === 'asc'); + default: + return 0; + } + }); + } +} diff --git a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html new file mode 100644 index 0000000000..c88222fa7c --- /dev/null +++ b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html @@ -0,0 +1,14 @@ +
    +

    Review portfolio of {{ project.student.name }}

    +

    View or download portfolio for assessment.

    + + @if (project.portfolioAvailable) { + + + } @else { +
    + menu_book +

    No Portfolio Submitted

    +
    + } +
    diff --git a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.scss b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts new file mode 100644 index 0000000000..48fca4e3ea --- /dev/null +++ b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts @@ -0,0 +1,11 @@ +import {Component, Input} from '@angular/core'; +import {Project} from 'src/app/api/models/project'; + +@Component({ + selector: 'f-portfolios-portfolio-view', + templateUrl: './portfolios-portfolio-view.component.html', + styleUrl: './portfolios-portfolio-view.component.scss', +}) +export class PortfoliosPortfolioViewComponent { + @Input() project: Project; +} diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html new file mode 100644 index 0000000000..062b08b966 --- /dev/null +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html @@ -0,0 +1,100 @@ +
    +

    Review progress of {{ project.student.name }}

    +

    Review the students progress through the unit's tasks.

    +
    +
    + + + Target Grade + + +
    +
    + + @for (grade of gradeValues; track grade) { + + + + } + +
    + {{ gradeWord(project.targetGrade) ?? 'N/A' }} +
    +
    +
    + + + Submitted Grade + + +
    +
    + + @for (grade of gradeValues; track grade) { + + + + } + +
    + {{ gradeWord(project.submittedGrade) ?? 'N/A' }} +
    +
    +
    +
    + + + Task List + + + + + +
    + + + Task Summary Chart + + + + + + + + Burndown Chart + + +
    + {{ project.student.name }} has completed {{ taskStats.numberOfTasksCompleted }} tasks + and have {{ taskStats.numberOfTasksRemaining }} left to complete to achieve their target + of a + {{ grades[project.targetGrade] }} +
    + +
    +
    +
    +
    +
    diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.scss b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts new file mode 100644 index 0000000000..b075d10c3f --- /dev/null +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts @@ -0,0 +1,82 @@ +import {Component, Input} from '@angular/core'; +import {Project} from 'src/app/api/models/project'; +import {Unit} from 'src/app/api/models/unit'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {TaskService} from 'src/app/api/services/task.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GradeService} from 'src/app/common/services/grade.service'; + +@Component({ + selector: 'f-portfolios-project-progress', + templateUrl: './portfolios-project-progress.component.html', + styleUrl: './portfolios-project-progress.component.scss', +}) +export class PortfoliosProjectProgressComponent { + @Input() project: Project; + @Input() unit: Unit; + + public taskStats: {numberOfTasksCompleted: number; numberOfTasksRemaining: number} = { + numberOfTasksCompleted: 0, + numberOfTasksRemaining: 0, + }; + + constructor( + private gradeService: GradeService, + private projectService: ProjectService, + private alertService: AlertService, + private taskService: TaskService, + ) {} + + public get gradeValues() { + return this.gradeService.gradeValues; + } + public get grades() { + return this.gradeService.grades; + } + + public gradeWord(grade) { + return this.gradeService.grades[grade]; + } + + updateTaskCompletionStats() { + this.taskStats.numberOfTasksCompleted = this.project.tasksByStatus( + this.taskService.completeStatus, + ).length; + this.taskStats.numberOfTasksRemaining = + this.project.activeTasks().length - this.taskStats.numberOfTasksCompleted; + } + + updateSubmittedGrade(newGrade: number): void { + const previousSubmittedGrade = this.project.submittedGrade; + this.project.submittedGrade = newGrade; + + this.projectService.update(this.project).subscribe({ + next: (project) => { + project.refreshBurndownChartData?.(); + this.alertService.success(`Updated project's submitted grade`); + this.updateTaskCompletionStats(); + }, + error: (error) => { + this.project.submittedGrade = previousSubmittedGrade; + this.alertService.error(`Failed to update submitted grade: ${error}`); + }, + }); + } + + updatedTargetGrade(newGrade: number): void { + const previousTargetGrade = this.project.targetGrade; + this.project.targetGrade = newGrade; + + this.projectService.update(this.project).subscribe({ + next: (project) => { + project.refreshBurndownChartData?.(); + this.alertService.success(`Updated project's target grade`); + this.updateTaskCompletionStats(); + }, + error: (error) => { + this.project.targetGrade = previousTargetGrade; + this.alertService.error(`Failed to update target grade: ${error}`); + }, + }); + } +} diff --git a/src/app/units/states/portfolios/portfolios.coffee b/src/app/units/states/portfolios/portfolios.coffee deleted file mode 100644 index c0837ba517..0000000000 --- a/src/app/units/states/portfolios/portfolios.coffee +++ /dev/null @@ -1,129 +0,0 @@ -angular.module('doubtfire.units.states.portfolios', []) -# -# State for staff viewing portfolios -# -.config(($stateProvider) -> - $stateProvider.state 'units/students/portfolios', { - parent: 'units/index' - url: '/students/portfolios' - templateUrl: "units/states/portfolios/portfolios.tpl.html" - controller: "UnitPortfoliosStateCtrl" - data: - task: "Student Portfolios" - pageTitle: "_Home_" - roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor'] - } -) -.controller("UnitPortfoliosStateCtrl", ($scope, alertService, analyticsService, gradeService, newProjectService, Visualisation, newTaskService, fileDownloaderService, newUserService) -> - # TODO: (@alexcu) Break this down into smaller directives/substates - - $scope.downloadGrades = -> fileDownloaderService.downloadFile($scope.unit.gradesUrl, "#{$scope.unit.code}-grades.csv") - $scope.downloadPortfolios = -> fileDownloaderService.downloadFile($scope.unit.portfoliosUrl, "#{$scope.unit.code}-portfolios.zip") - - $scope.studentFilter = 'allStudents' - $scope.portfolioFilter = 'withPortfolio' - - $scope.statusClass = newTaskService.statusClass - $scope.statusText = newTaskService.statusText - - refreshCharts = Visualisation.refreshAll - - # - # Sets the active tab - # - $scope.setActiveTab = (tab) -> - # Do nothing if we're switching to the same tab - return if tab is $scope.activeTab - $scope.activeTab?.active = false - $scope.activeTab = tab - $scope.activeTab.active = true - - if $scope.activeTab == $scope.tabs.viewProgress - refreshCharts() - - # - # Active task tab group - # - $scope.tabs = - selectStudent: - title: "Select Student" - subtitle: "Select the student to assess" - seq: 0 - viewProgress: - title: "View Progress" - subtitle: "See the progress of the student" - seq: 1 - viewPortfolio: - title: "View Portfolio" - subtitle: "See the portfolio of the student" - seq: 2 - assessPortfolio: - title: "Assess Portfolio" - subtitle: "Enter a grade for the student" - seq: 3 - - $scope.setActiveTab($scope.tabs.selectStudent) - - $scope.tutor = newUserService.currentUser - - $scope.search = "" - - # Pagination details - $scope.currentPage = 1 - $scope.maxSize = 5 - $scope.pageSize = 10 - - $scope.filterOptions = {selectedGrade: -1} - $scope.gradeValues = gradeService.gradeValues - $scope.grades = gradeService.grades - $scope.gradeAcronyms = gradeService.gradeAcronyms - - $scope.selectedStudent = null - - $scope.gradeResults = [ - { - name: 'Fail', - scores: [ 0, 10, 20, 30, 40, 44 ] - } - { - name: 'Pass', - scores: [ 50, 53, 55, 57 ] - } - { - name: 'Credit', - scores: [ 60, 63, 65, 67 ] - } - { - name: 'Distinction', - scores: [ 70, 73, 75, 77 ] - } - { - name: 'High Distinction', - scores: [ 80, 83, 85, 87 ] - } - { - name: 'High Distinction', - scores: [ 90, 93, 95, 97, 100 ] - } - ] - - $scope.editingRationale = false - - $scope.toggleEditRationale = -> - $scope.editingRationale = !$scope.editingRationale - - - analyticsService.watchEvent $scope, 'studentFilter', 'Teacher View - Grading Tab' - analyticsService.watchEvent $scope, 'sortOrder', 'Teacher View - Grading Tab' - analyticsService.watchEvent $scope, 'currentPage', 'Teacher View - Grading Tab', 'Selected Page' - - $scope.selectStudent = (student) -> - $scope.selectedStudent = student - $scope.project = null - newProjectService.loadProject(student, $scope.unit).subscribe({ - next: (project) -> - $scope.project = project - $scope.project.preloadedUrl = $scope.project.portfolioUrl() - error: (message) -> alertService.error( message, 6000) - }) -) diff --git a/src/app/units/states/portfolios/portfolios.component.html b/src/app/units/states/portfolios/portfolios.component.html new file mode 100644 index 0000000000..c9c70c8497 --- /dev/null +++ b/src/app/units/states/portfolios/portfolios.component.html @@ -0,0 +1,39 @@ +
    +

    Student Portfolios

    + @if (unit) { + + + + + + @if (selectedProject) { + + } + + + + + @if (selectedProject) { + + } + + + @if (selectedProject) { + + } + + + } @else { + +
    Loading unit...
    + } +
    diff --git a/src/app/units/states/portfolios/portfolios.component.scss b/src/app/units/states/portfolios/portfolios.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/portfolios/portfolios.component.ts b/src/app/units/states/portfolios/portfolios.component.ts new file mode 100644 index 0000000000..4ebd79eccd --- /dev/null +++ b/src/app/units/states/portfolios/portfolios.component.ts @@ -0,0 +1,71 @@ +import {Component, Input, OnInit, ViewChild} from '@angular/core'; +import {MatTabGroup} from '@angular/material/tabs'; +import {StateService} from '@uirouter/core'; +import {Project} from 'src/app/api/models/project'; +import {Unit} from 'src/app/api/models/unit'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {UnitService} from 'src/app/api/services/unit.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; + +@Component({ + selector: 'f-portfolios', + templateUrl: './portfolios.component.html', + styleUrl: './portfolios.component.scss', +}) +export class PortfoliosComponent implements OnInit { + // Passed from doubtfire.states.ts + @Input() unitId: number; + + // Exposed to child components + public unit: Unit = null; + public selectedProject: Project; + + @ViewChild('tabs') tabs!: MatTabGroup; + + constructor( + private globalStateService: GlobalStateService, + private unitService: UnitService, + private projectService: ProjectService, + private stateService: StateService, + private alertService: AlertService, + ) {} + + studentSelected(project: Project) { + this.selectedProject = null; + + this.projectService.loadProject(project, this.unit).subscribe({ + next: (project) => { + this.selectedProject = project; + this.tabs.selectedIndex = 1; + }, + error: (error) => { + this.alertService.error(`Failed to load project: ${error}`, 6000); + console.error(error); + }, + }); + } + + ngOnInit(): void { + // TODO 10.0.x: Unit and student loading needs to be moved to the parent controller (units/{unitId}) when everything is migrated + this.unitService.get(this.unitId).subscribe({ + next: (unit) => { + this.globalStateService.setView(ViewType.UNIT, unit); + + this.projectService.loadStudents(unit, false).subscribe({ + next: () => { + this.unit = unit; + }, + error: (error) => { + this.alertService.error(`Failed to load unit: ${error}`, 6000); + this.stateService.go('home'); + }, + }); + }, + error: (error) => { + this.alertService.error(`Failed to load unit: ${error}`, 6000); + this.stateService.go('home'); + }, + }); + } +} diff --git a/src/app/units/states/portfolios/portfolios.scss b/src/app/units/states/portfolios/portfolios.scss deleted file mode 100644 index 0e1e97b594..0000000000 --- a/src/app/units/states/portfolios/portfolios.scss +++ /dev/null @@ -1,26 +0,0 @@ -.unit-student-portfolio-list { - .select-portfolio-grade.btn-group { - @media (min-width: $screen-sm-max) { - margin: auto 1.2ex; - } - label.btn { - padding: 4px 7px; - font-size: 0.9em; - height: 34px; - } - } -} - -.grade-icon { - color: #fff; - font-size: 1em; - border-radius: 100%; - width: 2.25em; - height: 2.25em; - font-weight: 100; - margin: 0 auto; - display: flex; - align-items: center; - justify-content: center; - background-color: #333333; -} diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html deleted file mode 100644 index 75b9a955ee..0000000000 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ /dev/null @@ -1,319 +0,0 @@ -
    - - - {{tab.title}} - - - -
    -
    -
    -

    Mark Portfolios

    - Assess student portfolios -
    -
    -
    -
    - - -
    -
    - - -
    -
    - -
    -
    - -
    -
    - - - -
    - -
    - -
    -
    - -

    No portfolios found

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - Student - - - - - Name - - - - - Tutor - - - - - Tutorial - - - - - Target - - - - - Submitted as - - - - - Stats - - - - Portfolio? - - - - - Grade - - -
    {{student.student.studentId || student.student.username}}{{student.student.name}}{{student.tutorNames()}}{{student.shortTutorialDescription()}} - - - - - - - {{bar.value}}% - - - - {{student.hasPortfolio ? "Yes" : "No"}} - {{student.grade}}
    -
    - -
    -
    -
    -
    -

    Portfolio Details

    - Review portfolio and assign grade. -
    -
    -
    - -

    Select student to view portfolio and assign grade

    -
    -
    -
    -
    -
    -
    -

    Review Progress of {{selectedStudent.student.name}}

    - Review the students progress through the unit's tasks. -
    -
    -
    - -
    -
    - -
    -
    -
    -

    Review Portfolio of {{selectedStudent.student.name}}

    - View or download portfolio for assessment. -
    -
    -
    - -

    No Portfolio Submitted

    -
    -
    - - -
    -
    - -
    -
    -
    -

    Grade for {{selectedStudent.student.name}}

    - Assign Grade for this work. -
    -
    -
    -
    - -
    - -
    -
    {{results.name}}
    -

    - -

    -
    -
    - -
    -
    -
    -
    -
    diff --git a/src/app/units/states/states.coffee b/src/app/units/states/states.coffee index 7d68872f4a..cd08e56e0c 100644 --- a/src/app/units/states/states.coffee +++ b/src/app/units/states/states.coffee @@ -6,6 +6,5 @@ angular.module('doubtfire.units.states', [ 'doubtfire.units.states.groups' 'doubtfire.units.states.students' 'doubtfire.units.states.analytics' - 'doubtfire.units.states.portfolios' 'doubtfire.units.states.rollover' ]) diff --git a/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.html b/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.html index 374cee4ce8..039c289a6b 100644 --- a/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.html @@ -1,4 +1,4 @@ -
    +
    diff --git a/src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.html b/src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.html index 02f2e78dee..0364d01766 100644 --- a/src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.html +++ b/src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.html @@ -1,4 +1,4 @@ -
    +
    From 09ca9b040c31629e94dd48ee57b2483c38c96bf0 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 19 Nov 2025 16:58:47 +1100 Subject: [PATCH 0742/1531] chore: update migration progress --- README.md | 128 +++++++++++++++++++++++++++--------------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 3dfbd9c89c..a6a2b4bfbc 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,12 @@ A modern, lightweight learning management system. Important: When completing a frontend migration, please update the below list regarding the component you have migrated. -SUMMARY: +### SUMMARY: - `89 / 183` components migrated - `19` components no longer in the doubtfire-lms/9.x branch -NO LONGER IN doubtfire-lms/9.x +### NO LONGER IN doubtfire-lms/9.x - [x] ./src/app/projects/states/all/directives/all-projects-list/all-projects-list.coffee - [x] ./src/app/projects/states/all/all.coffee @@ -41,7 +41,7 @@ NO LONGER IN doubtfire-lms/9.x - [x] ./src/app/common/modals/progress-modal/progress-modal.coffee - [x] ./src/app/errors/states/not-found/not-found.coffee -MIGRATED: +### MIGRATED: - [x] ./src/app/home/splash-screen/splash-screen.component.ts - [x] ./src/app/home/states/home/home.component.ts @@ -151,88 +151,88 @@ MIGRATED: - [x] ./src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee - [x] ./src/app/projects/project-progress-dashboard/project-progress-dashboard.coffee - [x] ./src/app/units/states/portfolios/portfolios.coffee +- [x] ./src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.coffee +- [x] ./src/app/config/local-storage/local-storage.coffee (Removed in 10.0.x) +- [x] ./src/app/projects/states/tutorials/tutorials.coffee +- [x] ./src/app/admin/modals/modals.coffee -TODO: +### TODO: -- [ ] ./src/app/visualisations/alignment-bar-chart.coffee -- [ ] ./src/app/visualisations/summary-task-status-scatter.coffee -- [ ] ./src/app/visualisations/target-grade-pie-chart.coffee -- [ ] ./src/app/visualisations/achievement-custom-bar-chart.coffee -- [ ] ./src/app/visualisations/student-task-status-pie-chart.coffee -- [ ] ./src/app/visualisations/alignment-bullet-chart.coffee -- [ ] ./src/app/visualisations/task-status-pie-chart.coffee -- [ ] ./src/app/visualisations/achievement-box-plot.coffee -- [ ] ./src/app/visualisations/task-completion-box-plot.coffee -- [ ] ./src/app/visualisations/visualisations.coffee -- [ ] ./src/app/tasks/tasks.coffee -- [ ] ./src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment-modal/task-ilo-alignment-modal.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-rater/task-ilo-alignment-rater.coffee -- [ ] ./src/app/tasks/modals/modals.coffee +- [ ] ./src/app/common/common.coffee +- [ ] ./src/app/common/content-editable/content-editable.coffee +- [ ] ./src/app/common/filters/filters.coffee +- [ ] ./src/app/common/modals/csv-result-modal/csv-result-modal.coffee +- [ ] ./src/app/common/modals/modals.coffee +- [ ] ./src/app/common/services/analytics-service.coffee +- [ ] ./src/app/common/services/date-service.coffee +- [ ] ./src/app/common/services/listener-service.coffee +- [ ] ./src/app/common/services/media-service.coffee +- [ ] ./src/app/common/services/outcome-service.coffee +- [ ] ./src/app/common/services/recorder-service.coffee +- [ ] ./src/app/common/services/services.coffee +- [ ] ./src/app/config/analytics/analytics.coffee - [ ] ./src/app/config/config.coffee -- [ ] ./src/app/config/runtime/runtime.coffee - [ ] ./src/app/config/root-controller/root-controller.coffee -- [ ] ./src/app/config/local-storage/local-storage.coffee -- [ ] ./src/app/config/vendor-dependencies/vendor-dependencies.coffee - [ ] ./src/app/config/routing/routing.coffee -- [ ] ./src/app/config/analytics/analytics.coffee +- [ ] ./src/app/config/runtime/runtime.coffee +- [ ] ./src/app/config/vendor-dependencies/vendor-dependencies.coffee +- [ ] ./src/app/errors/errors.coffee +- [ ] ./src/app/errors/states/states.coffee +- [ ] ./src/app/errors/states/timeout/timeout.coffee +- [ ] ./src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee +- [ ] ./src/app/groups/groups.coffee +- [ ] ./src/app/groups/tutor-group-manager/tutor-group-manager.coffee +- [ ] ./src/app/projects/project-outcome-alignment/project-outcome-alignment.coffee - [ ] ./src/app/projects/projects.coffee -- [ ] ./src/app/projects/states/states.coffee -- [ ] ./src/app/projects/states/groups/groups.coffee -- [ ] ./src/app/projects/states/feedback/feedback.coffee +- [ ] ./src/app/projects/states/dashboard/dashboard.coffee - [ ] ./src/app/projects/states/dashboard/directives/directives.coffee - [ ] ./src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.coffee - [ ] ./src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee -- [ ] ./src/app/projects/states/dashboard/dashboard.coffee +- [ ] ./src/app/projects/states/feedback/feedback.coffee +- [ ] ./src/app/projects/states/groups/groups.coffee +- [ ] ./src/app/projects/states/index/index.coffee - [ ] ./src/app/projects/states/outcomes/outcomes.coffee -- [ ] ./src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.coffee - [ ] ./src/app/projects/states/portfolio/directives/directives.coffee -- [ ] ./src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.coffee -- [ ] ./src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.coffee +- [ ] ./src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.coffee (Wait until merged in with 10.0.x) +- [ ] ./src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.coffee (Wait until merged in with 10.0.x) - [ ] ./src/app/projects/states/portfolio/portfolio.coffee -- [ ] ./src/app/projects/states/index/index.coffee -- [ ] ./src/app/projects/project-outcome-alignment/project-outcome-alignment.coffee -- [ ] ./src/app/projects/states/tutorials/tutorials.coffee -- [ ] ./src/app/admin/modals/modals.coffee -- [ ] ./src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee -- [ ] ./src/app/groups/tutor-group-manager/tutor-group-manager.coffee -- [ ] ./src/app/groups/groups.coffee -- [ ] ./src/app/units/states/groups/groups.coffee -- [ ] ./src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.coffee +- [ ] ./src/app/projects/states/states.coffee +- [ ] ./src/app/tasks/modals/modals.coffee +- [ ] ./src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +- [ ] ./src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment-modal/task-ilo-alignment-modal.coffee +- [ ] ./src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment.coffee +- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.coffee +- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-rater/task-ilo-alignment-rater.coffee +- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.coffee +- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment.coffee +- [ ] ./src/app/tasks/tasks.coffee - [ ] ./src/app/units/modals/modals.coffee - [ ] ./src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.coffee -- [ ] ./src/app/units/units.coffee -- [ ] ./src/app/units/states/states.coffee -- [ ] ./src/app/units/states/tasks/tasks.coffee -- [ ] ./src/app/units/states/tasks/definition/definition.coffee -- [ ] ./src/app/units/states/analytics/analytics.coffee +- [ ] ./src/app/units/states/analytics/analytics.coffee (Just the routing, since the TypeScript f-analytics component has been expanded in 10.0.x) - [ ] ./src/app/units/states/edit/directives/directives.coffee +- [ ] ./src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.coffee - [ ] ./src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.coffee - [ ] ./src/app/units/states/edit/edit.coffee +- [ ] ./src/app/units/states/groups/groups.coffee +- [ ] ./src/app/units/states/index/index.coffee - [ ] ./src/app/units/states/rollover/directives/directives.coffee - [ ] ./src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.coffee - [ ] ./src/app/units/states/rollover/rollover.coffee -- [ ] ./src/app/units/states/index/index.coffee +- [ ] ./src/app/units/states/states.coffee - [ ] ./src/app/units/states/students-list/students-list.coffee -- [ ] ./src/app/common/modals/modals.coffee -- [ ] ./src/app/common/modals/csv-result-modal/csv-result-modal.coffee -- [ ] ./src/app/common/common.coffee -- [ ] ./src/app/common/content-editable/content-editable.coffee -- [ ] ./src/app/common/services/media-service.coffee -- [ ] ./src/app/common/services/recorder-service.coffee -- [ ] ./src/app/common/services/outcome-service.coffee -- [ ] ./src/app/common/services/listener-service.coffee -- [ ] ./src/app/common/services/services.coffee -- [ ] ./src/app/common/services/date-service.coffee -- [ ] ./src/app/common/services/analytics-service.coffee -- [ ] ./src/app/errors/errors.coffee -- [ ] ./src/app/errors/states/states.coffee -- [ ] ./src/app/errors/states/timeout/timeout.coffee -- [ ] ./src/app/common/filters/filters.coffee +- [ ] ./src/app/units/states/tasks/definition/definition.coffee +- [ ] ./src/app/units/states/tasks/tasks.coffee +- [ ] ./src/app/units/units.coffee +- [ ] ./src/app/visualisations/achievement-box-plot.coffee +- [ ] ./src/app/visualisations/achievement-custom-bar-chart.coffee +- [ ] ./src/app/visualisations/alignment-bar-chart.coffee +- [ ] ./src/app/visualisations/alignment-bullet-chart.coffee +- [ ] ./src/app/visualisations/student-task-status-pie-chart.coffee +- [ ] ./src/app/visualisations/summary-task-status-scatter.coffee +- [ ] ./src/app/visualisations/target-grade-pie-chart.coffee +- [ ] ./src/app/visualisations/task-completion-box-plot.coffee +- [ ] ./src/app/visualisations/task-status-pie-chart.coffee +- [ ] ./src/app/visualisations/visualisations.coffee ## Table of Contents From 5968f64644fa14505f65aea0f73f5dcfa117cc1a Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 19 Nov 2025 16:59:27 +1100 Subject: [PATCH 0743/1531] chore: remove admin modals coffeescript --- src/app/admin/modals/modals.coffee | 1 - src/app/doubtfire-angularjs.module.ts | 1 - 2 files changed, 2 deletions(-) delete mode 100644 src/app/admin/modals/modals.coffee diff --git a/src/app/admin/modals/modals.coffee b/src/app/admin/modals/modals.coffee deleted file mode 100644 index f05f3bf26b..0000000000 --- a/src/app/admin/modals/modals.coffee +++ /dev/null @@ -1 +0,0 @@ -angular.module('doubtfire.admin.modals', []) \ No newline at end of file diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 0a40d4e43e..f6e596f918 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -73,7 +73,6 @@ import 'build/src/app/projects/states/portfolio/directives/directives.js'; import 'build/src/app/projects/states/portfolio/portfolio.js'; import 'build/src/app/projects/states/index/index.js'; import 'build/src/app/projects/project-outcome-alignment/project-outcome-alignment.js'; -import 'build/src/app/admin/modals/modals.js'; import 'build/src/app/groups/groups.js'; import 'build/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.js'; import 'build/src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.js'; From 0e9223cc94ab96a07127c1523cbd36d4ccbaf972 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:01:48 +1100 Subject: [PATCH 0744/1531] chore: update migration progress --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a6a2b4bfbc..0102408209 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,7 @@ Important: When completing a frontend migration, please update the below list re - [x] ./src/app/config/local-storage/local-storage.coffee (Removed in 10.0.x) - [x] ./src/app/projects/states/tutorials/tutorials.coffee - [x] ./src/app/admin/modals/modals.coffee +- [x] ./src/app/common/services/date-service.coffee ### TODO: @@ -164,7 +165,6 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/common/modals/csv-result-modal/csv-result-modal.coffee - [ ] ./src/app/common/modals/modals.coffee - [ ] ./src/app/common/services/analytics-service.coffee -- [ ] ./src/app/common/services/date-service.coffee - [ ] ./src/app/common/services/listener-service.coffee - [ ] ./src/app/common/services/media-service.coffee - [ ] ./src/app/common/services/outcome-service.coffee From dde1e7697f8a9a93577bb0e18e3e81a3ebd1ace2 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:12:38 +1100 Subject: [PATCH 0745/1531] fix: display groups only when a group set is selected --- .../groups/group-selector/group-selector.component.html | 7 ++++++- src/app/groups/group-selector/group-selector.component.ts | 2 +- .../group-set-manager/group-set-manager.component.html | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/app/groups/group-selector/group-selector.component.html b/src/app/groups/group-selector/group-selector.component.html index b0984e69f3..b2878507d9 100644 --- a/src/app/groups/group-selector/group-selector.component.html +++ b/src/app/groups/group-selector/group-selector.component.html @@ -187,7 +187,12 @@ } - @if (selectedGroupSet.keepGroupsInSameClass && selectedGroupSet.groups.length > 0 && !unitRole) { + @if ( + selectedGroupSet && + selectedGroupSet.keepGroupsInSameClass && + selectedGroupSet.groups.length > 0 && + !unitRole + ) {

    Can't see the group you need to join? Groups shown are limited to those in your allocated tutorials. Use the diff --git a/src/app/groups/group-selector/group-selector.component.ts b/src/app/groups/group-selector/group-selector.component.ts index f4847ba263..54cde0a36d 100644 --- a/src/app/groups/group-selector/group-selector.component.ts +++ b/src/app/groups/group-selector/group-selector.component.ts @@ -87,7 +87,7 @@ export class GroupSelectorComponent refreshGroups() { this.groupsSub?.unsubscribe(); - this.groupsSub = this.selectedGroupSet.groupsCache.values.subscribe((values) => { + this.groupsSub = this.selectedGroupSet?.groupsCache.values.subscribe((values) => { this.groups = [...values]; }); this.applyFilters(); diff --git a/src/app/groups/group-set-manager/group-set-manager.component.html b/src/app/groups/group-set-manager/group-set-manager.component.html index 1f209b3870..0c114326a8 100644 --- a/src/app/groups/group-set-manager/group-set-manager.component.html +++ b/src/app/groups/group-set-manager/group-set-manager.component.html @@ -7,6 +7,7 @@ [selectedGroup]="selectedGroup" [selectedGroupSet]="selectedGroupSet" [onSelect]="groupSelectHandler" + [hidden]="!selectedGroupSet" > From e964d1edcd5a37f7ea5ee9db928348dac231e13b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:32:21 +1100 Subject: [PATCH 0746/1531] chore: revert hidden condition --- .../groups/group-set-manager/group-set-manager.component.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/groups/group-set-manager/group-set-manager.component.html b/src/app/groups/group-set-manager/group-set-manager.component.html index 0c114326a8..4dc322bbe2 100644 --- a/src/app/groups/group-set-manager/group-set-manager.component.html +++ b/src/app/groups/group-set-manager/group-set-manager.component.html @@ -1,4 +1,4 @@ -

    +
    From a79dd46e2e4c57ce4b9c529b673e441da5370994 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 20 Nov 2025 15:33:33 +1100 Subject: [PATCH 0747/1531] chore: update migration progress --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0102408209..df97cc67e5 100644 --- a/README.md +++ b/README.md @@ -156,6 +156,12 @@ Important: When completing a frontend migration, please update the below list re - [x] ./src/app/projects/states/tutorials/tutorials.coffee - [x] ./src/app/admin/modals/modals.coffee - [x] ./src/app/common/services/date-service.coffee +- [ ] ./src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment-modal/task-ilo-alignment-modal.coffee (Removed in 10.0.x) +- [ ] ./src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment.coffee (Removed in 10.0.x) +- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.coffee (Removed in 10.0.x) +- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-rater/task-ilo-alignment-rater.coffee (Removed in 10.0.x) +- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.coffee (Removed in 10.0.x) +- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment.coffee (Removed in 10.0.x) ### TODO: @@ -199,12 +205,6 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/projects/states/states.coffee - [ ] ./src/app/tasks/modals/modals.coffee - [ ] ./src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment-modal/task-ilo-alignment-modal.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-rater/task-ilo-alignment-rater.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment.coffee - [ ] ./src/app/tasks/tasks.coffee - [ ] ./src/app/units/modals/modals.coffee - [ ] ./src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.coffee From 15bbecf57552c59330ec06289a7e622203aec38b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 20 Nov 2025 15:34:24 +1100 Subject: [PATCH 0748/1531] chore: update migration progress --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index df97cc67e5..4a060d55af 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,7 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-rater/task-ilo-alignment-rater.coffee (Removed in 10.0.x) - [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.coffee (Removed in 10.0.x) - [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment.coffee (Removed in 10.0.x) +- [ ] ./src/app/projects/project-outcome-alignment/project-outcome-alignment.coffee (Removed in 10.0.x) ### TODO: @@ -188,7 +189,6 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee - [ ] ./src/app/groups/groups.coffee - [ ] ./src/app/groups/tutor-group-manager/tutor-group-manager.coffee -- [ ] ./src/app/projects/project-outcome-alignment/project-outcome-alignment.coffee - [ ] ./src/app/projects/projects.coffee - [ ] ./src/app/projects/states/dashboard/dashboard.coffee - [ ] ./src/app/projects/states/dashboard/directives/directives.coffee From f505823498bd52f6282d613512c085f8978f48b7 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 25 Nov 2025 12:58:21 +1100 Subject: [PATCH 0749/1531] chore(release): 10.0.0-64 --- CHANGELOG.md | 8 ++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25972b520c..e1e42ecd66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-64](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-63...v10.0.0-64) (2025-11-25) + + +### Bug Fixes + +* avoid calling window to open project in new tab ([9ab015d](https://github.com/b0ink/doubtfire-deploy/commit/9ab015d168cf7e421500910766b9e6fb0bf907f5)) +* use new google fonts api for proper weight loading ([#1039](https://github.com/b0ink/doubtfire-deploy/issues/1039)) ([40f2640](https://github.com/b0ink/doubtfire-deploy/commit/40f2640e6579536cef8e82e9476733083b82bac1)) + ## [10.0.0-63](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-62...v10.0.0-63) (2025-11-10) diff --git a/package-lock.json b/package-lock.json index ac840fcd6d..99a5447d53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-63", + "version": "10.0.0-64", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-63", + "version": "10.0.0-64", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 47621b97b8..2945358894 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-63", + "version": "10.0.0-64", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From bdcd75d91d5ddc7d9a60317bd91289a7242251e1 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 25 Nov 2025 13:11:37 +1100 Subject: [PATCH 0750/1531] fix: typo --- .../upload-submission-modal/upload-submission-modal.tpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html index 65695e16ec..bfda995467 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html @@ -101,7 +101,7 @@

    Final comments

    -
    Character count: {{comment.length}} (Min. 25)
    +
    Character count: {{comment.length}} (Min. 25)
    From 665d6ae86b65e9e8ba83df1ad3d4a053a4553851 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 25 Nov 2025 13:11:44 +1100 Subject: [PATCH 0751/1531] chore(release): 10.0.0-65 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1e42ecd66..6935c31476 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-65](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-64...v10.0.0-65) (2025-11-25) + + +### Bug Fixes + +* typo ([bdcd75d](https://github.com/b0ink/doubtfire-deploy/commit/bdcd75d91d5ddc7d9a60317bd91289a7242251e1)) + ## [10.0.0-64](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-63...v10.0.0-64) (2025-11-25) diff --git a/package-lock.json b/package-lock.json index 99a5447d53..c30263893b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-64", + "version": "10.0.0-65", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-64", + "version": "10.0.0-65", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 2945358894..fb458e4b24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-64", + "version": "10.0.0-65", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From c7776f489b68f97ab93b5f1faf19095bdec18558 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Fri, 28 Nov 2025 14:30:30 +1100 Subject: [PATCH 0752/1531] refactor: migrate rollover state (#1050) * refactor: init rollover migration * refactor: add rollover functionality * refactor: remove comment * chore: remove old rollover component * chore: revert formatting * chore: revert formatting * chore: update migration progress * chore: update migration progress * chore: update migration progress * chore: update migration progress * chore: update migration progress * chore: update migration progress --- README.md | 22 +++--- src/app/api/models/unit.ts | 8 +- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 3 - src/app/doubtfire.states.ts | 26 ++++++ .../unit-details-editor.tpl.html | 2 +- .../rollover/directives/directives.coffee | 3 - .../unit-dates-selector.coffee | 79 ------------------- .../unit-dates-selector.tpl.html | 65 --------------- src/app/units/states/rollover/rollover.coffee | 40 ---------- .../states/rollover/rollover.component.html | 57 +++++++++++++ .../states/rollover/rollover.component.scss | 0 .../states/rollover/rollover.component.ts | 77 ++++++++++++++++++ .../units/states/rollover/rollover.tpl.html | 3 - src/app/units/states/states.coffee | 1 - 15 files changed, 179 insertions(+), 209 deletions(-) delete mode 100644 src/app/units/states/rollover/directives/directives.coffee delete mode 100644 src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.coffee delete mode 100644 src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.tpl.html delete mode 100644 src/app/units/states/rollover/rollover.coffee create mode 100644 src/app/units/states/rollover/rollover.component.html create mode 100644 src/app/units/states/rollover/rollover.component.scss create mode 100644 src/app/units/states/rollover/rollover.component.ts delete mode 100644 src/app/units/states/rollover/rollover.tpl.html diff --git a/README.md b/README.md index 4a060d55af..b97274b557 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Important: When completing a frontend migration, please update the below list re - [x] ./src/app/common/alert-list/alert-list.coffee - [x] ./src/app/common/modals/progress-modal/progress-modal.coffee - [x] ./src/app/errors/states/not-found/not-found.coffee +- [x] ./src/app/groups/tutor-group-manager/tutor-group-manager.coffee ### MIGRATED: @@ -163,6 +164,14 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.coffee (Removed in 10.0.x) - [ ] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment.coffee (Removed in 10.0.x) - [ ] ./src/app/projects/project-outcome-alignment/project-outcome-alignment.coffee (Removed in 10.0.x) +- [ ] ./src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.coffee (Removed in 10.0.x) +- [ ] ./src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.coffee (Removed in 10.0.x) +- [ ] ./src/app/projects/states/outcomes/outcomes.coffee (Removed in 10.0.x) +- [ ] ./src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.coffee (Removed in 10.0.x) +- [x] ./src/app/units/states/rollover/directives/directives.coffee +- [x] ./src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.coffee +- [x] ./src/app/units/states/rollover/rollover.coffee +- [x] ./src/app/visualisations/task-status-pie-chart.coffee ### TODO: @@ -188,7 +197,6 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/errors/states/timeout/timeout.coffee - [ ] ./src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee - [ ] ./src/app/groups/groups.coffee -- [ ] ./src/app/groups/tutor-group-manager/tutor-group-manager.coffee - [ ] ./src/app/projects/projects.coffee - [ ] ./src/app/projects/states/dashboard/dashboard.coffee - [ ] ./src/app/projects/states/dashboard/directives/directives.coffee @@ -197,29 +205,22 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/projects/states/feedback/feedback.coffee - [ ] ./src/app/projects/states/groups/groups.coffee - [ ] ./src/app/projects/states/index/index.coffee -- [ ] ./src/app/projects/states/outcomes/outcomes.coffee - [ ] ./src/app/projects/states/portfolio/directives/directives.coffee -- [ ] ./src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.coffee (Wait until merged in with 10.0.x) -- [ ] ./src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.coffee (Wait until merged in with 10.0.x) +- [ ] ./src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.coffee (Migrate this in 10.0.x) - [ ] ./src/app/projects/states/portfolio/portfolio.coffee - [ ] ./src/app/projects/states/states.coffee - [ ] ./src/app/tasks/modals/modals.coffee - [ ] ./src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee - [ ] ./src/app/tasks/tasks.coffee - [ ] ./src/app/units/modals/modals.coffee -- [ ] ./src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.coffee - [ ] ./src/app/units/states/analytics/analytics.coffee (Just the routing, since the TypeScript f-analytics component has been expanded in 10.0.x) - [ ] ./src/app/units/states/edit/directives/directives.coffee - [ ] ./src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.coffee -- [ ] ./src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.coffee - [ ] ./src/app/units/states/edit/edit.coffee - [ ] ./src/app/units/states/groups/groups.coffee - [ ] ./src/app/units/states/index/index.coffee -- [ ] ./src/app/units/states/rollover/directives/directives.coffee -- [ ] ./src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.coffee -- [ ] ./src/app/units/states/rollover/rollover.coffee - [ ] ./src/app/units/states/states.coffee -- [ ] ./src/app/units/states/students-list/students-list.coffee +- [ ] ./src/app/units/states/students-list/students-list.coffee (Refer to the unit-students-editor component) - [ ] ./src/app/units/states/tasks/definition/definition.coffee - [ ] ./src/app/units/states/tasks/tasks.coffee - [ ] ./src/app/units/units.coffee @@ -231,7 +232,6 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/visualisations/summary-task-status-scatter.coffee - [ ] ./src/app/visualisations/target-grade-pie-chart.coffee - [ ] ./src/app/visualisations/task-completion-box-plot.coffee -- [ ] ./src/app/visualisations/task-status-pie-chart.coffee - [ ] ./src/app/visualisations/visualisations.coffee ## Table of Contents diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index 9d8ed9fa3f..59bbca86d0 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -253,9 +253,11 @@ export class Unit extends Entity { return Math.round((startToNow / totalDuration) * 100); } - public rolloverTo(body: {new_unit_code?: string, start_date: Date; end_date: Date}): Observable; - public rolloverTo(body: {new_unit_code?: string, teaching_period_id: number}): Observable; - public rolloverTo(body: any): Observable { + public rolloverTo( + body: + | {new_unit_code?: string; start_date: Date; end_date: Date} + | {new_unit_code?: string; teaching_period_id: number}, + ): Observable { const unitService = AppInjector.get(UnitService); return unitService.create( diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 939c0a9c83..0c0b4e2411 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -292,6 +292,7 @@ import {PortfoliosListComponent} from './units/states/portfolios/directives/port import {PortfoliosProjectProgressComponent} from './units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component'; import {PortfoliosPortfolioViewComponent} from './units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component'; import {PortfoliosAssessmentComponent} from './units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component'; +import {RolloverComponent} from './units/states/rollover/rollover.component'; @NgModule({ // Components we declare @@ -432,6 +433,7 @@ import {PortfoliosAssessmentComponent} from './units/states/portfolios/directive PortfoliosProjectProgressComponent, PortfoliosPortfolioViewComponent, PortfoliosAssessmentComponent, + RolloverComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index f6e596f918..c1f82e13e7 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -88,9 +88,6 @@ import 'build/src/app/units/states/edit/directives/unit-details-editor/unit-deta import 'build/src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.js'; import 'build/src/app/units/states/edit/directives/directives.js'; import 'build/src/app/units/states/edit/edit.js'; -import 'build/src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.js'; -import 'build/src/app/units/states/rollover/directives/directives.js'; -import 'build/src/app/units/states/rollover/rollover.js'; import 'build/src/app/units/states/index/index.js'; import 'build/src/app/units/states/students-list/students-list.js'; import 'build/src/app/units/states/analytics/analytics.js'; diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index 28da9ec3aa..9f3da83c84 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -16,6 +16,7 @@ import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component import { Ng2ViewDeclaration } from '@uirouter/angular'; import { TutorialsComponent } from './projects/states/tutorials/tutorials.component'; import {PortfoliosComponent} from './units/states/portfolios/portfolios.component'; +import { RolloverComponent } from './units/states/rollover/rollover.component'; /* * Use this file to store any states that are sourced by angular components. @@ -455,6 +456,30 @@ const PortfoliosState: NgHybridStateDeclaration = { }, }; + +const RolloverState: NgHybridStateDeclaration = { + name: 'units/rollover', + url: '/units/:unitId/rollover', + resolve: { + unitId: [ + '$stateParams', + function ($stateParams) { + return $stateParams.unitId; + }, + ], + }, + views: { + main: { + component: RolloverComponent, + }, + }, + data: { + task: 'Unit Rollover', + pageTitle: 'Unit Rollover', + roleWhitelist: ['Convenor', 'Admin'], + }, +}; + /** * Export the list of states we have created in angular */ @@ -479,4 +504,5 @@ export const doubtfireStates = [ ScormPlayerStudentReviewState, TutorialState, PortfoliosState, + RolloverState, ]; diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.tpl.html b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.tpl.html index 3cd81f09c4..1fd0ab346b 100644 --- a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.tpl.html +++ b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.tpl.html @@ -429,4 +429,4 @@

    Update Unit

    -
    +
    \ No newline at end of file diff --git a/src/app/units/states/rollover/directives/directives.coffee b/src/app/units/states/rollover/directives/directives.coffee deleted file mode 100644 index 4f892f1291..0000000000 --- a/src/app/units/states/rollover/directives/directives.coffee +++ /dev/null @@ -1,3 +0,0 @@ -angular.module('doubtfire.units.states.rollover.directives', [ - 'doubtfire.units.states.rollover.directives.unit-dates-selector' -]) \ No newline at end of file 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.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/rollover.coffee b/src/app/units/states/rollover/rollover.coffee deleted file mode 100644 index afc82b1dc9..0000000000 --- a/src/app/units/states/rollover/rollover.coffee +++ /dev/null @@ -1,40 +0,0 @@ -angular.module('doubtfire.units.states.rollover', [ - 'doubtfire.units.states.rollover.directives' -]) - -.config(($stateProvider) -> - $stateProvider.state 'units/rollover', { - parent: 'units/index' - url: '/rollover' - controller: 'RolloverUnitState' - templateUrl: 'units/states/rollover/rollover.tpl.html' - data: - task: 'Unit Rollover' - pageTitle: "_Unit Rollover_" - roleWhitelist: ['Convenor', 'Admin'] - } -) -.controller("RolloverUnitState", ($scope, $state, $stateParams, newUserService, alertService, newUnitService, globalStateService) -> - unitId = +$stateParams.unitId - return $state.go('home') unless unitId - - globalStateService.onLoad () -> - # Load assessing unit role - $scope.unitRole = globalStateService.loadedUnitRoles.currentValues.find((unitRole) -> unitRole.unit.id == unitId) - - if (! $scope.unitRole?) && ( newUserService.currentUser.role == "Admin" ) - $scope.unitRole = newUserService.adminRoleFor(unitId, newUserService.currentUser) - - # Go home if no unit role was found - return $state.go('home') unless $scope.unitRole? - - globalStateService.setView("UNIT", $scope.unitRole) - - newUnitService.get(unitId).subscribe({ - next: (unit)-> $scope.unit = unit - error: (err)-> - alertService.error( "Error loading unit: " + err, 8000) - setTimeout((()-> $state.go('home')), 5000) - }) - -) diff --git a/src/app/units/states/rollover/rollover.component.html b/src/app/units/states/rollover/rollover.component.html new file mode 100644 index 0000000000..f9ac373ed0 --- /dev/null +++ b/src/app/units/states/rollover/rollover.component.html @@ -0,0 +1,57 @@ +
    + + + Copy {{ unit?.code }} {{ unit?.nameAndPeriod }} + + + +

    + Duplicate this unit by copying it to the indicated teaching period, or a custom start and + end date. +

    + +
    + + Teaching Period + + Custom Date + @for (period of teachingPeriods; track period) { + {{ period.year }} {{ period.period }} + } + + + +
    + @if (!teachingPeriod) { + + Start Date + + DD/MM/YYYY + + + + + End Date + + DD/MM/YYYY + + + + } @else { + + {{ teachingPeriod.name }} Start Date + + + + {{ teachingPeriod.name }} End Date + + + } +
    +
    + + + +
    +
    +
    diff --git a/src/app/units/states/rollover/rollover.component.scss b/src/app/units/states/rollover/rollover.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/rollover/rollover.component.ts b/src/app/units/states/rollover/rollover.component.ts new file mode 100644 index 0000000000..f577daa588 --- /dev/null +++ b/src/app/units/states/rollover/rollover.component.ts @@ -0,0 +1,77 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {StateService} from '@uirouter/core'; +import {TeachingPeriod} from 'src/app/api/models/teaching-period'; +import {Unit} from 'src/app/api/models/unit'; +import {TeachingPeriodService} from 'src/app/api/services/teaching-period.service'; +import {UnitService} from 'src/app/api/services/unit.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; + +@Component({ + selector: 'f-rollover', + templateUrl: './rollover.component.html', + styleUrl: './rollover.component.scss', +}) +export class RolloverComponent implements OnInit { + @Input() unitId: number; + + public unit: Unit; + + public teachingPeriods: TeachingPeriod[] = []; + + public teachingPeriod: TeachingPeriod; + + public newStartDate: Date; + public newEndDate: Date; + + constructor( + private globalStateService: GlobalStateService, + private unitService: UnitService, + private alertService: AlertService, + private state: StateService, + private teachingPeriodService: TeachingPeriodService, + ) {} + ngOnInit(): void { + this.globalStateService.onLoad(() => { + this.unitService.get(this.unitId).subscribe({ + next: (unit) => { + this.unit = unit; + this.globalStateService.setView(ViewType.UNIT, unit); + setTimeout(() => { + this.initUnit(); + }); + }, + error: (error) => { + this.alertService.error(`Failed to load unit: ${error}`, 6000); + this.state.go('home'); + }, + }); + }); + } + + initUnit() { + this.teachingPeriodService.cache.values.subscribe((periods) => { + this.teachingPeriods = periods; + this.teachingPeriods = periods.filter((p) => p.endDate.getTime() > Date.now()); + if (this.teachingPeriods.length) { + this.teachingPeriod = this.teachingPeriods[this.teachingPeriods.length - 1]; + } + }); + } + + createUnit() { + const body = this.teachingPeriod + ? {teaching_period_id: this.teachingPeriod.id} + : {start_date: this.newStartDate, end_date: this.newEndDate}; + + this.unit.rolloverTo(body).subscribe({ + next: (response) => { + this.alertService.success(`Unit created`, 2000); + this.state.go('units/admin', {unitId: response.id}); + }, + error: (error) => { + this.alertService.error(`Error creating unit: ${error}`, 6000); + }, + }); + } +} diff --git a/src/app/units/states/rollover/rollover.tpl.html b/src/app/units/states/rollover/rollover.tpl.html deleted file mode 100644 index aa2a80abe2..0000000000 --- a/src/app/units/states/rollover/rollover.tpl.html +++ /dev/null @@ -1,3 +0,0 @@ -
    - -
    diff --git a/src/app/units/states/states.coffee b/src/app/units/states/states.coffee index cd08e56e0c..6860c0f2a0 100644 --- a/src/app/units/states/states.coffee +++ b/src/app/units/states/states.coffee @@ -6,5 +6,4 @@ angular.module('doubtfire.units.states', [ 'doubtfire.units.states.groups' 'doubtfire.units.states.students' 'doubtfire.units.states.analytics' - 'doubtfire.units.states.rollover' ]) From 0611be04e8fe7e75ae07504945a2984839475e3a Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:27:41 +1100 Subject: [PATCH 0753/1531] fix: correctly set rollover end date --- .../directives/unit-dates-selector/unit-dates-selector.coffee | 4 ++-- .../unit-dates-selector/unit-dates-selector.tpl.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 index 07569a20a0..1542d89d20 100644 --- 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 @@ -62,8 +62,8 @@ angular.module('doubtfire.units.states.rollover.directives.unit-dates-selector', } else body = { - start_date: $scope.saveData.startDate - end_date: $scope.saeData.endDate + start_date: $scope.saveData.startDate, + end_date: $scope.saveData.endDate } $scope.unit.rolloverTo(body).subscribe({ next: (response) -> 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 index c3be994325..fdfe7f5f21 100644 --- 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 @@ -39,11 +39,11 @@

    Copy {{unit.code}} {{unit.nameAndPeriod}}

    - + Date: Fri, 28 Nov 2025 15:47:58 +1100 Subject: [PATCH 0754/1531] refactor: migrate unit groups (#1049) * refactor: migrate unit groups * chore: update migration progress * chore: update migration progress * chore: add comment --- README.md | 4 ++-- src/app/doubtfire-angular.module.ts | 2 ++ src/app/doubtfire-angularjs.module.ts | 6 +++++ src/app/units/states/groups/groups.tpl.html | 24 ++++--------------- .../unit-groups/unit-groups.component.html | 21 ++++++++++++++++ .../unit-groups/unit-groups.component.scss | 5 ++++ .../unit-groups/unit-groups.component.ts | 17 +++++++++++++ 7 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 src/app/units/states/groups/unit-groups/unit-groups.component.html create mode 100644 src/app/units/states/groups/unit-groups/unit-groups.component.scss create mode 100644 src/app/units/states/groups/unit-groups/unit-groups.component.ts diff --git a/README.md b/README.md index b97274b557..7b478bcf16 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.coffee - [ ] ./src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee - [ ] ./src/app/projects/states/feedback/feedback.coffee -- [ ] ./src/app/projects/states/groups/groups.coffee +- [ ] ./src/app/projects/states/groups/groups.coffee (-> "project-groups") - [ ] ./src/app/projects/states/index/index.coffee - [ ] ./src/app/projects/states/portfolio/directives/directives.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.coffee (Migrate this in 10.0.x) @@ -217,7 +217,7 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/units/states/edit/directives/directives.coffee - [ ] ./src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.coffee - [ ] ./src/app/units/states/edit/edit.coffee -- [ ] ./src/app/units/states/groups/groups.coffee +- [ ] ./src/app/units/states/groups/groups.coffee (State only -> "unit-groups") - [ ] ./src/app/units/states/index/index.coffee - [ ] ./src/app/units/states/states.coffee - [ ] ./src/app/units/states/students-list/students-list.coffee (Refer to the unit-students-editor component) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 0c0b4e2411..f794925283 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -292,6 +292,7 @@ import {PortfoliosListComponent} from './units/states/portfolios/directives/port import {PortfoliosProjectProgressComponent} from './units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component'; import {PortfoliosPortfolioViewComponent} from './units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component'; import {PortfoliosAssessmentComponent} from './units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component'; +import {UnitGroupsComponent} from './units/states/groups/unit-groups/unit-groups.component'; import {RolloverComponent} from './units/states/rollover/rollover.component'; @NgModule({ @@ -433,6 +434,7 @@ import {RolloverComponent} from './units/states/rollover/rollover.component'; PortfoliosProjectProgressComponent, PortfoliosPortfolioViewComponent, PortfoliosAssessmentComponent, + UnitGroupsComponent, RolloverComponent, ], // Services we provide diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index c1f82e13e7..698deda67a 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -214,6 +214,7 @@ import {FileUploaderComponent} from './common/file-uploader/file-uploader.compon import {PortfolioWelcomeStepComponent} from './projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component'; import {PortfolioLearningSummaryReportStepComponent} from './projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component'; import {PortfolioAddExtraFilesStepComponent} from './projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component'; +import {UnitGroupsComponent} from './units/states/groups/unit-groups/unit-groups.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -550,3 +551,8 @@ DoubtfireAngularJSModule.directive( 'fPortfolioAddExtraFilesStep', downgradeComponent({component: PortfolioAddExtraFilesStepComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fUnitGroups', + downgradeComponent({component: UnitGroupsComponent}), +); diff --git a/src/app/units/states/groups/groups.tpl.html b/src/app/units/states/groups/groups.tpl.html index 6d79bdb9a3..987218beb6 100644 --- a/src/app/units/states/groups/groups.tpl.html +++ b/src/app/units/states/groups/groups.tpl.html @@ -1,19 +1,5 @@ -
    - - -
    - -
    -
    - -

    No Groupwork Enabled

    -
    -
    -

    - There is no group work enabled for this unit. Convenors should create at - least one group set first for groups to be created. This can be found under - the groups tab in the unit administration settings. -

    - Unit Administration -
    -
    + diff --git a/src/app/units/states/groups/unit-groups/unit-groups.component.html b/src/app/units/states/groups/unit-groups/unit-groups.component.html new file mode 100644 index 0000000000..bde04e582a --- /dev/null +++ b/src/app/units/states/groups/unit-groups/unit-groups.component.html @@ -0,0 +1,21 @@ +@if (unit.hasGroupwork()) { +
    + + +
    +} @else { +
    + groups + +

    No Groupwork Enabled

    + +

    + There is no group work enabled for this unit. Convenors should create at least one group set + first for groups to be created. This can be found under the groups tab in the unit + administration settings. +

    + +
    +} diff --git a/src/app/units/states/groups/unit-groups/unit-groups.component.scss b/src/app/units/states/groups/unit-groups/unit-groups.component.scss new file mode 100644 index 0000000000..542e68a366 --- /dev/null +++ b/src/app/units/states/groups/unit-groups/unit-groups.component.scss @@ -0,0 +1,5 @@ +.mat-icon { + font-size: 75px; + width: 75px; + height: 75px; +} diff --git a/src/app/units/states/groups/unit-groups/unit-groups.component.ts b/src/app/units/states/groups/unit-groups/unit-groups.component.ts new file mode 100644 index 0000000000..c9378bf5e0 --- /dev/null +++ b/src/app/units/states/groups/unit-groups/unit-groups.component.ts @@ -0,0 +1,17 @@ +import {Component, Input} from '@angular/core'; +import {GroupSet} from 'src/app/api/models/doubtfire-model'; +import {Unit} from 'src/app/api/models/unit'; +import {UnitRole} from 'src/app/api/models/unit-role'; + +// This component is only displayed to staff +// Students will be shown the projects/states/groups (project-groups) component +@Component({ + selector: 'f-unit-groups', + templateUrl: './unit-groups.component.html', + styleUrl: './unit-groups.component.scss', +}) +export class UnitGroupsComponent { + @Input() unit: Unit; + @Input() unitRole: UnitRole; + @Input() selectedGroupSet: GroupSet; +} From 67159985d84ddc3cff9b2863b41591b66c360128 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 28 Nov 2025 22:37:35 +1100 Subject: [PATCH 0755/1531] refactor: rename chart components --- src/app/doubtfire-angular.module.ts | 6 ++--- src/app/doubtfire-angularjs.module.ts | 6 ++--- ...=> progress-burndown-chart.component.html} | 0 ...=> progress-burndown-chart.component.scss} | 0 ...s => progress-burndown-chart.component.ts} | 4 +-- ...l => task-status-pie-chart.component.html} | 0 ...s => task-status-pie-chart.component.scss} | 0 ....ts => task-status-pie-chart.component.ts} | 4 +-- ...html => task-visualisation.component.html} | 0 ...scss => task-visualisation.component.scss} | 0 ...ent.ts => task-visualisation.component.ts} | 26 +++++++++++-------- 11 files changed, 25 insertions(+), 21 deletions(-) rename src/app/visualisations/progress-burndown-chart/{progressburndownchart.component.html => progress-burndown-chart.component.html} (100%) rename src/app/visualisations/progress-burndown-chart/{progressburndownchart.component.scss => progress-burndown-chart.component.scss} (100%) rename src/app/visualisations/progress-burndown-chart/{progressburndownchart.component.ts => progress-burndown-chart.component.ts} (97%) rename src/app/visualisations/task-status-pie-chart/{taskstatuspiechart.component.html => task-status-pie-chart.component.html} (100%) rename src/app/visualisations/task-status-pie-chart/{taskstatuspiechart.component.scss => task-status-pie-chart.component.scss} (100%) rename src/app/visualisations/task-status-pie-chart/{taskstatuspiechart.component.ts => task-status-pie-chart.component.ts} (95%) rename src/app/visualisations/task-visualisation/{taskvisualisation.component.html => task-visualisation.component.html} (100%) rename src/app/visualisations/task-visualisation/{taskvisualisation.component.scss => task-visualisation.component.scss} (100%) rename src/app/visualisations/task-visualisation/{taskvisualisation.component.ts => task-visualisation.component.ts} (72%) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index f794925283..2ed284691b 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -247,8 +247,8 @@ import {UnitRootStateComponent} from './units/unit-root-state.component'; import {TaskViewerStateComponent} from './units/task-viewer/task-viewer-state.component'; import {ProjectRootStateComponent} from './projects/states/project-root-state.component'; import {ProjectProgressDashboardComponent} from './projects/project-progress-dashboard/project-progress-dashboard.component'; -import {ProgressBurndownChartComponent} from './visualisations/progress-burndown-chart/progressburndownchart.component'; -import {TaskVisualisationComponent} from './visualisations/task-visualisation/taskvisualisation.component'; +import {ProgressBurndownChartComponent} from './visualisations/progress-burndown-chart/progress-burndown-chart.component'; +import {TaskVisualisationComponent} from './visualisations/task-visualisation/task-visualisation.component'; import {ChartBaseComponent} from './common/chart-base/chart-base-component/chart-base-component.component'; import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; import {ScormAdapterService} from './api/services/scorm-adapter.service'; @@ -279,7 +279,7 @@ const MY_DATE_FORMAT = { }; import {TutorialsComponent} from './projects/states/tutorials/tutorials.component'; import {UnitStudentEnrolmentModalComponent} from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component'; -import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-chart/taskstatuspiechart.component'; +import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-chart/task-status-pie-chart.component'; import {GroupMemberListComponent} from './groups/group-member-list/group-member-list.component'; import {GroupSelectorComponent} from './groups/group-selector/group-selector.component'; import {GroupSetManagerComponent} from './groups/group-set-manager/group-set-manager.component'; diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 698deda67a..7fdba35560 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -147,7 +147,7 @@ import {fPdfViewerComponent} from './common/pdf-viewer/pdf-viewer.component'; import {PdfViewerPanelComponent} from './common/pdf-viewer-panel/pdf-viewer-panel.component'; import {StaffTaskListComponent} from './units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component'; import {StatusIconComponent} from './common/status-icon/status-icon.component'; -import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-chart/taskstatuspiechart.component'; +import {TaskStatusPieChartComponent} from './visualisations/task-status-pie-chart/task-status-pie-chart.component'; import { GroupSetService, LearningOutcomeService, @@ -192,8 +192,8 @@ import {FUsersComponent} from './admin/states/users/users.component'; import {FUnitTaskListComponent} from './units/task-viewer/directives/unit-task-list/unit-task-list.component'; import {FTaskDetailsViewComponent} from './units/task-viewer/directives/task-details-view/task-details-view.component'; import {FTaskSheetViewComponent} from './units/task-viewer/directives/task-sheet-view/task-sheet-view.component'; -import {ProgressBurndownChartComponent} from './visualisations/progress-burndown-chart/progressburndownchart.component'; -import {TaskVisualisationComponent} from './visualisations/task-visualisation/taskvisualisation.component'; +import {ProgressBurndownChartComponent} from './visualisations/progress-burndown-chart/progress-burndown-chart.component'; +import {TaskVisualisationComponent} from './visualisations/task-visualisation/task-visualisation.component'; import {TutorialsComponent} from './projects/states/tutorials/tutorials.component'; import {ProgressDashboardComponent} from './projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component'; import {FUnitsComponent} from './admin/states/units/units.component'; diff --git a/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html similarity index 100% rename from src/app/visualisations/progress-burndown-chart/progressburndownchart.component.html rename to src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html diff --git a/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.scss b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.scss similarity index 100% rename from src/app/visualisations/progress-burndown-chart/progressburndownchart.component.scss rename to src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.scss diff --git a/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts similarity index 97% rename from src/app/visualisations/progress-burndown-chart/progressburndownchart.component.ts rename to src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts index e49ca853dc..cec3c2c3bf 100644 --- a/src/app/visualisations/progress-burndown-chart/progressburndownchart.component.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts @@ -6,8 +6,8 @@ import {ChartBaseComponent} from 'src/app/common/chart-base/chart-base-component @Component({ selector: 'f-progress-burndown-chart', - templateUrl: './progressburndownchart.component.html', - styleUrls: ['./progressburndownchart.component.scss'], + templateUrl: './progress-burndown-chart.component.html', + styleUrls: ['./progress-burndown-chart.component.scss'], }) export class ProgressBurndownChartComponent extends ChartBaseComponent implements OnInit { @Input() project: Project; diff --git a/src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.html b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.html similarity index 100% rename from src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.html rename to src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.html diff --git a/src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.scss b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.scss similarity index 100% rename from src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.scss rename to src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.scss diff --git a/src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.ts b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts similarity index 95% rename from src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.ts rename to src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts index 1e9bb142d8..27a9fcd8c4 100644 --- a/src/app/visualisations/task-status-pie-chart/taskstatuspiechart.component.ts +++ b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts @@ -4,8 +4,8 @@ import {ChartBaseComponent} from 'src/app/common/chart-base/chart-base-component @Component({ selector: 'f-task-status-pie-chart', - templateUrl: './taskstatuspiechart.component.html', - styleUrls: ['./taskstatuspiechart.component.scss'], + templateUrl: './task-status-pie-chart.component.html', + styleUrls: ['./task-status-pie-chart.component.scss'], }) export class TaskStatusPieChartComponent extends ChartBaseComponent implements OnInit { @Input() project: Project; diff --git a/src/app/visualisations/task-visualisation/taskvisualisation.component.html b/src/app/visualisations/task-visualisation/task-visualisation.component.html similarity index 100% rename from src/app/visualisations/task-visualisation/taskvisualisation.component.html rename to src/app/visualisations/task-visualisation/task-visualisation.component.html diff --git a/src/app/visualisations/task-visualisation/taskvisualisation.component.scss b/src/app/visualisations/task-visualisation/task-visualisation.component.scss similarity index 100% rename from src/app/visualisations/task-visualisation/taskvisualisation.component.scss rename to src/app/visualisations/task-visualisation/task-visualisation.component.scss diff --git a/src/app/visualisations/task-visualisation/taskvisualisation.component.ts b/src/app/visualisations/task-visualisation/task-visualisation.component.ts similarity index 72% rename from src/app/visualisations/task-visualisation/taskvisualisation.component.ts rename to src/app/visualisations/task-visualisation/task-visualisation.component.ts index 8b5c1e1f50..c90fc32759 100644 --- a/src/app/visualisations/task-visualisation/taskvisualisation.component.ts +++ b/src/app/visualisations/task-visualisation/task-visualisation.component.ts @@ -1,24 +1,22 @@ -import { Component, OnInit, Input, SimpleChanges } from '@angular/core'; -import { Color } from 'd3'; -import { Project, TaskStatus, TaskStatusEnum } from 'src/app/api/models/doubtfire-model'; +import {Component, OnInit, Input, SimpleChanges} from '@angular/core'; +import {Color} from 'd3'; +import {Project, TaskStatus, TaskStatusEnum} from 'src/app/api/models/doubtfire-model'; @Component({ selector: 'f-task-visualisation', - templateUrl: './taskvisualisation.component.html', - styleUrls: ['./taskvisualisation.component.scss'] + templateUrl: './task-visualisation.component.html', + styleUrls: ['./task-visualisation.component.scss'], }) - export class TaskVisualisationComponent implements OnInit { @Input() project: Project; @Input() grade: number; - data: {name: string, value: number}[] = []; - colors: {name: string, value: string}[]; + data: {name: string; value: number}[] = []; + colors: {name: string; value: string}[]; view: number[] = [700, 400]; // options textColor: string = '#F5F5F5'; - ngOnInit(): void { this.updateData(); } @@ -39,7 +37,13 @@ export class TaskVisualisationComponent implements OnInit { } }); - const sortOrder = ['Complete', 'Discuss', 'Awaiting Feedback', 'Working On It', 'Not Started']; + const sortOrder = [ + 'Complete', + 'Discuss', + 'Awaiting Feedback', + 'Working On It', + 'Not Started', + ]; this.data = Array.from(taskCounts) .map(([status, count]) => { @@ -60,7 +64,7 @@ export class TaskVisualisationComponent implements OnInit { }); this.colors = Array.from(TaskStatus.STATUS_COLORS).map(([status, color]) => { - return { name: TaskStatus.STATUS_LABELS.get(status), value: color }; + return {name: TaskStatus.STATUS_LABELS.get(status), value: color}; }); // console.log('Data:', this.data); From 6965c96f75f40c0423d606411c9aeef16f3f0a93 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 28 Nov 2025 22:39:50 +1100 Subject: [PATCH 0756/1531] chore: remove unused visualisations --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7b478bcf16..fc8827a0bd 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,11 @@ Important: When completing a frontend migration, please update the below list re - [x] ./src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.coffee - [x] ./src/app/units/states/rollover/rollover.coffee - [x] ./src/app/visualisations/task-status-pie-chart.coffee +- [x] ./src/app/visualisations/student-task-status-pie-chart.coffee +- [ ] ./src/app/visualisations/achievement-box-plot.coffee (ILO Alignments removed) +- [ ] ./src/app/visualisations/achievement-custom-bar-chart.coffee (ILO Alignments removed) +- [ ] ./src/app/visualisations/alignment-bar-chart.coffee (ILO Alignments removed) +- [ ] ./src/app/visualisations/alignment-bullet-chart.coffee (ILO Alignments removed) ### TODO: @@ -224,12 +229,7 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/units/states/tasks/definition/definition.coffee - [ ] ./src/app/units/states/tasks/tasks.coffee - [ ] ./src/app/units/units.coffee -- [ ] ./src/app/visualisations/achievement-box-plot.coffee -- [ ] ./src/app/visualisations/achievement-custom-bar-chart.coffee -- [ ] ./src/app/visualisations/alignment-bar-chart.coffee -- [ ] ./src/app/visualisations/alignment-bullet-chart.coffee -- [ ] ./src/app/visualisations/student-task-status-pie-chart.coffee -- [ ] ./src/app/visualisations/summary-task-status-scatter.coffee +- [ ] ./src/app/visualisations/summary-task-status-scatter.coffee (Unit task status summary) - [ ] ./src/app/visualisations/target-grade-pie-chart.coffee - [ ] ./src/app/visualisations/task-completion-box-plot.coffee - [ ] ./src/app/visualisations/visualisations.coffee From 9be2044886742a2aa78e5aed6da53f2837c49346 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 28 Nov 2025 22:40:09 +1100 Subject: [PATCH 0757/1531] chore: remove unused visualisations --- .../achievement-box-plot.coffee | 67 -- .../achievement-custom-bar-chart.coffee | 677 ------------------ .../visualisations/alignment-bar-chart.coffee | 41 -- .../alignment-bullet-chart.coffee | 591 --------------- .../student-task-status-pie-chart.coffee | 41 -- 5 files changed, 1417 deletions(-) delete mode 100644 src/app/visualisations/achievement-box-plot.coffee delete mode 100644 src/app/visualisations/achievement-custom-bar-chart.coffee delete mode 100644 src/app/visualisations/alignment-bar-chart.coffee delete mode 100644 src/app/visualisations/alignment-bullet-chart.coffee delete mode 100644 src/app/visualisations/student-task-status-pie-chart.coffee diff --git a/src/app/visualisations/achievement-box-plot.coffee b/src/app/visualisations/achievement-box-plot.coffee deleted file mode 100644 index 7ef7646829..0000000000 --- a/src/app/visualisations/achievement-box-plot.coffee +++ /dev/null @@ -1,67 +0,0 @@ -angular.module('doubtfire.visualisations.achievement-box-plot', []) -.directive 'achievementBoxPlot', -> - replace: true - restrict: 'E' - templateUrl: 'visualisations/visualisation.tpl.html' - scope: - rawData: '=data' - type: '=' - unit: '=' - pctHolder: '=' - height: '=?' - showLegend: '=?' - controller: ($scope, $timeout, Visualisation, outcomeService, $sce) -> - $scope.showLegend = unless $scope.showLegend? then true else $scope.showLegend - $scope.height = unless $scope.height? then 600 else $scope.height - - iloValues = outcomeService.calculateTargets($scope.unit, $scope.unit, $scope.unit.taskStatusFactor) - iloMaxes = _.mapValues iloValues, (d, k) -> _.reduce d, ((memo, value) -> memo + value), 0 - rangeMax = _.max _.values(iloMaxes) - - refreshData = (newData) -> - isPct = ($scope.pctHolder? and $scope.pctHolder.pct) - if isPct - $scope.options.chart.yDomain = [0, 1] - else - $scope.options.chart.yDomain = [0, rangeMax] - - $scope.data = _.map newData, (d, id) -> - max = iloMaxes[id] - if (! max?) or max == 0 or ! isPct - max = 1 - label = _.find($scope.unit.ilos, { id: +id }).abbreviation - { - label: $sce.getTrustedHtml(label), - values: { - Q1: d.lower / max - Q2: d.median / max - Q3: d.upper / max - whisker_low: d.min / max - whisker_high: d.max / max - } - } - $timeout -> - if $scope.api?.refresh? - $scope.api.refresh() - - [$scope.options, $scope.config] = Visualisation 'boxPlotChart', 'ILO Achievement Box Plot', { - x: (d) -> d.label - height: $scope.height - showXAxis: $scope.showLegend - margin: - top: if $scope.showLegend then 20 else 20 - right: if $scope.showLegend then 10 else 10 - bottom: if $scope.showLegend then 60 else 20 - left: if $scope.showLegend then 80 else 40 - yAxis: - axisLabel: if $scope.showLegend then "ILO Achievement" - tooltip: - enabled: $scope.showLegend - maxBoxWidth: 75 - yDomain: [0, 1] - }, {}, 'Achievement Box Plot' - - # $scope.$watch 'rawData', refreshData($scope.rawData) - $scope.$watch 'pctHolder.pct', (newData, oldData) -> if newData != oldData then refreshData($scope.rawData) - - refreshData($scope.rawData) diff --git a/src/app/visualisations/achievement-custom-bar-chart.coffee b/src/app/visualisations/achievement-custom-bar-chart.coffee deleted file mode 100644 index 6eafad4c6d..0000000000 --- a/src/app/visualisations/achievement-custom-bar-chart.coffee +++ /dev/null @@ -1,677 +0,0 @@ -angular.module('doubtfire.visualisations.achievement-custom-bar-chart', []) -.directive 'achievementCustomBarChart', -> - replace: true - restrict: 'E' - templateUrl: 'visualisations/visualisation.tpl.html' - scope: - project: '=' - unit: '=' - - controller: ($scope, Visualisation, outcomeService, gradeService, $sce) -> - $scope.showLegend = if $scope.showLegend? then $scope.showLegend else true - unless nv.models.achievementBar? - nv.models.achievementBar = -> - chart = (selection) -> - renderWatch.reset() - selection.each (data) -> - availableWidth = width - (margin.left) - (margin.right) - availableHeight = height - (margin.top) - (margin.bottom) - container = d3.select(this) - nv.utils.initSVG container - #add series index to each data point for reference - data.forEach (series, i) -> - series.values.forEach (point) -> - point.series = i - return - return - # Setup Scales - # remap and flatten the data for use in calculating the scales' domains - seriesData = if xDomain and yDomain then [] else data.map(((d) -> - d.values.map ((d, i) -> - { - x: getX(d, i) - y: getY(d, i) - y0: d.y0 - } - ) - )) - x.domain(xDomain or d3.merge(seriesData).map((d) -> - d.x - )).rangeBands xRange or [ - 0 - availableWidth - ], .1 - y.domain yDomain or d3.extent(d3.merge(seriesData).map((d) -> - d.y - ).concat(forceY)) - # If showValues, pad the Y axis range to account for label height - if showValues - y.range yRange or [ - availableHeight - (if y.domain()[0] < 0 then 12 else 0) - if y.domain()[1] > 0 then 12 else 0 - ] - else - y.range yRange or [ - availableHeight - 0 - ] - #store old scales if they exist - x0 = x0 or x - y0 = y0 or y.copy().range([ - y(0) - y(0) - ]) - # Setup containers and skeleton of chart - wrap = container.selectAll('g.nv-wrap.nv-discretebar').data([ data ]) - wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discretebar') - gEnter = wrapEnter.append('g') - g = wrap.select('g') - gEnter.append('g').attr 'class', 'nv-groups' - wrap.attr 'transform', 'translate(' + margin.left + ',' + margin.top + ')' - # TODO: (@macite) by definition, the discrete bar should not have multiple groups, will modify/remove later - groups = wrap.select('.nv-groups').selectAll('.nv-group').data(((d) -> - d - ), (d) -> - d.key - ) - groups.enter().append('g').style('stroke-opacity', 1e-6).style 'fill-opacity', 1e-6 - groups.exit().watchTransition(renderWatch, 'discreteBar: exit groups').style('stroke-opacity', 1e-6).style('fill-opacity', 1e-6).remove() - groups.attr('class', (d, i) -> - 'nv-group nv-series-' + i - ) - groups.watchTransition(renderWatch, 'discreteBar: groups').style('stroke-opacity', 1).style 'fill-opacity', .75 - - if targets? && _.size(targets) > 0 - # Create the background bars... match one set per ILO - backBarSeries = groups.selectAll('g.nv-backBarSeries').data((d) -> - d.values - ) - backBarSeries.exit().remove() - backBarSeries.enter().append('g') - backBarSeries.attr('class', (d, i) -> - 'nv-backBarSeries nv-backSeries-' + i - ).classed 'hover', (d) -> - d.hover - - backBars = backBarSeries.selectAll('g.nv-backBar').data( (d,i) -> _.map(_.values(d.targets), (v) -> { value: v, key: d.label } ) ) - backBars.exit().remove() - backBarsEnter = backBars.enter().append('g') - - backBarsEnter.append('rect').attr('height', 10).attr 'width', x.rangeBand() * 0.9 / data.length - backBarsEnter.on('mouseover', (d, i) -> - d3.select(this).classed 'hover', true - dispatch.elementMouseover - data: gradeService.grades[i] - index: i - color: d.value.color - return - ).on('mouseout', (d, i) -> - d3.select(this).classed 'hover', false - dispatch.elementMouseout - data: gradeService.grades[i] - index: i - color: d.value.color - return - ).on('mousemove', (d, i) -> - dispatch.elementMousemove - data: gradeService.grades[i] - index: i - color: d.value.color - return - ).on('click', (d, i) -> - element = this - dispatch.elementClick - data: gradeService.grades[i] - index: i - color: d.value.color - event: d3.event - element: element - d3.event.stopPropagation() - return - ).on('dblclick', (d, i) -> - dispatch.elementDblClick - data: gradeService.grades[i] - index: i - color: d.value.color - d3.event.stopPropagation() - return - ) - - backBars.attr('class', (d, i, j) -> - if d.value.height < 0 then 'nv-backBar negative' else 'nv-backBar positive' - ).select('rect').attr('class', rectClass).style('fill-opacity', '0.2'). - style('fill', (d) -> d.value.color). - watchTransition(renderWatch, 'discreteBar: backBars rect').attr 'width', x.rangeBand() * .9 / data.length - backBars.watchTransition(renderWatch, 'discreteBar: backBars').attr('transform', (d, i, j) -> - left = x(d.key) + x.rangeBand() * .05 - top = y(d.value.height + d.value.offset) - 'translate(' + left + ', ' + top + ')' - ).select('rect').attr 'height', (d, i, j) -> - Math.max Math.abs(y(d.value.height) - y(0)), 1 - - bars = groups.selectAll('g.nv-bar').data((d) -> - d.values - ) - bars.exit().remove() - barsEnter = bars.enter().append('g').on('mouseover', (d, i) -> - # TODO: (@macite) figure out why j works above, but not here - d3.select(this).classed 'hover', true - dispatch.elementMouseover - data: d - index: i - color: d3.select(this).style('fill') - return - ).on('mouseout', (d, i) -> - d3.select(this).classed 'hover', false - dispatch.elementMouseout - data: d - index: i - color: d3.select(this).style('fill') - return - ).on('mousemove', (d, i) -> - dispatch.elementMousemove - data: d - index: i - color: d3.select(this).style('fill') - return - ).on('click', (d, i) -> - element = this - dispatch.elementClick - data: d - index: i - color: d3.select(this).style('fill') - event: d3.event - element: element - d3.event.stopPropagation() - return - ).on('dblclick', (d, i) -> - dispatch.elementDblClick - data: d - index: i - color: d3.select(this).style('fill') - d3.event.stopPropagation() - return - ) - - barsEnter.append('rect').attr('height', 0).attr 'width', x.rangeBand() * .5 / data.length - if showValues - barsEnter.append('text').attr 'text-anchor', 'middle' - bars.select('text').text((d, i) -> - valueFormat getY(d, i) - ).watchTransition(renderWatch, 'discreteBar: bars text').attr('x', x.rangeBand() * .5 / 2).attr 'y', (d, i) -> - if getY(d, i) < 0 then y(getY(d, i)) - y(0) + 12 else -4 - else - bars.selectAll('text').remove() - bars.attr('class', (d, i) -> - if getY(d, i) < 0 then 'nv-bar negative' else 'nv-bar positive' - ).style('fill', (d, i) -> - d.color or color(d, i) - ).style('stroke', (d, i) -> - d.color or color(d, i) - ).select('rect').attr('class', rectClass).watchTransition(renderWatch, 'discreteBar: bars rect').attr 'width', x.rangeBand() * .5 / data.length - bars.watchTransition(renderWatch, 'discreteBar: bars').attr('transform', (d, i) -> - left = x(getX(d, i)) + x.rangeBand() * .25 - top = if getY(d, i) < 0 then y(0) else if y(0) - y(getY(d, i)) < 1 then y(0) - 1 else y(getY(d, i)) - 'translate(' + left + ', ' + top + ')' - ).select('rect').attr 'height', (d, i) -> - Math.max Math.abs(y(getY(d, i)) - y(0)), 1 - #store old scales for use in transitions on update - x0 = x.copy() - y0 = y.copy() - return - renderWatch.renderEnd 'achievementBar immediate' - chart - - 'use strict' - #============================================================ - # Public Variables with Default Settings - #------------------------------------------------------------ - margin = - top: 0 - right: 0 - bottom: 0 - left: 0 - width = 960 - height = 500 - id = Math.floor(Math.random() * 10000) - container = undefined - x = d3.scale.ordinal() - y = d3.scale.linear() - - getX = (d) -> - d.x - - getY = (d) -> - d.y - - forceY = [ 0 ] - color = nv.utils.defaultColor() - showValues = false - valueFormat = d3.format(',.2f') - xDomain = undefined - yDomain = undefined - xRange = undefined - yRange = undefined - dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') - rectClass = 'discreteBar' - duration = 250 - #============================================================ - # Private Variables - #------------------------------------------------------------ - x0 = undefined - y0 = undefined - renderWatch = nv.utils.renderWatch(dispatch, duration) - #============================================================ - # Expose Public Variables - #------------------------------------------------------------ - chart.dispatch = dispatch - chart.options = nv.utils.optionsFunc.bind(chart) - chart._options = Object.create({}, - width: - get: -> - width - set: (_) -> - width = _ - return - height: - get: -> - height - set: (_) -> - height = _ - return - forceY: - get: -> - forceY - set: (_) -> - forceY = _ - return - showValues: - get: -> - showValues - set: (_) -> - showValues = _ - return - x: - get: -> - getX - set: (_) -> - getX = _ - return - y: - get: -> - getY - set: (_) -> - getY = _ - return - xScale: - get: -> - x - set: (_) -> - x = _ - return - yScale: - get: -> - y - set: (_) -> - y = _ - return - xDomain: - get: -> - xDomain - set: (_) -> - xDomain = _ - return - yDomain: - get: -> - yDomain - set: (_) -> - yDomain = _ - return - xRange: - get: -> - xRange - set: (_) -> - xRange = _ - return - yRange: - get: -> - yRange - set: (_) -> - yRange = _ - return - valueFormat: - get: -> - valueFormat - set: (_) -> - valueFormat = _ - return - id: - get: -> - id - set: (_) -> - id = _ - return - rectClass: - get: -> - rectClass - set: (_) -> - rectClass = _ - return - margin: - get: -> - margin - set: (_) -> - margin.top = if _.top != undefined then _.top else margin.top - margin.right = if _.right != undefined then _.right else margin.right - margin.bottom = if _.bottom != undefined then _.bottom else margin.bottom - margin.left = if _.left != undefined then _.left else margin.left - return - color: - get: -> - color - set: (_) -> - color = nv.utils.getColor(_) - return - duration: - get: -> - duration - set: (_) -> - duration = _ - renderWatch.reset duration - return - ) - nv.utils.initOptions chart - chart - - # - # Chart that contains stacked bars in the background, overlaid by other bars... - # - nv.models.achievementBarChart = -> - chart = (selection) -> - renderWatch.reset() - renderWatch.models achievementbar - if showXAxis - renderWatch.models xAxis - if showYAxis - renderWatch.models yAxis - selection.each (data) -> - container = d3.select(this) - that = this - nv.utils.initSVG container - availableWidth = nv.utils.availableWidth(width, container, margin) - availableHeight = nv.utils.availableHeight(height, container, margin) - - chart.update = -> - dispatch.beforeUpdate() - container.transition().duration(duration).call chart - return - - chart.container = this - - # Display No Data message if there's nothing to show. - if (!data) or (!data.length) or data.filter(((d) -> d.values.length)).length <= 0 - nv.utils.noData chart, container - return chart - else - container.selectAll('.nv-noData').remove() - - # Setup Scales - x = achievementbar.xScale() - y = achievementbar.yScale().clamp(true) - # Setup containers and skeleton of chart - wrap = container.selectAll('g.nv-wrap.nv-discreteBarWithAxes').data([ data ]) - gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discreteBarWithAxes').append('g') - defsEnter = gEnter.append('defs') - g = wrap.select('g') - gEnter.append('g').attr 'class', 'nv-x nv-axis' - gEnter.append('g').attr('class', 'nv-y nv-axis').append('g').attr('class', 'nv-zeroLine').append 'line' - gEnter.append('g').attr 'class', 'nv-barsWrap' - gEnter.append('g').attr 'class', 'nv-legendWrap' - g.attr 'transform', 'translate(' + margin.left + ',' + margin.top + ')' - if showLegend - legend.width availableWidth - g.select('.nv-legendWrap').datum(data).call legend - if margin.top != legend.height() - margin.top = legend.height() - availableHeight = nv.utils.availableHeight(height, container, margin) - wrap.select('.nv-legendWrap').attr 'transform', 'translate(0,' + -margin.top + ')' - if rightAlignYAxis - g.select('.nv-y.nv-axis').attr 'transform', 'translate(' + availableWidth + ',0)' - if rightAlignYAxis - g.select('.nv-y.nv-axis').attr 'transform', 'translate(' + availableWidth + ',0)' - # Main Chart Component(s) - achievementbar.width(availableWidth).height availableHeight - barsWrap = g.select('.nv-barsWrap').datum(data.filter((d) -> - !d.disabled - )) - barsWrap.transition().call achievementbar - defsEnter.append('clipPath').attr('id', 'nv-x-label-clip-' + achievementbar.id()).append 'rect' - g.select('#nv-x-label-clip-' + achievementbar.id() + ' rect').attr('width', x.rangeBand() * (if staggerLabels then 2 else 1)).attr('height', 16).attr 'x', -x.rangeBand() / (if staggerLabels then 1 else 2) - # Setup Axes - if showXAxis - xAxis.scale(x)._ticks(nv.utils.calcTicksX(availableWidth / 100, data)).tickSize -availableHeight, 0 - g.select('.nv-x.nv-axis').attr 'transform', 'translate(0,' + (y.range()[0] + (if achievementbar.showValues() and y.domain()[0] < 0 then 16 else 0)) + ')' - g.select('.nv-x.nv-axis').call xAxis - xTicks = g.select('.nv-x.nv-axis').selectAll('g') - if staggerLabels - xTicks.selectAll('text').attr 'transform', (d, i, j) -> - 'translate(0,' + (if j % 2 == 0 then '5' else '17') + ')' - if rotateLabels - xTicks.selectAll('.tick text').attr('transform', 'rotate(' + rotateLabels + ' 0,0)').style 'text-anchor', if rotateLabels > 0 then 'start' else 'end' - if wrapLabels - g.selectAll('.tick text').call nv.utils.wrapTicks, chart.xAxis.rangeBand() - if showYAxis - yAxis.scale(y)._ticks(nv.utils.calcTicksY(availableHeight / 36, data)).tickSize -availableWidth, 0 - g.select('.nv-y.nv-axis').call yAxis - # Zero line - g.select('.nv-zeroLine line').attr('x1', 0).attr('x2', if rightAlignYAxis then -availableWidth else availableWidth).attr('y1', y(0)).attr 'y2', y(0) - return - renderWatch.renderEnd 'achievementBar chart immediate' - chart - - 'use strict' - #============================================================ - # Public Variables with Default Settings - #------------------------------------------------------------ - achievementbar = nv.models.achievementBar() - xAxis = nv.models.axis() - yAxis = nv.models.axis() - legend = nv.models.legend() - tooltip = nv.models.tooltip() - margin = - top: 15 - right: 10 - bottom: 50 - left: 60 - width = null - height = null - color = nv.utils.getColor() - showLegend = false - showXAxis = true - showYAxis = true - rightAlignYAxis = false - staggerLabels = false - wrapLabels = false - rotateLabels = 0 - x = undefined - y = undefined - noData = null - dispatch = d3.dispatch('beforeUpdate', 'renderEnd') - duration = 250 - xAxis.orient('bottom').showMaxMin(false).tickFormat (d) -> - d - yAxis.orient(if rightAlignYAxis then 'right' else 'left').tickFormat d3.format(',.1f') - tooltip.duration(0).headerEnabled(false).keyFormatter (d, i) -> - xAxis.tickFormat() d, i - #============================================================ - # Private Variables - #------------------------------------------------------------ - renderWatch = nv.utils.renderWatch(dispatch, duration) - #============================================================ - # Event Handling/Dispatching (out of chart's scope) - #------------------------------------------------------------ - achievementbar.dispatch.on 'elementMouseover.tooltip', (evt) -> - key = chart.x()(evt.data) - unless key? - key = "#{evt.data} task range" - else - key = "Your progress with #{key}" - evt['series'] = - key: key - # value: chart.y()(evt.data) - color: evt.color - tooltip.data(evt).hidden false - return - achievementbar.dispatch.on 'elementMouseout.tooltip', (evt) -> - tooltip.hidden true - return - achievementbar.dispatch.on 'elementMousemove.tooltip', (evt) -> - tooltip() - return - #============================================================ - # Expose Public Variables - #------------------------------------------------------------ - chart.dispatch = dispatch - chart.achievementbar = achievementbar - chart.legend = legend - chart.xAxis = xAxis - chart.yAxis = yAxis - chart.tooltip = tooltip - chart.options = nv.utils.optionsFunc.bind(chart) - chart._options = Object.create({}, - width: - get: -> - width - set: (_) -> - width = _ - return - height: - get: -> - height - set: (_) -> - height = _ - return - showLegend: - get: -> - showLegend - set: (_) -> - showLegend = _ - return - staggerLabels: - get: -> - staggerLabels - set: (_) -> - staggerLabels = _ - return - rotateLabels: - get: -> - rotateLabels - set: (_) -> - rotateLabels = _ - return - wrapLabels: - get: -> - wrapLabels - set: (_) -> - wrapLabels = ! !_ - return - showXAxis: - get: -> - showXAxis - set: (_) -> - showXAxis = _ - return - showYAxis: - get: -> - showYAxis - set: (_) -> - showYAxis = _ - return - noData: - get: -> - noData - set: (_) -> - noData = _ - return - margin: - get: -> - margin - set: (_) -> - margin.top = if _.top != undefined then _.top else margin.top - margin.right = if _.right != undefined then _.right else margin.right - margin.bottom = if _.bottom != undefined then _.bottom else margin.bottom - margin.left = if _.left != undefined then _.left else margin.left - return - duration: - get: -> - duration - set: (_) -> - duration = _ - renderWatch.reset duration - achievementbar.duration duration - xAxis.duration duration - yAxis.duration duration - return - color: - get: -> - color - set: (_) -> - color = nv.utils.getColor(_) - achievementbar.color color - legend.color color - return - rightAlignYAxis: - get: -> - rightAlignYAxis - set: (_) -> - rightAlignYAxis = _ - yAxis.orient if _ then 'right' else 'left' - return - ) - nv.utils.inheritOptions chart, achievementbar - nv.utils.initOptions chart - chart - - - # - # Get the data and options for the chart... - # - targets = outcomeService.calculateTargets($scope.unit, $scope.unit, $scope.unit.taskStatusFactor) - currentProgress = outcomeService.calculateProgress($scope.unit, $scope.project) - - achievementData = { - key: "Learning Achievement" - values: [] - } - - max = 0 - - _.each $scope.unit.ilos, (ilo) -> - iloTargets = { } - iloTargets[0] = { offset: 0, height: targets[ilo.id][0], color: gradeService.gradeColors.P } - iloTargets[1] = { offset: iloTargets[0].offset + iloTargets[0].height, height: targets[ilo.id][1], color: gradeService.gradeColors.C } - iloTargets[2] = { offset: iloTargets[1].offset + iloTargets[1].height, height: targets[ilo.id][2], color: gradeService.gradeColors.D } - iloTargets[3] = { offset: iloTargets[2].offset + iloTargets[2].height, height: targets[ilo.id][3], color: gradeService.gradeColors.HD } - - if iloTargets[3].offset + iloTargets[3].height > max - max = iloTargets[3].offset + iloTargets[3].height - - achievementData.values.push { - label: $sce.getTrustedHtml(ilo.name) - value: currentProgress[0][ilo.id] # 0 = staff value - targets: iloTargets - } - - [$scope.options, $scope.config] = Visualisation 'achievementBarChart', 'ILO Achievement Bar Chart', { - height: 600 - duration: 500 - yDomain: [0, max] - showValues: false - showYAxis: false - showLegend: false - x: (d) -> d.label - y: (d) -> d.value - color: (d) -> '#373737' - }, {} - - $scope.data = [ achievementData ] diff --git a/src/app/visualisations/alignment-bar-chart.coffee b/src/app/visualisations/alignment-bar-chart.coffee deleted file mode 100644 index b137cb1dbe..0000000000 --- a/src/app/visualisations/alignment-bar-chart.coffee +++ /dev/null @@ -1,41 +0,0 @@ -angular.module('doubtfire.visualisations.alignment-bar-chart', []) -.directive 'alignmentBarChart', -> - replace: true - restrict: 'E' - templateUrl: 'visualisations/visualisation.tpl.html' - scope: - project: '=' - unit: '=' - source: '=' - taskStatusFactor: '=' - controller: ($scope, Visualisation, gradeService, outcomeService) -> - xFn = (d) -> d.label - yFn = (d) -> d.value - - [$scope.options, $scope.config] = Visualisation 'multiBarChart', 'ILO Alignment Bar Chart', { - clipEdge: yes - stacked: no - height: 200 - duration: 500 - color: (d) -> - gradeService.gradeColors[gradeService.gradeAcronyms[d.key]] - x: xFn - y: yFn - forceY: 0 - showYAxis: no - }, {} - - $scope.data = [] - - $scope.calculateAlignmentVisualisation = (source, taskStatusFactor) -> - unit = $scope.unit - _.extend $scope.data, outcomeService.targetsByGrade($scope.unit, source) - - if $scope.api? - $scope.api.update() - - $scope.calculateAlignmentVisualisation($scope.source, $scope.taskStatusFactor) - - $scope.$on('UpdateAlignmentChart', -> - $scope.calculateAlignmentVisualisation($scope.source, $scope.taskStatusFactor) - ) diff --git a/src/app/visualisations/alignment-bullet-chart.coffee b/src/app/visualisations/alignment-bullet-chart.coffee deleted file mode 100644 index 9ef1f3f9e1..0000000000 --- a/src/app/visualisations/alignment-bullet-chart.coffee +++ /dev/null @@ -1,591 +0,0 @@ -angular.module('doubtfire.visualisations.alignment-bullet-chart', []) -.directive 'alignmentBulletChart', -> - replace: true - restrict: 'E' - templateUrl: 'visualisations/visualisation.tpl.html' - scope: - project: '=' - unit: '=' - ilo: '=' - targets: '=' - currentProgress: '=' - classStats: '=' - showLegend: '=?' - - controller: ($scope, gradeService, Visualisation, $sce) -> - $scope.showLegend = if $scope.showLegend? then $scope.showLegend else true - unless nv.models.iloBullet? - # Chart design based on the recommendations of Stephen Few. Implementation - # based on the work of Clint Ivy, Jamie Love, and Jason Davies. - # http://projects.instantcognition.com/protovis/bulletchart/ - nv.models.iloBullet = -> - chart = (selection) -> - selection.each (d, i) -> - availableWidth = width - (if $scope.legend then margin.left else 0) - (if $scope.legend then margin.right else 0) - availableHeight = height - (margin.top) - (margin.bottom) - container = d3.select(this) - nv.utils.initSVG container - rangez = ranges.call(this, d, i).slice().reverse() - markerz = markers.call(this, d, i).slice().sort(d3.descending) - measurez = measures.call(this, d, i) - rangeLabelz = rangeLabels.call(this, d, i).slice().reverse() - markerLabelz = markerLabels.call(this, d, i).slice() - measureLabelz = measureLabels.call(this, d, i).slice() - - # Setup Scales - # Compute the new x-scale. - x1 = d3.scale.linear().domain(d3.extent(d3.merge([ - forceX - rangez - ]))).range(if reverse then [ - availableWidth - 0 - ] else [ - 0 - availableWidth - ]) - # Retrieve the old x-scale, if this is an update. - x0 = @__chart__ or d3.scale.linear().domain([ - 0 - Infinity - ]).range(x1.range()) - - # Stash the new scale. - @__chart__ = x1 - - # Get the range values - rangeHD = rangez[0] - rangeD = rangez[1] - rangeC = rangez[2] - rangeP = rangez[3] - - # Setup containers and skeleton of chart - wrap = container.selectAll('g.nv-wrap.nv-bullet').data([ d ]) - wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bullet') - gEnter = wrapEnter.append('g') - g = wrap.select('g') - gEnter.append('rect').attr('class', 'nv-range nv-rangeHD').style('fill-opacity', '0.2').style('fill', gradeService.gradeColors.HD) - gEnter.append('rect').attr('class', 'nv-range nv-rangeD' ).style('fill-opacity', '0.2').style('fill', gradeService.gradeColors.D) - gEnter.append('rect').attr('class', 'nv-range nv-rangeC' ).style('fill-opacity', '0.2').style('fill', gradeService.gradeColors.C) - gEnter.append('rect').attr('class', 'nv-range nv-rangeP' ).style('fill-opacity', '0.2').style('fill', gradeService.gradeColors.P) - gEnter.append('rect').attr 'class', 'nv-measure' - gEnter.append('rect').attr('class', 'nv-median').style('fill-opacity', '1.0').style('fill','#ffffff') - wrap.attr 'transform', 'translate(' + margin.left + ',' + margin.top + ')' - - w0 = (d) -> - Math.abs x0(d) - x0(0) - - w1 = (d) -> - Math.abs x1(d) - x1(0) - - xp0 = (d) -> - if d > 0 then x0(d) else x0(0) - - xp1 = (d) -> - if d > 0 then x1(d) else x1(0) - - g.select('rect.nv-rangeHD') - .attr('height', availableHeight) - .attr('width', w1(rangeHD - rangeD) ) - .attr('x', xp1(rangeD)) - .datum rangeHD - - g.select('rect.nv-rangeD') - .attr('height', availableHeight) - .attr('width', w1(rangeD - rangeC)) - .attr('x', xp1(rangeC)) - .datum rangeD - - g.select('rect.nv-rangeC') - .attr('height', availableHeight) - .attr('width', w1(rangeC - rangeP)) - .attr('x', xp1(rangeP)) - .datum rangeC - - g.select('rect.nv-rangeP') - .attr('height', availableHeight) - .attr('width', w1(rangeP)) - .attr('x', xp1(0)) - .datum rangeP - - if measurez? - g.select('rect.nv-median') - .style('fill', "#373737") - .style('fill-opacity',0.6) - .attr('height', availableHeight) - .attr('y', 0) - .attr('width', 2) - .attr('x', xp1(measurez.median)) - .on('mouseover', -> - dispatch.elementMouseover - value: measurez.median - label: 'The average student is here' - color: d3.select(this).style('fill') - return) - .on('mousemove', -> - dispatch.elementMousemove - value: measurez.median - label: 'Class Median' - color: d3.select(this).style('fill') - return) - .on 'mouseout', -> - dispatch.elementMouseout - value: measurez.median - label: 'Class Median' - color: d3.select(this).style('fill') - return - - g.select('rect.nv-measure') - .style('fill', "#373737") - .style('fill-opacity',0.6) - .attr('height', availableHeight * 2 / 3) - .attr('y', availableHeight / 6) - .attr('width', xp1(measurez.upper) - xp1(measurez.lower)) - .attr('x', xp1(measurez.lower)) - .on('mouseover', -> - dispatch.elementMouseover - value: measurez[0] - label: measureLabelz[0] or 'Current' - color: d3.select(this).style('fill') - return) - .on('mousemove', -> - dispatch.elementMousemove - value: measurez[0] - label: measureLabelz[0] or 'Current' - color: d3.select(this).style('fill') - return) - .on 'mouseout', -> - dispatch.elementMouseout - value: measurez[0] - label: measureLabelz[0] or 'Current' - color: d3.select(this).style('fill') - return - - h3 = availableHeight / 6 - markerData = markerz.map((marker, index) -> - { - value: marker - label: markerLabelz[index] - } - ) - gEnter.selectAll('path.nv-markerTriangle') - .data(markerData) - .enter() - .append('path') - .attr('class', 'nv-markerTriangle') - .attr('d', (d,i) -> - if i % 2 == 0 - 'M0,' + h3 + 'L' + h3 + ',' + -h3 + ' ' + -h3 + ',' + -h3 + 'Z' - else - 'M0,' + -h3 + 'L' + -h3 + ',0L0,' + h3 + 'L' + h3 + ',0Z' - ) - .on('mouseover', (d) -> - dispatch.elementMouseover( - value: d.value - label: d.label or 'Previous' - color: d3.select(this).style('fill') - pos: [ - x1(d.value) - availableHeight / 2 - ]) - return ) - .on('mousemove', (d) -> - dispatch.elementMousemove( - value: d.value - label: d.label or 'Previous' - color: d3.select(this).style('fill') ) - return ) - .on 'mouseout', (d, i) -> - dispatch.elementMouseout( - value: d.value - label: d.label or 'Previous' - color: d3.select(this).style('fill')) - return - - g.selectAll('path.nv-markerTriangle') - .data(markerData).attr 'transform', (d) -> - 'translate(' + x1(d.value) + ',' + availableHeight / 2 + ')' - - wrap.selectAll('.nv-range').on('mouseover', (d, i) -> - label = rangeLabelz[i] or (if !i then 'Maximum' else if i == 1 then 'Mean' else 'Minimum') - dispatch.elementMouseover - value: d - label: label - color: d3.select(this).style('fill') - return - ).on('mousemove', -> - dispatch.elementMousemove - value: measurez[0] - label: measureLabelz[0] or 'Previous' - color: d3.select(this).style('fill') - return - ).on 'mouseout', (d, i) -> - label = rangeLabelz[i] or (if !i then 'Maximum' else if i == 1 then 'Mean' else 'Minimum') - dispatch.elementMouseout - value: d - label: label - color: d3.select(this).style('fill') - return - return - chart - - 'use strict' - #============================================================ - # Public Variables with Default Settings - #------------------------------------------------------------ - margin = - top: 0 - right: 0 - bottom: 0 - left: 0 - orient = 'left' - reverse = false - - ranges = (d) -> - d.ranges - - markers = (d) -> - if d.markers then d.markers else [] - - measures = (d) -> - d.measures - - rangeLabels = (d) -> - if d.rangeLabels then d.rangeLabels else [] - - markerLabels = (d) -> - if d.markerLabels then d.markerLabels else [] - - measureLabels = (d) -> - if d.measureLabels then d.measureLabels else [] - - forceX = [ 0 ] - width = 380 - height = 30 - container = null - tickFormat = null - color = nv.utils.getColor([ '#1f77b4' ]) - dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove') - #============================================================ - # Expose Public Variables - #------------------------------------------------------------ - chart.dispatch = dispatch - chart.options = nv.utils.optionsFunc.bind(chart) - chart._options = Object.create({}, - ranges: - get: -> - ranges - set: (_) -> - ranges = _ - return - markers: - get: -> - markers - set: (_) -> - markers = _ - return - measures: - get: -> - measures - set: (_) -> - measures = _ - return - forceX: - get: -> - forceX - set: (_) -> - forceX = _ - return - width: - get: -> - width - set: (_) -> - width = _ - return - height: - get: -> - height - set: (_) -> - height = _ - return - tickFormat: - get: -> - tickFormat - set: (_) -> - tickFormat = _ - return - margin: - get: -> - margin - set: (_) -> - margin.top = if _.top != undefined then _.top else margin.top - margin.right = if _.right != undefined then _.right else margin.right - margin.bottom = if _.bottom != undefined then _.bottom else margin.bottom - margin.left = if _.left != undefined then _.left else margin.left - return - orient: - get: -> - orient - set: (_) -> - # left, right, top, bottom - orient = _ - reverse = orient == 'right' or orient == 'bottom' - return - color: - get: -> - color - set: (_) -> - color = nv.utils.getColor(_) - return - ) - nv.utils.initOptions chart - chart - - # --- - # generated by js2coffee 2.1.0 - - - # Chart design based on NVD3 bullet chart. - nv.models.iloChart = -> - #============================================================ - # Public Variables with Default Settings - #------------------------------------------------------------ - - bullet = nv.models.iloBullet() - tooltip = nv.models.tooltip() - - # TODO: (@macite) top & bottom - orient = 'left' - reverse = false - margin = if $scope.legend then { top: 5, right: 40, bottom: 5, left: 120 } else { top: 5, right: 5, bottom: 5, left: 5 } - - ranges = (d) -> d.ranges - rangeLabels = (d) -> d.rangeLabels - markers = (d) -> if d.markers then d.markers else [] - measures = (d) -> d.measures - - width = null - height = 55 - tickFormat = null - ticks = null - noData = null - dispatch = d3.dispatch - - tooltip - .duration(0) - .headerEnabled(false) - - chart = (selection) -> - selection.each (d, i) -> - container = d3.select(this) - nv.utils.initSVG(container) - - availableWidth = nv.utils.availableWidth(width, container, margin) - availableHeight = height - margin.top - margin.bottom - that = this - - chart.update = -> chart(selection) - chart.container = this - - # Display No Data message if there's nothing to show. - if (!d || !ranges.call(this, d, i)) - nv.utils.noData(chart, container) - return chart - else - container.selectAll('.nv-noData').remove() - - rangez = ranges.call(this, d, i).slice().sort(d3.descending) - markerz = markers.call(this, d, i).slice().sort(d3.descending) - measurez = measures.call(this, d, i) - - # Setup containers and skeleton of chart - wrap = container.selectAll('g.nv-wrap.nv-bulletChart').data([d]) - wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bulletChart') - gEnter = wrapEnter.append('g') - g = wrap.select('g') - - gEnter.append('g').attr('class', 'nv-bulletWrap') - gEnter.append('g').attr('class', 'nv-titles') if $scope.legend - - wrap.attr('transform', 'translate(' + (if $scope.legend then margin.left else 10) + ',' + margin.top + ')') - - # Compute the new x-scale. - # TODO: (@macite) need to allow forceX and forceY, and xDomain, yDomain - x1 = d3.scale.linear() - .domain([0, Math.max(rangez[0], (markerz[0] || 0), measurez[0])]) - .range(if reverse then [availableWidth, 0] else [0, availableWidth]) - - # Retrieve the old x-scale, if this is an update. - x0 = this.__chart__ || d3.scale.linear() - .domain([0, Infinity]) - .range(x1.range()) - - # Stash the new scale. - this.__chart__ = x1 - - # TODO: (@macite) could optimize by precalculating x0(0) and x1(0) - w0 = (d) -> Math.abs(x0(d) - x0(0)) - w1 = (d) -> Math.abs(x1(d) - x1(0)) - - if $scope.legend - title = gEnter.select('.nv-titles').append('g') - .attr('text-anchor', 'end') - .attr('transform', 'translate(-6,' + (height - margin.top - margin.bottom) / 2 + ')') - - title.append('text') - .attr('class', 'nv-title') - .text((d) -> d.title ) - - title.append('text') - .attr('class', 'nv-subtitle') - .attr('dy', '1em') - .text( (d) -> d.subtitle ) - - bullet - .width(availableWidth) - .height(availableHeight) - - bulletWrap = g.select('.nv-bulletWrap') - d3.transition(bulletWrap).call(bullet) - - # # Compute the tick format. - # format = tickFormat || x1.tickFormat( availableWidth / 100 ) - - # # Update the tick groups. - # tick = g.selectAll('g.nv-tick') - # .data x1.ticks( if ticks then ticks else (availableWidth / 50) ), (d) -> - # this.textContent || format(d) - - # # Initialize the ticks with the old scale, x0. - # tickEnter = tick.enter().append('g') - # .attr('class', 'nv-tick') - # .attr('transform', (d) -> 'translate(' + x0(d) + ',0)' ) - # .style('opacity', 1e-6) - - # tickEnter.append('line') - # .attr('y1', availableHeight) - # .attr('y2', availableHeight * 7 / 6) - - # tickEnter.append('text') - # .attr('text-anchor', 'middle') - # .attr('dy', '1em') - # .attr('y', availableHeight * 7 / 6) - # .text(format) - - # # Transition the updating ticks to the new scale, x1. - # tickUpdate = d3.transition(tick) - # .attr('transform', (d) -> 'translate(' + x1(d) + ',0)') - # .style('opacity', 1) - - # tickUpdate.select('line') - # .attr('y1', availableHeight) - # .attr('y2', availableHeight * 7 / 6) - - # tickUpdate.select('text') - # .attr('y', availableHeight * 7 / 6) - - # #Transition the exiting ticks to the new scale, x1. - # d3.transition(tick.exit()) - # .attr('transform', (d) -> 'translate(' + x1(d) + ',0)' ) - # .style('opacity', 1e-6 ) - # .remove( ) - # end selection each - - d3.timer.flush() - chart - - #============================================================ - # Event Handling/Dispatching (out of chart's scope) - #------------------------------------------------------------ - bullet.dispatch.on 'elementMouseover.tooltip', (evt) -> - evt['series'] = { - key: evt.label - # value: evt.value - color: evt.color - } - tooltip.data(evt).hidden(false) - - bullet.dispatch.on 'elementMouseout.tooltip', (evt) -> - tooltip.hidden(true) - - bullet.dispatch.on 'elementMousemove.tooltip', (evt) -> - tooltip() - - #============================================================ - # Expose Public Variables - #------------------------------------------------------------ - - chart.bullet = bullet - chart.dispatch = dispatch - chart.tooltip = tooltip - - chart.options = nv.utils.optionsFunc.bind(chart) - - chart._options = Object.create({}, { - # simple options, just get/set the necessary values - ranges: {get: (-> ranges), set: ((_)-> ranges=_) }, # ranges (bad, satisfactory, good) - rangeLabels: {get: (-> rangeLabels), set: ((_)-> rangeLabels=_) }, # ranges (bad, satisfactory, good) - markers: {get: (-> markers), set: ((_) -> markers=_) }, # markers (previous, goal) - measures: {get: (-> measures), set: ((_) -> measures=_) }, # measures (actual, forecast) - width: {get: (-> width), set: ((_) -> width=_) }, - height: {get: (-> height), set: ((_) -> height=_) }, - tickFormat: {get: (-> tickFormat), set: ((_) -> tickFormat=_) }, - ticks: {get: (-> ticks), set: ((_) -> ticks=_) }, - noData: {get: (-> noData), set: ((_) -> noData=_) }, - - # options that require extra logic in the setter - margin: {get: (-> margin), set: (_) -> - margin.top = if _.top? then _.top else margin.top - margin.right = if _.right? then _.right else margin.right - margin.bottom = if _.bottom? then _.bottom else margin.bottom - margin.left = if _.left? then _.left else margin.left - }, - orient: {get: (-> orient), set: (_) -> # left, right, top, bottom - orient = _ - reverse = orient == 'right' || orient == 'bottom' - } - }) - - nv.utils.inheritOptions(chart, bullet) - nv.utils.initOptions(chart) - - chart - - [$scope.options, $scope.config] = Visualisation 'iloChart', 'ILO Alignment Bullet Chart', { - height: 60 - duration: 500 - }, {} - - targetP = $scope.targets[$scope.ilo.id][0] - targetC = targetP + $scope.targets[$scope.ilo.id][1] - targetD = targetC + $scope.targets[$scope.ilo.id][2] - targetHD = targetD + $scope.targets[$scope.ilo.id][3] - - $scope.data = { - "title": $sce.getTrustedHtml($scope.ilo.abbreviation), #Label the bullet chart - "subtitle": $sce.getTrustedHtml($scope.ilo.name), #sub-label for bullet chart - "ranges":[targetP,targetC,targetD,targetHD], #Minimum, mean and maximum values. - "rangeLabels":['Pass','Credit','Distinction','High Distinction'], #Minimum, mean and maximum values. - "measures": {}, #Value representing current measurement (the thick blue line in the example) - "measureLabels": ['Most of the class are in this area'] - "markers":[] #Place a marker on the chart (the white triangle marker) - "markerLabels": ['Your Suggested Progress - Staff Suggestion', 'Your Current Progress - Self Reflection'] - } - - if $scope.classStats? && $scope.classStats.title? - $scope.data.measureLabels[0] = $scope.classStats.title - - updateProgress = -> - if $scope.currentProgress? - _.each $scope.currentProgress, (d, i) -> - $scope.data.markers[i] = $scope.currentProgress[i][$scope.ilo.id] - if $scope.currentProgress[i].title? - $scope.data.markerLabels[i] = $scope.currentProgress[i].title - - $scope.data.measures = if $scope.classStats? && $scope.classStats[$scope.ilo.id]? then $scope.classStats[$scope.ilo.id] else 0 - - updateProgress() - - $scope.$on('ProgressUpdated', -> - updateProgress() - ) diff --git a/src/app/visualisations/student-task-status-pie-chart.coffee b/src/app/visualisations/student-task-status-pie-chart.coffee deleted file mode 100644 index 12a8ce47ad..0000000000 --- a/src/app/visualisations/student-task-status-pie-chart.coffee +++ /dev/null @@ -1,41 +0,0 @@ -angular.module('doubtfire.visualisations.student-task-status-pie-chart', []) -.directive 'studentTaskStatusPieChart', -> - replace: true - restrict: 'E' - templateUrl: 'visualisations/visualisation.tpl.html' - scope: - project: '=' - updateData: '=?' - controller: ($scope, newTaskService, Visualisation) -> - colors = newTaskService.statusColors - $scope.data = [] - - $scope.updateData = -> - $scope.data.length = 0 - newTaskService.statusLabels.forEach( (label, key) -> - count = $scope.project.tasksByStatus(key).length - $scope.data.push { key: label, y: count, statusKey: key } - ) - - if $scope.api - $scope.api.update() - - $scope.$on 'TaskStatusUpdated', $scope.updateData - - $scope.updateData() - - [$scope.options, $scope.config] = Visualisation 'pieChart', 'Student Task Status Pie Chart', { - color: (d, i) -> - colors.get(d.statusKey) - x: (d) -> d.key - y: (d) -> d.y - showLabels: no - tooltip: - valueFormatter: (d) -> - fixed = d.toFixed() - pct = Math.round((d / $scope.project.activeTasks().length) * 100) - task = if fixed is "1" then "task" else "tasks" - "#{fixed} #{task} (#{pct}%)" - keyFormatter: (d) -> - d - }, {} From 504a26e9c003880bee711d61287b111773b0c09a Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 28 Nov 2025 22:50:13 +1100 Subject: [PATCH 0758/1531] chore: remove unused visualisations --- src/app/doubtfire-angularjs.module.ts | 6 ------ src/app/visualisations/visualisations.coffee | 6 ------ 2 files changed, 12 deletions(-) diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 7fdba35560..2de407b9fe 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -32,16 +32,10 @@ import 'angular-md5/angular-md5.js'; import 'build/templates-app.js'; import 'build/assets/wav-worker.js'; import 'build/src/app/visualisations/summary-task-status-scatter.js'; -import 'build/src/app/visualisations/student-task-status-pie-chart.js'; -import 'build/src/app/visualisations/progress-burndown-chart.js'; import 'build/src/app/visualisations/target-grade-pie-chart.js'; import 'build/src/app/visualisations/task-status-pie-chart.js'; import 'build/src/app/visualisations/task-completion-box-plot.js'; import 'build/src/app/visualisations/visualisations.js'; -import 'build/src/app/visualisations/alignment-bullet-chart.js'; -import 'build/src/app/visualisations/achievement-custom-bar-chart.js'; -import 'build/src/app/visualisations/alignment-bar-chart.js'; -import 'build/src/app/visualisations/achievement-box-plot.js'; import 'build/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.js'; import 'build/src/app/tasks/modals/modals.js'; import 'build/src/app/tasks/tasks.js'; diff --git a/src/app/visualisations/visualisations.coffee b/src/app/visualisations/visualisations.coffee index f7882be92e..2e90fd66d2 100644 --- a/src/app/visualisations/visualisations.coffee +++ b/src/app/visualisations/visualisations.coffee @@ -1,14 +1,8 @@ angular.module('doubtfire.visualisations', [ 'doubtfire.visualisations.summary-task-status-scatter' - 'doubtfire.visualisations.progress-burndown-chart' - 'doubtfire.visualisations.alignment-bar-chart' - 'doubtfire.visualisations.alignment-bullet-chart' - 'doubtfire.visualisations.student-task-status-pie-chart' 'doubtfire.visualisations.task-status-pie-chart' 'doubtfire.visualisations.target-grade-pie-chart' 'doubtfire.visualisations.task-completion-box-plot' - 'doubtfire.visualisations.achievement-box-plot' - 'doubtfire.visualisations.achievement-custom-bar-chart' ]) .factory('Visualisation', ($interval, analyticsService) -> From 730ffd0c3f79a5ad42c0c59c2f2c2a901ab0d702 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:50:42 +1100 Subject: [PATCH 0759/1531] feat: discussion prompts (#1042) * feat: init discussion prompts ui * refactor: improve tutor discussion ui * refactor: display discussion prompts in tutor discussion view * refactor: reword weight to priority --- src/app/api/models/discussion-prompt.ts | 59 +++++++ src/app/api/models/task-definition.ts | 5 + .../api/services/discussion-prompt.service.ts | 128 +++++++++++++++ .../api/services/task-definition.service.ts | 1 + src/app/common/footer/footer.component.html | 13 ++ src/app/common/footer/footer.component.ts | 4 + src/app/doubtfire-angular.module.ts | 9 + .../discussion-prompts-view.component.html | 11 ++ .../discussion-prompts-view.component.scss | 0 .../discussion-prompts-view.component.ts | 11 ++ .../task-dashboard.component.html | 7 + .../states/dashboard/selected-task.service.ts | 5 + .../discussion-prompts.component.html | 21 +++ .../discussion-prompts.component.scss | 0 .../discussion-prompts.component.ts | 50 ++++++ .../tutor-discussion.component.html | 15 +- .../tutor-discussion.component.ts | 7 + ...finition-discussion-prompts.component.html | 107 ++++++++++++ ...finition-discussion-prompts.component.scss | 0 ...definition-discussion-prompts.component.ts | 155 ++++++++++++++++++ .../task-definition-editor.component.html | 12 ++ 21 files changed, 614 insertions(+), 6 deletions(-) create mode 100644 src/app/api/models/discussion-prompt.ts create mode 100644 src/app/api/services/discussion-prompt.service.ts create mode 100644 src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html create mode 100644 src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.scss create mode 100644 src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts create mode 100644 src/app/projects/states/discussion-prompts/discussion-prompts.component.html create mode 100644 src/app/projects/states/discussion-prompts/discussion-prompts.component.scss create mode 100644 src/app/projects/states/discussion-prompts/discussion-prompts.component.ts create mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.html create mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.scss create mode 100644 src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts diff --git a/src/app/api/models/discussion-prompt.ts b/src/app/api/models/discussion-prompt.ts new file mode 100644 index 0000000000..e984847084 --- /dev/null +++ b/src/app/api/models/discussion-prompt.ts @@ -0,0 +1,59 @@ +import {Entity} from 'ngx-entity-service'; +import {AppInjector} from 'src/app/app-injector'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {DiscussionPromptService} from '../services/discussion-prompt.service'; +import {Project, TaskDefinition, Unit, User} from './doubtfire-model'; + +export class DiscussionPrompt extends Entity { + id: number; + unit: Unit; + taskDefinition: TaskDefinition; + project: Project | null; + createdBy: User; + content: string; + priority: number; + discussedAt: Date; + + public readonly PRIORITY = { + 1: 'Low', + 2: 'Medium', + 3: 'High', + } as const; + + constructor(data?: Project | TaskDefinition | Unit) { + super(); + if (data) { + if (data instanceof Project) { + this.project = data; + } else if (data instanceof TaskDefinition) { + this.taskDefinition = data; + } else if (data instanceof Unit) { + this.unit = data; + } + } else { + console.error('Failed to get project'); + } + } + + public get priorityLabel() { + return this.PRIORITY[this.priority] ?? this.priority; + } + + public delete() { + const discussionPromptService: DiscussionPromptService = + AppInjector.get(DiscussionPromptService); + discussionPromptService + .delete( + {task_definition_id: this.taskDefinition.id, id: this.id}, + {cache: this.taskDefinition.discussionPromptsCache}, + ) + .subscribe({ + next: (_response: object) => { + AppInjector.get(AlertService).success('Successfully deleted discussion note', 4000); + }, + error: (error: any) => { + AppInjector.get(AlertService).error(error?.message || error || 'Unknown error', 2000); + }, + }); + } +} diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index 814c7a9c53..d3aa2a4317 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -8,6 +8,7 @@ import {TaskDefinitionService} from '../services/task-definition.service'; import {Grade, GroupSet, LearningOutcome, Project, TutorialStream, Unit} from './doubtfire-model'; import {Task} from './doubtfire-model'; import {TaskPrerequisite} from './task-prerequisite'; +import {DiscussionPrompt} from './discussion-prompt'; export type UploadRequirement = { key: string; @@ -57,10 +58,14 @@ export class TaskDefinition extends Entity { assessInPortfolioOnly: boolean; useResourcesForJplagBaseCode: boolean; lockAssessmentsToTutorialStream: boolean; + discussionPromptsCount: number; public readonly taskPrerequisitesCache: EntityCache = new EntityCache(); + public readonly discussionPromptsCache: EntityCache = + new EntityCache(); + public readonly learningOutcomesCache: EntityCache = new EntityCache(); diff --git a/src/app/api/services/discussion-prompt.service.ts b/src/app/api/services/discussion-prompt.service.ts new file mode 100644 index 0000000000..c102fbcbf1 --- /dev/null +++ b/src/app/api/services/discussion-prompt.service.ts @@ -0,0 +1,128 @@ +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; +import { + Project, + ProjectService, + TaskDefinition, + Unit, + UserService, +} from 'src/app/api/models/doubtfire-model'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {DiscussionPrompt} from '../models/discussion-prompt'; + +@Injectable() +export class DiscussionPromptService extends CachedEntityService { + protected readonly endpointFormat = + 'task_definitions/:task_definition_id:/discussion_prompts/:id:'; + + protected readonly projectEndpointFormat = 'projects/:projectId:/discussion_prompts'; + protected readonly taskDefinitionProjectEndpointFormat = + 'projects/:projectId:/discussion_prompts'; + protected readonly taskDefinitionEndpointFormat = + 'task_definitions/:taskDefinitionId:/discussion_prompts'; + + constructor( + httpClient: HttpClient, + private userService: UserService, + private projectService: ProjectService, + ) { + super(httpClient, API_URL); + + this.mapping.addKeys( + 'id', + 'content', + 'priority', + { + keys: ['createdBy', 'created_by_id'], + toEntityFn: (data: object, key: string, prompt: DiscussionPrompt) => { + if (prompt.project) { + return prompt.project.unit.staff.find((s) => s.user.id === data['created_by_id']).user; + } else if (prompt.taskDefinition) { + return prompt.taskDefinition.unit.staff.find((s) => s.user.id === data['created_by_id']) + ?.user; + } else if (prompt.unit) { + return prompt.unit.staff.find((s) => s.user.id === data['created_by_id'])?.user; + } + }, + }, + { + keys: ['taskDefinition', 'task_definition_id'], + toEntityFn: (data: object, key: string, entity: DiscussionPrompt) => { + if (entity.project) { + return entity.project.unit.taskDef(data[key]); + } else if (entity.unit) { + return entity.unit.taskDef(data[key]); + } + return entity.taskDefinition; + }, + toJsonFn: (entity: DiscussionPrompt, key: string) => { + return entity.taskDefinition?.id; + }, + }, + ); + + this.mapping.addJsonKey('project', 'taskDefinition', 'unit', 'createdBy'); + } + + public createInstanceFrom( + _json: object, + other?: Project | Unit | TaskDefinition, + ): DiscussionPrompt { + return new DiscussionPrompt(other); + } + + // TODO: loadDiscussionPromptsForProject and overload for loadTaskDefinitionDiscussionPrompts() + + public loadDiscussionPromptsForPoject(project: Project) { + const options: RequestOptions = { + endpointFormat: this.taskDefinitionProjectEndpointFormat, + cacheBehaviourOnGet: 'cacheQuery', + constructorParams: project, + }; + + return super.fetchAll( + { + projectId: project?.id, + }, + options, + ); + } + + public loadDiscussionPrompts( + project: Project, + taskDefinition?: TaskDefinition, + useFetch: boolean = true, + ): Observable { + const options: RequestOptions = { + endpointFormat: project + ? taskDefinition + ? this.taskDefinitionProjectEndpointFormat + : this.projectEndpointFormat + : this.taskDefinitionEndpointFormat, + cache: taskDefinition.discussionPromptsCache, + sourceCache: taskDefinition.discussionPromptsCache, + // cacheBehaviourOnGet: 'cacheQuery', + constructorParams: project ? project : taskDefinition, + }; + + if (useFetch) { + return super.fetchAll( + { + projectId: project?.id, + taskDefinitionId: taskDefinition?.id, + }, + options, + ); + } else { + return super.query( + { + projectId: project?.id, + taskDefinitionId: taskDefinition?.id, + }, + options, + ); + } + } +} diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index cb36d3cc32..59664c143a 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -125,6 +125,7 @@ export class TaskDefinitionService extends CachedEntityService { 'maxQualityPts', 'overseerImageId', 'assessmentEnabled', + 'discussionPromptsCount', { keys: 'ilos', toEntityOp: (data: object, key: string, taskDefinition: TaskDefinition) => { diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index 8fd9e50a33..e7d84ac5e5 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -128,6 +128,19 @@
    } @if (selectedTask?.project) { + @if (selectedTask?.definition.discussionPromptsCount) { + + } +
    @if (selectedTask.project.staffNoteCount > 0) {
    diff --git a/src/app/common/footer/footer.component.ts b/src/app/common/footer/footer.component.ts index 7e38438381..295b8612ee 100644 --- a/src/app/common/footer/footer.component.ts +++ b/src/app/common/footer/footer.component.ts @@ -107,6 +107,10 @@ export class FooterComponent implements OnInit { this.selectedTaskService.showStaffNotes(); } + viewDiscussionPrompts() { + this.selectedTaskService.showDiscussionPrompts(); + } + getJplagReport() { if (!this.selectedTask?.definition) { return; diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 318c601b35..7938a4e274 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -297,6 +297,10 @@ import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/direc import {OverseerScriptEditorModalComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component'; import {CodeEditorModule} from '@ngstack/code-editor'; import {UploadGradesComponent} from './units/states/portfolios/upload-grades/upload-grades.component'; +import {DiscussionPromptService} from './api/services/discussion-prompt.service'; +import {DiscussionPromptsComponent} from './projects/states/discussion-prompts/discussion-prompts.component'; +import {TaskDefinitionDiscussionPromptsComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component'; +import {DiscussionPromptsViewComponent} from './projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -452,6 +456,10 @@ const MY_DATE_FORMAT = { AnalyticsTutorTimesComponent, PortfolioIncludedTasksComponent, OverseerScriptEditorModalComponent, + UploadGradesComponent, + DiscussionPromptsComponent, + TaskDefinitionDiscussionPromptsComponent, + DiscussionPromptsViewComponent, ], providers: [ // Services we provide @@ -541,6 +549,7 @@ const MY_DATE_FORMAT = { LtiService, TaskPrerequisiteService, MarkingSessionService, + DiscussionPromptService, ], imports: [ FlexLayoutModule, diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html new file mode 100644 index 0000000000..8cc634a7fd --- /dev/null +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html @@ -0,0 +1,11 @@ +
    +
    + comment +

    Discussion Prompts for {{ project?.student?.name }}

    +
    + + +
    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.scss b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts new file mode 100644 index 0000000000..6156a4b191 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts @@ -0,0 +1,11 @@ +import {Component, Input} from '@angular/core'; + +@Component({ + selector: 'f-discussion-prompts-view', + templateUrl: './discussion-prompts-view.component.html', + styleUrls: ['./discussion-prompts-view.component.scss'], +}) +export class DiscussionPromptsViewComponent { + @Input() project; + @Input() taskDefinition; +} diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html index 705ab5b6d3..df91328f92 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html @@ -19,6 +19,13 @@ + + + + diff --git a/src/app/projects/states/dashboard/selected-task.service.ts b/src/app/projects/states/dashboard/selected-task.service.ts index 31b5dd8716..204714694e 100644 --- a/src/app/projects/states/dashboard/selected-task.service.ts +++ b/src/app/projects/states/dashboard/selected-task.service.ts @@ -9,6 +9,7 @@ export enum DashboardViews { task, similarity, staff_notes, + discussion_prompts, } @Injectable({ @@ -66,6 +67,10 @@ export class SelectedTaskService { this.currentView$.next(DashboardViews.staff_notes); } + public showDiscussionPrompts() { + this.currentView$.next(DashboardViews.discussion_prompts); + } + public showSubmission() { if (!this.task$.value) return; this.currentPdfUrl$.next(this.task$.value.submissionUrl(false)); diff --git a/src/app/projects/states/discussion-prompts/discussion-prompts.component.html b/src/app/projects/states/discussion-prompts/discussion-prompts.component.html new file mode 100644 index 0000000000..5dcbbf84ff --- /dev/null +++ b/src/app/projects/states/discussion-prompts/discussion-prompts.component.html @@ -0,0 +1,21 @@ +
    + @for (prompt of discussionPrompts; track prompt) { + + +
    + {{ prompt.taskDefinition.abbreviation }} +
    +
    + {{ prompt.content }} +
    +
    + {{ prompt.priorityLabel }} +
    +
    +
    + } +
    diff --git a/src/app/projects/states/discussion-prompts/discussion-prompts.component.scss b/src/app/projects/states/discussion-prompts/discussion-prompts.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts b/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts new file mode 100644 index 0000000000..2e384498af --- /dev/null +++ b/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts @@ -0,0 +1,50 @@ +import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core'; +import {DiscussionPrompt} from 'src/app/api/models/discussion-prompt'; +import {Project, TaskDefinition, UserService} from 'src/app/api/models/doubtfire-model'; +import {StaffNote} from 'src/app/api/models/staff-note'; +import {DiscussionPromptService} from 'src/app/api/services/discussion-prompt.service'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-discussion-prompts', + templateUrl: './discussion-prompts.component.html', + styleUrl: './discussion-prompts.component.scss', +}) +export class DiscussionPromptsComponent implements OnInit { + @ViewChild('staffNotesContainer') staffNotesContainer!: ElementRef; + @ViewChild('staffNoteEditor', {static: false}) staffNoteEditor!: ElementRef; + + @Input() project: Project; + @Input() taskDefinition: TaskDefinition; + + loadingStaffNotes: boolean = true; + + noteText: string = ''; + + editingNote?: StaffNote; + editingNoteText?: string = ''; + + replyingToNote?: StaffNote; + + hoveredNoteId: number | null = null; + + discussionPrompts: DiscussionPrompt[] = []; + + constructor( + private userService: UserService, + private discussionPromptService: DiscussionPromptService, + private alertService: AlertService, + private confirmationModalService: ConfirmationModalService, + ) {} + ngOnInit(): void { + console.log('task def?', this.taskDefinition); + this.loadingStaffNotes = true; + this.discussionPromptService + .loadDiscussionPromptsForPoject(this.project) + .subscribe((prompts) => { + console.log(prompts); + this.discussionPrompts = prompts; + }); + } +} diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html index 89cf35865f..f38d42764b 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html @@ -79,7 +79,7 @@ -
    -

    {{ task.definition.name }}

    -
    +
    +

    {{ task.definition.name }}

    + {{ task.definition.abbreviation }} - {{ getTargetTradeString(task.definition.targetGrade) }} Task -
    +
    @if (task.hasGrade()) {
    @@ -215,7 +215,8 @@

    {{ task.definition.name }}

    - + + @if (footerTabView === TutorDiscussionTabView.SHOW_COMMENTS) { @@ -235,6 +236,8 @@

    {{ task.definition.name }}

    } @else if (footerTabView === TutorDiscussionTabView.SHOW_STAFF_NOTES) { + } @else if (footerTabView === TutorDiscussionTabView.SHOW_DISCUSSION_PROMPTS) { + } }
    diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts index 567988d53d..801482ec4d 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts @@ -23,6 +23,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; enum TutorDiscussionTabView { SHOW_COMMENTS, SHOW_STAFF_NOTES, + SHOW_DISCUSSION_PROMPTS, } @Component({ selector: 'f-tutor-discussion', @@ -88,6 +89,8 @@ export class TutorDiscussionComponent implements AfterViewInit { this.showComments(); } else if (event.index === 1) { this.showStaffNotes(); + } else if (event.index === 2) { + this.showDiscussionPrompts(); } } @@ -99,6 +102,10 @@ export class TutorDiscussionComponent implements AfterViewInit { this.footerTabView = TutorDiscussionTabView.SHOW_STAFF_NOTES; } + public showDiscussionPrompts() { + this.footerTabView = TutorDiscussionTabView.SHOW_DISCUSSION_PROMPTS; + } + public ngAfterViewInit(): void { this.authService.afterAuthCall((result) => { if (!result) { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.html new file mode 100644 index 0000000000..86d762974e --- /dev/null +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.html @@ -0,0 +1,107 @@ +
    +
    + + + + + + + + + + + + + + + + + + +
    Discussion Prompt + @if (!editing(prompt)) { + {{ prompt.content }} + } @else { + + Discussion Prompt + + + } + Priority + @if (!editing(prompt)) { + {{ prompt.priorityLabel }} + } @else { +
    + + Priority + + + High + Medium + Low + + +
    + } +
    Actions +
    + @if (editing(prompt)) { + + + } @else { + + + } +
    +
    + @if (!dataSource.data.length) { +
    No discussion prompts
    + } +
    + @if (!creatingNewDiscussionPrompt) { +
    + +
    + } + + @if (creatingNewDiscussionPrompt) { + + +
    + + Discussion Prompt + + + + Priority + + + High + Medium + Low + + +
    +
    + + +
    +
    +
    + } +
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.scss b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts new file mode 100644 index 0000000000..149682d55d --- /dev/null +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts @@ -0,0 +1,155 @@ +import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import {UntypedFormControl, Validators} from '@angular/forms'; +import {MatTableDataSource} from '@angular/material/table'; +import {Observable, Subscription} from 'rxjs'; +import {DiscussionPrompt} from 'src/app/api/models/discussion-prompt'; +import {Task} from 'src/app/api/models/task'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {TaskPrerequisite} from 'src/app/api/models/task-prerequisite'; +import {Unit} from 'src/app/api/models/unit'; +import {DiscussionPromptService} from 'src/app/api/services/discussion-prompt.service'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {TaskPrerequisiteService} from 'src/app/api/services/task-prerequisite.service'; +import {EntityFormComponent} from 'src/app/common/entity-form/entity-form.component'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-task-definition-discussion-prompts', + templateUrl: 'task-definition-discussion-prompts.component.html', + styleUrls: ['task-definition-discussion-prompts.component.scss'], +}) +export class TaskDefinitionDiscussionPromptsComponent + extends EntityFormComponent + implements OnInit, OnChanges +{ + @Input() taskDefinition: TaskDefinition; + @Input() staffView: boolean; + @Input() task: Task; + + displayedColumns: string[] = ['content', 'priority', 'actions']; + + private prereqSub?: Subscription; + + public dataSource = new MatTableDataSource(); + + creatingNewDiscussionPrompt: boolean = false; + + newDiscussionPromptContent: string; + newDiscussionPromptWeight: number = 2; + + constructor( + private taskDefinitionService: TaskDefinitionService, + private alertService: AlertService, + private taskPrerequisiteService: TaskPrerequisiteService, + private discussionPromptService: DiscussionPromptService, + ) { + super( + { + content: new UntypedFormControl('', [Validators.required]), + priority: new UntypedFormControl('', [Validators.required]), + }, + 'Discussion Prompt', + ); + } + public get unit(): Unit { + return this.taskDefinition?.unit; + } + + public get prerequisites(): Observable { + return this.taskDefinition.taskPrerequisitesCache.values; + } + + ngOnInit(): void { + this.prereqSub = this.taskDefinition.discussionPromptsCache.values.subscribe((values) => { + this.dataSource.data = values; + }); + } + + ngOnChanges(changes: SimpleChanges): void { + if ( + changes.taskDefinition && + changes.taskDefinition.previousValue?.id !== changes.taskDefinition.currentValue?.id + ) { + this.prereqSub?.unsubscribe(); + this.prereqSub = this.taskDefinition.discussionPromptsCache.values.subscribe((values) => { + this.dataSource.data = values; + }); + this.fetchDiscussionPrompts(); + } + } + + private fetchDiscussionPrompts() { + const taskDefinition = this.taskDefinition; + this.discussionPromptService.loadDiscussionPrompts(null, taskDefinition).subscribe({ + next: (data) => { + this.dataSource.data = data; + }, + error: (error) => { + this.alertService.error(`Failed to load discussion promnpts: ${error}`); + }, + }); + } + + public addNewPrompt() { + const content = this.newDiscussionPromptContent; + const priority = this.newDiscussionPromptWeight; + this.discussionPromptService + .create( + { + task_definition_id: this.taskDefinition.id, + content: content, + priority: priority, + }, + { + cache: this.taskDefinition.discussionPromptsCache, + constructorParams: this.taskDefinition, + }, + ) + .subscribe({ + next: (_result) => { + this.cancelNewDiscussionPrompt(); + this.prereqSub?.unsubscribe(); + this.prereqSub = this.taskDefinition.discussionPromptsCache.values.subscribe((values) => { + this.dataSource.data = values; + }); + this.alertService.success(`Succesfully created prompt`, 3000); + }, + error: (error) => { + this.alertService.error(`Failed to create prompt: ${error}`, 6000); + }, + }); + } + + public deletePrompt(prompt: DiscussionPrompt) { + prompt.delete(); + } + + createNewDiscussionPrompt() { + this.creatingNewDiscussionPrompt = true; + } + + cancelNewDiscussionPrompt() { + this.creatingNewDiscussionPrompt = false; + this.newDiscussionPromptContent = ''; + this.newDiscussionPromptWeight = 2; + } + + submit() { + this.discussionPromptService + .put({ + id: this.selected.id, + task_definition_id: this.taskDefinition.id, + content: this.selected.content, + priority: this.selected.priority, + }) + .subscribe({ + next: (_response) => { + this.cancelEdit(); + this.alertService.success('Successfully saved prompt', 3000); + }, + error: (error) => { + this.alertService.error(`Failed to update prompt: ${error}`, 6000); + }, + }); + } +} diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html index 7744269ca5..a13d096675 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html @@ -68,6 +68,18 @@

    Details for {{ taskDefinition.abbreviation }} - {{ taskDefinition.name }} + + Discussion Prompts +
    +

    + Discussion prompts for tutors to use when discussing student tasks in class +

    + + + +
    +
    + @if (overseerEnabled) { Task Assessment Automation From 2db24183d551559414d8e1c7eee4ecdaf032ccb6 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 1 Dec 2025 14:54:28 +1100 Subject: [PATCH 0760/1531] refactor: migrate project groups (#1056) * refactor: migrate project groups component * chore: ensure callback is not null * chore: update migration progress --- README.md | 2 +- src/app/doubtfire-angular.module.ts | 2 ++ src/app/doubtfire-angularjs.module.ts | 6 ++++++ .../group-member-list.component.ts | 2 +- .../projects/states/groups/groups.tpl.html | 19 +++++-------------- .../project-groups.component.html | 12 ++++++++++++ .../project-groups.component.scss | 5 +++++ .../project-groups.component.ts | 15 +++++++++++++++ 8 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 src/app/projects/states/groups/project-groups/project-groups.component.html create mode 100644 src/app/projects/states/groups/project-groups/project-groups.component.scss create mode 100644 src/app/projects/states/groups/project-groups/project-groups.component.ts diff --git a/README.md b/README.md index fc8827a0bd..fe61c8d20f 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.coffee - [ ] ./src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee - [ ] ./src/app/projects/states/feedback/feedback.coffee -- [ ] ./src/app/projects/states/groups/groups.coffee (-> "project-groups") +- [ ] ./src/app/projects/states/groups/groups.coffee (State only -> "project-groups") - [ ] ./src/app/projects/states/index/index.coffee - [ ] ./src/app/projects/states/portfolio/directives/directives.coffee - [ ] ./src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.coffee (Migrate this in 10.0.x) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 2ed284691b..634304b171 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -294,6 +294,7 @@ import {PortfoliosPortfolioViewComponent} from './units/states/portfolios/direct import {PortfoliosAssessmentComponent} from './units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component'; import {UnitGroupsComponent} from './units/states/groups/unit-groups/unit-groups.component'; import {RolloverComponent} from './units/states/rollover/rollover.component'; +import {ProjectGroupsComponent} from './projects/states/groups/project-groups/project-groups.component'; @NgModule({ // Components we declare @@ -436,6 +437,7 @@ import {RolloverComponent} from './units/states/rollover/rollover.component'; PortfoliosAssessmentComponent, UnitGroupsComponent, RolloverComponent, + ProjectGroupsComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 2de407b9fe..ddfe5a39c9 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -209,6 +209,7 @@ import {PortfolioWelcomeStepComponent} from './projects/states/portfolio/directi import {PortfolioLearningSummaryReportStepComponent} from './projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component'; import {PortfolioAddExtraFilesStepComponent} from './projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component'; import {UnitGroupsComponent} from './units/states/groups/unit-groups/unit-groups.component'; +import {ProjectGroupsComponent} from './projects/states/groups/project-groups/project-groups.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -550,3 +551,8 @@ DoubtfireAngularJSModule.directive( 'fUnitGroups', downgradeComponent({component: UnitGroupsComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fProjectGroups', + downgradeComponent({component: ProjectGroupsComponent}), +); diff --git a/src/app/groups/group-member-list/group-member-list.component.ts b/src/app/groups/group-member-list/group-member-list.component.ts index 3e71170de3..b83199407c 100644 --- a/src/app/groups/group-member-list/group-member-list.component.ts +++ b/src/app/groups/group-member-list/group-member-list.component.ts @@ -50,7 +50,7 @@ export class GroupMemberListComponent implements OnInit, OnChanges { this.selectedGroup.getMembers().subscribe({ next: (members) => { this.loading = false; - this.onMembersLoaded(); + this.onMembersLoaded?.(); this.canRemoveMembers = !!this.unitRole || (this.selectedGroup.groupSet.allowStudentsToManageGroups && !this.selectedGroup.locked); diff --git a/src/app/projects/states/groups/groups.tpl.html b/src/app/projects/states/groups/groups.tpl.html index 804d268d35..47114d023d 100644 --- a/src/app/projects/states/groups/groups.tpl.html +++ b/src/app/projects/states/groups/groups.tpl.html @@ -1,14 +1,5 @@ -
    - - -
    - -
    -
    - -

    No Group Work

    -
    -
    - There is no group work enabled for this unit. -
    -
    + diff --git a/src/app/projects/states/groups/project-groups/project-groups.component.html b/src/app/projects/states/groups/project-groups/project-groups.component.html new file mode 100644 index 0000000000..6468b85e39 --- /dev/null +++ b/src/app/projects/states/groups/project-groups/project-groups.component.html @@ -0,0 +1,12 @@ +
    + @if (unit.hasGroupwork()) { + + + } @else { +
    + groups +

    No Group Work

    +

    There is no group work enabled for this unit.

    +
    + } +
    diff --git a/src/app/projects/states/groups/project-groups/project-groups.component.scss b/src/app/projects/states/groups/project-groups/project-groups.component.scss new file mode 100644 index 0000000000..542e68a366 --- /dev/null +++ b/src/app/projects/states/groups/project-groups/project-groups.component.scss @@ -0,0 +1,5 @@ +.mat-icon { + font-size: 75px; + width: 75px; + height: 75px; +} diff --git a/src/app/projects/states/groups/project-groups/project-groups.component.ts b/src/app/projects/states/groups/project-groups/project-groups.component.ts new file mode 100644 index 0000000000..9969bd6ceb --- /dev/null +++ b/src/app/projects/states/groups/project-groups/project-groups.component.ts @@ -0,0 +1,15 @@ +import {Component, Input} from '@angular/core'; +import {GroupSet, Project} from 'src/app/api/models/doubtfire-model'; +import {Unit} from 'src/app/api/models/unit'; + +// This component is only displayed to students (projects) +@Component({ + selector: 'f-project-groups', + templateUrl: './project-groups.component.html', + styleUrl: './project-groups.component.scss', +}) +export class ProjectGroupsComponent { + @Input() unit: Unit; + @Input() project: Project; + @Input() selectedGroupSet: GroupSet; +} From ec5376255a0c69dc887a5508e80ca4f614291b48 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:41:57 +1100 Subject: [PATCH 0761/1531] refactor: migrate group member contribution assigner component (#1057) * feat: migrate group-member-contribution-assigner component * refactor: use mat table * refactor: add table sorting * chore: update migration progress * chore: avoid defaulting group * fix: check if overseer test submission * refactor: remove groups module * refactor: improve hover rating effect * refactor: use modern for-loop directive * chore: default sort by student name * refactor: ensure confrating is set - used in other logic for statistics * refactor: remove unused code * refactor: remove confrating * chore: allow nullable overstar property * chore: remove class --------- Co-authored-by: EkamBhullar --- README.md | 4 +- src/app/api/models/groups/group.ts | 33 ++-- src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 9 +- .../group-member-contribution-assigner.coffee | 74 --------- ...ember-contribution-assigner.component.html | 51 ++++++ ...ember-contribution-assigner.component.scss | 0 ...-member-contribution-assigner.component.ts | 157 ++++++++++++++++++ .../group-member-contribution-assigner.scss | 19 --- ...roup-member-contribution-assigner.tpl.html | 41 ----- src/app/groups/groups.coffee | 3 - .../upload-submission-modal.coffee | 2 +- .../upload-submission-modal.tpl.html | 12 +- 13 files changed, 240 insertions(+), 167 deletions(-) delete mode 100644 src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee create mode 100644 src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.html create mode 100644 src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.scss create mode 100644 src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.ts delete mode 100644 src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.scss delete mode 100644 src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html delete mode 100644 src/app/groups/groups.coffee diff --git a/README.md b/README.md index fe61c8d20f..37ecf811c2 100644 --- a/README.md +++ b/README.md @@ -177,6 +177,8 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/visualisations/achievement-custom-bar-chart.coffee (ILO Alignments removed) - [ ] ./src/app/visualisations/alignment-bar-chart.coffee (ILO Alignments removed) - [ ] ./src/app/visualisations/alignment-bullet-chart.coffee (ILO Alignments removed) +- [x] ./src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee +- [x] ./src/app/groups/groups.coffee ### TODO: @@ -200,8 +202,6 @@ Important: When completing a frontend migration, please update the below list re - [ ] ./src/app/errors/errors.coffee - [ ] ./src/app/errors/states/states.coffee - [ ] ./src/app/errors/states/timeout/timeout.coffee -- [ ] ./src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee -- [ ] ./src/app/groups/groups.coffee - [ ] ./src/app/projects/projects.coffee - [ ] ./src/app/projects/states/dashboard/dashboard.coffee - [ ] ./src/app/projects/states/dashboard/directives/directives.coffee diff --git a/src/app/api/models/groups/group.ts b/src/app/api/models/groups/group.ts index 5abbb9f0ff..fd00bdf0e4 100644 --- a/src/app/api/models/groups/group.ts +++ b/src/app/api/models/groups/group.ts @@ -6,6 +6,13 @@ import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {Unit, GroupSet, Project, Tutorial, ProjectService} from '../doubtfire-model'; import {AlertService} from 'src/app/common/services/alert.service'; +export interface MemberContribution { + project: Project; + rating: number; + percent: number; + overStar?: number | null; +} + export class Group extends Entity { public id: number; public name: string; @@ -152,23 +159,13 @@ export class Group extends Entity { } } - public contributionSum( - contrib: {project: Project; rating: number; confRating: number; percent: number}[], - member?: Project, - value?: number, - ): number { - return contrib.reduce( - ( - prevValue: number, - current: {project: Project; rating: number; confRating: number; percent: number}, - ) => { - if (current.project === member) { - return prevValue + value; - } else { - return prevValue + current.rating; - } - }, - 0, - ); + public contributionSum(contrib: MemberContribution[], member?: Project, value?: number): number { + return contrib.reduce((prevValue: number, current) => { + if (current.project === member) { + return prevValue + value; + } else { + return prevValue + current.rating; + } + }, 0); } } diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 634304b171..fa5708f4d9 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -264,6 +264,7 @@ import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; // import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; import {UnitStaffEditorComponent} from './units/states/edit/directives/unit-staff-editor/unit-staff-editor.component'; import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component'; +import {GroupMemberContributionAssignerComponent} from './groups/group-member-contribution-assigner/group-member-contribution-assigner.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -438,6 +439,7 @@ import {ProjectGroupsComponent} from './projects/states/groups/project-groups/pr UnitGroupsComponent, RolloverComponent, ProjectGroupsComponent, + GroupMemberContributionAssignerComponent, ], // Services we provide providers: [ diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index ddfe5a39c9..4855d04ad6 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -67,8 +67,6 @@ import 'build/src/app/projects/states/portfolio/directives/directives.js'; import 'build/src/app/projects/states/portfolio/portfolio.js'; import 'build/src/app/projects/states/index/index.js'; import 'build/src/app/projects/project-outcome-alignment/project-outcome-alignment.js'; -import 'build/src/app/groups/groups.js'; -import 'build/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.js'; import 'build/src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.js'; import 'build/src/app/units/modals/modals.js'; import 'build/src/app/units/units.js'; @@ -210,6 +208,7 @@ import {PortfolioLearningSummaryReportStepComponent} from './projects/states/por import {PortfolioAddExtraFilesStepComponent} from './projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component'; import {UnitGroupsComponent} from './units/states/groups/unit-groups/unit-groups.component'; import {ProjectGroupsComponent} from './projects/states/groups/project-groups/project-groups.component'; +import {GroupMemberContributionAssignerComponent} from './groups/group-member-contribution-assigner/group-member-contribution-assigner.component'; export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.config', @@ -218,7 +217,6 @@ export const DoubtfireAngularJSModule = angular.module('doubtfire', [ 'doubtfire.units', 'doubtfire.tasks', 'doubtfire.projects', - 'doubtfire.groups', 'doubtfire.visualisations', ]); @@ -556,3 +554,8 @@ DoubtfireAngularJSModule.directive( 'fProjectGroups', downgradeComponent({component: ProjectGroupsComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fGroupMemberContributionAssigner', + downgradeComponent({component: GroupMemberContributionAssignerComponent}), +); diff --git a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee deleted file mode 100644 index b949a95d98..0000000000 --- a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee +++ /dev/null @@ -1,74 +0,0 @@ -angular.module('doubtfire.groups.group-member-contribution-assigner', []) - -# -# Directive to rate each student's contributions -# in a group task assessment -# -.directive('groupMemberContributionAssigner', -> - restrict: 'E' - templateUrl: 'groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html' - replace: true - scope: - task: '=' - project: '=' - team: '=' #out parameter - - controller: ($scope, gradeService) -> - $scope.selectedGroupSet = $scope.task.definition.groupSet - unless $scope.task.isTestSubmission - $scope.selectedGroup = $scope.project.getGroupForTask($scope.task) - - $scope.memberSortOrder = 'project.student.name' - $scope.numStars = 5 - $scope.initialStars = 3 - - $scope.percentages = { - danger: 0, - warning: 25, - info: 50, - success: 100 - } - - $scope.checkClearRating = (contrib) -> - if contrib.confRating == 1 && contrib.overStar == 1 && contrib.rating == 0 - contrib.rating = contrib.percent = 0 - else if contrib.confRating == 1 && contrib.overStar == 1 && contrib.rating == 0 - contrib.rating = 1 - contrib.confRating = contrib.rating - - memberPercentage = (contrib, rating) -> - (100 * (rating / $scope.selectedGroup.contributionSum($scope.team.memberContributions, contrib, rating))).toFixed() - - $scope.hoveringOver = (contrib, value) -> - contrib.overStar = value - contrib.percent = memberPercentage(contrib, value) - - $scope.gradeFor = gradeService.gradeFor - - if $scope.selectedGroup && $scope.selectedGroupSet - $scope.selectedGroup.getMembers().subscribe({ - next: (members) -> - $scope.team.memberContributions = _.map(members, (member) -> - result = { - project: member, - rating: $scope.initialStars, - confRating: $scope.initialStars, - percent: 0 - } - result.percent = memberPercentage(result, $scope.initialStars) - result - ) - # Need the '+' to convert to number - $scope.percentages.warning = +(25 / members.length).toFixed() - $scope.percentages.info = +(50 / members.length).toFixed() - $scope.percentages.success = +(95 / members.length).toFixed() - }) - else - $scope.team.memberContributions = [] - - $scope.percentClass = (pct) -> - return 'label-success' if pct >= $scope.percentages.success - return 'label-info' if $scope.percentages.info <= pct < $scope.percentages.success - return 'label-warning' if $scope.percentages.warning <= pct < $scope.percentages.info - return 'label-danger' if $scope.percentages.danger <= pct < $scope.percentages.warning -) diff --git a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.html b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.html new file mode 100644 index 0000000000..d799655b00 --- /dev/null +++ b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.html @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + +
    Team Member + {{ member.project.student.name }} + Target Grade + + Contribution + @for (i of [].constructor(numStars); track $index) { + + person + + } +
    diff --git a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.scss b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.ts b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.ts new file mode 100644 index 0000000000..15129a953f --- /dev/null +++ b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.ts @@ -0,0 +1,157 @@ +import { + Component, + EventEmitter, + Input, + OnChanges, + OnInit, + Output, + SimpleChanges, +} from '@angular/core'; +import {Sort} from '@angular/material/sort'; +import {MatTableDataSource} from '@angular/material/table'; +import {GroupSet} from 'src/app/api/models/doubtfire-model'; +import {Group, MemberContribution} from 'src/app/api/models/groups/group'; +import {Project} from 'src/app/api/models/project'; +import {Task} from 'src/app/api/models/task'; + +@Component({ + selector: 'f-group-member-contribution-assigner', + templateUrl: './group-member-contribution-assigner.component.html', + styleUrls: ['./group-member-contribution-assigner.component.scss'], +}) +export class GroupMemberContributionAssignerComponent implements OnInit, OnChanges { + @Input() isTestSubmission: boolean; + + @Input() task: Task; + @Input() project: Project; + @Input() team = {memberContributions: [] as MemberContribution[]}; + @Output() teamChange = new EventEmitter<{memberContributions: MemberContribution[]}>(); + + selectedGroupSet: GroupSet; + selectedGroup: Group; + + numStars = 5; + initialStars = 3; + + percentages = { + danger: 0, + warning: 25, + info: 50, + success: 100, + }; + + displayedColumns = ['name', 'target-grade', 'contribution']; + dataSource = new MatTableDataSource([]); + + ngOnInit(): void { + this.initializeGroupData(); + this.loadMembers(); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes['task'] || changes['project']) { + this.initializeGroupData(); + this.loadMembers(); + } + } + + private initializeGroupData(): void { + this.selectedGroupSet = this.task?.definition?.groupSet; + // Check if this is an overseer test submission + if (!this.isTestSubmission) { + const group = this.project?.getGroupForTask(this.task); + this.selectedGroup = group; + if (!this.selectedGroup && this.selectedGroupSet?.groups?.length > 0) { + this.selectedGroup = this.selectedGroupSet.groups[0]; + } + } + } + + private loadMembers(): void { + if (!this.selectedGroup && this.selectedGroupSet?.groups?.length > 0) { + console.error(`Could not find project's group`); + this.team.memberContributions = []; + return; + } + if (this.selectedGroup && this.selectedGroupSet) { + this.selectedGroup.getMembers().subscribe({ + next: (members) => { + this.team.memberContributions = members.map((member) => { + const result: MemberContribution = { + project: member, + rating: this.initialStars, + percent: 0, + overStar: null, + }; + result.percent = this.memberPercentage(result, this.initialStars); + return result; + }); + + // Update percentages based on member count + this.percentages.warning = +(25 / members.length).toFixed(); + this.percentages.info = +(50 / members.length).toFixed(); + this.percentages.success = +(95 / members.length).toFixed(); + + this.teamChange.emit(this.team); + this.dataSource.data = [...this.team.memberContributions]; + }, + }); + } else { + this.team.memberContributions = []; + this.teamChange.emit(this.team); + } + } + + private memberPercentage(contrib: MemberContribution, rating: number): number { + return +( + 100 * + (rating / + this.selectedGroup.contributionSum(this.team.memberContributions, contrib.project, rating)) + ).toFixed(); + } + + selectRating(contrib: MemberContribution, rating: number) { + if (contrib.rating !== rating) { + contrib.rating = rating; + this.hoveringOver(contrib, rating); + } else { + contrib.rating = 0; + this.hoveringOver(contrib, 0); + } + } + + hoveringOver(contrib: MemberContribution, value: number): void { + contrib.overStar = value; + contrib.percent = this.memberPercentage(contrib, value); + } + + private sortCompare(aValue: number | string, bValue: number | string, isAsc: boolean) { + return (aValue < bValue ? -1 : 1) * (isAsc ? 1 : -1); + } + + sortTableData(sort: Sort) { + if (!sort.active || sort.direction === '') { + return; + } + this.dataSource.data = this.dataSource.data.sort((a, b) => { + switch (sort.active) { + case 'name': + return this.sortCompare( + a.project.student.name, + b.project.student.name, + sort.direction === 'asc', + ); + case 'target-grade': + return this.sortCompare( + a.project.targetGrade, + b.project.targetGrade, + sort.direction === 'asc', + ); + case 'contribution': + return this.sortCompare(a.rating, b.rating, sort.direction === 'asc'); + default: + return 0; + } + }); + } +} diff --git a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.scss b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.scss deleted file mode 100644 index 8199fd2757..0000000000 --- a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.scss +++ /dev/null @@ -1,19 +0,0 @@ -.group-member-contribution-assigner { - .group-member-contribution-rating { - &:focus { - outline: none; - } - i { - font-size: 2em; - cursor: pointer; - } - .icon-colorful { - color: rgb(255, 247, 141); - -webkit-text-stroke-width: 1px; - -webkit-text-stroke-color: orange; - } - .icon-disable { - color: #ccc; - } - } -} diff --git a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html deleted file mode 100644 index 1fa8194d11..0000000000 --- a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html +++ /dev/null @@ -1,41 +0,0 @@ -
    - - - - - - - - - - - - - - - -
    Team MemberTarget GradeContribution
    {{member.student_name}} - - - - - - - {{member.percent}} % effort - - - No effort - - -
    -
    diff --git a/src/app/groups/groups.coffee b/src/app/groups/groups.coffee deleted file mode 100644 index feae90ec11..0000000000 --- a/src/app/groups/groups.coffee +++ /dev/null @@ -1,3 +0,0 @@ -angular.module('doubtfire.groups', [ - 'doubtfire.groups.group-member-contribution-assigner' -]) diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee index 7646c70ff4..b0a94257ab 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee @@ -166,7 +166,7 @@ angular.module('doubtfire.tasks.modals.upload-submission-modal', []) shouldDisableByState = { # Disable group if group members not allocated anything group: -> - _.chain($scope.team.memberContributions).map('confRating').compact().value().length == 0 + _.chain($scope.team.memberContributions).map('rating').compact().value().length == 0 # Disable alignment if no alignments made (need at least 1) and # if description is blank alignment: -> diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html index 9b96abcd0b..f8019a3011 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.tpl.html @@ -35,12 +35,12 @@

    - - + +
    - @if (comment.assessment_result && comment.assessment_result.is_successful) { -
    -
    -
    {{ comment.text }}
    + +
    +
    +
    {{ comment.text }}
    - -
    -
    - } @else { + +
    +
    +
    diff --git a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts index 44e22eea8b..ed2e404b26 100644 --- a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts @@ -46,7 +46,7 @@ export class TaskAssessmentCommentComponent implements OnInit { } ngOnInit() { - this.update(); + // this.update(); } get message() { From e454166455d0af105bd9ef037ff7a19c2180e915 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Dec 2025 11:56:10 +1100 Subject: [PATCH 0764/1531] chore(release): 10.0.0-66 --- CHANGELOG.md | 12 ++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6935c31476..aa893a612a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-66](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-65...v10.0.0-66) (2025-12-03) + + +### Features + +* discussion prompts ([#1042](https://github.com/b0ink/doubtfire-deploy/issues/1042)) ([730ffd0](https://github.com/b0ink/doubtfire-deploy/commit/730ffd0c3f79a5ad42c0c59c2f2c2a901ab0d702)) + + +### Bug Fixes + +* correctly set rollover end date ([0611be0](https://github.com/b0ink/doubtfire-deploy/commit/0611be04e8fe7e75ae07504945a2984839475e3a)) + ## [10.0.0-65](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-64...v10.0.0-65) (2025-11-25) diff --git a/package-lock.json b/package-lock.json index c30263893b..184b9874da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-65", + "version": "10.0.0-66", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-65", + "version": "10.0.0-66", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index fb458e4b24..307e43542b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-65", + "version": "10.0.0-66", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 6651279c49f431dbddf6fd5d810440ae7b3b9898 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Dec 2025 14:33:08 +1100 Subject: [PATCH 0765/1531] feat: allow sidekiq web access (#1053) --- ngsw-config.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ngsw-config.json b/ngsw-config.json index 8c80cd0891..5c8069284f 100644 --- a/ngsw-config.json +++ b/ngsw-config.json @@ -47,5 +47,14 @@ } } ], - "navigationUrls": ["/**", "!/**/*.*", "!/**/*__*", "!/**/*__*/**", "!/JPlag/**", "!/JPlag"] + "navigationUrls": [ + "/**", + "!/**/*.*", + "!/**/*__*", + "!/**/*__*/**", + "!/JPlag/**", + "!/JPlag", + "!/sidekiq/**", + "!/sidekiq" + ] } From 8db864661ec58c111bd611e9a33c65f11db59f3d Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Dec 2025 14:33:23 +1100 Subject: [PATCH 0766/1531] chore(release): 10.0.0-67 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa893a612a..eb4dacb6a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-67](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-66...v10.0.0-67) (2025-12-03) + + +### Features + +* allow sidekiq web access ([#1053](https://github.com/b0ink/doubtfire-deploy/issues/1053)) ([6651279](https://github.com/b0ink/doubtfire-deploy/commit/6651279c49f431dbddf6fd5d810440ae7b3b9898)) + ## [10.0.0-66](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-65...v10.0.0-66) (2025-12-03) diff --git a/package-lock.json b/package-lock.json index 184b9874da..452c2770cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-66", + "version": "10.0.0-67", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-66", + "version": "10.0.0-67", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 307e43542b..377855c416 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-66", + "version": "10.0.0-67", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From fbc63b0308d87d921e1d74788e8da6031443e57e Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 8 Dec 2025 15:40:42 +1100 Subject: [PATCH 0767/1531] fix: only trim if valid --- src/app/api/models/user/user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/models/user/user.ts b/src/app/api/models/user/user.ts index 03a281bf12..b11826505a 100644 --- a/src/app/api/models/user/user.ts +++ b/src/app/api/models/user/user.ts @@ -54,7 +54,7 @@ export class User extends Entity { } public get preferredName(): string { - const nickname = this.nickname.trim(); + const nickname = this.nickname?.trim(); const firstName = this.firstName.trim(); if (nickname) { return nickname; From 520be4a74735e9dd9fe9ab511208b48e2fcff152 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 8 Dec 2025 15:43:11 +1100 Subject: [PATCH 0768/1531] chore(release): 10.0.0-68 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb4dacb6a1..6bf63acef3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-68](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-67...v10.0.0-68) (2025-12-08) + + +### Bug Fixes + +* only trim if valid ([fbc63b0](https://github.com/b0ink/doubtfire-deploy/commit/fbc63b0308d87d921e1d74788e8da6031443e57e)) + ## [10.0.0-67](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-66...v10.0.0-67) (2025-12-03) diff --git a/package-lock.json b/package-lock.json index 452c2770cb..7d80fd42ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-67", + "version": "10.0.0-68", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-67", + "version": "10.0.0-68", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 377855c416..5bd6fc814f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-67", + "version": "10.0.0-68", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 2674d4e5ade26e5420b87518f4cd9da909ec7246 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:20:45 +1100 Subject: [PATCH 0769/1531] feat: display number of stuff notes in tutor discussion --- .../states/tutor-discussion/tutor-discussion.component.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html index f38d42764b..87703c8b6b 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html @@ -215,7 +215,10 @@

    {{ task.definition.name }}

    - + From 15365ed4f42af790af9a9ae24dae42f041dff1df Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Fri, 12 Dec 2025 12:26:45 +1100 Subject: [PATCH 0770/1531] feat: attention required task status (#1061) * feat: init discuss check task status * refactor: add discuss check status * refactor: add discuss and check marking button * refactor: add warning badge to discuss check tasks * refactor: update discuss check status description * refactor: update discuss check description * chore: ensure discuss check status does not unlock requisite tasks * refactor: rename to off track * refactor: rename to attention required * refactor: update status colors * refactor: rename to attention required internally * chore: update assess in portfolio color --- src/app/api/models/task-prerequisite.ts | 1 + src/app/api/models/task-status.ts | 84 +++++++++++++++---- src/app/common/footer/footer.component.html | 45 ++++++---- .../status-icon/status-icon.component.scss | 3 + .../tutor-discussion.component.html | 6 +- .../tutor-discussion.component.ts | 1 + ...task-definition-prerequisites.component.ts | 1 + src/styles/common/task-status-colors.scss | 12 ++- src/styles/mixins/task-list.scss | 6 ++ .../mixins/task-status-colors-generator.scss | 3 + src/styles/modules/project-task-bar.scss | 6 ++ src/styles/modules/task-status.scss | 14 ++++ 12 files changed, 144 insertions(+), 38 deletions(-) diff --git a/src/app/api/models/task-prerequisite.ts b/src/app/api/models/task-prerequisite.ts index 510d6ce3b6..9645adfe5b 100644 --- a/src/app/api/models/task-prerequisite.ts +++ b/src/app/api/models/task-prerequisite.ts @@ -23,6 +23,7 @@ export class TaskPrerequisite extends Entity { ready_for_feedback: 1, assess_in_portfolio: 1, discuss: 2, + attention_required: 0, demonstrate: 2, complete: 3, }; diff --git a/src/app/api/models/task-status.ts b/src/app/api/models/task-status.ts index 4bff84e86c..0933627924 100644 --- a/src/app/api/models/task-status.ts +++ b/src/app/api/models/task-status.ts @@ -1,4 +1,4 @@ -import { Task } from './task'; +import {Task} from './task'; export type TaskStatusEnum = | 'not_started' @@ -13,14 +13,15 @@ export type TaskStatusEnum = | 'complete' | 'fail' | 'time_exceeded' - | 'assess_in_portfolio'; + | 'assess_in_portfolio' + | 'attention_required'; export type TaskStatusUiData = { status: TaskStatusEnum; icon: string; label: string; class: string; - help: { detail: string; reason: string; action: string }; + help: {detail: string; reason: string; action: string}; }; export class TaskStatus { @@ -38,6 +39,7 @@ export class TaskStatus { 'fail', 'time_exceeded', 'assess_in_portfolio', + 'attention_required', ]; public static readonly VALID_TOP_TASKS: TaskStatusEnum[] = [ @@ -48,6 +50,7 @@ export class TaskStatus { 'fix_and_resubmit', 'ready_for_feedback', 'discuss', + 'attention_required', 'demonstrate', ]; @@ -60,6 +63,7 @@ export class TaskStatus { 'fail', 'time_exceeded', 'assess_in_portfolio', + 'attention_required', ]; public static readonly FINAL_STATUSES: TaskStatusEnum[] = [ @@ -70,11 +74,25 @@ export class TaskStatus { 'assess_in_portfolio', ]; - public static readonly GRADEABLE_STATUSES: TaskStatusEnum[] = ['fail', 'discuss', 'demonstrate', 'complete']; + public static readonly GRADEABLE_STATUSES: TaskStatusEnum[] = [ + 'fail', + 'discuss', + 'demonstrate', + 'complete', + ]; - public static readonly TO_BE_WORKED_ON: TaskStatusEnum[] = ['not_started', 'redo', 'need_help', 'working_on_it']; + public static readonly TO_BE_WORKED_ON: TaskStatusEnum[] = [ + 'not_started', + 'redo', + 'need_help', + 'working_on_it', + ]; - public static readonly DISCUSSION_STATES: TaskStatusEnum[] = ['discuss', 'demonstrate']; + public static readonly DISCUSSION_STATES: TaskStatusEnum[] = [ + 'discuss', + 'attention_required', + 'demonstrate', + ]; public static readonly STATE_THAT_ALLOWS_EXTENSION: TaskStatusEnum[] = [ 'not_started', @@ -112,6 +130,7 @@ export class TaskStatus { 'discuss', 'demonstrate', 'complete', + 'attention_required', ]; public static readonly FEEDBACK_TEMPLATE_STATUSES: TaskStatusEnum[] = [ @@ -120,9 +139,13 @@ export class TaskStatus { 'fix_and_resubmit', 'redo', 'feedback_exceeded', + 'attention_required', ]; - public static readonly LEARNING_WEIGHT: Map = new Map([ + public static readonly LEARNING_WEIGHT: Map = new Map< + TaskStatusEnum, + number + >([ ['fail', 0.0], ['not_started', 0.0], ['working_on_it', 0.0], @@ -135,10 +158,14 @@ export class TaskStatus { ['demonstrate', 0.8], ['complete', 1.0], ['time_exceeded', 0.3], - ['assess_in_portfolio', 0.0], + ['assess_in_portfolio', 1.0], + ['attention_required', 0.1], ]); - public static readonly STATUS_ACRONYM: Map = new Map([ + public static readonly STATUS_ACRONYM: Map = new Map< + TaskStatusEnum, + string + >([ ['ready_for_feedback', 'RFF'], ['not_started', 'NOS'], ['working_on_it', 'WRK'], @@ -152,6 +179,7 @@ export class TaskStatus { ['fail', 'FAL'], ['time_exceeded', 'TIE'], ['assess_in_portfolio', 'AIP'], + ['attention_required', 'AR'], ]); // Which status should not show up in the task status drop down... for students @@ -172,6 +200,7 @@ export class TaskStatus { ['time_exceeded', ['ready_for_feedback', 'not_started', 'working_on_it', 'need_help']], ['fail', ['ready_for_feedback', 'not_started', 'working_on_it', 'need_help']], ['assess_in_portfolio', ['not_started']], + ['attention_required', ['ready_for_feedback', 'not_started', 'working_on_it', 'need_help']], ]); public static readonly STATUS_LABELS = new Map([ @@ -188,6 +217,7 @@ export class TaskStatus { ['fail', 'Fail'], ['time_exceeded', 'Time Exceeded'], ['assess_in_portfolio', 'Assess in Portfolio'], + ['attention_required', 'Attention Required'], ]); public static readonly STATUS_ICONS = new Map([ @@ -204,6 +234,7 @@ export class TaskStatus { ['fail', 'fa fa-times'], ['time_exceeded', 'fa fa-clock-o'], ['assess_in_portfolio', 'fa fa-folder-open'], + ['attention_required', 'fa fa-commenting'], ]); // Please make sure this matches task-status-colors.less @@ -220,7 +251,8 @@ export class TaskStatus { ['complete', '#5BB75B'], ['fail', '#d93713'], ['time_exceeded', '#d93713'], - ['assess_in_portfolio', '#91b891'], + ['assess_in_portfolio', '#f2d85c'], + ['attention_required', '#f1814d'], ]); public static readonly STATUS_SEQ = new Map([ @@ -237,6 +269,7 @@ export class TaskStatus { ['demonstrate', 11], ['complete', 12], ['assess_in_portfolio', 13], + ['attention_required', 14], ]); public static readonly SWITCHABLE_STATES = { @@ -244,6 +277,7 @@ export class TaskStatus { tutor: [ 'complete', 'discuss', + 'attention_required', 'demonstrate', 'fix_and_resubmit', 'redo', @@ -258,14 +292,16 @@ export class TaskStatus { // action = action student can take public static readonly HELP_DESCRIPTIONS = new Map< TaskStatusEnum, - { detail: string; reason: string; action: string } + {detail: string; reason: string; action: string} >([ [ 'ready_for_feedback', { detail: 'Submitted this task for feedback', - reason: 'You have finished working on the task and have uploaded it for your tutor to assess.', - action: 'No further action is required. Your tutor will change this task status once they have assessed it.', + reason: + 'You have finished working on the task and have uploaded it for your tutor to assess.', + action: + 'No further action is required. Your tutor will change this task status once they have assessed it.', }, ], [ @@ -289,7 +325,8 @@ export class TaskStatus { { detail: 'Need help for the task', reason: 'You are working on the task but would like some help to get it complete.', - action: 'Upload the task with what you have completed so far and add a comment on what you would like help on.', + action: + 'Upload the task with what you have completed so far and add a comment on what you would like help on.', }, ], [ @@ -306,7 +343,8 @@ export class TaskStatus { 'feedback_exceeded', { detail: 'Feedback will no longer be given', - reason: 'This work is not complete to an acceptable standard and your tutor will not reassess it again.', + reason: + 'This work is not complete to an acceptable standard and your tutor will not reassess it again.', action: "It is now your responsibility to ensure this task is at an adequate standard in your portfolio. You should fix your work according to your tutor's prior feedback and include a corrected version in your portfolio.", }, @@ -329,6 +367,16 @@ export class TaskStatus { action: 'For this to be marked as complete, attend class and discuss it with your tutor.', }, ], + [ + 'attention_required', + { + detail: 'Your work is off track and needs focused discussion.', + reason: + 'It seems you have misunderstood some key requirements for this task. Previous feedback has not led to sufficient progress.', + action: + 'Attend class so your tutor can go through your work in detail and help you get back on track.', + }, + ], [ 'demonstrate', { @@ -343,7 +391,8 @@ export class TaskStatus { { detail: 'You are finished with this task 🎉', reason: 'Your tutor is happy with your work and it has been discussed with them.', - action: 'No further action required. Move onto the next task, or go party if everything is done.', + action: + 'No further action required. Move onto the next task, or go party if everything is done.', }, ], [ @@ -359,7 +408,8 @@ export class TaskStatus { 'time_exceeded', { detail: 'Time limit exceeded', - reason: 'This work was submitted after the deadline, having missed both the target date and deadline.', + reason: + 'This work was submitted after the deadline, having missed both the target date and deadline.', action: 'Work submitted after the feedback deadline will not be checked by tutors prior to the portfolio assessment. You will need to ensure this task is at an adequate standard in your portfolio.', }, diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index e7d84ac5e5..a31bf9fac8 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -14,18 +14,32 @@
    - - + +
    + + + +
    - + @if (selectedTask && selectedTask.suggestedTaskStatus) { - } @if (selectedTask?.definition?.assessInPortfolioOnly) { -
    + + +

    } diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts index 801482ec4d..f08edf198c 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts @@ -352,6 +352,7 @@ export class TutorDiscussionComponent implements AfterViewInit { 'demonstrate', 'ready_for_feedback', 'discuss', + 'attention_required', 'need_help', // 'complete', 'fix_and_resubmit', diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts index eff30b4bd3..2528ffcd6d 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts @@ -37,6 +37,7 @@ export class TaskDefinitionPrerequisitesComponent implements OnInit, OnChanges { ready_for_feedback: 1, assess_in_portfolio: 1, discuss: 2, + attention_required: 0, demonstrate: 2, complete: 3, }; diff --git a/src/styles/common/task-status-colors.scss b/src/styles/common/task-status-colors.scss index 563e2cf038..3e045a4406 100644 --- a/src/styles/common/task-status-colors.scss +++ b/src/styles/common/task-status-colors.scss @@ -85,9 +85,15 @@ $task-status-colors: ( fore: $task-status-foreground-color-light, ), assess-in-portfolio: ( - base: #91b891, - dark: darken(#91b891, 15%), - light: lighten(#91b891, 15%), + base: #f2d85c, + dark: darken(#f2d85c, 15%), + light: lighten(#f2d85c, 15%), + fore: $task-status-foreground-color-dark, + ), + attention-required: ( + base: #f1814d, + dark: darken(#f1814d, 15%), + light: lighten(#f1814d, 15%), fore: $task-status-foreground-color-light, ), ); diff --git a/src/styles/mixins/task-list.scss b/src/styles/mixins/task-list.scss index 5684822871..63af66d655 100644 --- a/src/styles/mixins/task-list.scss +++ b/src/styles/mixins/task-list.scss @@ -81,6 +81,9 @@ &.assess-in-portfolio { @include custom-box-shadow(lighten(task-status-color('assess-in-portfolio'), 15%)); } + &.attention-required { + @include custom-box-shadow(lighten(task-status-color('attention-required'), 15%)); + } } &.selected { &.ready-for-feedback { @@ -122,6 +125,9 @@ &.assess-in-portfolio { @include custom-box-shadow(task-status-color('assess-in-portfolio')); } + &.attention-required { + @include custom-box-shadow(task-status-color('attention-required')); + } } .task-badges { width: 50px; diff --git a/src/styles/mixins/task-status-colors-generator.scss b/src/styles/mixins/task-status-colors-generator.scss index 4d0646ecd6..6f2b97e2c5 100644 --- a/src/styles/mixins/task-status-colors-generator.scss +++ b/src/styles/mixins/task-status-colors-generator.scss @@ -62,3 +62,6 @@ @mixin task-status-color-assess-in-portfolio { @include task-status-color('assess-in-portfolio'); } +@mixin task-status-color-attention-required { + @include task-status-color('attention-required'); +} diff --git a/src/styles/modules/project-task-bar.scss b/src/styles/modules/project-task-bar.scss index 78d15e07f6..d3af788607 100644 --- a/src/styles/modules/project-task-bar.scss +++ b/src/styles/modules/project-task-bar.scss @@ -76,6 +76,12 @@ .progress-bar-complete { @include task-status-color-complete; } +.progress-bar-assess-in-portfolio { + @include task-status-color-assess-in-portfolio; +} +.progress-bar-attention-required { + @include task-status-color-attention-required; +} .progress-bar-not-started { @include task-status-color-not-started; diff --git a/src/styles/modules/task-status.scss b/src/styles/modules/task-status.scss index ba7252f899..6ed7ea0f57 100644 --- a/src/styles/modules/task-status.scss +++ b/src/styles/modules/task-status.scss @@ -41,6 +41,9 @@ &.assess-in-portfolio { @include task-status-color-assess-in-portfolio; } + &.attention-required { + @include task-status-color-attention-required; + } &.ready-for-feedback:hover { background-color: task-status-color('ready-for-feedback'); @@ -81,6 +84,9 @@ &.assess-in-portfolio:hover { background-color: task-status-color('assess-in-portfolio'); } + &.attention-required:hover { + background-color: task-status-color('attention-required'); + } } .task-status > .btn-default { @@ -149,6 +155,11 @@ &.assess-in-portfolio:hover { @include task-status-color-assess-in-portfolio; } + &.attention-required, + &.attention-required.active, + &.attention-required:hover { + @include task-status-color-attention-required; + } &.ready-for-feedback { background-color: lighten(task-status-color('ready-for-feedback'), 15%); @@ -189,6 +200,9 @@ &.assess-in-portfolio { background-color: lighten(task-status-color('assess-in-portfolio'), 15%); } + &.attention-required { + background-color: lighten(task-status-color('attention-required'), 15%); + } } i.task-status-icon { From 7cb8fc7471f0402c562fb8a0b87df672ceb22ea3 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 5 Jan 2026 15:01:53 +1100 Subject: [PATCH 0771/1531] feat: overseer pipeline (#1064) * feat: init overseer pipeline ui * chore: init drag and drop steps panel * feat: init overseer-step crud * feat: use new monaco editor package * refactor: clean up ui * feat: get list of overseer resource files * chore: allow no input file * feat: allow partial input output diff check * feat: allow deleting of overseer steps * feat: overseer step result model * refactor: improve overseer report view * refactor: organise imports * refactor: retrieve feedback message * refactor: expose overseer assessment details to task comment * feat: dropdown for command language * fix: set fixed height size * chore: show overseer reports to students * build: ensure monaco editor is packed correctly * refactor: lazy load step results for overseer assessments * refactor: align default feedback messages with the backend * refactor: improve assessment comment ui * chore: ignore old assessment script * refactor: hide test result until report is ready * fix: use new overseer report component for test submission history * chore: allow for overseer report refresh * refactor: reduce icon size * refactor: auto expand selected overseer report * chore: enable submission history if project is valid * chore: delete new step * chore: set correct overseer steps when changing task definition * feat: add overseer task status result * chore: add hint explaining test submissions can be used before enabling overseer * refactor: hide overseer steps until docker image has been selected * chore: move overseer editor to original place * refactor: ensure task definition is saved before adding overseer steps * chore: show delete and save buttons when step is selected * refactor: use seconds for overseer timeout * refactor: show status dropdown only when halting step * refactor: cleanup * chore: render diff if overseer step is null * refactor: remove debug * chore: show empty overseer reports --- angular.json | 8 + package-lock.json | 47 +-- package.json | 3 +- .../models/overseer/overseer-assessment.ts | 23 +- .../models/overseer/overseer-step-result.ts | 35 ++ src/app/api/models/overseer/overseer-step.ts | 75 ++++ src/app/api/models/task-definition.ts | 4 + src/app/api/models/task.ts | 6 +- .../services/overseer-assessment.service.ts | 28 +- .../services/overseer-step-result.service.ts | 52 +++ src/app/api/services/overseer-step.service.ts | 47 +++ src/app/api/services/task-comment.service.ts | 5 + .../api/services/task-definition.service.ts | 18 + src/app/common/footer/footer.component.ts | 6 +- .../task-assessment-modal.component.html | 16 +- .../task-assessment-modal.component.ts | 7 +- .../task-assessment-modal.service.ts | 35 +- src/app/doubtfire-angular.module.ts | 13 +- src/app/doubtfire-angularjs.module.ts | 6 + .../task-overseer-report.component.html | 167 ++++++++ .../task-overseer-report.component.scss | 0 .../task-overseer-report.component.ts | 145 +++++++ .../task-dashboard/task-dashboard.coffee | 2 +- .../task-dashboard.component.html | 4 + .../task-dashboard/task-dashboard.tpl.html | 14 +- .../states/dashboard/selected-task.service.ts | 5 + .../task-assessment-comment.component.html | 58 ++- .../task-assessment-comment.component.scss | 56 --- .../task-assessment-comment.component.ts | 24 +- .../task-definition-overseer.component.html | 376 +++++++++++++++++- .../task-definition-overseer.component.scss | 50 +++ .../task-definition-overseer.component.ts | 206 +++++++++- 32 files changed, 1383 insertions(+), 158 deletions(-) create mode 100644 src/app/api/models/overseer/overseer-step-result.ts create mode 100644 src/app/api/models/overseer/overseer-step.ts create mode 100644 src/app/api/services/overseer-step-result.service.ts create mode 100644 src/app/api/services/overseer-step.service.ts create mode 100644 src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html create mode 100644 src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.scss create mode 100644 src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts diff --git a/angular.json b/angular.json index cf6bc6bd32..0d892151bd 100644 --- a/angular.json +++ b/angular.json @@ -29,8 +29,16 @@ "input": "./JPlag-Report-Viewer", "output": "/JPlag", "glob": "**/!(*.gitignore|README.md|.git)" + }, + { + "glob": "**/*", + "input": "./node_modules/monaco-editor/min", + "output": "/assets/monaco/min/" } ], + "loader": { + ".ttf": "binary" + }, "styles": [ "src/theme.scss", "src/styles.scss", diff --git a/package-lock.json b/package-lock.json index 7d80fd42ec..05dae886a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,7 +61,7 @@ "lottie-web": "^5.12.2", "marked": "^11.1.0", "moment": "^2.29.4", - "monaco-editor": "^0.54.0", + "monaco-editor": "^0.44.0", "ng-csv": "0.2.3", "ng-file-upload": "~5.0.9", "ng-flex-layout": "^17.3.7-beta.1", @@ -69,6 +69,7 @@ "ngx-bootstrap": "^6.1.0", "ngx-entity-service": "^0.0.41", "ngx-lottie": "^11.0.2", + "ngx-monaco-editor-v2": "^17.0.1", "nvd3": "1.8.6", "qrcode": "^1.5.4", "rxjs": "~7.4.0", @@ -9254,12 +9255,6 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/dompurify": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", - "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==", - "license": "(MPL-2.0 OR Apache-2.0)" - }, "node_modules/domutils": { "version": "3.1.0", "dev": true, @@ -15766,26 +15761,10 @@ } }, "node_modules/monaco-editor": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.54.0.tgz", - "integrity": "sha512-hx45SEUoLatgWxHKCmlLJH81xBo0uXP4sRkESUpmDQevfi+e7K1VuiSprK6UpQ8u4zOcKNiH0pMvHvlMWA/4cw==", - "license": "MIT", - "dependencies": { - "dompurify": "3.1.7", - "marked": "14.0.0" - } - }, - "node_modules/monaco-editor/node_modules/marked": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", - "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 18" - } + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.44.0.tgz", + "integrity": "sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==", + "license": "MIT" }, "node_modules/morgan": { "version": "1.10.0", @@ -16126,6 +16105,20 @@ "lottie-web": ">=5.9.2" } }, + "node_modules/ngx-monaco-editor-v2": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/ngx-monaco-editor-v2/-/ngx-monaco-editor-v2-17.0.1.tgz", + "integrity": "sha512-GP+Ni6zKFQjF/ve5ZQtfE9eRLKL4GxMvdmDTrla1x6F5pSIcYGCcjZ4gQ1/AHMa5dgarfs+Et+1bBtAOJtI6KA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@angular/common": "^17.0.3", + "@angular/core": "^17.0.3", + "monaco-editor": "^0.44.0" + } + }, "node_modules/nice-napi": { "version": "1.0.2", "dev": true, diff --git a/package.json b/package.json index 5bd6fc814f..d3eeccad5d 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "lottie-web": "^5.12.2", "marked": "^11.1.0", "moment": "^2.29.4", - "monaco-editor": "^0.54.0", + "monaco-editor": "^0.44.0", "ng-csv": "0.2.3", "ng-file-upload": "~5.0.9", "ng-flex-layout": "^17.3.7-beta.1", @@ -88,6 +88,7 @@ "ngx-bootstrap": "^6.1.0", "ngx-entity-service": "^0.0.41", "ngx-lottie": "^11.0.2", + "ngx-monaco-editor-v2": "^17.0.1", "nvd3": "1.8.6", "qrcode": "^1.5.4", "rxjs": "~7.4.0", diff --git a/src/app/api/models/overseer/overseer-assessment.ts b/src/app/api/models/overseer/overseer-assessment.ts index dcffd8fd4f..005b6be09f 100644 --- a/src/app/api/models/overseer/overseer-assessment.ts +++ b/src/app/api/models/overseer/overseer-assessment.ts @@ -1,20 +1,28 @@ -import {Entity, EntityMapping} from 'ngx-entity-service'; +import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; import {Task} from '../doubtfire-model'; +import {OverseerStepResult} from './overseer-step-result'; export class OverseerAssessment extends Entity { id: number; + // overseerStepId: number; timestamp: Date; timestampString: string; content?: [{label: string; result: string}]; task?: Task; taskStatus?: string; - submissionStatus?: string; + submissionStatus?: 'queued' | 'executing' | 'passed' | 'failed' | 'error'; createdAt?: Date; updatedAt?: Date; taskId?: number; + totalSteps: number; + passedSteps: number; + label: string; + public readonly stepResultsCache: EntityCache = + new EntityCache(); + constructor(task?: Task) { super(); @@ -31,4 +39,15 @@ export class OverseerAssessment extends Entity { overseer_assessment: super.toJson(mappingData, ignoreKeys), }; } + + public get stepsSkipped() { + return this.task?.definition.overseerStepsCache.currentValues.filter( + (step) => + !this.stepResultsCache.currentValues.find((result) => result.overseerStepId === step.id), + ); + } + + public get reportReady() { + return this.submissionStatus === 'passed' || this.submissionStatus === 'failed'; + } } diff --git a/src/app/api/models/overseer/overseer-step-result.ts b/src/app/api/models/overseer/overseer-step-result.ts new file mode 100644 index 0000000000..2a44371825 --- /dev/null +++ b/src/app/api/models/overseer/overseer-step-result.ts @@ -0,0 +1,35 @@ +import {Entity, EntityMapping} from 'ngx-entity-service'; +import {OverseerAssessment} from './overseer-assessment'; +import {OverseerStep} from './overseer-step'; + +export class OverseerStepResult extends Entity { + id: number; + overseerAssessment: OverseerAssessment; + overseerStep: OverseerStep; + overseerStepId: number; + + exitStatus: number; + pass: boolean; + stdout: string; + stdin: string; + expectedOutput: string; + stdoutSha256: string; + stdinSha256: string; + expectedOutputSha256: string; + feedbackMessage: string; + + constructor(oa?: OverseerAssessment, os?: OverseerStep) { + super(); + this.overseerAssessment = oa; + // this.overseerStep = os; + } + + public override toJson( + mappingData: EntityMapping, + ignoreKeys?: string[], + ): object { + return { + overseer_step_result: super.toJson(mappingData, ignoreKeys), + }; + } +} diff --git a/src/app/api/models/overseer/overseer-step.ts b/src/app/api/models/overseer/overseer-step.ts new file mode 100644 index 0000000000..5d2a03ee28 --- /dev/null +++ b/src/app/api/models/overseer/overseer-step.ts @@ -0,0 +1,75 @@ +import {Entity, EntityMapping} from 'ngx-entity-service'; +import {TaskDefinition} from '../task-definition'; +import {TaskStatus, TaskStatusEnum} from '../task-status'; +import {OverseerStepService} from '../../services/overseer-step.service'; +import {AppInjector} from 'src/app/app-injector'; +import {AlertService} from 'src/app/common/services/alert.service'; + +export class OverseerStep extends Entity { + id: number; + taskDefinition: TaskDefinition; + + name: string; + description: string; + + // Shown to the student's + displayName: string; + displayDescription: string; + + runCommand: string; + commandLanguage: string; + timeout: number; + sortOrder: number; + stepType: 'status_check' | 'output_diff'; + partialOutputDiff: boolean; + stdinInputFile: string; + expectedOutputFile: string; + + feedbackMessage: string; + statusOnSuccess: TaskStatusEnum | 'no_change'; + statusOnFailure: TaskStatusEnum | 'no_change'; + + haltOnSuccess: boolean; + haltOnFailure: boolean; + + showExpectedOutput: boolean; + showStdin: boolean; + showStdout: boolean; + + enabled: boolean; + + // showStdOutToStudent: boolean + + constructor(td?: TaskDefinition) { + super(); + this.taskDefinition = td; + } + + public override toJson( + mappingData: EntityMapping, + ignoreKeys?: string[], + ): object { + return { + overseer_step: super.toJson(mappingData, ignoreKeys), + }; + } + + public delete() { + const overseerStepService: OverseerStepService = AppInjector.get(OverseerStepService); + overseerStepService + .delete( + { + id: this.id, + }, + {cache: this.taskDefinition.overseerStepsCache, endpointFormat: 'overseer_steps/:id:'}, + ) + .subscribe({ + next: (_response: object) => { + AppInjector.get(AlertService).success('Successfully deleted overseer step', 4000); + }, + error: (error) => { + AppInjector.get(AlertService).error(error?.message || error || 'Unknown error', 2000); + }, + }); + } +} diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index d3aa2a4317..4a47a7ab96 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -9,6 +9,7 @@ import {Grade, GroupSet, LearningOutcome, Project, TutorialStream, Unit} from '. import {Task} from './doubtfire-model'; import {TaskPrerequisite} from './task-prerequisite'; import {DiscussionPrompt} from './discussion-prompt'; +import {OverseerStep} from './overseer/overseer-step'; export type UploadRequirement = { key: string; @@ -59,6 +60,7 @@ export class TaskDefinition extends Entity { useResourcesForJplagBaseCode: boolean; lockAssessmentsToTutorialStream: boolean; discussionPromptsCount: number; + overseerResourceFiles: string[] = []; public readonly taskPrerequisitesCache: EntityCache = new EntityCache(); @@ -69,6 +71,8 @@ export class TaskDefinition extends Entity { public readonly learningOutcomesCache: EntityCache = new EntityCache(); + public readonly overseerStepsCache: EntityCache = new EntityCache(); + readonly unit: Unit; constructor(unit: Unit) { diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index c920e985a7..d624a8285d 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -579,11 +579,7 @@ export class Task extends Entity { } public get overseerEnabled(): boolean { - return ( - this.unit.overseerEnabled && - this.definition.assessmentEnabled && - this.definition.hasTaskAssessmentResources - ); + return this.unit.overseerEnabled && this.definition.assessmentEnabled; } public get scormEnabled(): boolean { diff --git a/src/app/api/services/overseer-assessment.service.ts b/src/app/api/services/overseer-assessment.service.ts index 2226887caf..df897e43be 100644 --- a/src/app/api/services/overseer-assessment.service.ts +++ b/src/app/api/services/overseer-assessment.service.ts @@ -5,6 +5,7 @@ import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiUrl'; import {OverseerAssessment} from '../models/overseer/overseer-assessment'; import {Task} from '../models/doubtfire-model'; +import {OverseerStepResultService} from './overseer-step-result.service'; @Injectable() export class OverseerAssessmentService extends EntityService { @@ -13,7 +14,10 @@ export class OverseerAssessmentService extends EntityService protected readonly triggerEndpointFormat = 'projects/:project_id:/task_def_id/:td_id:/overseer_assessment/:id:/trigger'; - constructor(httpClient: HttpClient) { + constructor( + httpClient: HttpClient, + private overseerStepResultService: OverseerStepResultService, + ) { super(httpClient, API_URL); this.mapping.addKeys( @@ -31,6 +35,24 @@ export class OverseerAssessmentService extends EntityService }, }, ['timestampString', 'submission_timestamp'], + { + keys: 'overseerStepResults', + toEntityOp: (data: object, key: string, overseerAssesment: OverseerAssessment) => { + data[key]?.forEach((overseerStep) => { + overseerAssesment.stepResultsCache.getOrCreate( + overseerStep['id'], + this.overseerStepResultService, + overseerStep, + { + constructorParams: overseerAssesment, + }, + ); + }); + }, + }, + 'overseerStepId', + 'totalSteps', + 'passedSteps', ); } @@ -44,7 +66,9 @@ export class OverseerAssessmentService extends EntityService td_id: task.definition.id, }; - return this.query(pathIds); + return this.query(pathIds, { + constructorParams: task, + }); } public triggerOverseer(assessment: OverseerAssessment): Observable { diff --git a/src/app/api/services/overseer-step-result.service.ts b/src/app/api/services/overseer-step-result.service.ts new file mode 100644 index 0000000000..f7e873281b --- /dev/null +++ b/src/app/api/services/overseer-step-result.service.ts @@ -0,0 +1,52 @@ +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {CachedEntityService} from 'ngx-entity-service'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {OverseerAssessment} from '../models/doubtfire-model'; +import {OverseerStepResult} from '../models/overseer/overseer-step-result'; +import {Observable} from 'rxjs'; + +@Injectable() +export class OverseerStepResultService extends CachedEntityService { + protected readonly endpointFormat = + 'units/:unitId:/task_definitions/:taskDefId:/overseer_step_results/:id:'; + + constructor(httpClient: HttpClient) { + super(httpClient, API_URL); + + this.mapping.addKeys( + 'id', + 'overseerStepId', + 'exitStatus', + 'pass', + 'feedbackMessage', + 'stdout', + 'stdin', + 'expectedOutput', + 'stdoutSha256', + 'stdinSha256', + 'expectedOutputSha256', + ); + + this.mapping.mapAllKeysToJsonExcept('id'); + } + + public createInstanceFrom(json: object, other?: any): OverseerStepResult { + return new OverseerStepResult(other as OverseerAssessment); + } + + public getOverseerStepResults(assessment: OverseerAssessment): Observable { + const pathIds = { + projectId: assessment.task.project.id, + taskDefId: assessment.task.definition.id, + id: assessment.id, + }; + + return this.query(pathIds, { + endpointFormat: + 'projects/:projectId:/task_definitions/:taskDefId:/overseer_assessments_results/:id:', + constructorParams: assessment.task, + cache: assessment.stepResultsCache, + }); + } +} diff --git a/src/app/api/services/overseer-step.service.ts b/src/app/api/services/overseer-step.service.ts new file mode 100644 index 0000000000..6df6323294 --- /dev/null +++ b/src/app/api/services/overseer-step.service.ts @@ -0,0 +1,47 @@ +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {CachedEntityService} from 'ngx-entity-service'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {OverseerStep} from '../models/overseer/overseer-step'; +import {TaskDefinition} from '../models/task-definition'; + +@Injectable() +export class OverseerStepService extends CachedEntityService { + protected readonly endpointFormat = + 'units/:unitId:/task_definitions/:taskDefId:/overseer_steps/:id:'; + + constructor(httpClient: HttpClient) { + super(httpClient, API_URL); + + this.mapping.addKeys( + 'id', + // 'taskDefinition', + 'name', + 'description', + 'displayName', + 'displayDescription', + 'runCommand', + 'timeout', + 'sortOrder', + 'stepType', + 'partialOutputDiff', + 'stdinInputFile', + 'expectedOutputFile', + 'feedbackMessage', + 'statusOnSuccess', + 'statusOnFailure', + 'haltOnSuccess', + 'haltOnFailure', + 'showExpectedOutput', + 'showStdin', + 'showStdout', + 'enabled', + ); + + this.mapping.mapAllKeysToJsonExcept('id'); + } + + public createInstanceFrom(json: object, other?: any): OverseerStep { + return new OverseerStep(other as TaskDefinition); + } +} diff --git a/src/app/api/services/task-comment.service.ts b/src/app/api/services/task-comment.service.ts index b804b164b4..6761bc715c 100644 --- a/src/app/api/services/task-comment.service.ts +++ b/src/app/api/services/task-comment.service.ts @@ -120,6 +120,11 @@ export class TaskCommentService extends CachedEntityService { // Scorm Extension Comments ['taskScormExtensions', 'scorm_extensions'], + 'overseerAssessmentId', + 'overseerPassedSteps', + 'overseerTotalSteps', + 'overseerInProgress', + 'overseerStatus', ); this.mapping.addJsonKey('granted'); diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 59664c143a..8e98e8175d 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -15,6 +15,7 @@ import {TaskPrerequisiteService} from './task-prerequisite.service'; import {TaskPrerequisite} from '../models/task-prerequisite'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {SidekiqJob} from '../models/sidekiq-job'; +import {OverseerStepService} from './overseer-step.service'; @Injectable() export class TaskDefinitionService extends CachedEntityService { @@ -24,6 +25,7 @@ export class TaskDefinitionService extends CachedEntityService { httpClient: HttpClient, private learningOutcomeService: LearningOutcomeService, private taskPrerequisiteService: TaskPrerequisiteService, + private overseerStepService: OverseerStepService, ) { super(httpClient, API_URL); @@ -140,6 +142,22 @@ export class TaskDefinitionService extends CachedEntityService { }, 'useResourcesForJplagBaseCode', 'lockAssessmentsToTutorialStream', + { + keys: 'overseerSteps', + toEntityOp: (data: object, key: string, taskDefinition: TaskDefinition) => { + data[key]?.forEach((overseerStep) => { + taskDefinition.overseerStepsCache.getOrCreate( + overseerStep['id'], + this.overseerStepService, + overseerStep, + { + constructorParams: taskDefinition, + }, + ); + }); + }, + }, + 'overseerResourceFiles', ); this.mapping.mapAllKeysToJsonExcept( diff --git a/src/app/common/footer/footer.component.ts b/src/app/common/footer/footer.component.ts index 295b8612ee..fa44839024 100644 --- a/src/app/common/footer/footer.component.ts +++ b/src/app/common/footer/footer.component.ts @@ -99,8 +99,12 @@ export class FooterComponent implements OnInit { this.selectedTaskService.showSimilarity(); } + // viewOverseer() { + // this.taskAssessmentModal.show(this.selectedTask); + // } + viewOverseer() { - this.taskAssessmentModal.show(this.selectedTask); + this.selectedTaskService.showOverseerReports(); } viewStaffNotes() { diff --git a/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.html b/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.html index 080a65cfd6..4ac4445bfb 100644 --- a/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.html +++ b/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.html @@ -1,14 +1,20 @@

    Overseer Assessment

    - - + +
    @if (noDataFlag) { - + }
    diff --git a/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.ts b/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.ts index 06c8fb3246..13bd6e9236 100644 --- a/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.ts +++ b/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.ts @@ -2,6 +2,7 @@ import {Component, OnInit, Inject, Input} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {Subject} from 'rxjs'; import {Task} from 'src/app/api/models/doubtfire-model'; +import {TaskAssessmentModalData} from './task-assessment-modal.service'; @Component({ selector: 'task-assessment-modal', @@ -10,16 +11,18 @@ import {Task} from 'src/app/api/models/doubtfire-model'; }) export class TaskAssessmentModalComponent implements OnInit { @Input() task: Task; + @Input() overseerAssessmentId?: number; noDataFlag: boolean; refreshTrigger: Subject = new Subject(); constructor( public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any, + @Inject(MAT_DIALOG_DATA) public data: TaskAssessmentModalData, ) {} ngOnInit() { - this.task = this.data; + this.task = this.data.task; + this.overseerAssessmentId = this.data.overseerAssessmentId; } setNoDataFlag($event) { diff --git a/src/app/common/modals/task-assessment-modal/task-assessment-modal.service.ts b/src/app/common/modals/task-assessment-modal/task-assessment-modal.service.ts index 927c861a04..31e9bc54c9 100644 --- a/src/app/common/modals/task-assessment-modal/task-assessment-modal.service.ts +++ b/src/app/common/modals/task-assessment-modal/task-assessment-modal.service.ts @@ -1,21 +1,30 @@ -import { Injectable } from '@angular/core'; -import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog'; +import {Injectable} from '@angular/core'; +import {MatDialogRef, MAT_DIALOG_DATA, MatDialog} from '@angular/material/dialog'; import {TaskAssessmentModalComponent} from './task-assessment-modal.component'; +import {Task} from 'src/app/api/models/task'; + +export interface TaskAssessmentModalData { + task: Task; + overseerAssessmentId: number; +} @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class TaskAssessmentModalService { - constructor( - public dialog: MatDialog, - ) { } + constructor(public dialog: MatDialog) {} - public show(task: any) { - let dialogRef: MatDialogRef; - dialogRef = this.dialog.open(TaskAssessmentModalComponent, { - data: task, - width: '80%', - panelClass: 'submission-history-modal' - }); + public show(task: Task, overseerAssessmentId?: number) { + this.dialog.open( + TaskAssessmentModalComponent, + { + data: { + task: task, + overseerAssessmentId, + }, + width: '80%', + panelClass: 'submission-history-modal', + }, + ); } } diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 7938a4e274..86b5fc459d 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -43,9 +43,13 @@ import {UIRouterUpgradeModule} from '@uirouter/angular-hybrid'; import {MatDialogModule as MatDialogModuleNew} from '@angular/material/dialog'; import {AlertService} from 'src/app/common/services/alert.service'; import {AlertComponent} from 'src/app/common/services/alert.service'; +import {MatSidenavModule} from '@angular/material/sidenav'; import {setTheme} from 'ngx-bootstrap/utils'; +import {CodeEditorModule} from '@ngstack/code-editor'; +import {MonacoEditorModule} from 'ngx-monaco-editor-v2'; + import {AboutDoubtfireModalService} from 'src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.service'; import { D2lUnitDetailsFormComponent, @@ -295,12 +299,14 @@ import {AnalyticsTutorTimesComponent} from './units/states/analytics/directives/ import {MarkingSessionService} from './api/services/marking-session.service'; import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component'; import {OverseerScriptEditorModalComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component'; -import {CodeEditorModule} from '@ngstack/code-editor'; import {UploadGradesComponent} from './units/states/portfolios/upload-grades/upload-grades.component'; import {DiscussionPromptService} from './api/services/discussion-prompt.service'; import {DiscussionPromptsComponent} from './projects/states/discussion-prompts/discussion-prompts.component'; import {TaskDefinitionDiscussionPromptsComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component'; import {DiscussionPromptsViewComponent} from './projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component'; +import {OverseerStepService} from './api/services/overseer-step.service'; +import {TaskOverseerReportComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component'; +import {OverseerStepResultService} from './api/services/overseer-step-result.service'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { @@ -460,6 +466,7 @@ const MY_DATE_FORMAT = { DiscussionPromptsComponent, TaskDefinitionDiscussionPromptsComponent, DiscussionPromptsViewComponent, + TaskOverseerReportComponent, ], providers: [ // Services we provide @@ -550,6 +557,8 @@ const MY_DATE_FORMAT = { TaskPrerequisiteService, MarkingSessionService, DiscussionPromptService, + OverseerStepService, + OverseerStepResultService, ], imports: [ FlexLayoutModule, @@ -613,6 +622,8 @@ const MY_DATE_FORMAT = { MatDialogModuleNew, CalendarModule.forRoot({provide: CalendarDateAdapter, useFactory: adapterFactory}), CodeEditorModule.forRoot(), + MatSidenavModule, + MonacoEditorModule.forRoot(), ], }) diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 8187457400..8d0fee5456 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -233,6 +233,7 @@ import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/dir import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component'; import {TaskSimilarityViewComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component'; import {UploadGradesComponent} from './units/states/portfolios/upload-grades/upload-grades.component'; +import {TaskOverseerReportComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component'; export const DoubtfireAngularJSModule = angular .module('doubtfire', [ @@ -575,3 +576,8 @@ DoubtfireAngularJSModule.directive( 'fUploadGrades', downgradeComponent({component: UploadGradesComponent}), ); + +DoubtfireAngularJSModule.directive( + 'fTaskOverseerReport', + downgradeComponent({component: TaskOverseerReportComponent}), +); diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html new file mode 100644 index 0000000000..5609881791 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html @@ -0,0 +1,167 @@ +
    + +
    + + @for (oa of overseerAssessments; track oa; let idx = $index) { + + + + + Submission {{ idx + 1 }}: {{ oa.timestamp | humanizedDate }} + @if (idx === 0) { + (Most recent) + } + + @if (oa.reportReady) { +
    + {{ oa.passedSteps }} / {{ oa.totalSteps }} + @if (oa.passedSteps === oa.totalSteps) { + done + } @else { + cancel + } +
    + } @else { +
    + Tests In Progress + +
    + } +
    + + + @for (result of oa.stepResultsCache.values | async; track result.id; let idx = $index) { + + + + Step {{ idx + 1 }}: {{ result.overseerStep?.displayName }} + @if (result.pass) { + done + } @else { + cancel + } + + + + + + @if (!result.pass) { +

    + {{ result.feedbackMessage }} +

    + } + + @if ( + result.expectedOutput && + result.expectedOutput !== result.stdout && + (result.overseerStep?.stepType === 'output_diff' || !result.overseerStep) + ) { +
    + + + + + + +
    + @if (viewOutput === 'diff' || viewOutput === 'split_diff') { + @if (result.expectedOutput !== result.stdout) { + + } + } @else if (viewOutput === 'your_output') { + + } @else if (viewOutput === 'expected_output') { + + } + } @else if (result.stdout) { +
    {{result.stdout}}
    + } @else if (result.pass) { +
    SUCCESS
    +
    + (No Output) +
    + } +
    + } + @if (loadingAssessments.has(oa.id)) { +
    + +
    + } @else { + @for (skipped of oa.stepsSkipped; track skipped.id; let idx = $index) { + + + + + + Step {{ oa.stepResultsCache.currentValues.length + idx + 1 }}: + {{ skipped?.displayName ?? '-' }} + (Skipped) + + + pause + + + } + } +
    +
    + } @empty { +
    + subtitles_off +
    No submission reports for this task.
    +
    + } +
    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.scss b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts new file mode 100644 index 0000000000..cf4c5a86ed --- /dev/null +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts @@ -0,0 +1,145 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {OverseerAssessment} from 'src/app/api/models/doubtfire-model'; +import {Task} from 'src/app/api/models/task'; +import {OverseerAssessmentService} from 'src/app/api/services/overseer-assessment.service'; +import {OverseerStepResultService} from 'src/app/api/services/overseer-step-result.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {TaskSubmissionService} from 'src/app/common/services/task-submission.service'; + +@Component({ + selector: 'f-task-overseer-report', + templateUrl: './task-overseer-report.component.html', + styleUrl: './task-overseer-report.component.scss', +}) +export class TaskOverseerReportComponent implements OnInit { + @Input() task: Task; + @Input() loadOverseerAssessmentId?: number; + + constructor( + private alerts: AlertService, + private submissions: TaskSubmissionService, + private overseerAssessmentService: OverseerAssessmentService, + private overseerStepResultsService: OverseerStepResultService, + ) {} + + public viewOutput: 'your_output' | 'expected_output' | 'diff' | 'split_diff' = 'your_output'; + + stdoutOptions = { + theme: 'vs-dark', + language: 'plaintext', + renderMinimap: false, + lineNumbers: false, + + minimap: { + enabled: false, + }, + }; + editorOptions = { + theme: 'vs', + language: 'text', + renderMinimap: false, + minimap: { + enabled: false, + }, + readOnly: true, + }; + + diffEditorOptions = { + theme: 'vs', + language: 'plaintext', + renderMinimap: false, + readOnly: true, + domReadOnly: true, + renderMarginRevertIcon: false, + enableSplitViewResizing: false, + useInlineViewWhenSpaceIsLimited: false, + renderSideBySideInlineBreakpoint: 1000, + renderSideBySide: true, + compactMode: true, + minimap: { + enabled: false, + }, + lineNumbers: 'off', + }; + + diff() { + this.diffEditorOptions.renderSideBySide = false; + this.diffEditorOptions.compactMode = true; + this.diffEditorOptions = {...this.diffEditorOptions}; + this.viewOutput = 'diff'; + } + + splitDiff() { + this.diffEditorOptions.renderSideBySide = true; + this.diffEditorOptions.compactMode = false; + this.diffEditorOptions = {...this.diffEditorOptions}; + setTimeout(() => { + this.viewOutput = 'split_diff'; + }, 100); + } + + submissionOutput() { + this.viewOutput = 'your_output'; + } + + expectedOutput() { + this.viewOutput = 'expected_output'; + } + + public overseerAssessments: OverseerAssessment[] = []; + + ngOnInit(): void { + this.loadAssessments(); + } + + loadAssessments(isRefresh: boolean = false) { + if (isRefresh) { + this.loadOverseerAssessmentId = null; + } + this.overseerAssessmentService.queryForTask(this.task).subscribe({ + next: (assessments) => { + this.overseerAssessments = assessments; + for (const oa of this.overseerAssessments) { + for (const result of oa.stepResultsCache.currentValues) { + result.overseerStep = this.task.definition.overseerStepsCache.currentValues.find( + (step) => step.id === result.overseerStepId, + ); + } + } + }, + error: (error) => { + this.alerts.error(`Failed to load overseer reports: ${error}`, 6000); + }, + }); + } + + loadingAssessments = new Set(); + + onAssessmentOpen(overseerAssesment: OverseerAssessment) { + if (this.loadOverseerAssessmentId === overseerAssesment.id) { + setTimeout(() => { + const el = document.getElementById(`oa-panel-${overseerAssesment.id}`); + el?.scrollIntoView({behavior: 'smooth', block: 'start'}); + }, 250); + } + + this.loadingAssessments.add(overseerAssesment.id); + + this.overseerStepResultsService.getOverseerStepResults(overseerAssesment).subscribe({ + next: () => { + for (const oa of this.overseerAssessments) { + for (const result of oa.stepResultsCache.currentValues) { + result.overseerStep = this.task.definition.overseerStepsCache.currentValues.find( + (step) => step.id === result.overseerStepId, + ); + } + } + this.loadingAssessments.delete(overseerAssesment.id); + }, + error: (error) => { + console.error(error); + this.loadingAssessments.delete(overseerAssesment.id); + }, + }); + } +} diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee index f70113800c..a5d9df4511 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee @@ -25,7 +25,7 @@ angular.module('doubtfire.projects.states.dashboard.directives.task-dashboard', # Is the current user a tutor? $scope.tutor = $stateParams.tutor # the ways in which the dashboard can be viewed - $scope.dashboardViews = ["details", "submission", "task", "similarities"] + $scope.dashboardViews = ["details", "submission", "task", "similarities", "overseer"] # set the current dashboard view to details by default updateCurrentView = -> diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html index df91328f92..fc861e5b34 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html @@ -16,6 +16,10 @@ + + + + diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html index 16d998bc0a..45893297a0 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.tpl.html @@ -2,7 +2,9 @@
    {{task.definition.name}} - {{task.definition.name}} + {{task.definition.name}} + @@ -94,6 +99,9 @@
    +
    + +
    diff --git a/src/app/projects/states/dashboard/selected-task.service.ts b/src/app/projects/states/dashboard/selected-task.service.ts index 204714694e..3385019a77 100644 --- a/src/app/projects/states/dashboard/selected-task.service.ts +++ b/src/app/projects/states/dashboard/selected-task.service.ts @@ -10,6 +10,7 @@ export enum DashboardViews { similarity, staff_notes, discussion_prompts, + overseer, } @Injectable({ @@ -67,6 +68,10 @@ export class SelectedTaskService { this.currentView$.next(DashboardViews.staff_notes); } + public showOverseerReports() { + this.currentView$.next(DashboardViews.overseer); + } + public showDiscussionPrompts() { this.currentView$.next(DashboardViews.discussion_prompts); } diff --git a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.html b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.html index d6d344fc06..4feda189a2 100644 --- a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.html +++ b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.html @@ -1,15 +1,49 @@ -
    -
    - -
    -
    -
    {{ comment.text }}
    - - -
    +
    + +
    +
    + +
    + @if (comment.overseerStatus === 'pre_queued') { + Tests In Progress + } @else if (comment.overseerStatus === 'passed') { + Tests Passed {{ comment.overseerPassedSteps }} / {{ comment.overseerTotalSteps }} + } @else if (comment.overseerStatus === 'failed') { + Tests Failed {{ comment.overseerPassedSteps }} / {{ comment.overseerTotalSteps }} + }
    - + +
    + + @if (comment.overseerStatus === 'passed') { + check_circle + } @else if (comment.overseerStatus === 'failed') { + highlight_off_outline + } @else if (comment.overseerStatus === 'pre_queued') { + + } + + @if (comment.overseerStatus !== 'pre_queued') { + + }
    diff --git a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.scss b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.scss index 816d3724e7..e69de29bb2 100644 --- a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.scss +++ b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.scss @@ -1,56 +0,0 @@ -div { - width: 100%; -} - -p { - color: #2c2c2c; - text-align: center; -} - -hr { - width: 100%; -} - -.hr-fade { - background: linear-gradient(to right, transparent, #9696969d, transparent); - width: 100%; - margin-top: 1px; -} - -.fade-text { - color: #9696969d; - opacity: 0.8; -} - -.hr-text { - margin: 0; - line-height: 1em; - position: relative; - outline: 0; - border: 0; - color: black; - text-align: center; - height: 1.5em; - opacity: 0.8; - &:before { - content: ""; - background: linear-gradient(to right, transparent, #9696969d, transparent); - position: absolute; - left: 0; - top: 50%; - width: 100%; - height: 1px; - } - &:after { - content: attr(data-content); - position: relative; - display: inline-block; - color: black; - - padding: 0 0.5em; - line-height: 1.5em; - - color: #9696969d; - background-color: #fff; - } -} diff --git a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts index ed2e404b26..a57f866649 100644 --- a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts @@ -1,8 +1,11 @@ -import { Component, OnInit, Input, Inject } from '@angular/core'; -import { TaskSubmissionService, TaskAssessmentResult } from 'src/app/common/services/task-submission.service'; -import { TaskAssessmentModalService } from 'src/app/common/modals/task-assessment-modal/task-assessment-modal.service'; -import { Task } from 'src/app/api/models/doubtfire-model'; -import { AlertService } from 'src/app/common/services/alert.service'; +import {Component, OnInit, Input, Inject} from '@angular/core'; +import { + TaskSubmissionService, + TaskAssessmentResult, +} from 'src/app/common/services/task-submission.service'; +import {TaskAssessmentModalService} from 'src/app/common/modals/task-assessment-modal/task-assessment-modal.service'; +import {Task} from 'src/app/api/models/doubtfire-model'; +import {AlertService} from 'src/app/common/services/alert.service'; export interface User { id: number; @@ -23,6 +26,11 @@ export interface TaskAssessmentComment { recipient_read_time?: Date; // new fields that extend regular Comment Interface. TODO: create a separate Comment entity and extend it. assessment_result?: TaskAssessmentResult; + overseerAssessmentId: number; + overseerPassedSteps: number; + overseerTotalSteps: number; + overseerInProgress: boolean; + overseerStatus: string; } @Component({ @@ -53,12 +61,12 @@ export class TaskAssessmentCommentComponent implements OnInit { return this.comment.assessment_result.assessment_output; } - showTaskAssessmentResult() { - this.modalService.show(this.task); + showTaskAssessmentResult(overseerAssessmentId?: number) { + this.modalService.show(this.task, overseerAssessmentId); } scroll(el: HTMLElement) { - el.scrollIntoView({ behavior: 'smooth' }); + el.scrollIntoView({behavior: 'smooth'}); } update(): void { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html index 0e5c521bcb..fb78832932 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html @@ -1,12 +1,19 @@
    - - Automation Enabled - +
    + + Automation Enabled + +
    + + You can add or modify Overseer steps while keeping this unchecked and use the test submission + feature. Once everything is ready, enable automation to apply it to all student submissions. + +
    Docker Image @@ -18,10 +25,6 @@ Docker image for Overseer - - upload_file Test Submission -
    + +
    + +@if (taskDefinition.overseerImageId) { + @if (!taskDefinitionHasChanges()) { +
    +
    + @if (this.selectedOverseerStep) { + + + } +
    +
    + + + +
    +
    Overseer Steps
    + @if (!newOverseerStep) { + + } +
    +
    + @for (step of overseerSteps; track step.id) { +
    + drag_indicator + {{ step.sortOrder }}. {{ step.name ?? 'Untitled Step' }} +
    + } + @if (newOverseerStep) { +
    + + {{ newOverseerStep.sortOrder }}. {{ newOverseerStep.name || 'Untitled Step' }} +
    + } + + +
    +
    + + @if (selectedOverseerStep) { + + + +
    + + Step Name + + Visible to staff only + + + Description + + Visible to staff only + +
    + + + Step Type + + Custom Script + Input/Output + + + + @if (selectedOverseerStep.stepType === 'output_diff') { +
    +
    + + Script Input File + + + (none) + @for (file of taskDefinition.overseerResourceFiles; track file) { + {{ file }} + } + + The selected file will be passed as standard input to the program when it + runs. + + + + Show input file to student + +
    +
    + + Expected Output File + + @for (file of taskDefinition.overseerResourceFiles; track file) { + {{ file }} + } + + Program output must exactly match this file to pass. + + + Show expected output file to student + +
    + Partial Output Comparison +
    + + If enabled, test passes if the expected output appears anywhere in the + student's output. Otherwise, only exact matches pass. + +
    +
    + + } + +
    +
    Execution Script
    + + Language + + @for (language of getLanguages; track language) { + {{ + language.id ?? language.aliases?.[0] ?? language.id + }} + } + + Visual use only + +
    + + + +
    + + + @if (selectedOverseerStep.stepType === 'status_check') { + This step passes only if the script exits with status 0. Any non-zero exit code + marks the step as failed. + } @else if (selectedOverseerStep.stepType === 'output_diff') { + The script output is compared against the expected output. If noisy warnings + cause failures, move that logic into a separate step. + } + +
    + + Time Limit (s) + + How long the code can execute for before overseer automatically kills the + process. A timeout will result in a failed test (Exit status 124) + +
    +
    + +
    + Halt on success + + @if (selectedOverseerStep.haltOnSuccess) { + + Status on Success + + No Change + @for (status of statusKeys; track status) { + {{ statusName(status) }} + } + + + } +
    +
    + +
    + +
    + + Halt on failure + + @if (selectedOverseerStep.haltOnFailure) { + + + Status on Fail + + No Change + @for (status of statusKeys; track status) { + {{ statusName(status) }} + } + + + } +
    +
    +
    + + +
    + + + Test Name + + Shown to student in overseer report + + + Description + + Shown to student in overseer report + +
    + + Feedback message + + Feedback to provide to the student if the task failed. You can leave this blank + and a default will message will be used instead. + + + +
    + Enabled +
    + + If disabled, this step will not run and will not appear in the Overseer report for + students. + +
    + +
    + Show output +
    + + When enabled, students can see this step’s standard output, including script + output, program output, and compile errors. + +
    +
    +
    + } @else { +
    + No steps selected + tab_unselected +
    + } +
    +
    + } @else { +
    + Please save the task definition before configuring the overseer steps. +
    + } +} diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.scss b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.scss index e69de29bb2..ff10c528b0 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.scss +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.scss @@ -0,0 +1,50 @@ +.example-list { + width: 300px; + max-width: 100%; + border: solid 1px #ccc; + min-height: 50px; + height: 100%; + display: block; + background: white; + // border-radius: 4px; + overflow: hidden; +} + +.example-box { + padding: 20px 10px; + border-bottom: solid 1px #ccc; + height: 50px; + color: rgba(0, 0, 0, 0.87); + display: flex; + flex-direction: row; + align-items: center; + // justify-content: space-between; + box-sizing: border-box; + cursor: pointer; + background: white; + font-size: 14px; + font-family: sans-serif; + user-select: none; +} + +.cdk-drag-preview { + border: none; + box-sizing: border-box; + border-radius: 4px; + box-shadow: + 0 5px 5px -3px rgba(0, 0, 0, 0.2), + 0 8px 10px 1px rgba(0, 0, 0, 0.14), + 0 3px 14px 2px rgba(0, 0, 0, 0.12); +} +.cdk-drag-placeholder { + opacity: 0; +} +.cdk-drag-animating { + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); +} +.example-box:last-child { + border: none; +} +.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder) { + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); +} diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts index ea0f92ba89..07f7eb597c 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts @@ -1,32 +1,52 @@ -import {Component, Input, OnChanges} from '@angular/core'; +import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop'; +import {Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild} from '@angular/core'; import {Observable} from 'rxjs'; import { OverseerAssessment, OverseerImage, OverseerImageService, Task, + TaskService, + TaskStatusEnum, User, UserService, } from 'src/app/api/models/doubtfire-model'; +import {OverseerStep} from 'src/app/api/models/overseer/overseer-step'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; +import {OverseerStepService} from 'src/app/api/services/overseer-step.service'; import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {TaskAssessmentModalService} from 'src/app/common/modals/task-assessment-modal/task-assessment-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {TaskSubmissionService} from 'src/app/common/services/task-submission.service'; import {OverseerScriptEditorModalService} from './overseer-script-editor-modal/overseer-script-editor-modal.service'; - +import * as monaco from 'monaco-editor'; +import {MatSelectChange} from '@angular/material/select'; @Component({ selector: 'f-task-definition-overseer', templateUrl: 'task-definition-overseer.component.html', styleUrls: ['task-definition-overseer.component.scss'], }) -export class TaskDefinitionOverseerComponent implements OnChanges { +export class TaskDefinitionOverseerComponent implements OnChanges, OnInit { @Input() taskDefinition: TaskDefinition; + @ViewChild('editor') editorComponent; + public currentUserTask: Task; + editorOptions = { + theme: 'vs', + language: 'shell', + renderMinimap: false, + + minimap: { + enabled: false, + }, + }; + + public stepType: 'status_check' | 'output_diff' = 'status_check'; + public visibility = 'public'; constructor( private alerts: AlertService, private overseerImageService: OverseerImageService, @@ -36,8 +56,175 @@ export class TaskDefinitionOverseerComponent implements OnChanges { private taskDefinitionService: TaskDefinitionService, private fileDownloaderService: FileDownloaderService, private overseerScriptEditorModal: OverseerScriptEditorModalService, + private overseerStepService: OverseerStepService, + private taskService: TaskService, ) {} + public get statusKeys() { + return this.taskService.statusKeys; + } + + public statusName(status: TaskStatusEnum) { + return this.taskService.statusLabels.get(status); + } + + public selectedOverseerStep: OverseerStep = null; + public newOverseerStep: OverseerStep = null; + + public overseerSteps: OverseerStep[] = []; + + selectStep(step: OverseerStep) { + this.selectedOverseerStep = step; + setTimeout(() => { + const editor = this.editorComponent?._editor; + if (editor) { + editor.revealLine(1); + editor.setScrollPosition({scrollTop: 0}); + } + }); + } + + addStep() { + this.newOverseerStep = new OverseerStep(this.taskDefinition); + this.newOverseerStep.stepType = 'status_check'; + this.newOverseerStep.timeout = 30; + this.newOverseerStep.enabled = true; + this.newOverseerStep.showStdout = true; + this.newOverseerStep.statusOnFailure = 'no_change'; + this.newOverseerStep.statusOnSuccess = 'no_change'; + this.newOverseerStep.commandLanguage = 'shell'; + this.newOverseerStep.runCommand = '#!/bin/bash\n\n'; + this.newOverseerStep.showExpectedOutput = true; + + this.newOverseerStep.sortOrder = this.taskDefinition.overseerStepsCache.currentValues.length; + this.selectedOverseerStep = this.newOverseerStep; + } + + getFeedbackMessagePlaceholder() { + // If the feedback message is blank, this is what will automatically be used + // (If this changes, ensure to update it in AcceptOverseerJob) + switch (this.selectedOverseerStep.stepType) { + case 'status_check': + return 'This test did not complete successfully. Check the output for any errors.'; + case 'output_diff': + return 'Your output did not match the expected result.'; + } + } + + ngOnInit(): void { + this.taskDefinition.overseerStepsCache.values.subscribe((steps) => { + this.overseerSteps = [...steps]; + }); + } + + public get getLanguages() { + return monaco?.languages.getLanguages() ?? []; + } + + onLanguageChange(event: MatSelectChange) { + const value = event.value; + this.editorOptions.language = value; + this.editorOptions = {...this.editorOptions}; + } + + drop(event: CdkDragDrop) { + if (this.newOverseerStep) { + this.alerts.error('Please save changes before re-ordering steps', 3000); + return; + } + moveItemInArray(this.overseerSteps, event.previousIndex, event.currentIndex); + // TODO: open endpoint to update sort orders in a single request + for (let i = 0; i < this.overseerSteps.length; i++) { + const step = this.taskDefinition.overseerStepsCache.get(this.overseerSteps[i].id); + if (step.sortOrder === i) { + // Ignore if no change + continue; + } + step.sortOrder = i; + this.overseerStepService + .update( + { + id: step.id, + unitId: this.unit.id, + taskDefId: this.taskDefinition.id, + }, + { + entity: step, + constructorParams: this.taskDefinition, + }, + ) + .subscribe({ + next: () => { + // console.log('updated!'); + }, + error: (error) => { + this.alerts.error(`Failed to update order of steps: ${error}`, 6000); + }, + }); + } + } + + deleteStep() { + if (this.selectedOverseerStep && this.selectedOverseerStep === this.newOverseerStep) { + this.newOverseerStep = null; + this.selectedOverseerStep = null; + return; + } + this.selectedOverseerStep?.delete(); + this.selectedOverseerStep = null; + } + + saveStep() { + if (!this.selectedOverseerStep.id) { + // this.newOverseerStep.runCommand = this.model.value; + this.overseerStepService + .create( + { + unitId: this.unit.id, + taskDefId: this.taskDefinition.id, + }, + { + entity: this.newOverseerStep, + }, + ) + .subscribe({ + next: (result) => { + this.alerts.success('Added overseer step', 3000); + result.taskDefinition = this.taskDefinition; + this.taskDefinition.overseerStepsCache.add(result); + this.selectStep(result); + this.newOverseerStep = null; + }, + error: (error) => { + console.error(error); + this.alerts.error(error, 3000); + }, + }); + } else { + this.overseerStepService + .update( + { + id: this.selectedOverseerStep.id, + unitId: this.unit.id, + taskDefId: this.taskDefinition.id, + }, + { + entity: this.selectedOverseerStep, + cache: this.taskDefinition.overseerStepsCache, + }, + ) + .subscribe({ + next: (result) => { + this.alerts.success('Saved overseer step', 3000); + }, + error: (error) => { + console.error(error); + this.alerts.error(error, 3000); + }, + }); + } + } + public get overseerEnabled(): boolean { return this.unit.overseerEnabled; } @@ -54,12 +241,21 @@ export class TaskDefinitionOverseerComponent implements OnChanges { return this.userService.currentUser; } - public ngOnChanges() { + public taskDefinitionHasChanges(): boolean { + return this.taskDefinition.hasChanges(this.taskDefinitionService.mapping); + } + + public ngOnChanges(changes: SimpleChanges) { const proj = this.unit.findProjectForUsername(this.currentUser.username); if (proj) { this.currentUserTask = proj.findTaskForDefinition(this.taskDefinition.id); this.hasAnySubmissions(); } + if (changes['taskDefinition']) { + this.taskDefinition.overseerStepsCache.values.subscribe((steps) => { + this.overseerSteps = [...steps]; + }); + } } testSubmission() { @@ -69,7 +265,7 @@ export class TaskDefinitionOverseerComponent implements OnChanges { this.currentUserTask.definition = this.taskDefinition; this.currentUserTask.status = 'ready_for_feedback'; this.currentUserTask.id = this.taskDefinition.id; // set a default id... - this.hasAnySubmissions(); + // this.hasAnySubmissions(); } this.currentUserTask.presentTaskSubmissionModal(this.currentUserTask.status, false, true); From 4f607926e3ac305316a05607fda7f7bff7faec00 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 5 Jan 2026 15:42:12 +1100 Subject: [PATCH 0772/1531] feat: project task planner gantt chart (#1051) * feat: init project plan gatt chart * chore: set compatible version * chore: update gantt chart package * refactor: display task items and map prerequisites * refactor: add task target start and due date * refactor: show prerequisite for tasks in tooltip * refactor: save target and due dates * feat: display task definition dates as baseline items * chore: remove extension * fix: create unique baseline item * refactor: fix timezone issues * refactor: clean up ui buttons * refactor: ensure timeline view shows the earliest task * chore: always show task planner * refactor: rename project plan * refactor: minify ui * chore: confirm changes * feat: allow target grade changes * refactor: display tasks target grade * feat: link to task details * refactor: remove debug * chore: remove old task sliders * refactor: display show date toggle * chore: add curved links * fix: save target dates * chore: reverse prerequisite links * refactor: reset target dates if task is prerequisite for another task * chore: fix gantt chart config * refactor: display warning if prerequisite task ends after dependent task starts * fix: return false if no linked item * refactor: highlight prerequisite conflicts * refactor: move task planner into its own component * refactor: highlight prerequisites on task hover * chore: fix prerequisite conflicts * feat: add status icon to task list * chore: update bar color * feat: display task prerequisites modal * refactor: display dependent tasks * fix: only use target start and end date if unit allows flexible dates * refactor: ensure prerequisites are mapped * chore: only update z-index of lines when hovering over * feat: task planner card for project dashboard * chore: add more details * chore: add tooltip delay * chore: add description heading * chore: add back watch command * refactor: use single endpoint to reset all target dates * chore: add button to redirect to task planner * chore: only show dates in tooltip * refactor: set gantt view dates to latest possible end date * feat: scroll to and highlight selected task item * refactor: remove unused code * refactor: remove unused code * chore: format * refactor: assign gantt config variable * refactor: add oop logic + cleanup duplicated code * fix: convert correct deadline date string * chore: import task planner card --- angular.json | 3 +- package-lock.json | 68 +++ package.json | 2 + src/app/api/models/project.ts | 13 + src/app/api/models/task.ts | 30 +- src/app/api/models/unit.ts | 10 + .../api/services/task-prerequisite.service.ts | 13 + src/app/api/services/task.service.ts | 8 + .../task-dropdown.component.html | 12 +- .../task-date-slider.component.html | 13 +- src/app/doubtfire-angular.module.ts | 36 ++ src/app/doubtfire-angularjs.module.ts | 18 + src/app/doubtfire.states.ts | 5 +- .../progress-dashboard.tpl.html | 5 + .../task-planner-card.component.html | 28 + .../task-planner-card.component.scss | 0 .../task-planner-card.component.ts | 14 + .../states/plan/project-plan.component.html | 35 +- .../states/plan/project-plan.component.scss | 0 .../states/plan/project-plan.component.ts | 63 +- ...planner-prerequisites-modal.component.html | 79 +++ ...planner-prerequisites-modal.component.scss | 0 ...k-planner-prerequisites-modal.component.ts | 39 ++ ...ask-planner-prerequisites-modal.service.ts | 27 + .../task-planner/task-planner.component.html | 129 +++++ .../task-planner/task-planner.component.scss | 18 + .../task-planner/task-planner.component.ts | 544 ++++++++++++++++++ src/styles.scss | 1 + tsconfig.json | 3 +- 29 files changed, 1184 insertions(+), 32 deletions(-) create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.html create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.scss create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts create mode 100644 src/app/projects/states/plan/project-plan.component.scss create mode 100644 src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html create mode 100644 src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.scss create mode 100644 src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts create mode 100644 src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.service.ts create mode 100644 src/app/projects/states/plan/task-planner/task-planner.component.html create mode 100644 src/app/projects/states/plan/task-planner/task-planner.component.scss create mode 100644 src/app/projects/states/plan/task-planner/task-planner.component.ts diff --git a/angular.json b/angular.json index 0d892151bd..6a528bd8c1 100644 --- a/angular.json +++ b/angular.json @@ -49,7 +49,8 @@ "./build/assets/node_modules/codemirror/lib/codemirror.css", "./build/assets/node_modules/codemirror/theme/xq-light.css", "./build/assets/node_modules/nvd3/build/nv.d3.css", - "node_modules/@ctrl/ngx-emoji-mart/picker.css" + "node_modules/@ctrl/ngx-emoji-mart/picker.css", + "node_modules/@worktile/gantt/styles/index.scss" ], "scripts": [ "node_modules/moment/moment.js", diff --git a/package-lock.json b/package-lock.json index 05dae886a7..53f1d09af5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "@uirouter/angularjs": "^1.0.30", "@uirouter/core": "^6.1.0", "@uirouter/rx": "^1.0.0", + "@worktile/gantt": "^18.0.5", "angular": "1.5.11", "angular-calendar": "^0.31.1", "angular-filter": "0.5.17", @@ -55,6 +56,7 @@ "es5-shim": "^4.5.12", "file-saver": "^2.0.5", "font-awesome": "~4.7.0", + "html2canvas": "^1.4.1", "html5-qrcode": "^2.3.8", "jquery": "2.1.4", "lodash": "~4.17", @@ -6186,6 +6188,22 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@worktile/gantt": { + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@worktile/gantt/-/gantt-18.0.5.tgz", + "integrity": "sha512-LCcWaFBmeg5u9cVDEmREHdR+qJJHE3Ld4VxdoJpTXfhDkx2f19tp0wMR9MkwOLRwwTCx/5gGJ1kTbz4P0Zfc1Q==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/cdk": ">=17.0.0", + "@angular/common": ">=17.0.0", + "@angular/core": ">=17.0.0", + "date-fns": ">=2.0.0", + "rxjs": "^6.5.0 || ^7.0.0" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "dev": true, @@ -7235,6 +7253,15 @@ "node": ">= 0.4" } }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "funding": [ @@ -8704,6 +8731,15 @@ "node": ">= 8" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-loader": { "version": "6.10.0", "dev": true, @@ -8860,6 +8896,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/kossnocorp" @@ -12848,6 +12885,19 @@ "dev": true, "license": "MIT" }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "license": "MIT", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/html5-qrcode": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/html5-qrcode/-/html5-qrcode-2.3.8.tgz", @@ -21515,6 +21565,15 @@ "node": ">=0.10" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/text-table": { "version": "0.2.0", "dev": true, @@ -22306,6 +22365,15 @@ "node": ">= 0.4.0" } }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "license": "MIT", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/uuid": { "version": "3.4.0", "dev": true, diff --git a/package.json b/package.json index d3eeccad5d..4b9234d2b7 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "@uirouter/angularjs": "^1.0.30", "@uirouter/core": "^6.1.0", "@uirouter/rx": "^1.0.0", + "@worktile/gantt": "^18.0.5", "angular": "1.5.11", "angular-calendar": "^0.31.1", "angular-filter": "0.5.17", @@ -74,6 +75,7 @@ "es5-shim": "^4.5.12", "file-saver": "^2.0.5", "font-awesome": "~4.7.0", + "html2canvas": "^1.4.1", "html5-qrcode": "^2.3.8", "jquery": "2.1.4", "lodash": "~4.17", diff --git a/src/app/api/models/project.ts b/src/app/api/models/project.ts index df3c3cda26..2afef9ffa2 100644 --- a/src/app/api/models/project.ts +++ b/src/app/api/models/project.ts @@ -537,4 +537,17 @@ export class Project extends Entity { const httpClient = AppInjector.get(HttpClient); return httpClient.get(this.tasksIncludedInPortfolioUrl()); } + + public resetTargetDates(): Observable { + const projectService: ProjectService = AppInjector.get(ProjectService); + return projectService.update( + { + projectId: this.id, + }, + { + endpointFormat: '/projects/:projectId:/reset_target_dates', + entity: this, + }, + ); + } } diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index d624a8285d..e2d85bf61b 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -53,6 +53,9 @@ export class Task extends Entity { pinned: boolean = false; + targetStartDate: Date; + targetDueDate: Date; + public topWeight: number = 0; public readonly commentCache: EntityCache = new EntityCache(); @@ -167,7 +170,9 @@ export class Task extends Entity { } public localDueDate(): Date { - if (this.dueDate) { + if (this.targetDueDate && this.unit.allowFlexibleDates) { + return this.targetDueDate; + } else if (this.dueDate) { return this.dueDate; } else { return this.definition.localDueDate(); @@ -236,6 +241,25 @@ export class Task extends Entity { ); } + public saveTargetDates(startDate: Date | string, dueDate: Date | string): Observable { + const taskService: TaskService = AppInjector.get(TaskService); + + return taskService.update( + { + projectId: this.project.id, + taskDefId: this.definition.id, + }, + { + endpointFormat: '/projects/:projectId:/task_def_id/:taskDefId:/target_dates', + entity: this, + body: { + target_start_date: startDate, + target_due_date: dueDate, + }, + }, + ); + } + /** * Calculate the time between two dates * @@ -297,7 +321,9 @@ export class Task extends Entity { } public get startDate(): Date { - if (this.extensions < 0) { + if (this.targetStartDate && this.unit.allowFlexibleDates) { + return this.targetStartDate; + } else if (this.extensions < 0) { // If the task has an extension, the start date is the due date minus the extension return MappingFunctions.addWeeks(this.definition.startDate, this.extensions); } else { diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index 0caa668085..452bbceb98 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -34,6 +34,7 @@ import {HttpClient, HttpParams} from '@angular/common/http'; import {TaskPrerequisiteService} from '../services/task-prerequisite.service'; import {MarkingSession} from './marking-session'; import {MarkingSessionService} from '../services/marking-session.service'; +import {TaskPrerequisite} from './task-prerequisite'; export class Unit extends Entity { id: number; @@ -721,4 +722,13 @@ export class Unit extends Entity { }), ); } + + public get taskDefinitionsPrerequisitesUrl(): string { + return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.id}/task_prerequisites`; + } + + public getTaskPrerequisites(): Observable { + const prerequisiteService = AppInjector.get(TaskPrerequisiteService); + return prerequisiteService.getUnitPrerequisites(this.id); + } } diff --git a/src/app/api/services/task-prerequisite.service.ts b/src/app/api/services/task-prerequisite.service.ts index d3906860f8..ffb323b0d1 100644 --- a/src/app/api/services/task-prerequisite.service.ts +++ b/src/app/api/services/task-prerequisite.service.ts @@ -9,6 +9,8 @@ export class TaskPrerequisiteService extends CachedEntityService { keys: 'dueDate', toEntityFn: MappingFunctions.mapDateToEndOfDay, }, + { + keys: 'targetStartDate', + toEntityFn: MappingFunctions.mapDateToEndOfDay, + }, + { + keys: 'targetDueDate', + toEntityFn: MappingFunctions.mapDateToEndOfDay, + }, 'extensions', 'scormExtensions', { diff --git a/src/app/common/header/task-dropdown/task-dropdown.component.html b/src/app/common/header/task-dropdown/task-dropdown.component.html index c5d1d763d4..cc8cec968f 100644 --- a/src/app/common/header/task-dropdown/task-dropdown.component.html +++ b/src/app/common/header/task-dropdown/task-dropdown.component.html @@ -63,13 +63,11 @@ > Dashboard - @if (currentProject.unit.allowFlexibleDates) { - - - } + + + } +
    @if (editMode) { diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 86b5fc459d..33c8db369b 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -300,10 +300,15 @@ import {MarkingSessionService} from './api/services/marking-session.service'; import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component'; import {OverseerScriptEditorModalComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component'; import {UploadGradesComponent} from './units/states/portfolios/upload-grades/upload-grades.component'; +import {GANTT_GLOBAL_CONFIG, GanttLinkLineType, NgxGanttModule} from '@worktile/gantt'; import {DiscussionPromptService} from './api/services/discussion-prompt.service'; import {DiscussionPromptsComponent} from './projects/states/discussion-prompts/discussion-prompts.component'; import {TaskDefinitionDiscussionPromptsComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component'; import {DiscussionPromptsViewComponent} from './projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component'; +import {TaskPlannerComponent} from './projects/states/plan/task-planner/task-planner.component'; +import {TaskPlannerPrerequisitesModalComponent} from './projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component'; +import {TaskPlannerPrerequisitesModalService} from './projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.service'; +import {TaskPlannerCardComponent} from './projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component'; import {OverseerStepService} from './api/services/overseer-step.service'; import {TaskOverseerReportComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component'; import {OverseerStepResultService} from './api/services/overseer-step-result.service'; @@ -321,6 +326,31 @@ const MY_DATE_FORMAT = { }, }; +const GANTT_CHART_CONFIG = { + provide: GANTT_GLOBAL_CONFIG, + useValue: { + // locale: 'en-US', + dateFormat: { + // timeZone: 'UTC', + weekStartsOn: 1, + week: 'w', + year: 'yyyy', + month: 'MMMM', + yearMonth: 'yyyy MMM', + yearQuarter: 'yyyy', + }, + linkOptions: { + showArrow: true, + lineType: GanttLinkLineType.curve, + }, + styleOptions: { + // lineHeight: '25', + // barHeight: '23', + // headerHeight: '50px', + }, + }, +}; + @NgModule({ // Components we declare declarations: [ @@ -466,6 +496,9 @@ const MY_DATE_FORMAT = { DiscussionPromptsComponent, TaskDefinitionDiscussionPromptsComponent, DiscussionPromptsViewComponent, + TaskPlannerComponent, + TaskPlannerCardComponent, + TaskPlannerPrerequisitesModalComponent, TaskOverseerReportComponent, ], providers: [ @@ -557,6 +590,8 @@ const MY_DATE_FORMAT = { TaskPrerequisiteService, MarkingSessionService, DiscussionPromptService, + GANTT_CHART_CONFIG, + TaskPlannerPrerequisitesModalService, OverseerStepService, OverseerStepResultService, ], @@ -622,6 +657,7 @@ const MY_DATE_FORMAT = { MatDialogModuleNew, CalendarModule.forRoot({provide: CalendarDateAdapter, useFactory: adapterFactory}), CodeEditorModule.forRoot(), + NgxGanttModule, MatSidenavModule, MonacoEditorModule.forRoot(), ], diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 8d0fee5456..40e8930490 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -233,6 +233,9 @@ import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/dir import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component'; import {TaskSimilarityViewComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component'; import {UploadGradesComponent} from './units/states/portfolios/upload-grades/upload-grades.component'; +import {ProjectPlanComponent} from './projects/states/plan/project-plan.component'; +import {TaskPlannerComponent} from './projects/states/plan/task-planner/task-planner.component'; +import {TaskPlannerCardComponent} from './projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component'; import {TaskOverseerReportComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component'; export const DoubtfireAngularJSModule = angular @@ -577,6 +580,21 @@ DoubtfireAngularJSModule.directive( downgradeComponent({component: UploadGradesComponent}), ); +DoubtfireAngularJSModule.directive( + 'fProjectPlan', + downgradeComponent({component: ProjectPlanComponent}), +); + +DoubtfireAngularJSModule.directive( + 'fTaskPlanner', + downgradeComponent({component: TaskPlannerComponent}), +); + +DoubtfireAngularJSModule.directive( + 'fTaskPlannerCard', + downgradeComponent({component: TaskPlannerCardComponent}), +); + DoubtfireAngularJSModule.directive( 'fTaskOverseerReport', downgradeComponent({component: TaskOverseerReportComponent}), diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index 01b722864a..f1710f6b54 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -429,8 +429,11 @@ const SuccessCloseState: NgHybridStateDeclaration = { const projectPlanState: NgHybridStateDeclaration = { name: 'project/plan', parent: 'projects/index', - url: '/plan', + url: '/plan?:taskDef?', component: ProjectPlanComponent, + params: { + taskDef: {value: null, squash: true, dynamic: true}, + }, // views: { // main: { // // Main body links to angular component diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.tpl.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.tpl.html index 93069ef71b..b5859c8b2a 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.tpl.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.tpl.html @@ -5,6 +5,11 @@

    +
    +
    + +
    +
    diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.html new file mode 100644 index 0000000000..da584e5670 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.html @@ -0,0 +1,28 @@ + + + Plan Your Tasks + +

    + The Task Planner shows a timeline of your tasks, their due dates, and prerequisite + relationships. Use it to plan when to start and submit tasks, ensuring prerequisites are + completed early so you have time for feedback. +

    + @if (unit.allowFlexibleDates) { +

    + You can set your own start and target dates. Be mindful of each task’s + Feedback Deadline — submissions after this date will not be checked. Aim + to finish at least one week before the deadline, especially if you are targeting a higher + grade. +

    + } +
    +
    + + + +
    diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.scss b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts new file mode 100644 index 0000000000..3af5379eec --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts @@ -0,0 +1,14 @@ +import {Component, Input} from '@angular/core'; +import {Project} from 'src/app/api/models/project'; + +@Component({ + selector: 'f-task-planner-card', + templateUrl: './task-planner-card.component.html', + styleUrl: './task-planner-card.component.scss', +}) +export class TaskPlannerCardComponent { + @Input() project: Project; + public get unit() { + return this.project?.unit; + } +} diff --git a/src/app/projects/states/plan/project-plan.component.html b/src/app/projects/states/plan/project-plan.component.html index d8f43331cb..cf49f02ec0 100644 --- a/src/app/projects/states/plan/project-plan.component.html +++ b/src/app/projects/states/plan/project-plan.component.html @@ -1,13 +1,34 @@
    -

    Plan Your Tasks

    +

    Task Planner

    - View and adjust the due dates of tasks. Remember to leave time to get and respond to feedback. + @if (unit.allowFlexibleDates) { + View and adjust the due dates for your tasks. Remember to leave time to get and respond to + feedback. + } @else { + View the task deadlines for your project, so you can organise your work and ensure you meet + all submission requirements on time. + } +

    +

    + Click on a task in the timeline to see how it connects to other tasks. This will show you which + tasks must be completed before it, and which tasks depend on it being completed first.

    - +
    -
    - @for (taskDef of taskDefs(); track $index) { - - } +
    +
    + + Target Grade + + @for (grade of gradeValues; track grade) { + {{ gradeString(grade) }} + } + +
    +
    diff --git a/src/app/projects/states/plan/project-plan.component.scss b/src/app/projects/states/plan/project-plan.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/plan/project-plan.component.ts b/src/app/projects/states/plan/project-plan.component.ts index c3002f3026..d1a9194f75 100644 --- a/src/app/projects/states/plan/project-plan.component.ts +++ b/src/app/projects/states/plan/project-plan.component.ts @@ -1,16 +1,44 @@ -import {Component} from '@angular/core'; +import {Component, OnInit, ViewChild} from '@angular/core'; +import {MatSelectChange} from '@angular/material/select'; +import {Project, ProjectService} from 'src/app/api/models/doubtfire-model'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GradeService} from 'src/app/common/services/grade.service'; import {GlobalStateService} from '../index/global-state.service'; -import { Project, TaskDefinition } from 'src/app/api/models/doubtfire-model'; +import {TaskPlannerComponent} from './task-planner/task-planner.component'; @Component({ selector: 'f-project-plan', templateUrl: 'project-plan.component.html', - // styleUrls: ['project-plan.component.scss'] + styleUrls: ['project-plan.component.scss'], }) -export class ProjectPlanComponent { +export class ProjectPlanComponent implements OnInit { public project: Project; - constructor(private globalStateService: GlobalStateService) { + @ViewChild(TaskPlannerComponent) planner!: TaskPlannerComponent; + + public get unit() { + return this.project?.unit; + } + + public get gradeValues() { + return this.gradeService.gradeValues; + } + + public get gradeAcronyms() { + return this.gradeService.gradeAcronyms; + } + + public gradeString(grade: number) { + return this.gradeService.grades[grade]; + } + + constructor( + private globalStateService: GlobalStateService, + private gradeService: GradeService, + private projectService: ProjectService, + private alertService: AlertService, + ) { this.globalStateService.currentViewAndEntitySubject$.subscribe((viewAndEntity) => { if (viewAndEntity.viewType === 'PROJECT' && viewAndEntity.entity) { this.project = viewAndEntity.entity as Project; @@ -18,13 +46,26 @@ export class ProjectPlanComponent { }); } - public taskDefs(): TaskDefinition[] { - if (!this.project || !this.project.unit.taskDefinitions) { - return []; - } + public selectedTargetGrade: number; + + ngOnInit(): void { + this.selectedTargetGrade = this.project.targetGrade; + } + + onTargetGradeChange(event: MatSelectChange) { + const previousTargetGrade = this.project.targetGrade; + this.project.targetGrade = event.value; - return this.project.unit.taskDefinitions.filter((taskDef) => { - return taskDef.targetGrade <= this.project.targetGrade; + this.projectService.update(this.project).subscribe({ + next: () => { + this.alertService.success(`Succesfully updated target grade`, 2000); + this.planner.refreshItems(); + }, + error: (error) => { + this.project.targetGrade = previousTargetGrade; + this.selectedTargetGrade = previousTargetGrade; + this.alertService.error(`Failed to update target grade: ${error}`, 6000); + }, }); } } diff --git a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html new file mode 100644 index 0000000000..5ea71774fd --- /dev/null +++ b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html @@ -0,0 +1,79 @@ + + + + {{ taskDefinition.abbreviation }} {{ taskDefinition.name }} + + + + + Task Description: +

    {{ taskDefinition.description }}

    + + @if (!task.hasPrerequisiteTasks()) { +
    This task has no prerequisites.
    + } + + @if (dependents.length) { + + + Required by + + + + + {{ taskDefinition.abbreviation }} {{ taskDefinition.name }} is a + prerequisite for the following tasks. In some cases, + {{ taskDefinition.abbreviation }} {{ taskDefinition.name }} needs to + reach the Discuss or Complete status, which requires + tutor feedback. Plan ahead to avoid being locked out of submission. + + + + + + + + + + + + + + + + + + +
    Task + {{ link.taskDefinition?.abbreviation }} {{ link.taskDefinition?.name }} + Submission Open + @if (link.taskDefinition.projectTask(project).blockedByPrerequisiteTasks()) { + block_outlined + } @else { + check_circle + } + + Required Status + +
    +
    +
    + } @else { +
    + This task is not a prerequisite for any other tasks. +
    + } +
    +
    diff --git a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.scss b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts new file mode 100644 index 0000000000..54f2aaadf0 --- /dev/null +++ b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts @@ -0,0 +1,39 @@ +import {Component, Inject, Input, OnInit} from '@angular/core'; +import {MAT_DIALOG_DATA} from '@angular/material/dialog'; +import {MatTableDataSource} from '@angular/material/table'; +import {Project} from 'src/app/api/models/project'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {TaskPrerequisite} from 'src/app/api/models/task-prerequisite'; + +export interface TaskPlannerPrerequisitesModalData { + taskDefinition: TaskDefinition; + project: Project; + dependents: TaskPrerequisite[]; +} + +@Component({ + selector: 'f-task-planner-prerequisites-modal', + templateUrl: './task-planner-prerequisites-modal.component.html', + styleUrl: './task-planner-prerequisites-modal.component.scss', +}) +export class TaskPlannerPrerequisitesModalComponent implements OnInit { + @Input() taskDefinition: TaskDefinition; + @Input() project: Project; + @Input() dependents: TaskPrerequisite[]; + + public dataSource = new MatTableDataSource(); + public displayedColumns: string[] = ['task-definition', 'current-status', 'required-status']; + + public get task() { + return this.project?.findTaskForDefinition(this.taskDefinition?.id); + } + + constructor(@Inject(MAT_DIALOG_DATA) public data: TaskPlannerPrerequisitesModalData) {} + + ngOnInit(): void { + this.taskDefinition = this.data.taskDefinition; + this.project = this.data.project; + this.dependents = this.data.dependents; + this.dataSource.data = this.dependents; + } +} diff --git a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.service.ts b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.service.ts new file mode 100644 index 0000000000..4f12f4fd1f --- /dev/null +++ b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.service.ts @@ -0,0 +1,27 @@ +import {Injectable} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import {Project, TaskDefinition} from 'src/app/api/models/doubtfire-model'; +import { + TaskPlannerPrerequisitesModalComponent, + TaskPlannerPrerequisitesModalData, +} from './task-planner-prerequisites-modal.component'; +import {TaskPrerequisite} from 'src/app/api/models/task-prerequisite'; + +@Injectable({ + providedIn: 'root', +}) +export class TaskPlannerPrerequisitesModalService { + constructor(public dialog: MatDialog) {} + + public show(project: Project, taskDefinition: TaskDefinition, dependents: TaskPrerequisite[]) { + this.dialog.open( + TaskPlannerPrerequisitesModalComponent, + { + data: {taskDefinition, project, dependents}, + width: '100%', + maxWidth: '900px', + panelClass: 'overflow-y-auto', + }, + ); + } +} diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.html b/src/app/projects/states/plan/task-planner/task-planner.component.html new file mode 100644 index 0000000000..025da92aa5 --- /dev/null +++ b/src/app/projects/states/plan/task-planner/task-planner.component.html @@ -0,0 +1,129 @@ +
    +
    + Show Task Dates +
    + @if (unit.allowFlexibleDates) { +
    + + +
    + } +
    + + + + +
    +
    + +
    + {{ item.title }} +
    +
    + +
    +
    +
    + + @if (showDatesColumn) { + + + {{ toDateString(item.start) }} + + + + + + {{ toDateString(item.end) }} + + + + + + {{ item.task.localDeadlineDate() ? toDateString(item.task.localDeadlineDate()) : 'N/A' }} + + + } + + +
    +
    + @if (unsavedChanges(item)) { + change_circle + } + @if (prerequisiteConflict(item)) { + warning + } @else if (isBlockedByPrerequisite(item)) { + warning + } + @if (isPastFeedbackDeadline(item)) { + dangerous + } + @if (isCloseToFeedbackDeadline(item)) { + query_builder + } +
    + +   {{ item.title }} +
    +
    +
    +
    +
    diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.scss b/src/app/projects/states/plan/task-planner/task-planner.component.scss new file mode 100644 index 0000000000..ddf668e57b --- /dev/null +++ b/src/app/projects/states/plan/task-planner/task-planner.component.scss @@ -0,0 +1,18 @@ +:host ::ng-deep .flexible-dates .gantt-links-overlay svg { + z-index: 999 !important; + pointer-events: none; +} + +:host ::ng-deep .flexible-dates .gantt-links-overlay-main { + height: 1px; + overflow: visible !important; + pointer-events: none; +} + +.gantt-bar { + background-color: var(--bar-bg); +} + +.flash { + transition: background-color 500ms ease-in-out; +} diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.ts b/src/app/projects/states/plan/task-planner/task-planner.component.ts new file mode 100644 index 0000000000..097b0e6b92 --- /dev/null +++ b/src/app/projects/states/plan/task-planner/task-planner.component.ts @@ -0,0 +1,544 @@ +import {Component, Input, OnInit, ViewChild} from '@angular/core'; +import {UIRouter} from '@uirouter/core'; +import { + GanttBaselineItem, + GanttDate, + GanttItem, + GanttLink, + GanttLinkType, + GanttViewOptions, + GanttViewType, + NgxGanttComponent, +} from '@worktile/gantt'; +import {Project} from 'src/app/api/models/project'; +import {Task} from 'src/app/api/models/task'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {TaskPrerequisite} from 'src/app/api/models/task-prerequisite'; +import {TaskPrerequisiteService} from 'src/app/api/services/task-prerequisite.service'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GradeService} from 'src/app/common/services/grade.service'; +import {TaskPlannerPrerequisitesModalService} from './task-planner-prerequisites-modal/task-planner-prerequisites-modal.service'; + +interface TaskGanttItem extends GanttItem { + highlighted?: boolean; + taskDefinition: TaskDefinition; + task: Task; + originalLinks: GanttLink[]; +} + +@Component({ + selector: 'f-task-planner', + templateUrl: './task-planner.component.html', + styleUrl: './task-planner.component.scss', +}) +export class TaskPlannerComponent implements OnInit { + // Show a warning if the task's target end date is within this many days of the feedback deadline + public readonly CLOSE_TO_FEEDBACK_DEADLINE_THRESHOLD = 7; + + @Input() project: Project; + @ViewChild('gantt') ganttComponent: NgxGanttComponent; + + public viewType: GanttViewType = GanttViewType.day; + public viewOptions: GanttViewOptions; + + public allTaskPrerequisites: TaskPrerequisite[]; + public taskPrerequisites: TaskPrerequisite[]; + + public items: TaskGanttItem[] = []; + + // TaskDefinition default dates for reference + public baselineItems: GanttBaselineItem[] = []; + + public animateBackground: boolean = false; + public showDatesColumn: boolean = false; + public overlayLines: boolean = false; + + public get unit() { + return this.project?.unit; + } + + constructor( + private gradeService: GradeService, + private alertService: AlertService, + private confirmationModalService: ConfirmationModalService, + private taskPlannerPrerequisitesModal: TaskPlannerPrerequisitesModalService, + private taskPrerequisiteService: TaskPrerequisiteService, + private router: UIRouter, + ) {} + + public get gradeValues() { + return this.gradeService.gradeValues; + } + + public get gradeAcronyms() { + return this.gradeService.gradeAcronyms; + } + + public gradeString(grade: number) { + return this.gradeService.grades[grade]; + } + + onBarHover(item: TaskGanttItem) { + this.setLinkColors(item, true); + } + + onBarLeave(item: TaskGanttItem) { + this.setLinkColors(item, false); + } + + setLinkColors(item: TaskGanttItem, active: boolean) { + this.overlayLines = active; + + const ganttItem = this.items.find((i) => i.id === item.id); + ganttItem.links.forEach((linkItem) => { + const link = linkItem as GanttLink; + this.toggleLinkOpacity(link, active); + }); + + const prerequisites = this.items.filter((i) => { + const links = i.links; + if (typeof links === 'string') { + return false; + } + + return links.some((l) => typeof l !== 'string' && l.link === item.id); + }); + + prerequisites.forEach((prereq) => { + prereq.links.forEach((linkItem) => { + const link = linkItem as GanttLink; + if (link.link == item.id) { + this.toggleLinkOpacity(link, active); + } + }); + }); + + this.items = [...this.items]; + } + + private toggleLinkOpacity(link: GanttLink, active: boolean) { + const color = link.color as {active: string; default: string}; + + if (!active && !color.default.endsWith('0.1)')) { + // Dim link by lowering alpha + color.default = color.default.slice(0, -2) + '0.1)'; + } else if (active && color.default.endsWith('0.1)')) { + // Restore full opacity + color.default = color.default.slice(0, -4) + '1)'; + } + } + + barClick(item: TaskGanttItem) { + const td = item.taskDefinition; + const prereqs = this.taskPrerequisites.filter((p) => p.prerequisiteId === td.id); + this.taskPlannerPrerequisitesModal.show(this.project, td, prereqs); + } + + private mapPrerequisites() { + for (const prerequisite of this.allTaskPrerequisites) { + prerequisite.taskDefinition = this.unit.taskDefinitions.find( + (td) => td.id === prerequisite.taskDefinitionId, + ); + prerequisite.prerequisite = this.unit.taskDefinitions.find( + (td) => td.id === prerequisite.prerequisiteId, + ); + } + this.allTaskPrerequisites = [...this.allTaskPrerequisites]; + } + + public blockedDependents: Map = new Map(); + + // Check to see if this task is a prerequisite for another task + // If it is, ensure the end date on the task is before the start of its dependent task + prerequisiteConflict(item: TaskGanttItem) { + if (!item.links.length) { + return false; + } + + let isAfterDependentStartDate: boolean = false; + for (const ganttLink of item.links) { + if (typeof ganttLink === 'string') { + continue; + } + + const ganttItem = this.items.find((i) => i.id === ganttLink.link); + if (!ganttItem) { + return false; + } + const diff = this.normalizeDateUTC(item.end) - this.normalizeDateUTC(ganttItem.end); + const color = typeof ganttLink.color === 'string' ? ganttLink.color : ganttLink.color.default; + + if (diff > 0) { + isAfterDependentStartDate = true; + } + + continue; + + if (color === '#0079D8') { + // Ready for feedback + if (diff > 0) { + isAfterDependentStartDate = true; + } + } else if (color === '#31b0d5' || color === '#5BB75B') { + // Discuss or Complete + if (diff >= -7 * 24 * 60 * 60) { + // We need to ensure this task is submitted a week earlier than its dependent so get it in a Discuss state + isAfterDependentStartDate = true; + } + } + } + + return isAfterDependentStartDate; + } + + isBlockedByPrerequisite(item: TaskGanttItem) { + const prerequisites = this.items.filter((i) => { + const links = i.links; + if (typeof links === 'string') { + return false; + } + + return links.some((l) => typeof l !== 'string' && l.link === item.id); + }); + + for (const link of prerequisites) { + if (this.prerequisiteConflict(link)) { + const diff = this.normalizeDateUTC(link.end) - this.normalizeDateUTC(item.end); + if (diff > 0) { + return true; + } + } + } + + return false; + } + + getItemClasses(item: TaskGanttItem): string[] { + const classes: string[] = ['gantt-bar']; + if (this.animateBackground) { + classes.push('flash'); + } + if (item.highlighted) { + classes.push('[--bar-bg:#03c6fc]'); + } else if (this.isPastFeedbackDeadline(item)) { + classes.push('[--bar-bg:#cd3704]', 'text-white'); + } else if (this.isBlockedByPrerequisite(item)) { + classes.push('[--bar-bg:#e88307]', 'text-black'); + } else if (this.isCloseToFeedbackDeadline(item)) { + classes.push('[--bar-bg:#ffc53d]', 'text-black'); + } else { + classes.push('[--bar-bg:#0e467b]', 'text-white'); + } + + return classes; + } + + isPastFeedbackDeadline(item: TaskGanttItem) { + return item.end > item.task.localDeadlineDate().getTime() / 1000; + } + + isCloseToFeedbackDeadline(item: TaskGanttItem) { + if (!this.unit.allowFlexibleDates) { + return false; + } + + const task = item.task; + const diff = + this.normalizeDateUTC(task.localDeadlineDate().getTime() / 1000) - + this.normalizeDateUTC(item.end); + + return diff >= 0 && diff <= this.CLOSE_TO_FEEDBACK_DEADLINE_THRESHOLD * 24 * 60 * 60; + } + + toDateStr = (timestamp: number) => { + const d = new Date(timestamp * 1000); + return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; + }; + + saveTargetDates() { + for (const item of this.items) { + const td = item.taskDefinition; + if (!td) { + continue; + } + if (this.unsavedChanges(item)) { + this.saveTargetDate(item); + } + } + } + + saveTargetDate(item: TaskGanttItem) { + const td = item.taskDefinition; + const task = item.task; + + task.saveTargetDates(this.toDateStr(item.start), this.toDateStr(item.end)).subscribe({ + next: (data) => { + task.targetDueDate = data.targetDueDate; + task.targetStartDate = data.targetStartDate; + item.start = this.normalizeDateUTC(data.targetStartDate.getTime() / 1000); + item.end = this.normalizeDateUTC(data.targetDueDate.getTime() / 1000); + this.items = [...this.items]; + }, + error: (error) => { + this.alertService.error( + `Failed to save target date for ${td.abbreviation}: ${error}`, + 6000, + ); + }, + }); + } + + anyUnsavedChanges() { + return this.items.some((i) => this.unsavedChanges(i)); + } + + confirmSaveTargetDates() { + this.confirmationModalService.show( + 'Save Task Dates?', + `Do you want to save these new target dates for your tasks? You can always reset them to the unit's default later.`, + () => { + this.saveTargetDates(); + }, + ); + } + + confirmResetTargetDates() { + this.confirmationModalService.show( + 'Reset Task Dates?', + `Are you sure you want to reset all target dates to the unit's default? All modified dates will be reset.`, + () => { + this.project.resetTargetDates().subscribe({ + next: (_project) => { + for (const task of this.project.tasks) { + task.targetDueDate = null; + task.targetStartDate = null; + + const item = this.items.find((item) => item.id === task.definition.id.toString()); + + item.start = this.normalizeDateUTC(task.startDate.getTime() / 1000); + item.end = this.normalizeDateUTC(task.localDueDate().getTime() / 1000); + } + this.items = [...this.items]; + }, + error: (error) => { + this.alertService.error(`Failed to reset target dates: ${error}`, 6000); + }, + }); + }, + ); + } + + normalizeDateUTC = (ts: number) => { + const d = new GanttDate(ts * 1000); + // const utc = Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), 0, 0, 0, 0); + return Math.floor(d.getUnixTime()); + }; + + toDateString(timestamp: number | Date) { + const date = timestamp instanceof Date ? timestamp : new Date(timestamp * 1000); + return date.toLocaleDateString('en-AU', { + month: 'short', + day: 'numeric', + // year: '2-digit', + }); + } + + unsavedChanges(item: TaskGanttItem) { + const task = item.task; + const start = this.normalizeDateUTC(task.startDate.getTime() / 1000); + const end = this.normalizeDateUTC(task.localDueDate().getTime() / 1000); + return start !== this.normalizeDateUTC(item.start) || end !== this.normalizeDateUTC(item.end); + } + + getTooltip(item: TaskGanttItem) { + return `${this.toDateString(item.start)} — ${this.toDateString(item.end)}`; + } + + public get earliestStartDate() { + const earliestTaskStartDate = Math.min( + ...this.taskDefs().map((t) => t.startDate.getTime() / 1000), + ); + return Math.floor(Math.min(this.unit.startDate.getTime() / 1000, earliestTaskStartDate)); + } + + public get latestEndDate() { + const latestTaskEndDate = Math.max(...this.taskDefs().map((t) => t.dueDate.getTime() / 1000)); + return Math.floor(Math.max(this.unit.endDate.getTime() / 1000, latestTaskEndDate)); + } + + ngOnInit(): void { + this.viewOptions = { + datePrecisionUnit: 'day', + start: new GanttDate(this.earliestStartDate), + end: new GanttDate(this.latestEndDate), + dragPreviewDateFormat: 'MMM dd', + }; + + this.unit.getTaskPrerequisites().subscribe({ + next: (prereqs) => { + this.allTaskPrerequisites = prereqs; + this.mapPrerequisites(); + for (const prerequisite of this.allTaskPrerequisites) { + prerequisite.taskDefinition.taskPrerequisitesCache.getOrCreate( + prerequisite.id, + this.taskPrerequisiteService, + prerequisite, + ); + } + + for (const td of this.unit.taskDefinitions) { + const prerequisites = td.taskPrerequisitesCache.currentValues; + const definitions = this.unit.taskDefinitions; + for (const prerequisite of prerequisites) { + prerequisite.taskDefinition = definitions.find( + (td) => td.id === prerequisite.taskDefinitionId, + ); + prerequisite.prerequisite = definitions.find( + (td) => td.id === prerequisite.prerequisiteId, + ); + } + } + + this.refreshItems(); + }, + error: (error) => { + this.alertService.error(`Failed to get task prerequisites: ${error}`, 6000); + }, + }); + } + + refreshItems() { + this.taskPrerequisites = this.allTaskPrerequisites.filter((pre) => + this.taskDefs().find((td) => td.id === pre.taskDefinitionId), + ); + + const taskDefinitions = this.taskDefs(); + this.items = []; + + for (const td of taskDefinitions) { + const task = this.project.findTaskForDefinition(td.id); + + const item: TaskGanttItem = { + id: td.id.toString(), + title: `${td.abbreviation} ${td.name}`, + start: this.normalizeDateUTC(task.startDate.getTime() / 1000), + end: this.normalizeDateUTC(task.localDueDate().getTime() / 1000), + expandable: false, + draggable: this.project.unit.allowFlexibleDates, + // color: this.gradeService.gradeColors[td.targetGrade], + expanded: false, + color: '#3333ff', + taskDefinition: td, + task: task, + // progress: 0.5, + originalLinks: [], + links: this.taskPrerequisites + .filter((p) => p.prerequisiteId === td.id) + // .filter((p) => p.taskDefinitionId === td.id) + .map((p) => { + let color: string; + + switch (p.taskStatus) { + case 'ready_for_feedback': + color = 'rgba(0, 121, 216, 0.1)'; + break; + case 'complete': + color = 'rgba(91, 183, 91, 0.1)'; + break; + case 'discuss': + color = 'rgba(49, 176, 213, 0.1)'; + break; + case 'demonstrate': + color = 'rgba(49, 176, 213, 0.1)'; + break; + default: + color = 'gray'; + } + const link: GanttLink = { + type: GanttLinkType.fs, + link: p.taskDefinitionId.toString(), + // link: p.prerequisiteId.toString(), + color: { + default: color, + active: color, + }, + }; + + return link; + }), + }; + + // if ( + // item.links.length && + // (this.isCloseToFeedbackDeadline(item) || this.isPastFeedbackDeadline(item)) + // ) { + // const task = this.project.findTaskForDefinition(td.id); + + // item.start = this.normalizeDateUTC(task.startDate.getTime() / 1000); + // item.end = this.normalizeDateUTC(task.localDueDate().getTime() / 1000); + + // // If the task defaults are still invalid, reset them to the task definition default + // if (this.isCloseToFeedbackDeadline(item) || this.isPastFeedbackDeadline(item)) { + // item.start = this.normalizeDateUTC(td.startDate.getTime() / 1000); + // item.end = this.normalizeDateUTC(td.localDueDate().getTime() / 1000); + // } + // } + + const originalItem = {...item}; + item.originalLinks = [...(originalItem.links as GanttLink[])]; + + this.items.push(item); + this.items = [...this.items]; + + // Create baseline item + const baselineItem = {...item}; + baselineItem.start = this.normalizeDateUTC(td.startDate.getTime() / 1000); + baselineItem.end = this.normalizeDateUTC(td.targetDate.getTime() / 1000); + this.baselineItems.push(baselineItem); + this.baselineItems = [...this.baselineItems]; + + // if (this.unsavedChanges(item)) { + // this.saveTargetDate(item); + // } + } + + this.ganttComponent.scrollToToday(); + + if (this.router.globals.params.taskDef) { + const taskItem = this.items.find((item) => item.id === this.router.globals.params.taskDef); + if (taskItem) { + this.ganttComponent.scrollToDate(taskItem.start); + taskItem.highlighted = true; + this.animateBackground = true; + + setTimeout(() => { + const el = document.querySelector(`[data-gantt-id="${taskItem.id}"]`) as HTMLElement; + + el?.scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'nearest', + }); + }); + setTimeout(() => (taskItem.highlighted = false), 1000); + setTimeout(() => (this.animateBackground = false), 2000); + } + this.router.stateService.go( + this.router.globals.current.name, + {taskDef: null}, + {location: 'replace', notify: false, reload: false}, + ); + } + } + + public taskDefs(): TaskDefinition[] { + if (!this.project || !this.project.unit.taskDefinitions) { + return []; + } + + return this.project.unit.taskDefinitions.filter((taskDef) => { + return taskDef.targetGrade <= this.project.targetGrade; + }); + } +} diff --git a/src/styles.scss b/src/styles.scss index 7eec75221c..8b8db3480d 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,5 +1,6 @@ // For more information: https://material.angular.io/guide/theming @use '@angular/material' as mat; +@use '@worktile/gantt/styles/index'; @include mat.core(); diff --git a/tsconfig.json b/tsconfig.json index c1f136d7b7..f062ffbb0f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,8 @@ "typeRoots": ["node_modules/@types"], "lib": ["es2020", "dom", "ES2021.String"], "useDefineForClassFields": false, - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "skipLibCheck": true }, "angularCompilerOptions": { "strictTemplates": false From 6b616fc6de2f58197988c7999005a9abaa79864b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 5 Jan 2026 15:45:22 +1100 Subject: [PATCH 0773/1531] chore(release): 10.0.0-69 --- CHANGELOG.md | 10 ++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bf63acef3..51a2cd51da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-69](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-68...v10.0.0-69) (2026-01-05) + + +### Features + +* attention required task status ([#1061](https://github.com/b0ink/doubtfire-deploy/issues/1061)) ([15365ed](https://github.com/b0ink/doubtfire-deploy/commit/15365ed4f42af790af9a9ae24dae42f041dff1df)) +* display number of stuff notes in tutor discussion ([2674d4e](https://github.com/b0ink/doubtfire-deploy/commit/2674d4e5ade26e5420b87518f4cd9da909ec7246)) +* overseer pipeline ([#1064](https://github.com/b0ink/doubtfire-deploy/issues/1064)) ([7cb8fc7](https://github.com/b0ink/doubtfire-deploy/commit/7cb8fc7471f0402c562fb8a0b87df672ceb22ea3)) +* project task planner gantt chart ([#1051](https://github.com/b0ink/doubtfire-deploy/issues/1051)) ([4f60792](https://github.com/b0ink/doubtfire-deploy/commit/4f607926e3ac305316a05607fda7f7bff7faec00)) + ## [10.0.0-68](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-67...v10.0.0-68) (2025-12-08) diff --git a/package-lock.json b/package-lock.json index 53f1d09af5..ae33639815 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-68", + "version": "10.0.0-69", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-68", + "version": "10.0.0-69", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 4b9234d2b7..33f6f2b521 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-68", + "version": "10.0.0-69", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 6c6c7f9cd1297d0671231c80fbad77b900be5cba Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:44:33 +1100 Subject: [PATCH 0774/1531] chore: allow no expected output file --- .../task-definition-overseer.component.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html index fb78832932..cde5ed4e7e 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html @@ -194,6 +194,7 @@ Expected Output File + (none) @for (file of taskDefinition.overseerResourceFiles; track file) { {{ file }} } From 7ff9fa3380b58320ed1819f04ac8a258c72ada39 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 6 Jan 2026 08:08:24 +1100 Subject: [PATCH 0775/1531] chore: render correct error --- src/app/home/states/lti-dashboard/lti-dashboard.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/home/states/lti-dashboard/lti-dashboard.component.ts b/src/app/home/states/lti-dashboard/lti-dashboard.component.ts index db081c7375..0c0ad93d57 100644 --- a/src/app/home/states/lti-dashboard/lti-dashboard.component.ts +++ b/src/app/home/states/lti-dashboard/lti-dashboard.component.ts @@ -78,7 +78,7 @@ export class LtiDashboardComponent implements AfterViewInit { this.isLoading = false; }, error: (error) => { - this.alertsService.error(error.error, 6000); + this.alertsService.error(error.error || error, 6000); this.isLoading = false; }, }); From a6bdd22ff864e72c679fae1844345963447fdf08 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 6 Jan 2026 09:02:27 +1100 Subject: [PATCH 0776/1531] fix: skip query for unsaved task definition --- .../task-definition-discussion-prompts.component.ts | 5 ++++- .../task-definition-prerequisites.component.ts | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts index 149682d55d..e22072d433 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts @@ -80,12 +80,15 @@ export class TaskDefinitionDiscussionPromptsComponent private fetchDiscussionPrompts() { const taskDefinition = this.taskDefinition; + if (!taskDefinition.id) { + return; + } this.discussionPromptService.loadDiscussionPrompts(null, taskDefinition).subscribe({ next: (data) => { this.dataSource.data = data; }, error: (error) => { - this.alertService.error(`Failed to load discussion promnpts: ${error}`); + this.alertService.error(`Failed to load discussion prompts: ${error}`, 6000); }, }); } diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts index 2528ffcd6d..201e8a35ab 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts @@ -101,6 +101,9 @@ export class TaskDefinitionPrerequisitesComponent implements OnInit, OnChanges { private fetchTaskPrerequisites() { const taskDefinition = this.taskDefinition; + if (!taskDefinition.id) { + return; + } this.taskPrerequisiteService .query( { @@ -127,7 +130,10 @@ export class TaskDefinitionPrerequisitesComponent implements OnInit, OnChanges { this.filterTaskDefs(this.searchCtrl.value ?? ''); }, error: (error) => { - console.error(error); + this.alertService.error( + `Failed to fetch prerequisites for task definition: ${error}`, + 6000, + ); }, }); } From 9317a5477bb27ed59d9c2e29af9e4538c253816c Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 6 Jan 2026 09:13:21 +1100 Subject: [PATCH 0777/1531] chore: remove required fields --- .../task-definition-overseer.component.html | 45 ++----------------- 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html index cde5ed4e7e..87e44b0754 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html @@ -113,35 +113,14 @@ cdkDragDisabled (click)="selectStep(newOverseerStep)" > - {{ newOverseerStep.sortOrder }}. {{ newOverseerStep.name || 'Untitled Step' }}
    } - -
    @if (selectedOverseerStep) { -
    @@ -193,7 +172,7 @@
    Expected Output File - + (none) @for (file of taskDefinition.overseerResourceFiles; track file) { {{ file }} @@ -220,9 +199,6 @@
    - }
    @@ -231,7 +207,6 @@ Language @for (language of getLanguages; track language) { @@ -244,11 +219,6 @@
    - -
    Status on Success - + No Change @for (status of statusKeys; track status) { {{ statusName(status) }} @@ -318,7 +288,7 @@ Status on Fail - + No Change @for (status of statusKeys; track status) { {{ statusName(status) }} @@ -361,15 +331,6 @@ and a default will message will be used instead. -
    Date: Tue, 6 Jan 2026 09:26:42 +1100 Subject: [PATCH 0778/1531] chore(release): 10.0.0-70 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51a2cd51da..6121dce31b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [10.0.0-70](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-69...v10.0.0-70) (2026-01-05) + + +### Bug Fixes + +* skip query for unsaved task definition ([a6bdd22](https://github.com/b0ink/doubtfire-deploy/commit/a6bdd22ff864e72c679fae1844345963447fdf08)) + ## [10.0.0-69](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.0-68...v10.0.0-69) (2026-01-05) diff --git a/package-lock.json b/package-lock.json index ae33639815..2eb60f3bef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.0-69", + "version": "10.0.0-70", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.0-69", + "version": "10.0.0-70", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 33f6f2b521..6b4ad8bb97 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.0-69", + "version": "10.0.0-70", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 6dcfe952f0415fb1327b738137f817a0fcfa0488 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:06:34 +1100 Subject: [PATCH 0779/1531] feat: download staff notes csv (#1062) * feat: download staff notes csv * chore: restore imports --- src/app/api/models/unit.ts | 11 +++++++++ src/app/doubtfire-angular.module.ts | 2 ++ src/app/doubtfire-angularjs.module.ts | 6 +++++ .../download-staff-notes.component.html | 3 +++ .../download-staff-notes.component.scss | 0 .../download-staff-notes.component.ts | 24 +++++++++++++++++++ .../states/portfolios/portfolios.tpl.html | 1 + 7 files changed, 47 insertions(+) create mode 100644 src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html create mode 100644 src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.scss create mode 100644 src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index 452bbceb98..0415a8bda2 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -723,6 +723,17 @@ export class Unit extends Entity { ); } + public get staffNotesCsvDownloadUrl(): string { + return `${AppInjector.get(DoubtfireConstants).API_URL}/csv/units/${this.id}/staff_notes`; + } + + public downloadStaffNotesCsv(): void { + AppInjector.get(FileDownloaderService).downloadFile( + `${AppInjector.get(DoubtfireConstants).API_URL}/csv/units/${this.id}/staff_notes`, + `${this.name}-StaffNotes.csv`, + ); + } + public get taskDefinitionsPrerequisitesUrl(): string { return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.id}/task_prerequisites`; } diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 33c8db369b..16e6c15557 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -305,6 +305,7 @@ import {DiscussionPromptService} from './api/services/discussion-prompt.service' import {DiscussionPromptsComponent} from './projects/states/discussion-prompts/discussion-prompts.component'; import {TaskDefinitionDiscussionPromptsComponent} from './units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component'; import {DiscussionPromptsViewComponent} from './projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component'; +import {DownloadStaffNotesComponent} from './units/states/portfolios/download-staff-notes/download-staff-notes.component'; import {TaskPlannerComponent} from './projects/states/plan/task-planner/task-planner.component'; import {TaskPlannerPrerequisitesModalComponent} from './projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component'; import {TaskPlannerPrerequisitesModalService} from './projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.service'; @@ -497,6 +498,7 @@ const GANTT_CHART_CONFIG = { TaskDefinitionDiscussionPromptsComponent, DiscussionPromptsViewComponent, TaskPlannerComponent, + DownloadStaffNotesComponent, TaskPlannerCardComponent, TaskPlannerPrerequisitesModalComponent, TaskOverseerReportComponent, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index 40e8930490..1fb4868e3c 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -233,6 +233,7 @@ import {PortfolioGradeSelectStepComponent} from './projects/states/portfolio/dir import {PortfolioIncludedTasksComponent} from './projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component'; import {TaskSimilarityViewComponent} from './projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component'; import {UploadGradesComponent} from './units/states/portfolios/upload-grades/upload-grades.component'; +import {DownloadStaffNotesComponent} from './units/states/portfolios/download-staff-notes/download-staff-notes.component'; import {ProjectPlanComponent} from './projects/states/plan/project-plan.component'; import {TaskPlannerComponent} from './projects/states/plan/task-planner/task-planner.component'; import {TaskPlannerCardComponent} from './projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component'; @@ -580,6 +581,11 @@ DoubtfireAngularJSModule.directive( downgradeComponent({component: UploadGradesComponent}), ); +DoubtfireAngularJSModule.directive( + 'fDownloadStaffNotes', + downgradeComponent({component: DownloadStaffNotesComponent}), +); + DoubtfireAngularJSModule.directive( 'fProjectPlan', downgradeComponent({component: ProjectPlanComponent}), diff --git a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html new file mode 100644 index 0000000000..529708f97c --- /dev/null +++ b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html @@ -0,0 +1,3 @@ + diff --git a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.scss b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts new file mode 100644 index 0000000000..eb3e1501bd --- /dev/null +++ b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts @@ -0,0 +1,24 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {Unit} from 'src/app/api/models/unit'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-download-staff-notes', + templateUrl: 'download-staff-notes.component.html', + styleUrl: 'download-staff-notes.component.scss', +}) +export class DownloadStaffNotesComponent implements OnInit { + @Input() unit: Unit; + + constructor(private alertService: AlertService) {} + + public ngOnInit(): void { + if (!this.unit) { + return console.error(`Invalid unit`); + } + } + + public downloadStaffNotesCsv() { + this.unit.downloadStaffNotesCsv(); + } +} diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html index 34d00d5d7f..eaff240d73 100644 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ b/src/app/units/states/portfolios/portfolios.tpl.html @@ -236,6 +236,7 @@

    Mark Portfolios

    rotate="false" >
    +
    -
    -

    You are not enrolled in any {{ externalName.value }} units.

    -

    Contact your unit convenor or tutor to enrol you in a subject.

    -
    + @if (!notEnrolled && projects?.length === 0 && unitRoles?.length === 0) { +
    +

    You are not enrolled in any {{ externalName.value }} units.

    +

    Contact your unit convenor or tutor to enrol you in a subject.

    +
    + }

    Units you teach

    @@ -19,38 +18,38 @@

    Units you teach

    -
    - - - {{ unitRole.unit?.name }} - {{ unitRole.unit?.code }} - - - - - - - {{ unitRole.teachingPeriod?.name || showDate(unitRole.unit.startDate) }} - - - {{ unitRole.role }} - - - - - - -
    + @if (!unitRole.unit.teachingPeriod || unitRole.unit.teachingPeriod?.active) { +
    + + + {{ unitRole.unit?.name }} + {{ unitRole.unit?.code }} + + + + + + + {{ unitRole.teachingPeriod?.name || showDate(unitRole.unit.startDate) }} + + + {{ unitRole.role }} + + + + + + +
    + }
    Enrolled units
    -
    -
    - - - {{ project.unit.name }} - {{ project.unit.code }} - - - - - - - {{ project.unit.teachingPeriod?.name || showDate(project.unit.startDate) }} - - - - - - + @for (project of projects; track project) { +
    + @if (project.unit.isActive) { +
    + + + {{ project.unit.name }} + {{ project.unit.code }} + + + + + + + {{ project.unit.teachingPeriod?.name || showDate(project.unit.startDate) }} + + + + + + +
    + }
    -
    + } + @if (d2lDataMapping.id) { + + } diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html index 210e1be655..092508da3a 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html @@ -132,9 +132,11 @@

    Unit Staff

    (optionSelected)="addSelectedStaff($event.option.value)" [displayWith]="displayStaffName" > - - {{ staff.name }} - + @for (staff of filteredStaff; track staff) { + + {{ staff.name }} + + } diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html index cf4faacbe4..f534b66b97 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html @@ -39,9 +39,11 @@ matTooltipShowDelay="1000" (selectionChange)="updateTaskPrerequisite(link)" > - - {{ state.label }} - + @for (state of stateOptions; track state) { + + {{ state.label }} + + } } } diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html index b5250fe675..63c972facf 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html @@ -54,64 +54,66 @@

    Manage Target Dates

    - - -
    - -
    - - -
    - - Start Date - + +
    + +
    + + +
    + - - - - - - Target Date - + Start Date + + + + + - @if (isStartAfterTarget(td, g)) { - Target date must be after start date - } - - - - -
    - - + > + Target Date + + @if (isStartAfterTarget(td, g)) { + + Target date must be after start date + + } + + +
    +
    + +
    + } diff --git a/src/app/units/states/edit/unit-admin-state.component.html b/src/app/units/states/edit/unit-admin-state.component.html index c0414b2692..ebe4a87ca1 100644 --- a/src/app/units/states/edit/unit-admin-state.component.html +++ b/src/app/units/states/edit/unit-admin-state.component.html @@ -10,76 +10,72 @@ } -
    - - @if (unit) { -
    - -
    +
    + @switch (currentTab.routeSegment) { + @case ('details') { + @if (unit) { +
    + +
    + } } - - - - @if (unit) { -
    -
    -

    Unit Learning Outcomes

    -

    Manage unit outcomes and related feedback templates.

    + @case ('learning-outcomes') { + @if (unit) { +
    +
    +

    Unit Learning Outcomes

    +

    Manage unit outcomes and related feedback templates.

    +
    +
    - -
    + } } - - - - @if (unit) { -
    - -
    + @case ('staff') { + @if (unit) { +
    + +
    + } } -
    - - - @if (unit) { -
    -
    -

    Tutorials

    -

    Manage tutorial streams and classes for this unit.

    + @case ('tutorials') { + @if (unit) { +
    +
    +

    Tutorials

    +

    Manage tutorial streams and classes for this unit.

    +
    +
    - -
    + } } - - - - @if (unit) { -
    - -
    + @case ('students') { + @if (unit) { +
    + +
    + } } -
    - - - @if (unit) { -
    - -
    + @case ('tasks') { + @if (unit) { +
    + +
    + } } -
    - - - @if (unit) { -
    -
    -

    Groups

    -

    Configure group sets and manage team-based activities.

    + @case ('groups') { + @if (unit) { +
    +
    +

    Groups

    +

    Configure group sets and manage team-based activities.

    +
    +
    - -
    + } } - + }
    diff --git a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html index 773d151132..dda733d9bf 100644 --- a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html +++ b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html @@ -60,56 +60,53 @@
    -
    - -
    - @if (task.hasPdf) { - - } @else { -
    - - description_off - -
    - } -
    -
    - - -
    - @if (task.definition.hasTaskSheet) { - - } @else { -
    - - subtitles_off - -
    - } -
    -
    - - -
    - -
    -
    - - -
    - -
    -
    - - -
    - -
    -
    - - -
    -
    +
    + @switch (currentTab) { + @case (InboxDashboardTab.submission) { +
    + @if (task.hasPdf) { + + } @else { +
    + + description_off + +
    + } +
    + } + @case (InboxDashboardTab.taskSheet) { +
    + @if (task.definition.hasTaskSheet) { + + } @else { +
    + + subtitles_off + +
    + } +
    + } + @case (InboxDashboardTab.staffNotes) { +
    + +
    + } + @case (InboxDashboardTab.tutorNotes) { +
    + +
    + } + @case (InboxDashboardTab.similarities) { +
    + +
    + } + @case (InboxDashboardTab.overseer) { +
    + } + }
    } @else {
    diff --git a/src/app/units/task-viewer/task-viewer-state.component.html b/src/app/units/task-viewer/task-viewer-state.component.html index 8cdf71603b..3b54723add 100644 --- a/src/app/units/task-viewer/task-viewer-state.component.html +++ b/src/app/units/task-viewer/task-viewer-state.component.html @@ -1,56 +1,58 @@ -
    - -
    -
    - -
    +@if (unit$ | async; as unit) { +
    + +
    +
    + +
    + +
    +
    + +
    + @if (selectedTaskDefinition$ | async; as selectedTaskDef) { +
    +
    + +
    + +
    + } +
    +
    +
    + +
    +
    - -
    - - -
    -
    -
    - -
    - +
    +
    +
    +
    + +
    +
    - - -
    -
    - -
    - -
    -
    - -
    - -
    - -
    - -
    -
    -
    +} diff --git a/src/main.ts b/src/main.ts index 9fbcaa2373..75742be059 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,4 @@ -import {enableProdMode} from '@angular/core'; +import {enableProdMode, provideZoneChangeDetection} from '@angular/core'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {environment} from 'src/environments/environment'; @@ -8,4 +8,6 @@ if (environment.production) { enableProdMode(); } -platformBrowserDynamic().bootstrapModule(DoubtfireAngularModule); +platformBrowserDynamic().bootstrapModule(DoubtfireAngularModule, { + applicationProviders: [provideZoneChangeDetection()], +}); diff --git a/tsconfig.json b/tsconfig.json index 3a4f21d922..84230f0709 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,18 +16,12 @@ "strict": false, "strictPropertyInitialization": false, "target": "ES2022", - "typeRoots": [ - "node_modules/@types" - ], - "lib": [ - "es2020", - "dom", - "ES2021.String" - ], + "typeRoots": ["node_modules/@types"], "useDefineForClassFields": false, "skipLibCheck": true }, "angularCompilerOptions": { - "strictTemplates": false + "strictTemplates": false, + "typeCheckHostBindings": false } } From 5fd0f3d51fb87dfc6058ff2176c839d25dd52de2 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:03:24 +1000 Subject: [PATCH 0996/1531] chore: ugprade to material 21 --- package-lock.json | 43 ++++++++++++++++++++++--------------------- package.json | 6 +++--- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 465a278d8b..eb369a8db1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,13 +10,13 @@ "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", - "@angular/cdk": "^20.2.14", + "@angular/cdk": "^21.2.9", "@angular/common": "^21.2.11", "@angular/compiler": "^21.2.11", "@angular/core": "^21.2.11", "@angular/forms": "^21.2.11", - "@angular/material": "^20.2.14", - "@angular/material-date-fns-adapter": "^20.2.14", + "@angular/material": "^21.2.9", + "@angular/material-date-fns-adapter": "^21.2.9", "@angular/platform-browser": "^21.2.11", "@angular/platform-browser-dynamic": "^21.2.11", "@angular/router": "^21.2.11", @@ -835,17 +835,18 @@ } }, "node_modules/@angular/cdk": { - "version": "20.2.14", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.2.14.tgz", - "integrity": "sha512-7bZxc01URbiPiIBWThQ69XwOxVduqEKN4PhpbF2AAyfMc/W8Hcr4VoIJOwL0O1Nkq5beS8pCAqoOeIgFyXd/kg==", + "version": "21.2.9", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-21.2.9.tgz", + "integrity": "sha512-0JXsr8f7xjV2815esTSq4+zGqWMa0CyNT/DV1F7lYS6qkYXcFdYUzGcd/WjNL05VKkajkSkWmTi6uyVsOpYdGA==", "license": "MIT", "dependencies": { "parse5": "^8.0.0", "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^20.0.0 || ^21.0.0", - "@angular/core": "^20.0.0 || ^21.0.0", + "@angular/common": "^21.0.0 || ^22.0.0", + "@angular/core": "^21.0.0 || ^22.0.0", + "@angular/platform-browser": "^21.0.0 || ^22.0.0", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -1607,33 +1608,33 @@ } }, "node_modules/@angular/material": { - "version": "20.2.14", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-20.2.14.tgz", - "integrity": "sha512-IbAgV6XLsvmHiJzxycVhcNC1PA4M30qi+ERCOir6cT333Bxm8vDV32gsOjfL52uzG5YRARroPC+8s1XqR2oxeA==", + "version": "21.2.9", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-21.2.9.tgz", + "integrity": "sha512-uU5Sy0rSd4Y4WjqTcrqs3MpfY/Uy5tmDPSAAvwD0y5y4QVOLoV8uhTQDI/nNg2Lh9NoJKvykZE1ITRMvjfRALQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/cdk": "20.2.14", - "@angular/common": "^20.0.0 || ^21.0.0", - "@angular/core": "^20.0.0 || ^21.0.0", - "@angular/forms": "^20.0.0 || ^21.0.0", - "@angular/platform-browser": "^20.0.0 || ^21.0.0", + "@angular/cdk": "21.2.9", + "@angular/common": "^21.0.0 || ^22.0.0", + "@angular/core": "^21.0.0 || ^22.0.0", + "@angular/forms": "^21.0.0 || ^22.0.0", + "@angular/platform-browser": "^21.0.0 || ^22.0.0", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/material-date-fns-adapter": { - "version": "20.2.14", - "resolved": "https://registry.npmjs.org/@angular/material-date-fns-adapter/-/material-date-fns-adapter-20.2.14.tgz", - "integrity": "sha512-/LRtKSP1WOSgbahbeQlagCZoMOQc9VYZqSDSzmhV0xfiNtT6oQD9a5KMbr5LkozJZQnZUoY7QYveTXe4BD8r2Q==", + "version": "21.2.9", + "resolved": "https://registry.npmjs.org/@angular/material-date-fns-adapter/-/material-date-fns-adapter-21.2.9.tgz", + "integrity": "sha512-tZ48ToUMzGkrwRPsUxPElNsw4AHRtDo8wGjyihwPUAlDQRXU8Mx0oszHcceJFWlTeXSy5uK722jS4rOd+c1t0w==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/core": "^20.0.0 || ^21.0.0", - "@angular/material": "20.2.14", + "@angular/core": "^21.0.0 || ^22.0.0", + "@angular/material": "21.2.9", "date-fns": ">2.20.0 <5.0" } }, diff --git a/package.json b/package.json index 8257012b92..4af41c7999 100644 --- a/package.json +++ b/package.json @@ -27,13 +27,13 @@ "author": "", "dependencies": { "@angular/animations": "^21.2.11", - "@angular/cdk": "^20.2.14", + "@angular/cdk": "^21.2.9", "@angular/common": "^21.2.11", "@angular/compiler": "^21.2.11", "@angular/core": "^21.2.11", "@angular/forms": "^21.2.11", - "@angular/material": "^20.2.14", - "@angular/material-date-fns-adapter": "^20.2.14", + "@angular/material": "^21.2.9", + "@angular/material-date-fns-adapter": "^21.2.9", "@angular/platform-browser": "^21.2.11", "@angular/platform-browser-dynamic": "^21.2.11", "@angular/router": "^21.2.11", From 5114f184ed0cd48adaac29465bbc1c4b6ce08777 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:42:55 +1000 Subject: [PATCH 0997/1531] chore: remove client side code to check for feedback --- src/app/api/models/task.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index c66b757b6d..2f65d2bcce 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -989,20 +989,6 @@ export class Task extends Entity { return; } - if (status === 'complete' || status === 'fix_and_resubmit' || status === 'redo') { - if (!this.commentsSinceLatestReadyForFeedback().some((comment) => comment.isManualFeedback)) { - alerts.error( - status === 'complete' - ? 'Feedback must be given before moving this task to Complete' - : status === 'fix_and_resubmit' - ? 'Feedback must be given before moving this task to Fix and Resubmit' - : 'Feedback must be given before moving this task to Redo', - 6000, - ); - return; - } - } - const updateFunc = () => { const taskService: TaskService = AppInjector.get(TaskService); const options: RequestOptions = { From d75ca816ac6b67b7749582f245485120a38ad713 Mon Sep 17 00:00:00 2001 From: Cilly Leang Date: Mon, 4 May 2026 20:44:29 +1000 Subject: [PATCH 0998/1531] fix(dashboard): truncate unit code also remove some leftover testing code, oops --- src/app/dashboard/f-cross-dashboard.component.html | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/app/dashboard/f-cross-dashboard.component.html b/src/app/dashboard/f-cross-dashboard.component.html index a71a34fcf0..dc1a456d7a 100644 --- a/src/app/dashboard/f-cross-dashboard.component.html +++ b/src/app/dashboard/f-cross-dashboard.component.html @@ -2,8 +2,7 @@
    -

    {{ unit.code }}

    -
    +

    {{ unit.code }}

    {{ unit.code }}
    -->
    -
    -
    -
    -

    yop

    -
    -
    -
    From 1ff046bba12d6c59abf619f1cd97316d11e7283b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 5 May 2026 11:17:17 +1000 Subject: [PATCH 0999/1531] chore(release): 10.0.1-36 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abe6841cd3..ce3017c2a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [10.0.1-36](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-35...v10.0.1-36) (2026-05-05) + ### [10.0.1-35](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-34...v10.0.1-35) (2026-04-28) diff --git a/package-lock.json b/package-lock.json index 2d04bf6335..756a0fb315 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.1-35", + "version": "10.0.1-36", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.1-35", + "version": "10.0.1-36", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 03f33ec244..80e455b7b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.1-35", + "version": "10.0.1-36", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From ed2b4b889e651d9dda63cd0a99e97230d2286182 Mon Sep 17 00:00:00 2001 From: Cilly Leang Date: Tue, 5 May 2026 21:38:03 +1000 Subject: [PATCH 1000/1531] style: linting --- src/app/doubtfire-angular.module.ts | 2 +- src/app/doubtfire.states.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index aa6520bfbf..be5d7eeb31 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -324,7 +324,7 @@ import {TutorNotesModalComponent} from './common/modals/tutor-notes-modal/tutor- import {FeedbackAppealModalComponent} from './tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component'; import {ConfirmModerationModalComponent} from './units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component'; import {TaskClaimComponent} from './units/states/tasks/inbox/directives/task-claim/task-claim.component'; -import { CrossDashboardComponent } from './dashboard/f-cross-dashboard.component'; +import {CrossDashboardComponent} from './dashboard/f-cross-dashboard.component'; // See https://stackoverflow.com/questions/55721254/how-to-change-mat-datepicker-date-format-to-dd-mm-yyyy-in-simplest-way/58189036#58189036 const MY_DATE_FORMAT = { diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index b1f88a4415..96a59c79c2 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -15,7 +15,7 @@ import {ProjectPlanComponent} from './projects/states/plan/project-plan.componen import {JplagReportViewerComponent} from './projects/states/jplag/jplag-report-viewer.component'; import {LtiDashboardComponent} from './home/states/lti-dashboard/lti-dashboard.component'; import {LtiUnitLinkComponent} from './home/states/lti-unit-link/lti-unit-link.component'; -import { CrossDashboardComponent } from './dashboard/f-cross-dashboard.component'; +import {CrossDashboardComponent} from './dashboard/f-cross-dashboard.component'; /* * Use this file to store any states that are sourced by angular components. */ From f57ffeb428f9c7b5708ebb7e64a316e40d13090f Mon Sep 17 00:00:00 2001 From: Labibatanjim Date: Thu, 7 May 2026 21:02:48 +1000 Subject: [PATCH 1001/1531] feat: add dashboard list item component --- .../dashboard-list-item.component.html | 8 +++++++ .../dashboard-list-item.component.scss | 22 +++++++++++++++++ .../dashboard-list-item.component.ts | 24 +++++++++++++++++++ src/app/doubtfire-angular.module.ts | 3 ++- 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/app/dashboard/dashboard-list-item.component.html create mode 100644 src/app/dashboard/dashboard-list-item.component.scss create mode 100644 src/app/dashboard/dashboard-list-item.component.ts diff --git a/src/app/dashboard/dashboard-list-item.component.html b/src/app/dashboard/dashboard-list-item.component.html new file mode 100644 index 0000000000..ef5bd52e56 --- /dev/null +++ b/src/app/dashboard/dashboard-list-item.component.html @@ -0,0 +1,8 @@ +
    +

    {{ task?.title }}

    + +
    + Task {{ task?.number }} + {{ task?.type }} +
    +
    \ No newline at end of file diff --git a/src/app/dashboard/dashboard-list-item.component.scss b/src/app/dashboard/dashboard-list-item.component.scss new file mode 100644 index 0000000000..463fb3471c --- /dev/null +++ b/src/app/dashboard/dashboard-list-item.component.scss @@ -0,0 +1,22 @@ +.task-item { + padding: 12px; + border-radius: 8px; + background: white; + cursor: pointer; + margin-bottom: 10px; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); + + &:hover { + background: #f5f5f5; + } +} + +.task-details { + display: flex; + justify-content: space-between; + font-size: 12px; +} + +.task-type { + font-weight: bold; +} \ No newline at end of file diff --git a/src/app/dashboard/dashboard-list-item.component.ts b/src/app/dashboard/dashboard-list-item.component.ts new file mode 100644 index 0000000000..8c3dd6171b --- /dev/null +++ b/src/app/dashboard/dashboard-list-item.component.ts @@ -0,0 +1,24 @@ +import { Component, Input } from '@angular/core'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'dashboard-list-item', + templateUrl: './dashboard-list-item.component.html', + styleUrls: ['./dashboard-list-item.component.scss'] +}) +export class DashboardListItemComponent { + @Input() task: any; + + constructor(private router: Router) {} + + goToTask() { + if (!this.task) return; + + this.router.navigate([ + '/units', + this.task.unitId, + 'tasks', + this.task.id + ]); + } +} \ No newline at end of file diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 879db426d0..78ddb71d25 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -44,7 +44,7 @@ import {MatDialogModule as MatDialogModuleNew} from '@angular/material/dialog'; import {AlertService} from 'src/app/common/services/alert.service'; import {AlertComponent} from 'src/app/common/services/alert.service'; import {MatSidenavModule} from '@angular/material/sidenav'; - +import { DashboardListItemComponent } from './dashboard/dashboard-list-item.component'; import {setTheme} from 'ngx-bootstrap/utils'; import {CodeEditorModule} from '@ngstack/code-editor'; @@ -366,6 +366,7 @@ const GANTT_CHART_CONFIG = { @NgModule({ // Components we declare declarations: [ + DashboardListItemComponent, AlertComponent, AboutDoubtfireModalContent, D2lUnitDetailsFormComponent, From e4080d03a629654518bc362f48e8e0fbb790dd96 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Mon, 11 May 2026 12:35:21 +1000 Subject: [PATCH 1002/1531] fix: unlock task status selection for staff (#1222) fix: unlock task status selection for staff --- .../task-status-card/task-status-card.component.html | 6 ++++-- .../task-status-card/task-status-card.component.ts | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html index 7b49a65daa..fd2497ea4a 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html @@ -4,7 +4,7 @@ @@ -47,7 +47,9 @@
    {{ task?.statusLabel() }}
    mat-stroked-button (click)="uploadSubmission()" [disabled]=" - isReadyForFeedback() || task?.blockedByPrerequisiteTasks() || isSubmittedForPortfolio() + isReadyForFeedback() || + (task?.blockedByPrerequisiteTasks() && !isTutor) || + isSubmittedForPortfolio() " > Upload Submission diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts index 8738a0bffd..b4233712db 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts @@ -12,6 +12,7 @@ import {SubmissionTypeModalService} from 'src/app/tasks/modals/submission-type-m import {Project} from 'src/app/api/models/project'; import {UserService} from 'src/app/api/services/user.service'; import {FeedbackAppealModalService} from 'src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.service'; +import {UnitRole} from 'src/app/api/models/unit-role'; @Component({ selector: 'f-task-status-card', templateUrl: './task-status-card.component.html', @@ -129,4 +130,13 @@ export class TaskStatusCardComponent implements OnChanges, AfterViewInit { openFeedbackAppealModal(): void { this.feedbackAppealService.show(this.task); } + + public get currentUnitRole(): UnitRole | undefined { + const currentUser = this.userService.currentUser; + return this.project.unit.staff.find((ur) => ur.user.id === currentUser.id); + } + + public get isTutor(): boolean { + return this.currentUnitRole.role === 'Convenor' || this.currentUnitRole.role === 'Tutor'; + } } From 8e18d30fc52ce62ee9d3c8ee94c7335bda652d9f Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 12 May 2026 11:39:15 +1000 Subject: [PATCH 1003/1531] chore(release): 10.0.1-37 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce3017c2a9..6c02ea7571 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [10.0.1-37](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-36...v10.0.1-37) (2026-05-12) + + +### Bug Fixes + +* unlock task status selection for staff ([#1222](https://github.com/b0ink/doubtfire-deploy/issues/1222)) ([e4080d0](https://github.com/b0ink/doubtfire-deploy/commit/e4080d03a629654518bc362f48e8e0fbb790dd96)) + ### [10.0.1-36](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-35...v10.0.1-36) (2026-05-05) ### [10.0.1-35](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-34...v10.0.1-35) (2026-04-28) diff --git a/package-lock.json b/package-lock.json index 756a0fb315..9326ac911f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.1-36", + "version": "10.0.1-37", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.1-36", + "version": "10.0.1-37", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 80e455b7b2..0802cc8121 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.1-36", + "version": "10.0.1-37", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 88a866ea7ff2e17be331ec2c09b7c2d67f4c667c Mon Sep 17 00:00:00 2001 From: Cilly Leang Date: Tue, 12 May 2026 22:33:08 +1000 Subject: [PATCH 1004/1531] feat(dashboard): create dashboard list item --- .../dashboard-list-item.component.html | 19 +++++++----- .../dashboard-list-item.component.scss | 22 ------------- .../dashboard-list-item.component.ts | 31 +++++++------------ 3 files changed, 24 insertions(+), 48 deletions(-) delete mode 100644 src/app/dashboard/dashboard-list-item.component.scss diff --git a/src/app/dashboard/dashboard-list-item.component.html b/src/app/dashboard/dashboard-list-item.component.html index ef5bd52e56..f4d34fdccb 100644 --- a/src/app/dashboard/dashboard-list-item.component.html +++ b/src/app/dashboard/dashboard-list-item.component.html @@ -1,8 +1,13 @@ -
    -

    {{ task?.title }}

    - -
    - Task {{ task?.number }} - {{ task?.type }} +
    +
    +
    +

    {{ task.title }}

    +

    {{ task.subtitle }}

    -
    \ No newline at end of file +
    +
    + {{ task.comments }} +
    + keyboard_arrow_down +
    +
    diff --git a/src/app/dashboard/dashboard-list-item.component.scss b/src/app/dashboard/dashboard-list-item.component.scss deleted file mode 100644 index 463fb3471c..0000000000 --- a/src/app/dashboard/dashboard-list-item.component.scss +++ /dev/null @@ -1,22 +0,0 @@ -.task-item { - padding: 12px; - border-radius: 8px; - background: white; - cursor: pointer; - margin-bottom: 10px; - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); - - &:hover { - background: #f5f5f5; - } -} - -.task-details { - display: flex; - justify-content: space-between; - font-size: 12px; -} - -.task-type { - font-weight: bold; -} \ No newline at end of file diff --git a/src/app/dashboard/dashboard-list-item.component.ts b/src/app/dashboard/dashboard-list-item.component.ts index 8c3dd6171b..b201cfcad0 100644 --- a/src/app/dashboard/dashboard-list-item.component.ts +++ b/src/app/dashboard/dashboard-list-item.component.ts @@ -1,24 +1,17 @@ -import { Component, Input } from '@angular/core'; -import { Router } from '@angular/router'; +import {Component, Input} from '@angular/core'; + +export type DashboardTask = { + title: string; + subtitle: string; + abbreviation: string; + color: string; + comments: number; +}; @Component({ - selector: 'dashboard-list-item', + selector: 'f-dashboard-list-item', templateUrl: './dashboard-list-item.component.html', - styleUrls: ['./dashboard-list-item.component.scss'] }) export class DashboardListItemComponent { - @Input() task: any; - - constructor(private router: Router) {} - - goToTask() { - if (!this.task) return; - - this.router.navigate([ - '/units', - this.task.unitId, - 'tasks', - this.task.id - ]); - } -} \ No newline at end of file + @Input() task: DashboardTask; +} From d19717cd5c2dea3bfca37e8645a93205155b82ee Mon Sep 17 00:00:00 2001 From: Cilly Leang Date: Tue, 12 May 2026 22:33:44 +1000 Subject: [PATCH 1005/1531] feat(dashboard): link up items to main dashboard page --- .../f-cross-dashboard.component.html | 17 +++++-- .../f-cross-dashboard.component.scss | 0 .../dashboard/f-cross-dashboard.component.ts | 48 ++++++++++++------- 3 files changed, 45 insertions(+), 20 deletions(-) delete mode 100644 src/app/dashboard/f-cross-dashboard.component.scss diff --git a/src/app/dashboard/f-cross-dashboard.component.html b/src/app/dashboard/f-cross-dashboard.component.html index dc1a456d7a..978148aa11 100644 --- a/src/app/dashboard/f-cross-dashboard.component.html +++ b/src/app/dashboard/f-cross-dashboard.component.html @@ -1,7 +1,7 @@
    -
    -
    +
    +

    {{ unit.code }}

    {{ unit.code }} filter_list_alt
    - +
    +
    +
    + +
    +
    +
    diff --git a/src/app/dashboard/f-cross-dashboard.component.scss b/src/app/dashboard/f-cross-dashboard.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/dashboard/f-cross-dashboard.component.ts b/src/app/dashboard/f-cross-dashboard.component.ts index 2f1bfcdb6e..bd4bbc0721 100644 --- a/src/app/dashboard/f-cross-dashboard.component.ts +++ b/src/app/dashboard/f-cross-dashboard.component.ts @@ -1,41 +1,57 @@ import {Component, OnInit} from '@angular/core'; -import {Unit} from 'src/app/api/models/unit'; import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; +import {Project} from '../api/models/project'; +import {TaskStatus} from '../api/models/task-status'; +import {DashboardTask} from './dashboard-list-item.component'; +import {Task} from '../api/models/task'; +import {TaskDefinition} from '../api/models/task-definition'; -type IUnits = { - id: number; +type DashboardUnit = { + projectId: number; code: string; name: string; - // tasks: ITask[]; + tasks: DashboardTask[]; }; @Component({ selector: 'f-cross-dashboard', templateUrl: './f-cross-dashboard.component.html', - styleUrls: ['./f-cross-dashboard.component.scss'], }) export class CrossDashboardComponent implements OnInit { constructor(private globalStateService: GlobalStateService) {} - units: IUnits[] = []; + units: DashboardUnit[] = []; ngOnInit(): void { this.globalStateService.onLoad(() => { - this.globalStateService.loadedUnits.values.subscribe((units) => { - this.units = this.mapUnits(units); + this.globalStateService.currentUserProjects.values.subscribe((projects) => { + this.units = this.mapProjects(projects); }); }); } - mapUnit(unit: Unit): IUnits { - return { - id: unit.id, - code: unit.code, - name: unit.name, - }; + mapProjects(projects: readonly Project[]): DashboardUnit[] { + return projects.map((project) => { + const unit = project.unit; + return { + projectId: project.id, + code: unit.code, + name: unit.name, + tasks: this.mapTasks(project.tasks, unit.taskDefinitions), + }; + }); } - mapUnits(units: readonly Unit[]) { - return units.map((unit) => this.mapUnit(unit)); + mapTasks(tasks: readonly Task[], taskDefs: readonly TaskDefinition[]): DashboardTask[] { + return taskDefs.map((def) => { + const task = tasks.find((t) => t.taskDefId == def.id); + return { + title: def.name, + subtitle: `${def.abbreviation} - ${def.targetGradeText} Task`, + abbreviation: def.abbreviation, + color: TaskStatus.STATUS_COLORS.get(task?.status ?? 'not_started'), + comments: task?.numNewComments ?? 0, + }; + }); } } From d50d77ab7d48af17b42dd20abebfe5e150f95410 Mon Sep 17 00:00:00 2001 From: Cilly Leang Date: Tue, 12 May 2026 22:34:35 +1000 Subject: [PATCH 1006/1531] feat(dashboard): include task definitions on initial projects load --- .../states/index/global-state.service.ts | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/app/projects/states/index/global-state.service.ts b/src/app/projects/states/index/global-state.service.ts index 6d3cdb12d2..1837e240ea 100644 --- a/src/app/projects/states/index/global-state.service.ts +++ b/src/app/projects/states/index/global-state.service.ts @@ -292,18 +292,24 @@ export class GlobalStateService implements OnDestroy { next: (_unitRoles: UnitRole[]) => { // unit roles are now in the cache - this.projectService.query(undefined, {params: {include_in_active: false}}).subscribe({ - next: (_projects: Project[]) => { - // projects updated in cache - - setTimeout(() => { - this.isLoadingSubject.next(false); - }, 800); - }, - error: (_response) => { - this.alerts.error('Unable to access the units you study.', 6000); - }, - }); + this.projectService + .query(undefined, { + params: { + include_inactive: false, + include_task_definitions: true, + }, + }) + .subscribe({ + next: (_projects: Project[]) => { + // projects updated in cache + setTimeout(() => { + this.isLoadingSubject.next(false); + }, 800); + }, + error: (_response) => { + this.alerts.error('Unable to access the units you study.', 6000); + }, + }); }, error: (_response) => { this.alerts.error('Unable to access your units.', 6000); From f1528d1aedc7d6485b094ed3c4923b44c786d45b Mon Sep 17 00:00:00 2001 From: Cilly Leang Date: Tue, 12 May 2026 23:15:46 +1000 Subject: [PATCH 1007/1531] fix: prevent multiple global fetches --- src/app/projects/states/index/global-state.service.ts | 4 +--- src/app/sessions/states/sign-in/sign-in.component.ts | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/app/projects/states/index/global-state.service.ts b/src/app/projects/states/index/global-state.service.ts index 6d3cdb12d2..63570b09e0 100644 --- a/src/app/projects/states/index/global-state.service.ts +++ b/src/app/projects/states/index/global-state.service.ts @@ -122,9 +122,7 @@ export class GlobalStateService implements OnDestroy { setTimeout(() => { // Try to login using the refresh token this.authenticationService.attemptLoginUsingRefreshToken((result: boolean) => { - if (result) { - this.loadGlobals(); - } else { + if (!result) { // Loading is finshed... this.isLoadingSubject.next(false); diff --git a/src/app/sessions/states/sign-in/sign-in.component.ts b/src/app/sessions/states/sign-in/sign-in.component.ts index 2196ee83c9..3417cefecc 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.ts +++ b/src/app/sessions/states/sign-in/sign-in.component.ts @@ -211,7 +211,6 @@ export class SignInComponent implements OnInit { * Perform the actions needed when the user successfully signs in. */ private actionSignInSuccess(): void { - this.globalState.loadGlobals(); this.state.go('welcome'); } @@ -251,7 +250,6 @@ export class SignInComponent implements OnInit { this.authService.signIn(signInCredentials).subscribe({ next: () => { if (this.isLtiLogin) { - this.globalState.loadGlobals(); const params = getUrlParams(document.location.href); this.state.go('lti', { ltik: params.ltik, From d81ac52cf1b90e139a34bf13ed08142919b6cc53 Mon Sep 17 00:00:00 2001 From: Cilly Leang Date: Tue, 12 May 2026 23:16:29 +1000 Subject: [PATCH 1008/1531] fix: improve global loading logic for staff Ensure that specifically the CampusService and TeachingPeriodService are loaded before starting to load projects --- .../projects/states/index/global-state.service.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/app/projects/states/index/global-state.service.ts b/src/app/projects/states/index/global-state.service.ts index 63570b09e0..e22ea3dc94 100644 --- a/src/app/projects/states/index/global-state.service.ts +++ b/src/app/projects/states/index/global-state.service.ts @@ -2,7 +2,7 @@ import {Inject, Injectable, OnDestroy} from '@angular/core'; import {MediaObserver} from 'ng-flex-layout'; import {UIRouter} from '@uirouter/angular'; import {EntityCache} from 'ngx-entity-service'; -import {BehaviorSubject, Observable, Subject, skip, take} from 'rxjs'; +import {BehaviorSubject, Observable, Subject, find} from 'rxjs'; import { CampusService, LearningOutcomeService, @@ -220,6 +220,7 @@ export class GlobalStateService implements OnDestroy { } public loadGlobals(): void { + let loaded = 0; // Indicate we are loading data... this.isLoadingSubject.next(true); @@ -228,7 +229,7 @@ export class GlobalStateService implements OnDestroy { // Loading campuses this.campusService.query().subscribe({ next: (_response) => { - subscriber.next(true); + subscriber.next(++loaded); }, error: (_response) => { this.alerts.error('Unable to access service. Failed loading campuses.', 6000); @@ -240,7 +241,7 @@ export class GlobalStateService implements OnDestroy { .query({}, {endpointFormat: LearningOutcomeService.globalEndpoint}) .subscribe({ next: (_response) => { - subscriber.next(true); + subscriber.next(null); }, error: (_response) => { this.alerts.error('Unable to access service. Failed loading GLOs.', 6000); @@ -251,7 +252,7 @@ export class GlobalStateService implements OnDestroy { .query({}, {endpointFormat: FeedbackTemplateService.globalEndpoint}) .subscribe({ next: (_response) => { - subscriber.next(true); + subscriber.next(null); }, error: (_response) => { this.alerts.error( @@ -265,7 +266,7 @@ export class GlobalStateService implements OnDestroy { // Loading teaching periods this.teachingPeriodService.query().subscribe({ next: (_response) => { - subscriber.next(true); + subscriber.next(++loaded); }, error: (_response) => { this.alerts.error('Unable to access service. Failed loading teaching periods.', 6000); @@ -274,7 +275,7 @@ export class GlobalStateService implements OnDestroy { }); // Watch for load of campuses and teaching periods, then trigger loading of unit roles and projects - loadingObserver.pipe(skip(1), take(1)).subscribe({ + loadingObserver.pipe(find(loaded => loaded === 2)).subscribe({ next: () => { // trigger loading of units and projects - this will end the loading when complete this.loadUnitsAndProjects(); From a415d45cdf51c04421a1cb39a480feecedc7a870 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:25:31 +1000 Subject: [PATCH 1009/1531] chore: upgrade ngx-entity-service --- package-lock.json | 502 +++++++++++++++++- package.json | 8 +- .../api/models/activity-type/activity-type.ts | 9 +- src/app/api/models/campus/campus.ts | 14 +- src/app/api/models/groups/group-membership.ts | 7 +- src/app/api/models/groups/group-set.ts | 12 +- src/app/api/models/overseer/overseer-image.ts | 9 +- src/app/api/models/task-definition.ts | 10 +- src/app/api/models/task-outcome-alignment.ts | 10 +- src/app/api/models/teaching-period.ts | 31 +- src/app/api/models/tii-action.ts | 7 +- src/app/api/models/tutorial-enrolment.ts | 5 +- .../models/tutorial-stream/tutorial-stream.ts | 4 +- src/app/api/models/tutorial/tutorial.ts | 14 +- src/app/api/models/webcal/webcal.ts | 7 +- src/app/api/services/project.service.ts | 10 +- src/app/api/services/sidekiq-job.service.ts | 2 +- src/app/api/services/staff-note.service.ts | 2 +- src/app/api/services/task-comment.service.ts | 2 +- .../api/services/task-definition.service.ts | 4 +- src/app/api/services/task.service.ts | 5 +- src/app/api/services/tutorial.service.ts | 2 +- src/app/api/services/unit.service.ts | 4 +- .../entity-form/entity-form.component.ts | 27 +- .../unit-tutorials-list.component.ts | 70 ++- 25 files changed, 648 insertions(+), 129 deletions(-) diff --git a/package-lock.json b/package-lock.json index eb369a8db1..e9b7526355 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,15 +51,15 @@ "lottie-web": "^5.13.0", "marked": "^12", "moment": "^2.30", - "monaco-editor": "^0.52.2", + "monaco-editor": "^0.55.1", "ng-csv": "0.2.3", "ng-file-upload": "~5.0.9", "ng-flex-layout": "^17.3.7-beta.1", "ng2-pdf-viewer": "10.2.2", "ngx-bootstrap": "^6.1.0", - "ngx-entity-service": "^0.0.41", + "ngx-entity-service": "^0.0.42", "ngx-lottie": "^11.0.2", - "ngx-monaco-editor-v2": "^19", + "ngx-monaco-editor-v2": "^21", "npm": "^10.4.0", "nvd3": "1.8.6", "qrcode": "^1.5.4", @@ -3591,6 +3591,208 @@ "win32" ] }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "optional": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/@mattlewis92/dom-autoscroller": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@mattlewis92/dom-autoscroller/-/dom-autoscroller-2.4.2.tgz", @@ -6064,6 +6266,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.11.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.11.0.tgz", @@ -6380,7 +6589,7 @@ }, "node_modules/abbrev": { "version": "1.1.1", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/accepts": { @@ -7043,6 +7252,28 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/arg": { "version": "5.0.2", "dev": true, @@ -8039,6 +8270,22 @@ "dev": true, "license": "MIT" }, + "node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/canvas-confetti": { "version": "1.9.4", "license": "ISC", @@ -8452,6 +8699,16 @@ "version": "1.1.4", "license": "MIT" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -8662,6 +8919,13 @@ "date-now": "^0.1.4" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", + "optional": true + }, "node_modules/constantinople": { "version": "3.1.2", "dev": true, @@ -9280,6 +9544,19 @@ "node": ">=0.10" } }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/deep-is": { "version": "0.1.4", "license": "MIT", @@ -9385,6 +9662,13 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, "node_modules/depd": { "version": "2.0.0", "dev": true, @@ -9420,7 +9704,6 @@ }, "node_modules/detect-libc": { "version": "2.1.2", - "dev": true, "license": "Apache-2.0", "optional": true, "engines": { @@ -9547,6 +9830,15 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", + "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", @@ -11029,6 +11321,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/gaze": { "version": "1.1.3", "dev": true, @@ -12596,6 +12910,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, "node_modules/has-value": { "version": "1.0.0", "dev": true, @@ -15004,6 +15325,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "9.0.5", "dev": true, @@ -15219,10 +15553,26 @@ } }, "node_modules/monaco-editor": { - "version": "0.52.2", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz", - "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==", - "license": "MIT" + "version": "0.55.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz", + "integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==", + "license": "MIT", + "dependencies": { + "dompurify": "3.2.7", + "marked": "14.0.0" + } + }, + "node_modules/monaco-editor/node_modules/marked": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", + "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } }, "node_modules/morgan": { "version": "1.10.1", @@ -15359,7 +15709,6 @@ "version": "2.26.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.26.2.tgz", "integrity": "sha512-0tTvBTYkt3tdGw22nrAy50x7gpbGCCFH3AFcyS5WiUu7Eu4vWlri1woE6qHBSfy11vksDqkiwjOnlR7WV8G1Hw==", - "dev": true, "license": "MIT", "optional": true }, @@ -15538,6 +15887,8 @@ }, "node_modules/ng2-pdf-viewer": { "version": "10.2.2", + "resolved": "https://registry.npmjs.org/ng2-pdf-viewer/-/ng2-pdf-viewer-10.2.2.tgz", + "integrity": "sha512-GaKAvF0nXAiR9U4LFWuT54MM9nzp0ie8GGscp34W+lFsSOXdlwS0iFx5UPuVlODRm3YEUKx6xcK5oaJeBq0SAw==", "license": "MIT", "dependencies": { "pdfjs-dist": "^3.11.174", @@ -15553,13 +15904,15 @@ } }, "node_modules/ngx-entity-service": { - "version": "0.0.41", + "version": "0.0.42", + "resolved": "https://registry.npmjs.org/ngx-entity-service/-/ngx-entity-service-0.0.42.tgz", + "integrity": "sha512-RmehGi3FmftKz2W/i9o35MwR548mz+I/pRXPgU9CWtMhi4VFqqrq5+XFrzSzx3iMpRuLHER19tmdFnX5PYihtQ==", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17 || ^18", - "@angular/core": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17 || ^18" + "@angular/common": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17 || ^18 || ^19 || ^20 || ^21", + "@angular/core": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17 || ^18 || ^19 || ^20 || ^21" } }, "node_modules/ngx-lottie": { @@ -15575,17 +15928,17 @@ } }, "node_modules/ngx-monaco-editor-v2": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/ngx-monaco-editor-v2/-/ngx-monaco-editor-v2-19.0.2.tgz", - "integrity": "sha512-hkPiCnLU0vdIF2DW7Ko/EHoGCtLxuN85eygKuk3fXL2GRbEIl5VcbUXmRX9ItfLOI1F5QcH80HhavY5r0gNfEw==", + "version": "21.1.4", + "resolved": "https://registry.npmjs.org/ngx-monaco-editor-v2/-/ngx-monaco-editor-v2-21.1.4.tgz", + "integrity": "sha512-dZu3dY3D1YXPTIDRn9zOERdtDtGy1SOztpWG6gJlaj6NMSV59kNR/hfzaP+L3BukP6Ve07f3bIyvsx6Pz7uOaA==", "license": "MIT", "dependencies": { - "tslib": "^2.1.0" + "tslib": "^2.8.1" }, "peerDependencies": { - "@angular/common": "^19.0.4", - "@angular/core": "^19.0.4", - "monaco-editor": "^0.52.2" + "@angular/common": "^21.1.4", + "@angular/core": "^21.1.4", + "monaco-editor": "^0.55.1" } }, "node_modules/no-case": { @@ -15604,6 +15957,27 @@ "license": "MIT", "optional": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-gyp": { "version": "12.3.0", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.3.0.tgz", @@ -18262,6 +18636,20 @@ "node": ">=18" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -18605,7 +18993,7 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -19179,6 +19567,8 @@ }, "node_modules/path2d-polyfill": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz", + "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==", "license": "MIT", "optional": true, "engines": { @@ -19187,6 +19577,8 @@ }, "node_modules/pdfjs-dist": { "version": "3.11.174", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz", + "integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==", "license": "Apache-2.0", "engines": { "node": ">=18" @@ -21628,11 +22020,44 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, "node_modules/simple-fmt": { "version": "0.1.0", "dev": true, "license": "MIT" }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/simple-is": { "version": "0.2.0", "dev": true, @@ -22606,6 +23031,13 @@ "node": ">=6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT", + "optional": true + }, "node_modules/tree-kill": { "version": "1.2.2", "dev": true, @@ -23607,6 +24039,13 @@ "node": ">=0.8.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause", + "optional": true + }, "node_modules/websocket-driver": { "version": "0.7.4", "dev": true, @@ -23628,6 +24067,17 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "license": "ISC", @@ -23645,6 +24095,16 @@ "version": "2.0.1", "license": "ISC" }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/window-size": { "version": "0.1.0", "dev": true, diff --git a/package.json b/package.json index 4af41c7999..a3fe329138 100644 --- a/package.json +++ b/package.json @@ -68,15 +68,15 @@ "lottie-web": "^5.13.0", "marked": "^12", "moment": "^2.30", - "monaco-editor": "^0.52.2", + "monaco-editor": "^0.55.1", "ng-csv": "0.2.3", "ng-file-upload": "~5.0.9", "ng-flex-layout": "^17.3.7-beta.1", "ng2-pdf-viewer": "10.2.2", "ngx-bootstrap": "^6.1.0", - "ngx-entity-service": "^0.0.41", + "ngx-entity-service": "^0.0.42", "ngx-lottie": "^11.0.2", - "ngx-monaco-editor-v2": "^19", + "ngx-monaco-editor-v2": "^21", "npm": "^10.4.0", "nvd3": "1.8.6", "qrcode": "^1.5.4", @@ -161,4 +161,4 @@ "@rollup/rollup-linux-arm64-gnu": "*", "@rollup/rollup-linux-x64-gnu": "*" } -} \ No newline at end of file +} diff --git a/src/app/api/models/activity-type/activity-type.ts b/src/app/api/models/activity-type/activity-type.ts index e75d09677d..d084a1901e 100644 --- a/src/app/api/models/activity-type/activity-type.ts +++ b/src/app/api/models/activity-type/activity-type.ts @@ -1,13 +1,16 @@ -import { Entity, EntityMapping } from 'ngx-entity-service'; +import {Entity, EntityMapping} from 'ngx-entity-service'; export class ActivityType extends Entity { id: number; name: string; abbreviation: string; - public override toJson(mappingData: EntityMapping, ignoreKeys?: string[]): object { + public override toJson( + mappingData: EntityMapping, + ignoreKeys?: string[], + ): object { return { - activity_type: super.toJson(mappingData, ignoreKeys) + activity_type: super.toJson(mappingData, ignoreKeys), }; } } diff --git a/src/app/api/models/campus/campus.ts b/src/app/api/models/campus/campus.ts index 9491e29e53..9df9ef23e6 100644 --- a/src/app/api/models/campus/campus.ts +++ b/src/app/api/models/campus/campus.ts @@ -1,4 +1,4 @@ -import { Entity, EntityMapping } from "ngx-entity-service"; +import {Entity, EntityMapping} from 'ngx-entity-service'; type campusModes = 'timetable' | 'automatic' | 'manual'; @@ -9,9 +9,12 @@ export class Campus extends Entity { abbreviation: string; timezone: string; - public override toJson(mappingData: EntityMapping, ignoreKeys?: string[]): object { + public override toJson( + mappingData: EntityMapping, + ignoreKeys?: string[], + ): object { return { - campus: super.toJson(mappingData, ignoreKeys) + campus: super.toJson(mappingData, ignoreKeys), }; } @@ -21,6 +24,9 @@ export class Campus extends Entity { * @param matchText the text to match */ public matches(matchText: string): boolean { - return this.name.toLowerCase().indexOf(matchText) >= 0 || this.abbreviation.toLowerCase().indexOf(matchText) >= 0; + return ( + this.name.toLowerCase().indexOf(matchText) >= 0 || + this.abbreviation.toLowerCase().indexOf(matchText) >= 0 + ); } } diff --git a/src/app/api/models/groups/group-membership.ts b/src/app/api/models/groups/group-membership.ts index b7952d8b5e..0a0dca1539 100644 --- a/src/app/api/models/groups/group-membership.ts +++ b/src/app/api/models/groups/group-membership.ts @@ -1,9 +1,8 @@ -import { Entity } from 'ngx-entity-service'; +import {Entity} from 'ngx-entity-service'; export class GroupMembership extends Entity { - public get student_name(): string { - console.log("implement student_name"); - return "TODO NAME"; + console.log('implement student_name'); + return 'TODO NAME'; } } diff --git a/src/app/api/models/groups/group-set.ts b/src/app/api/models/groups/group-set.ts index 42882017d4..cb99f99e44 100644 --- a/src/app/api/models/groups/group-set.ts +++ b/src/app/api/models/groups/group-set.ts @@ -1,11 +1,9 @@ -import { Entity, EntityCache, EntityMapping } from 'ngx-entity-service'; -import { AppInjector } from 'src/app/app-injector'; -import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; -import { Group, Unit, User } from '../doubtfire-model'; - +import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; +import {AppInjector} from 'src/app/app-injector'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Group, Unit, User} from '../doubtfire-model'; export class GroupSet extends Entity { - public id: number; public name: string; public allowStudentsToCreateGroups: boolean = true; @@ -34,7 +32,7 @@ export class GroupSet extends Entity { } public findGroupById(id: number): Group { - return this.groups.find(grp => grp.id === id); + return this.groups.find((grp) => grp.id === id); } public groupCSVUploadUrl(): string { diff --git a/src/app/api/models/overseer/overseer-image.ts b/src/app/api/models/overseer/overseer-image.ts index 277c3df426..2f6627d3be 100644 --- a/src/app/api/models/overseer/overseer-image.ts +++ b/src/app/api/models/overseer/overseer-image.ts @@ -1,5 +1,5 @@ -import { StringNullableChain } from 'lodash'; -import { Entity, EntityMapping } from 'ngx-entity-service'; +import {StringNullableChain} from 'lodash'; +import {Entity, EntityMapping} from 'ngx-entity-service'; export class OverseerImage extends Entity { id: number; @@ -9,7 +9,10 @@ export class OverseerImage extends Entity { pulledImageStatus: string; lastPulledDate: string; - public override toJson(mappingData: EntityMapping, ignoreKeys?: string[]): object { + public override toJson( + mappingData: EntityMapping, + ignoreKeys?: string[], + ): object { return { overseer_image: super.toJson(mappingData, ignoreKeys), }; diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index c8f88d1e9e..cd5ede1e4b 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -11,15 +11,19 @@ import {TaskPrerequisite} from './task-prerequisite'; import {DiscussionPrompt} from './discussion-prompt'; import {OverseerStep} from './overseer/overseer-step'; -export type UploadRequirement = { +export interface UploadRequirement { key: string; name: string; type: string; tiiCheck?: boolean; tiiPct?: number; -}; +} -export type SimilarityCheck = {key: string; type: string; pattern: string}; +export interface SimilarityCheck { + key: string; + type: string; + pattern: string; +} export class TaskDefinition extends Entity { id: number; diff --git a/src/app/api/models/task-outcome-alignment.ts b/src/app/api/models/task-outcome-alignment.ts index 62414b5245..8569ae5549 100644 --- a/src/app/api/models/task-outcome-alignment.ts +++ b/src/app/api/models/task-outcome-alignment.ts @@ -1,6 +1,6 @@ -import { Entity } from 'ngx-entity-service'; -import { Project, Unit, TaskDefinition, Task } from './doubtfire-model'; -import { LearningOutcome } from './learning-outcome'; +import {Entity} from 'ngx-entity-service'; +import {Project, Unit, TaskDefinition, Task} from './doubtfire-model'; +import {LearningOutcome} from './learning-outcome'; export class TaskOutcomeAlignment extends Entity { public within: Unit | Project; @@ -18,7 +18,7 @@ export class TaskOutcomeAlignment extends Entity { } public get unit(): Unit { - if ( this.within instanceof Unit) { + if (this.within instanceof Unit) { return this.within; } else { return this.within.unit; @@ -26,7 +26,7 @@ export class TaskOutcomeAlignment extends Entity { } public get project(): Project { - if ( this.within instanceof Project) { + if (this.within instanceof Project) { return this.within; } diff --git a/src/app/api/models/teaching-period.ts b/src/app/api/models/teaching-period.ts index 2aca186b7c..f8e11f5f8e 100644 --- a/src/app/api/models/teaching-period.ts +++ b/src/app/api/models/teaching-period.ts @@ -1,7 +1,7 @@ -import { Entity, EntityCache, EntityMapping } from 'ngx-entity-service'; -import { Observable } from 'rxjs'; -import { AppInjector } from 'src/app/app-injector'; -import { TeachingPeriodBreakService, TeachingPeriodService, Unit } from './doubtfire-model'; +import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; +import {AppInjector} from 'src/app/app-injector'; +import {TeachingPeriodBreakService, TeachingPeriodService, Unit} from './doubtfire-model'; export class TeachingPeriodBreak extends Entity { id: number; @@ -27,7 +27,10 @@ export class TeachingPeriod extends Entity { * @param ignoreKeys * @returns */ - public override toJson(mappingData: EntityMapping, ignoreKeys?: string[]): object { + public override toJson( + mappingData: EntityMapping, + ignoreKeys?: string[], + ): object { return { teaching_period: super.toJson(mappingData, ignoreKeys), }; @@ -69,7 +72,10 @@ export class TeachingPeriod extends Entity { breakEntity.numberOfWeeks = weeks; const breakService: TeachingPeriodBreakService = AppInjector.get(TeachingPeriodBreakService); - return breakService.create({ teaching_period_id: this.id }, { cache: this.breaksCache, entity: breakEntity }); + return breakService.create( + {teaching_period_id: this.id}, + {cache: this.breaksCache, entity: breakEntity}, + ); } /** @@ -79,10 +85,17 @@ export class TeachingPeriod extends Entity { */ public removeBreak(teachingBreakID: number): Observable { const breakService: TeachingPeriodBreakService = AppInjector.get(TeachingPeriodBreakService); - return breakService.delete({ teaching_period_id: this.id, id: teachingBreakID }, { cache: this.breaksCache }); + return breakService.delete( + {teaching_period_id: this.id, id: teachingBreakID}, + {cache: this.breaksCache}, + ); } - public rollover(newPeriod: TeachingPeriod, rolloverInactive: boolean, searchForward: boolean): Observable { + public rollover( + newPeriod: TeachingPeriod, + rolloverInactive: boolean, + searchForward: boolean, + ): Observable { const teachingPeriodService: TeachingPeriodService = AppInjector.get(TeachingPeriodService); return teachingPeriodService.post( @@ -94,7 +107,7 @@ export class TeachingPeriod extends Entity { }, { endpointFormat: TeachingPeriodService.rolloverEndpointFormat, - } + }, ); } } diff --git a/src/app/api/models/tii-action.ts b/src/app/api/models/tii-action.ts index 0f0ed3d599..661ba9324f 100644 --- a/src/app/api/models/tii-action.ts +++ b/src/app/api/models/tii-action.ts @@ -1,6 +1,6 @@ -import { Entity, EntityCache, EntityMapping } from 'ngx-entity-service'; -import { Observable } from 'rxjs'; -import { Unit } from './doubtfire-model'; +import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; +import {Unit} from './doubtfire-model'; export class TiiAction extends Entity { id: number; @@ -14,5 +14,4 @@ export class TiiAction extends Entity { log: string; description: string; - } diff --git a/src/app/api/models/tutorial-enrolment.ts b/src/app/api/models/tutorial-enrolment.ts index 7463175365..2b6f822405 100644 --- a/src/app/api/models/tutorial-enrolment.ts +++ b/src/app/api/models/tutorial-enrolment.ts @@ -1,6 +1,5 @@ -import { Entity } from 'ngx-entity-service'; -import { Tutorial, User } from './doubtfire-model'; - +import {Entity} from 'ngx-entity-service'; +import {Tutorial, User} from './doubtfire-model'; export class TutorialEnrolment extends Entity { public tutorial: Tutorial; diff --git a/src/app/api/models/tutorial-stream/tutorial-stream.ts b/src/app/api/models/tutorial-stream/tutorial-stream.ts index 2ccb96759d..b1ef5ad77d 100644 --- a/src/app/api/models/tutorial-stream/tutorial-stream.ts +++ b/src/app/api/models/tutorial-stream/tutorial-stream.ts @@ -1,5 +1,5 @@ -import { Entity } from 'ngx-entity-service'; -import { Unit, Tutorial } from '../doubtfire-model'; +import {Entity} from 'ngx-entity-service'; +import {Unit, Tutorial} from '../doubtfire-model'; export class TutorialStream extends Entity { name: string; diff --git a/src/app/api/models/tutorial/tutorial.ts b/src/app/api/models/tutorial/tutorial.ts index 181b1ec0d0..0ef41a464d 100644 --- a/src/app/api/models/tutorial/tutorial.ts +++ b/src/app/api/models/tutorial/tutorial.ts @@ -1,7 +1,13 @@ -import { Entity, EntityMapping } from 'ngx-entity-service'; -import { AppInjector } from '../../../app-injector'; -import { User, Campus, UserService, CampusService, TutorialStream } from 'src/app/api/models/doubtfire-model'; -import { Unit } from '../unit'; +import {Entity, EntityMapping} from 'ngx-entity-service'; +import {AppInjector} from '../../../app-injector'; +import { + User, + Campus, + UserService, + CampusService, + TutorialStream, +} from 'src/app/api/models/doubtfire-model'; +import {Unit} from '../unit'; export class Tutorial extends Entity { unit: Unit; // TODO: Convert to a unit object once this exists diff --git a/src/app/api/models/webcal/webcal.ts b/src/app/api/models/webcal/webcal.ts index 26dab8e18f..a77f247b14 100644 --- a/src/app/api/models/webcal/webcal.ts +++ b/src/app/api/models/webcal/webcal.ts @@ -1,4 +1,4 @@ -import { Entity, EntityMapping } from 'ngx-entity-service'; +import {Entity, EntityMapping} from 'ngx-entity-service'; export class Webcal extends Entity { enabled: boolean; @@ -15,7 +15,10 @@ export class Webcal extends Entity { // Used only when updating the webcal. Never returned from the API. shouldChangeGuid?: boolean; - public override toJson(mappingData: EntityMapping, ignoreKeys?: string[]): object { + public override toJson( + mappingData: EntityMapping, + ignoreKeys?: string[], + ): object { return { webcal: super.toJson(mappingData, ignoreKeys), }; diff --git a/src/app/api/services/project.service.ts b/src/app/api/services/project.service.ts index 0149e89793..3a99563192 100644 --- a/src/app/api/services/project.service.ts +++ b/src/app/api/services/project.service.ts @@ -1,4 +1,4 @@ -import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; +import {CachedEntityService, MappingProcess, RequestOptions} from 'ngx-entity-service'; import { CampusService, Project, @@ -15,12 +15,6 @@ import {TaskService} from './task.service'; import {TaskOutcomeAlignmentService} from './task-outcome-alignment.service'; import {GroupService} from './group.service'; -interface MappingProcessLike { - data: object; - entity: T; - continue(): void; -} - @Injectable() export class ProjectService extends CachedEntityService { protected readonly endpointFormat = 'projects/:id:'; @@ -142,7 +136,7 @@ export class ProjectService extends CachedEntityService { }, { keys: 'unitId', - toEntityOpAsync: (process: MappingProcessLike) => { + toEntityOpAsync: (process: MappingProcess) => { const unitService: UnitService = AppInjector.get(UnitService); const unitId = process.data['unit_id']; // Load what we have... or a a stub for now... diff --git a/src/app/api/services/sidekiq-job.service.ts b/src/app/api/services/sidekiq-job.service.ts index dd5332a258..8a61e01b55 100644 --- a/src/app/api/services/sidekiq-job.service.ts +++ b/src/app/api/services/sidekiq-job.service.ts @@ -15,7 +15,7 @@ export interface SidekiqJobEntry { export class SidekiqJobService extends CachedEntityService { protected readonly endpointFormat = 'sidekiq/:id:'; - public jobEntries: Map = new Map(); + public jobEntries = new Map(); // Allow components to track changes to jobEntries public sidekiqJobsSubject = new BehaviorSubject([]); diff --git a/src/app/api/services/staff-note.service.ts b/src/app/api/services/staff-note.service.ts index 0a707fea8c..6e989e17f3 100644 --- a/src/app/api/services/staff-note.service.ts +++ b/src/app/api/services/staff-note.service.ts @@ -8,7 +8,7 @@ import {Observable, tap} from 'rxjs'; @Injectable() export class StaffNoteService extends CachedEntityService { - public readonly staffNoteAdded$: EventEmitter = new EventEmitter(); + public readonly staffNoteAdded$ = new EventEmitter(); protected readonly endpointFormat = 'projects/:projectId:/staff_notes/:id:'; diff --git a/src/app/api/services/task-comment.service.ts b/src/app/api/services/task-comment.service.ts index 658cd85d80..8e49f12cc8 100644 --- a/src/app/api/services/task-comment.service.ts +++ b/src/app/api/services/task-comment.service.ts @@ -20,7 +20,7 @@ import {ScormExtensionComment} from '../models/task-comment/scorm-extension-comm @Injectable() export class TaskCommentService extends CachedEntityService { - public readonly commentAdded$: EventEmitter = new EventEmitter(); + public readonly commentAdded$ = new EventEmitter(); private readonly commentEndpointFormat = 'projects/:projectId:/task_def_id/:taskDefinitionId:/comments/:id:'; diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 364d0f89c3..7591ae3f66 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -72,13 +72,13 @@ export class TaskDefinitionService extends CachedEntityService { }, toEntityFn: (data: object, key: string, taskDef: TaskDefinition, params?: any) => { return ( - data[key] as Array<{ + data[key] as { key: string; name: string; type: string; tii_check: boolean; tii_pct: number; - }> + }[] )?.map((upreq) => { return { key: upreq.key, diff --git a/src/app/api/services/task.service.ts b/src/app/api/services/task.service.ts index fdc69de09d..95cbceb5e1 100644 --- a/src/app/api/services/task.service.ts +++ b/src/app/api/services/task.service.ts @@ -16,7 +16,7 @@ import {Observable, map, tap} from 'rxjs'; @Injectable() export class TaskService extends CachedEntityService { - public readonly taskStatusUpdated$: EventEmitter = new EventEmitter(); + public readonly taskStatusUpdated$ = new EventEmitter(); protected readonly endpointFormat = '/projects/:projectId:/task_def_id/:taskDefId:'; @@ -231,7 +231,8 @@ export class TaskService extends CachedEntityService { public readonly statusSeq = TaskStatus.STATUS_SEQ; public readonly helpDescriptions = TaskStatus.HELP_DESCRIPTIONS; public readonly statusIcons: Map = TaskStatus.STATUS_ICONS; - public readonly statusMaterialIcons: Map = TaskStatus.STATUS_MATERIAL_ICONS; + public readonly statusMaterialIcons: Map = + TaskStatus.STATUS_MATERIAL_ICONS; public readonly rejectFutureStates = TaskStatus.REJECT_FUTURE_STATES; public statusClass(status: TaskStatusEnum): string { diff --git a/src/app/api/services/tutorial.service.ts b/src/app/api/services/tutorial.service.ts index 4d802b67fd..7f444157ce 100644 --- a/src/app/api/services/tutorial.service.ts +++ b/src/app/api/services/tutorial.service.ts @@ -102,7 +102,7 @@ export class TutorialService extends CachedEntityService { body: {}, }; - var observer: Observable; + let observer: Observable; if (isEnrol) { observer = this.post(pathIds, options); } else { diff --git a/src/app/api/services/unit.service.ts b/src/app/api/services/unit.service.ts index 08a27f3e58..114e050df1 100644 --- a/src/app/api/services/unit.service.ts +++ b/src/app/api/services/unit.service.ts @@ -78,7 +78,7 @@ export class UnitService extends CachedEntityService { { keys: ['mainConvenor', 'main_convenor_id'], toEntityFn: (data, key, entity) => { - let result = entity.staffCache.get(data[key]); + const result = entity.staffCache.get(data[key]); entity.mainConvenorUser = result?.user; return result; }, @@ -219,7 +219,7 @@ export class UnitService extends CachedEntityService { { keys: 'taskDefinitions', toEntityOp: (data, key, unit) => { - var seq: number = 0; + let seq: number = 0; data['task_definitions'].forEach((taskDefinitionJson: object) => { const td = unit.taskDefinitionCache.getOrCreate( taskDefinitionJson['id'], diff --git a/src/app/common/entity-form/entity-form.component.ts b/src/app/common/entity-form/entity-form.component.ts index 5ebe626f8a..abf2a498c5 100644 --- a/src/app/common/entity-form/entity-form.component.ts +++ b/src/app/common/entity-form/entity-form.component.ts @@ -1,10 +1,10 @@ -import { AfterViewInit, Directive } from '@angular/core'; -import { UntypedFormGroup, AbstractControl } from '@angular/forms'; -import { Entity, RequestOptions } from 'ngx-entity-service'; -import { EntityService } from 'ngx-entity-service'; -import { Observable, tap } from 'rxjs'; -import { Sort } from '@angular/material/sort'; -import { MatTableDataSource } from '@angular/material/table'; +import {AfterViewInit, Directive} from '@angular/core'; +import {UntypedFormGroup, AbstractControl} from '@angular/forms'; +import {Entity, RequestOptions} from 'ngx-entity-service'; +import {EntityService} from 'ngx-entity-service'; +import {Observable, tap} from 'rxjs'; +import {Sort} from '@angular/material/sort'; +import {MatTableDataSource} from '@angular/material/table'; export type OnSuccessMethod = (object: T, isNew: boolean) => void; @@ -47,7 +47,10 @@ export abstract class EntityFormComponent implements AfterView * * @param controls the FormControls that will make up the form. */ - constructor(controls: { [key: string]: AbstractControl }, protected entityName: string) { + constructor( + controls: Record, + protected entityName: string, + ) { this.formData = new UntypedFormGroup(controls); // Iterate over the FormControls passed in and assign the default values // For each based on the values that they are constructed with @@ -138,14 +141,14 @@ export abstract class EntityFormComponent implements AfterView response = service.create(data, this.optionsOnRequest('create')); } else { // Nothing has changed if the selected value, so we want to inform the user - alertService.error( `${this.entityName} was not changed`, 6000); + alertService.error(`${this.entityName} was not changed`, 6000); return; } // Handle the response response.subscribe({ next: (result: T) => { - alertService.success( `${this.entityName} saved`, 2000); + alertService.success(`${this.entityName} saved`, 2000); // Success is implemented on all inheriting instances and is used // to handle the response appropriately for the context of the form success(result, this.selected ? false : true); @@ -163,7 +166,7 @@ export abstract class EntityFormComponent implements AfterView if (this.selected) { this.restoreFromBackup(); } - alertService.error( `${this.entityName} save failed: ${error}`, 6000); + alertService.error(`${this.entityName} save failed: ${error}`, 6000); }, }); } else { @@ -179,7 +182,7 @@ export abstract class EntityFormComponent implements AfterView this.cancelEdit(); entities.splice(entities.indexOf(entity), 1); this.dataSource.data = entities; - }) + }), ); } diff --git a/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts b/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts index f482c9bb7e..6f87b1f1bf 100644 --- a/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts +++ b/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts @@ -1,6 +1,6 @@ -import { Component, Input, ViewChild, AfterViewInit } from '@angular/core'; -import { MatSort, Sort } from '@angular/material/sort'; -import { MatTableDataSource, MatTable } from '@angular/material/table'; +import {Component, Input, ViewChild, AfterViewInit} from '@angular/core'; +import {MatSort, Sort} from '@angular/material/sort'; +import {MatTableDataSource, MatTable} from '@angular/material/table'; import { Tutorial, TutorialService, @@ -11,28 +11,49 @@ import { TutorialStreamService, Unit, } from 'src/app/api/models/doubtfire-model'; -import { EntityFormComponent } from 'src/app/common/entity-form/entity-form.component'; -import { UntypedFormControl, Validators } from '@angular/forms'; -import { RequestOptions } from 'ngx-entity-service'; -import { AlertService } from 'src/app/common/services/alert.service'; -import { ConfirmationModalService } from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {EntityFormComponent} from 'src/app/common/entity-form/entity-form.component'; +import {UntypedFormControl, Validators} from '@angular/forms'; +import {RequestOptions} from 'ngx-entity-service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; @Component({ - selector: 'df-unit-tutorials-list', - templateUrl: 'unit-tutorials-list.component.html', - styleUrls: ['unit-tutorials-list.component.scss'], - standalone: false + selector: 'df-unit-tutorials-list', + templateUrl: 'unit-tutorials-list.component.html', + styleUrls: ['unit-tutorials-list.component.scss'], + standalone: false, }) -export class UnitTutorialsListComponent extends EntityFormComponent implements AfterViewInit { - @ViewChild(MatTable, { static: true }) table: MatTable; - @ViewChild(MatSort, { static: true }) sort: MatSort; +export class UnitTutorialsListComponent + extends EntityFormComponent + implements AfterViewInit +{ + @ViewChild(MatTable, {static: true}) table: MatTable; + @ViewChild(MatSort, {static: true}) sort: MatSort; @Input() stream: TutorialStream; @Input() unit: Unit; - days: string[] = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'Asynchronous']; + days: string[] = [ + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + 'Sunday', + 'Asynchronous', + ]; campuses: Campus[] = new Array(); - columns: string[] = ['abbreviation', 'campus', 'location', 'day', 'time', 'tutor', 'capacity', 'options']; + columns: string[] = [ + 'abbreviation', + 'campus', + 'location', + 'day', + 'time', + 'tutor', + 'capacity', + 'options', + ]; tutorials: Tutorial[] = []; dataSource = new MatTableDataSource(); @@ -82,14 +103,15 @@ export class UnitTutorialsListComponent extends EntityFormComponent im private filterTutorials(): void { this.tutorials = this.unit.tutorials.filter( - (tutorial) => tutorial.tutorialStream === this.stream || (!tutorial.tutorialStream && !this.stream), + (tutorial) => + tutorial.tutorialStream === this.stream || (!tutorial.tutorialStream && !this.stream), ); this.dataSource.data = this.tutorials; } public saveStream(): void { this.tutorialStreamService - .update({ abbreviation: this.origStreamAbbr, unit_id: this.unit.id }, { entity: this.stream }) + .update({abbreviation: this.origStreamAbbr, unit_id: this.unit.id}, {entity: this.stream}) .subscribe({ next: (stream: TutorialStream) => { this.stream = stream; @@ -198,7 +220,9 @@ export class UnitTutorialsListComponent extends EntityFormComponent im /** * Ensure that the unit is passed to the Tutorial entity when create it called. */ - protected override optionsOnRequest(kind: 'create' | 'update' | 'delete'): RequestOptions { + protected override optionsOnRequest( + kind: 'create' | 'update' | 'delete', + ): RequestOptions { return { constructorParams: this.unit, cache: this.unit.tutorialsCache, @@ -223,7 +247,11 @@ export class UnitTutorialsListComponent extends EntityFormComponent im const isAsc = sort.direction === 'asc'; switch (sort.active) { case 'campus': - return this.sortCompare(a.campus ? a.campus.abbreviation : '', b.campus ? b.campus.abbreviation : '', isAsc); + return this.sortCompare( + a.campus ? a.campus.abbreviation : '', + b.campus ? b.campus.abbreviation : '', + isAsc, + ); case 'tutor': return this.sortCompare(a.tutor.name, b.tutor.name, isAsc); default: From 8a7c6b55090130612cf9d0d63a6309442013227d Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 13 May 2026 11:28:51 +1000 Subject: [PATCH 1010/1531] refactor: only show working on it status button if task is aip --- src/app/common/footer/footer.component.html | 110 ++++++++++---------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index 50233659f3..22b9873c35 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -13,19 +13,32 @@ -
    + @if (selectedTask?.definition?.assessInPortfolioOnly) { - -
    - - - @if (selectedTask && selectedTask.suggestedTaskStatus) { +
    - } - + @if (selectedTask && selectedTask.suggestedTaskStatus) { + + } - @if (selectedTask?.definition?.assessInPortfolioOnly) { - } @else { +
    Date: Wed, 13 May 2026 13:39:40 +1000 Subject: [PATCH 1012/1531] chore(release): 11.0.0-1 --- CHANGELOG.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abe6841cd3..85f1206dfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,59 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-1](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-21...v11.0.0-1) (2026-05-13) + + +### Features + +* (wip) add name to new student experience skeleton ([7b9ace4](https://github.com/b0ink/doubtfire-deploy/commit/7b9ace47132f0237bc621d3d0e45c3031e7fac05)) +* add burndown replacement ([837658a](https://github.com/b0ink/doubtfire-deploy/commit/837658afff090e52d53cefa7c2eed20a46c1ac01)) +* add new progress component ([8beef70](https://github.com/b0ink/doubtfire-deploy/commit/8beef701e6b7fc0dbea42f8849dc02e79a665fb7)) +* add new student experience ([9bb77ab](https://github.com/b0ink/doubtfire-deploy/commit/9bb77ab108e50b637329bd739925d1d9566d9203)) +* allow paste attachment comment ([#1165](https://github.com/b0ink/doubtfire-deploy/issues/1165)) ([0f24980](https://github.com/b0ink/doubtfire-deploy/commit/0f24980e6edcc5d0f81e015990adaf14afea400e)) +* batch upload feedback csv ([#1175](https://github.com/b0ink/doubtfire-deploy/issues/1175)) ([9f95987](https://github.com/b0ink/doubtfire-deploy/commit/9f959877b6f47d878d87b468f4aab73f536d598b)) +* bulk import staff via emails ([#1195](https://github.com/b0ink/doubtfire-deploy/issues/1195)) ([c91ab47](https://github.com/b0ink/doubtfire-deploy/commit/c91ab478ae1d1cd459040290f6f7a44c7dce3efe)) +* confirm recursive fix in mobile tutor view ([b64601a](https://github.com/b0ink/doubtfire-deploy/commit/b64601a425c7a64bccfaf47c1e4fccb0343b1589)) +* confirmation modal to reassign tutorials when removing staff ([5f90e90](https://github.com/b0ink/doubtfire-deploy/commit/5f90e9085d69913eced55ad54ce9ac09431d3822)) +* discussed in class refactor ([#1145](https://github.com/b0ink/doubtfire-deploy/issues/1145)) ([4d8bb5b](https://github.com/b0ink/doubtfire-deploy/commit/4d8bb5b82d89caa02ed4936819be601b3f6977fc)) +* display icon for tasks escalated by student ([dfcfd47](https://github.com/b0ink/doubtfire-deploy/commit/dfcfd472305ef2971fa72734c18e77253b98fa11)) +* display portfolio submission time ([d717b27](https://github.com/b0ink/doubtfire-deploy/commit/d717b270eb80c0b0245e6b39f0b3f0567c379512)) +* display sso redirecting state ([248c992](https://github.com/b0ink/doubtfire-deploy/commit/248c992f46488f61916e00a87ca32ed987721f31)) +* edit comments ([#1194](https://github.com/b0ink/doubtfire-deploy/issues/1194)) ([976b6ac](https://github.com/b0ink/doubtfire-deploy/commit/976b6ac4fa3bd2d5e954eebcae3fcb40dd8d1f0e)) +* enable task pinning in explorer ([1647e2b](https://github.com/b0ink/doubtfire-deploy/commit/1647e2bcc86ac6fb08c82be9795a06939c57bb6e)) +* improve look of task status count ([475c316](https://github.com/b0ink/doubtfire-deploy/commit/475c3165db099e1412e30fb6cf18bbaddd516e75)) +* pause feedback threshold during teaching period breaks ([#1138](https://github.com/b0ink/doubtfire-deploy/issues/1138)) ([12fbf81](https://github.com/b0ink/doubtfire-deploy/commit/12fbf8147107dc185a9a9cbea940efac93a0f316)) +* require discussion before marking complete ([#1103](https://github.com/b0ink/doubtfire-deploy/issues/1103)) ([86ae886](https://github.com/b0ink/doubtfire-deploy/commit/86ae8865268ee19e4b3430ff679358cc075e1346)) +* staff note and similarity indicators ([4a65a9b](https://github.com/b0ink/doubtfire-deploy/commit/4a65a9b21d615ecf78bf09743c9cf8c3026ff621)) +* visualisations ([f1cc39e](https://github.com/b0ink/doubtfire-deploy/commit/f1cc39e59dd224c55ee0e8b5f1d50855263d147e)) + + +### Bug Fixes + +* avoid rendering the staff list twice ([9e5be59](https://github.com/b0ink/doubtfire-deploy/commit/9e5be591b9a0cf72d01efa5e28e5b2b9e7eba043)) +* burndown chart visualisation ([#942](https://github.com/b0ink/doubtfire-deploy/issues/942)) ([8487b8d](https://github.com/b0ink/doubtfire-deploy/commit/8487b8d20e838fa1b2a2238bb856f73edc86442c)) +* check for valid unit ([d9560c3](https://github.com/b0ink/doubtfire-deploy/commit/d9560c3b68df0a09f577cdab990d252b5cd24c58)) +* complete student enrolment modal ([efa89c3](https://github.com/b0ink/doubtfire-deploy/commit/efa89c344069d386f2411a417e570d4158af91b9)) +* debounce duplicate task submission requests ([80f92e2](https://github.com/b0ink/doubtfire-deploy/commit/80f92e2277c48978e1738340063a7223c04fddb8)) +* display groups only when a group set is selected ([dde1e76](https://github.com/b0ink/doubtfire-deploy/commit/dde1e7697f8a9a93577bb0e18e3e81a3ebd1ace2)) +* duplicate files ([da51e8e](https://github.com/b0ink/doubtfire-deploy/commit/da51e8e0cc9518a2a76447a48079b42f144064fc)) +* ensure authorisation active in angular ([deaa1e9](https://github.com/b0ink/doubtfire-deploy/commit/deaa1e940f8295ff962c111f1dbac75ed5ff51fa)) +* ensure loading screen removed in sign in component ([6954ac6](https://github.com/b0ink/doubtfire-deploy/commit/6954ac62627e058b6a73c0e83dc8dc8a1740698d)) +* ensure pdf viewer is visible [#1186](https://github.com/b0ink/doubtfire-deploy/issues/1186) ([6bc0752](https://github.com/b0ink/doubtfire-deploy/commit/6bc075228fe2a48dcf91aa5350b5f15f602e2dc8)) +* ensure selected group is valid ([95cb9ac](https://github.com/b0ink/doubtfire-deploy/commit/95cb9ace6615b45dd75161fd02d6dd130420817b)) +* fix pdf viewer for portfolios ([456cf46](https://github.com/b0ink/doubtfire-deploy/commit/456cf466bf49b86467b269ec3d6fb4e63f6a059f)) +* get new visualisations to build ([f828fd4](https://github.com/b0ink/doubtfire-deploy/commit/f828fd42fafaf09d7f807cea8f6a1e14ec56ecc5)) +* link task list to definitions for project dashboard ([90853e9](https://github.com/b0ink/doubtfire-deploy/commit/90853e93c109430669e3f80e4324649cd2d0dba6)) +* new burndown and task status count ([bfecd08](https://github.com/b0ink/doubtfire-deploy/commit/bfecd086eeeae33e9bbba430c79bcc4f21506a07)) +* only render if submission date is valid ([04986a0](https://github.com/b0ink/doubtfire-deploy/commit/04986a0e501f0185dbd199b8d2554133217f7e75)) +* open report in turnitin ([091aaf8](https://github.com/b0ink/doubtfire-deploy/commit/091aaf8ba744bbf677f9b8f51a58bc16b7d631ab)) +* remove hardcoded chart view size ([1b31930](https://github.com/b0ink/doubtfire-deploy/commit/1b319303ac969ef63617b2362297233bc79bb916)) +* remove markdown filter from learning outcomes ([1de217c](https://github.com/b0ink/doubtfire-deploy/commit/1de217c0bc19b8dbedb21cf2e89e195772ae2a02)) +* set task data for project dashboard state ([ef75340](https://github.com/b0ink/doubtfire-deploy/commit/ef7534064ef92c06e459953076bc30b6eff4647d)) +* support building on windows ([b2aa7ae](https://github.com/b0ink/doubtfire-deploy/commit/b2aa7ae6ea7a456953ed4f2a8c63f784ac3870b5)) +* switch staff to unit roles in unit service ([0e5d9de](https://github.com/b0ink/doubtfire-deploy/commit/0e5d9de9df2eaf16e473f4f8fde920ffb59ce765)) +* task route transition race when switching from inbox ([63c52dc](https://github.com/b0ink/doubtfire-deploy/commit/63c52dc4cdb2f2fbc701f69c64b7273f5778c868)) + ### [10.0.1-35](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-34...v10.0.1-35) (2026-04-28) diff --git a/package-lock.json b/package-lock.json index e9b7526355..69cfec245b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.1-35", + "version": "11.0.0-1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.1-35", + "version": "11.0.0-1", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index edff34e09e..6b2eea5828 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.1-35", + "version": "11.0.0-1", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 014c778fa238273ed6b7535ec2ddbb78c5eb3072 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 13 May 2026 13:49:21 +1000 Subject: [PATCH 1013/1531] chore: disable ngsw and set beta href --- angular.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/angular.json b/angular.json index aad04ef924..f71b44e605 100644 --- a/angular.json +++ b/angular.json @@ -85,7 +85,8 @@ "outputHashing": "bundles", "sourceMap": false, "extractLicenses": true, - "serviceWorker": "ngsw-config.json" + "baseHref": "/beta/", + "deployUrl": "/beta/" }, "development": { "optimization": false, From eab4bc4a80dfc081e1b087379dc3840aeebb3311 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 13 May 2026 13:49:30 +1000 Subject: [PATCH 1014/1531] chore(release): 11.0.0-2 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85f1206dfe..cfb5ee2c02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-2](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-1...v11.0.0-2) (2026-05-13) + ## [11.0.0-1](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-21...v11.0.0-1) (2026-05-13) diff --git a/package-lock.json b/package-lock.json index 69cfec245b..e02d692e47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-1", + "version": "11.0.0-2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-1", + "version": "11.0.0-2", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 6b2eea5828..a2f1b0884a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-1", + "version": "11.0.0-2", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 41a2ec0d071043860e1b9b98f564fece3e4fb16b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 13 May 2026 13:58:50 +1000 Subject: [PATCH 1015/1531] chore: enable beta access --- ngsw-config.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ngsw-config.json b/ngsw-config.json index 5c8069284f..7e559abeb8 100644 --- a/ngsw-config.json +++ b/ngsw-config.json @@ -55,6 +55,8 @@ "!/JPlag/**", "!/JPlag", "!/sidekiq/**", - "!/sidekiq" + "!/sidekiq", + "!/beta/**", + "!/beta" ] } From 5cdae6313030850c75918627269b55fc888c00ef Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 13 May 2026 14:00:33 +1000 Subject: [PATCH 1016/1531] chore(release): 10.0.1-38 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c02ea7571..8dcf8745cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [10.0.1-38](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-37...v10.0.1-38) (2026-05-13) + ### [10.0.1-37](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-36...v10.0.1-37) (2026-05-12) diff --git a/package-lock.json b/package-lock.json index 9326ac911f..0d00669e9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.1-37", + "version": "10.0.1-38", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.1-37", + "version": "10.0.1-38", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 0802cc8121..11df0fa2f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.1-37", + "version": "10.0.1-38", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 5702082e7934ebcb8d4ae259b5904fd12cf04866 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 11:29:22 +1000 Subject: [PATCH 1017/1531] chore: null check unit role --- .../directives/task-status-card/task-status-card.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts index b4233712db..3bf4faf9a8 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts @@ -137,6 +137,6 @@ export class TaskStatusCardComponent implements OnChanges, AfterViewInit { } public get isTutor(): boolean { - return this.currentUnitRole.role === 'Convenor' || this.currentUnitRole.role === 'Tutor'; + return this.currentUnitRole?.role === 'Convenor' || this.currentUnitRole?.role === 'Tutor'; } } From 714303e21daf48cbd5e2dd417d04da2aafa63ae3 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 11:29:43 +1000 Subject: [PATCH 1018/1531] chore(release): 10.0.1-39 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dcf8745cc..bb308e9538 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [10.0.1-39](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-38...v10.0.1-39) (2026-05-14) + ### [10.0.1-38](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-37...v10.0.1-38) (2026-05-13) ### [10.0.1-37](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-36...v10.0.1-37) (2026-05-12) diff --git a/package-lock.json b/package-lock.json index 0d00669e9c..404cdd3efc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "10.0.1-38", + "version": "10.0.1-39", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "10.0.1-38", + "version": "10.0.1-39", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^17.3.6", diff --git a/package.json b/package.json index 11df0fa2f2..82a21b89d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "10.0.1-38", + "version": "10.0.1-39", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 6837414ec0cfc03c302e572fe86582eb0901c009 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 13:03:28 +1000 Subject: [PATCH 1019/1531] refactor: add missing badges in task list --- src/app/api/models/task.ts | 4 +- ...te-portfolio-task-list-item.component.html | 2 +- .../unit-task-list.component.html | 124 ++++++++++++++++-- .../unit-task-list.component.ts | 4 + 4 files changed, 122 insertions(+), 12 deletions(-) diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index 20c5a66eaf..c8787c0795 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -525,9 +525,9 @@ export class Task extends Entity { public timeToDue(): string { const days = this.daysUntilDueDate(); if (days < 0) { - return '!'; + return 'Past Due Date'; } else if (days < 11) { - return `${days}d`; + return `Due in ${days} day${days > 1 ? 's' : ''}`; } else { return `${Math.floor(days / 7)}w`; } diff --git a/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html b/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html index bf3f0c0baf..c5a07269cc 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html +++ b/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html @@ -1,5 +1,5 @@
    diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index e620e5b0a6..e7efd21ac8 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -24,38 +24,144 @@ @for (taskDef of filteredTaskDefinitions; track taskDef) { @if (taskDef) { -
    +
    {{ taskDef.name }}
    -
    +
    @if (taskDef.isGroupTask()) { - groups + groups } @else { - person + person } -
    +
    {{ taskDef.abbreviation }} - {{ gradeNames[taskDef.targetGrade] }} Task
    + @if (taskListItem(taskDef); as task) { + + @if (!task.isBeforeStartDate() && !task.inSubmittedState()) { + + hourglass_bottom + {{ task.timeToDue() }} + + } + }
    - @if (hasTasks && taskForTaskDef(taskDef)) { - + @if (taskListItem(taskDef); as task) { +
    + + +
    + @if (task.numNewComments > 0) { + + {{ task.numNewComments }} + + } + @if (task.similaritiesDetected) { + + visibility + + } +
    + +
    + @if (task.hasGrade()) { + + {{ task.gradeDesc() }} + + } + @if (task.hasQualityPoints()) { + + {{ task.qualityPts }} + + {{ + task.definition.maxQualityPts + }} + + } + @if (task.isDueSoon() && !task.inFinalState()) { + + schedule + + } + @if ( + task.betweenDueDateAndDeadlineDate() && + !task.isPastDeadline() && + !task.inFinalState() + ) { + + schedule + + } + @if (task.isPastDeadline() && !task.inFinalState()) { + + schedule + ! + + } +
    +
    }
    } diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index 89a2131f06..cbe680d79a 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -65,6 +65,10 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { return this.tasks.find((task) => task.definition.id === taskDef?.id); } + public taskListItem(taskDef: TaskDefinition): Task { + return this.taskForTaskDef(taskDef); + } + /* TODO: There's still an issue where loading the route for the first time will cause child components (like task-dashboard) to load trigger OnInit and OnChanges twice... Causing duplicate queries to submission_details and task comments. From 94f4216e588d6dfb6abc4d10804971cb0e8f8678 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 13:05:49 +1000 Subject: [PATCH 1020/1531] fix: add padding --- src/app/common/footer/footer.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index be4c9bf647..4a451a79d7 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -1,4 +1,4 @@ - + @if (selectedTask?.similaritiesDetected) {

    Date: Thu, 14 May 2026 13:31:09 +1000 Subject: [PATCH 1021/1531] refactor: fix inbox layout --- src/app/common/footer/footer.component.html | 2 +- src/app/common/footer/footer.component.scss | 1 + .../projects/states/index/global-state.service.ts | 15 ++++++++++----- .../units/states/tasks/inbox/inbox.component.html | 2 +- .../inbox/unit-task-inbox-state.component.ts | 6 +++++- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index 4a451a79d7..be4c9bf647 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -1,4 +1,4 @@ - + @if (selectedTask?.similaritiesDetected) {

    ; private _showFooter = false; + private _isInboxState = false; private _showFooterWarning = false; /** @@ -148,7 +149,9 @@ export class GlobalStateService implements OnDestroy { setTimeout(() => { const vh = window.innerHeight * 0.01; - if (!this.mediaObserver.isActive('gt-sm') || !this._showFooter) { + if (this._isInboxState) { + document.body.style.setProperty('--vh', `${vh}px`); + } else if (!this.mediaObserver.isActive('gt-sm') || !this._showFooter) { document.body.style.setProperty('--vh', `${vh - 0.2}px`); } else { if (this._showFooter && !this._showFooterWarning) { @@ -161,13 +164,14 @@ export class GlobalStateService implements OnDestroy { } public get isInboxState(): boolean { - return this._showFooter; + return this._isInboxState; } public setInboxState() { - this._showFooter = true; - // set background color to white + this._isInboxState = true; + // set background color to inbox grey document.body.style.setProperty('background-color', '#f5f5f5'); + this.resetHeight(); } public goHome() { @@ -176,9 +180,10 @@ export class GlobalStateService implements OnDestroy { } public setNotInboxState() { - this._showFooter = false; + this._isInboxState = false; // set background color to white document.body.style.setProperty('background-color', '#fff'); + this.resetHeight(); } public showFooter(): void { diff --git a/src/app/units/states/tasks/inbox/inbox.component.html b/src/app/units/states/tasks/inbox/inbox.component.html index 0ff4e12217..93178c5467 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.html +++ b/src/app/units/states/tasks/inbox/inbox.component.html @@ -1,5 +1,5 @@ @if (!isMobileView) { -

    +
    @if (taskData) { diff --git a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts index c362f24749..3cf5547882 100644 --- a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts +++ b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts @@ -82,6 +82,8 @@ export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { ) {} ngOnInit(): void { + this.globalStateService.setInboxState(); + this.routeMode = this.route.snapshot.data.routeMode ?? this.routeMode; this.configureRouteMode(); this.setTaskKeyFromRoute(); @@ -121,7 +123,9 @@ export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { }); } - ngOnDestroy(): void {} + ngOnDestroy(): void { + this.globalStateService.setNotInboxState(); + } private getTaskSource(): TaskSource { switch (this.routeMode) { From f4e4ff6d5541b3bcdef251f396d1590ad139a88c Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 13:31:45 +1000 Subject: [PATCH 1022/1531] chore(release): 11.0.0-3 --- CHANGELOG.md | 8 ++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfb5ee2c02..999c07b59c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-3](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-2...v11.0.0-3) (2026-05-14) + + +### Bug Fixes + +* add padding ([94f4216](https://github.com/b0ink/doubtfire-deploy/commit/94f4216e588d6dfb6abc4d10804971cb0e8f8678)) +* unlock task status selection for staff ([#1222](https://github.com/b0ink/doubtfire-deploy/issues/1222)) ([e4080d0](https://github.com/b0ink/doubtfire-deploy/commit/e4080d03a629654518bc362f48e8e0fbb790dd96)) + ## [11.0.0-2](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-1...v11.0.0-2) (2026-05-13) ## [11.0.0-1](https://github.com/b0ink/doubtfire-deploy/compare/v10.0.1-21...v11.0.0-1) (2026-05-13) diff --git a/package-lock.json b/package-lock.json index e02d692e47..56e0dd6f6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-2", + "version": "11.0.0-3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-2", + "version": "11.0.0-3", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index a2f1b0884a..c54fc09535 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-2", + "version": "11.0.0-3", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From e956ea8c2560bd19b7ccacec29fc7a00c183cae8 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 14:27:30 +1000 Subject: [PATCH 1023/1531] refactor: improve unauthorised component styling --- .../unauthorised/unauthorised.component.html | 12 ++++++------ .../unauthorised/unauthorised.component.scss | 14 -------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/src/app/errors/states/unauthorised/unauthorised.component.html b/src/app/errors/states/unauthorised/unauthorised.component.html index 6954101277..262a097696 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.html +++ b/src/app/errors/states/unauthorised/unauthorised.component.html @@ -1,7 +1,7 @@ - -
    - warning -
    +
    + warning

    Unauthorised

    -

    You do not have sufficient permissions to access this resource, or your session has expired.

    - +

    + You do not have sufficient permissions to access this resource, or your session has expired. +

    +
    diff --git a/src/app/errors/states/unauthorised/unauthorised.component.scss b/src/app/errors/states/unauthorised/unauthorised.component.scss index 52cb7522ff..e69de29bb2 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.scss +++ b/src/app/errors/states/unauthorised/unauthorised.component.scss @@ -1,14 +0,0 @@ -.icon-display { - font-size: 15rem; - padding-top: 10px; - padding-bottom: 10px; - -} - -.icon-container{ - padding-right: 12rem; -} - -.text-centre{ - text-align: center; -} \ No newline at end of file From f8b11af1abb5ff66200f790ec164a2105761fe77 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 14:31:44 +1000 Subject: [PATCH 1024/1531] refactor: add go back button --- .../unauthorised/unauthorised.component.html | 1 + .../unauthorised/unauthorised.component.ts | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/app/errors/states/unauthorised/unauthorised.component.html b/src/app/errors/states/unauthorised/unauthorised.component.html index 262a097696..5bca2da675 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.html +++ b/src/app/errors/states/unauthorised/unauthorised.component.html @@ -4,4 +4,5 @@

    Unauthorised

    You do not have sufficient permissions to access this resource, or your session has expired.

    +
    diff --git a/src/app/errors/states/unauthorised/unauthorised.component.ts b/src/app/errors/states/unauthorised/unauthorised.component.ts index 7ec73045c5..289a4ad067 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.ts +++ b/src/app/errors/states/unauthorised/unauthorised.component.ts @@ -1,11 +1,16 @@ -import { Component } from '@angular/core'; +import {Location} from '@angular/common'; +import {Component} from '@angular/core'; @Component({ - selector: 'unauthorised', - templateUrl: 'unauthorised.component.html', - styleUrls: ['unauthorised.component.scss'], - standalone: false + selector: 'unauthorised', + templateUrl: 'unauthorised.component.html', + styleUrls: ['unauthorised.component.scss'], + standalone: false, }) export class UnauthorisedComponent { - constructor(){} + constructor(private location: Location) {} + + goBack() { + this.location.back(); + } } From b7585a4f969b62382ee933cca88d88b7d011a633 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 14:44:56 +1000 Subject: [PATCH 1025/1531] chore: format time until due --- src/app/api/models/task.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index c8787c0795..b0ed8902e4 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -527,7 +527,7 @@ export class Task extends Entity { if (days < 0) { return 'Past Due Date'; } else if (days < 11) { - return `Due in ${days} day${days > 1 ? 's' : ''}`; + return `Due in ${this.timeUntilDueDateDescription()}`; } else { return `${Math.floor(days / 7)}w`; } From fb2e78113b13782dbbafe38c21f27c5d63be69c6 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 14:54:09 +1000 Subject: [PATCH 1026/1531] feat: add route auth guards --- src/app/app.routes.ts | 47 +++++++++++++--- src/app/common/guards/role-whitelist.guard.ts | 56 +++++++++++++++++++ 2 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 src/app/common/guards/role-whitelist.guard.ts diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 418c94d789..9b9bbc6da4 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -32,6 +32,7 @@ import {TaskViewerStateComponent} from './units/task-viewer/task-viewer-state.co import {resolveUnit} from './units/unit.resolver'; import {UnitRootStateComponent} from './units/unit-root-state.component'; import {WelcomeComponent} from './welcome/welcome.component'; +import {roleWhitelistGuard} from './common/guards/role-whitelist.guard'; export const routes: Routes = [ {path: '', pathMatch: 'full', redirectTo: 'home'}, @@ -63,11 +64,35 @@ export const routes: Routes = [ }, {path: 'view-all-units', component: FUnitsComponent, data: {mode: 'tutor'}}, {path: 'view-all-projects', component: FUnitsComponent, data: {mode: 'student'}}, - {path: 'admin/units', component: FUnitsComponent, data: {mode: 'admin'}}, - {path: 'admin/users', component: FUsersComponent}, - {path: 'admin/institution-settings', component: InstitutionSettingsComponent}, - {path: 'tutor-discussion', component: TutorDiscussionComponent, data: {task: 'Discussion'}}, - {path: 'tutor-attendance', component: TutorDiscussionComponent, data: {attendance: true, task: 'Check-in'}}, + { + path: 'admin/units', + component: FUnitsComponent, + canActivate: [roleWhitelistGuard], + data: {mode: 'admin', roleWhitelist: ['Admin', 'Auditor', 'Convenor']}, + }, + { + path: 'admin/users', + component: FUsersComponent, + canActivate: [roleWhitelistGuard], + data: {roleWhitelist: ['Admin', 'Auditor']}, + }, + { + path: 'admin/institution-settings', + component: InstitutionSettingsComponent, + canActivate: [roleWhitelistGuard], + data: {roleWhitelist: ['Admin', 'Auditor']}, + }, + { + path: 'tutor-discussion', + component: TutorDiscussionComponent, + canActivate: [roleWhitelistGuard], + data: {task: 'Discussion', roleWhitelist: ['Admin', 'Auditor', 'Tutor']}, + }, + { + path: 'tutor-attendance', + component: TutorDiscussionComponent, + data: {attendance: true, task: 'Check-in'}, + }, {path: 'projects2/:projectId', pathMatch: 'full', redirectTo: 'projects/:projectId/dashboard'}, { path: 'projects2/:projectId/dashboard2', @@ -149,12 +174,14 @@ export const routes: Routes = [ { path: 'admin', component: UnitAdminStateComponent, - data: {task: 'Unit Administration'}, + canActivate: [roleWhitelistGuard], + data: {task: 'Unit Administration', roleWhitelist: ['Convenor', 'Admin', 'Auditor']}, }, { path: 'admin/:tab', component: UnitAdminStateComponent, - data: {task: 'Unit Administration'}, + canActivate: [roleWhitelistGuard], + data: {task: 'Unit Administration', roleWhitelist: ['Convenor', 'Admin', 'Auditor']}, }, {path: 'rollover', component: RolloverComponent, data: {task: 'Unit Rollover'}}, {path: 'discussion', component: TutorDiscussionComponent, data: {task: 'Discussion'}}, @@ -167,10 +194,14 @@ export const routes: Routes = [ path: 'tasks', pathMatch: 'full', component: TaskViewerStateComponent, - data: {task: 'Task Lists'}, + data: {task: 'Task Lists', roleWhitelist: ['Convenor', 'Admin', 'Auditor']}, + canActivate: [roleWhitelistGuard], }, { path: 'tasks', + canActivate: [roleWhitelistGuard], + data: {roleWhitelist: ['Convenor', 'Admin', 'Auditor']}, + children: [ {path: '', pathMatch: 'full', redirectTo: 'inbox'}, { diff --git a/src/app/common/guards/role-whitelist.guard.ts b/src/app/common/guards/role-whitelist.guard.ts new file mode 100644 index 0000000000..2cbd19edf7 --- /dev/null +++ b/src/app/common/guards/role-whitelist.guard.ts @@ -0,0 +1,56 @@ +import {inject} from '@angular/core'; +import {ActivatedRouteSnapshot, CanActivateFn, Router, UrlTree} from '@angular/router'; +import {filter, map, Observable, of, take} from 'rxjs'; +import {AuthenticationService, UserService} from 'src/app/api/models/doubtfire-model'; +import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; + +export const roleWhitelistGuard: CanActivateFn = ( + route: ActivatedRouteSnapshot, +): Observable => { + const authenticationService = inject(AuthenticationService); + const globalState = inject(GlobalStateService); + const router = inject(Router); + const userService = inject(UserService); + const roleWhitelist = route.data['roleWhitelist'] as string[] | undefined; + + if (!roleWhitelist?.length) { + return of(true); + } + + return globalState.isLoadingSubject.pipe( + filter((isLoading) => !isLoading), + take(1), + map(() => { + const role = roleForRoute(route, userService, globalState); + return authenticationService.isAuthorised(roleWhitelist, role) + ? true + : router.createUrlTree(['/unauthorised']); + }), + ); +}; + +function roleForRoute( + route: ActivatedRouteSnapshot, + userService: UserService, + globalState: GlobalStateService, +): string | undefined { + const unitId = Number(route.paramMap.get('unitId') ?? route.parent?.paramMap.get('unitId')); + + if (!Number.isNaN(unitId) && unitId > 0) { + const unitRole = globalState.loadedUnitRoles.currentValues.find( + (role) => role.unit?.id === unitId, + ); + + if (unitRole) { + return unitRole.role; + } + + if (userService.currentUser.role === 'Admin' || userService.currentUser.role === 'Auditor') { + return userService.currentUser.role; + } + + return undefined; + } + + return userService.currentUser.role; +} From 05d3eda76bdcfb491649f5d83e69213db3de0885 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 15:19:06 +1000 Subject: [PATCH 1027/1531] fix: enable inbox access for tutors --- src/app/app.routes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 9b9bbc6da4..c8b73f53d4 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -200,7 +200,7 @@ export const routes: Routes = [ { path: 'tasks', canActivate: [roleWhitelistGuard], - data: {roleWhitelist: ['Convenor', 'Admin', 'Auditor']}, + data: {roleWhitelist: ['Convenor', 'Admin', 'Auditor', 'Tutor']}, children: [ {path: '', pathMatch: 'full', redirectTo: 'inbox'}, From 164fbc3fc6fb59df35ee8323685c7ec9eb4682a3 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 15:25:04 +1000 Subject: [PATCH 1028/1531] chore: upgrade ngx-entity-service --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 56e0dd6f6e..1d780776dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,7 +57,7 @@ "ng-flex-layout": "^17.3.7-beta.1", "ng2-pdf-viewer": "10.2.2", "ngx-bootstrap": "^6.1.0", - "ngx-entity-service": "^0.0.42", + "ngx-entity-service": "^0.0.43", "ngx-lottie": "^11.0.2", "ngx-monaco-editor-v2": "^21", "npm": "^10.4.0", @@ -15904,9 +15904,9 @@ } }, "node_modules/ngx-entity-service": { - "version": "0.0.42", - "resolved": "https://registry.npmjs.org/ngx-entity-service/-/ngx-entity-service-0.0.42.tgz", - "integrity": "sha512-RmehGi3FmftKz2W/i9o35MwR548mz+I/pRXPgU9CWtMhi4VFqqrq5+XFrzSzx3iMpRuLHER19tmdFnX5PYihtQ==", + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/ngx-entity-service/-/ngx-entity-service-0.0.43.tgz", + "integrity": "sha512-O77ZIu3822bKsiL8nBpj+4DW5q6V53URO5iiAojYVwITdd2zFmsiOZjgrYUEjEAIT7B+o5sDKvpzROZ1CS33OQ==", "dependencies": { "tslib": "^2.3.0" }, diff --git a/package.json b/package.json index c54fc09535..9aec3a9fb0 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "ng-flex-layout": "^17.3.7-beta.1", "ng2-pdf-viewer": "10.2.2", "ngx-bootstrap": "^6.1.0", - "ngx-entity-service": "^0.0.42", + "ngx-entity-service": "^0.0.43", "ngx-lottie": "^11.0.2", "ngx-monaco-editor-v2": "^21", "npm": "^10.4.0", From f1a5020688d06d438f185fe7afd0d75e94f40b6d Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 15:26:22 +1000 Subject: [PATCH 1029/1531] chore(release): 11.0.0-4 --- CHANGELOG.md | 12 ++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 999c07b59c..d77d7c63ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-4](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-3...v11.0.0-4) (2026-05-14) + + +### Features + +* add route auth guards ([fb2e781](https://github.com/b0ink/doubtfire-deploy/commit/fb2e78113b13782dbbafe38c21f27c5d63be69c6)) + + +### Bug Fixes + +* enable inbox access for tutors ([05d3eda](https://github.com/b0ink/doubtfire-deploy/commit/05d3eda76bdcfb491649f5d83e69213db3de0885)) + ## [11.0.0-3](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-2...v11.0.0-3) (2026-05-14) diff --git a/package-lock.json b/package-lock.json index 1d780776dc..5db5a2fe97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-3", + "version": "11.0.0-4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-3", + "version": "11.0.0-4", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 9aec3a9fb0..eaad1f49b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-3", + "version": "11.0.0-4", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 4875e2534349137411cff29cf334afce3a834a70 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 16:01:47 +1000 Subject: [PATCH 1030/1531] chore: display empty similarities --- .../task-similarity-view/task-similarity-view.component.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html index 9dcb038923..97e885640b 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html @@ -87,6 +87,10 @@

    } } + } @empty { +
    + There are no similarities for this submission +
    } } From 7d29aecd07199f508598eeea0874531112fe9eb2 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 16:08:45 +1000 Subject: [PATCH 1031/1531] chore: remove similarities flag from footer --- src/app/common/footer/footer.component.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index be4c9bf647..cb2e0216a7 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -1,5 +1,5 @@ - @if (selectedTask?.similaritiesDetected) { + @@ -180,7 +180,7 @@
    - @if (selectedTask?.similaritiesDetected) { + @if (selectedTask?.project) { @if (selectedTask?.definition.discussionPromptsCount) {
    } @case (InboxDashboardTab.similarities) { diff --git a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts index e0f3f25c31..9c91ae71ee 100644 --- a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts +++ b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts @@ -1,6 +1,8 @@ import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core'; import {MatTabChangeEvent} from '@angular/material/tabs'; +import {UnitRole} from 'src/app/api/models/doubtfire-model'; import {Task} from 'src/app/api/models/task'; +import {UserService} from 'src/app/api/services/user.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; enum InboxDashboardTab { @@ -13,10 +15,10 @@ enum InboxDashboardTab { } @Component({ - selector: 'f-inbox-dashboard', - templateUrl: './inbox-dashboard.component.html', - host: { 'class': 'block h-full' }, - standalone: false + selector: 'f-inbox-dashboard', + templateUrl: './inbox-dashboard.component.html', + host: {'class': 'block h-full'}, + standalone: false, }) export class InboxDashboardComponent implements OnChanges { @Input() task: Task; @@ -26,7 +28,10 @@ export class InboxDashboardComponent implements OnChanges { public currentTab: InboxDashboardTab = InboxDashboardTab.submission; public currentIndex = InboxDashboardTab.submission; - constructor(private fileDownloader: FileDownloaderService) {} + constructor( + private fileDownloader: FileDownloaderService, + private userService: UserService, + ) {} ngOnChanges(changes: SimpleChanges): void { if (changes.task) { @@ -88,4 +93,30 @@ export class InboxDashboardComponent implements OnChanges { return null; } } + + public get currentUnitRole(): UnitRole | undefined { + const currentUser = this.userService.currentUser; + return this.task.unit.staff.find((ur) => ur.user.id === currentUser.id); + } + + public get canAccessTutorNotes(): boolean { + const tutor = this.task.tutor; + if (!tutor) { + return false; + } + + if (!this.currentUnitRole) { + return false; + } + + // Ensure the unit is mapped correctly to access the mentor + tutor.unit = this.task.unit; + + const canAccess = + this.currentUnitRole.role === 'Convenor' || + this.currentUnitRole.role === 'Admin' || + (tutor.mentor && tutor.mentor.id === this.currentUnitRole.id); + + return canAccess; + } } From deaae7fb819ea8dfc01d6ad67415f50c2e4258a2 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 14 May 2026 16:13:38 +1000 Subject: [PATCH 1033/1531] fix: ensure valid selected task --- src/app/common/footer/footer.component.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index cb2e0216a7..ae0ce25e83 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -147,7 +147,7 @@ } @@ -43,17 +48,26 @@ - - - + - \ No newline at end of file + diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.ts index 66cfc03d59..a763a1437b 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.ts @@ -1,26 +1,36 @@ -import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; -import { Task } from 'src/app/api/models/task'; -import { TaskService } from 'src/app/api/services/task.service'; -import { FileDownloaderService } from 'src/app/common/file-downloader/file-downloader.service'; -import { AlertService } from 'src/app/common/services/alert.service'; +import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import {Task} from 'src/app/api/models/task'; +import {TaskService} from 'src/app/api/services/task.service'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {AlertService} from 'src/app/common/services/alert.service'; @Component({ - selector: 'f-task-submission-card', - templateUrl: './task-submission-card.component.html', - styleUrls: ['./task-submission-card.component.scss'], - standalone: false + selector: 'f-task-submission-card', + templateUrl: './task-submission-card.component.html', + styleUrls: ['./task-submission-card.component.scss'], + standalone: false, }) export class TaskSubmissionCardComponent implements OnChanges, OnInit { @Input() task: Task; - canReuploadEvidence: boolean; - canRegeneratePdf: boolean; - submission: { isProcessing: boolean; isUploaded: boolean } = { isProcessing: false, isUploaded: false }; - urls: { pdf: string; files: string }; + + public get canRegeneratePdf(): boolean { + return ( + this.taskService.pdfRegeneratableStatuses.includes(this.task?.status) && this.task?.hasPdf + ); + } + + public get taskPdfUrl(): string { + return this.task?.submissionUrl(true); + } + + public get taskFilesUrl(): string { + return this.task?.submittedFilesUrl(); + } constructor( private taskService: TaskService, private alerts: AlertService, - private fileDownloader: FileDownloaderService + private fileDownloader: FileDownloaderService, ) {} ngOnInit(): void { @@ -36,18 +46,7 @@ export class TaskSubmissionCardComponent implements OnChanges, OnInit { } reapplySubmissionData(): void { - this.task.getSubmissionDetails().subscribe(() => { - this.canReuploadEvidence = this.task.inSubmittedState(); - this.canRegeneratePdf = this.taskService.pdfRegeneratableStatuses.includes(this.task.status) && this.task.hasPdf; - this.submission = { - isProcessing: this.task.processingPdf, - isUploaded: this.task.hasPdf, - }; - this.urls = { - pdf: this.task.submissionUrl(true), - files: this.task.submittedFilesUrl(), - }; - }); + this.task.getSubmissionDetails().subscribe(); } uploadAlternateFiles(): void { @@ -63,7 +62,7 @@ export class TaskSubmissionCardComponent implements OnChanges, OnInit { this.task.processingPdf = true; this.alerts.success( 'The PDF is being regenerated. Please refresh the page in a few minutes.', - 6000 + 6000, ); } }, @@ -74,10 +73,10 @@ export class TaskSubmissionCardComponent implements OnChanges, OnInit { } downloadSubmission(): void { - this.fileDownloader.downloadFile(this.urls.pdf, `${this.task.definition.abbreviation}.pdf`); + this.fileDownloader.downloadFile(this.taskPdfUrl, `${this.task.definition.abbreviation}.pdf`); } downloadSubmissionFiles(): void { - this.fileDownloader.downloadFile(this.urls.files, `${this.task.definition.abbreviation}.zip`); + this.fileDownloader.downloadFile(this.taskFilesUrl, `${this.task.definition.abbreviation}.zip`); } -} \ No newline at end of file +} diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html index 3ff78659d5..a7d0f9b1eb 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html @@ -8,7 +8,16 @@ > - + + + + Your Submission + @if (task.processingPdf) { + + } + + + + + +
    +
    +
    diff --git a/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.scss b/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.ts b/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.ts new file mode 100644 index 0000000000..ae1247d954 --- /dev/null +++ b/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.ts @@ -0,0 +1,28 @@ +import {Component, Input} from '@angular/core'; +import {DashboardTask} from '../dashboard-list-item.component'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; + +@Component({ + selector: 'f-expanded-list-item', + templateUrl: './expanded-list-item.component.html', + styleUrls: ['./expanded-list-item.component.scss'], +}) +export class DashboardExpandedListItemComponent { + @Input() task: DashboardTask; + + constructor(private fileDownloader: FileDownloaderService) {} + + downloadTaskSheet() { + this.fileDownloader.downloadFile( + this.task.taskDef.getTaskPDFUrl(true), + `${this.task.unitCode}-${this.task.abbreviation}-TaskSheet.pdf` + ); + } + + downloadResources() { + this.fileDownloader.downloadFile( + this.task.taskDef.getTaskResourcesUrl(true), + `${this.task.unitCode}-${this.task.abbreviation}-TaskResources.zip` + ); + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index df568bdbe8..d6016da9b3 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -44,7 +44,8 @@ import {MatDialogModule as MatDialogModuleNew} from '@angular/material/dialog'; import {AlertService} from 'src/app/common/services/alert.service'; import {AlertComponent} from 'src/app/common/services/alert.service'; import {MatSidenavModule} from '@angular/material/sidenav'; -import { DashboardListItemComponent } from './dashboard/dashboard-list-item.component'; +import {DashboardListItemComponent} from './dashboard/list-item/dashboard-list-item.component'; +import {DashboardExpandedListItemComponent} from './dashboard/list-item/expanded-list-item/expanded-list-item.component'; import {setTheme} from 'ngx-bootstrap/utils'; import {CodeEditorModule} from '@ngstack/code-editor'; @@ -368,6 +369,7 @@ const GANTT_CHART_CONFIG = { // Components we declare declarations: [ DashboardListItemComponent, + DashboardExpandedListItemComponent, AlertComponent, AboutDoubtfireModalContent, D2lUnitDetailsFormComponent, From 3e40777c07903bbfdb5c7bfedbe40a883eabf347 Mon Sep 17 00:00:00 2001 From: owens-hub-git Date: Mon, 18 May 2026 21:17:45 +1000 Subject: [PATCH 1043/1531] fix: linting and colour changes --- .../dashboard-list-item.component.html | 10 ++++--- .../expanded-list-item.component.html | 29 ++++++++++++++----- .../expanded-list-item.component.scss | 3 ++ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.html b/src/app/dashboard/list-item/dashboard-list-item.component.html index 257fbafb4c..2bbc5cb854 100644 --- a/src/app/dashboard/list-item/dashboard-list-item.component.html +++ b/src/app/dashboard/list-item/dashboard-list-item.component.html @@ -1,17 +1,19 @@
    -

    - {{ task.title }} + [uiParams]="{projectId: task.projectId, taskAbbr: task.abbreviation}" + > + {{ task.title }}

    {{ task.subtitle }}

    - {{ task.comments }} + {{ task.comments }}
    diff --git a/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.html b/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.html index 6454e0939b..21ed3d2345 100644 --- a/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.html +++ b/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.html @@ -3,26 +3,39 @@

    {{ task.statusLabel }}

    {{ task.description }}

    -

    Complete by +

    + Complete by {{ task.dueDate | date: 'EEEE d MMMM' }}

    - - - diff --git a/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.scss b/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.scss index e69de29bb2..a3b7bc573e 100644 --- a/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.scss +++ b/src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.scss @@ -0,0 +1,3 @@ +.mat-badge-warn { + --mat-badge-text-color: white; +} From aeca8291c770d0a073d66b1c20bc3282f3b872a6 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 19 May 2026 01:35:17 +1000 Subject: [PATCH 1044/1531] chore: disable mouse events eslint --- eslint.config.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index a519ed7891..281102fa9e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -58,6 +58,8 @@ module.exports = tseslint.config( // Apply the Angular template rules which focus on accessibility of our apps ...angular.configs.templateAccessibility, ], - rules: {}, + rules: { + '@angular-eslint/template/mouse-events-have-key-events': 'off', + }, }, ); From 215579030b7ab539b29c03c9a601750e3ffaaeef Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 19 May 2026 01:36:13 +1000 Subject: [PATCH 1045/1531] refactor: add skeleton ui unit and inbox loading --- package-lock.json | 14 + package.json | 1 + src/app/doubtfire-angular.module.ts | 2 + src/app/projects/project.resolver.ts | 50 ++-- .../project-dashboard.component.html | 65 ++++- .../project-dashboard.component.ts | 83 +++++- .../staff-task-list.component.html | 49 +++- .../staff-task-list.component.ts | 2 + .../states/tasks/inbox/inbox.component.html | 242 +++++++++++------- .../states/tasks/inbox/inbox.component.ts | 1 + .../unit-task-inbox-state.component.html | 5 +- .../inbox/unit-task-inbox-state.component.ts | 15 +- src/app/units/unit.resolver.ts | 23 +- 13 files changed, 416 insertions(+), 136 deletions(-) diff --git a/package-lock.json b/package-lock.json index 75774ca976..9a7c90b0de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,6 +60,7 @@ "ngx-entity-service": "^0.0.43", "ngx-lottie": "^11.0.2", "ngx-monaco-editor-v2": "^21", + "ngx-skeleton-loader": "^12.0.0", "npm": "^10.4.0", "nvd3": "1.8.6", "qrcode": "^1.5.4", @@ -15941,6 +15942,19 @@ "monaco-editor": "^0.55.1" } }, + "node_modules/ngx-skeleton-loader": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ngx-skeleton-loader/-/ngx-skeleton-loader-12.0.0.tgz", + "integrity": "sha512-vGEytpLElYKSLovFHCJkwgPZOdy0lPqyejxuhVFcZJg9dsp07o0/NeM4/Nnc2oCDE8T/wkXSPIbrpKzfTDbMCQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": ">=19.0.0", + "@angular/core": ">=19.0.0" + } + }, "node_modules/no-case": { "version": "2.3.2", "dev": true, diff --git a/package.json b/package.json index 3641b0472a..5e74d844f5 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "ngx-entity-service": "^0.0.43", "ngx-lottie": "^11.0.2", "ngx-monaco-editor-v2": "^21", + "ngx-skeleton-loader": "^12.0.0", "npm": "^10.4.0", "nvd3": "1.8.6", "qrcode": "^1.5.4", diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 6bfd207b53..1b43b1af94 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -41,6 +41,7 @@ import {MatTooltipModule} from '@angular/material/tooltip'; import player from 'lottie-web'; import {PdfViewerModule} from 'ng2-pdf-viewer'; import {LottieComponent, provideLottieOptions} from 'ngx-lottie'; +import {NgxSkeletonLoaderModule} from 'ngx-skeleton-loader'; import {AlertComponent, AlertService} from 'src/app/common/services/alert.service'; import {ProgressDashboardComponent} from './projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component'; @@ -751,6 +752,7 @@ const GANTT_CHART_CONFIG = { NgxGanttModule, MonacoEditorModule.forRoot(), MatChipListbox, + NgxSkeletonLoaderModule, ], bootstrap: [AppComponent], }) diff --git a/src/app/projects/project.resolver.ts b/src/app/projects/project.resolver.ts index c3cb9dadf9..d5f16b2d0e 100644 --- a/src/app/projects/project.resolver.ts +++ b/src/app/projects/project.resolver.ts @@ -1,32 +1,42 @@ import {ResolveFn} from '@angular/router'; -import {AsyncSubject} from 'rxjs'; +import {Observable} from 'rxjs'; import {Project, ProjectService} from 'src/app/api/models/doubtfire-model'; import {GlobalStateService, ViewType} from './states/index/global-state.service'; import {inject} from '@angular/core'; -export const resolveProject: ResolveFn = (route) => { +export const resolveProject: ResolveFn = (route, state) => { const projectService = inject(ProjectService); const globalState = inject(GlobalStateService); const projectId = Number(route.paramMap.get('projectId')); - const result = new AsyncSubject(); + const resolveProgressively = state.url.split('?')[0].includes('/dashboard'); - const mappingCompleteCallback = (project: Project) => { - globalState.setView(ViewType.PROJECT, project); - result.next(project); - result.complete(); - }; + return new Observable((observer) => { + const mappingCompleteCallback = (project: Project) => { + globalState.setView(ViewType.PROJECT, project); + if (!resolveProgressively) { + observer.next(project); + observer.complete(); + } + }; - globalState.onLoad(() => { - projectService - .get( - {id: projectId}, - { - cacheBehaviourOnGet: 'cacheQuery', - mappingCompleteCallback, - }, - ) - .subscribe(); - }); + globalState.onLoad(() => { + if (resolveProgressively) { + observer.next(projectService.cache.getOrCreate(projectId, projectService, {id: projectId})); + observer.complete(); + return; + } - return result; + projectService + .get( + {id: projectId}, + { + cacheBehaviourOnGet: 'cacheQuery', + mappingCompleteCallback, + }, + ) + .subscribe({ + error: (error) => observer.error(error), + }); + }); + }); }; diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html index b806be00a2..d701893c18 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html @@ -1,18 +1,60 @@ + +
    +
    +
    + + +
    +
    + +
    + @for (row of skeletonRows; track row) { +
    +
    + + +
    + +
    + } +
    +
    +
    + @if (project$ | async; as project) {
    @if (subs$ | async) { - @if (project.unit.taskDefinitions.length > 0) { + @if (isProjectTaskListReady(project)) { + } @else { +
    + +
    }
    + } @else if (!isProjectTaskListReady(project)) { +
    +
    + + + +
    +
    } @else {
    diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts index a4d94f75d7..eaff580905 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts @@ -7,21 +7,23 @@ import { Observable, Subject, auditTime, + first, merge, of, tap, withLatestFrom, } from 'rxjs'; import {ProjectService} from 'src/app/api/services/project.service'; +import {UnitService} from 'src/app/api/services/unit.service'; import {GlobalStateService, ViewType} from '../../index/global-state.service'; import {UserService} from 'src/app/api/services/user.service'; import {Project, TaskDefinition} from 'src/app/api/models/doubtfire-model'; @Component({ - selector: 'f-project-dashboard', - templateUrl: './project-dashboard.component.html', - styleUrl: './project-dashboard.component.scss', - standalone: false + selector: 'f-project-dashboard', + templateUrl: './project-dashboard.component.html', + styleUrl: './project-dashboard.component.scss', + standalone: false, }) export class ProjectDashboardComponent implements OnInit { @Input() public project$: Observable; @@ -34,16 +36,20 @@ export class ProjectDashboardComponent implements OnInit { new BehaviorSubject(null); subs$: Observable; + readonly skeletonRows = Array.from({length: 10}, (_, index) => index); + private readonly projectSubject = new BehaviorSubject(null); private leftComponentStartSize$ = new Subject(); private dragMove$ = new Subject<{event: CdkDragMove; div: HTMLDivElement}>(); private dragMoveAudited$; + private projectReady = false; projectTasks = []; constructor( private currentUser: UserService, private projectService: ProjectService, + private unitService: UnitService, private globalStateService: GlobalStateService, private route: ActivatedRoute, ) {} @@ -54,6 +60,24 @@ export class ProjectDashboardComponent implements OnInit { public startLeftX = 0; + public isProjectTaskListReady(project: Project): boolean { + return ( + this.projectReady && + !!project?.id && + !!project.unit?.id && + project.targetGrade !== undefined && + project.targetGrade !== null + ); + } + + public taskDefinitionsForProject(project: Project): TaskDefinition[] { + if (!this.isProjectTaskListReady(project)) { + return []; + } + + return project.unit.taskDefinitionsForGrade(project.targetGrade); + } + startedDragging(event: CdkDragStart, boundary: HTMLElement) { const rect = boundary.getBoundingClientRect(); // x relative to the container @@ -80,7 +104,15 @@ export class ProjectDashboardComponent implements OnInit { } ngOnInit(): void { - this.project$ = this.project$ ?? of(this.route.parent?.snapshot.data.project as Project); + const initialProject$ = + this.project$ ?? of(this.route.parent?.snapshot.data.project as Project); + this.project$ = this.projectSubject.asObservable(); + initialProject$.pipe(first()).subscribe((project) => { + this.projectSubject.next(project); + this.loadProject( + project?.id ?? Number(this.route.parent?.snapshot.paramMap.get('projectId')), + ); + }); this.dragMoveAudited$ = this.dragMove$.pipe( withLatestFrom(this.leftComponentStartSize$), @@ -112,4 +144,45 @@ export class ProjectDashboardComponent implements OnInit { this.subs$ = merge(this.dragMoveAudited$, of(true)); window.dispatchEvent(new Event('resize')); } + + private loadProject(projectId: number): void { + if (!projectId) { + return; + } + + this.projectService + .get( + {id: projectId}, + { + cacheBehaviourOnGet: 'cacheQuery', + mappingCompleteCallback: (project: Project) => this.loadUnit(project), + }, + ) + .subscribe(); + } + + private loadUnit(project: Project): void { + const unitId = project.unit?.id; + if (!unitId) { + this.showLoadedProject(project); + return; + } + + this.unitService.get(unitId).subscribe({ + next: (unit) => { + project.unit = unit; + unit.studentCache.add(project); + this.showLoadedProject(project); + }, + error: () => { + this.showLoadedProject(project); + }, + }); + } + + private showLoadedProject(project: Project): void { + this.projectReady = true; + this.globalStateService.setView(ViewType.PROJECT, project); + this.projectSubject.next(project); + } } diff --git a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html index 7994495ae3..d013d91a1a 100644 --- a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html +++ b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html @@ -219,16 +219,57 @@
    } -
    - hourglass_bottom -
    + @if (loading) { +
    + @for (row of skeletonRows; track row) { +
    + + +
    + + +
    + +
    + } +
    + }
    done_all
    - @if (filteredTasks) { + @if (filteredTasks && !loading) { @if (filteredTasks.length) {
    {{ filteredTasks.length }} Tasks
    diff --git a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts index fa2423e573..89997623cb 100644 --- a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts +++ b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts @@ -105,6 +105,7 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { panelOpenState = false; loading = true; + skeletonRows = Array.from({length: 12}, (_, index) => index); definedTasksPipe = new TasksOfTaskDefinitionPipe(); tasksInTutorialsPipe = new TasksInTutorialsPipe(); @@ -587,6 +588,7 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { }, error: (message) => { this.alertService.error(message, 6000); + this.loading = false; }, }); } diff --git a/src/app/units/states/tasks/inbox/inbox.component.html b/src/app/units/states/tasks/inbox/inbox.component.html index 93178c5467..b7cded7591 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.html +++ b/src/app/units/states/tasks/inbox/inbox.component.html @@ -1,106 +1,166 @@ + +
    + + @for (row of [0, 1, 2, 3, 4, 5, 6, 7]; track row) { +
    + + +
    + + +
    + +
    + } +
    +
    + + + + + @if (!isMobileView) { -
    -
    -
    - @if (taskData) { - +
    +
    +
    + @if (loading) { + + } @else if (taskData) { + + } +
    + @if (subs$ | async) { +
    } -
    - @if (subs$ | async) { + +
    + @if (loading) { + + } @else { + + } +
    - } - -
    - -
    -
    -
    - +
    + @if (loading) { + + } @else { + + } +
    +
    - -
    } @else { -
    -
    - @if (taskData) { - - } -
    -
    -
    - -

    {{ taskData?.selectedTask?.project.student.nickname }}

    -
    - - +
    +
    + @if (loading) { + + } @else if (taskData) { + + }
    +
    +
    + +

    {{ taskData?.selectedTask?.project.student.nickname }}

    +
    + + +
    -
    - +
    + @if (loading) { + + } @else { + + } +
    -
    } diff --git a/src/app/units/states/tasks/inbox/inbox.component.ts b/src/app/units/states/tasks/inbox/inbox.component.ts index b9cadd8e8f..1d0bd529d7 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.ts +++ b/src/app/units/states/tasks/inbox/inbox.component.ts @@ -25,6 +25,7 @@ export class InboxComponent implements OnInit, OnDestroy { @Input() unit: Unit; @Input() unitRole: UnitRole; @Input() taskData: {selectedTask: Task; any}; + @Input() loading = false; @Input() filters: Partial<{ taskDefinition: TaskDefinition; tutorials: Tutorial[]; diff --git a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html index 7d5fc01f5d..fc283c02a6 100644 --- a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html +++ b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html @@ -1,13 +1,10 @@ -@if (unit && unitRole && studentsLoaded) { -} diff --git a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts index 23cce689bf..d8d6bfe81e 100644 --- a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts +++ b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts @@ -39,9 +39,9 @@ type TaskSource = ( ) => Observable; @Component({ - selector: 'f-unit-task-inbox-state', - templateUrl: './unit-task-inbox-state.component.html', - standalone: false + selector: 'f-unit-task-inbox-state', + templateUrl: './unit-task-inbox-state.component.html', + standalone: false, }) export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { @Input() public unit$: Observable; @@ -55,6 +55,10 @@ export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { public studentsLoaded = false; public filters: Partial = {}; + public get inboxLoading(): boolean { + return !(this.unit && this.unitRole && this.studentsLoaded); + } + public taskData: { taskKey: TaskKey | null; source: TaskSource; @@ -173,7 +177,7 @@ export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { case 'inbox': default: this.viewType = 'inbox'; - this.showSearchOptions = true; + this.showSearchOptions = false; this.taskData.taskDefMode = false; break; } @@ -217,7 +221,8 @@ export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { if ( !unitRole && - (this.userService.currentUser.role === 'Admin' || this.userService.currentUser.role === 'Auditor') + (this.userService.currentUser.role === 'Admin' || + this.userService.currentUser.role === 'Auditor') ) { unitRole = this.userService.adminOrAuditorRoleFor( this.userService.currentUser.role, diff --git a/src/app/units/unit.resolver.ts b/src/app/units/unit.resolver.ts index db682a9065..0ddeb34a9d 100644 --- a/src/app/units/unit.resolver.ts +++ b/src/app/units/unit.resolver.ts @@ -5,7 +5,7 @@ import {Unit, UnitRole, UnitService, UserService} from 'src/app/api/models/doubt import {AlertService} from 'src/app/common/services/alert.service'; import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; -export const resolveUnit: ResolveFn = (route) => { +export const resolveUnit: ResolveFn = (route, state) => { const unitService = inject(UnitService); const globalState = inject(GlobalStateService); const userService = inject(UserService); @@ -29,17 +29,30 @@ export const resolveUnit: ResolveFn = (route) => { ); } + const resolveProgressively = state.url.split('?')[0].includes('/tasks'); + if (resolveProgressively) { + const unit = + unitRole?.unit ?? unitService.cache.getOrCreate(unitId, unitService, {id: unitId}); + globalState.setView(ViewType.UNIT, routeEntity(unit, unitRole)); + observer.next(unit); + observer.complete(); + } + unitService.get(unitId).subscribe({ next: (unit) => { globalState.setView(ViewType.UNIT, routeEntity(unit, unitRole)); - observer.next(unit); - observer.complete(); + if (!resolveProgressively) { + observer.next(unit); + observer.complete(); + } }, error: (err) => { if (unitRole?.unit) { globalState.setView(ViewType.UNIT, unitRole); - observer.next(unitRole.unit); - observer.complete(); + if (!resolveProgressively) { + observer.next(unitRole.unit); + observer.complete(); + } return; } From 3de43060e165f4194dd1c6b482bd7c6248bc9615 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 19 May 2026 01:36:43 +1000 Subject: [PATCH 1046/1531] chore(release): 11.0.0-8 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53c58b79ab..04f703353a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-8](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-7...v11.0.0-8) (2026-05-18) + ## [11.0.0-7](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-6...v11.0.0-7) (2026-05-17) ## [11.0.0-6](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-5...v11.0.0-6) (2026-05-14) diff --git a/package-lock.json b/package-lock.json index 9a7c90b0de..0b8c1966de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-7", + "version": "11.0.0-8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-7", + "version": "11.0.0-8", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 5e74d844f5..5928b811ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-7", + "version": "11.0.0-8", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 6d7c9fb8ff7fe714844ebc8f0e04f2ef9a40d4d0 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 19 May 2026 02:01:25 +1000 Subject: [PATCH 1047/1531] fix: ensure unit is loaded first before querying inbox --- .../inbox/unit-task-inbox-state.component.ts | 52 ++++++++++++------- src/app/units/unit.resolver.ts | 1 + 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts index d8d6bfe81e..f09ba87889 100644 --- a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts +++ b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts @@ -7,6 +7,7 @@ import { Tutorial, Unit, UnitRole, + UnitService, UserService, } from 'src/app/api/models/doubtfire-model'; import {Task} from 'src/app/api/models/task'; @@ -81,6 +82,7 @@ export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { private taskService: TaskService, private globalStateService: GlobalStateService, private userService: UserService, + private unitService: UnitService, private projectService: ProjectService, private route: ActivatedRoute, private router: Router, @@ -100,25 +102,11 @@ export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { this.unit$ = of(routeUnit); } - this.unit$.pipe(first()).subscribe((unit) => { - this.unit = unit; - this.unitRole = this.findUnitRole(unit.id); - this.filters = { - ...this.filters, - ...this.getFilterOverrides(unit), - }; - - this.projectService - .loadStudents(unit) + this.unit$.pipe(first()).subscribe((routeUnit) => { + this.unitService + .fetch(routeUnit.id) .pipe(first()) - .subscribe({ - next: () => { - this.studentsLoaded = true; - }, - error: () => { - this.studentsLoaded = true; - }, - }); + .subscribe((unit) => this.loadInboxData(unit)); }); this.route.paramMap.subscribe(() => { @@ -183,6 +171,34 @@ export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { } } + private loadInboxData(unit: Unit): void { + this.unit = unit; + this.unitRole = this.findUnitRole(unit.id); + if (this.unitRole) { + this.unitRole.unit = unit; + this.globalStateService.setView(ViewType.UNIT, this.unitRole); + } else { + this.globalStateService.setView(ViewType.UNIT, unit); + } + + this.filters = { + ...this.filters, + ...this.getFilterOverrides(unit), + }; + + this.projectService + .loadStudents(unit) + .pipe(first()) + .subscribe({ + next: () => { + this.studentsLoaded = true; + }, + error: () => { + this.studentsLoaded = true; + }, + }); + } + private getFilterOverrides(unit: Unit): Partial { const selectedStudents = this.route.snapshot.queryParamMap.get('students'); diff --git a/src/app/units/unit.resolver.ts b/src/app/units/unit.resolver.ts index 0ddeb34a9d..7b5771d654 100644 --- a/src/app/units/unit.resolver.ts +++ b/src/app/units/unit.resolver.ts @@ -36,6 +36,7 @@ export const resolveUnit: ResolveFn = (route, state) => { globalState.setView(ViewType.UNIT, routeEntity(unit, unitRole)); observer.next(unit); observer.complete(); + return; } unitService.get(unitId).subscribe({ From f5c881dbe9181046819c6fd22f3e6e9361f738a1 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 19 May 2026 02:01:36 +1000 Subject: [PATCH 1048/1531] chore(release): 11.0.0-9 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04f703353a..297623589e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-9](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-8...v11.0.0-9) (2026-05-18) + + +### Bug Fixes + +* ensure unit is loaded first before querying inbox ([6d7c9fb](https://github.com/b0ink/doubtfire-deploy/commit/6d7c9fb8ff7fe714844ebc8f0e04f2ef9a40d4d0)) + ## [11.0.0-8](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-7...v11.0.0-8) (2026-05-18) ## [11.0.0-7](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-6...v11.0.0-7) (2026-05-17) diff --git a/package-lock.json b/package-lock.json index 0b8c1966de..b8346917ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-8", + "version": "11.0.0-9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-8", + "version": "11.0.0-9", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 5928b811ea..b71629cb0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-8", + "version": "11.0.0-9", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 71e8f2bec9579c664ca317b6027b64164e457bfa Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 19 May 2026 02:08:14 +1000 Subject: [PATCH 1049/1531] chore: fix invalid permissions-policy header --- nginx.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nginx.conf b/nginx.conf index 679f2082fc..a7721192b1 100644 --- a/nginx.conf +++ b/nginx.conf @@ -12,8 +12,7 @@ http { listen 80; add_header Content-Security-Policy "default-src https: 'unsafe-inline' 'unsafe-eval' blob: data: ws:" always; - # add_header Feature-Policy "microphone=(self),speaker=(self),fullscreen=(self),payment=(none);" always; - add_header Permissions-Policy "microphone=(self),speaker=(self),fullscreen=(self),payment=(none)" always; + add_header Permissions-Policy "microphone=(self),fullscreen=(self),payment=()" always; location / { try_files $uri $uri/ $uri/index.html /index.html; From 28ba58b62cdd926da382cbe02d7b12ee945baa80 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 19 May 2026 02:08:43 +1000 Subject: [PATCH 1050/1531] chore(release): 11.0.0-10 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 297623589e..1b8887b4ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-10](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-9...v11.0.0-10) (2026-05-18) + ## [11.0.0-9](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-8...v11.0.0-9) (2026-05-18) diff --git a/package-lock.json b/package-lock.json index b8346917ef..132ddbfeae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-9", + "version": "11.0.0-10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-9", + "version": "11.0.0-10", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index b71629cb0d..c965f4199c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-9", + "version": "11.0.0-10", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 04f3fd24670bddb046fada1aafb795e103668559 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 19 May 2026 11:40:16 +1000 Subject: [PATCH 1051/1531] chore: add overseer report to tutor inbox view --- .../directives/inbox-dashboard/inbox-dashboard.component.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html index 958e87da71..33533bbfb9 100644 --- a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html +++ b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html @@ -108,7 +108,9 @@
    } @case (InboxDashboardTab.overseer) { -
    +
    + +
    } }
    From 2fc28b8483674a726eb6f42b1aaaf6856412e10c Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 19 May 2026 11:51:04 +1000 Subject: [PATCH 1052/1531] chore(release): 11.0.0-11 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b8887b4ae..ffa5097323 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-11](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-10...v11.0.0-11) (2026-05-19) + ## [11.0.0-10](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-9...v11.0.0-10) (2026-05-18) ## [11.0.0-9](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-8...v11.0.0-9) (2026-05-18) diff --git a/package-lock.json b/package-lock.json index 132ddbfeae..db3fb1fdbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-10", + "version": "11.0.0-11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-10", + "version": "11.0.0-11", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index c965f4199c..8d226020c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-10", + "version": "11.0.0-11", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 50d8836abe858728c69e5dffd21c68b651505b4c Mon Sep 17 00:00:00 2001 From: Cilly Leang Date: Thu, 21 May 2026 22:00:57 +1000 Subject: [PATCH 1053/1531] feat(dashboard): implement sorting and filtering --- .../dashboard-list-item.component.ts | 4 + .../f-cross-dashboard.component.html | 46 ++++++++- .../dashboard/f-cross-dashboard.component.ts | 96 +++++++++++++++++-- 3 files changed, 131 insertions(+), 15 deletions(-) diff --git a/src/app/dashboard/dashboard-list-item.component.ts b/src/app/dashboard/dashboard-list-item.component.ts index b201cfcad0..6d321294bc 100644 --- a/src/app/dashboard/dashboard-list-item.component.ts +++ b/src/app/dashboard/dashboard-list-item.component.ts @@ -1,4 +1,5 @@ import {Component, Input} from '@angular/core'; +import {TaskStatusEnum} from '../api/models/task-status'; export type DashboardTask = { title: string; @@ -6,6 +7,9 @@ export type DashboardTask = { abbreviation: string; color: string; comments: number; + status: TaskStatusEnum; + date: Date; + weight: number; }; @Component({ diff --git a/src/app/dashboard/f-cross-dashboard.component.html b/src/app/dashboard/f-cross-dashboard.component.html index 978148aa11..6787111c41 100644 --- a/src/app/dashboard/f-cross-dashboard.component.html +++ b/src/app/dashboard/f-cross-dashboard.component.html @@ -1,15 +1,51 @@
    -
    +
    -
    -

    {{ unit.code }}

    +
    +

    + {{ unit.code }} +

    + - sort - filter_list_alt + +
    + + +
    + +
    +
    +
    + +
    + + +
    + + {{ mode }} +
    +
    +
    diff --git a/src/app/dashboard/f-cross-dashboard.component.ts b/src/app/dashboard/f-cross-dashboard.component.ts index bd4bbc0721..ff2d9314f5 100644 --- a/src/app/dashboard/f-cross-dashboard.component.ts +++ b/src/app/dashboard/f-cross-dashboard.component.ts @@ -1,10 +1,21 @@ import {Component, OnInit} from '@angular/core'; import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; import {Project} from '../api/models/project'; -import {TaskStatus} from '../api/models/task-status'; +import {TaskStatus, TaskStatusEnum} from '../api/models/task-status'; import {DashboardTask} from './dashboard-list-item.component'; import {Task} from '../api/models/task'; -import {TaskDefinition} from '../api/models/task-definition'; + +enum Filter { + HideCompleted = 'Hide Completed', +} + +enum SortMode { + Recommended = 'Recommended', + SubmissionDate = 'Due Date', + Default = 'Default', +} + +const completedTypes: readonly TaskStatusEnum[] = ['complete']; type DashboardUnit = { projectId: number; @@ -20,37 +31,102 @@ type DashboardUnit = { export class CrossDashboardComponent implements OnInit { constructor(private globalStateService: GlobalStateService) {} - units: DashboardUnit[] = []; + filterOptions = Object.values(Filter); + sortOptions = Object.values(SortMode); + + private units: DashboardUnit[] = []; + unitsProcessed: DashboardUnit[] = []; + + private filters = new Map(); + private sorting = new Map(); ngOnInit(): void { this.globalStateService.onLoad(() => { this.globalStateService.currentUserProjects.values.subscribe((projects) => { this.units = this.mapProjects(projects); + this.processTasks(); }); }); } - mapProjects(projects: readonly Project[]): DashboardUnit[] { + unitIdentify(_index: number, item: DashboardUnit) { + return item.projectId; + } + + setSort(project: number, mode: SortMode) { + this.sorting.set(project, mode); + this.processTasks(); + } + + toggleFilter(project: number, filter: Filter) { + let filters = this.filters.get(project) ?? []; + if (filters.includes(filter)) { + filters = filters.filter((f) => f != filter); + } else { + filters = [...filters, filter]; + } + this.filters.set(project, filters); + this.processTasks(); + } + + private processTasks() { + this.unitsProcessed = this.units.map((unit) => ({ + ...unit, + tasks: unit.tasks + .filter((task) => { + const filters = this.filters.get(unit.projectId) ?? []; + if (filters.includes(Filter.HideCompleted) && completedTypes.includes(task.status)) { + return false; + } else { + return true; + } + }) + .sort((a, b) => { + const sort = this.sorting.get(unit.projectId) ?? 'recommended'; + if (completedTypes.includes(a.status) && !completedTypes.includes(b.status)) { + return -1; + } else if (!completedTypes.includes(a.status) && completedTypes.includes(b.status)) { + return 1; + } + switch (sort) { + case SortMode.Recommended: { + // TODO: Connect to recommender's points + return 0; + } + case SortMode.SubmissionDate: + return a.date.getTime() - b.date.getTime(); + case SortMode.Default: + return a.weight - b.weight; + } + }), + })); + } + + private mapProjects(projects: readonly Project[]): DashboardUnit[] { return projects.map((project) => { + project.calcTopTasks(); const unit = project.unit; return { projectId: project.id, code: unit.code, name: unit.name, - tasks: this.mapTasks(project.tasks, unit.taskDefinitions), + tasks: this.mapTasks(project.activeTasks()), }; }); } - mapTasks(tasks: readonly Task[], taskDefs: readonly TaskDefinition[]): DashboardTask[] { - return taskDefs.map((def) => { - const task = tasks.find((t) => t.taskDefId == def.id); + private mapTasks(tasks: readonly Task[]): DashboardTask[] { + return tasks.map((task) => { + const def = task.definition; return { title: def.name, subtitle: `${def.abbreviation} - ${def.targetGradeText} Task`, abbreviation: def.abbreviation, - color: TaskStatus.STATUS_COLORS.get(task?.status ?? 'not_started'), - comments: task?.numNewComments ?? 0, + color: TaskStatus.STATUS_COLORS.get(task.status), + comments: task.numNewComments ?? 0, + status: task.status, + date: def.targetDate, + weight: task.topWeight, }; }); } From e3667b46779f0c459dde65e9496b4482a6763e37 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:28:12 +1000 Subject: [PATCH 1054/1531] refactor: sticky tab group in task dashboard --- .../task-dashboard.component.html | 170 +++++++++--------- .../inbox-dashboard.component.html | 2 +- 2 files changed, 87 insertions(+), 85 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html index 17091f8089..d73b3cd91f 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html @@ -1,5 +1,5 @@ -
    -
    +
    +
    - @switch (currentView) { - @case (DashboardViews.details) { -
    - - - - - - - - -
    - } - - @case (DashboardViews.task) { - @if (task && task.blockedByPrerequisiteTasks()) { -
    - - Warning: This task has - {{ task.definition.taskPrerequisitesCache.currentValues.length }} prerequisite{{ - task.definition.taskPrerequisitesCache.currentValues.length > 1 ? 's' : '' - }} - that you still need to complete. You won’t be able to submit this task until all - prerequisites are met. -
    + @case (DashboardViews.task) { + @if (task && task.blockedByPrerequisiteTasks()) { +
    + + Warning: This task has + {{ task.definition.taskPrerequisitesCache.currentValues.length }} prerequisite{{ + task.definition.taskPrerequisitesCache.currentValues.length > 1 ? 's' : '' + }} + that you still need to complete. You won’t be able to submit this task until all + prerequisites are met. +
    + } + @if (task.definition.hasTaskSheet) { + + } @else { +
    + subtitles_off +
    + } } - @if (task.definition.hasTaskSheet) { - - } @else { -
    - subtitles_off -
    + @case (DashboardViews.submission) { + @if (task.hasPdf) { + + } @else { +
    + subtitles_off +
    + } } - } - @case (DashboardViews.submission) { - @if (task.hasPdf) { - - } @else { -
    - subtitles_off -
    + @case (DashboardViews.similarity) { + @if (canAccessStaffViews) { +
    + +
    + } } - } - @case (DashboardViews.similarity) { - @if (canAccessStaffViews) { -
    - -
    + @case (DashboardViews.overseer) { + @if (canAccessStaffViews) { +
    + +
    + } } - } - @case (DashboardViews.overseer) { - @if (canAccessStaffViews) { -
    - -
    + @case (DashboardViews.staff_notes) { + @if (canAccessStaffViews) { +
    + +
    + } } - } - @case (DashboardViews.staff_notes) { - @if (canAccessStaffViews) { -
    - + @case (DashboardViews.tutor_notes) { +
    + @if (canAccessTutorNotes) { + + }
    } - } - @case (DashboardViews.tutor_notes) { -
    - @if (canAccessTutorNotes) { - + @case (DashboardViews.discussion_prompts) { + @if (canAccessStaffViews) { + } -
    - } - @case (DashboardViews.discussion_prompts) { - @if (canAccessStaffViews) { - } } - } +
    -
    +
    -
    -
    + Teaching Period Name @@ -68,7 +68,7 @@ -

    Teaching Breaks for {{ newOrSelectedTeachingPeriod.name }}

    +

    Teaching Breaks for {{ newOrSelectedTeachingPeriod.name }}

    @for (break of newOrSelectedTeachingPeriod.breaksCache.values | async; track break) { @@ -86,8 +86,8 @@

    Teaching Breaks for {{ newOrSelectedTeachingPeriod.name }}

    }
    - - + + Break Start Date -
    +

    Teaching periods

    - + Bulk users operations diff --git a/src/app/admin/tii-action-log/tii-action-log.component.html b/src/app/admin/tii-action-log/tii-action-log.component.html index e61877520d..c12c822525 100644 --- a/src/app/admin/tii-action-log/tii-action-log.component.html +++ b/src/app/admin/tii-action-log/tii-action-log.component.html @@ -1,5 +1,5 @@
    -
    +

    Turnitin Actions

    diff --git a/src/app/common/archive-viewer/archive-viewer.component.html b/src/app/common/archive-viewer/archive-viewer.component.html index da1de5293f..e48d00a0dc 100644 --- a/src/app/common/archive-viewer/archive-viewer.component.html +++ b/src/app/common/archive-viewer/archive-viewer.component.html @@ -1,39 +1,39 @@
    @if (isLoading) {
    Loading archive...
    } @else if (errorMessage) { -
    - error_outline +
    + error_outline {{ errorMessage }}
    } @else if (!archiveFile) {
    - folder_zip + folder_zip Select an archive to preview.
    } @else if (!hasFiles) {
    - folder_off + folder_off No files to display.
    } @else { @if (!readOnly && saveEndpoint) { -
    +
    } -
    +
    @if (showUploader && uploadingInfo === null && shownUploadZones.length) {
    @for (upload of shownUploadZones; track upload) { @@ -41,7 +41,7 @@
    Select {{ upload.display.name }}
    Click to select {{ upload.display.type }} file } } @else { - + block Invalid file provided Select {{ upload.display.name }}
    @if (!singleDropZone && upload.model?.length > 0) { -
    +
    {{ upload.display.icon }} {{ upload.model[0].name }} diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index ae0ce25e83..7e0d7f62bc 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -1,6 +1,6 @@ - + @if (selectedTask?.definition?.assessInPortfolioOnly) {
    -

    Manage your learning, with feedback you'll want to receive.

    +

    Manage your learning, with feedback you'll want to receive.

    diff --git a/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html b/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html index 9031ccde39..c93603fa33 100644 --- a/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html +++ b/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html @@ -1,4 +1,4 @@ -
    +
    -
    +
    @@ -117,11 +117,11 @@ @if (selectedOutcome) { -
    +
    -

    Edit Outcome

    +

    Edit Outcome

    -
    +
    Abbreviation

    Download the {{ data.type }} CSV

    -
    +

    This action will download all {{ data.type.toLowerCase() }} associated with this unit.

    Include task {{ data.type.toLowerCase() }}Download the {{ data.type }} CSV
    -
    +
    diff --git a/src/app/common/modals/comments-modal/comments-modal.component.html b/src/app/common/modals/comments-modal/comments-modal.component.html index 707bcff36c..4236c93c2d 100644 --- a/src/app/common/modals/comments-modal/comments-modal.component.html +++ b/src/app/common/modals/comments-modal/comments-modal.component.html @@ -1,4 +1,4 @@ -
    +
    @if (taskComment.commentType === 'image') { } @else if (taskComment.commentType === 'pdf') { diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.component.html b/src/app/common/modals/confirmation-modal/confirmation-modal.component.html index 547f9fe8cd..4232cf08ee 100644 --- a/src/app/common/modals/confirmation-modal/confirmation-modal.component.html +++ b/src/app/common/modals/confirmation-modal/confirmation-modal.component.html @@ -1,7 +1,7 @@

    - help + help
    {{ title }}
    Please confirm that you want to perform this action. diff --git a/src/app/common/modals/csv-result-modal/csv-result-modal.component.html b/src/app/common/modals/csv-result-modal/csv-result-modal.component.html index bea497db15..1de2d91f66 100644 --- a/src/app/common/modals/csv-result-modal/csv-result-modal.component.html +++ b/src/app/common/modals/csv-result-modal/csv-result-modal.component.html @@ -4,7 +4,7 @@

    {{ data.title }}

    @for (selection of csvResponseSelections; track selection.key) { {{ data.title }}

    } - + @if (dataSource.data.length > 0) { +
    @if (showTaskAbbr && editMode) { } -
    +
    @if (showTaskAbbr) { } @else { @@ -70,13 +70,13 @@
    @if (editMode) { @if (afterDeadline()) { -
    diff --git a/src/app/groups/group-selector/group-selector.component.html b/src/app/groups/group-selector/group-selector.component.html index 641cb00bde..ba6a56d696 100644 --- a/src/app/groups/group-selector/group-selector.component.html +++ b/src/app/groups/group-selector/group-selector.component.html @@ -2,7 +2,7 @@
    -
    +
    Groups for @if (!showGroupSetSelector && selectedGroup) { @@ -21,7 +21,7 @@ }
    @if (unitRole || selectedGroupSet?.allowStudentsToCreateGroups) { -
    +
    @if (selectedGroupSet && selectedGroupSet.groups.length === 0) { -
    +
    group_off -

    There are no groups in this set

    +

    There are no groups in this set

    } @else {
    @@ -61,7 +61,7 @@ @for (ilo of learningOutcomes; track ilo) { - - - + + -
    Name @if (editing(group)) { - + } @else { @@ -74,7 +74,7 @@ Tutorial @if (editing(group)) { - + @for (tutorial of unit.tutorials; track tutorial) { {{ tutorial.abbreviation }} @@ -96,7 +96,7 @@ @if (unitRole) { @if (editing(group)) { - + } @if (unitRole) { -
    +
    @if (editing(group)) { -
    +
    diff --git a/src/app/groups/group-set-manager/group-set-manager.component.html b/src/app/groups/group-set-manager/group-set-manager.component.html index 6c013fcbe3..0f89d4712f 100644 --- a/src/app/groups/group-set-manager/group-set-manager.component.html +++ b/src/app/groups/group-set-manager/group-set-manager.component.html @@ -1,4 +1,4 @@ -
    +
    + } } @else { @if (unitRole || selectedGroup.groupSet?.allowStudentsToManageGroups) { - + - - } @@ -51,7 +51,7 @@ @if (unitRole) { - + +

    You are not enrolled in {{ externalName.value }}.

    Contact your unit convenor or tutor to enrol you in a subject.

    @@ -77,7 +77,7 @@

    Units you teach

    -
    +

    Enrolled units

    diff --git a/src/app/home/states/lti-dashboard/lti-dashboard.component.html b/src/app/home/states/lti-dashboard/lti-dashboard.component.html index ba12db70e8..0a31177529 100644 --- a/src/app/home/states/lti-dashboard/lti-dashboard.component.html +++ b/src/app/home/states/lti-dashboard/lti-dashboard.component.html @@ -1,5 +1,5 @@ -
    -
    +
    +
    -

    OnTrack

    +

    OnTrack

    @if (isLoading) { @if (unauthorised) { -
    +
    An error occurred. Please refresh the page.
    } @else { @@ -20,7 +20,7 @@

    OnTrack

    Loading...

    } } @else { -
    +
    @if (currentUser?.systemRole === 'Convenor' || currentUser?.systemRole === 'Admin') { -
    +
    @if (linkedUnit) { {{ linkedUnit.code }} — {{ linkedUnit.name }} @if (currentUser?.systemRole === 'Convenor' || currentUser?.systemRole === 'Admin') { diff --git a/src/app/home/states/lti-unit-link/lti-unit-link.component.html b/src/app/home/states/lti-unit-link/lti-unit-link.component.html index 2ab7465ca9..1020993ed1 100644 --- a/src/app/home/states/lti-unit-link/lti-unit-link.component.html +++ b/src/app/home/states/lti-unit-link/lti-unit-link.component.html @@ -1,5 +1,5 @@ -
    -
    +
    +
    -

    OnTrack

    +

    OnTrack

    @if (loadingUnits) { diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html index 685e34f3af..b450dfad58 100644 --- a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html +++ b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html @@ -1,22 +1,22 @@ @if (project$ | async; as project) { -
    +
    - + - -

    + +

    {{ project.student.nickname || project.student.firstName }}'s {{ project.unit.name }}

    -

    {{ project.unit.description }}

    +

    {{ project.unit.description }}

    - + - -

    Targetting

    + +

    Targetting

    info diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html index d3fdd7b90d..66174425af 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html @@ -1,13 +1,13 @@
    -
    -

    +
    +

    Progress Dashboard @if (tutor) { for {{ project.student.name }} }

    -
    +
    @@ -18,7 +18,7 @@

    Target Grade - +

    Your target grade changes which tasks you need to complete.

    @@ -39,7 +39,7 @@

    } -

    [grade]="project.targetGrade" >

    -
    +
    Aim to keep your Complete line close to or ahead of the @@ -85,15 +85,15 @@

    Progress Burndown

    -
    -
    -

    Task Statuses

    -

    +

    +
    +

    Task Statuses

    +

    Breakdown summary of each of your task statuses.

    -
    +
    Plan Your Tasks - +

    The Task Planner shows a timeline of your tasks, their due dates, and prerequisite relationships. Use it to plan when to start and submit tasks, ensuring prerequisites are diff --git a/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html b/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html index c5a07269cc..39825c6d7b 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html +++ b/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html @@ -1,13 +1,13 @@ -

    -
    +
    +
    Create Portfolio
    -
    +
    person
    Create and submit your portfolio
    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html index 8cc634a7fd..5636823212 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html @@ -1,6 +1,6 @@ -
    +
    - comment + comment

    Discussion Prompts for {{ project?.student?.name }}

    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html index 8b57557240..f92fd644e5 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html @@ -1,6 +1,6 @@ -
    +
    - comment + comment

    Staff Notes for {{ project?.student?.name }}

    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html index 858f5ddd29..b7548c3c90 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html @@ -1,7 +1,7 @@ -
    - +
    + {{ taskDef?.name }}
    @@ -42,7 +42,7 @@ @if (flexibleDatesEnabled) { -

    +

    You should have submitted this task by {{ task?.localDueDateString() }} to keep your progress on track. Try to finish it as soon as possible to avoid delays. You can revise your project plan dates, but ensure you submit before the deadline to receive feedback.

    } @else { -

    +

    You should have completed this task by {{ task?.localDueDateString() }}. Try and finish it as soon as possible to avoid falling behind. You will need to @@ -116,16 +116,16 @@ @if (task?.isPastDeadline()) { - error - Passed Due Date By {{ task?.timePastDueDateDescription() }} -

    +

    @if (task?.definition?.unit.markLateSubmissionsAsAssessInPortfolio) { You should have completed this task by {{ task?.localDueDateString() }}{{ getIloContextLabel() }} Learning Outcomes - These outcomes describe the key skills and knowledge you are aiming to achieve by completing this {{ getIloContextLabel().toLowerCase() }}. @@ -11,11 +11,11 @@

    {{ ilo.abbreviation }}{{ ilo.fullOutcomeDescription }} + {{ ilo.abbreviation }}{{ ilo.fullOutcomeDescription }} @for (outcome of getLinkedOutcomes(ilo); track outcome.abbreviation) { - {{ + {{ outcome.abbreviation }} } diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html index 5d1d69f412..ae35bec796 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html @@ -1,4 +1,4 @@ -
    +

    @if (compareMode) { @@ -16,21 +16,21 @@

    -
    +
    @if (isLoading) {
    } @else if (errorMessage) {
    {{ errorMessage }}
    } @else if (compareMode) { @if (archiveBlob && comparedArchiveBlob) { -
    -
    +
    +
    @if (!bothSelectionsReady) {
    Select a file in both submissions to compare.
    } @else if (canShowDiffEditor) {
    -
    +
    {{ primarySelectedFile?.path ?? primarySelectedFile?.name }}
    @@ -105,7 +105,7 @@

    >

    } @else { -
    +
    } @else {
    Unable to load one or both submission archives.
    @@ -150,7 +150,7 @@

    } @else {
    Unable to load submission files.
    @@ -163,7 +163,7 @@

    let-isMostRecent="isMostRecent" let-timestamp="timestamp" > -
    +
    Submission{{ number !== undefined ? ' ' + number : '' }}{{ isMostRecent ? ' (Most recent)' : '' }}: {{ timestamp | date: 'dd/MM/yyyy HH:mm' }} @@ -173,7 +173,7 @@

    @@ -198,7 +198,7 @@

    } @else if (isArchivePdfFile(file)) { } @else if (isArchiveImageFile(file)) { -
    +
    />
    } @else { -
    +
    Preview not available for this file type.
    } diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html index 2773aed285..233333462b 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html @@ -1,4 +1,4 @@ -
    +
    @@ -10,7 +10,7 @@ [expanded]="oa.id === loadOverseerAssessmentId && oa.reportReady" > - + Submission {{ overseerAssessments.length - idx }}: {{ oa.timestamp | humanizedDate }} @if (idx === 0) { @@ -21,7 +21,7 @@ } @if (oa.reportReady) { -
    +
    {{ oa.passedSteps }} / {{ oa.totalSteps }} @if (oa.passedSteps === oa.totalSteps) { done @@ -67,7 +67,7 @@ }
    } @else { -
    +
    Tests In Progress
    @@ -92,7 +92,7 @@ @if (!result.pass) { -

    +

    {{ result.feedbackMessage }}

    } @@ -102,7 +102,7 @@ result.expectedOutput !== result.stdout && (result.overseerStep?.stepType === 'output_diff' || !result.overseerStep) ) { -
    +

    -
    {{ trigger.label }}
    +
    {{ trigger.label }}
    } @@ -42,7 +42,7 @@
    {{ task?.statusLabel() }}
    -
    +
    diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html index 575a9f5faf..ce69d3dcb3 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html @@ -8,22 +8,22 @@

    Select Grade

    -

    +

    In preparing your portfolio, you need to undertake a self-assessment. Use the unit's assessment criteria to determine the grade your portfolio should be awarded.

    - + - + warning Read the assessment criteria -

    +

    Make sure that you have reviewed the Assessment Criteria for the grade you are applying for. Each grade will have a list of criteria that you can use to determine if you meet the requirements to achieve that grade. @@ -40,15 +40,15 @@

    Select Grade

    @if (agreedToAssessmentCriteria) { - + - + Grade Application -

    +

    Select the grade you are applying for {{ unit.code }} {{ unit.name }} below.

    @@ -62,7 +62,7 @@

    Select Grade

    @for (grade of gradeValues; track grade) { @@ -70,7 +70,7 @@

    Select Grade

    } -

    +

    Make sure your Learning Summary Report justifies how your portfolio demonstrates you have met all unit learning outcomes to a {{ targetGrade }} level diff --git a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html index 3ef553e787..74cb105802 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html @@ -3,7 +3,7 @@ Learning Summary Report -

    +

    Upload the Learning Summary Report, the primary porfolio document which justifies your desired grade.

    @@ -12,7 +12,7 @@ summary of what you have learnt in this unit. It consists of two sections:

    -
      +
      1. a self-assessment, and
      2. your reflections on the unit.
      @@ -30,13 +30,13 @@ @if ( projectHasDraftLearningSummaryReport && !forceLSRSubmit && !acceptUploadNewLearningSummary ) { -
      -

    @if (project) { -
    +
    @if (this.allTasks?.length > 0) { @if (this.filteredTasks?.length < this.allTasks?.length) {
    @if (project && filteredTasks.length) { -
    -
    +
    +
    @if (attendance) {

    @if (footerTabView === TutorDiscussionTabView.SHOW_COMMENTS) {
    - + } --> -
    +
    @if (!loadingTutorNotes) { @for (note of filteredNotes; track note) { @if (note.replyToId) {
    - reply + reply
    @if (note.replyTo) { Replying to {{ note.replyTo.user.preferredName }} {{ note.replyTo.user.lastName }} ({{ note.replyTo.user.nickname }}) - {{ note.replyTo.note }} + {{ note.replyTo.note }} } @else { - Replying to: Deleted note + Replying to: Deleted note }
    @@ -33,11 +33,11 @@ } -
    +
    @if (note.authorIsMe) { edit @@ -52,7 +52,7 @@ } } @else { -
    Read by tutor
    +
    Read by tutor
    }
    @@ -71,7 +71,7 @@
    -
    +
    @if (note.taskDefinition) { {{ note.taskDefinition?.abbreviation }} {{ note.taskDefinition.name }} - + @if (editingNote && editingNote.id === note.id) { Update Note @@ -98,9 +98,9 @@ #tutorNoteEditor matInput [(ngModel)]="editingNoteText" - class="resize-none w-full px-2 py-1 placeholder:px-2 placeholder:py-1 overflow-hidden" + class="resize-none w-full px-1 py-0.5 placeholder:px-1 placeholder:py-0.5 overflow-hidden" > -
    +
    -
    - +
    +
    - reply + reply
    Replying to {{ replyingToNote.user.firstName }} {{ replyingToNote.user.lastName }} ({{ replyingToNote.user.nickname }}) - {{ replyingToNote.note }} + {{ replyingToNote.note }}
    close @@ -165,7 +165,7 @@
    diff --git a/src/app/projects/states/tutorials/tutorials.component.html b/src/app/projects/states/tutorials/tutorials.component.html index a29c236808..726ed0745c 100644 --- a/src/app/projects/states/tutorials/tutorials.component.html +++ b/src/app/projects/states/tutorials/tutorials.component.html @@ -1,5 +1,5 @@ @if (project && unit) { -
    +

    Tutorials

    diff --git a/src/app/sessions/states/sign-in/sign-in.component.html b/src/app/sessions/states/sign-in/sign-in.component.html index 373d82d8b8..31917944ce 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.html +++ b/src/app/sessions/states/sign-in/sign-in.component.html @@ -57,7 +57,7 @@

    type="form" [disabled]="form.invalid" > -
    +
    @if (redirectingSSO) { Signing In... diff --git a/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.html b/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.html index 131bc86541..ad6470153b 100644 --- a/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.html +++ b/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.html @@ -17,7 +17,7 @@

    Request Feedback Review

    request will not be counted against your remaining total.

    - + Reason for review request - + Priority diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html index 66290bd179..cca24f04c2 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html @@ -1,15 +1,15 @@ -
    +

    Details for {{ taskDefinition.abbreviation }} - {{ taskDefinition.name }}

    -
    -

    @if (staffView) { - + diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html index fb02d119a2..1db7e15ffc 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html @@ -1,4 +1,4 @@ -
    +
    Enable test for task @@ -11,7 +11,7 @@ [desiredFileName]="'SCORM zip'" /> @if (taskDefinition.hasScormData) { -
    +
    @@ -24,7 +24,7 @@
    } -
    +
    Allow students to review completed test attempt @@ -45,7 +45,7 @@
    -
    +
    @if (taskDefinition.needsJplag) { -
    +
    Language used for JPLAG checks diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html index f36a92f380..4f363e2b22 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html @@ -10,7 +10,7 @@ } -
    +
    Tutorial Stream - Which tutor provides feedback? 3) { -
  • +
  • +{{ taskDefinition.tutorialStream.tutorialsIn(unit).length - 3 }} more tutorials
  • } @if (taskDefinition.tutorialStream?.tutorialsIn(unit).length > 3) { -
    +
    @if (!showAllTutorials) { } @@ -39,13 +39,13 @@

    Task List

    @if (unit.allowFlexibleDates) { @if (manageDueDates) {
    - +

    Manage Target Dates

    Modify or add target dates for each target grade

    -
    +
    @@ -62,7 +62,7 @@

    Manage Target Dates

    - +
    Task -
    +
    Manage Target Dates } } -
    +
    -
    +
    -
    +
    @@ -246,7 +246,7 @@

    Tutorials without a stream

    -
    diff --git a/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html b/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html index 9f98162d6d..752fb350e6 100644 --- a/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html +++ b/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html @@ -7,13 +7,13 @@
    groups

    No Tutorials

    -

    +

    There are no tutorials yet. Create a tutorial stream to begin adding tutorials.

    } -
    +
    } -
    +
    @@ -177,10 +177,10 @@

    Mark portfolios

    matTooltipDelay="100" > @if (bar.key === 'not_started') { - {{ bar.value }}% + {{ bar.value }}% } @if (bar.key === 'complete') { - {{ bar.value }}% + {{ bar.value }}% }
    } @@ -212,7 +212,7 @@

    Mark portfolios

    >
    No students foundNo students found
    diff --git a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html index c88222fa7c..c885e73b1f 100644 --- a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html @@ -1,4 +1,4 @@ -
    +

    Review portfolio of {{ project.student.name }}

    View or download portfolio for assessment.

    @@ -6,9 +6,9 @@

    Review portfolio of {{ project.student.name }}

    } @else { -
    +
    menu_book -

    No Portfolio Submitted

    +

    No Portfolio Submitted

    }
    diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html index fc9ea5374c..da4eacf5a9 100644 --- a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html @@ -1,20 +1,20 @@ -
    +

    Review progress of {{ project.student.name }}

    Review the students progress through the unit's tasks.

    -
    -
    +
    +
    Target Grade - -
    -
    + +
    +
    @for (grade of gradeValues; track grade) { @@ -30,9 +30,9 @@

    Review progress of {{ project.student.name }}

    Submitted Grade - -
    -
    + +
    +
    Review progress of {{ project.student.name }} @for (grade of gradeValues; track grade) { @@ -57,7 +57,7 @@

    Review progress of {{ project.student.name }}

    Task List - + Review progress of {{ project.student.name }} > -
    +
    Task Summary Chart - + Review progress of {{ project.student.name }} Burndown Chart - -
    + +
    {{ project.student.name }} has completed {{ taskStats.numberOfTasksCompleted }} tasks and have {{ taskStats.numberOfTasksRemaining }} left to complete to achieve their target of a diff --git a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html index 2ef82a722d..2d454fd43c 100644 --- a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html +++ b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html @@ -1,3 +1,3 @@ - diff --git a/src/app/units/states/portfolios/upload-grades/upload-grades.component.html b/src/app/units/states/portfolios/upload-grades/upload-grades.component.html index a2b05b8f79..a95e240410 100644 --- a/src/app/units/states/portfolios/upload-grades/upload-grades.component.html +++ b/src/app/units/states/portfolios/upload-grades/upload-grades.component.html @@ -1,3 +1,3 @@ - diff --git a/src/app/units/states/rollover/rollover.component.html b/src/app/units/states/rollover/rollover.component.html index f9ac373ed0..d2eee891a4 100644 --- a/src/app/units/states/rollover/rollover.component.html +++ b/src/app/units/states/rollover/rollover.component.html @@ -4,13 +4,13 @@ Copy {{ unit?.code }} {{ unit?.nameAndPeriod }} - +

    Duplicate this unit by copying it to the indicated teaching period, or a custom start and end date.

    -
    +
    Teaching Period @@ -21,7 +21,7 @@ -
    +
    @if (!teachingPeriod) { Start Date diff --git a/src/app/units/states/students-list/students-list.component.html b/src/app/units/states/students-list/students-list.component.html index 860e707883..ee55246c20 100644 --- a/src/app/units/states/students-list/students-list.component.html +++ b/src/app/units/states/students-list/students-list.component.html @@ -1,5 +1,5 @@
    -
    +

    Students

    Browse progress, filter tutorial groups, and manage enrolments.

    @@ -146,15 +146,15 @@

    Students

    >
    + No students were found using the filters specified.
    -
    -
    +
    +
    diff --git a/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.html b/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.html index e7477fa34f..f208622ae8 100644 --- a/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.html +++ b/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.html @@ -14,9 +14,9 @@ [disabled]=" !selectedTask || selectedTask.loadingSubmissionDetails || selectedTask.claimedByUnitRoleId " - class="ml-5" + class="ml-3" > -
    +
    @if (selectedTask.claimedByUnitRoleId) { @if (selectedTask.claimedByUnitRoleId === currentUnitRole.id) { check_circle diff --git a/src/app/units/states/tasks/inbox/inbox.component.html b/src/app/units/states/tasks/inbox/inbox.component.html index b7cded7591..1b29d83c9e 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.html +++ b/src/app/units/states/tasks/inbox/inbox.component.html @@ -38,7 +38,7 @@ @if (!isMobileView) { -
    +
    @if (loading) { diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index e7efd21ac8..d57c3d6d3c 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -24,7 +24,7 @@ @for (taskDef of filteredTaskDefinitions; track taskDef) { @if (taskDef) { -
    -
    -
    +
    +
    +
    {{ taskDef.name }}
    -
    +
    @if (taskDef.isGroupTask()) { groups } @else { @@ -54,7 +54,7 @@ @if (taskListItem(taskDef); as task) { @if (!task.isBeforeStartDate() && !task.inSubmittedState()) { +
    @if (task.numNewComments > 0) {
    @if (task.hasGrade()) { @@ -172,7 +172,7 @@ @if (mode === 'project' && project) { diff --git a/src/app/units/unit-root-state.component.html b/src/app/units/unit-root-state.component.html index a7f38ec243..44c6a074e3 100644 --- a/src/app/units/unit-root-state.component.html +++ b/src/app/units/unit-root-state.component.html @@ -2,7 +2,7 @@ } @else {

    Loading unit details...

    diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index 08cbcd19e9..25726a1383 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -1,4 +1,4 @@ -
    +
    +
    Date: Wed, 3 Jun 2026 14:43:45 +1000 Subject: [PATCH 1065/1531] chore(release): 11.0.0-13 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8127ffc6f4..9e25745206 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-13](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-12...v11.0.0-13) (2026-06-03) + ## [11.0.0-12](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-11...v11.0.0-12) (2026-06-02) diff --git a/package-lock.json b/package-lock.json index ebb426d6ab..2b666898ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-12", + "version": "11.0.0-13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-12", + "version": "11.0.0-13", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index cad96e247b..4a49f30c79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-12", + "version": "11.0.0-13", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 84fb6b899e12983a4c44ed21b8a57901b10a5611 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:54:36 +1000 Subject: [PATCH 1066/1531] chore: switch to outlined version of icon --- src/app/api/models/task-status.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/models/task-status.ts b/src/app/api/models/task-status.ts index 86614c08f4..9e51c5386e 100644 --- a/src/app/api/models/task-status.ts +++ b/src/app/api/models/task-status.ts @@ -256,7 +256,7 @@ export class TaskStatus { // Material icons used by newer UI elements. public static readonly STATUS_MATERIAL_ICONS = new Map([ - ['ready_for_feedback', 'thumb_up_alt'], + ['ready_for_feedback', 'thumb_up_off_alt'], ['not_started', 'pause'], ['working_on_it', 'bolt'], ['need_help', 'help'], From 7547d4c6819b134c1796acf0cca7fc87ac334eed Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:56:41 +1000 Subject: [PATCH 1067/1531] refactor: reduce icon size to match original --- src/app/common/status-icon/status-icon.component.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/common/status-icon/status-icon.component.html b/src/app/common/status-icon/status-icon.component.html index 0db2f44416..816db2306a 100644 --- a/src/app/common/status-icon/status-icon.component.html +++ b/src/app/common/status-icon/status-icon.component.html @@ -3,8 +3,12 @@ matTooltip="{{ statusLabel(status) }}" matTooltipPosition="above" [matTooltipDisabled]="!showTooltip" - class="status-chip rounded-full cursor-pointer pl-3.5 pr-3.5 min-h-[30px] h-7 ml-0.5 mr-0.5 flex justify-center items-center" + class="status-chip rounded-full cursor-pointer px-3 min-h-[30px] h-7 mx-0.5 flex justify-center items-center" style="font-size: 14px; min-width: 50px" > - {{ statusIcon(status) }} + {{ statusIcon(status) }}
    From 68c51d290159e446ed23220894fcc810bac15fd1 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:01:49 +1000 Subject: [PATCH 1068/1531] chore: clarify tutorial change option --- .../unit-details-editor/unit-details-editor.component.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html index cc1672fdc2..2d41f55d16 100644 --- a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html +++ b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html @@ -166,7 +166,10 @@

    Unit Details

    Allow students to change tutorial -

    When false only staff can change student tutorials.

    +

    + When false only staff can change student tutorials. When true, students may switch between + tutors who provide feedback on their work. +

    From e13e69e4ab657ef7f9a6d80065483069dc0a873b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:02:06 +1000 Subject: [PATCH 1069/1531] chore(release): 11.0.0-14 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e25745206..e4b1ac6757 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-14](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-13...v11.0.0-14) (2026-06-03) + ## [11.0.0-13](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-12...v11.0.0-13) (2026-06-03) ## [11.0.0-12](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-11...v11.0.0-12) (2026-06-02) diff --git a/package-lock.json b/package-lock.json index 2b666898ff..c6f60e3ac7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-13", + "version": "11.0.0-14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-13", + "version": "11.0.0-14", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 4a49f30c79..71ba28446e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-13", + "version": "11.0.0-14", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 9654d930fbe7072ee4dfc71c454c55c545fe354d Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:12:59 +1000 Subject: [PATCH 1070/1531] chore: temporarily disable discussion prompts from inbox view --- src/app/common/footer/footer.component.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index 7e0d7f62bc..e7a031ddc7 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -200,7 +200,8 @@
    } --> @if (selectedTask?.project) { - @if (selectedTask?.definition.discussionPromptsCount) { + +
    -
    +
    Homepage Logo diff --git a/src/styles/common/hero-sidebar-layout.scss b/src/styles/common/hero-sidebar-layout.scss index ab2213bcab..aa5f6ac4fc 100644 --- a/src/styles/common/hero-sidebar-layout.scss +++ b/src/styles/common/hero-sidebar-layout.scss @@ -8,7 +8,7 @@ font-size: 24px; } -.subcontainer { +.content-panel { overflow-y: hidden; height: auto; padding-top: 42px; @@ -48,8 +48,8 @@ h1 { } } -f-sign-in .container, -f-welcome .container { +f-sign-in .content-container, +f-welcome .content-container { max-width: 416px; width: 100%; margin: auto; From cd47f5c0e4c351e2421afd94647a1297b3b5ec75 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:49:28 +1000 Subject: [PATCH 1072/1531] fix: display past due date on same day --- src/app/api/models/task.ts | 3 +-- .../directives/unit-task-list/unit-task-list.component.html | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index f812ce1920..b022d3159a 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -525,8 +525,7 @@ export class Task extends Entity { public timeToDue(): string { const days = this.daysUntilDueDate(); - // TODO: check with <= - if (days < 0) { + if (days <= 0) { return 'Past Due Date'; } else if (days < 11) { return `Due in ${this.timeUntilDueDateDescription()}`; diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index d57c3d6d3c..bd2daea1f6 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -66,7 +66,7 @@ Date: Wed, 3 Jun 2026 16:05:44 +1000 Subject: [PATCH 1075/1531] chore: update icon for assess in portfolio --- src/app/api/models/task-status.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/models/task-status.ts b/src/app/api/models/task-status.ts index 9e51c5386e..816d016ba5 100644 --- a/src/app/api/models/task-status.ts +++ b/src/app/api/models/task-status.ts @@ -268,7 +268,7 @@ export class TaskStatus { ['complete', 'done'], ['fail', 'close'], ['time_exceeded', 'schedule'], - ['assess_in_portfolio', 'folder_open'], + ['assess_in_portfolio', 'rate_review'], ['attention_required', 'sms_failed'], ]); From bc5348702280e1b515cfc0873dbf77fd86d3c065 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 16:17:54 +1000 Subject: [PATCH 1076/1531] chore: replace container with tailwind --- src/app/projects/states/plan/project-plan.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/projects/states/plan/project-plan.component.html b/src/app/projects/states/plan/project-plan.component.html index f48483b8bd..a29342d512 100644 --- a/src/app/projects/states/plan/project-plan.component.html +++ b/src/app/projects/states/plan/project-plan.component.html @@ -1,5 +1,5 @@ @if (project) { -
    +

    Task Planner

    @if (unit.allowFlexibleDates) { @@ -16,7 +16,7 @@

    Task Planner

    -
    +
    Target Grade From 7fdee2f43c3c041517a9cba1fb7412950bb159af Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 16:21:43 +1000 Subject: [PATCH 1077/1531] chore(release): 11.0.0-16 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 403239aa0a..cb7a8ea40f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-16](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-15...v11.0.0-16) (2026-06-03) + ## [11.0.0-15](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-14...v11.0.0-15) (2026-06-03) diff --git a/package-lock.json b/package-lock.json index 5eb4d88cd5..b28b8e1394 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-15", + "version": "11.0.0-16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-15", + "version": "11.0.0-16", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 4bccceda69..885d587841 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-15", + "version": "11.0.0-16", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 9e1ef8bcb8e677bd3390e89611d069d669561ab8 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 16:43:47 +1000 Subject: [PATCH 1078/1531] chore: increase stats bar size --- .../directives/portfolios-list/portfolios-list.component.html | 2 +- src/app/units/states/students-list/students-list.component.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html index 1bd6709bcc..fa83b9e354 100644 --- a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html @@ -164,7 +164,7 @@

    Mark portfolios

    Stats -
    +
    @for (bar of project.taskStats; track bar) {
    Students Stats -
    +
    @for (bar of project.taskStats; track bar.key) {
    Date: Wed, 3 Jun 2026 17:00:43 +1000 Subject: [PATCH 1079/1531] feat: support zip file submissions (#1240) --- src/app/app.routes.ts | 5 ++ .../file-uploader/file-uploader.component.ts | 10 ++-- .../submission-files-download.component.html | 26 +++++++++ .../submission-files-download.component.ts | 56 +++++++++++++++++++ src/app/doubtfire-angular.module.ts | 2 + ...tfolio-add-extra-files-step.component.html | 1 + ...ortfolio-add-extra-files-step.component.ts | 2 +- .../task-definition-upload.component.html | 1 + 8 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 src/app/common/submission-files-download/submission-files-download.component.html create mode 100644 src/app/common/submission-files-download/submission-files-download.component.ts diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 25a3244008..5c3f4b8bf1 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -33,6 +33,7 @@ import {resolveUnit} from './units/unit.resolver'; import {UnitRootStateComponent} from './units/unit-root-state.component'; import {WelcomeComponent} from './welcome/welcome.component'; import {roleWhitelistGuard} from './common/guards/role-whitelist.guard'; +import {SubmissionFilesDownloadComponent} from './common/submission-files-download/submission-files-download.component'; export const routes: Routes = [ {path: '', pathMatch: 'full', redirectTo: 'home'}, @@ -62,6 +63,10 @@ export const routes: Routes = [ component: ScormPlayerComponent, data: {mode: 'preview'}, }, + { + path: 'projects/:projectId/task_def_id/:taskDefId/submission_files/download', + component: SubmissionFilesDownloadComponent, + }, {path: 'view-all-units', component: FUnitsComponent, data: {mode: 'tutor'}}, {path: 'view-all-projects', component: FUnitsComponent, data: {mode: 'student'}}, { diff --git a/src/app/common/file-uploader/file-uploader.component.ts b/src/app/common/file-uploader/file-uploader.component.ts index 5f27871ee2..b256d67f54 100644 --- a/src/app/common/file-uploader/file-uploader.component.ts +++ b/src/app/common/file-uploader/file-uploader.component.ts @@ -69,10 +69,9 @@ export const ACCEPTED_TYPES = { name: 'image', }, zip: { - extensions: ['zip', 'tar.gz', 'tar'], - // icon: 'folder_zip', - icon: 'zip_outlined', - name: 'archive', + extensions: ['zip', 'tar.gz', 'tgz', 'tar'], + icon: 'folder_zip', + name: 'zip', }, } as const; @@ -332,7 +331,8 @@ export class FileUploaderComponent implements OnInit, OnChanges { createUploadZones(files: FileData[]) { const zones = Object.entries(files).map(([uploadName, uploadData]) => { - const typeData = ACCEPTED_TYPES[uploadData.type]; + const uploadType = uploadData.type === 'archive' ? 'zip' : uploadData.type; + const typeData = ACCEPTED_TYPES[uploadType]; if (!typeData) throw new Error(`Invalid type provided to File Uploader ${uploadData.type}`); return { diff --git a/src/app/common/submission-files-download/submission-files-download.component.html b/src/app/common/submission-files-download/submission-files-download.component.html new file mode 100644 index 0000000000..67373cd3e5 --- /dev/null +++ b/src/app/common/submission-files-download/submission-files-download.component.html @@ -0,0 +1,26 @@ +
    + @switch (downloadState) { + @case ('downloading') { + +

    Downloading submitted files...

    + } + + @case ('downloaded') { + check_circle +

    Submitted files downloaded.

    + + } + + @case ('failed') { + error +

    Could not download submitted files.

    + + } + } +
    diff --git a/src/app/common/submission-files-download/submission-files-download.component.ts b/src/app/common/submission-files-download/submission-files-download.component.ts new file mode 100644 index 0000000000..386000446b --- /dev/null +++ b/src/app/common/submission-files-download/submission-files-download.component.ts @@ -0,0 +1,56 @@ +import {HttpResponse} from '@angular/common/http'; +import {Component, OnInit} from '@angular/core'; +import {ActivatedRoute} from '@angular/router'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {FileDownloaderService} from '../file-downloader/file-downloader.service'; + +type DownloadState = 'downloading' | 'downloaded' | 'failed'; + +@Component({ + selector: 'f-submission-files-download', + templateUrl: './submission-files-download.component.html', + standalone: false, +}) +export class SubmissionFilesDownloadComponent implements OnInit { + protected downloadState: DownloadState = 'downloading'; + private downloadUrl = ''; + + constructor( + private readonly route: ActivatedRoute, + private readonly constants: DoubtfireConstants, + private readonly fileDownloader: FileDownloaderService, + ) {} + + public ngOnInit(): void { + const projectId = this.route.snapshot.paramMap.get('projectId'); + const taskDefId = this.route.snapshot.paramMap.get('taskDefId'); + + this.downloadUrl = `${this.constants.API_URL}/projects/${projectId}/task_def_id/${taskDefId}/submission_files?as_attachment=true`; + this.download(); + } + + protected download(): void { + this.downloadState = 'downloading'; + + this.fileDownloader.downloadBlob( + this.downloadUrl, + (resourceUrl: string, response: HttpResponse) => { + this.fileDownloader.downloadBlobToFile( + resourceUrl, + this.filenameFromResponse(response) ?? 'submitted-files.zip', + ); + this.downloadState = 'downloaded'; + }, + () => { + this.downloadState = 'failed'; + }, + ); + } + + private filenameFromResponse(response: HttpResponse): string | null { + const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; + const matches = filenameRegex.exec(response.headers.get('Content-Disposition')); + + return matches?.[1]?.replace(/['"]/g, '') ?? null; + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 1b43b1af94..406b585682 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -81,6 +81,7 @@ import {ConfirmationModalComponent} from './common/modals/confirmation-modal/con import {DiscussedInClassReasonModalComponent} from './common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.component'; import {ExtensionModalComponent} from './common/modals/extension-modal/extension-modal.component'; import {HttpAuthenticationInterceptor} from './common/services/http-authentication.interceptor'; +import {SubmissionFilesDownloadComponent} from './common/submission-files-download/submission-files-download.component'; import {ProjectTasksListComponent} from './tasks/project-tasks-list/project-tasks-list.component'; import {DiscussionPromptComposerComponent} from './tasks/task-comment-composer/discussion-prompt-composer/discussion-prompt-composer.component'; import {ExtensionCommentComponent} from './tasks/task-comments-viewer/extension-comment/extension-comment.component'; @@ -484,6 +485,7 @@ const GANTT_CHART_CONFIG = { UnitDropdownComponent, TaskDropdownComponent, SplashScreenComponent, + SubmissionFilesDownloadComponent, ProjectDashboardComponent, GradeIconComponent, GradeTaskModalComponent, diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html index 237e5ce512..073401c523 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html @@ -31,6 +31,7 @@ Document File Code File Image File + Zip File
    diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts index 8b527c3edb..caaaff49ee 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts +++ b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts @@ -13,7 +13,7 @@ export class PortfolioAddExtraFilesStepComponent implements OnInit { @Input() project: Project; @Input() onAdvanceActiveTab?: (index: 1 | -1) => void; - public uploadType: 'document' | 'code' | 'image' = 'document'; + public uploadType: 'document' | 'code' | 'image' | 'zip' = 'document'; public isUploading: boolean; diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html index 6f6f505b28..802213c691 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html @@ -17,6 +17,7 @@ Code Document Image + Zip From 1827efa8f6b1121462e4971770cbc18e6163b656 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:06:46 +1000 Subject: [PATCH 1080/1531] chore(release): 11.0.0-17 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb7a8ea40f..7cbbe891ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-17](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-16...v11.0.0-17) (2026-06-03) + + +### Features + +* support zip file submissions ([#1240](https://github.com/b0ink/doubtfire-deploy/issues/1240)) ([99d546f](https://github.com/b0ink/doubtfire-deploy/commit/99d546f1544feeab31fc6b2434e330b22544b56f)) + ## [11.0.0-16](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-15...v11.0.0-16) (2026-06-03) ## [11.0.0-15](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-14...v11.0.0-15) (2026-06-03) diff --git a/package-lock.json b/package-lock.json index b28b8e1394..ef98296e3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-16", + "version": "11.0.0-17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-16", + "version": "11.0.0-17", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 885d587841..2258c84bdf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-16", + "version": "11.0.0-17", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From f77115691730be298aa808d9a838b516d0a54b44 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:12:36 +1000 Subject: [PATCH 1081/1531] chore: capitalise zip --- .../task-definition-upload.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html index 802213c691..88a76bac70 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html @@ -17,7 +17,7 @@ Code Document Image - Zip + ZIP From 528fd749f730b4cd9cdc49945c2be1fbaca2c1a3 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:13:03 +1000 Subject: [PATCH 1082/1531] chore: capitalise zip --- .../portfolio-add-extra-files-step.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html index 073401c523..84bd32601d 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html @@ -31,7 +31,7 @@ Document File Code File Image File - Zip File + ZIP File
    From 13b476ac8e8460fe52384e7056b3e16988ad9c1d Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:13:11 +1000 Subject: [PATCH 1083/1531] chore(release): 11.0.0-18 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cbbe891ff..7109991baa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-18](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-17...v11.0.0-18) (2026-06-03) + ## [11.0.0-17](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-16...v11.0.0-17) (2026-06-03) diff --git a/package-lock.json b/package-lock.json index ef98296e3c..efc4c770fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-17", + "version": "11.0.0-18", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-17", + "version": "11.0.0-18", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 2258c84bdf..5bd7ecddde 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-17", + "version": "11.0.0-18", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 54b1cf03ed662447e7027a61d084f62f2548c996 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:23:59 +1000 Subject: [PATCH 1084/1531] fix: ensure unit is fetched in unit task editor --- src/app/units/unit.resolver.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/units/unit.resolver.ts b/src/app/units/unit.resolver.ts index 7b5771d654..181cafe4fa 100644 --- a/src/app/units/unit.resolver.ts +++ b/src/app/units/unit.resolver.ts @@ -29,7 +29,7 @@ export const resolveUnit: ResolveFn = (route, state) => { ); } - const resolveProgressively = state.url.split('?')[0].includes('/tasks'); + const resolveProgressively = shouldResolveUnitProgressively(state.url, unitId); if (resolveProgressively) { const unit = unitRole?.unit ?? unitService.cache.getOrCreate(unitId, unitService, {id: unitId}); @@ -65,6 +65,14 @@ export const resolveUnit: ResolveFn = (route, state) => { }).pipe(first()); }; +// Only `/units/:unitId/tasks...` can safely start with a placeholder unit because those screens +// immediately fetch their own inbox/explorer data. Admin routes like `/units/:unitId/admin/tasks` +// still need the full unit payload here so staff, tutorials, and task definitions are populated. +function shouldResolveUnitProgressively(url: string, unitId: number): boolean { + const pathname = url.split('?')[0]; + return new RegExp(`^/units/${unitId}/tasks(?:/|$)`).test(pathname); +} + function routeEntity(unit: Unit, unitRole?: UnitRole): Unit | UnitRole { if (!unitRole) { return unit; From 82848dd8564313f5162b3bcf17c06df7cb2c70cc Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:24:10 +1000 Subject: [PATCH 1085/1531] chore(release): 11.0.0-19 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7109991baa..bc93760c7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-19](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-18...v11.0.0-19) (2026-06-03) + + +### Bug Fixes + +* ensure unit is fetched in unit task editor ([54b1cf0](https://github.com/b0ink/doubtfire-deploy/commit/54b1cf03ed662447e7027a61d084f62f2548c996)) + ## [11.0.0-18](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-17...v11.0.0-18) (2026-06-03) ## [11.0.0-17](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-16...v11.0.0-17) (2026-06-03) diff --git a/package-lock.json b/package-lock.json index efc4c770fa..98764a4477 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-18", + "version": "11.0.0-19", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-18", + "version": "11.0.0-19", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 5bd7ecddde..a382363bcd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-18", + "version": "11.0.0-19", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 2febef9ef68ab455b47f46b4fbec77bd76746faa Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 4 Jun 2026 09:46:43 +1000 Subject: [PATCH 1086/1531] chore: rebuild package-lock.json --- package-lock.json | 2642 ++++++++++----------------------------------- 1 file changed, 586 insertions(+), 2056 deletions(-) diff --git a/package-lock.json b/package-lock.json index 98764a4477..b118832f0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2365,660 +2365,460 @@ "tslib": "^2.4.0" } }, - "node_modules/@esbuild/aix-ppc64": { + "node_modules/@esbuild/linux-arm64": { "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "aix" + "linux" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "peer": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "license": "Python-2.0", + "peer": true }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.1", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "peer": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "peer": true + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@eslint/js": { + "version": "8.57.1", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "peer": true, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], + "node_modules/@gar/promise-retry": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", + "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], + "node_modules/@harperfast/extended-iterable": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@harperfast/extended-iterable/-/extended-iterable-1.0.3.tgz", + "integrity": "sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } + "license": "Apache-2.0", + "optional": true }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], + "node_modules/@hono/node-server": { + "version": "1.19.14", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", + "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, "engines": { - "node": ">=18" + "node": ">=10.10.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], - "dev": true, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.12", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@inquirer/ansi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/checkbox": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", + "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], + "node_modules/@inquirer/confirm": { + "version": "5.1.21", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/core": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.3" + }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "license": "ISC", "engines": { - "node": ">=18" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/editor": { + "version": "4.2.23", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", + "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/external-editor": "^1.0.3", + "@inquirer/type": "^3.0.10" + }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], + "node_modules/@inquirer/expand": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", + "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/external-editor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", + "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.0" + }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], + "node_modules/@inquirer/external-editor/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, "engines": { - "node": ">=18" + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/input": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", + "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.4.3" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "license": "MIT", - "peer": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "license": "MIT", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "license": "Python-2.0", - "peer": true - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.1", - "license": "MIT", - "peer": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "license": "MIT", - "peer": true - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" + "@types/node": ">=18" }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "license": "MIT", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@gar/promise-retry": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", - "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.17.0 || >=22.9.0" + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@harperfast/extended-iterable": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@harperfast/extended-iterable/-/extended-iterable-1.0.3.tgz", - "integrity": "sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==", - "dev": true, - "license": "Apache-2.0", - "optional": true - }, - "node_modules/@hono/node-server": { - "version": "1.19.14", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", - "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", + "node_modules/@inquirer/number": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", + "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "hono": "^4" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "license": "Apache-2.0", - "peer": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" }, "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" + "node": ">=18" }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">=12.22" + "peerDependencies": { + "@types/node": ">=18" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/@inquirer/ansi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", - "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@inquirer/checkbox": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", - "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", + "node_modules/@inquirer/password": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", + "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", "dev": true, "license": "MIT", "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@inquirer/type": "^3.0.10" }, "engines": { "node": ">=18" @@ -3032,248 +2832,23 @@ } } }, - "node_modules/@inquirer/confirm": { - "version": "5.1.21", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", - "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", + "node_modules/@inquirer/prompts": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", + "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/core": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", - "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/core/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@inquirer/editor": { - "version": "4.2.23", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", - "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/external-editor": "^1.0.3", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/expand": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", - "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", - "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^2.1.1", - "iconv-lite": "^0.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/external-editor/node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@inquirer/figures": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", - "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/input": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", - "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/number": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", - "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/password": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", - "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/prompts": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", - "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/checkbox": "^4.3.2", - "@inquirer/confirm": "^5.1.21", - "@inquirer/editor": "^4.2.23", - "@inquirer/expand": "^4.0.23", - "@inquirer/input": "^4.3.1", - "@inquirer/number": "^3.0.23", - "@inquirer/password": "^4.0.23", - "@inquirer/rawlist": "^4.1.11", - "@inquirer/search": "^3.2.2", - "@inquirer/select": "^4.4.2" + "@inquirer/checkbox": "^4.3.2", + "@inquirer/confirm": "^5.1.21", + "@inquirer/editor": "^4.2.23", + "@inquirer/expand": "^4.0.23", + "@inquirer/input": "^4.3.1", + "@inquirer/number": "^3.0.23", + "@inquirer/password": "^4.0.23", + "@inquirer/rawlist": "^4.1.11", + "@inquirer/search": "^3.2.2", + "@inquirer/select": "^4.4.2" }, "engines": { "node": ">=18" @@ -3378,822 +2953,197 @@ } }, "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", - "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@listr2/prompt-adapter-inquirer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-3.0.5.tgz", - "integrity": "sha512-WELs+hj6xcilkloBXYf9XXK8tYEnKsgLj01Xl5ONUJpKjmT5hGVUzNUS5tooUxs7pGMrw+jFD/41WpqW4V3LDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/type": "^3.0.8" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@inquirer/prompts": ">= 3 < 8", - "listr2": "9.0.5" - } - }, - "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.1.tgz", - "integrity": "sha512-tpfN4kKrrMpQ+If1l8bhmoNkECJi0iOu6AEdrTJvWVC+32sLxTARX5Rsu579mPImRP9YFWfWgeRQ5oav7zApQQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.1.tgz", - "integrity": "sha512-+a2tTfc3rmWhLAolFUWRgJtpSuu+Fw/yjn4rF406NMxhfjbMuiOUTDRvRlMFV+DzyjkwnokisskHbCWkS3Ly5w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.1.tgz", - "integrity": "sha512-0EgcE6reYr8InjD7V37EgXcYrloqpxVPINy3ig1MwDSbl6LF/vXTYRH9OE1Ti1D8YZnB35ZH9aTcdfSb5lql2A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.1.tgz", - "integrity": "sha512-aoERa5B6ywXdyFeYGQ1gbQpkMkDbEo45qVoXE5QpIRavqjnyPwjOulMkmkypkmsbJ5z4Wi0TBztON8agCTG0Vg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.1.tgz", - "integrity": "sha512-SqNDY1+vpji7bh0sFH5wlWyFTOzjbDOl0/kB5RLLYDAFyd/uw3n7wyrmas3rYPpAW7z18lMOi1yKlTPv967E3g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-win32-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.1.tgz", - "integrity": "sha512-50v0O1Lt37cwrmR9vWZK5hRW0Aw+KEmxJJ75fge/zIYdvNKB/0bSMSVR5Uc2OV9JhosIUyklOmrEvavwNJ8D6w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.1.tgz", - "integrity": "sha512-qwosvPyl+zpUlp3gRb7UcJ3H8S28XHCzkv0Y0EgQToXjQP91ZD67EHSCDmaLjtKhe+GVIW5om1KUpzVLA0l6pg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "license": "MIT", - "optional": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "license": "MIT", - "optional": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "license": "MIT", - "optional": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "license": "ISC", - "optional": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC", - "optional": true - }, - "node_modules/@mattlewis92/dom-autoscroller": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@mattlewis92/dom-autoscroller/-/dom-autoscroller-2.4.2.tgz", - "integrity": "sha512-YbrUWREPGEjE/FU6foXcAT1YbVwqD/jkYnY1dFb0o4AxtP3s4xKBthlELjndZih8uwsDWgQZx1eNskRNe2BgZQ==", - "license": "MIT" - }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz", - "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@hono/node-server": "^1.19.9", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.2.1", - "express-rate-limit": "^8.2.1", - "hono": "^4.11.4", - "jose": "^6.1.3", - "json-schema-typed": "^8.0.2", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.25 || ^4.0", - "zod-to-json-schema": "^3.25.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@cfworker/json-schema": "^4.1.1", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "@cfworker/json-schema": { - "optional": true - }, - "zod": { - "optional": false - } - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", - "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", - "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", - "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", - "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", - "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@napi-rs/nice": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", - "integrity": "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "optionalDependencies": { - "@napi-rs/nice-android-arm-eabi": "1.1.1", - "@napi-rs/nice-android-arm64": "1.1.1", - "@napi-rs/nice-darwin-arm64": "1.1.1", - "@napi-rs/nice-darwin-x64": "1.1.1", - "@napi-rs/nice-freebsd-x64": "1.1.1", - "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", - "@napi-rs/nice-linux-arm64-gnu": "1.1.1", - "@napi-rs/nice-linux-arm64-musl": "1.1.1", - "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", - "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", - "@napi-rs/nice-linux-s390x-gnu": "1.1.1", - "@napi-rs/nice-linux-x64-gnu": "1.1.1", - "@napi-rs/nice-linux-x64-musl": "1.1.1", - "@napi-rs/nice-openharmony-arm64": "1.1.1", - "@napi-rs/nice-win32-arm64-msvc": "1.1.1", - "@napi-rs/nice-win32-ia32-msvc": "1.1.1", - "@napi-rs/nice-win32-x64-msvc": "1.1.1" - } - }, - "node_modules/@napi-rs/nice-android-arm-eabi": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.1.1.tgz", - "integrity": "sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-android-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.1.1.tgz", - "integrity": "sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==", - "cpu": [ - "arm64" - ], + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, "engines": { - "node": ">= 10" + "node": ">=18.0.0" } }, - "node_modules/@napi-rs/nice-darwin-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.1.1.tgz", - "integrity": "sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==", - "cpu": [ - "arm64" - ], + "node_modules/@istanbuljs/schema": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">= 10" + "node": ">=8" } }, - "node_modules/@napi-rs/nice-darwin-x64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.1.1.tgz", - "integrity": "sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==", - "cpu": [ - "x64" - ], + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": ">= 10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@napi-rs/nice-freebsd-x64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.1.1.tgz", - "integrity": "sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==", - "cpu": [ - "x64" - ], + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.1.1.tgz", - "integrity": "sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==", - "cpu": [ - "arm" - ], + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@napi-rs/nice-linux-arm64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz", - "integrity": "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==", - "cpu": [ - "arm64" - ], + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">= 10" + "node": ">=6.0.0" } }, - "node_modules/@napi-rs/nice-linux-arm64-musl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz", - "integrity": "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==", - "cpu": [ - "arm64" - ], + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@napi-rs/nice-linux-ppc64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.1.1.tgz", - "integrity": "sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==", - "cpu": [ - "ppc64" - ], + "node_modules/@listr2/prompt-adapter-inquirer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-3.0.5.tgz", + "integrity": "sha512-WELs+hj6xcilkloBXYf9XXK8tYEnKsgLj01Xl5ONUJpKjmT5hGVUzNUS5tooUxs7pGMrw+jFD/41WpqW4V3LDA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@inquirer/type": "^3.0.8" + }, "engines": { - "node": ">= 10" + "node": ">=20.0.0" + }, + "peerDependencies": { + "@inquirer/prompts": ">= 3 < 8", + "listr2": "9.0.5" } }, - "node_modules/@napi-rs/nice-linux-riscv64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.1.1.tgz", - "integrity": "sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==", + "node_modules/@lmdb/lmdb-linux-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.1.tgz", + "integrity": "sha512-aoERa5B6ywXdyFeYGQ1gbQpkMkDbEo45qVoXE5QpIRavqjnyPwjOulMkmkypkmsbJ5z4Wi0TBztON8agCTG0Vg==", "cpu": [ - "riscv64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@napi-rs/nice-linux-s390x-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.1.1.tgz", - "integrity": "sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==", - "cpu": [ - "s390x" - ], + "node_modules/@mattlewis92/dom-autoscroller": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@mattlewis92/dom-autoscroller/-/dom-autoscroller-2.4.2.tgz", + "integrity": "sha512-YbrUWREPGEjE/FU6foXcAT1YbVwqD/jkYnY1dFb0o4AxtP3s4xKBthlELjndZih8uwsDWgQZx1eNskRNe2BgZQ==", + "license": "MIT" + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz", + "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@hono/node-server": "^1.19.9", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "hono": "^4.11.4", + "jose": "^6.1.3", + "json-schema-typed": "^8.0.2", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.25 || ^4.0", + "zod-to-json-schema": "^3.25.1" + }, "engines": { - "node": ">= 10" + "node": ">=18" + }, + "peerDependencies": { + "@cfworker/json-schema": "^4.1.1", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "@cfworker/json-schema": { + "optional": true + }, + "zod": { + "optional": false + } } }, - "node_modules/@napi-rs/nice-linux-x64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.1.1.tgz", - "integrity": "sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==", - "cpu": [ - "x64" - ], + "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, "engines": { - "node": ">= 10" + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/@napi-rs/nice-linux-x64-musl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.1.1.tgz", - "integrity": "sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==", - "cpu": [ - "x64" - ], + "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, "engines": { - "node": ">= 10" + "node": ">= 0.10" } }, - "node_modules/@napi-rs/nice-openharmony-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-openharmony-arm64/-/nice-openharmony-arm64-1.1.1.tgz", - "integrity": "sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==", + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", "cpu": [ "arm64" ], @@ -4201,58 +3151,72 @@ "license": "MIT", "optional": true, "os": [ - "openharmony" - ], - "engines": { - "node": ">= 10" - } + "linux" + ] }, - "node_modules/@napi-rs/nice-win32-arm64-msvc": { + "node_modules/@napi-rs/nice": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.1.1.tgz", - "integrity": "sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==", - "cpu": [ - "arm64" - ], + "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", + "integrity": "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/nice-android-arm-eabi": "1.1.1", + "@napi-rs/nice-android-arm64": "1.1.1", + "@napi-rs/nice-darwin-arm64": "1.1.1", + "@napi-rs/nice-darwin-x64": "1.1.1", + "@napi-rs/nice-freebsd-x64": "1.1.1", + "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", + "@napi-rs/nice-linux-arm64-gnu": "1.1.1", + "@napi-rs/nice-linux-arm64-musl": "1.1.1", + "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", + "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", + "@napi-rs/nice-linux-s390x-gnu": "1.1.1", + "@napi-rs/nice-linux-x64-gnu": "1.1.1", + "@napi-rs/nice-linux-x64-musl": "1.1.1", + "@napi-rs/nice-openharmony-arm64": "1.1.1", + "@napi-rs/nice-win32-arm64-msvc": "1.1.1", + "@napi-rs/nice-win32-ia32-msvc": "1.1.1", + "@napi-rs/nice-win32-x64-msvc": "1.1.1" } }, - "node_modules/@napi-rs/nice-win32-ia32-msvc": { + "node_modules/@napi-rs/nice-linux-arm64-gnu": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.1.1.tgz", - "integrity": "sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz", + "integrity": "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==", "cpu": [ - "ia32" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": ">= 10" } }, - "node_modules/@napi-rs/nice-win32-x64-msvc": { + "node_modules/@napi-rs/nice-linux-arm64-musl": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.1.1.tgz", - "integrity": "sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz", + "integrity": "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==", "cpu": [ - "x64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": ">= 10" @@ -4835,323 +3799,106 @@ }, "node_modules/@nx/nx-win32-x64-msvc": { "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-18.3.5.tgz", - "integrity": "sha512-xFwKVTIXSgjdfxkpriqHv5NpmmFILTrWLEkUGSoimuRaAm1u15YWx/VmaUQ+UWuJnmgqvB/so4SMHSfNkq3ijA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@oxc-project/types": { - "version": "0.113.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.113.0.tgz", - "integrity": "sha512-Tp3XmgxwNQ9pEN9vxgJBAqdRamHibi76iowQ38O2I4PMpcvNRQNVsU2n1x1nv9yh0XoTrGFzf7cZSGxmixxrhA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, - "node_modules/@parcel/watcher": { - "version": "2.5.6", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.3", - "is-glob": "^4.0.3", - "node-addon-api": "^7.0.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.6", - "@parcel/watcher-darwin-arm64": "2.5.6", - "@parcel/watcher-darwin-x64": "2.5.6", - "@parcel/watcher-freebsd-x64": "2.5.6", - "@parcel/watcher-linux-arm-glibc": "2.5.6", - "@parcel/watcher-linux-arm-musl": "2.5.6", - "@parcel/watcher-linux-arm64-glibc": "2.5.6", - "@parcel/watcher-linux-arm64-musl": "2.5.6", - "@parcel/watcher-linux-x64-glibc": "2.5.6", - "@parcel/watcher-linux-x64-musl": "2.5.6", - "@parcel/watcher-win32-arm64": "2.5.6", - "@parcel/watcher-win32-ia32": "2.5.6", - "@parcel/watcher-win32-x64": "2.5.6" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.6", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher/node_modules/node-addon-api": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/@parcel/watcher/node_modules/picomatch": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.4.tgz", - "integrity": "sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.4.tgz", - "integrity": "sha512-kFgEvkWLqt3YCgKB5re9RlIrx9bRsvyVUnaTakEpOPuLGzLpLapYxE9BufJNvPg8GjT6mB1alN4yN1NjzoeM8Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.4.tgz", - "integrity": "sha512-JXmaOJGsL/+rsmMfutcDjxWM2fTaVgCHGoXS7nE8Z3c9NAYjGqHvXrAhMUZvMpHS/k7Mg+X7n/MVKb7NYWKKww==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.4.tgz", - "integrity": "sha512-ep3Catd6sPnHTM0P4hNEvIv5arnDvk01PfyJIJ+J3wVCG1eEaPo09tvFqdtcaTrkwQy0VWR24uz+cb4IsK53Qw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.4.tgz", - "integrity": "sha512-LwA5ayKIpnsgXJEwWc3h8wPiS33NMIHd9BhsV92T8VetVAbGe2qXlJwNVDGHN5cOQ22R9uYvbrQir2AB+ntT2w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.4.tgz", - "integrity": "sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.4.tgz", - "integrity": "sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.4.tgz", - "integrity": "sha512-DZaN1f0PGp/bSvKhtw50pPsnln4T13ycDq1FrDWRiHmWt1JeW+UtYg9touPFf8yt993p8tS2QjybpzKNTxYEwg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.4.tgz", - "integrity": "sha512-RnGxwZLN7fhMMAItnD6dZ7lvy+TI7ba+2V54UF4dhaWa/p8I/ys1E73KO6HmPmgz92ZkfD8TXS1IMV8+uhbR9g==", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-18.3.5.tgz", + "integrity": "sha512-xFwKVTIXSgjdfxkpriqHv5NpmmFILTrWLEkUGSoimuRaAm1u15YWx/VmaUQ+UWuJnmgqvB/so4SMHSfNkq3ijA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 10" } }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.4.tgz", - "integrity": "sha512-6lcI79+X8klGiGd8yHuTgQRjuuJYNggmEml+RsyN596P23l/zf9FVmJ7K0KVKkFAeYEdg0iMUKyIxiV5vebDNQ==", - "cpu": [ - "arm64" - ], + "node_modules/@oxc-project/types": { + "version": "0.113.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.113.0.tgz", + "integrity": "sha512-Tp3XmgxwNQ9pEN9vxgJBAqdRamHibi76iowQ38O2I4PMpcvNRQNVsU2n1x1nv9yh0XoTrGFzf7cZSGxmixxrhA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.4.tgz", - "integrity": "sha512-wz7ohsKCAIWy91blZ/1FlpPdqrsm1xpcEOQVveWoL6+aSPKL4VUcoYmmzuLTssyZxRpEwzuIxL/GDsvpjaBtOw==", - "cpu": [ - "wasm32" - ], + "node_modules/@parcel/watcher": { + "version": "2.5.6", "dev": true, + "hasInstallScript": true, "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^1.1.1" + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">=14.0.0" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" } }, - "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.1" + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "node_modules/@parcel/watcher/node_modules/node-addon-api": { + "version": "7.1.1", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@parcel/watcher/node_modules/picomatch": { + "version": "4.0.3", "dev": true, "license": "MIT", "optional": true, - "dependencies": { - "tslib": "^2.4.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { + "node_modules/@rolldown/binding-linux-arm64-gnu": { "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.4.tgz", - "integrity": "sha512-cfiMrfuWCIgsFmcVG0IPuO6qTRHvF7NuG3wngX1RZzc6dU8FuBFb+J3MIR5WrdTNozlumfgL4cvz+R4ozBCvsQ==", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.4.tgz", + "integrity": "sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==", "cpu": [ "arm64" ], @@ -5159,24 +3906,24 @@ "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-win32-x64-msvc": { + "node_modules/@rolldown/binding-linux-arm64-musl": { "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.4.tgz", - "integrity": "sha512-p6UeR9y7ht82AH57qwGuFYn69S6CZ7LLKdCKy/8T3zS9VTrJei2/CGsTUV45Da4Z9Rbhc7G4gyWQ/Ioamqn09g==", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.4.tgz", + "integrity": "sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==", "cpu": [ - "x64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" @@ -5427,9 +4174,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", - "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.0.tgz", + "integrity": "sha512-0uMOcf3eZ5K+K4cYHkdxShFMPlPXCOdfDFEFn9dNYAEEd2cVvmOfH7zFgRVoDgmtQ1m9k5q7qfrHzyMAubKYUA==", "cpu": [ "x64" ], @@ -6545,11 +5292,6 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/abbrev": { - "version": "1.1.1", - "license": "ISC", - "optional": true - }, "node_modules/accepts": { "version": "1.3.8", "dev": true, @@ -7155,28 +5897,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/aproba": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "license": "ISC", - "optional": true - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/arg": { "version": "5.0.2", "dev": true, @@ -7887,22 +6607,6 @@ "dev": true, "license": "MIT" }, - "node_modules/canvas": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", - "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.17.0", - "simple-get": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/canvas-confetti": { "version": "1.9.4", "license": "ISC", @@ -8113,16 +6817,6 @@ "version": "1.1.4", "license": "MIT" }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "license": "ISC", - "optional": true, - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -8302,13 +6996,6 @@ "dev": true, "license": "MIT" }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "license": "ISC", - "optional": true - }, "node_modules/content-disposition": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", @@ -8883,19 +7570,6 @@ "node": ">=0.10.0" } }, - "node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "license": "MIT", - "optional": true, - "dependencies": { - "mimic-response": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/deep-is": { "version": "0.1.4", "license": "MIT", @@ -8990,13 +7664,6 @@ "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "license": "MIT", - "optional": true - }, "node_modules/depd": { "version": "2.0.0", "dev": true, @@ -9024,6 +7691,7 @@ }, "node_modules/detect-libc": { "version": "2.1.2", + "dev": true, "license": "Apache-2.0", "optional": true, "engines": { @@ -10424,28 +9092,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -10760,13 +9406,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "license": "ISC", - "optional": true - }, "node_modules/hasown": { "version": "2.0.2", "dev": true, @@ -12623,19 +11262,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/minimatch": { "version": "9.0.5", "dev": true, @@ -12917,13 +11543,6 @@ "thenify-all": "^1.0.0" } }, - "node_modules/nan": { - "version": "2.26.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.26.2.tgz", - "integrity": "sha512-0tTvBTYkt3tdGw22nrAy50x7gpbGCCFH3AFcyS5WiUu7Eu4vWlri1woE6qHBSfy11vksDqkiwjOnlR7WV8G1Hw==", - "license": "MIT", - "optional": true - }, "node_modules/nanoid": { "version": "3.3.11", "dev": true, @@ -13052,27 +11671,6 @@ "license": "MIT", "optional": true }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "optional": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-gyp": { "version": "12.3.0", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.3.0.tgz", @@ -15720,20 +14318,6 @@ "node": ">=18" } }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -16077,7 +14661,7 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -17766,6 +16350,20 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", + "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -18294,39 +16892,6 @@ "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "optional": true - }, - "node_modules/simple-get": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", - "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", - "license": "MIT", - "optional": true, - "dependencies": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/slash": { "version": "3.0.0", "dev": true, @@ -18998,13 +17563,6 @@ "node": ">=6" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT", - "optional": true - }, "node_modules/tree-kill": { "version": "1.2.2", "dev": true, @@ -19855,24 +18413,6 @@ "node": ">=0.8.0" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause", - "optional": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "optional": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "license": "ISC", @@ -19890,16 +18430,6 @@ "version": "2.0.1", "license": "ISC" }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "license": "ISC", - "optional": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "license": "MIT", From 0eb003ae99454d158d06f48067f4477e18157756 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:07:05 +1000 Subject: [PATCH 1087/1531] chore: remove npm package --- package-lock.json | 3147 +++++++++------------------------------------ package.json | 1 - 2 files changed, 589 insertions(+), 2559 deletions(-) diff --git a/package-lock.json b/package-lock.json index b118832f0b..70f9a49c31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,7 +58,6 @@ "ngx-lottie": "^11.0.2", "ngx-monaco-editor-v2": "^21", "ngx-skeleton-loader": "^12.0.0", - "npm": "^10.4.0", "nvd3": "1.8.6", "qrcode": "^1.5.4", "rxjs": "~7.8.2", @@ -2428,7 +2427,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "license": "MIT", "peer": true, "dependencies": { @@ -2448,7 +2449,9 @@ "peer": true }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "license": "MIT", "peer": true, "dependencies": { @@ -2473,7 +2476,9 @@ "peer": true }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "peer": true, "dependencies": { @@ -2536,7 +2541,9 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.12", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "license": "MIT", "peer": true, "dependencies": { @@ -2545,7 +2552,9 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "peer": true, "dependencies": { @@ -3446,9 +3455,9 @@ } }, "node_modules/@npmcli/package-json/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -3858,6 +3867,132 @@ "@parcel/watcher-win32-x64": "2.5.6" } }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@parcel/watcher-linux-arm64-glibc": { "version": "2.5.6", "cpu": [ @@ -3877,6 +4012,132 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@parcel/watcher/node_modules/node-addon-api": { "version": "7.1.1", "dev": true, @@ -3884,7 +4145,9 @@ "optional": true }, "node_modules/@parcel/watcher/node_modules/picomatch": { - "version": "4.0.3", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "optional": true, @@ -4852,9 +5115,9 @@ } }, "node_modules/@tufjs/models/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -4978,6 +5241,16 @@ "license": "MIT", "optional": true }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.11.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.11.0.tgz", @@ -5419,7 +5692,10 @@ } }, "node_modules/angular": { - "version": "1.5.11", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz", + "integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==", + "deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward.", "license": "MIT" }, "node_modules/angular-calendar": { @@ -5715,9 +5991,9 @@ } }, "node_modules/angular-eslint/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -5887,7 +6163,9 @@ } }, "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "devOptional": true, "license": "MIT", "engines": { @@ -6100,15 +6378,29 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", - "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.17.0.tgz", + "integrity": "sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw==", "dev": true, "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.11", + "follow-redirects": "^1.16.0", "form-data": "^4.0.5", - "proxy-from-env": "^1.1.0" + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axios/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" } }, "node_modules/axios/node_modules/form-data": { @@ -6128,6 +6420,20 @@ "node": ">= 6" } }, + "node_modules/axios/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "4.0.0", "dev": true, @@ -6245,7 +6551,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.4", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "dev": true, "license": "MIT", "dependencies": { @@ -6257,7 +6565,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.14.0", + "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -6310,7 +6618,9 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.0.2", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "dev": true, "license": "MIT", "dependencies": { @@ -6469,9 +6779,9 @@ } }, "node_modules/cacache/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -7948,19 +8258,22 @@ } }, "node_modules/engine.io": { - "version": "6.6.5", + "version": "6.6.8", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.8.tgz", + "integrity": "sha512-2agL3ueZhqxoVrfmntO8yuVj+uNSlIOnhykYHk3Cq0ShYPdUjjUiSJrQvXjq01I9jAuI0Zl2YO8Evv5Mqytm5g==", "dev": true, "license": "MIT", "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", + "@types/ws": "^8.5.12", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.4.1", "engine.io-parser": "~5.2.1", - "ws": "~8.18.3" + "ws": "~8.20.1" }, "engines": { "node": ">=10.2.0" @@ -8256,7 +8569,9 @@ } }, "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "license": "MIT", "peer": true, "dependencies": { @@ -8276,7 +8591,9 @@ "peer": true }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "license": "MIT", "peer": true, "dependencies": { @@ -8327,7 +8644,9 @@ "peer": true }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "peer": true, "dependencies": { @@ -8496,13 +8815,13 @@ } }, "node_modules/express-rate-limit": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.4.1.tgz", - "integrity": "sha512-NGVYwQSAyEQgzxX1iCM978PP9AdO/hW93gMcF6ZwQCm+rFvLsBH6w4xcXWTcliS8La5EPRN3p9wzItqBwJrfNw==", + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.2.tgz", + "integrity": "sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==", "dev": true, "license": "MIT", "dependencies": { - "ip-address": "10.1.0" + "ip-address": "^10.2.0" }, "engines": { "node": ">= 16" @@ -8794,9 +9113,9 @@ "peer": true }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "funding": [ { "type": "github", @@ -8975,11 +9294,15 @@ } }, "node_modules/flatted": { - "version": "3.3.3", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.11", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "dev": true, "funding": [ { @@ -9219,7 +9542,9 @@ "license": "BSD-2-Clause" }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.12", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -9227,7 +9552,9 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -9336,7 +9663,9 @@ } }, "node_modules/har-validator/node_modules/ajv": { - "version": "6.12.6", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -9418,9 +9747,9 @@ } }, "node_modules/hono": { - "version": "4.12.15", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.15.tgz", - "integrity": "sha512-qM0jDhFEaCBb4TxoW7f53Qrpv9RBiayUHo0S52JudprkhvpjIrGoU1mnnr29Fvd1U335ZFPZQY1wlkqgfGXyLg==", + "version": "4.12.23", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.23.tgz", + "integrity": "sha512-eIaZ9qDgu7XV0pxOCrg7/WhnQ6Ivm22UcxhXx/A3dcbqbbYgBEkc6e/J/s7j2tS96zoB0S9VBdLwQNCWwUo4LA==", "dev": true, "license": "MIT", "engines": { @@ -9655,9 +9984,9 @@ } }, "node_modules/ignore-walk/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -9688,7 +10017,9 @@ "license": "MIT" }, "node_modules/immutable": { - "version": "5.1.4", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.6.tgz", + "integrity": "sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==", "dev": true, "license": "MIT" }, @@ -9769,9 +10100,9 @@ "license": "MIT" }, "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", "dev": true, "license": "MIT", "engines": { @@ -10434,7 +10765,9 @@ } }, "node_modules/karma-coverage-istanbul-reporter/node_modules/brace-expansion": { - "version": "1.1.12", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -10443,7 +10776,9 @@ } }, "node_modules/karma-coverage-istanbul-reporter/node_modules/minimatch": { - "version": "3.1.2", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -10483,7 +10818,9 @@ "license": "MIT" }, "node_modules/karma/node_modules/brace-expansion": { - "version": "1.1.12", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -10502,7 +10839,9 @@ } }, "node_modules/karma/node_modules/minimatch": { - "version": "3.1.2", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -11202,7 +11541,9 @@ } }, "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -11263,11 +11604,13 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -11796,2526 +12139,201 @@ }, "node_modules/normalize-range": { "version": "0.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm": { - "version": "10.9.6", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.9.6.tgz", - "integrity": "sha512-EHxr81fXY1K9yyLklI2gc9WuhMSh2e4PXuVG/VXJoHSrH4Lbrv01V/Nhkqu+mvm+58UMh59YBtvHU2wb4ikCUw==", - "bundleDependencies": [ - "@isaacs/string-locale-compare", - "@npmcli/arborist", - "@npmcli/config", - "@npmcli/fs", - "@npmcli/map-workspaces", - "@npmcli/package-json", - "@npmcli/promise-spawn", - "@npmcli/redact", - "@npmcli/run-script", - "@sigstore/tuf", - "abbrev", - "archy", - "cacache", - "chalk", - "ci-info", - "cli-columns", - "fastest-levenshtein", - "fs-minipass", - "glob", - "graceful-fs", - "hosted-git-info", - "ini", - "init-package-json", - "is-cidr", - "json-parse-even-better-errors", - "libnpmaccess", - "libnpmdiff", - "libnpmexec", - "libnpmfund", - "libnpmhook", - "libnpmorg", - "libnpmpack", - "libnpmpublish", - "libnpmsearch", - "libnpmteam", - "libnpmversion", - "make-fetch-happen", - "minimatch", - "minipass", - "minipass-pipeline", - "ms", - "node-gyp", - "nopt", - "normalize-package-data", - "npm-audit-report", - "npm-install-checks", - "npm-package-arg", - "npm-pick-manifest", - "npm-profile", - "npm-registry-fetch", - "npm-user-validate", - "p-map", - "pacote", - "parse-conflict-json", - "proc-log", - "qrcode-terminal", - "read", - "semver", - "spdx-expression-parse", - "ssri", - "supports-color", - "tar", - "text-table", - "tiny-relative-date", - "treeverse", - "validate-npm-package-name", - "which", - "write-file-atomic" - ], - "license": "Artistic-2.0", - "workspaces": [ - "docs", - "smoke-tests", - "mock-globals", - "mock-registry", - "workspaces/*" - ], - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^8.0.3", - "@npmcli/config": "^9.0.0", - "@npmcli/fs": "^4.0.0", - "@npmcli/map-workspaces": "^4.0.2", - "@npmcli/package-json": "^6.2.0", - "@npmcli/promise-spawn": "^8.0.3", - "@npmcli/redact": "^3.2.2", - "@npmcli/run-script": "^9.1.0", - "@sigstore/tuf": "^3.1.1", - "abbrev": "^3.0.1", - "archy": "~1.0.0", - "cacache": "^19.0.1", - "chalk": "^5.6.2", - "ci-info": "^4.4.0", - "cli-columns": "^4.0.0", - "fastest-levenshtein": "^1.0.16", - "fs-minipass": "^3.0.3", - "glob": "^10.5.0", - "graceful-fs": "^4.2.11", - "hosted-git-info": "^8.1.0", - "ini": "^5.0.0", - "init-package-json": "^7.0.2", - "is-cidr": "^5.1.1", - "json-parse-even-better-errors": "^4.0.0", - "libnpmaccess": "^9.0.0", - "libnpmdiff": "^7.0.3", - "libnpmexec": "^9.0.3", - "libnpmfund": "^6.0.3", - "libnpmhook": "^11.0.0", - "libnpmorg": "^7.0.0", - "libnpmpack": "^8.0.3", - "libnpmpublish": "^10.0.2", - "libnpmsearch": "^8.0.0", - "libnpmteam": "^7.0.0", - "libnpmversion": "^7.0.0", - "make-fetch-happen": "^14.0.3", - "minimatch": "^9.0.9", - "minipass": "^7.1.3", - "minipass-pipeline": "^1.2.4", - "ms": "^2.1.2", - "node-gyp": "^11.5.0", - "nopt": "^8.1.0", - "normalize-package-data": "^7.0.1", - "npm-audit-report": "^6.0.0", - "npm-install-checks": "^7.1.2", - "npm-package-arg": "^12.0.2", - "npm-pick-manifest": "^10.0.0", - "npm-profile": "^11.0.1", - "npm-registry-fetch": "^18.0.2", - "npm-user-validate": "^3.0.0", - "p-map": "^7.0.4", - "pacote": "^19.0.1", - "parse-conflict-json": "^4.0.0", - "proc-log": "^5.0.0", - "qrcode-terminal": "^0.12.0", - "read": "^4.1.0", - "semver": "^7.7.4", - "spdx-expression-parse": "^4.0.0", - "ssri": "^12.0.0", - "supports-color": "^9.4.0", - "tar": "^7.5.11", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "treeverse": "^3.0.0", - "validate-npm-package-name": "^6.0.2", - "which": "^5.0.0", - "write-file-atomic": "^6.0.0" - }, - "bin": { - "npm": "bin/npm-cli.js", - "npx": "bin/npx-cli.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm-bundled": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-5.0.0.tgz", - "integrity": "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^5.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-bundled/node_modules/npm-normalize-package-bin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", - "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-install-checks": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", - "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", - "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm-package-arg": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.2.tgz", - "integrity": "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==", - "dev": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^9.0.0", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^7.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-packlist": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.4.tgz", - "integrity": "sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng==", - "dev": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^8.0.0", - "proc-log": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-pick-manifest": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", - "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^8.0.0", - "npm-normalize-package-bin": "^5.0.0", - "npm-package-arg": "^13.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", - "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-registry-fetch": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", - "integrity": "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/redact": "^4.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^15.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^5.0.0", - "minizlib": "^3.0.1", - "npm-package-arg": "^13.0.0", - "proc-log": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-run-all2": { - "version": "7.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "cross-spawn": "^7.0.6", - "memorystream": "^0.3.1", - "minimatch": "^9.0.0", - "pidtree": "^0.6.0", - "read-package-json-fast": "^4.0.0", - "shell-quote": "^1.7.3", - "which": "^5.0.0" - }, - "bin": { - "npm-run-all": "bin/npm-run-all/index.js", - "npm-run-all2": "bin/npm-run-all/index.js", - "run-p": "bin/run-p/index.js", - "run-s": "bin/run-s/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0", - "npm": ">= 9" - } - }, - "node_modules/npm-run-all2/node_modules/ansi-styles": { - "version": "6.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm-run-all2/node_modules/isexe": { - "version": "3.1.5", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/npm-run-all2/node_modules/which": { - "version": "5.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui": { - "version": "8.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.2.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/npm/node_modules/@isaacs/string-locale-compare": { - "version": "1.1.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/@npmcli/agent": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "8.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/fs": "^4.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/map-workspaces": "^4.0.1", - "@npmcli/metavuln-calculator": "^8.0.0", - "@npmcli/name-from-folder": "^3.0.0", - "@npmcli/node-gyp": "^4.0.0", - "@npmcli/package-json": "^6.0.1", - "@npmcli/query": "^4.0.0", - "@npmcli/redact": "^3.0.0", - "@npmcli/run-script": "^9.0.1", - "bin-links": "^5.0.0", - "cacache": "^19.0.1", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^8.0.0", - "json-parse-even-better-errors": "^4.0.0", - "json-stringify-nice": "^1.1.4", - "lru-cache": "^10.2.2", - "minimatch": "^9.0.4", - "nopt": "^8.0.0", - "npm-install-checks": "^7.1.0", - "npm-package-arg": "^12.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.1", - "pacote": "^19.0.0", - "parse-conflict-json": "^4.0.0", - "proc-log": "^5.0.0", - "proggy": "^3.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^3.0.1", - "promise-retry": "^2.0.1", - "read-package-json-fast": "^4.0.0", - "semver": "^7.3.7", - "ssri": "^12.0.0", - "treeverse": "^3.0.0", - "walk-up-path": "^3.0.1" - }, - "bin": { - "arborist": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/config": { - "version": "9.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/map-workspaces": "^4.0.1", - "@npmcli/package-json": "^6.0.1", - "ci-info": "^4.0.0", - "ini": "^5.0.0", - "nopt": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/fs": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/git": { - "version": "6.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^8.0.0", - "ini": "^5.0.0", - "lru-cache": "^10.0.1", - "npm-pick-manifest": "^10.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/installed-package-contents": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^4.0.0", - "npm-normalize-package-bin": "^4.0.0" - }, - "bin": { - "installed-package-contents": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "4.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/name-from-folder": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "glob": "^10.2.2", - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "8.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "cacache": "^19.0.0", - "json-parse-even-better-errors": "^4.0.0", - "pacote": "^20.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator/node_modules/pacote": { - "version": "20.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "@npmcli/run-script": "^9.0.0", - "cacache": "^19.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^12.0.0", - "npm-packlist": "^9.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^3.0.0", - "ssri": "^12.0.0", - "tar": "^7.5.10" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/name-from-folder": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/node-gyp": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "6.2.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.0", - "glob": "^10.2.2", - "hosted-git-info": "^8.0.0", - "json-parse-even-better-errors": "^4.0.0", - "proc-log": "^5.0.0", - "semver": "^7.5.3", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "8.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/query": { - "version": "4.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "postcss-selector-parser": "^7.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/redact": { - "version": "3.2.2", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "9.1.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^4.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "node-gyp": "^11.0.0", - "proc-log": "^5.0.0", - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.4.3", - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "3.1.1", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.4.1", - "tuf-js": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@tufjs/canonical-json": { - "version": "2.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/abbrev": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/agent-base": { - "version": "7.1.4", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/ansi-regex": { - "version": "5.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-styles": { - "version": "6.2.3", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/aproba": { - "version": "2.1.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/archy": { - "version": "1.0.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/balanced-match": { - "version": "1.0.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/bin-links": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "cmd-shim": "^7.0.0", - "npm-normalize-package-bin": "^4.0.0", - "proc-log": "^5.0.0", - "read-cmd-shim": "^5.0.0", - "write-file-atomic": "^6.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/binary-extensions": { - "version": "2.3.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/brace-expansion": { - "version": "2.0.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/npm/node_modules/cacache": { - "version": "19.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^4.0.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^7.0.2", - "ssri": "^12.0.0", - "tar": "^7.4.3", - "unique-filename": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/chalk": { - "version": "5.6.2", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/npm/node_modules/chownr": { - "version": "3.0.0", - "inBundle": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/ci-info": { - "version": "4.4.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/cidr-regex": { - "version": "4.1.3", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "ip-regex": "^5.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/cli-columns": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/cmd-shim": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/color-convert": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/npm/node_modules/color-name": { - "version": "1.1.4", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/common-ancestor-path": { - "version": "1.0.1", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/cross-spawn": { - "version": "7.0.6", - "inBundle": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cssesc": { - "version": "3.0.0", - "inBundle": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/debug": { - "version": "4.4.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/npm/node_modules/diff": { - "version": "5.2.2", - "inBundle": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/npm/node_modules/eastasianwidth": { - "version": "0.2.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/emoji-regex": { - "version": "8.0.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/encoding": { - "version": "0.1.13", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/npm/node_modules/env-paths": { - "version": "2.2.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/err-code": { - "version": "2.0.3", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/exponential-backoff": { - "version": "3.1.3", - "inBundle": true, - "license": "Apache-2.0" - }, - "node_modules/npm/node_modules/fastest-levenshtein": { - "version": "1.0.16", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/npm/node_modules/fdir": { - "version": "6.5.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/npm/node_modules/foreground-child": { - "version": "3.3.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/fs-minipass": { - "version": "3.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/glob": { - "version": "10.5.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/graceful-fs": { - "version": "4.2.11", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/hosted-git-info": { - "version": "8.1.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/http-cache-semantics": { - "version": "4.2.0", - "inBundle": true, - "license": "BSD-2-Clause" - }, - "node_modules/npm/node_modules/http-proxy-agent": { - "version": "7.0.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/https-proxy-agent": { - "version": "7.0.6", - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/iconv-lite": { - "version": "0.6.3", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/ignore-walk": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/imurmurhash": { - "version": "0.1.4", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/npm/node_modules/ini": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/init-package-json": { - "version": "7.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/package-json": "^6.0.0", - "npm-package-arg": "^12.0.0", - "promzard": "^2.0.0", - "read": "^4.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^6.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/ip-address": { - "version": "10.1.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/npm/node_modules/ip-regex": { - "version": "5.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/is-cidr": { - "version": "5.1.1", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "cidr-regex": "^4.1.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/isexe": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/jackspeak": { - "version": "3.4.3", - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/npm/node_modules/json-parse-even-better-errors": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/json-stringify-nice": { - "version": "1.1.4", - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/jsonparse": { - "version": "1.3.1", - "engines": [ - "node >= 0.2.0" - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff": { - "version": "6.0.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff-apply": { - "version": "5.5.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/libnpmaccess": { - "version": "9.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^12.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmdiff": { - "version": "7.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.3", - "@npmcli/installed-package-contents": "^3.0.0", - "binary-extensions": "^2.3.0", - "diff": "^5.1.0", - "minimatch": "^9.0.4", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0", - "tar": "^7.5.11" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmexec": { - "version": "9.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.3", - "@npmcli/run-script": "^9.0.1", - "ci-info": "^4.0.0", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0", - "proc-log": "^5.0.0", - "read": "^4.0.0", - "read-package-json-fast": "^4.0.0", - "semver": "^7.3.7", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmfund": { - "version": "6.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.3" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmhook": { - "version": "11.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmorg": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmpack": { - "version": "8.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.3", - "@npmcli/run-script": "^9.0.1", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmpublish": { - "version": "10.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "ci-info": "^4.0.0", - "normalize-package-data": "^7.0.0", - "npm-package-arg": "^12.0.0", - "npm-registry-fetch": "^18.0.1", - "proc-log": "^5.0.0", - "semver": "^7.3.7", - "sigstore": "^3.0.0", - "ssri": "^12.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmsearch": { - "version": "8.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmteam": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmversion": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.1", - "@npmcli/run-script": "^9.0.1", - "json-parse-even-better-errors": "^4.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/lru-cache": { - "version": "10.4.3", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/make-fetch-happen": { - "version": "14.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^3.0.0", - "cacache": "^19.0.1", - "http-cache-semantics": "^4.1.1", - "minipass": "^7.0.2", - "minipass-fetch": "^4.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^1.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "ssri": "^12.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/minimatch": { - "version": "9.0.9", - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/minipass": { - "version": "7.1.3", - "inBundle": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm/node_modules/minipass-collect": { - "version": "2.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm/node_modules/minipass-fetch": { - "version": "4.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/minipass-flush": { - "version": "1.0.5", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-flush/node_modules/yallist": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/minipass-pipeline": { - "version": "1.2.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline/node_modules/yallist": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/minipass-sized": { - "version": "1.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized/node_modules/yallist": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/minizlib": { - "version": "3.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/npm/node_modules/ms": { - "version": "2.1.3", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/mute-stream": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/negotiator": { - "version": "1.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/node-gyp": { - "version": "11.5.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^14.0.3", - "nopt": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "tar": "^7.4.3", - "tinyglobby": "^0.2.12", - "which": "^5.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/nopt": { - "version": "8.1.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^3.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/normalize-package-data": { - "version": "7.0.1", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^8.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-audit-report": { - "version": "6.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-bundled": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-install-checks": { - "version": "7.1.2", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-normalize-package-bin": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-package-arg": { - "version": "12.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^6.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-packlist": { - "version": "9.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^7.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "10.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^7.1.0", - "npm-normalize-package-bin": "^4.0.0", - "npm-package-arg": "^12.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-profile": { - "version": "11.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^18.0.0", - "proc-log": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "18.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/redact": "^3.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^14.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^4.0.0", - "minizlib": "^3.0.1", - "npm-package-arg": "^12.0.0", - "proc-log": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-user-validate": { - "version": "3.0.0", - "inBundle": true, - "license": "BSD-2-Clause", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/p-map": { - "version": "7.0.4", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/package-json-from-dist": { - "version": "1.0.1", - "inBundle": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/npm/node_modules/pacote": { - "version": "19.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "@npmcli/run-script": "^9.0.0", - "cacache": "^19.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^12.0.0", - "npm-packlist": "^9.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^3.0.0", - "ssri": "^12.0.0", - "tar": "^7.5.10" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/parse-conflict-json": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^4.0.0", - "just-diff": "^6.0.0", - "just-diff-apply": "^5.2.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/path-key": { - "version": "3.1.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/path-scurry": { - "version": "1.11.1", - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/picomatch": { - "version": "4.0.3", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "7.1.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/proc-log": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/proggy": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/promise-all-reject-late": { - "version": "1.0.1", - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-call-limit": { - "version": "3.0.2", - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-retry": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/promzard": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "read": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/qrcode-terminal": { - "version": "0.12.0", - "inBundle": true, - "bin": { - "qrcode-terminal": "bin/qrcode-terminal.js" - } - }, - "node_modules/npm/node_modules/read": { - "version": "4.1.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "mute-stream": "^2.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/read-cmd-shim": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/read-package-json-fast": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^4.0.0", - "npm-normalize-package-bin": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/retry": { - "version": "0.12.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/npm/node_modules/safer-buffer": { - "version": "2.1.2", - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/npm/node_modules/semver": { - "version": "7.7.4", - "inBundle": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/shebang-command": { - "version": "2.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/shebang-regex": { - "version": "3.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/signal-exit": { - "version": "4.1.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/sigstore": { - "version": "3.1.0", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^3.1.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.4.0", - "@sigstore/sign": "^3.1.0", - "@sigstore/tuf": "^3.1.0", - "@sigstore/verify": "^2.1.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/bundle": { - "version": "3.1.0", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.4.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/core": { - "version": "2.0.0", - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/sign": { - "version": "3.1.0", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^3.1.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.4.0", - "make-fetch-happen": "^14.0.2", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/verify": { - "version": "2.1.1", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^3.1.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.4.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/smart-buffer": { - "version": "4.2.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks": { - "version": "2.8.7", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "8.0.5", - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/spdx-correct": { - "version": "3.2.0", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-exceptions": { - "version": "2.5.0", - "inBundle": true, - "license": "CC-BY-3.0" - }, - "node_modules/npm/node_modules/spdx-expression-parse": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.23", - "inBundle": true, - "license": "CC0-1.0" - }, - "node_modules/npm/node_modules/ssri": { - "version": "12.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/string-width": { - "version": "4.2.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi": { - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/supports-color": { - "version": "9.4.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/npm/node_modules/tar": { - "version": "7.5.11", - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/text-table": { - "version": "0.2.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/tiny-relative-date": { - "version": "1.3.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/tinyglobby": { - "version": "0.2.15", - "inBundle": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/npm/node_modules/treeverse": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js": { - "version": "3.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/models": "3.0.1", - "debug": "^4.4.1", - "make-fetch-happen": "^14.0.3" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/@tufjs/models": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.5" - }, + "dev": true, + "license": "MIT", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=0.10.0" } }, - "node_modules/npm/node_modules/unique-filename": { - "version": "4.0.0", - "inBundle": true, + "node_modules/npm-bundled": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-5.0.0.tgz", + "integrity": "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==", + "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^5.0.0" + "npm-normalize-package-bin": "^5.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/unique-slug": { + "node_modules/npm-bundled/node_modules/npm-normalize-package-bin": { "version": "5.0.0", - "inBundle": true, + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", + "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", + "dev": true, "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/util-deprecate": { - "version": "1.0.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/validate-npm-package-license": { - "version": "3.0.4", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", + "node_modules/npm-install-checks": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", + "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "semver": "^7.1.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "6.0.2", - "inBundle": true, + "node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", + "dev": true, "license": "ISC", "engines": { "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/walk-up-path": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/which": { - "version": "5.0.0", - "inBundle": true, + "node_modules/npm-package-arg": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.2.tgz", + "integrity": "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==", + "dev": true, "license": "ISC", "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" + "hosted-git-info": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^7.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/which/node_modules/isexe": { - "version": "3.1.5", - "inBundle": true, - "license": "BlueOak-1.0.0", + "node_modules/npm-packlist": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.4.tgz", + "integrity": "sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng==", + "dev": true, + "license": "ISC", + "dependencies": { + "ignore-walk": "^8.0.0", + "proc-log": "^6.0.0" + }, "engines": { - "node": ">=18" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/wrap-ansi": { - "version": "8.1.0", - "inBundle": true, - "license": "MIT", + "node_modules/npm-pick-manifest": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", + "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", + "dev": true, + "license": "ISC", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "npm-install-checks": "^8.0.0", + "npm-normalize-package-bin": "^5.0.0", + "npm-package-arg": "^13.0.0", + "semver": "^7.3.5" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, + "node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", + "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", + "dev": true, + "license": "ISC", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "inBundle": true, - "license": "MIT", + "node_modules/npm-registry-fetch": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", + "integrity": "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==", + "dev": true, + "license": "ISC", "dependencies": { - "color-convert": "^2.0.1" + "@npmcli/redact": "^4.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^15.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^5.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^13.0.0", + "proc-log": "^6.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.2.2", - "inBundle": true, + "node_modules/npm-run-all2": { + "version": "7.0.2", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "ansi-styles": "^6.2.1", + "cross-spawn": "^7.0.6", + "memorystream": "^0.3.1", + "minimatch": "^9.0.0", + "pidtree": "^0.6.0", + "read-package-json-fast": "^4.0.0", + "shell-quote": "^1.7.3", + "which": "^5.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0", + "npm": ">= 9" } }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "inBundle": true, + "node_modules/npm-run-all2/node_modules/ansi-styles": { + "version": "6.2.3", + "dev": true, "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.2.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, + "node_modules/npm-run-all2/node_modules/isexe": { + "version": "3.1.5", + "dev": true, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=18" } }, - "node_modules/npm/node_modules/write-file-atomic": { - "version": "6.0.0", - "inBundle": true, + "node_modules/npm-run-all2/node_modules/which": { + "version": "5.0.0", + "dev": true, "license": "ISC", "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" }, "engines": { "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/yallist": { - "version": "5.0.0", - "inBundle": true, - "license": "BlueOak-1.0.0", + "node_modules/npm-run-path": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, "node_modules/nth-check": { @@ -15280,20 +13298,6 @@ "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/postcss-load-config/node_modules/yaml": { - "version": "2.8.2", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", @@ -15798,11 +13802,14 @@ } }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/psl": { "version": "1.15.0", @@ -15949,7 +13956,9 @@ } }, "node_modules/qs": { - "version": "6.14.2", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -16120,7 +14129,9 @@ } }, "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "devOptional": true, "license": "MIT", "engines": { @@ -16168,7 +14179,9 @@ } }, "node_modules/request/node_modules/qs": { - "version": "6.5.3", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz", + "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -16975,16 +14988,20 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.6", + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.7.tgz", + "integrity": "sha512-e0LyK91f3cUxTmv95/KzoLg47+zF+s/sbxRGDNsyG4dmIP8ZSX8ax6byOxfJXeNNtS/8AZlfD+uP7gBeR7DLlg==", "dev": true, "license": "MIT", "dependencies": { "debug": "~4.4.1", - "ws": "~8.18.3" + "ws": "~8.20.1" } }, "node_modules/socket.io-parser": { - "version": "4.2.5", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", "dev": true, "license": "MIT", "dependencies": { @@ -17025,16 +15042,6 @@ "node": ">= 14" } }, - "node_modules/socks/node_modules/ip-address": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.1.tgz", - "integrity": "sha512-1FMu8/N15Ck1BL551Jf42NYIoin2unWjLQ2Fze/DXryJRl5twqtwNHlO39qERGbIOcKYWHdgRryhOC+NG4eaLw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -17507,7 +15514,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", "engines": { "node": ">=12" @@ -17517,7 +15526,9 @@ } }, "node_modules/tmp": { - "version": "0.2.3", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true, "license": "MIT", "engines": { @@ -17937,9 +15948,9 @@ } }, "node_modules/typescript-eslint/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -18022,7 +16033,9 @@ } }, "node_modules/underscore": { - "version": "1.13.7", + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", "dev": true, "license": "MIT" }, @@ -18455,7 +16468,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.3", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "license": "MIT", "engines": { @@ -18509,6 +16524,22 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yargs": { "version": "17.7.2", "dev": true, diff --git a/package.json b/package.json index a382363bcd..5abce61683 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "ngx-lottie": "^11.0.2", "ngx-monaco-editor-v2": "^21", "ngx-skeleton-loader": "^12.0.0", - "npm": "^10.4.0", "nvd3": "1.8.6", "qrcode": "^1.5.4", "rxjs": "~7.8.2", From b46d6070744d98b04c71c43203ec6cee6c0ae228 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 5 Jun 2026 08:52:00 +1000 Subject: [PATCH 1088/1531] refactor: migrate about modal to tailwind --- .../about-doubtfire-modal-content.tpl.html | 62 ++++++--- .../about-doubtfire-modal.scss | 119 ------------------ 2 files changed, 42 insertions(+), 139 deletions(-) diff --git a/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal-content.tpl.html b/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal-content.tpl.html index 08c5fd09bf..8b6732c0ea 100644 --- a/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal-content.tpl.html +++ b/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal-content.tpl.html @@ -1,32 +1,51 @@ -
    - +
    + - + - + - + - + - + - + - + - +
    Name @if (!editing(activityType)) { -
    - {{ activityType.name }} -
    +
    + {{ activityType.name }} +
    } @else { @@ -32,9 +38,9 @@

    Activities

    Abbreviation @if (!editing(activityType)) { -
    - {{ activityType.abbreviation }} -
    +
    + {{ activityType.abbreviation }} +
    } @else { @@ -53,21 +59,34 @@

    Activities

    @if (!editing(activityType)) { -
    - -
    +
    + +
    } @else {
    - - diff --git a/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.ts b/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.ts index 57b765b93c..773f811760 100644 --- a/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.ts +++ b/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.ts @@ -1,19 +1,22 @@ -import {Component, ViewChild} from '@angular/core'; -import {MatTableDataSource, MatTable} from '@angular/material/table'; import {ActivityType, ActivityTypeService} from 'src/app/api/models/doubtfire-model'; import {EntityFormComponent} from 'src/app/common/entity-form/entity-form.component'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {AfterViewInit, Component, ViewChild} from '@angular/core'; import {UntypedFormControl, Validators} from '@angular/forms'; import {MatSort, Sort} from '@angular/material/sort'; -import {AlertService} from 'src/app/common/services/alert.service'; +import {MatTable, MatTableDataSource} from '@angular/material/table'; @Component({ - selector: 'activity-type-list', - templateUrl: 'activity-type-list.component.html', - styleUrls: ['activity-type-list.component.scss'], - standalone: false + selector: 'activity-type-list', + templateUrl: 'activity-type-list.component.html', + styleUrls: ['activity-type-list.component.scss'], + standalone: false, }) -export class ActivityTypeListComponent extends EntityFormComponent { - @ViewChild(MatTable, {static: true}) table: MatTable; +export class ActivityTypeListComponent + extends EntityFormComponent + implements AfterViewInit +{ + @ViewChild(MatTable, {static: true}) table: MatTable; @ViewChild(MatSort, {static: true}) sort: MatSort; // Set up the table @@ -55,7 +58,11 @@ export class ActivityTypeListComponent extends EntityFormComponent // to the datasource private pushToTable(value: ActivityType | ActivityType[]) { if (!value) return; - value instanceof Array ? this.activityTypes.push(...value) : this.activityTypes.push(value); + if (value instanceof Array) { + this.activityTypes.push(...value); + } else { + this.activityTypes.push(value); + } this.dataSource.sort = this.sort; this.table.renderRows(); } diff --git a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html index 1307b8f8f1..5045f1adcf 100644 --- a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html +++ b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html @@ -5,7 +5,14 @@

    Campuses

    Add new campuses or modify existing ones

    - +
    @@ -61,9 +68,9 @@

    Campuses

    Default Sync Mode @for (mode of syncModes; track mode) { - - {{ mode | titlecase }} - + + {{ mode | titlecase }} + } @@ -74,9 +81,9 @@

    Campuses

    Default Sync Mode @for (mode of syncModes; track mode) { - - {{ mode | titlecase }} - + + {{ mode | titlecase }} + } @@ -129,26 +136,36 @@

    Campuses

    @@ -80,9 +84,11 @@

    @@ -91,39 +97,41 @@

    @@ -132,22 +140,23 @@

    diff --git a/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts b/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts index aecdea2434..4cafb185e5 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts +++ b/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts @@ -1,10 +1,16 @@ -import { Component, Inject, Injectable, OnInit, ViewChild } from '@angular/core'; -import { MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material/dialog'; -import { FormControl } from '@angular/forms'; -import { Unit, TeachingPeriod, User, UserService, UnitService } from 'src/app/api/models/doubtfire-model'; -import { MatTable, MatTableDataSource } from '@angular/material/table'; -import { GlobalStateService } from 'src/app/projects/states/index/global-state.service'; -import { Observable, map, startWith } from 'rxjs'; +import {Observable, map, startWith} from 'rxjs'; +import { + TeachingPeriod, + Unit, + UnitService, + User, + UserService, +} from 'src/app/api/models/doubtfire-model'; +import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; +import {Component, Inject, Injectable, OnInit, ViewChild} from '@angular/core'; +import {FormControl} from '@angular/forms'; +import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog'; +import {MatTable, MatTableDataSource} from '@angular/material/table'; export interface TeachingPeriodUnitImportData { teachingPeriod: TeachingPeriod; @@ -15,7 +21,7 @@ interface UnitImportData { unitName?: string; sourceUnit: Unit; convenor: User; - relatedUnits?: { value: Unit; text: string }[]; + relatedUnits?: {value: Unit; text: string}[]; done?: boolean; convenorFormControl: FormControl; filteredStaff: Observable; @@ -27,7 +33,7 @@ export class TeachingPeriodUnitImportService { openImportUnitsDialog(teachingPeriod: TeachingPeriod): void { const dialogRef = this.dialog.open(TeachingPeriodUnitImportDialogComponent, { - data: { teachingPeriod: teachingPeriod }, + data: {teachingPeriod: teachingPeriod}, }); dialogRef.afterClosed().subscribe(() => { @@ -41,13 +47,13 @@ export class TeachingPeriodUnitImportService { * This dialog allows the user to enter a number of units to be rolled over into the a teaching period. */ @Component({ - selector: 'f-teaching-period-unit-import', - templateUrl: 'teaching-period-unit-import.dialog.html', - styleUrls: ['teaching-period-unit-import.dialog.scss'], - standalone: false + selector: 'f-teaching-period-unit-import', + templateUrl: 'teaching-period-unit-import.dialog.html', + styleUrls: ['teaching-period-unit-import.dialog.scss'], + standalone: false, }) export class TeachingPeriodUnitImportDialogComponent implements OnInit { - @ViewChild(MatTable, { static: true }) table: MatTable; + @ViewChild(MatTable, {static: true}) table: MatTable; /** * The list of unit related data for the import. @@ -66,7 +72,14 @@ export class TeachingPeriodUnitImportDialogComponent implements OnInit { */ public codesToAdd: string = ''; - public displayedColumns: string[] = ['unitCode', 'sourceUnit', 'unitName', 'convenor', 'status', 'actions']; + public displayedColumns: string[] = [ + 'unitCode', + 'sourceUnit', + 'unitName', + 'convenor', + 'status', + 'actions', + ]; constructor( public dialogRef: MatDialogRef, @@ -105,8 +118,8 @@ export class TeachingPeriodUnitImportDialogComponent implements OnInit { private loadAllUnits() { // Load all units - this.unitService.query(undefined, { params: { include_in_active: true } }).subscribe({ - next: (success) => { + this.unitService.query(undefined, {params: {include_in_active: true}}).subscribe({ + next: () => { return; }, error: (failure) => { @@ -134,12 +147,12 @@ export class TeachingPeriodUnitImportDialogComponent implements OnInit { value.sourceUnit = value.relatedUnits.length > 0 ? value.relatedUnits[0].value : null; } - public relatedUnits(code: string): { value: Unit; text: string }[] { + public relatedUnits(code: string): {value: Unit; text: string}[] { return this.allUnits .filter((u) => u.code.includes(code) || code.includes(u.code)) .sort((a, b) => b.startDate.valueOf() - a.startDate.valueOf()) .map((u) => { - return { value: u, text: u.codeAndPeriod }; + return {value: u, text: u.codeAndPeriod}; }); } @@ -151,7 +164,8 @@ export class TeachingPeriodUnitImportDialogComponent implements OnInit { if (value.done) return 'Done!'; if (value.done !== undefined && !value.done) return 'Error! - check log'; if (!value.sourceUnit) return 'Create new unit'; - if (this.teachigPeriod.hasUnitLike(value.sourceUnit)) return 'Skip - Already in teaching period'; + if (this.teachigPeriod.hasUnitLike(value.sourceUnit)) + return 'Skip - Already in teaching period'; if (this.unitsToImport.filter((u) => u.unitCode === value.sourceUnit.code).length > 1) { return 'Duplicate - Source unit appears twice'; } @@ -179,7 +193,9 @@ export class TeachingPeriodUnitImportDialogComponent implements OnInit { const relatedUnits = this.relatedUnits(code); const sourceUnit = relatedUnits.length > 0 ? relatedUnits[0].value : null; - const formControl = new FormControl(sourceUnit?.mainConvenor?.user || sourceUnit?.mainConvenorUser); + const formControl: FormControl = new FormControl( + sourceUnit?.mainConvenor?.user || sourceUnit?.mainConvenorUser, + ); this.unitsToImport.push({ unitCode: code, @@ -252,7 +268,7 @@ export class TeachingPeriodUnitImportDialogComponent implements OnInit { }, }) .subscribe({ - next: (newUnit: Unit) => { + next: () => { unitToImport.done = true; this.importUnit(idx + 1); }, diff --git a/src/app/admin/states/units/units.component.html b/src/app/admin/states/units/units.component.html index e718d73431..769db63c2d 100644 --- a/src/app/admin/states/units/units.component.html +++ b/src/app/admin/states/units/units.component.html @@ -1,11 +1,11 @@
    -
    +

    {{ title }}

    - + Search search @@ -13,7 +13,7 @@

    {{ title }}

    Name @if (!editing(campus)) { -
    - - - - -
    + + + + } @else {
    - - diff --git a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts index bbd2a18090..51e8a760d5 100644 --- a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts +++ b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts @@ -1,18 +1,18 @@ -import {Component, ViewChild} from '@angular/core'; -import {MatSort, Sort} from '@angular/material/sort'; -import {MatTableDataSource, MatTable} from '@angular/material/table'; -import {UntypedFormControl, Validators} from '@angular/forms'; import {Campus, CampusService} from 'src/app/api/models/doubtfire-model'; import {EntityFormComponent} from 'src/app/common/entity-form/entity-form.component'; import {AlertService} from 'src/app/common/services/alert.service'; +import {AfterViewInit, Component, ViewChild} from '@angular/core'; +import {UntypedFormControl, Validators} from '@angular/forms'; +import {MatSort, Sort} from '@angular/material/sort'; +import {MatTable, MatTableDataSource} from '@angular/material/table'; @Component({ - selector: 'campus-list', - templateUrl: 'campus-list.component.html', - styleUrls: ['campus-list.component.scss'], - standalone: false + selector: 'campus-list', + templateUrl: 'campus-list.component.html', + styleUrls: ['campus-list.component.scss'], + standalone: false, }) -export class CampusListComponent extends EntityFormComponent { +export class CampusListComponent extends EntityFormComponent implements AfterViewInit { @ViewChild(MatTable, {static: true}) table: MatTable; @ViewChild(MatSort, {static: true}) sort: MatSort; @@ -61,7 +61,11 @@ export class CampusListComponent extends EntityFormComponent { private pushToTable(value: Campus | Campus[]) { if (!value) return; - value instanceof Array ? this.campuses.push(...value) : this.campuses.push(value); + if (value instanceof Array) { + this.campuses.push(...value); + } else { + this.campuses.push(value); + } this.dataSource.sort = this.sort; } diff --git a/src/app/admin/institution-settings/institution-settings.component.html b/src/app/admin/institution-settings/institution-settings.component.html index bb183c747a..3cb3491d22 100644 --- a/src/app/admin/institution-settings/institution-settings.component.html +++ b/src/app/admin/institution-settings/institution-settings.component.html @@ -21,13 +21,14 @@

    Learning Outcomes

    @if (overseerEnabled) { - - - - } @if (tiiEnabled) { - - - + + + + } + @if (tiiEnabled) { + + + } diff --git a/src/app/admin/institution-settings/institution-settings.component.ts b/src/app/admin/institution-settings/institution-settings.component.ts index 0d2ef01806..8de6ae566e 100644 --- a/src/app/admin/institution-settings/institution-settings.component.ts +++ b/src/app/admin/institution-settings/institution-settings.component.ts @@ -1,23 +1,20 @@ -import { Component } from '@angular/core'; -import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Component} from '@angular/core'; @Component({ - selector: 'institution-settings', - templateUrl: 'institution-settings.component.html', - styleUrls: ['institution-settings.component.scss'], - standalone: false + selector: 'institution-settings', + templateUrl: 'institution-settings.component.html', + styleUrls: ['institution-settings.component.scss'], + standalone: false, }) export class InstitutionSettingsComponent { + constructor(private constants: DoubtfireConstants) {} - constructor( - private constants: DoubtfireConstants, - ) { } - - public get overseerEnabled() : boolean { + public get overseerEnabled(): boolean { return this.constants.IsOverseerEnabled.value; } - public get tiiEnabled() : boolean { + public get tiiEnabled(): boolean { return this.constants.IsTiiEnabled.value; } } diff --git a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html index a41c1dd67b..62667efd70 100644 --- a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html +++ b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html @@ -1,5 +1,5 @@ - +
    {{ data.text }}
    @@ -27,14 +27,15 @@

    Name -
    - {{ overseerImage.name }} -
    - + @if (!editing(overseerImage)) { +
    + {{ overseerImage.name }} +
    + } @else { -
    + }
    @@ -47,14 +48,15 @@

    Tag -
    - {{ overseerImage.tag }} -
    - + @if (!editing(overseerImage)) { +
    + {{ overseerImage.tag }} +
    + } @else { -
    + }
    @@ -67,11 +69,13 @@

    -
    - -
    + @if (!editing(overseerImage)) { +
    + +
    + }
    Last Pulled -
    - {{ overseerImage.lastPulledDate | humanizedDate }} -
    + @if (!editing(overseerImage)) { +
    + {{ overseerImage.lastPulledDate | humanizedDate }} +
    + }
    Status -
    - - - -
    + @if (overseerImage.pulledImageStatus === 'success') { + + } + @if (overseerImage.pulledImageStatus === 'loading') { + + } + @if (overseerImage.pulledImageStatus === 'failed') { + + } + + }
    -
    - - - - -
    - + + + + + } @else {
    -
    + }
    diff --git a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts index 2cb839338c..7320f0aac0 100644 --- a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts +++ b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts @@ -1,27 +1,27 @@ +import {OverseerImage, OverseerImageService} from 'src/app/api/models/doubtfire-model'; +import {EntityFormComponent} from 'src/app/common/entity-form/entity-form.component'; +import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; import {HttpClient} from '@angular/common/http'; import {AfterViewInit, Component, TemplateRef, ViewChild} from '@angular/core'; import {UntypedFormControl, Validators} from '@angular/forms'; import {MatDialog} from '@angular/material/dialog'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTable, MatTableDataSource} from '@angular/material/table'; -import {OverseerImage, OverseerImageService} from 'src/app/api/models/doubtfire-model'; -import {EntityFormComponent} from 'src/app/common/entity-form/entity-form.component'; -import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; -import {AlertService} from 'src/app/common/services/alert.service'; @Component({ - selector: 'overseer-image-list', - templateUrl: 'overseer-image-list.component.html', - styleUrls: ['overseer-image-list.component.scss'], - standalone: false + selector: 'overseer-image-list', + templateUrl: 'overseer-image-list.component.html', + styleUrls: ['overseer-image-list.component.scss'], + standalone: false, }) export class OverseerImageListComponent extends EntityFormComponent implements AfterViewInit { - @ViewChild('textDialog') textDialog!: TemplateRef; + @ViewChild('textDialog') textDialog!: TemplateRef; - @ViewChild(MatTable, {static: true}) table: MatTable; + @ViewChild(MatTable, {static: true}) table: MatTable; @ViewChild(MatSort, {static: true}) sort: MatSort; // Set up the table @@ -75,7 +75,11 @@ export class OverseerImageListComponent // to the datasource private pushToTable(value: OverseerImage | OverseerImage[]) { if (!value) return; - value instanceof Array ? this.overseerImages.push(...value) : this.overseerImages.push(value); + if (value instanceof Array) { + this.overseerImages.push(...value); + } else { + this.overseerImages.push(value); + } this.dataSource.sort = this.sort; } @@ -103,7 +107,7 @@ export class OverseerImageListComponent deleteOverseerImage(image: OverseerImage) { this.overseerImageService.delete(image).subscribe( - ((response) => { + ((_response) => { this.cancelEdit(); this.overseerImages.splice(this.overseerImages.indexOf(image), 1); this.dataSource.data = this.overseerImages; diff --git a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.ts b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.ts index 2592fa920c..d735b6f7ca 100644 --- a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.ts +++ b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.ts @@ -1,13 +1,14 @@ -import { Component, OnInit } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; -import { TeachingPeriod } from 'src/app/api/models/teaching-period'; -import { TeachingPeriodService } from 'src/app/api/services/teaching-period.service'; -import { UnitService } from 'src/app/api/services/unit.service'; -import { AlertService } from 'src/app/common/services/alert.service'; +import {TeachingPeriod} from 'src/app/api/models/teaching-period'; +import {TeachingPeriodService} from 'src/app/api/services/teaching-period.service'; +import {UnitService} from 'src/app/api/services/unit.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, OnInit} from '@angular/core'; +import {MatDialogRef} from '@angular/material/dialog'; + @Component({ - selector: 'create-new-unit-modal-content', - templateUrl: 'create-new-unit-modal-content.component.html', - standalone: false + selector: 'create-new-unit-modal-content', + templateUrl: 'create-new-unit-modal-content.component.html', + standalone: false, }) export class CreateNewUnitModalContentComponent implements OnInit { constructor( @@ -28,7 +29,11 @@ export class CreateNewUnitModalContentComponent implements OnInit { }); } - public createUnit(unit: { unitName: string; unitCode: string; selectedTeachingPeriod: number }): void { + public createUnit(unit: { + unitName: string; + unitCode: string; + selectedTeachingPeriod: number; + }): void { let newUnit; if (this.selectedTeachingPeriod === null) { diff --git a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component.html b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component.ts b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component.ts index 2dd7597ce3..6096f86bcc 100644 --- a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component.ts +++ b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component.ts @@ -1,11 +1,11 @@ -import { Component } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { CreateNewUnitModalContentComponent } from './create-new-unit-modal-content.component'; +import {Component} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import {CreateNewUnitModalContentComponent} from './create-new-unit-modal-content.component'; @Component({ - selector: 'create-new-unit-modal', - template: '', - standalone: false + selector: 'create-new-unit-modal', + templateUrl: './create-new-unit-modal.component.html', + standalone: false, }) export class CreateNewUnitModal { constructor(public dialog: MatDialog) {} diff --git a/src/app/admin/states/teaching-periods/teaching-period-list/new-teaching-period-dialog.component.html b/src/app/admin/states/teaching-periods/teaching-period-list/new-teaching-period-dialog.component.html index 58049818e9..b8ae10c207 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-list/new-teaching-period-dialog.component.html +++ b/src/app/admin/states/teaching-periods/teaching-period-list/new-teaching-period-dialog.component.html @@ -1,6 +1,8 @@ -
    +
    - + + @@ -9,7 +11,7 @@ --> -
    +
    - + Teaching Period Name - + Teaching Period Year - + @@ -71,22 +85,22 @@

    Teaching Breaks for {{ newOrSelectedTeachingPeriod.name }}

    @for (break of newOrSelectedTeachingPeriod.breaksCache.values | async; track break) { - - - - {{ break.startDate | date }} - {{ break.numberOfWeeks }} week(s) + + + + {{ break.startDate | date }} + {{ break.numberOfWeeks }} week(s) + + + - - - - + } - + Break Start Date @@ -105,7 +119,13 @@

    Teaching Breaks for {{ newOrSelectedTeachingPeriod.name }}

    Number of weeks - +
    Unit Code - +
    boolean; matchesGroup?: (filter: string) => boolean; matches: (filter: string) => boolean; -}; +} @Component({ - selector: 'f-units', - templateUrl: './units.component.html', - styleUrls: ['./units.component.scss'], - standalone: false + selector: 'f-units', + templateUrl: './units.component.html', + styleUrls: ['./units.component.scss'], + standalone: false, }) export class FUnitsComponent implements OnInit, AfterViewInit { @ViewChild(MatTable, {static: false}) table: MatTable; @@ -88,7 +88,7 @@ export class FUnitsComponent implements OnInit, AfterViewInit { this.globalStateService.onLoad(() => { this.unitService.query(undefined, {params: {include_in_active: true}}).subscribe({ - next: (units) => { + next: () => { this.globalStateService.loadedUnits.values.subscribe( (loadedUnits) => (this.dataSource.data = this.mapUnitOrProjectsToColumns(loadedUnits)), diff --git a/src/app/admin/states/users/users.component.ts b/src/app/admin/states/users/users.component.ts index ccc747653c..03aa2d7af4 100644 --- a/src/app/admin/states/users/users.component.ts +++ b/src/app/admin/states/users/users.component.ts @@ -1,27 +1,34 @@ -import { Component, AfterViewInit, ViewChild, OnDestroy, OnInit } from '@angular/core'; -import { MatTable, MatTableDataSource } from '@angular/material/table'; -import { MatSort, Sort } from '@angular/material/sort'; -import { User } from 'src/app/api/models/doubtfire-model'; -import { MatPaginator } from '@angular/material/paginator'; -import { UserService } from 'src/app/api/models/doubtfire-model'; -import { EditProfileDialogService } from 'src/app/common/modals/edit-profile-dialog/edit-profile-dialog.service'; -import { Subscription } from 'rxjs'; -import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; -import { FileDownloaderService } from 'src/app/common/file-downloader/file-downloader.service'; -import { AlertService } from 'src/app/common/services/alert.service'; +import {Subscription} from 'rxjs'; +import {User} from 'src/app/api/models/doubtfire-model'; +import {UserService} from 'src/app/api/models/doubtfire-model'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {EditProfileDialogService} from 'src/app/common/modals/edit-profile-dialog/edit-profile-dialog.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {AfterViewInit, Component, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import {MatPaginator} from '@angular/material/paginator'; +import {MatSort, Sort} from '@angular/material/sort'; +import {MatTable, MatTableDataSource} from '@angular/material/table'; @Component({ - selector: 'f-users', - templateUrl: './users.component.html', - styleUrls: ['./users.component.scss'], - standalone: false + selector: 'f-users', + templateUrl: './users.component.html', + styleUrls: ['./users.component.scss'], + standalone: false, }) export class FUsersComponent implements OnInit, AfterViewInit, OnDestroy { - @ViewChild(MatTable, { static: false }) table: MatTable; - @ViewChild(MatSort, { static: false }) sort: MatSort; - @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator; - - displayedColumns: string[] = ['avatar', 'firstName', 'lastName', 'username', 'email', 'systemRole']; + @ViewChild(MatTable, {static: false}) table: MatTable; + @ViewChild(MatSort, {static: false}) sort: MatSort; + @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; + + displayedColumns: string[] = [ + 'avatar', + 'firstName', + 'lastName', + 'username', + 'email', + 'systemRole', + ]; public dataSource: MatTableDataSource; public filter: string; dataload: boolean; @@ -88,7 +95,9 @@ export class FUsersComponent implements OnInit, AfterViewInit, OnDestroy { error_string += error.message + '\n'; }); - max_full_errors > num_errors ? (error_string += `... and ${max_full_errors - num_errors} more`) : null; + if (num_errors > max_full_errors) { + error_string += `... and ${num_errors - max_full_errors} more`; + } this.alerts.error(error_string); this.userService.query(); diff --git a/src/app/admin/tii-action-log/tii-action-log.component.html b/src/app/admin/tii-action-log/tii-action-log.component.html index c12c822525..9d1e9d85d3 100644 --- a/src/app/admin/tii-action-log/tii-action-log.component.html +++ b/src/app/admin/tii-action-log/tii-action-log.component.html @@ -1,16 +1,21 @@
    -
    +

    Turnitin Actions

    - +
    Turnitin Actions diff --git a/src/app/admin/tii-action-log/tii-action-log.component.spec.ts b/src/app/admin/tii-action-log/tii-action-log.component.spec.ts index a3caf79062..38e5d9ec65 100644 --- a/src/app/admin/tii-action-log/tii-action-log.component.spec.ts +++ b/src/app/admin/tii-action-log/tii-action-log.component.spec.ts @@ -1,6 +1,5 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { TiiActionLogComponent } from './tii-action-log.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {TiiActionLogComponent} from './tii-action-log.component'; describe('TiiActionLogComponent', () => { let component: TiiActionLogComponent; @@ -8,7 +7,7 @@ describe('TiiActionLogComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - declarations: [TiiActionLogComponent] + declarations: [TiiActionLogComponent], }); fixture = TestBed.createComponent(TiiActionLogComponent); component = fixture.componentInstance; diff --git a/src/app/admin/tii-action-log/tii-action-log.component.ts b/src/app/admin/tii-action-log/tii-action-log.component.ts index 8d1771cce4..d53d488d47 100644 --- a/src/app/admin/tii-action-log/tii-action-log.component.ts +++ b/src/app/admin/tii-action-log/tii-action-log.component.ts @@ -1,29 +1,37 @@ -import { AfterViewInit, Component, ViewChild } from '@angular/core'; -import { MatPaginator } from '@angular/material/paginator'; -import { MatSort, Sort } from '@angular/material/sort'; -import { MatTable, MatTableDataSource } from '@angular/material/table'; -import { TiiAction } from 'src/app/api/models/doubtfire-model'; -import { TiiActionService } from 'src/app/api/services/tii-action.service'; -import { AlertService } from 'src/app/common/services/alert.service'; +import {TiiAction} from 'src/app/api/models/doubtfire-model'; +import {TiiActionService} from 'src/app/api/services/tii-action.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {AfterViewInit, Component, ViewChild} from '@angular/core'; +import {MatPaginator} from '@angular/material/paginator'; +import {MatSort, Sort} from '@angular/material/sort'; +import {MatTable, MatTableDataSource} from '@angular/material/table'; @Component({ - selector: 'f-tii-action-log', - templateUrl: './tii-action-log.component.html', - styleUrls: ['./tii-action-log.component.scss'], - standalone: false + selector: 'f-tii-action-log', + templateUrl: './tii-action-log.component.html', + styleUrls: ['./tii-action-log.component.scss'], + standalone: false, }) export class TiiActionLogComponent implements AfterViewInit { - @ViewChild(MatTable, { static: false }) table: MatTable; - @ViewChild(MatSort, { static: false }) sort: MatSort; - @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator; + @ViewChild(MatTable, {static: false}) table: MatTable; + @ViewChild(MatSort, {static: false}) sort: MatSort; + @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; public tiiActionsSource: MatTableDataSource; - public columns: string[] = ['type', 'lastRun', 'retries', 'retry', 'errorMessage', 'tiiActionTools']; //, 'complete', 'retries', 'lastRun', 'errorCode', 'log', 'tiiActionAction']; + public columns: string[] = [ + 'type', + 'lastRun', + 'retries', + 'retry', + 'errorMessage', + 'tiiActionTools', + ]; //, 'complete', 'retries', 'lastRun', 'errorCode', 'log', 'tiiActionAction']; public filter: string; - constructor(private tiiActionService: TiiActionService, private alertService: AlertService) { - - } + constructor( + private tiiActionService: TiiActionService, + private alertService: AlertService, + ) {} ngAfterViewInit(): void { this.tiiActionService.query().subscribe((actions) => { @@ -31,8 +39,10 @@ export class TiiActionLogComponent implements AfterViewInit { this.tiiActionsSource = new MatTableDataSource(actions); this.tiiActionsSource.paginator = this.paginator; this.tiiActionsSource.sort = this.sort; - this.tiiActionsSource.filterPredicate = (data: any, filter: string) => data.matches(filter); - + this.tiiActionsSource.filterPredicate = ( + data: TiiAction & {matches(filter: string): boolean}, + filter: string, + ) => data.matches(filter); }); } @@ -68,20 +78,20 @@ export class TiiActionLogComponent implements AfterViewInit { } public retryAction(action: TiiAction) { - this.tiiActionService.put(action, { - body: { - action: 'retry' - } - }).subscribe({ - next: (updatedAction) => { - action.retry = true; - this.alertService.success('Action has been queued for retry'); - }, - error: (error) => { - this.alertService.error('Failed to queue action for retry'); - } - }); + this.tiiActionService + .put(action, { + body: { + action: 'retry', + }, + }) + .subscribe({ + next: () => { + action.retry = true; + this.alertService.success('Action has been queued for retry'); + }, + error: (error) => { + this.alertService.error(`Failed to queue action for retry: ${error}`); + }, + }); } - - } diff --git a/src/app/api/models/d2l/d2l_assessment_mapping.service.ts b/src/app/api/models/d2l/d2l_assessment_mapping.service.ts index 3f2fe47087..afd5318aca 100644 --- a/src/app/api/models/d2l/d2l_assessment_mapping.service.ts +++ b/src/app/api/models/d2l/d2l_assessment_mapping.service.ts @@ -1,9 +1,9 @@ -import {Injectable} from '@angular/core'; import {EntityService} from 'ngx-entity-service'; import API_URL from 'src/app/config/constants/apiUrl'; import {HttpClient} from '@angular/common/http'; -import {D2lAssessmentMapping} from './d2l_assessment_mapping'; +import {Injectable} from '@angular/core'; import {Unit} from '../doubtfire-model'; +import {D2lAssessmentMapping} from './d2l_assessment_mapping'; @Injectable() export class D2lAssessmentMappingService extends EntityService { diff --git a/src/app/api/models/discussion-prompt.ts b/src/app/api/models/discussion-prompt.ts index e984847084..2f9d7605c5 100644 --- a/src/app/api/models/discussion-prompt.ts +++ b/src/app/api/models/discussion-prompt.ts @@ -51,8 +51,9 @@ export class DiscussionPrompt extends Entity { next: (_response: object) => { AppInjector.get(AlertService).success('Successfully deleted discussion note', 4000); }, - error: (error: any) => { - AppInjector.get(AlertService).error(error?.message || error || 'Unknown error', 2000); + error: (error: Error) => { + const message = error.message || 'Unknown error'; + AppInjector.get(AlertService).error(message, 2000); }, }); } diff --git a/src/app/api/models/feedback-template.ts b/src/app/api/models/feedback-template.ts index 1634cb70d6..0df083f96d 100644 --- a/src/app/api/models/feedback-template.ts +++ b/src/app/api/models/feedback-template.ts @@ -61,7 +61,7 @@ export class FeedbackTemplate extends Entity { return !this.id; } - public delete(): Observable { + public delete(): Observable { const svc = AppInjector.get(FeedbackTemplateService); return svc.delete( diff --git a/src/app/api/models/grade.ts b/src/app/api/models/grade.ts index e139dee8fb..7506f647cd 100644 --- a/src/app/api/models/grade.ts +++ b/src/app/api/models/grade.ts @@ -2,7 +2,10 @@ export class Grade { public static readonly PASS_RANGE: number[] = [0, 1, 2, 3]; public static readonly FULL_RANGE: number[] = [-1, 0, 1, 2, 3]; - public static readonly GRADE_ACRONYMS: Map = new Map([ + public static readonly GRADE_ACRONYMS: Map = new Map< + string | number, + string + >([ ['Fail', 'F'], ['Pass', 'P'], ['Credit', 'C'], diff --git a/src/app/api/models/groups/group-set.ts b/src/app/api/models/groups/group-set.ts index cb99f99e44..5e15231ee1 100644 --- a/src/app/api/models/groups/group-set.ts +++ b/src/app/api/models/groups/group-set.ts @@ -1,7 +1,7 @@ import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; import {AppInjector} from 'src/app/app-injector'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; -import {Group, Unit, User} from '../doubtfire-model'; +import {Group, Unit} from '../doubtfire-model'; export class GroupSet extends Entity { public id: number; diff --git a/src/app/api/models/groups/group.ts b/src/app/api/models/groups/group.ts index 6a55b2d716..e2202df690 100644 --- a/src/app/api/models/groups/group.ts +++ b/src/app/api/models/groups/group.ts @@ -1,10 +1,10 @@ -import {HttpClient} from '@angular/common/http'; import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; import {Observable, tap} from 'rxjs'; import {AppInjector} from 'src/app/app-injector'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; -import {Unit, GroupSet, Project, Tutorial, ProjectService} from '../doubtfire-model'; import {AlertService} from 'src/app/common/services/alert.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {HttpClient} from '@angular/common/http'; +import {GroupSet, Project, ProjectService, Tutorial, Unit} from '../doubtfire-model'; export interface MemberContribution { project: Project; @@ -86,7 +86,7 @@ export class Group extends Entity { httpClient .post(`${AppInjector.get(DoubtfireConstants).API_URL}/${this.memberUri(member)}`, {}) .subscribe({ - next: (success) => { + next: () => { // Get old group.. const grp = member.groupForGroupSet(this.groupSet); if (grp) { @@ -119,7 +119,7 @@ export class Group extends Entity { httpClient .delete(`${AppInjector.get(DoubtfireConstants).API_URL}/${this.memberUri(member)}`, {}) .subscribe({ - next: (success) => { + next: () => { // Get old group.. this.projectsCache.delete(member); member.groupCache.delete(this); diff --git a/src/app/api/models/learning-outcome.ts b/src/app/api/models/learning-outcome.ts index dfdc55fa19..211c3931d1 100644 --- a/src/app/api/models/learning-outcome.ts +++ b/src/app/api/models/learning-outcome.ts @@ -1,8 +1,8 @@ import {Entity, EntityMapping} from 'ngx-entity-service'; import {Observable, tap} from 'rxjs'; import {AppInjector} from 'src/app/app-injector'; -import {LearningOutcomeService, TaskDefinition, Unit} from './doubtfire-model'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {LearningOutcomeService, TaskDefinition, Unit} from './doubtfire-model'; export class LearningOutcome extends Entity { id: number; @@ -121,7 +121,7 @@ export class LearningOutcome extends Entity { return !this.id; } - public delete(): Observable { + public delete(): Observable { const svc = AppInjector.get(LearningOutcomeService); if (this.context) { diff --git a/src/app/api/models/overseer/overseer-assessment.ts b/src/app/api/models/overseer/overseer-assessment.ts index a41bcbb5d2..f658c57986 100644 --- a/src/app/api/models/overseer/overseer-assessment.ts +++ b/src/app/api/models/overseer/overseer-assessment.ts @@ -9,7 +9,7 @@ export class OverseerAssessment extends Entity { // overseerStepId: number; timestamp: Date; timestampString: string; - content?: [{label: string; result: string}]; + content?: {label: string; result: string}[]; task?: Task; taskStatus?: string; submissionStatus?: 'queued' | 'executing' | 'passed' | 'failed' | 'error'; diff --git a/src/app/api/models/overseer/overseer-image.ts b/src/app/api/models/overseer/overseer-image.ts index 2f6627d3be..aef5b416bb 100644 --- a/src/app/api/models/overseer/overseer-image.ts +++ b/src/app/api/models/overseer/overseer-image.ts @@ -1,4 +1,3 @@ -import {StringNullableChain} from 'lodash'; import {Entity, EntityMapping} from 'ngx-entity-service'; export class OverseerImage extends Entity { diff --git a/src/app/api/models/overseer/overseer-step-result.ts b/src/app/api/models/overseer/overseer-step-result.ts index 2a44371825..ebba556c69 100644 --- a/src/app/api/models/overseer/overseer-step-result.ts +++ b/src/app/api/models/overseer/overseer-step-result.ts @@ -18,7 +18,7 @@ export class OverseerStepResult extends Entity { expectedOutputSha256: string; feedbackMessage: string; - constructor(oa?: OverseerAssessment, os?: OverseerStep) { + constructor(oa?: OverseerAssessment, _os?: OverseerStep) { super(); this.overseerAssessment = oa; // this.overseerStep = os; diff --git a/src/app/api/models/overseer/overseer-step.ts b/src/app/api/models/overseer/overseer-step.ts index 6fa14bf1bf..7ed380fee7 100644 --- a/src/app/api/models/overseer/overseer-step.ts +++ b/src/app/api/models/overseer/overseer-step.ts @@ -1,9 +1,9 @@ import {Entity, EntityMapping} from 'ngx-entity-service'; -import {TaskDefinition} from '../task-definition'; -import {TaskStatus, TaskStatusEnum} from '../task-status'; -import {OverseerStepService} from '../../services/overseer-step.service'; import {AppInjector} from 'src/app/app-injector'; import {AlertService} from 'src/app/common/services/alert.service'; +import {OverseerStepService} from '../../services/overseer-step.service'; +import {TaskDefinition} from '../task-definition'; +import {TaskStatusEnum} from '../task-status'; export class OverseerStep extends Entity { id: number; diff --git a/src/app/api/models/project.ts b/src/app/api/models/project.ts index f833fd3383..3cf3e7a3b0 100644 --- a/src/app/api/models/project.ts +++ b/src/app/api/models/project.ts @@ -1,9 +1,9 @@ -import {HttpClient} from '@angular/common/http'; import {Entity, EntityCache, RequestOptions} from 'ngx-entity-service'; import {Observable, tap} from 'rxjs'; import {AppInjector} from 'src/app/app-injector'; import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {HttpClient} from '@angular/common/http'; import {MappingFunctions} from '../services/mapping-fn'; import { Campus, @@ -284,7 +284,7 @@ export class Project extends Entity { return httpClient.delete(this.portfolioUrl(false)); } - public deleteFileFromPortfolio(file: {idx: any; kind: any; name: any}) { + public deleteFileFromPortfolio(file: {idx: number; kind: string; name: string}) { const httpClient = AppInjector.get(HttpClient); return httpClient .delete( @@ -331,7 +331,7 @@ export class Project extends Entity { cache: this.unit.studentCache, }; - projectService.get(this, options).subscribe((response) => { + projectService.get(this, options).subscribe(() => { // Legacy AngularJS visualisation refresh hook removed with upgraded providers. // (AppInjector.get(visualisations) as any).refreshAll(); }); @@ -423,7 +423,7 @@ export class Project extends Entity { // get total value of all tasks assigned to this project const total = targetTasks .map((td) => td.weighting) - .reduce((prev, current, idx, array) => prev + current, 0); + .reduce((prev, current, _idx, _array) => prev + current, 0); // exit if no tasks or no weights if (targetTasks.length === 0 || total === 0) { @@ -438,7 +438,7 @@ export class Project extends Entity { task.status, ), ); - let lastTargetDate: Date; + // let lastTargetDate: Date; const completedTasks = tasks.filter((task) => task.status === 'complete'); @@ -452,11 +452,11 @@ export class Project extends Entity { // last done task date) if (readyOrCompleteTasks.length === 0) { - lastTargetDate = this.unit.startDate; + // lastTargetDate = this.unit.startDate; } else { - lastTargetDate = readyOrCompleteTasks - .sort((a, b) => a.dueDate.getTime() - b.dueDate.getTime()) - .splice(-1)[0].dueDate; + // lastTargetDate = readyOrCompleteTasks + // .sort((a, b) => a.dueDate.getTime() - b.dueDate.getTime()) + // .splice(-1)[0].dueDate; } // today is used to determine when to stop adding done tasks @@ -470,7 +470,7 @@ export class Project extends Entity { if (weeksElapsed > 0) { const completedTasksWeight = readyOrCompleteTasks .map((t) => t.definition.weighting) - .reduce((prev, current, idx, arr) => prev + current, 0); + .reduce((prev, current, _idx, _arr) => prev + current, 0); completionRate = completedTasksWeight / weeksElapsed; } } diff --git a/src/app/api/models/scorm-datamodel.ts b/src/app/api/models/scorm-datamodel.ts index 0fdc2d3a06..b967e24c83 100644 --- a/src/app/api/models/scorm-datamodel.ts +++ b/src/app/api/models/scorm-datamodel.ts @@ -1,5 +1,5 @@ export class ScormDataModel { - dataModel: {[key: string]: any} = {}; + dataModel: Record = {}; readonly msgPrefix = 'SCORM DataModel: '; constructor() { @@ -8,19 +8,19 @@ export class ScormDataModel { public restore(dataModel: string) { // console.log(this.msgPrefix + 'restoring DataModel with provided data'); - this.dataModel = JSON.parse(dataModel); + this.dataModel = JSON.parse(dataModel) as Record; } public get(key: string): string { // console.log(`SCORM DataModel: get ${key} ${this.dataModel[key]}`); - return this.dataModel[key] ?? ''; + return String(this.dataModel[key] ?? ''); } - public dump(): {[key: string]: any} { + public dump(): Record { return this.dataModel; } - public set(key: string, value: any): string { + public set(key: string, value: string): string { // console.log(this.msgPrefix + 'set: ', key, value); this.dataModel[key] = value; if (key.match('cmi.interactions.\\d+.id')) { @@ -28,7 +28,8 @@ export class ScormDataModel { const interactionPath = key.match('cmi.interactions.\\d+'); const objectivesCounterForInteraction = interactionPath.toString() + '.objectives._count'; // console.log('Incrementing cmi.interactions._count'); - this.dataModel['cmi.interactions._count']++; + this.dataModel['cmi.interactions._count'] = + Number(this.dataModel['cmi.interactions._count'] ?? 0) + 1; // cmi.interactions.n.objectives._count must be initialized after an interaction is created // console.log(`Initializing ${objectivesCounterForInteraction}`); this.dataModel[objectivesCounterForInteraction] = 0; @@ -38,12 +39,14 @@ export class ScormDataModel { const objectivesCounterForInteraction = interactionPath.toString() + '._count'; // cmi.interactions.n.objectives._count must be incremented after objective creation // console.log(`Incrementing ${objectivesCounterForInteraction}`); - this.dataModel[objectivesCounterForInteraction.toString()]++; + this.dataModel[objectivesCounterForInteraction.toString()] = + Number(this.dataModel[objectivesCounterForInteraction.toString()] ?? 0) + 1; } if (key.match('cmi.objectives.\\d+.id')) { // cmi.objectives._count must be incremented after a new objective is created // console.log('Incrementing cmi.objectives._count'); - this.dataModel['cmi.objectives._count']++; + this.dataModel['cmi.objectives._count'] = + Number(this.dataModel['cmi.objectives._count'] ?? 0) + 1; } return 'true'; } diff --git a/src/app/api/models/staff-note.ts b/src/app/api/models/staff-note.ts index bcd1b00e34..ab3ab60a8a 100644 --- a/src/app/api/models/staff-note.ts +++ b/src/app/api/models/staff-note.ts @@ -1,8 +1,8 @@ import {Entity} from 'ngx-entity-service'; -import {Project, Unit, User, UserService} from './doubtfire-model'; import {AppInjector} from 'src/app/app-injector'; import {AlertService} from 'src/app/common/services/alert.service'; import {StaffNoteService} from '../services/staff-note.service'; +import {Project, User, UserService} from './doubtfire-model'; export class StaffNote extends Entity { id: number; @@ -41,13 +41,14 @@ export class StaffNote extends Entity { staffNoteService .delete({projectId: this.project.id, id: this.id}, {cache: this.project.staffNoteCache}) .subscribe({ - next: (response: object) => { + next: () => { AppInjector.get(AlertService).error('Successfully deleted staff note', 4000); this.project.staffNoteCount--; staffNoteService.updateStaffNoteReplies(this.project.staffNoteCache.currentValues); }, - error: (error: any) => { - AppInjector.get(AlertService).error(error?.message || error || 'Unknown error', 2000); + error: (error: Error) => { + const message = error.message || 'Unknown error'; + AppInjector.get(AlertService).error(message, 2000); }, }); } diff --git a/src/app/api/models/task-comment/discussion-comment.ts b/src/app/api/models/task-comment/discussion-comment.ts index 97bb24ee7e..c69968f2b7 100644 --- a/src/app/api/models/task-comment/discussion-comment.ts +++ b/src/app/api/models/task-comment/discussion-comment.ts @@ -1,6 +1,6 @@ -import { AppInjector } from 'src/app/app-injector'; -import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; -import { Task, TaskComment } from '../doubtfire-model' +import {AppInjector} from 'src/app/app-injector'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Task, TaskComment} from '../doubtfire-model'; /** * Create a Discussion Comment, extending the base TaskComment class diff --git a/src/app/api/models/task-comment/extension-comment.ts b/src/app/api/models/task-comment/extension-comment.ts index 443bb34200..8c07459d31 100644 --- a/src/app/api/models/task-comment/extension-comment.ts +++ b/src/app/api/models/task-comment/extension-comment.ts @@ -1,8 +1,8 @@ -import { Observable } from 'rxjs'; -import { tap } from 'rxjs/operators'; -import { AppInjector } from 'src/app/app-injector'; -import { TaskCommentService } from '../../services/task-comment.service'; -import { TaskComment, TaskStatusEnum, Task } from '../doubtfire-model'; +import {Observable} from 'rxjs'; +import {AppInjector} from 'src/app/app-injector'; +import {tap} from 'rxjs/operators'; +import {TaskCommentService} from '../../services/task-comment.service'; +import {Task, TaskComment, TaskStatusEnum} from '../doubtfire-model'; /** * Create a Discussion Comment, extending the base TaskComment class @@ -46,7 +46,7 @@ export class ExtensionComment extends TaskComment { tc.project.updateBurndownChart(); tc.project.calcTopTasks(); // Sort the task list again - }) + }), ); } diff --git a/src/app/api/models/task-comment/scorm-extension-comment.ts b/src/app/api/models/task-comment/scorm-extension-comment.ts index b8aac7909b..d5c6f19168 100644 --- a/src/app/api/models/task-comment/scorm-extension-comment.ts +++ b/src/app/api/models/task-comment/scorm-extension-comment.ts @@ -1,8 +1,8 @@ import {Observable} from 'rxjs'; -import {tap} from 'rxjs/operators'; import {AppInjector} from 'src/app/app-injector'; +import {tap} from 'rxjs/operators'; import {TaskCommentService} from '../../services/task-comment.service'; -import {TaskComment, Task} from '../doubtfire-model'; +import {Task, TaskComment} from '../doubtfire-model'; export class ScormExtensionComment extends TaskComment { assessed: boolean; diff --git a/src/app/api/models/task-comment/task-comment.ts b/src/app/api/models/task-comment/task-comment.ts index fad8869f9a..d1c74abd86 100644 --- a/src/app/api/models/task-comment/task-comment.ts +++ b/src/app/api/models/task-comment/task-comment.ts @@ -1,10 +1,9 @@ -import {AppInjector} from 'src/app/app-injector'; import {Entity} from 'ngx-entity-service'; import {Project, Task, TaskCommentService, User} from 'src/app/api/models/doubtfire-model'; -import {UserService} from '../../services/user.service'; -import API_URL from 'src/app/config/constants/apiUrl'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {AppInjector} from 'src/app/app-injector'; import {AlertService} from 'src/app/common/services/alert.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {UserService} from '../../services/user.service'; export class TaskComment extends Entity { private static readonly EDIT_WINDOW_MS = 10 * 60 * 1000; @@ -46,12 +45,12 @@ export class TaskComment extends Entity { } public get authorIsMe(): boolean { - const userService: any = AppInjector.get(UserService); + const userService: UserService = AppInjector.get(UserService); return this.author.id === userService.currentUser.id; } public get recipientIsMe(): boolean { - const userService: any = AppInjector.get(UserService); + const userService: UserService = AppInjector.get(UserService); return this.recipient.id === userService.currentUser.id; } @@ -102,12 +101,13 @@ export class TaskComment extends Entity { {cache: this.task.commentCache}, ) .subscribe({ - next: (response: object) => { + next: (_response: object) => { // this.task.comments = this.task.comments.filter((e: TaskComment) => e.id !== this.id); this.task.refreshCommentData(); }, - error: (error: any) => { - AppInjector.get(AlertService).error(error?.message || error || 'Unknown error', 2000); + error: (error: Error) => { + const message = error.message || 'Unknown error'; + AppInjector.get(AlertService).error(message, 2000); }, }); } diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index cd5ede1e4b..f9f575fc6d 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -1,15 +1,15 @@ -import {HttpClient} from '@angular/common/http'; import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; import {Observable, tap} from 'rxjs'; import {AppInjector} from 'src/app/app-injector'; import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {HttpClient} from '@angular/common/http'; import {TaskDefinitionService} from '../services/task-definition.service'; +import {DiscussionPrompt} from './discussion-prompt'; import {Grade, GroupSet, LearningOutcome, Project, TutorialStream, Unit} from './doubtfire-model'; import {Task} from './doubtfire-model'; -import {TaskPrerequisite} from './task-prerequisite'; -import {DiscussionPrompt} from './discussion-prompt'; import {OverseerStep} from './overseer/overseer-step'; +import {TaskPrerequisite} from './task-prerequisite'; export interface UploadRequirement { key: string; @@ -307,27 +307,31 @@ export class TaskDefinition extends Entity { return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.unit.id}/task_definitions/${this.id}/jplag_report`; } - public deleteTaskSheet(): Observable { + public deleteTaskSheet(): Observable { const httpClient = AppInjector.get(HttpClient); - return httpClient.delete(this.taskSheetUploadUrl).pipe(tap(() => (this.hasTaskSheet = false))); + return httpClient + .delete(this.taskSheetUploadUrl) + .pipe(tap(() => (this.hasTaskSheet = false))); } - public deleteTaskResources(): Observable { + public deleteTaskResources(): Observable { const httpClient = AppInjector.get(HttpClient); return httpClient - .delete(this.taskResourcesUploadUrl) + .delete(this.taskResourcesUploadUrl) .pipe(tap(() => (this.hasTaskResources = false))); } - public deleteScormData(): Observable { + public deleteScormData(): Observable { const httpClient = AppInjector.get(HttpClient); - return httpClient.delete(this.scormDataUploadUrl).pipe(tap(() => (this.hasScormData = false))); + return httpClient + .delete(this.scormDataUploadUrl) + .pipe(tap(() => (this.hasScormData = false))); } - public deleteOverseerResources(): Observable { + public deleteOverseerResources(): Observable { const httpClient = AppInjector.get(HttpClient); return httpClient - .delete(this.taskOverseerResourcesUploadUrl) + .delete(this.taskOverseerResourcesUploadUrl) .pipe(tap(() => (this.hasTaskAssessmentResources = false))); } diff --git a/src/app/api/models/task-outcome-alignment.ts b/src/app/api/models/task-outcome-alignment.ts index 8569ae5549..0fcf222056 100644 --- a/src/app/api/models/task-outcome-alignment.ts +++ b/src/app/api/models/task-outcome-alignment.ts @@ -1,5 +1,5 @@ import {Entity} from 'ngx-entity-service'; -import {Project, Unit, TaskDefinition, Task} from './doubtfire-model'; +import {Project, Task, TaskDefinition, Unit} from './doubtfire-model'; import {LearningOutcome} from './learning-outcome'; export class TaskOutcomeAlignment extends Entity { diff --git a/src/app/api/models/task-prerequisite.ts b/src/app/api/models/task-prerequisite.ts index 9645adfe5b..4e26df0917 100644 --- a/src/app/api/models/task-prerequisite.ts +++ b/src/app/api/models/task-prerequisite.ts @@ -5,6 +5,12 @@ import {AlertService} from 'src/app/common/services/alert.service'; import {TaskPrerequisiteService} from '../services/task-prerequisite.service'; import {Project, TaskDefinition, TaskStatus, TaskStatusEnum} from './doubtfire-model'; +export interface TaskPrerequisiteData { + taskDefinitionId: number; + prerequisiteId: number; + taskStatus: TaskStatusEnum; +} + export class TaskPrerequisite extends Entity { id: number; @@ -28,7 +34,7 @@ export class TaskPrerequisite extends Entity { complete: 3, }; - constructor(json: any) { + constructor(json: TaskPrerequisiteData) { super(); this.taskDefinitionId = json.taskDefinitionId; this.prerequisiteId = json.prerequisiteId; @@ -61,12 +67,12 @@ export class TaskPrerequisite extends Entity { return false; } - public delete(): Observable { + public delete(): Observable { const taskPrerequisiteService: TaskPrerequisiteService = AppInjector.get(TaskPrerequisiteService); return taskPrerequisiteService - .delete( + .delete( { unitId: this.taskDefinition.unit.id, taskDefId: this.taskDefinitionId, diff --git a/src/app/api/models/task-similarity.ts b/src/app/api/models/task-similarity.ts index cb9640966c..c18a012d36 100644 --- a/src/app/api/models/task-similarity.ts +++ b/src/app/api/models/task-similarity.ts @@ -1,8 +1,8 @@ import {Entity} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; import {AppInjector} from 'src/app/app-injector'; -import {Task, TaskSimilarityService, User} from './doubtfire-model'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; -import {Observable} from 'rxjs'; +import {Task, TaskSimilarityService, User} from './doubtfire-model'; export enum TaskSimilarityType { Jplag = 'JplagTaskSimilarity', diff --git a/src/app/api/models/task-status.ts b/src/app/api/models/task-status.ts index 816d016ba5..d2894a4478 100644 --- a/src/app/api/models/task-status.ts +++ b/src/app/api/models/task-status.ts @@ -204,7 +204,7 @@ export class TaskStatus { ['attention_required', ['ready_for_feedback', 'not_started', 'working_on_it', 'need_help']], ]); - public static readonly STATUS_LABELS = new Map([ + public static readonly STATUS_LABELS: Map = new Map([ ['ready_for_feedback', 'Awaiting Feedback'], ['not_started', 'Not Started'], ['working_on_it', 'Working On It'], @@ -221,7 +221,7 @@ export class TaskStatus { ['attention_required', 'Attention Required'], ]); - public static readonly STATUS_NAME_TO_KEY = new Map([ + public static readonly STATUS_NAME_TO_KEY: Map = new Map([ ['Ready for Feedback', 'ready_for_feedback'], ['Awaiting Feedback', 'ready_for_feedback'], ['Not Started', 'not_started'], @@ -237,7 +237,7 @@ export class TaskStatus { ['Time Exceeded', 'time_exceeded'], ]); - public static readonly STATUS_ICONS = new Map([ + public static readonly STATUS_ICONS: Map = new Map([ ['ready_for_feedback', 'thumb_up'], ['not_started', 'pause'], ['working_on_it', 'bolt'], @@ -255,7 +255,7 @@ export class TaskStatus { ]); // Material icons used by newer UI elements. - public static readonly STATUS_MATERIAL_ICONS = new Map([ + public static readonly STATUS_MATERIAL_ICONS: Map = new Map([ ['ready_for_feedback', 'thumb_up_off_alt'], ['not_started', 'pause'], ['working_on_it', 'bolt'], @@ -273,7 +273,7 @@ export class TaskStatus { ]); // Please make sure this matches task-status-colors.less - public static readonly STATUS_COLORS = new Map([ + public static readonly STATUS_COLORS: Map = new Map([ ['ready_for_feedback', '#0079D8'], ['not_started', '#CCCCCC'], ['working_on_it', '#EB8F06'], @@ -290,7 +290,7 @@ export class TaskStatus { ['attention_required', '#f1814d'], ]); - public static readonly STATUS_SEQ = new Map([ + public static readonly STATUS_SEQ: Map = new Map([ ['not_started', 1], ['fail', 2], ['feedback_exceeded', 3], @@ -325,10 +325,10 @@ export class TaskStatus { // detail = in a brief context to the student // reason = reason for this status // action = action student can take - public static readonly HELP_DESCRIPTIONS = new Map< + public static readonly HELP_DESCRIPTIONS: Map< TaskStatusEnum, {detail: string; reason: string; action: string} - >([ + > = new Map([ [ 'ready_for_feedback', { diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index b022d3159a..de1c41d59a 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -1,36 +1,36 @@ import {Entity, EntityCache, RequestOptions} from 'ngx-entity-service'; +import {Observable, firstValueFrom, map} from 'rxjs'; import {AppInjector} from 'src/app/app-injector'; -import {formatDate} from '@angular/common'; +import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {GradeTaskModalService} from 'src/app/tasks/modals/grade-task-modal/grade-task-modal.service'; +import {UploadSubmissionModalService} from 'src/app/tasks/modals/upload-submission-modal/upload-submission-modal.service'; +import {formatDate} from '@angular/common'; +import {HttpClient} from '@angular/common/http'; +import {LOCALE_ID} from '@angular/core'; +import {MappingFunctions} from '../services/mapping-fn'; +import {TutorNoteService} from '../services/tutor-note.service'; import { - TaskDefinition, + Group, Project, - Unit, + ScormComment, TaskComment, - TaskStatusEnum, - TaskStatus, - TaskStatusUiData, - TaskService, - Group, TaskCommentService, + TaskDefinition, + TaskService, TaskSimilarity, TaskSimilarityService, + TaskStatus, + TaskStatusEnum, + TaskStatusUiData, TestAttempt, TestAttemptService, - ScormComment, - UnitRoleService, + Unit, UnitRole, + UnitRoleService, UserService, } from './doubtfire-model'; -import {TutorNoteService} from '../services/tutor-note.service'; import {Grade} from './grade'; -import {LOCALE_ID} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; -import {Observable, firstValueFrom, map} from 'rxjs'; -import {AlertService} from 'src/app/common/services/alert.service'; -import {MappingFunctions} from '../services/mapping-fn'; -import {GradeTaskModalService} from 'src/app/tasks/modals/grade-task-modal/grade-task-modal.service'; -import {UploadSubmissionModalService} from 'src/app/tasks/modals/upload-submission-modal/upload-submission-modal.service'; import {TaskPrerequisite} from './task-prerequisite'; export const FeedbackModerationAction = { @@ -148,9 +148,9 @@ export class Task extends Entity { AppInjector.get(TaskCommentService) .addComment(this, textString, 'text') .subscribe({ - next: (tc) => {}, error: (error) => { - console.log(error); + const alerts: AlertService = AppInjector.get(AlertService); + alerts.error(`Failed to add comment: ${error}`); }, }); } @@ -631,7 +631,6 @@ export class Task extends Entity { } comments[comments.length - 1].shouldShowAvatar = true; - comments; } public taskKey(): {studentId: number; taskDefAbbr: string} { @@ -650,14 +649,14 @@ export class Task extends Entity { return this.similarityFlag; } - public getSimilarityData(match: number): Observable { + public getSimilarityData(match: number): Observable { const httpClient = AppInjector.get(HttpClient); return httpClient.get( `${AppInjector.get(DoubtfireConstants).API_URL}/tasks/${this.id}/similarity/${match}`, ); } - public updateSimilarity(match: number, other: any, dismissed: boolean): Observable { + public updateSimilarity(match: number, other: object, dismissed: boolean): Observable { const httpClient = AppInjector.get(HttpClient); return httpClient.put( `${AppInjector.get(DoubtfireConstants).API_URL}/tasks/${this.id}/similarity/${match}`, @@ -892,13 +891,15 @@ export class Task extends Entity { modal.result.then( // Grade was selected (modal closed with result) - (response) => {}, + (_response) => { + /* empty */ + }, // Grade was not selected (modal was dismissed) (_dismissed) => { if (!isTestSubmission) { this.status = oldStatus; } - const alerts: any = AppInjector.get(AlertService); + const alerts: AlertService = AppInjector.get(AlertService); alerts.message('Submission cancelled. Status was reverted.', 6000); }, ); @@ -1033,7 +1034,7 @@ export class Task extends Entity { options, ) .subscribe({ - next: (response) => { + next: (_response) => { if (!hasId && this.id > 0) { this.project.taskCache.delete(this.definition.abbreviation); this.project.taskCache.add(this); @@ -1112,7 +1113,7 @@ export class Task extends Entity { const http = AppInjector.get(HttpClient); http.post(`${AppInjector.get(DoubtfireConstants).API_URL}/tasks/${this.id}/pin`, {}).subscribe({ - next: (data) => { + next: (_data) => { this.pinned = true; onSuccess?.(); }, diff --git a/src/app/api/models/tii-action.ts b/src/app/api/models/tii-action.ts index 661ba9324f..75afd42516 100644 --- a/src/app/api/models/tii-action.ts +++ b/src/app/api/models/tii-action.ts @@ -1,6 +1,4 @@ -import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; -import {Observable} from 'rxjs'; -import {Unit} from './doubtfire-model'; +import {Entity} from 'ngx-entity-service'; export class TiiAction extends Entity { id: number; diff --git a/src/app/api/models/tutorial-enrolment.ts b/src/app/api/models/tutorial-enrolment.ts index 2b6f822405..9af8408c51 100644 --- a/src/app/api/models/tutorial-enrolment.ts +++ b/src/app/api/models/tutorial-enrolment.ts @@ -1,5 +1,5 @@ import {Entity} from 'ngx-entity-service'; -import {Tutorial, User} from './doubtfire-model'; +import {Tutorial} from './doubtfire-model'; export class TutorialEnrolment extends Entity { public tutorial: Tutorial; diff --git a/src/app/api/models/tutorial-stream/tutorial-stream.ts b/src/app/api/models/tutorial-stream/tutorial-stream.ts index b1ef5ad77d..2ba8c4db36 100644 --- a/src/app/api/models/tutorial-stream/tutorial-stream.ts +++ b/src/app/api/models/tutorial-stream/tutorial-stream.ts @@ -1,5 +1,5 @@ import {Entity} from 'ngx-entity-service'; -import {Unit, Tutorial} from '../doubtfire-model'; +import {Tutorial, Unit} from '../doubtfire-model'; export class TutorialStream extends Entity { name: string; diff --git a/src/app/api/models/tutorial/tutorial.ts b/src/app/api/models/tutorial/tutorial.ts index 0ef41a464d..b4cf26785d 100644 --- a/src/app/api/models/tutorial/tutorial.ts +++ b/src/app/api/models/tutorial/tutorial.ts @@ -1,12 +1,5 @@ import {Entity, EntityMapping} from 'ngx-entity-service'; -import {AppInjector} from '../../../app-injector'; -import { - User, - Campus, - UserService, - CampusService, - TutorialStream, -} from 'src/app/api/models/doubtfire-model'; +import {Campus, TutorialStream, User} from 'src/app/api/models/doubtfire-model'; import {Unit} from '../unit'; export class Tutorial extends Entity { diff --git a/src/app/api/models/unit-role.ts b/src/app/api/models/unit-role.ts index 967d542381..1436c96847 100644 --- a/src/app/api/models/unit-role.ts +++ b/src/app/api/models/unit-role.ts @@ -1,5 +1,5 @@ import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; -import {User, Unit} from './doubtfire-model'; +import {Unit, User} from './doubtfire-model'; import {TutorNote} from './tutor-note'; /** diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index 55dd4275ea..a976538d4f 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -1,10 +1,10 @@ -import {HttpClient, HttpParams} from '@angular/common/http'; import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; import {Observable, tap} from 'rxjs'; import {AppInjector} from 'src/app/app-injector'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {HttpClient, HttpParams} from '@angular/common/http'; import {GroupService} from '../services/group.service'; import {MarkingSessionService} from '../services/marking-session.service'; import {ProjectService} from '../services/project.service'; @@ -101,8 +101,6 @@ export class Unit extends Entity { readonly studentCache: EntityCache = new EntityCache(); - analytics: {} = {}; - public override toJson( mappingData: EntityMapping, ignoreKeys?: string[], @@ -220,7 +218,7 @@ export class Unit extends Entity { taskDefinitionService .delete({unitId: this.id, id: taskDef.id}, {cache: this.taskDefinitionCache, entity: taskDef}) .subscribe({ - next: (response) => { + next: () => { alerts.success('Task Deleted', 2000); }, error: (message) => alerts.error(message, 6000), @@ -447,7 +445,7 @@ export class Unit extends Entity { return `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.id}/grades/csv`; } - public taskStatusFactor(td: TaskDefinition): number { + public taskStatusFactor(_td: TaskDefinition): number { return 1; } diff --git a/src/app/api/models/user/user.ts b/src/app/api/models/user/user.ts index b11826505a..f157d80b03 100644 --- a/src/app/api/models/user/user.ts +++ b/src/app/api/models/user/user.ts @@ -1,9 +1,8 @@ -import {HttpClient} from '@angular/common/http'; import {Entity, EntityMapping} from 'ngx-entity-service'; import {Observable, map} from 'rxjs'; import {AppInjector} from 'src/app/app-injector'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; -import {AuthenticationService} from '../doubtfire-model'; +import {HttpClient} from '@angular/common/http'; export type Tutor = User; diff --git a/src/app/api/services/activity-type.service.ts b/src/app/api/services/activity-type.service.ts index 628acde622..3b39e4ac2c 100644 --- a/src/app/api/services/activity-type.service.ts +++ b/src/app/api/services/activity-type.service.ts @@ -1,8 +1,8 @@ -import {ActivityType} from 'src/app/api/models/doubtfire-model'; -import {Injectable} from '@angular/core'; import {CachedEntityService} from 'ngx-entity-service'; +import {ActivityType} from 'src/app/api/models/doubtfire-model'; import API_URL from 'src/app/config/constants/apiUrl'; import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable() export class ActivityTypeService extends CachedEntityService { @@ -16,7 +16,7 @@ export class ActivityTypeService extends CachedEntityService { this.mapping.mapAllKeysToJsonExcept('id'); } - public createInstanceFrom(json: object, other?: any): ActivityType { + public createInstanceFrom(_json: object): ActivityType { return new ActivityType(); } } diff --git a/src/app/api/services/authentication.service.ts b/src/app/api/services/authentication.service.ts index ce19ab7178..0020c89ae3 100644 --- a/src/app/api/services/authentication.service.ts +++ b/src/app/api/services/authentication.service.ts @@ -1,12 +1,12 @@ -import {HttpClient} from '@angular/common/http'; -import {Injectable} from '@angular/core'; -import {Router} from '@angular/router'; -import {AsyncSubject, catchError, map, Observable, throwError} from 'rxjs'; +import {AsyncSubject, Observable, catchError, map, throwError} from 'rxjs'; import {User, UserService} from 'src/app/api/models/doubtfire-model'; import {AppInjector} from 'src/app/app-injector'; import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {Router} from '@angular/router'; /** * The format for the data returned from the auth api. diff --git a/src/app/api/services/campus.service.ts b/src/app/api/services/campus.service.ts index d46d793cc3..5ec6e65c48 100644 --- a/src/app/api/services/campus.service.ts +++ b/src/app/api/services/campus.service.ts @@ -1,8 +1,8 @@ -import {Campus} from 'src/app/api/models/doubtfire-model'; -import {Injectable} from '@angular/core'; import {CachedEntityService} from 'ngx-entity-service'; -import {HttpClient} from '@angular/common/http'; +import {Campus} from 'src/app/api/models/doubtfire-model'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable() export class CampusService extends CachedEntityService { @@ -16,7 +16,7 @@ export class CampusService extends CachedEntityService { this.mapping.mapAllKeysToJsonExcept('id'); } - public createInstanceFrom(json: object, other?: any): Campus { + public createInstanceFrom(_json: object): Campus { return new Campus(); } } diff --git a/src/app/api/services/discussion-prompt.service.ts b/src/app/api/services/discussion-prompt.service.ts index c102fbcbf1..482c80dfe8 100644 --- a/src/app/api/services/discussion-prompt.service.ts +++ b/src/app/api/services/discussion-prompt.service.ts @@ -1,5 +1,3 @@ -import {HttpClient} from '@angular/common/http'; -import {Injectable} from '@angular/core'; import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; import {Observable} from 'rxjs'; import { @@ -10,6 +8,8 @@ import { UserService, } from 'src/app/api/models/doubtfire-model'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {DiscussionPrompt} from '../models/discussion-prompt'; @Injectable() @@ -57,7 +57,7 @@ export class DiscussionPromptService extends CachedEntityService { + toJsonFn: (entity: DiscussionPrompt, _key: string) => { return entity.taskDefinition?.id; }, }, diff --git a/src/app/api/services/feedback-template.service.ts b/src/app/api/services/feedback-template.service.ts index 54d981d56b..7d9e110031 100644 --- a/src/app/api/services/feedback-template.service.ts +++ b/src/app/api/services/feedback-template.service.ts @@ -1,8 +1,8 @@ -import {Injectable} from '@angular/core'; import {CachedEntityService} from 'ngx-entity-service'; -import {FeedbackTemplate} from '../models/feedback-template'; -import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {FeedbackTemplate} from '../models/feedback-template'; @Injectable() export class FeedbackTemplateService extends CachedEntityService { @@ -29,7 +29,7 @@ export class FeedbackTemplateService extends CachedEntityService { @@ -24,7 +24,7 @@ export class GroupSetService extends CachedEntityService { this.mapping.mapAllKeysToJsonExcept('id'); } - public createInstanceFrom(json: object, other?: any): GroupSet { - return new GroupSet(other as Unit); + public createInstanceFrom(_json: object, other?: Unit): GroupSet { + return new GroupSet(other); } } diff --git a/src/app/api/services/group.service.ts b/src/app/api/services/group.service.ts index c9a7435828..6bc73d95db 100644 --- a/src/app/api/services/group.service.ts +++ b/src/app/api/services/group.service.ts @@ -1,8 +1,8 @@ import {CachedEntityService} from 'ngx-entity-service'; import {Group, Unit} from 'src/app/api/models/doubtfire-model'; -import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable() export class GroupService extends CachedEntityService { @@ -28,7 +28,7 @@ export class GroupService extends CachedEntityService { toEntityFn: (data: object, jsonKey: string, grp: Group) => { return grp.unit.tutorialsCache.get(data[jsonKey]); }, - toJsonFn: (group: Group, key: string) => { + toJsonFn: (group: Group, _key: string) => { return group.tutorial.id; }, }, @@ -37,7 +37,7 @@ export class GroupService extends CachedEntityService { this.mapping.mapAllKeysToJsonExcept('id', 'groupSet', 'studentCount'); } - public createInstanceFrom(json: object, other?: any): Group { - return new Group(other as Unit); + public createInstanceFrom(_json: object, other?: Unit): Group { + return new Group(other); } } diff --git a/src/app/api/services/learning-outcome.service.ts b/src/app/api/services/learning-outcome.service.ts index 2c4d6181c8..24377596c0 100644 --- a/src/app/api/services/learning-outcome.service.ts +++ b/src/app/api/services/learning-outcome.service.ts @@ -1,8 +1,8 @@ import {CachedEntityService} from 'ngx-entity-service'; import {LearningOutcome} from 'src/app/api/models/doubtfire-model'; -import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable() export class LearningOutcomeService extends CachedEntityService { @@ -27,7 +27,7 @@ export class LearningOutcomeService extends CachedEntityService this.mapping.mapAllKeysToJsonExcept('id', 'context'); } - public createInstanceFrom(json: object, other?: any): LearningOutcome { + public createInstanceFrom(_json: object): LearningOutcome { return new LearningOutcome(); } } diff --git a/src/app/api/services/lti.service.ts b/src/app/api/services/lti.service.ts index f4d7004ec7..b0f62ef09a 100644 --- a/src/app/api/services/lti.service.ts +++ b/src/app/api/services/lti.service.ts @@ -1,16 +1,16 @@ -import {HttpClient} from '@angular/common/http'; -import {Injectable} from '@angular/core'; import {Observable} from 'rxjs'; +import {CsvResult} from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; import LTI_API_URL from 'src/app/config/constants/ltiApiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {Project} from '../models/project'; import {SidekiqJob} from '../models/sidekiq-job'; -import {CsvResult} from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; interface info { name?: string; email?: string; roles?: string[]; - custom?: any; + custom?: Record; context?: | { id?: string; @@ -35,6 +35,19 @@ export interface UnitLink { unitId: string; } +export interface LtiMembers { + members: LtiMember[]; +} + +export interface LtiMember { + email: string; + family_name: string; + given_name: string; + name: string; + user_id: string; + roles: string[]; +} + @Injectable() export class LtiService { constructor(private httpClient: HttpClient) {} @@ -59,8 +72,8 @@ export class LtiService { return this.httpClient.post(`${LTI_API_URL}/enrol`, unit); } - public getMembers(): Observable { - return this.httpClient.get(`${LTI_API_URL}/members`); + public getMembers(): Observable { + return this.httpClient.get(`${LTI_API_URL}/members`); } // Sync grades for all members in the context (course) diff --git a/src/app/api/services/marking-session.service.ts b/src/app/api/services/marking-session.service.ts index a621dfa5f0..5c67dd5f80 100644 --- a/src/app/api/services/marking-session.service.ts +++ b/src/app/api/services/marking-session.service.ts @@ -1,8 +1,8 @@ -import {HttpClient} from '@angular/common/http'; -import {Injectable} from '@angular/core'; import {CachedEntityService} from 'ngx-entity-service'; import {Unit} from 'src/app/api/models/doubtfire-model'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {MarkingSession} from '../models/marking-session'; @Injectable() diff --git a/src/app/api/services/overseer-assessment.service.ts b/src/app/api/services/overseer-assessment.service.ts index 82c41e3dbc..aa60a2ff50 100644 --- a/src/app/api/services/overseer-assessment.service.ts +++ b/src/app/api/services/overseer-assessment.service.ts @@ -1,10 +1,10 @@ -import {Injectable} from '@angular/core'; import {EntityService} from 'ngx-entity-service'; import {Observable} from 'rxjs'; -import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiUrl'; -import {OverseerAssessment} from '../models/overseer/overseer-assessment'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {Task} from '../models/doubtfire-model'; +import {OverseerAssessment} from '../models/overseer/overseer-assessment'; import {OverseerStepResultService} from './overseer-step-result.service'; @Injectable() @@ -30,7 +30,7 @@ export class OverseerAssessmentService extends EntityService ['submissionStatus', 'status'], { keys: ['timestamp', 'submission_timestamp'], - toEntityFn: (data, key, entity, params?) => { + toEntityFn: (data, _key, _entity, _params?) => { return new Date(data['submission_timestamp'] * 1000); }, }, @@ -57,7 +57,7 @@ export class OverseerAssessmentService extends EntityService ); } - public createInstanceFrom(json: any, other?: any): OverseerAssessment { + public createInstanceFrom(_json: object, other?: Task): OverseerAssessment { return new OverseerAssessment(other); } diff --git a/src/app/api/services/overseer-image.service.ts b/src/app/api/services/overseer-image.service.ts index 7edc65932f..a282288160 100644 --- a/src/app/api/services/overseer-image.service.ts +++ b/src/app/api/services/overseer-image.service.ts @@ -1,9 +1,9 @@ import {CachedEntityService} from 'ngx-entity-service'; -import {Observable, switchMap} from 'rxjs'; +import {Observable} from 'rxjs'; import {OverseerImage} from 'src/app/api/models/doubtfire-model'; -import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {SidekiqJob} from '../models/sidekiq-job'; @Injectable() @@ -32,7 +32,7 @@ export class OverseerImageService extends CachedEntityService { }); } - public createInstanceFrom(json: object, other?: any): OverseerImage { + public createInstanceFrom(_json: object): OverseerImage { return new OverseerImage(); } } diff --git a/src/app/api/services/overseer-step-result.service.ts b/src/app/api/services/overseer-step-result.service.ts index f7e873281b..d3f3c99009 100644 --- a/src/app/api/services/overseer-step-result.service.ts +++ b/src/app/api/services/overseer-step-result.service.ts @@ -1,10 +1,10 @@ -import {HttpClient} from '@angular/common/http'; -import {Injectable} from '@angular/core'; import {CachedEntityService} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {OverseerAssessment} from '../models/doubtfire-model'; import {OverseerStepResult} from '../models/overseer/overseer-step-result'; -import {Observable} from 'rxjs'; @Injectable() export class OverseerStepResultService extends CachedEntityService { @@ -31,8 +31,8 @@ export class OverseerStepResultService extends CachedEntityService { diff --git a/src/app/api/services/overseer-step.service.ts b/src/app/api/services/overseer-step.service.ts index 3d8a8fca9a..90a1ad70d7 100644 --- a/src/app/api/services/overseer-step.service.ts +++ b/src/app/api/services/overseer-step.service.ts @@ -1,7 +1,7 @@ -import {HttpClient} from '@angular/common/http'; -import {Injectable} from '@angular/core'; import {CachedEntityService} from 'ngx-entity-service'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {OverseerStep} from '../models/overseer/overseer-step'; import {TaskDefinition} from '../models/task-definition'; @@ -23,7 +23,7 @@ export class OverseerStepService extends CachedEntityService { // 'runCommand', { keys: 'runCommand', - toEntityFn: (data: object, key: string, entity: OverseerStep, params?: any) => { + toEntityFn: (data: object, key: string, entity: OverseerStep) => { const raw = data['run_command']; if (raw?.startsWith('b64:')) { entity.decodedRunCommand = atob(raw.slice(4)); @@ -54,7 +54,7 @@ export class OverseerStepService extends CachedEntityService { this.mapping.mapAllKeysToJsonExcept('id'); } - public createInstanceFrom(json: object, other?: any): OverseerStep { - return new OverseerStep(other as TaskDefinition); + public createInstanceFrom(_json: object, other?: TaskDefinition): OverseerStep { + return new OverseerStep(other); } } diff --git a/src/app/api/services/project.service.ts b/src/app/api/services/project.service.ts index 3a99563192..aee67e8c87 100644 --- a/src/app/api/services/project.service.ts +++ b/src/app/api/services/project.service.ts @@ -1,4 +1,5 @@ import {CachedEntityService, MappingProcess, RequestOptions} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; import { CampusService, Project, @@ -6,14 +7,13 @@ import { UnitService, UserService, } from 'src/app/api/models/doubtfire-model'; -import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; -import API_URL from 'src/app/config/constants/apiUrl'; import {AppInjector} from 'src/app/app-injector'; -import {Observable} from 'rxjs'; -import {TaskService} from './task.service'; -import {TaskOutcomeAlignmentService} from './task-outcome-alignment.service'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {GroupService} from './group.service'; +import {TaskOutcomeAlignmentService} from './task-outcome-alignment.service'; +import {TaskService} from './task.service'; @Injectable() export class ProjectService extends CachedEntityService { @@ -36,20 +36,20 @@ export class ProjectService extends CachedEntityService { 'id', { keys: ['campus', 'campus_id'], - toEntityOp: (data: object, key: string, entity: Project, params?: any) => { + toEntityOp: (data: object, key: string, entity: Project) => { if (data['campus_id']) { return this.campusService.get(data['campus_id']).subscribe((campus) => { entity.campus = campus; }); } }, - toJsonFn: (entity: Project, key: string) => { + toJsonFn: (entity: Project, _key: string) => { return entity.campus ? entity.campus.id : entity.originalJson['camput_id'] ? -1 : null; }, }, { keys: 'student', - toEntityFn: (data: object, key: string, entity: Project, params?: any) => { + toEntityFn: (data: object) => { const userData = data['student']; return this.userService.cache.getOrCreate(userData.id, this.userService, userData); @@ -57,7 +57,7 @@ export class ProjectService extends CachedEntityService { }, { keys: 'userId', - toEntityOp: (data: object, key: string, entity: Project, params?: any) => { + toEntityOp: (data: object, key: string, entity: Project) => { const userId = data['user_id']; this.userService.get(userId).subscribe({ @@ -77,7 +77,7 @@ export class ProjectService extends CachedEntityService { 'staffNoteCount', { keys: 'hasPortfolio', - toEntityFn: (data: object, key: string, entity: Project, params?: any) => { + toEntityFn: (data: object, key: string, entity: Project) => { const result = data[key] === true; if (result) entity.portfolioStatus = 1; @@ -91,7 +91,7 @@ export class ProjectService extends CachedEntityService { 'usesDraftLearningSummary', { keys: ['taskStats', 'stats'], - toEntityOp: (data: object, key: string, entity: Project, params?: any) => { + toEntityOp: (data: object, key: string, entity: Project) => { const values = data[key]; entity.taskStats = [ { @@ -123,14 +123,14 @@ export class ProjectService extends CachedEntityService { 'gradeRationale', { keys: 'unit', - toEntityFn: (data: object, key: string, entity: Project, params?: any) => { + toEntityFn: (data: object, key: string, entity: Project) => { const unitService: UnitService = AppInjector.get(UnitService); const unitData = data['unit']; const result = unitService.cache.getOrCreate(unitData.id, unitService, unitData); result.studentCache.add(entity); return result; }, - toJsonFn: (entity: Project, key: string) => { + toJsonFn: (entity: Project, _key: string) => { return entity.unit?.id; }, }, @@ -150,7 +150,7 @@ export class ProjectService extends CachedEntityService { }, { keys: 'tutorialEnrolments', - toEntityOp: (data: object, key: string, project: Project, params?: any) => { + toEntityOp: (data: object, key: string, project: Project) => { const unit: Unit = project.unit; data[key]?.forEach((tutorialEnrolment: {tutorial_id: number}) => { if (tutorialEnrolment.tutorial_id) { @@ -162,7 +162,7 @@ export class ProjectService extends CachedEntityService { }, { keys: 'groups', - toEntityOp: (data: object, key: string, project: Project, params?: any) => { + toEntityOp: (data: object, key: string, project: Project) => { data[key]?.forEach((group) => { const theGroup = project.unit.groupSetsCache .get(group.group_set_id) @@ -174,13 +174,13 @@ export class ProjectService extends CachedEntityService { theGroup.projectsCache.add(project); }); }, - toJsonFn: (entity: Project, key: string) => { + toJsonFn: (entity: Project, _key: string) => { return entity.unit?.id; }, }, { keys: 'tasks', - toEntityOp: (data: object, key: string, project: Project, params?: any) => { + toEntityOp: (data: object, key: string, project: Project) => { // create tasks from json data['tasks']?.forEach((taskData) => { project.taskCache.getOrCreate(taskData['id'], this.taskService, taskData, { @@ -193,7 +193,7 @@ export class ProjectService extends CachedEntityService { }, { keys: 'taskOutcomeAlignments', - toEntityOp: (data: object, key: string, project: Project, params?: any) => { + toEntityOp: (data: object, key: string, project: Project) => { data[key]?.forEach((alignment) => { project.taskOutcomeAlignmentsCache.getOrCreate( alignment['id'], @@ -221,8 +221,8 @@ export class ProjectService extends CachedEntityService { ); } - public createInstanceFrom(json: object, other?: any): Project { - return new Project(other as Unit); + public createInstanceFrom(_json: object, other?: Unit): Project { + return new Project(other); } public loadStudents( diff --git a/src/app/api/services/scorm-adapter.service.ts b/src/app/api/services/scorm-adapter.service.ts index bdeb14fc77..5cb1fd717d 100644 --- a/src/app/api/services/scorm-adapter.service.ts +++ b/src/app/api/services/scorm-adapter.service.ts @@ -1,7 +1,7 @@ +import {ScormDataModel, ScormPlayerContext} from 'src/app/api/models/doubtfire-model'; +import API_URL from 'src/app/config/constants/apiUrl'; import {Injectable} from '@angular/core'; import {UserService} from './user.service'; -import API_URL from 'src/app/config/constants/apiUrl'; -import {ScormDataModel, ScormPlayerContext} from 'src/app/api/models/doubtfire-model'; @Injectable({ providedIn: 'root', @@ -200,7 +200,7 @@ export class ScormAdapterService { return value; } - SetValue(element: string, value: any): string { + SetValue(element: string, value: string): string { // console.log(`API_1484_11: SetValue:`, element, value); // TODO: error reporting @@ -275,7 +275,7 @@ export class ScormAdapterService { return errorString; } - GetDiagnostic(errorCode: string): string { + GetDiagnostic(_errorCode: string): string { // TODO: implement this // console.log(`API_1484_11: GetDiagnostic:`, errorCode); return 'GetDiagnostic is currently not implemented'; diff --git a/src/app/api/services/sidekiq-job.service.ts b/src/app/api/services/sidekiq-job.service.ts index 8a61e01b55..e103ad4258 100644 --- a/src/app/api/services/sidekiq-job.service.ts +++ b/src/app/api/services/sidekiq-job.service.ts @@ -1,8 +1,8 @@ -import {HttpClient} from '@angular/common/http'; -import {Injectable} from '@angular/core'; import {CachedEntityService} from 'ngx-entity-service'; import {BehaviorSubject, Observable, Subject} from 'rxjs'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {SidekiqJob} from '../models/sidekiq-job'; export interface SidekiqJobEntry { @@ -15,10 +15,10 @@ export interface SidekiqJobEntry { export class SidekiqJobService extends CachedEntityService { protected readonly endpointFormat = 'sidekiq/:id:'; - public jobEntries = new Map(); + public jobEntries: Map = new Map(); // Allow components to track changes to jobEntries - public sidekiqJobsSubject = new BehaviorSubject([]); + public sidekiqJobsSubject: BehaviorSubject = new BehaviorSubject([]); public setJob(jobId: string, title: string, subject: Subject, job?: SidekiqJob) { this.jobEntries.set(jobId, { diff --git a/src/app/api/services/spec/campus.service.spec.ts b/src/app/api/services/spec/campus.service.spec.ts index a91b8c7685..9ac6fc32fe 100644 --- a/src/app/api/services/spec/campus.service.spec.ts +++ b/src/app/api/services/spec/campus.service.spec.ts @@ -1,8 +1,8 @@ -import { TestBed, tick, fakeAsync } from '@angular/core/testing'; -import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; -import { Campus } from 'src/app/api/models/doubtfire-model'; -import { CampusService } from '../campus.service'; -import { HttpRequest, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; +import {Campus} from 'src/app/api/models/doubtfire-model'; +import {HttpRequest, provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; +import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; +import {TestBed, fakeAsync, tick} from '@angular/core/testing'; +import {CampusService} from '../campus.service'; describe('CampusService', () => { let campusService: CampusService; @@ -10,9 +10,13 @@ describe('CampusService', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [], - providers: [CampusService, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()] -}); + imports: [], + providers: [ + CampusService, + provideHttpClient(withInterceptorsFromDi()), + provideHttpClientTesting(), + ], + }); campusService = TestBed.inject(CampusService); httpMock = TestBed.inject(HttpTestingController); @@ -31,9 +35,11 @@ describe('CampusService', () => { const expectedCampuses: Campus[] = [c]; - campusService.query().subscribe((campuses) => expect(campuses).toEqual(expectedCampuses, 'expected campuses')); + campusService + .query() + .subscribe((campuses) => expect(campuses).toEqual(expectedCampuses, 'expected campuses')); - const req = httpMock.expectOne((request: HttpRequest): boolean => { + const req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/campuses/'); expect(request.method).toBe('GET'); return true; diff --git a/src/app/api/services/spec/user.service.spec.ts b/src/app/api/services/spec/user.service.spec.ts index 2d5272b7a4..9d0fc0b774 100644 --- a/src/app/api/services/spec/user.service.spec.ts +++ b/src/app/api/services/spec/user.service.spec.ts @@ -1,7 +1,7 @@ -import { TestBed, tick, fakeAsync } from '@angular/core/testing'; -import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; -import { User, UserService } from 'src/app/api/models/doubtfire-model'; -import { HttpRequest, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; +import {User, UserService} from 'src/app/api/models/doubtfire-model'; +import {HttpRequest, provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; +import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; +import {TestBed, fakeAsync, tick} from '@angular/core/testing'; describe('UserService', () => { let userService: UserService; @@ -9,9 +9,13 @@ describe('UserService', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [], - providers: [UserService, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()] -}); + imports: [], + providers: [ + UserService, + provideHttpClient(withInterceptorsFromDi()), + provideHttpClientTesting(), + ], + }); userService = TestBed.inject(UserService); httpMock = TestBed.inject(HttpTestingController); @@ -38,9 +42,11 @@ describe('UserService', () => { const expectedUsers: User[] = [u]; - userService.query().subscribe((users) => expect(users).toEqual(expectedUsers, 'expected users')); + userService + .query() + .subscribe((users) => expect(users).toEqual(expectedUsers, 'expected users')); - const req = httpMock.expectOne((request: HttpRequest): boolean => { + const req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/users/'); expect(request.method).toBe('GET'); return true; @@ -71,7 +77,7 @@ describe('UserService', () => { const expectedUser = user; expectedUser.id = 1; - const req = httpMock.expectOne((request: HttpRequest): boolean => { + const req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/users/'); expect(request.method).toBe('POST'); @@ -120,7 +126,7 @@ describe('UserService', () => { expect(result.firstName).toBe(u.firstName); }, fail); - let req = httpMock.expectOne((request: HttpRequest): boolean => { + let req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/users/1'); expect(request.method).toBe('PUT'); return true; @@ -136,7 +142,7 @@ describe('UserService', () => { error: fail, }); - req = httpMock.expectOne((request: HttpRequest): boolean => { + req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/users/1'); expect(request.method).toBe('PUT'); return true; @@ -161,9 +167,9 @@ describe('UserService', () => { user.receiveFeedbackNotifications = false; user.receiveTaskNotifications = false; - userService.get(1).subscribe((data) => {}); + userService.get(1).subscribe(); - const req = httpMock.expectOne((request: HttpRequest): boolean => { + const req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/users/1'); expect(request.method).toBe('GET'); return true; @@ -173,9 +179,9 @@ describe('UserService', () => { req.flush(user2); tick(); - userService.get(1).subscribe((data) => {}); + userService.get(1).subscribe(); - httpMock.expectNone((request: HttpRequest): boolean => { + httpMock.expectNone((_request: HttpRequest): boolean => { return true; }); tick(); @@ -201,7 +207,7 @@ describe('UserService', () => { user = data; }); - let req = httpMock.expectOne((request: HttpRequest): boolean => { + let req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/users/1'); expect(request.method).toBe('GET'); return true; @@ -213,7 +219,7 @@ describe('UserService', () => { req.flush(user2); tick(); - let user3; + let _user3; // 1 request here userService.fetch(1).subscribe((data) => { @@ -221,7 +227,7 @@ describe('UserService', () => { user3 = data; }); - req = httpMock.expectOne((request: HttpRequest): boolean => { + req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/users/1'); expect(request.method).toBe('GET'); return true; @@ -232,7 +238,7 @@ describe('UserService', () => { user4.firstName = 'fred'; req.flush(user4); - httpMock.expectNone((request: HttpRequest): boolean => { + httpMock.expectNone((_request: HttpRequest): boolean => { return true; }); tick(); diff --git a/src/app/api/services/staff-note.service.ts b/src/app/api/services/staff-note.service.ts index 6e989e17f3..decb75316e 100644 --- a/src/app/api/services/staff-note.service.ts +++ b/src/app/api/services/staff-note.service.ts @@ -1,14 +1,14 @@ -import {HttpClient} from '@angular/common/http'; -import {EventEmitter, Injectable} from '@angular/core'; import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; +import {Observable, tap} from 'rxjs'; import {Project, ProjectService, UserService} from 'src/app/api/models/doubtfire-model'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {EventEmitter, Injectable} from '@angular/core'; import {StaffNote} from '../models/staff-note'; -import {Observable, tap} from 'rxjs'; @Injectable() export class StaffNoteService extends CachedEntityService { - public readonly staffNoteAdded$ = new EventEmitter(); + public readonly staffNoteAdded$: EventEmitter = new EventEmitter(); protected readonly endpointFormat = 'projects/:projectId:/staff_notes/:id:'; diff --git a/src/app/api/services/task-comment.service.ts b/src/app/api/services/task-comment.service.ts index 8e49f12cc8..ca29cacc91 100644 --- a/src/app/api/services/task-comment.service.ts +++ b/src/app/api/services/task-comment.service.ts @@ -1,3 +1,5 @@ +import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; import { ScormComment, Task, @@ -5,22 +7,20 @@ import { TestAttemptService, UserService, } from 'src/app/api/models/doubtfire-model'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {EmojiService} from 'src/app/common/services/emoji.service'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; import {EventEmitter, Injectable} from '@angular/core'; -import {Observable} from 'rxjs'; import {tap} from 'rxjs/operators'; -import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; import {DiscussionComment} from '../models/task-comment/discussion-comment'; import {ExtensionComment} from '../models/task-comment/extension-comment'; -import {HttpClient} from '@angular/common/http'; -import API_URL from 'src/app/config/constants/apiUrl'; -import {EmojiService} from 'src/app/common/services/emoji.service'; -import {MappingFunctions} from './mapping-fn'; -import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {ScormExtensionComment} from '../models/task-comment/scorm-extension-comment'; +import {MappingFunctions} from './mapping-fn'; @Injectable() export class TaskCommentService extends CachedEntityService { - public readonly commentAdded$ = new EventEmitter(); + public readonly commentAdded$: EventEmitter = new EventEmitter(); private readonly commentEndpointFormat = 'projects/:projectId:/task_def_id/:taskDefinitionId:/comments/:id:'; @@ -62,7 +62,7 @@ export class TaskCommentService extends CachedEntityService { }, { keys: 'recipient', - toEntityFn: (data: object, key: string, comment: TaskComment) => { + toEntityFn: (data: object, key: string, _comment: TaskComment) => { return this.userService.cache.getOrCreate(data[key]?.id, userService, data[key]); }, }, @@ -71,7 +71,7 @@ export class TaskCommentService extends CachedEntityService { 'isNew', { keys: ['text', 'comment'], - toEntityFn: (data, key, entity) => { + toEntityFn: (data, _key, _entity) => { return this.emojiService.colonsToNative(data['comment']); }, }, @@ -132,7 +132,7 @@ export class TaskCommentService extends CachedEntityService { /** * Create a Task Comment - use the type to determine the exact object type to return. */ - public createInstanceFrom(json: any, other?: any): TaskComment { + public createInstanceFrom(json: {type?: string}, other?: Task): TaskComment { switch (json.type) { case 'discussion': return new DiscussionComment(other); @@ -160,9 +160,9 @@ export class TaskCommentService extends CachedEntityService { options?: RequestOptions, ): Observable { return super.query(pathIds, options).pipe( - tap((result) => { + tap((_result) => { // Access the task and set the number of new comments to 0 - they are now read on the server - const task = other as any; //TODO: change to Task object + const task = other as Task; task.numNewComments = 0; }), ); @@ -257,7 +257,7 @@ export class TaskCommentService extends CachedEntityService { public requestExtension( reason: string, weeksRequested: number, - task: any, + task: Task, ): Observable { const opts: RequestOptions = { endpointFormat: this.requestExtensionEndpointFormat, @@ -292,7 +292,7 @@ export class TaskCommentService extends CachedEntityService { ); } - public requestScormExtension(reason: string, task: any): Observable { + public requestScormExtension(reason: string, task: Task): Observable { const opts: RequestOptions = { endpointFormat: this.scormRequestExtensionEndpointFormat, body: { diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 7591ae3f66..3badfc2a56 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -1,21 +1,21 @@ import {CachedEntityService} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; import { LearningOutcomeService, TaskDefinition, TaskStatusEnum, Unit, } from 'src/app/api/models/doubtfire-model'; -import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; -import API_URL from 'src/app/config/constants/apiUrl'; -import {MappingFunctions} from './mapping-fn'; import {AppInjector} from 'src/app/app-injector'; -import {Observable} from 'rxjs'; -import {TaskPrerequisiteService} from './task-prerequisite.service'; -import {TaskPrerequisite} from '../models/task-prerequisite'; +import API_URL from 'src/app/config/constants/apiUrl'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {SidekiqJob} from '../models/sidekiq-job'; +import {TaskPrerequisite} from '../models/task-prerequisite'; +import {MappingFunctions} from './mapping-fn'; import {OverseerStepService} from './overseer-step.service'; +import {TaskPrerequisiteService} from './task-prerequisite.service'; @Injectable() export class TaskDefinitionService extends CachedEntityService { @@ -57,7 +57,7 @@ export class TaskDefinitionService extends CachedEntityService { }, { keys: 'uploadRequirements', - toJsonFn: (taskDef: TaskDefinition, key: string) => { + toJsonFn: (taskDef: TaskDefinition, _key: string) => { return JSON.stringify( taskDef.uploadRequirements?.map((upreq) => { return { @@ -70,7 +70,7 @@ export class TaskDefinitionService extends CachedEntityService { }), ); }, - toEntityFn: (data: object, key: string, taskDef: TaskDefinition, params?: any) => { + toEntityFn: (data: object, key: string) => { return ( data[key] as { key: string; @@ -92,10 +92,10 @@ export class TaskDefinitionService extends CachedEntityService { }, { keys: ['tutorialStream', 'tutorial_stream_abbr'], - toEntityFn: (data: object, key: string, taskDef: TaskDefinition, params?: any) => { + toEntityFn: (data: object, key: string, taskDef: TaskDefinition) => { return taskDef.unit.tutorialStreamsCache.get(data[key]); }, - toJsonFn: (taskDef: TaskDefinition, key: string) => { + toJsonFn: (taskDef: TaskDefinition, _key: string) => { return taskDef.tutorialStream?.abbreviation; }, }, @@ -103,14 +103,14 @@ export class TaskDefinitionService extends CachedEntityService { 'restrictStatusUpdates', { keys: ['groupSet', 'group_set_id'], - toEntityFn: (data: object, key: string, taskDef: TaskDefinition, params?: any) => { + toEntityFn: (data: object, key: string, taskDef: TaskDefinition) => { if (data[key]) { return taskDef.unit.groupSetsCache.get(data[key]); } else { return data[key]; } }, - toJsonFn: (taskDef: TaskDefinition, key: string) => { + toJsonFn: (taskDef: TaskDefinition, _key: string) => { return taskDef.groupSet?.id; }, }, @@ -207,8 +207,8 @@ export class TaskDefinitionService extends CachedEntityService { ); } - public override createInstanceFrom(json: object, other?: any): TaskDefinition { - return new TaskDefinition(other as Unit); + public override createInstanceFrom(_json: object, other?: Unit): TaskDefinition { + return new TaskDefinition(other); } public uploadTaskSheet(taskDefinition: TaskDefinition, file: File): Observable { diff --git a/src/app/api/services/task-outcome-alignment.service.ts b/src/app/api/services/task-outcome-alignment.service.ts index 44fd1ea07f..e0a542869e 100644 --- a/src/app/api/services/task-outcome-alignment.service.ts +++ b/src/app/api/services/task-outcome-alignment.service.ts @@ -1,9 +1,8 @@ -import {HttpClient} from '@angular/common/http'; import {CachedEntityService} from 'ngx-entity-service'; import {Project, TaskOutcomeAlignment, Unit} from 'src/app/api/models/doubtfire-model'; -import {Injectable} from '@angular/core'; import API_URL from 'src/app/config/constants/apiUrl'; -import {UnitTutorialsListComponent} from 'src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable() export class TaskOutcomeAlignmentService extends CachedEntityService { @@ -22,7 +21,7 @@ export class TaskOutcomeAlignmentService extends CachedEntityService { + toJsonFn: (entity: TaskOutcomeAlignment, _key: string) => { return entity.learningOutcome.id; }, }, @@ -32,7 +31,7 @@ export class TaskOutcomeAlignmentService extends CachedEntityService { + toJsonFn: (entity: TaskOutcomeAlignment, _key: string) => { return entity.taskDefinition.id; }, }, @@ -42,7 +41,7 @@ export class TaskOutcomeAlignmentService extends CachedEntityService { + toJsonFn: (entity: TaskOutcomeAlignment, _key: string) => { return entity.task?.id; }, }, @@ -51,7 +50,7 @@ export class TaskOutcomeAlignmentService extends CachedEntityService { @@ -20,7 +20,7 @@ export class TaskPrerequisiteService extends CachedEntityService { diff --git a/src/app/api/services/task.service.ts b/src/app/api/services/task.service.ts index f7b9bd6f61..06a59b6ce1 100644 --- a/src/app/api/services/task.service.ts +++ b/src/app/api/services/task.service.ts @@ -1,3 +1,5 @@ +import {CachedEntityService, EntityCache, RequestOptions} from 'ngx-entity-service'; +import {Observable, map, tap} from 'rxjs'; import { Project, Task, @@ -7,16 +9,14 @@ import { TaskStatusUiData, Unit, } from 'src/app/api/models/doubtfire-model'; -import {EventEmitter, Injectable} from '@angular/core'; -import {CachedEntityService, EntityCache, RequestOptions} from 'ngx-entity-service'; -import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {EventEmitter, Injectable} from '@angular/core'; import {MappingFunctions} from './mapping-fn'; -import {Observable, map, tap} from 'rxjs'; @Injectable() export class TaskService extends CachedEntityService { - public readonly taskStatusUpdated$ = new EventEmitter(); + public readonly taskStatusUpdated$: EventEmitter = new EventEmitter(); protected readonly endpointFormat = '/projects/:projectId:/task_def_id/:taskDefId:'; @@ -33,14 +33,14 @@ export class TaskService extends CachedEntityService { 'id', { keys: 'projectId', - toEntityOp: (data: object, jsonKey: string, task: Task, _params?: any) => { + toEntityOp: (data: object, jsonKey: string, task: Task) => { // Is fetching task outside of project... task.project = task.unit.findStudent(data[jsonKey]); }, }, { keys: 'taskDefinitionId', - toEntityOp: (data: object, key: string, entity: Task, _params?: any) => { + toEntityOp: (data: object, key: string, entity: Task) => { entity.definition = entity.project.unit.taskDef(data['task_definition_id']); }, }, @@ -79,13 +79,13 @@ export class TaskService extends CachedEntityService { 'pinned', { keys: 'new_stat', - toEntityOp: (data: object, key: string, entity: Task, params?: any) => { + toEntityOp: (data: object, key: string, entity: Task) => { entity.project.taskStats = data['new_stat']; }, }, { keys: 'otherProjects', - toEntityOp: (data: object, key: string, entity: Task, params?: any) => { + toEntityOp: (data: object, key: string, entity: Task) => { data['other_projects'].forEach((details) => { const proj = entity.unit.findStudent(details.id); if (proj) { @@ -106,8 +106,8 @@ export class TaskService extends CachedEntityService { this.mapping.addJsonKey('qualityPts', 'grade', 'includeInPortfolio', 'trigger'); } - public createInstanceFrom(json: object, other?: any): Task { - return new Task(other as Project); + public createInstanceFrom(_json: object, other?: Project): Task { + return new Task(other); } public queryTasksForTaskInbox( @@ -209,7 +209,6 @@ export class TaskService extends CachedEntityService { }; this.get(pathIds, options).subscribe({ - next: (value: Task) => {}, error: (message) => { console.log(`Failed to refresh tasks ${message}`); }, diff --git a/src/app/api/services/teaching-period-break.service.ts b/src/app/api/services/teaching-period-break.service.ts index a7e3b296de..75dbae6fe1 100644 --- a/src/app/api/services/teaching-period-break.service.ts +++ b/src/app/api/services/teaching-period-break.service.ts @@ -1,8 +1,8 @@ -import {HttpClient} from '@angular/common/http'; import {CachedEntityService} from 'ngx-entity-service'; import {TeachingPeriodBreak} from 'src/app/api/models/doubtfire-model'; -import {Injectable} from '@angular/core'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {MappingFunctions} from './mapping-fn'; @Injectable() @@ -25,7 +25,7 @@ export class TeachingPeriodBreakService extends CachedEntityService { this.cacheBehaviourOnGet = 'cacheQuery'; } - public createInstanceFrom(json: any, other?: any): TeachingPeriod { + public createInstanceFrom(_json: object): TeachingPeriod { return new TeachingPeriod(); } } diff --git a/src/app/api/services/test-attempt.service.ts b/src/app/api/services/test-attempt.service.ts index 9b418045ec..b9e6e1e0a7 100644 --- a/src/app/api/services/test-attempt.service.ts +++ b/src/app/api/services/test-attempt.service.ts @@ -1,12 +1,12 @@ -import {Injectable} from '@angular/core'; import {CachedEntityService} from 'ngx-entity-service'; -import API_URL from 'src/app/config/constants/apiUrl'; -import {Task, TestAttempt} from 'src/app/api/models/doubtfire-model'; import {Observable} from 'rxjs'; +import {Task, TestAttempt} from 'src/app/api/models/doubtfire-model'; import {AppInjector} from 'src/app/app-injector'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {AlertService} from 'src/app/common/services/alert.service'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable() export class TestAttemptService extends CachedEntityService { diff --git a/src/app/api/services/tii-action.service.ts b/src/app/api/services/tii-action.service.ts index 330a1bd147..21bfced4d9 100644 --- a/src/app/api/services/tii-action.service.ts +++ b/src/app/api/services/tii-action.service.ts @@ -1,9 +1,8 @@ +import {CachedEntityService} from 'ngx-entity-service'; +import {TiiAction} from 'src/app/api/models/doubtfire-model'; +import API_URL from 'src/app/config/constants/apiUrl'; import {HttpClient} from '@angular/common/http'; -import {CachedEntityService, Entity} from 'ngx-entity-service'; -import {TiiAction, Unit, UnitService, UserService} from 'src/app/api/models/doubtfire-model'; import {Injectable} from '@angular/core'; -import API_URL from 'src/app/config/constants/apiUrl'; -import {AppInjector} from 'src/app/app-injector'; import {MappingFunctions} from './mapping-fn'; @Injectable() @@ -36,7 +35,7 @@ export class TiiActionService extends CachedEntityService { // this.cacheBehaviourOnGet = 'cacheQuery'; } - public createInstanceFrom(json: any, other?: any): TiiAction { + public createInstanceFrom(_json: object): TiiAction { return new TiiAction(); } } diff --git a/src/app/api/services/tii.service.spec.ts b/src/app/api/services/tii.service.spec.ts index af14851920..5aefcb548c 100644 --- a/src/app/api/services/tii.service.spec.ts +++ b/src/app/api/services/tii.service.spec.ts @@ -1,6 +1,5 @@ -import { TestBed } from '@angular/core/testing'; - -import { TiiService } from './tii.service'; +import {TestBed} from '@angular/core/testing'; +import {TiiService} from './tii.service'; describe('TiiServiceService', () => { let service: TiiService; diff --git a/src/app/api/services/tii.service.ts b/src/app/api/services/tii.service.ts index 385e9eef5c..75b1d311a3 100644 --- a/src/app/api/services/tii.service.ts +++ b/src/app/api/services/tii.service.ts @@ -1,7 +1,7 @@ -import {HttpClient} from '@angular/common/http'; -import {Injectable} from '@angular/core'; import {Observable} from 'rxjs'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable({ providedIn: 'root', diff --git a/src/app/api/services/tutor-note.service.ts b/src/app/api/services/tutor-note.service.ts index 3e08ce451d..481526b023 100644 --- a/src/app/api/services/tutor-note.service.ts +++ b/src/app/api/services/tutor-note.service.ts @@ -1,9 +1,9 @@ -import {HttpClient} from '@angular/common/http'; -import {Injectable} from '@angular/core'; import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; import {Observable, tap} from 'rxjs'; import {ProjectService, Task, UnitRole, UserService} from 'src/app/api/models/doubtfire-model'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; import {TutorNote} from '../models/tutor-note'; @Injectable() diff --git a/src/app/api/services/tutorial-stream.service.ts b/src/app/api/services/tutorial-stream.service.ts index 4a5c5a617d..0f17efcb7c 100644 --- a/src/app/api/services/tutorial-stream.service.ts +++ b/src/app/api/services/tutorial-stream.service.ts @@ -1,8 +1,8 @@ -import {HttpClient} from '@angular/common/http'; import {CachedEntityService} from 'ngx-entity-service'; import {TutorialStream} from 'src/app/api/models/doubtfire-model'; -import {Injectable} from '@angular/core'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable() export class TutorialStreamService extends CachedEntityService { @@ -16,11 +16,11 @@ export class TutorialStreamService extends CachedEntityService { this.mapping.mapAllKeysToJson(); } - public createInstanceFrom(json: any, other?: any): TutorialStream { + public createInstanceFrom(_json: object): TutorialStream { return new TutorialStream(); } - public override keyForJson(json: any): string { + public override keyForJson(json: {abbreviation: string}): string { return json['abbreviation']; } diff --git a/src/app/api/services/tutorial.service.ts b/src/app/api/services/tutorial.service.ts index 7f444157ce..d2c14fbaa4 100644 --- a/src/app/api/services/tutorial.service.ts +++ b/src/app/api/services/tutorial.service.ts @@ -1,5 +1,5 @@ -import {Inject, Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; +import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; import { CampusService, Project, @@ -7,10 +7,10 @@ import { Unit, UserService, } from 'src/app/api/models/doubtfire-model'; -import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; -import API_URL from 'src/app/config/constants/apiUrl'; -import {Observable} from 'rxjs'; import {AlertService} from 'src/app/common/services/alert.service'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable() export class TutorialService extends CachedEntityService { @@ -34,22 +34,22 @@ export class TutorialService extends CachedEntityService { 'abbreviation', { keys: ['campus', 'campus_id'], - toEntityOp: (data: object, key: string, entity: Tutorial, params?: any) => { + toEntityOp: (data: object, key: string, entity: Tutorial) => { this.campusService.get(data['campus_id']).subscribe((campus) => { entity.campus = campus; }); }, - toJsonFn: (entity: Tutorial, key: string) => { + toJsonFn: (entity: Tutorial, _key: string) => { return entity.campus ? entity.campus.id : -1; }, }, 'capacity', { keys: ['tutor', 'tutor_id'], - toEntityFn: (data: object, key: string, entity: Tutorial, params?: any) => { + toEntityFn: (data: object, key: string) => { return this.userService.cache.get(data[key]); }, - toJsonFn: (entity: Tutorial, key: string) => { + toJsonFn: (entity: Tutorial, _key: string) => { return entity.tutor?.id; }, }, @@ -57,17 +57,17 @@ export class TutorialService extends CachedEntityService { 'numStudents', { keys: ['tutorialStream', 'tutorial_stream_abbr'], - toEntityFn: (data: object, key: string, entity: Tutorial, params?: any) => { + toEntityFn: (data: object, key: string, entity: Tutorial) => { return entity.unit.tutorialStreamForAbbr(data[key]); }, - toJsonFn: (entity: Tutorial, key: string) => { + toJsonFn: (entity: Tutorial, _key: string) => { return entity.tutorialStream ? entity.tutorialStream.abbreviation : null; }, }, { keys: ['unit', 'unit_id'], - toJsonFn: (entity: Tutorial, key: string) => { + toJsonFn: (entity: Tutorial, _key: string) => { return entity.unit?.id; }, }, @@ -76,11 +76,11 @@ export class TutorialService extends CachedEntityService { this.mapping.mapAllKeysToJsonExcept('numStudents'); } - public createInstanceFrom(json: any, other?: any): Tutorial { - return new Tutorial(other as Unit); + public createInstanceFrom(_json: object, other?: Unit): Tutorial { + return new Tutorial(other); } - public override keyForJson(json: any): string | number { + public override keyForJson(json: {tutorial_id?: number}): string | number { if (json.tutorial_id) { return json.tutorial_id; } else { @@ -102,7 +102,7 @@ export class TutorialService extends CachedEntityService { body: {}, }; - let observer: Observable; + let observer: Observable<{enrolments: {tutorial_id: number}[]}>; if (isEnrol) { observer = this.post(pathIds, options); } else { diff --git a/src/app/api/services/unit-role.service.ts b/src/app/api/services/unit-role.service.ts index 2aee5b609f..4d6f71b4e1 100644 --- a/src/app/api/services/unit-role.service.ts +++ b/src/app/api/services/unit-role.service.ts @@ -1,3 +1,4 @@ +import {CachedEntityService} from 'ngx-entity-service'; import { TeachingPeriodService, Unit, @@ -5,10 +6,9 @@ import { UnitService, UserService, } from 'src/app/api/models/doubtfire-model'; -import {CachedEntityService} from 'ngx-entity-service'; -import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable() export class UnitRoleService extends CachedEntityService { @@ -26,7 +26,7 @@ export class UnitRoleService extends CachedEntityService { 'id', { keys: 'unit', - toEntityFn: (data, key, entity) => { + toEntityFn: (data, _key, _entity) => { const unitData = data['unit']; const result: Unit = this.unitService.cache.getOrCreate( unitData.id, @@ -36,13 +36,13 @@ export class UnitRoleService extends CachedEntityService { result.updateFromJson(unitData, this.unitService.mapping); return result; }, - toJsonFn: (entity: UnitRole, key: string) => { + toJsonFn: (entity: UnitRole, _key: string) => { return entity.unit?.id; }, }, { keys: 'user', - toEntityFn: (data: object, key: string, entity: UnitRole, params?: any) => { + toEntityFn: (data: object) => { return this.userService.cache.getOrCreate(data['user']['id'], userService, data['user']); }, }, @@ -50,13 +50,13 @@ export class UnitRoleService extends CachedEntityService { 'roleId', { keys: 'userId', - toJsonFn: (entity: UnitRole, key: string) => { + toJsonFn: (entity: UnitRole, _key: string) => { return entity.user?.id; }, }, { keys: 'unitId', - toJsonFn: (entity: UnitRole, key: string) => { + toJsonFn: (entity: UnitRole, _key: string) => { return entity.unit?.id; }, }, @@ -77,7 +77,7 @@ export class UnitRoleService extends CachedEntityService { ); } - public createInstanceFrom(json: any, other?: any): UnitRole { + public createInstanceFrom(_json: object): UnitRole { return new UnitRole(); } } diff --git a/src/app/api/services/unit.service.ts b/src/app/api/services/unit.service.ts index abb09084f7..150f99ba38 100644 --- a/src/app/api/services/unit.service.ts +++ b/src/app/api/services/unit.service.ts @@ -1,5 +1,5 @@ -import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; +import {CachedEntityService} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; import { GroupSetService, LearningOutcomeService, @@ -11,16 +11,16 @@ import { Unit, UserService, } from 'src/app/api/models/doubtfire-model'; -import {CachedEntityService, Entity, EntityMapping} from 'ngx-entity-service'; -import API_URL from 'src/app/config/constants/apiUrl'; -import {UnitRoleService} from './unit-role.service'; +import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; import {AppInjector} from 'src/app/app-injector'; -import {TaskDefinitionService} from './task-definition.service'; -import {GroupService} from './group.service'; -import {Observable} from 'rxjs'; +import API_URL from 'src/app/config/constants/apiUrl'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; -import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {GroupService} from './group.service'; import {MappingFunctions} from './mapping-fn'; +import {TaskDefinitionService} from './task-definition.service'; +import {UnitRoleService} from './unit-role.service'; export type IloStats = { median: number; @@ -30,6 +30,35 @@ export type IloStats = { max: number; }[]; +export interface TaskStatusStat { + tutorial_stream_id: number; + status: string; + num: number; +} + +export type TaskStatusStats = Record>; + +export interface TargetGradeStat { + tutorial_id: number; + tutorial_stream_id: number; + grade: number; + num: number; +} + +export interface TaskCompletionSummary { + median: number; + lower: number; + upper: number; + min: number; + max: number; +} + +export interface TaskCompletionStats { + unit: TaskCompletionSummary; + tutorial: Record; + grade: Record; +} + @Injectable() export class UnitService extends CachedEntityService { protected readonly endpointFormat = 'units/:id:'; @@ -59,7 +88,7 @@ export class UnitService extends CachedEntityService { 'myRole', { keys: 'unitRole', - toEntityFn: (data: object, jsonKey: string, entity: Unit) => { + toEntityFn: (data: object, jsonKey: string, _entity: Unit) => { const unitRoleService = AppInjector.get(UnitRoleService); unitRoleService.cache.get(data[jsonKey]); }, @@ -83,16 +112,16 @@ export class UnitService extends CachedEntityService { entity.mainConvenorUser = result?.user; return result; }, - toJsonFn: (unit: Unit, key: string) => { + toJsonFn: (unit: Unit, _key: string) => { return unit.mainConvenor?.id; }, }, { keys: ['mainConvenorUser', 'main_convenor_user_id'], - toEntityFn: (data, key, entity) => { + toEntityFn: (data, key, _entity) => { return AppInjector.get(UserService).cache.get(data[key]); }, - toJsonFn: (unit: Unit, key: string) => { + toJsonFn: (unit: Unit, _key: string) => { return unit.mainConvenor?.user.id; }, }, @@ -107,27 +136,27 @@ export class UnitService extends CachedEntityService { return undefined; } }, - toJsonFn: (entity: Unit, key: string) => { + toJsonFn: (entity: Unit, _key: string) => { return entity.teachingPeriod ? entity.teachingPeriod.id : undefined; }, }, { keys: 'startDate', - toEntityFn: (data, key, entity, params?) => { + toEntityFn: (data, key, _entity, _params?) => { return new Date(data[key]); }, toJsonFn: MappingFunctions.mapDayToJson, }, { keys: 'endDate', - toEntityFn: (data, key, entity, params?) => { + toEntityFn: (data, key, _entity, _params?) => { return new Date(data[key]); }, toJsonFn: MappingFunctions.mapDayToJson, }, { keys: 'portfolioAutoGenerationDate', - toEntityFn: (data, key, entity, params?) => { + toEntityFn: (data, key, _entity, _params?) => { return new Date(data[key]); }, toJsonFn: MappingFunctions.mapDayToJson, @@ -231,7 +260,7 @@ export class UnitService extends CachedEntityService { toEntityFn: (data: object, jsonKey: string, unit: Unit) => { return unit.taskDef(data[jsonKey]); }, - toJsonFn: (unit: Unit, key: string) => { + toJsonFn: (unit: Unit, _key: string) => { return unit.draftTaskDefinition?.id; }, }, @@ -289,7 +318,7 @@ export class UnitService extends CachedEntityService { ); } - public override createInstanceFrom(json: any, other?: any): Unit { + public override createInstanceFrom(_json: object): Unit { return new Unit(); } @@ -307,25 +336,25 @@ export class UnitService extends CachedEntityService { return httpClient.get(url); } - public taskStatusCountByTutorial(unit: Unit): Observable { + public taskStatusCountByTutorial(unit: Unit): Observable { const url = `${AppInjector.get(DoubtfireConstants).API_URL}/units/${unit.id}/stats/task_status_pct`; const httpClient = AppInjector.get(HttpClient); - return httpClient.get(url); + return httpClient.get(url); } - public targetGradeStats(unit: Unit): Observable { + public targetGradeStats(unit: Unit): Observable { const url = `${AppInjector.get(DoubtfireConstants).API_URL}/units/${unit.id}/stats/student_target_grade`; const httpClient = AppInjector.get(HttpClient); - return httpClient.get(url); + return httpClient.get(url); } - public taskCompletionStats(unit: Unit): Observable { + public taskCompletionStats(unit: Unit): Observable { const url = `${AppInjector.get(DoubtfireConstants).API_URL}/units/${unit.id}/stats/task_completion_stats`; const httpClient = AppInjector.get(HttpClient); - return httpClient.get(url); + return httpClient.get(url); } public zipPortfolios(unit: Unit): Observable { diff --git a/src/app/api/services/user.service.ts b/src/app/api/services/user.service.ts index d4396e8666..fe52b4e341 100644 --- a/src/app/api/services/user.service.ts +++ b/src/app/api/services/user.service.ts @@ -1,11 +1,10 @@ +import {CachedEntityService} from 'ngx-entity-service'; +import {Observable} from 'rxjs'; import {UnitRole, UnitService, User} from 'src/app/api/models/doubtfire-model'; -import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; -import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; -import API_URL from 'src/app/config/constants/apiUrl'; import {AppInjector} from 'src/app/app-injector'; -import {AuthenticationService} from './authentication.service'; -import {Observable, tap} from 'rxjs'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable() export class UserService extends CachedEntityService { diff --git a/src/app/api/services/webcal.service.ts b/src/app/api/services/webcal.service.ts index 9644b85d73..c0a213a5f5 100644 --- a/src/app/api/services/webcal.service.ts +++ b/src/app/api/services/webcal.service.ts @@ -1,8 +1,8 @@ +import {EntityService} from 'ngx-entity-service'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; import {Injectable} from '@angular/core'; import {Webcal} from '../models/webcal/webcal'; -import {Entity, EntityService} from 'ngx-entity-service'; -import {HttpClient} from '@angular/common/http'; -import API_URL from 'src/app/config/constants/apiUrl'; @Injectable() export class WebcalService extends EntityService { @@ -29,7 +29,7 @@ export class WebcalService extends EntityService { this.mapping.mapAllKeysToJsonExcept('id'); } - public createInstanceFrom(json: any, other?: any): Webcal { + public createInstanceFrom(_json: object): Webcal { return new Webcal(); } } diff --git a/src/app/app-injector.ts b/src/app/app-injector.ts index 0d113cf3fc..9a37215985 100644 --- a/src/app/app-injector.ts +++ b/src/app/app-injector.ts @@ -1,4 +1,4 @@ -import { Injector } from '@angular/core'; +import {Injector} from '@angular/core'; /** * Allows for retrieving singletons using `AppInjector.get(MyService)` (whereas diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a42564e5b5..13e1f88e52 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,11 +1,11 @@ +import {Subscription, filter} from 'rxjs'; import {Component, OnDestroy, OnInit, Renderer2} from '@angular/core'; import {NavigationEnd, Router} from '@angular/router'; -import {Subscription, filter} from 'rxjs'; @Component({ - selector: 'app-root', - templateUrl: './app.component.html', - standalone: false + selector: 'app-root', + templateUrl: './app.component.html', + standalone: false, }) export class AppComponent implements OnInit, OnDestroy { private routerSub?: Subscription; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 5c3f4b8bf1..6122dd6101 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,39 +1,39 @@ import {Routes} from '@angular/router'; import {EditProfileComponent} from './account/edit-profile/edit-profile.component'; -import {UnauthorisedComponent} from './errors/states/unauthorised/unauthorised.component'; +import {InstitutionSettingsComponent} from './admin/institution-settings/institution-settings.component'; +import {FUnitsComponent} from './admin/states/units/units.component'; +import {FUsersComponent} from './admin/states/users/users.component'; +import {roleWhitelistGuard} from './common/guards/role-whitelist.guard'; +import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; +import {SubmissionFilesDownloadComponent} from './common/submission-files-download/submission-files-download.component'; +import {SuccessCloseComponent} from './common/success-close/success-close.component'; import {TimeoutComponent} from './errors/states/timeout/timeout.component'; +import {UnauthorisedComponent} from './errors/states/unauthorised/unauthorised.component'; import {AcceptEulaComponent} from './eula/accept-eula/accept-eula.component'; import {HomeComponent} from './home/states/home/home.component'; import {LtiDashboardComponent} from './home/states/lti-dashboard/lti-dashboard.component'; import {LtiUnitLinkComponent} from './home/states/lti-unit-link/lti-unit-link.component'; -import {SignInComponent} from './sessions/states/sign-in/sign-in.component'; -import {SuccessCloseComponent} from './common/success-close/success-close.component'; -import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; -import {FUnitsComponent} from './admin/states/units/units.component'; -import {FUsersComponent} from './admin/states/users/users.component'; -import {InstitutionSettingsComponent} from './admin/institution-settings/institution-settings.component'; -import {TutorDiscussionComponent} from './projects/states/tutor-discussion/tutor-discussion.component'; -import {JplagReportViewerComponent} from './projects/states/jplag/jplag-report-viewer.component'; +import {resolveProject} from './projects/project.resolver'; import {ProjectDashboardComponent} from './projects/states/dashboard/project-dashboard/project-dashboard.component'; import {ProjectGroupsStateComponent} from './projects/states/groups/project-groups-state.component'; +import {JplagReportViewerComponent} from './projects/states/jplag/jplag-report-viewer.component'; import {ProjectPlanComponent} from './projects/states/plan/project-plan.component'; -import {ProjectRootStateComponent} from './projects/states/project-root-state.component'; import {PortfolioStateComponent} from './projects/states/portfolio/portfolio-state.component'; +import {ProjectRootStateComponent} from './projects/states/project-root-state.component'; +import {TutorDiscussionComponent} from './projects/states/tutor-discussion/tutor-discussion.component'; import {TutorialsComponent} from './projects/states/tutorials/tutorials.component'; -import {resolveProject} from './projects/project.resolver'; +import {SignInComponent} from './sessions/states/sign-in/sign-in.component'; +import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-route.component'; import {UnitAdminStateComponent} from './units/states/edit/unit-admin-state.component'; -import {RolloverComponent} from './units/states/rollover/rollover.component'; import {UnitGroupsComponent} from './units/states/groups/unit-groups/unit-groups.component'; -import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-route.component'; -import {StudentsListComponent} from './units/states/students-list/students-list.component'; import {PortfoliosComponent} from './units/states/portfolios/portfolios.component'; +import {RolloverComponent} from './units/states/rollover/rollover.component'; +import {StudentsListComponent} from './units/states/students-list/students-list.component'; import {UnitTaskInboxStateComponent} from './units/states/tasks/inbox/unit-task-inbox-state.component'; import {TaskViewerStateComponent} from './units/task-viewer/task-viewer-state.component'; -import {resolveUnit} from './units/unit.resolver'; import {UnitRootStateComponent} from './units/unit-root-state.component'; +import {resolveUnit} from './units/unit.resolver'; import {WelcomeComponent} from './welcome/welcome.component'; -import {roleWhitelistGuard} from './common/guards/role-whitelist.guard'; -import {SubmissionFilesDownloadComponent} from './common/submission-files-download/submission-files-download.component'; export const routes: Routes = [ {path: '', pathMatch: 'full', redirectTo: 'home'}, diff --git a/src/app/common/archive-viewer/archive-viewer.component.html b/src/app/common/archive-viewer/archive-viewer.component.html index e48d00a0dc..5368148a38 100644 --- a/src/app/common/archive-viewer/archive-viewer.component.html +++ b/src/app/common/archive-viewer/archive-viewer.component.html @@ -1,33 +1,27 @@ -
    +
    @if (isLoading) { -
    +
    Loading archive...
    } @else if (errorMessage) { -
    - error_outline +
    + error_outline {{ errorMessage }}
    } @else if (!archiveFile) { -
    - folder_zip +
    + folder_zip Select an archive to preview.
    } @else if (!hasFiles) { -
    - folder_off +
    + folder_off No files to display.
    } @else { @if (!readOnly && saveEndpoint) { -
    +
    ) => { + ((blobUrl: string, _response: HttpResponse) => { this.isLoaded = true; this.setSrc(blobUrl); this.audio.src = blobUrl; @@ -97,9 +97,9 @@ export class AudioPlayerComponent implements OnDestroy { fn(); } }).bind(this), - ((error: any) => { + ((error: Error) => { this.alerts.error(`Error loading audio. ${error}`, 6000); - }).bind(this) + }).bind(this), ); } } @@ -115,7 +115,7 @@ export class AudioPlayerComponent implements OnDestroy { this.audio.pause(); this.isPlaying = false; } - }).bind(this) + }).bind(this), ); } } diff --git a/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html b/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html index 26d0f04358..1638aeb89d 100644 --- a/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html +++ b/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html @@ -3,7 +3,12 @@ Audio recording
    only supported in modern versions of Chrome, Firefox and Safari.

    - +
    - {{isRecording ? 'stop_circle' : 'radio_button_checked' }} + {{isRecording ? 'stop_circle' : 'radio_button_checked' }} + - +
    - +
    @@ -17,14 +25,22 @@

    Step 1. Record some audio!

    -
    +

    Step 2. Stop the recording, and playback the audio to make sure it's audible:

    - +
    -
    -

    Step 3. Check the "Ready to go" cehckbox below if you're all set!

    +
    +

    Step 3. Check the "Ready to go" cehckbox below if you're all set!

    diff --git a/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester-component.scss b/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester-component.scss index 4b6a37e52a..d201a8dadd 100644 --- a/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester-component.scss +++ b/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester-component.scss @@ -1,5 +1,4 @@ microphone-tester { - h1 { font-size: 12pt; } @@ -9,7 +8,9 @@ microphone-tester { border-radius: 72px; color: #fff; height: 72px; - transition: width 0.1s, height 0.1s; + transition: + width 0.1s, + height 0.1s; width: 72px; border: none; outline: none; @@ -18,7 +19,7 @@ microphone-tester { top: 50%; p { - font-family: "Helvetica Neue", "Segoe UI", "Helvetica", "Arial", "sans-serif"; + font-family: 'Helvetica Neue', 'Segoe UI', 'Helvetica', 'Arial', 'sans-serif'; text-rendering: optimizeLegibility; line-height: 1.3; font-size: 14px; diff --git a/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester.component.ts b/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester.component.ts index dbb42e7a4c..05736d3db9 100644 --- a/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester.component.ts +++ b/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester.component.ts @@ -1,13 +1,13 @@ -import { Input, Component, AfterViewInit } from '@angular/core'; -import { BaseAudioRecorderComponent } from '../base-audio-recorder'; -import { Task } from 'src/app/api/models/doubtfire-model'; -import { MediaRecorderService } from 'src/app/common/services/recorder-service'; +import {Task} from 'src/app/api/models/doubtfire-model'; +import {MediaRecorderService} from 'src/app/common/services/recorder-service'; +import {AfterViewInit, Component, Input} from '@angular/core'; +import {BaseAudioRecorderComponent} from '../base-audio-recorder'; @Component({ - selector: 'microphone-tester', - templateUrl: './microphone-tester-component.html', - providers: [MediaRecorderService], - standalone: false + selector: 'microphone-tester', + templateUrl: './microphone-tester-component.html', + providers: [MediaRecorderService], + standalone: false, }) export class MicrophoneTesterComponent extends BaseAudioRecorderComponent implements AfterViewInit { @Input() task: Task; @@ -25,9 +25,6 @@ export class MicrophoneTesterComponent extends BaseAudioRecorderComponent implem } } - // We need to override default behaviour of the parent class. - ngOnInit() {} - init(): void { super.init(); this.canvas = document.getElementById('micTesterVisualiser') as HTMLCanvasElement; @@ -35,5 +32,7 @@ export class MicrophoneTesterComponent extends BaseAudioRecorderComponent implem this.canvasCtx = this.canvas.getContext('2d'); } - sendRecording(): void {} + sendRecording(): void { + /* empty */ + } } diff --git a/src/app/common/chart-base/chart-base-component/chart-base-component.component.html b/src/app/common/chart-base/chart-base-component/chart-base-component.component.html new file mode 100644 index 0000000000..16e336d2ba --- /dev/null +++ b/src/app/common/chart-base/chart-base-component/chart-base-component.component.html @@ -0,0 +1 @@ +

    chart-base-component works!

    diff --git a/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts b/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts index 1bf6262fe9..0fa371406d 100644 --- a/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts +++ b/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts @@ -1,6 +1,6 @@ -import { Component, ViewContainerRef } from '@angular/core'; -import { TooltipService } from '@swimlane/ngx-charts'; -import { AppInjector } from "src/app/app-injector"; +import {TooltipService} from '@swimlane/ngx-charts'; +import {AppInjector} from 'src/app/app-injector'; +import {Component, ViewContainerRef} from '@angular/core'; /** * @title chart-base-component @@ -9,8 +9,8 @@ import { AppInjector } from "src/app/app-injector"; * Child classes need to extend this class and call super() in the constructor, passing in the ViewContainerRef. */ @Component({ - template: `

    chart-base-component works!

    `, - standalone: false + templateUrl: './chart-base-component.component.html', + standalone: false, }) export class ChartBaseComponent { constructor(public viewContainerRef: ViewContainerRef) { diff --git a/src/app/common/directives/drag-drop.directive.spec.ts b/src/app/common/directives/drag-drop.directive.spec.ts index 0d39e1f01c..101b686e5a 100644 --- a/src/app/common/directives/drag-drop.directive.spec.ts +++ b/src/app/common/directives/drag-drop.directive.spec.ts @@ -1,4 +1,4 @@ -import { DragDropDirective } from './drag-drop.directive'; +import {DragDropDirective} from './drag-drop.directive'; describe('DragDropDirective', () => { it('should create an instance', () => { diff --git a/src/app/common/directives/drag-drop.directive.ts b/src/app/common/directives/drag-drop.directive.ts index 0f2b352581..415e2475b4 100644 --- a/src/app/common/directives/drag-drop.directive.ts +++ b/src/app/common/directives/drag-drop.directive.ts @@ -1,4 +1,4 @@ -import { Directive, Output, EventEmitter, HostBinding, HostListener } from '@angular/core'; +import {Directive, EventEmitter, HostBinding, HostListener, Output} from '@angular/core'; /** * The "appDragDrop" directive can be added to angular components to allow them to act as @@ -7,11 +7,11 @@ import { Directive, Output, EventEmitter, HostBinding, HostListener } from '@ang * class will be applied to the element. */ @Directive({ - selector: '[appDragDrop]', - standalone: false + selector: '[appDragDrop]', + standalone: false, }) export class DragDropDirective { - @Output() fileDropped = new EventEmitter(); + @Output() fileDropped: EventEmitter = new EventEmitter(); // @HostBinding('style.background-color') private background = '#f5fcff'; // @HostBinding('style.opacity') private opacity = '1'; diff --git a/src/app/common/edit-profile-form/edit-profile-form.component.html b/src/app/common/edit-profile-form/edit-profile-form.component.html index 585012d1bd..f314ea254c 100644 --- a/src/app/common/edit-profile-form/edit-profile-form.component.html +++ b/src/app/common/edit-profile-form/edit-profile-form.component.html @@ -5,11 +5,11 @@ fxLayoutAlign="center start" [ngClass]="{'p-10': modal}" > -
    -
    +
    +
    -
    -
    +
    +
    @@ -35,7 +35,7 @@

    {{ user?.firstName }}

    --> Username - +
    @@ -84,10 +84,10 @@

    {{ user?.firstName }}

    @if (user.systemRole === 'Student') { - - Student ID - - + + Student ID + + } @@ -96,28 +96,43 @@

    {{ user?.firstName }}

    @if (canSeeSystemRole) { - - System Role - - Administrator - Convenor - Tutor - Student - Auditor - - + + System Role + + Administrator + Convenor + Tutor + Student + Auditor + + }
    - Receive notifications for new messages
    - Receive notifications when your portfolio is ready
    - Receive notifications when new tasks are available
    @@ -127,33 +142,52 @@

    {{ user?.firstName }}

    - @if(tiiEnabled){ -
    - Accepted TurnItIn EULA - -
    + @if (tiiEnabled) { +
    + Accepted TurnItIn EULA + +
    }
    - -
    - @if (mode === 'create') { - - } @if (mode === 'edit') { +
    + @if (mode === 'create') { + + } + @if (mode === 'edit') { + }
    diff --git a/src/app/common/edit-profile-form/edit-profile-form.component.spec.ts b/src/app/common/edit-profile-form/edit-profile-form.component.spec.ts index 969d9531ae..18f1c2815b 100644 --- a/src/app/common/edit-profile-form/edit-profile-form.component.spec.ts +++ b/src/app/common/edit-profile-form/edit-profile-form.component.spec.ts @@ -1,5 +1,4 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; - import {EditProfileFormComponent} from './edit-profile-form.component'; describe('EditProfileComponent', () => { diff --git a/src/app/common/edit-profile-form/edit-profile-form.component.ts b/src/app/common/edit-profile-form/edit-profile-form.component.ts index e8bf1204de..5ff0848938 100644 --- a/src/app/common/edit-profile-form/edit-profile-form.component.ts +++ b/src/app/common/edit-profile-form/edit-profile-form.component.ts @@ -1,17 +1,17 @@ -import {Component, Inject, Input, OnInit, Optional} from '@angular/core'; -import {MAT_DIALOG_DATA} from '@angular/material/dialog'; -import {MatSnackBar} from '@angular/material/snack-bar'; -import {Router} from '@angular/router'; import {User} from 'src/app/api/models/user/user'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {UserService} from 'src/app/api/services/user.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Component, Inject, Input, OnInit, Optional} from '@angular/core'; +import {MAT_DIALOG_DATA} from '@angular/material/dialog'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {Router} from '@angular/router'; @Component({ - selector: 'f-edit-profile-form', - templateUrl: './edit-profile-form.component.html', - styleUrls: ['./edit-profile-form.component.scss'], - standalone: false + selector: 'f-edit-profile-form', + templateUrl: './edit-profile-form.component.html', + styleUrls: ['./edit-profile-form.component.scss'], + standalone: false, }) export class EditProfileFormComponent implements OnInit { constructor( diff --git a/src/app/common/entity-form/entity-form.component.ts b/src/app/common/entity-form/entity-form.component.ts index abf2a498c5..e46257a9df 100644 --- a/src/app/common/entity-form/entity-form.component.ts +++ b/src/app/common/entity-form/entity-form.component.ts @@ -1,8 +1,9 @@ -import {AfterViewInit, Directive} from '@angular/core'; -import {UntypedFormGroup, AbstractControl} from '@angular/forms'; import {Entity, RequestOptions} from 'ngx-entity-service'; import {EntityService} from 'ngx-entity-service'; import {Observable, tap} from 'rxjs'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {AfterViewInit, Directive} from '@angular/core'; +import {AbstractControl, UntypedFormGroup} from '@angular/forms'; import {Sort} from '@angular/material/sort'; import {MatTableDataSource} from '@angular/material/table'; @@ -59,7 +60,10 @@ export abstract class EntityFormComponent implements AfterView } } - ngAfterViewInit() {} + // eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method + ngAfterViewInit() { + /* empty */ + } /** * Cancel edit of current selected value. @@ -116,7 +120,7 @@ export abstract class EntityFormComponent implements AfterView * @param alertService the alert service used to provide alerts. * @param success the function, provided by inheritor, that is executed on success of CRUD methods. */ - submit(service: EntityService, alertService: any, success: OnSuccessMethod) { + submit(service: EntityService, alertService: AlertService, success: OnSuccessMethod) { // response is what we get back from the server // when creating or updating let response: Observable; @@ -176,9 +180,9 @@ export abstract class EntityFormComponent implements AfterView } } - protected delete(entity: T, entities: T[], service: EntityService): Observable { - return service.delete(entity, this.optionsOnRequest('delete')).pipe( - tap((obj) => { + protected delete(entity: T, entities: T[], service: EntityService): Observable { + return service.delete(entity, this.optionsOnRequest('delete')).pipe( + tap((_obj) => { this.cancelEdit(); entities.splice(entities.indexOf(entity), 1); this.dataSource.data = entities; @@ -210,7 +214,7 @@ export abstract class EntityFormComponent implements AfterView * to the entity constructor when an object is created. This is then passed along * in the `create` call as the `other` value to the EntityService's create method. */ - protected optionsOnRequest(kind: 'create' | 'update' | 'delete'): RequestOptions { + protected optionsOnRequest(_kind: 'create' | 'update' | 'delete'): RequestOptions { return undefined; } diff --git a/src/app/common/f-chip/chip.component.html b/src/app/common/f-chip/chip.component.html index d247144b2a..9d414dc60e 100644 --- a/src/app/common/f-chip/chip.component.html +++ b/src/app/common/f-chip/chip.component.html @@ -1,5 +1,5 @@
    diff --git a/src/app/common/f-chip/chip.component.spec.ts b/src/app/common/f-chip/chip.component.spec.ts index a08f153a40..2360020249 100644 --- a/src/app/common/f-chip/chip.component.spec.ts +++ b/src/app/common/f-chip/chip.component.spec.ts @@ -1,6 +1,5 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { FChipComponent } from './chip.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {FChipComponent} from './chip.component'; describe('FChipComponent', () => { let component: FChipComponent; @@ -8,9 +7,8 @@ describe('FChipComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ FChipComponent ] - }) - .compileComponents(); + declarations: [FChipComponent], + }).compileComponents(); fixture = TestBed.createComponent(FChipComponent); component = fixture.componentInstance; diff --git a/src/app/common/f-chip/chip.component.ts b/src/app/common/f-chip/chip.component.ts index edb9ea33a6..ff926f0556 100644 --- a/src/app/common/f-chip/chip.component.ts +++ b/src/app/common/f-chip/chip.component.ts @@ -1,9 +1,9 @@ -import { Component } from '@angular/core'; +import {Component} from '@angular/core'; @Component({ - selector: 'f-chip', - templateUrl: './chip.component.html', - styleUrls: ['./chip.component.scss'], - standalone: false + selector: 'f-chip', + templateUrl: './chip.component.html', + styleUrls: ['./chip.component.scss'], + standalone: false, }) export class FChipComponent {} diff --git a/src/app/common/feedback-template-editor/feedback-template-editor.component.html b/src/app/common/feedback-template-editor/feedback-template-editor.component.html index 516c4709cc..1def23d307 100644 --- a/src/app/common/feedback-template-editor/feedback-template-editor.component.html +++ b/src/app/common/feedback-template-editor/feedback-template-editor.component.html @@ -1,11 +1,11 @@ -
    +
    -

    Edit Feedback Templates for Outcome

    +

    Edit Feedback Templates for Outcome

    @if (!(action.complete || action.retry)) { - + }
    Edit Feedback Templates for Outcom @if (selectedTemplate) {
    -

    Edit Template

    +

    Edit Template

    @if (selectedTemplate.isNew) { diff --git a/src/app/common/feedback-template-editor/feedback-template-editor.component.ts b/src/app/common/feedback-template-editor/feedback-template-editor.component.ts index dc98c9b8a1..55ad47f8b7 100644 --- a/src/app/common/feedback-template-editor/feedback-template-editor.component.ts +++ b/src/app/common/feedback-template-editor/feedback-template-editor.component.ts @@ -1,8 +1,3 @@ -import {AfterViewInit, Component, Input, OnChanges, SimpleChanges, ViewChild} from '@angular/core'; -import {MatPaginator} from '@angular/material/paginator'; -import {MatSelectChange} from '@angular/material/select'; -import {MatSort, Sort} from '@angular/material/sort'; -import {MatTable, MatTableDataSource} from '@angular/material/table'; import { FeedbackTemplate, FeedbackTemplateService, @@ -12,6 +7,11 @@ import { Unit, } from 'src/app/api/models/doubtfire-model'; import {AlertService} from 'src/app/common/services/alert.service'; +import {AfterViewInit, Component, Input, OnChanges, SimpleChanges, ViewChild} from '@angular/core'; +import {MatPaginator} from '@angular/material/paginator'; +import {MatSelectChange} from '@angular/material/select'; +import {MatSort, Sort} from '@angular/material/sort'; +import {MatTable, MatTableDataSource} from '@angular/material/table'; import {FileDownloaderService} from '../file-downloader/file-downloader.service'; import {ConfirmationModalService} from '../modals/confirmation-modal/confirmation-modal.service'; import { @@ -21,9 +21,9 @@ import { import {CsvUploadModalService} from '../modals/csv-upload-modal/csv-upload-modal.service'; @Component({ - selector: 'f-feedback-template-editor', - templateUrl: 'feedback-template-editor.component.html', - standalone: false + selector: 'f-feedback-template-editor', + templateUrl: 'feedback-template-editor.component.html', + standalone: false, }) export class FeedbackTemplateEditorComponent implements OnChanges, AfterViewInit { @Input() context?: TaskDefinition | Unit; @@ -61,7 +61,7 @@ export class FeedbackTemplateEditorComponent implements OnChanges, AfterViewInit this.getFeedbackChips(); } - ngOnChanges(changes: SimpleChanges): void { + ngOnChanges(_changes: SimpleChanges): void { this.selectedTemplate = null; this.getFeedbackChips(); } @@ -147,7 +147,7 @@ export class FeedbackTemplateEditorComponent implements OnChanges, AfterViewInit const sortedTemplates = [...this.templateSource.data].sort(compare); // Determine maximum depth of the hierarchy (only groups contribute to depth) - const depthMap = new Map(); + const depthMap: Map = new Map(); let maxDepth = 0; const feedbackGroups = sortedTemplates.filter((t) => t.type === 'group'); @@ -167,7 +167,7 @@ export class FeedbackTemplateEditorComponent implements OnChanges, AfterViewInit }); // Assign sequential order numbers - const orderMap = new Map(); + const orderMap: Map = new Map(); let orderIndex = 1; sortedTemplates.forEach((template) => { diff --git a/src/app/common/file-downloader/file-downloader.service.ts b/src/app/common/file-downloader/file-downloader.service.ts index 14dfaffb33..57b8fff783 100644 --- a/src/app/common/file-downloader/file-downloader.service.ts +++ b/src/app/common/file-downloader/file-downloader.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpResponse } from '@angular/common/http'; +import {HttpClient, HttpResponse} from '@angular/common/http'; import {Injectable} from '@angular/core'; import {AlertService} from '../services/alert.service'; diff --git a/src/app/common/file-drop/file-drop.component.html b/src/app/common/file-drop/file-drop.component.html index bbb7236982..4fdd27ad68 100644 --- a/src/app/common/file-drop/file-drop.component.html +++ b/src/app/common/file-drop/file-drop.component.html @@ -7,27 +7,28 @@ #fileUpload /> -
    +
    -
    -
    +
    +
    @if (file?.name) { - upload_file + upload_file } - {{ file?.name || message }} + {{ file?.name || message }} {{ uploadProgress }}
    @if (uploadProgress) { - - } @if (!uploadProgress) { - + + } + @if (!uploadProgress) { + }
    diff --git a/src/app/common/file-drop/file-drop.component.scss b/src/app/common/file-drop/file-drop.component.scss index 2c3f68d5d2..bb6482adfe 100644 --- a/src/app/common/file-drop/file-drop.component.scss +++ b/src/app/common/file-drop/file-drop.component.scss @@ -1,6 +1,6 @@ // import color .f-inner-border { - box-shadow: inset 0 0 1px rgba(0,0,0,0.8); + box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.8); clip-path: inset(-1px -1px 0px 0px); } diff --git a/src/app/common/file-drop/file-drop.component.ts b/src/app/common/file-drop/file-drop.component.ts index 0f020a3f38..93f613812a 100644 --- a/src/app/common/file-drop/file-drop.component.ts +++ b/src/app/common/file-drop/file-drop.component.ts @@ -1,19 +1,19 @@ -import { HttpClient, HttpErrorResponse, HttpEventType, HttpResponse } from '@angular/common/http'; -import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { Subscription, throwError } from 'rxjs'; -import { AlertService } from '../services/alert.service'; +import {Subscription, throwError} from 'rxjs'; +import {HttpClient, HttpErrorResponse, HttpEventType, HttpResponse} from '@angular/common/http'; +import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {AlertService} from '../services/alert.service'; /** * Allow files to be dropped for upload */ @Component({ - selector: 'f-file-drop', - templateUrl: 'file-drop.component.html', - styleUrls: ['file-drop.component.scss'], - standalone: false + selector: 'f-file-drop', + templateUrl: 'file-drop.component.html', + styleUrls: ['file-drop.component.scss'], + standalone: false, }) export class FileDropComponent { - @Input({ required: true }) mode: 'endpoint' | 'event'; + @Input({required: true}) mode: 'endpoint' | 'event'; /** The name of the file(s) you are asking the user to upload */ @Input() desiredFileName: string; @@ -27,8 +27,8 @@ export class FileDropComponent { /** The URL of the endpoint to POST the file to if mode is endpoint*/ @Input() endpoint: string; @Input() body: object; - @Output() fileChange = new EventEmitter(); - @Output() uploadSuccess = new EventEmitter>(); + @Output() fileChange: EventEmitter = new EventEmitter(); + @Output() uploadSuccess: EventEmitter> = new EventEmitter(); protected uploadProgress: number; protected uploadSub: Subscription; @@ -39,7 +39,7 @@ export class FileDropComponent { /** * Report all files dropped if mode is event */ - @Output() filesDropped = new EventEmitter(); + @Output() filesDropped: EventEmitter = new EventEmitter(); constructor( private http: HttpClient, @@ -80,21 +80,23 @@ export class FileDropComponent { const formData = new FormData(); formData.append('file', this.file); - this.http.post(this.endpoint, formData, { reportProgress: true, observe: 'events' }).subscribe( - (data) => { - if (data.type == HttpEventType.UploadProgress) { - this.uploadProgress = Math.round(100 * (data.loaded / data.total)); - } - if (data.type == HttpEventType.Response) { - if (data.ok) { - this.alert.success(`File uploaded successfully`); - this.uploadSuccess.emit(data as HttpResponse); + this.http + .post(this.endpoint, formData, {reportProgress: true, observe: 'events'}) + .subscribe( + (data) => { + if (data.type == HttpEventType.UploadProgress) { + this.uploadProgress = Math.round(100 * (data.loaded / data.total)); } - } - }, - (error) => this.handleError(error), - () => this.reset(), - ); + if (data.type == HttpEventType.Response) { + if (data.ok) { + this.alert.success(`File uploaded successfully`); + this.uploadSuccess.emit(data as HttpResponse); + } + } + }, + (error) => this.handleError(error), + () => this.reset(), + ); } } else { this.filesDropped.emit([this.file]); diff --git a/src/app/common/file-uploader/file-uploader.component.html b/src/app/common/file-uploader/file-uploader.component.html index 96f067af6f..2ff41c792b 100644 --- a/src/app/common/file-uploader/file-uploader.component.html +++ b/src/app/common/file-uploader/file-uploader.component.html @@ -34,14 +34,18 @@
    Select {{ upload.display.name }}
    @if (!upload.display.error) { {{ upload.display.icon }} @if (dropSupported) { - - Drop {{ upload.display.type }} file here
    or click to select + + Drop {{ upload.display.type }} file here
    or click to select
    } @else { Click to select {{ upload.display.type }} file } } @else { - + block Invalid file provided Select {{ upload.display.name }}
    Upload Summary
    @for (upload of uploadZones; track upload) { -
    +
    {{ upload.display.icon }} {{ upload.display.name }} @@ -115,13 +119,13 @@
    Upload Summary
    @if (showUploader && readyToUpload() && isUploading) { @if (!uploadingInfo?.complete) { -
    -
    +
    +
    @for (upload of uploadZones; track upload) { {{ upload.display.icon }} } arrow_right_alt - +
    @@ -130,8 +134,8 @@
    Upload Summary
    } @if (uploadingInfo?.complete) { -
    -
    +
    +
    {{ uploadingInfo.success ? 'check_circle' : 'cancel' }} @@ -142,7 +146,7 @@
    Upload Summary
    @if (!uploadingInfo.success) { -
    +

    Error Message: {{ uploadingInfo.error }}

    diff --git a/src/app/common/file-uploader/file-uploader.component.ts b/src/app/common/file-uploader/file-uploader.component.ts index b256d67f54..021d0e4e83 100644 --- a/src/app/common/file-uploader/file-uploader.component.ts +++ b/src/app/common/file-uploader/file-uploader.component.ts @@ -1,3 +1,5 @@ +import {UserService} from 'src/app/api/services/user.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import { Component, EventEmitter, @@ -7,8 +9,6 @@ import { Output, SimpleChanges, } from '@angular/core'; -import {UserService} from 'src/app/api/services/user.service'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; interface FileData { name: string; @@ -107,8 +107,8 @@ export class FileUploaderComponent implements OnInit, OnChanges { // Once all parent components such as upload-submission-modal are migrated.. // .. these *wont* be necessary anymore // Parent components should declare the file-uploader using @ViewChild() and directly call initiateUpload() - @Output() isReadyChange = new EventEmitter(); - @Output() uploadReady = new EventEmitter<() => void>(); + @Output() isReadyChange: EventEmitter = new EventEmitter(); + @Output() uploadReady: EventEmitter<() => void> = new EventEmitter(); public readonly ACCEPTED_TYPES = ACCEPTED_TYPES; diff --git a/src/app/common/file-viewer/file-viewer.component.html b/src/app/common/file-viewer/file-viewer.component.html index 476c76b464..537049c15b 100644 --- a/src/app/common/file-viewer/file-viewer.component.html +++ b/src/app/common/file-viewer/file-viewer.component.html @@ -1,23 +1,27 @@
    - @if (blobUrl && fileType === 'pdf') { @if (!loaded) { - + @if (blobUrl && fileType === 'pdf') { + @if (!loaded) { + + } + } - - - } @if (fileType === 'html') { -
    - -
    + @if (fileType === 'html') { +
    + +
    }
    diff --git a/src/app/common/file-viewer/file-viewer.component.spec.ts b/src/app/common/file-viewer/file-viewer.component.spec.ts index bfec618b8c..d3e256c208 100644 --- a/src/app/common/file-viewer/file-viewer.component.spec.ts +++ b/src/app/common/file-viewer/file-viewer.component.spec.ts @@ -1,6 +1,5 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { FileViewerComponent } from './file-viewer.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {FileViewerComponent} from './file-viewer.component'; describe('FileViewerComponent', () => { let component: FileViewerComponent; @@ -8,9 +7,8 @@ describe('FileViewerComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ FileViewerComponent ] - }) - .compileComponents(); + declarations: [FileViewerComponent], + }).compileComponents(); fixture = TestBed.createComponent(FileViewerComponent); component = fixture.componentInstance; diff --git a/src/app/common/file-viewer/file-viewer.component.ts b/src/app/common/file-viewer/file-viewer.component.ts index f3145a2e6d..ae6ae795d1 100644 --- a/src/app/common/file-viewer/file-viewer.component.ts +++ b/src/app/common/file-viewer/file-viewer.component.ts @@ -1,17 +1,17 @@ -import { Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; -import { FileDownloaderService } from '../file-downloader/file-downloader.service'; -import { HttpResponse } from '@angular/common/http'; -import { PDFProgressData } from 'ng2-pdf-viewer'; -import { AlertService } from '../services/alert.service'; +import {PDFProgressData} from 'ng2-pdf-viewer'; +import {HttpResponse} from '@angular/common/http'; +import {Component, Input, OnChanges, OnDestroy, SimpleChanges} from '@angular/core'; +import {FileDownloaderService} from '../file-downloader/file-downloader.service'; +import {AlertService} from '../services/alert.service'; /** * The file viewer downloads a file from a URL and displays it's contents. */ @Component({ - selector: 'f-file-viewer', - templateUrl: './file-viewer.component.html', - styleUrls: ['./file-viewer.component.scss'], - standalone: false + selector: 'f-file-viewer', + templateUrl: './file-viewer.component.html', + styleUrls: ['./file-viewer.component.scss'], + standalone: false, }) export class FileViewerComponent implements OnDestroy, OnChanges { /** @@ -51,7 +51,10 @@ export class FileViewerComponent implements OnDestroy, OnChanges { * @param fileDownloader is used to download the resources from the api * @param alerts is used to render alerts */ - constructor(private fileDownloader: FileDownloaderService, private alertService: AlertService) {} + constructor( + private fileDownloader: FileDownloaderService, + private alertService: AlertService, + ) {} /** * When destroyed, the component must free its resources. @@ -99,12 +102,12 @@ export class FileViewerComponent implements OnDestroy, OnChanges { private downloadBlob(downloadUrl: string): void { this.fileDownloader.downloadBlob( downloadUrl, - (url: string, response: HttpResponse) => { + (url: string, _response: HttpResponse) => { this.blobUrl = url; }, - (error: any) => { + (error: Error) => { this.alertService.error(`Error downloading resource. ${error}`); - } + }, ); } diff --git a/src/app/common/filters/filters.pipe.ts b/src/app/common/filters/filters.pipe.ts index 51c71088f1..1a130df9f1 100644 --- a/src/app/common/filters/filters.pipe.ts +++ b/src/app/common/filters/filters.pipe.ts @@ -1,11 +1,11 @@ -import { Pipe, PipeTransform } from '@angular/core'; +import {Pipe, PipeTransform} from '@angular/core'; @Pipe({ - name: 'filters', - standalone: false + name: 'filters', + standalone: false, }) export class FiltersPipe implements PipeTransform { - transform(value: unknown, ...args: unknown[]): unknown { + transform(_value: unknown, ..._args: unknown[]): unknown { return null; } } diff --git a/src/app/common/filters/order-by.pipe.ts b/src/app/common/filters/order-by.pipe.ts index 445cab4c14..7f86a0139b 100644 --- a/src/app/common/filters/order-by.pipe.ts +++ b/src/app/common/filters/order-by.pipe.ts @@ -1,11 +1,15 @@ -import { Pipe, PipeTransform } from '@angular/core'; +import {Pipe, PipeTransform} from '@angular/core'; @Pipe({ - name: 'orderBy', - standalone: false + name: 'orderBy', + standalone: false, }) export class OrderByPipe implements PipeTransform { - transform(array: any[], field: string, reverse: boolean = false): any[] { + transform>( + array: T[], + field: keyof T, + reverse: boolean = false, + ): T[] { if (!array || !field) { return array; } diff --git a/src/app/common/filters/task-definition-name.pipe.ts b/src/app/common/filters/task-definition-name.pipe.ts index adbb4ed9ea..6ee6f136b8 100644 --- a/src/app/common/filters/task-definition-name.pipe.ts +++ b/src/app/common/filters/task-definition-name.pipe.ts @@ -1,14 +1,15 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { Task, TaskDefinition } from '../../api/models/doubtfire-model'; +import {Pipe, PipeTransform} from '@angular/core'; +import {TaskDefinition} from '../../api/models/doubtfire-model'; @Pipe({ - name: 'taskDefinitionName', - standalone: false + name: 'taskDefinitionName', + standalone: false, }) export class TaskDefinitionNamePipe implements PipeTransform { transform(taskDefinitions: TaskDefinition[], searchName: string): TaskDefinition[] { searchName = searchName.toLowerCase(); - return taskDefinitions.filter( // use lodash filter? + return taskDefinitions.filter( + // use lodash filter? (td) => { return ( td?.name.toLowerCase().includes(searchName) || diff --git a/src/app/common/filters/tasks-by-tutor.pipe.ts b/src/app/common/filters/tasks-by-tutor.pipe.ts index 92f49f13cf..0bc94b7635 100644 --- a/src/app/common/filters/tasks-by-tutor.pipe.ts +++ b/src/app/common/filters/tasks-by-tutor.pipe.ts @@ -2,8 +2,8 @@ import {Pipe, PipeTransform} from '@angular/core'; import {Task, UnitRole} from '../../api/models/doubtfire-model'; @Pipe({ - name: 'tasksByTutor', - standalone: false + name: 'tasksByTutor', + standalone: false, }) export class TasksByTutorPipe implements PipeTransform { transform(currentUnitRole: UnitRole, tasks: Task[], unitRoleId?: number | string): Task[] { diff --git a/src/app/common/filters/tasks-for-group-set.pipe.ts b/src/app/common/filters/tasks-for-group-set.pipe.ts index 10f611f29b..214647340f 100644 --- a/src/app/common/filters/tasks-for-group-set.pipe.ts +++ b/src/app/common/filters/tasks-for-group-set.pipe.ts @@ -1,16 +1,16 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { Task, GroupSet } from 'src/app/api/models/doubtfire-model'; +import {GroupSet, Task} from 'src/app/api/models/doubtfire-model'; +import {Pipe, PipeTransform} from '@angular/core'; @Pipe({ - name: 'tasksForGroupset', - standalone: false + name: 'tasksForGroupset', + standalone: false, }) export class TasksForGroupsetPipe implements PipeTransform { transform(tasks: Task[], groupSet: GroupSet): Task[] { if (!tasks) return tasks; - return tasks.filter(task => { - return (task.definition.groupSet === groupSet) || (!task.definition.groupSet && !groupSet); + return tasks.filter((task) => { + return task.definition.groupSet === groupSet || (!task.definition.groupSet && !groupSet); }); } } diff --git a/src/app/common/filters/tasks-for-inbox-search.pipe.ts b/src/app/common/filters/tasks-for-inbox-search.pipe.ts index d48da24b17..26a923f665 100644 --- a/src/app/common/filters/tasks-for-inbox-search.pipe.ts +++ b/src/app/common/filters/tasks-for-inbox-search.pipe.ts @@ -1,9 +1,9 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { Task } from 'src/app/api/models/task'; +import {Task} from 'src/app/api/models/task'; +import {Pipe, PipeTransform} from '@angular/core'; @Pipe({ - name: 'tasksWithStudentName', - standalone: false + name: 'tasksWithStudentName', + standalone: false, }) export class TasksForInboxSearchPipe implements PipeTransform { transform(tasks: Task[], searchText: string): Task[] { @@ -20,8 +20,8 @@ export class TasksForInboxSearchPipe implements PipeTransform { searchTerms .map((term: string) => task.matches(term)) .reduce((prev: boolean, current: boolean, currentIndex: number) => - operators[currentIndex - 1] === '&' ? prev && current : prev || current - ) + operators[currentIndex - 1] === '&' ? prev && current : prev || current, + ), ); } } diff --git a/src/app/common/filters/tasks-in-tutorials.pipe.ts b/src/app/common/filters/tasks-in-tutorials.pipe.ts index 93ab0b15ad..918a8da811 100644 --- a/src/app/common/filters/tasks-in-tutorials.pipe.ts +++ b/src/app/common/filters/tasks-in-tutorials.pipe.ts @@ -1,9 +1,9 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { Task } from '../../api/models/doubtfire-model'; +import {Pipe, PipeTransform} from '@angular/core'; +import {Task} from '../../api/models/doubtfire-model'; @Pipe({ - name: 'tasksInTutorials', - standalone: false + name: 'tasksInTutorials', + standalone: false, }) export class TasksInTutorialsPipe implements PipeTransform { transform(tasks: Task[], tutorialIds: number[], forceStream: boolean): Task[] { diff --git a/src/app/common/filters/tasks-of-task-definition.pipe.ts b/src/app/common/filters/tasks-of-task-definition.pipe.ts index ae1a4ceaaf..bd039c8a00 100644 --- a/src/app/common/filters/tasks-of-task-definition.pipe.ts +++ b/src/app/common/filters/tasks-of-task-definition.pipe.ts @@ -1,9 +1,9 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { Task, TaskDefinition } from 'src/app/api/models/doubtfire-model'; +import {Task, TaskDefinition} from 'src/app/api/models/doubtfire-model'; +import {Pipe, PipeTransform} from '@angular/core'; @Pipe({ - name: 'tasksOfTaskDefinition', - standalone: false + name: 'tasksOfTaskDefinition', + standalone: false, }) export class TasksOfTaskDefinitionPipe implements PipeTransform { transform(tasks: Task[], taskDefinition: TaskDefinition): Task[] { diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index e7a031ddc7..8e470d155d 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -1,4 +1,4 @@ - + more_time Overflow @@ -136,16 +112,10 @@ - - @@ -154,10 +124,7 @@ - @if ( diff --git a/src/app/common/header/task-dropdown/task-dropdown.component.spec.ts b/src/app/common/header/task-dropdown/task-dropdown.component.spec.ts index 7bea55283c..298ab4f769 100644 --- a/src/app/common/header/task-dropdown/task-dropdown.component.spec.ts +++ b/src/app/common/header/task-dropdown/task-dropdown.component.spec.ts @@ -1,7 +1,6 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; - -import { TaskDropdownComponent } from './task-dropdown.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {RouterTestingModule} from '@angular/router/testing'; +import {TaskDropdownComponent} from './task-dropdown.component'; describe('TaskDropdownComponent', () => { let component: TaskDropdownComponent; diff --git a/src/app/common/header/task-dropdown/task-dropdown.component.ts b/src/app/common/header/task-dropdown/task-dropdown.component.ts index 4bde5624ac..e964b3307d 100644 --- a/src/app/common/header/task-dropdown/task-dropdown.component.ts +++ b/src/app/common/header/task-dropdown/task-dropdown.component.ts @@ -1,26 +1,26 @@ -import {Component, Input} from '@angular/core'; -import {ActivatedRoute, NavigationEnd, Router} from '@angular/router'; +import {filter} from 'rxjs'; import {Project, Unit, UnitRole} from 'src/app/api/models/doubtfire-model'; import {ViewType} from 'src/app/projects/states/index/global-state.service'; +import {Component, Input} from '@angular/core'; +import {ActivatedRoute, NavigationEnd, Router} from '@angular/router'; import {TutorNotesModalService} from '../../modals/tutor-notes-modal/tutor-notes-modal.service'; -import {filter} from 'rxjs'; @Component({ - selector: 'task-dropdown', - templateUrl: './task-dropdown.component.html', - styleUrls: ['./task-dropdown.component.scss'], - standalone: false + selector: 'task-dropdown', + templateUrl: './task-dropdown.component.html', + styleUrls: ['./task-dropdown.component.scss'], + standalone: false, }) export class TaskDropdownComponent { currentActivity: string; menuText: string; - @Input() data: { isTutor: boolean }; + @Input() data: {isTutor: boolean}; @Input() currentUnit: Unit; @Input() currentProject: Project; @Input() currentView: ViewType; @Input() unitRole: UnitRole; - taskToShortName: { [key: string]: string } = { + taskToShortName: Record = { 'Portfolio Creation': 'Portfolio', 'Staff Tasks': 'Staff Tasks', 'Student Groups': 'Groups', @@ -36,7 +36,7 @@ export class TaskDropdownComponent { 'Unit Analytics': 'Analytics', }; - taskDropdownData: {title: string; target: string; visible: any}[]; + taskDropdownData: {title: string; target: string; visible: boolean}[]; constructor( private angularRouter: Router, private route: ActivatedRoute, diff --git a/src/app/common/header/unit-dropdown/unit-dropdown.component.html b/src/app/common/header/unit-dropdown/unit-dropdown.component.html index 5830470da8..7c0afe82e5 100644 --- a/src/app/common/header/unit-dropdown/unit-dropdown.component.html +++ b/src/app/common/header/unit-dropdown/unit-dropdown.component.html @@ -47,8 +47,8 @@

    Units y mat-menu-item class="w-full" > -
    -
    {{ unitRole.unit.name }}
    +
    +
    {{ unitRole.unit.name }}
    @@ -62,12 +62,12 @@

    Units yo @if (!project.unit.teachingPeriod || project.unit.teachingPeriod.active) { diff --git a/src/app/common/header/unit-dropdown/unit-dropdown.component.spec.ts b/src/app/common/header/unit-dropdown/unit-dropdown.component.spec.ts index 255c47f1bb..17d17ccaaa 100644 --- a/src/app/common/header/unit-dropdown/unit-dropdown.component.spec.ts +++ b/src/app/common/header/unit-dropdown/unit-dropdown.component.spec.ts @@ -1,26 +1,22 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { MatMenuModule } from '@angular/material/menu'; -import { DateService } from 'src/app/common/services/date.service'; - -import { UnitDropdownComponent } from './unit-dropdown.component'; +import {DateService} from 'src/app/common/services/date.service'; +import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; +import {MatMenuModule} from '@angular/material/menu'; +import {UnitDropdownComponent} from './unit-dropdown.component'; describe('UnitDropdownComponent', () => { let component: UnitDropdownComponent; let fixture: ComponentFixture; - let dateServiceStub: jasmine.SpyObj; + let dateServiceStub: Pick; - beforeEach( - waitForAsync(() => { - dateServiceStub = jasmine.createSpy(); - dateServiceStub.showDate = true; + beforeEach(waitForAsync(() => { + dateServiceStub = {showDate: true}; - TestBed.configureTestingModule({ - declarations: [UnitDropdownComponent], - imports: [MatMenuModule], - providers: [{ provide: DateService, useValue: dateServiceStub }], - }).compileComponents(); - }) - ); + TestBed.configureTestingModule({ + declarations: [UnitDropdownComponent], + imports: [MatMenuModule], + providers: [{provide: DateService, useValue: dateServiceStub}], + }).compileComponents(); + })); beforeEach(() => { fixture = TestBed.createComponent(UnitDropdownComponent); diff --git a/src/app/common/header/unit-dropdown/unit-dropdown.component.ts b/src/app/common/header/unit-dropdown/unit-dropdown.component.ts index 778d75f85f..65acb26fa1 100644 --- a/src/app/common/header/unit-dropdown/unit-dropdown.component.ts +++ b/src/app/common/header/unit-dropdown/unit-dropdown.component.ts @@ -1,14 +1,14 @@ -import {Component, Input, OnInit} from '@angular/core'; -import {Project, Unit, UnitRole} from 'src/app/api/models/doubtfire-model'; import {MediaObserver} from 'ng-flex-layout'; +import {Project, Unit, UnitRole} from 'src/app/api/models/doubtfire-model'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'unit-dropdown', - templateUrl: './unit-dropdown.component.html', - styleUrls: ['./unit-dropdown.component.scss'], - standalone: false + selector: 'unit-dropdown', + templateUrl: './unit-dropdown.component.html', + styleUrls: ['./unit-dropdown.component.scss'], + standalone: false, }) -export class UnitDropdownComponent implements OnInit { +export class UnitDropdownComponent { @Input() unitRoles: UnitRole[]; @Input() projects: Project[]; @Input() unit: Unit; @@ -16,6 +16,4 @@ export class UnitDropdownComponent implements OnInit { unitTitle: string; constructor(public media: MediaObserver) {} - - ngOnInit(): void {} } diff --git a/src/app/common/hero-sidebar/hero-sidebar.component.html b/src/app/common/hero-sidebar/hero-sidebar.component.html index 99fba02150..12145dfff4 100644 --- a/src/app/common/hero-sidebar/hero-sidebar.component.html +++ b/src/app/common/hero-sidebar/hero-sidebar.component.html @@ -1,12 +1,17 @@
    -
    - Homepage Logo +
    + Homepage Logo

    {{ externalName.value }}

    Manage your learning, with feedback you'll want to receive.

    -
    +
    diff --git a/src/app/common/hero-sidebar/hero-sidebar.component.scss b/src/app/common/hero-sidebar/hero-sidebar.component.scss index aaf7e537d5..b49aa2b548 100644 --- a/src/app/common/hero-sidebar/hero-sidebar.component.scss +++ b/src/app/common/hero-sidebar/hero-sidebar.component.scss @@ -35,8 +35,20 @@ } .pattern { - -webkit-mask-image: -webkit-gradient(linear, left top, left bottom, to(rgba(0, 0, 0, 1)), from(rgba(0, 0, 0, 0))); - mask-image: -webkit-gradient(linear, left top, left bottom, to(rgba(0, 0, 0, 1)), from(rgba(0, 0, 0, 0))); + -webkit-mask-image: -webkit-gradient( + linear, + left top, + left bottom, + to(rgba(0, 0, 0, 1)), + from(rgba(0, 0, 0, 0)) + ); + mask-image: -webkit-gradient( + linear, + left top, + left bottom, + to(rgba(0, 0, 0, 1)), + from(rgba(0, 0, 0, 0)) + ); transition: 4s linear all; background-color: #e5e5f7; opacity: 1; diff --git a/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts b/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts index 5cc1ec36c0..aeefe2f6cd 100644 --- a/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts +++ b/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts @@ -1,6 +1,5 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { HeroSidebarComponent } from './hero-sidebar.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {HeroSidebarComponent} from './hero-sidebar.component'; describe('HeroSidebarComponent', () => { let component: HeroSidebarComponent; @@ -8,9 +7,8 @@ describe('HeroSidebarComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ HeroSidebarComponent ] - }) - .compileComponents(); + declarations: [HeroSidebarComponent], + }).compileComponents(); }); beforeEach(() => { diff --git a/src/app/common/hero-sidebar/hero-sidebar.component.ts b/src/app/common/hero-sidebar/hero-sidebar.component.ts index ef02f8508e..395dfcf401 100644 --- a/src/app/common/hero-sidebar/hero-sidebar.component.ts +++ b/src/app/common/hero-sidebar/hero-sidebar.component.ts @@ -1,15 +1,13 @@ -import { Component, OnInit } from '@angular/core'; -import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Component} from '@angular/core'; @Component({ - selector: 'f-hero-sidebar', - templateUrl: './hero-sidebar.component.html', - styleUrls: ['./hero-sidebar.component.scss'], - standalone: false + selector: 'f-hero-sidebar', + templateUrl: './hero-sidebar.component.html', + styleUrls: ['./hero-sidebar.component.scss'], + standalone: false, }) -export class HeroSidebarComponent implements OnInit { +export class HeroSidebarComponent { public externalName = this.constants.ExternalName; constructor(private constants: DoubtfireConstants) {} - - ngOnInit(): void {} } diff --git a/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html b/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html index c93603fa33..34110a1323 100644 --- a/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html +++ b/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html @@ -1,7 +1,7 @@

    @if (selectedOutcome) { -
    +
    -

    Edit Outcome

    +

    Edit Outcome

    diff --git a/src/app/common/learning-outcome-editor/learning-outcome-editor.component.ts b/src/app/common/learning-outcome-editor/learning-outcome-editor.component.ts index c348401d40..06d2827757 100644 --- a/src/app/common/learning-outcome-editor/learning-outcome-editor.component.ts +++ b/src/app/common/learning-outcome-editor/learning-outcome-editor.component.ts @@ -1,37 +1,37 @@ +import {isEqual} from 'lodash'; +import {Subscription} from 'rxjs'; +import { + FeedbackTemplateService, + LearningOutcome, + LearningOutcomeService, + TaskDefinition, + TaskService, + Unit, +} from 'src/app/api/models/doubtfire-model'; +import {AlertService} from 'src/app/common/services/alert.service'; +import API_URL from 'src/app/config/constants/apiUrl'; import {LiveAnnouncer} from '@angular/cdk/a11y'; import {COMMA, ENTER} from '@angular/cdk/keycodes'; import { AfterViewInit, Component, - computed, - effect, - inject, Input, - model, OnChanges, OnDestroy, OnInit, - signal, SimpleChanges, ViewChild, + computed, + effect, + inject, + model, + signal, } from '@angular/core'; import {MatAutocompleteSelectedEvent} from '@angular/material/autocomplete'; import {MatChipInputEvent} from '@angular/material/chips'; import {MatPaginator} from '@angular/material/paginator'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTable, MatTableDataSource} from '@angular/material/table'; -import {isEqual} from 'lodash'; -import {Subscription} from 'rxjs'; -import { - FeedbackTemplateService, - LearningOutcome, - LearningOutcomeService, - TaskDefinition, - TaskService, - Unit, -} from 'src/app/api/models/doubtfire-model'; -import {AlertService} from 'src/app/common/services/alert.service'; -import API_URL from 'src/app/config/constants/apiUrl'; import {FileDownloaderService} from '../file-downloader/file-downloader.service'; import {ConfirmationModalService} from '../modals/confirmation-modal/confirmation-modal.service'; import { @@ -42,9 +42,9 @@ import {CsvUploadModalService} from '../modals/csv-upload-modal/csv-upload-modal import {NestedCsvDownloadModalService} from './nested-csv-download-modal/nested-csv-download-modal.service'; @Component({ - selector: 'f-learning-outcome-editor', - templateUrl: 'learning-outcome-editor.component.html', - standalone: false + selector: 'f-learning-outcome-editor', + templateUrl: 'learning-outcome-editor.component.html', + standalone: false, }) export class LearningOutcomeEditorComponent implements OnChanges, OnInit, AfterViewInit, OnDestroy { @Input() context?: TaskDefinition | Unit; @@ -53,7 +53,7 @@ export class LearningOutcomeEditorComponent implements OnChanges, OnInit, AfterV @ViewChild(MatSort, {static: false}) outcomeSort: MatSort; @ViewChild(MatPaginator, {static: false}) outcomePaginator: MatPaginator; - public outcomeSource = new MatTableDataSource([]); + public outcomeSource: MatTableDataSource = new MatTableDataSource([]); public outcomeColumns: string[] = [ 'abbreviation', 'shortDescription', @@ -143,7 +143,7 @@ export class LearningOutcomeEditorComponent implements OnChanges, OnInit, AfterV } } - ngOnChanges(changes: SimpleChanges): void { + ngOnChanges(_changes: SimpleChanges): void { this.setAbbreviationPrefix(); this.selectedOutcome = null; } diff --git a/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.html b/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.html index a076bde450..d236474d37 100644 --- a/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.html +++ b/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.html @@ -8,7 +8,7 @@

    Download the {{ data.type }} CSV

    -
    +
    diff --git a/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.ts b/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.ts index 92cb486d97..1c072924cf 100644 --- a/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.ts +++ b/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.ts @@ -3,9 +3,9 @@ import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {FileDownloaderService} from '../../file-downloader/file-downloader.service'; @Component({ - selector: 'f-nested-csv-download-modal', - templateUrl: './nested-csv-download-modal.component.html', - standalone: false + selector: 'f-nested-csv-download-modal', + templateUrl: './nested-csv-download-modal.component.html', + standalone: false, }) export class NestedCsvDownloadModalComponent { public includeNested = false; diff --git a/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.service.ts b/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.service.ts index 91e34ff400..9aad82f209 100644 --- a/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.service.ts +++ b/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.service.ts @@ -1,5 +1,5 @@ import {Injectable} from '@angular/core'; -import {MatDialogRef, MatDialog} from '@angular/material/dialog'; +import {MatDialog} from '@angular/material/dialog'; import {NestedCsvDownloadModalComponent} from './nested-csv-download-modal.component'; @Injectable({ @@ -9,7 +9,7 @@ export class NestedCsvDownloadModalService { constructor(public dialog: MatDialog) {} public show(url: string, name: string, type: string) { - const dialogRef: MatDialogRef = this.dialog.open( + this.dialog.open( NestedCsvDownloadModalComponent, { data: {url, name, type}, diff --git a/src/app/common/modals/about-doubtfire-modal/about-dialog-data.ts b/src/app/common/modals/about-doubtfire-modal/about-dialog-data.ts index e85e989082..e94c182df7 100644 --- a/src/app/common/modals/about-doubtfire-modal/about-dialog-data.ts +++ b/src/app/common/modals/about-doubtfire-modal/about-dialog-data.ts @@ -1,7 +1,7 @@ -import { GithubProfile } from './github-profile'; -import { ContributorData } from './contributor-data'; -import { BehaviorSubject } from 'rxjs'; -import { Sort } from '@angular/material/sort'; +import {BehaviorSubject} from 'rxjs'; +import {Sort} from '@angular/material/sort'; +import {ContributorData} from './contributor-data'; +import {GithubProfile} from './github-profile'; /** * The data shared between the AboutDoubtfireModal and its associated @@ -51,7 +51,7 @@ export class AboutDialogData { default: return 0; } - }) + }), ); } } diff --git a/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.component.ts b/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.component.ts index 26bf10dedc..ce01e3d284 100644 --- a/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.component.ts +++ b/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.component.ts @@ -1,19 +1,18 @@ // // Modal to show Doubtfire version info // -import { Injectable, Component, Inject } from '@angular/core'; -import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; -import { AboutDoubtfireModalService } from '../about-doubtfire-modal/about-doubtfire-modal.service'; -import { GithubProfile } from './github-profile'; - -import { MatDialog, MAT_DIALOG_DATA } from '@angular/material/dialog'; -import { AboutDialogData } from './about-dialog-data'; -import { Sort } from '@angular/material/sort'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Component, Inject, Injectable} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialog} from '@angular/material/dialog'; +import {Sort} from '@angular/material/sort'; +import {AboutDoubtfireModalService} from '../about-doubtfire-modal/about-doubtfire-modal.service'; +import {AboutDialogData} from './about-dialog-data'; +import {GithubProfile} from './github-profile'; @Component({ - selector: 'about-doubtfire-dialog', - templateUrl: 'about-doubtfire-modal-content.tpl.html', - standalone: false + selector: 'about-doubtfire-dialog', + templateUrl: 'about-doubtfire-modal-content.tpl.html', + standalone: false, }) export class AboutDoubtfireModalContent { public displayedColumns: string[] = [ @@ -44,7 +43,7 @@ export class AboutDoubtfireModal { constructor( public dialog: MatDialog, private constants: DoubtfireConstants, - private aboutDoubtfireModalService: AboutDoubtfireModalService + private aboutDoubtfireModalService: AboutDoubtfireModalService, ) { this.loaded = false; this.aboutDialogData = new AboutDialogData(); diff --git a/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.service.ts b/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.service.ts index eeadc89f86..90cad12986 100644 --- a/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.service.ts +++ b/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.service.ts @@ -1,9 +1,8 @@ -import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; - -import { GithubProfile } from './github-profile'; -import { ContributorData } from './contributor-data'; -import { AboutDialogData } from './about-dialog-data'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {AboutDialogData} from './about-dialog-data'; +import {ContributorData} from './contributor-data'; +import {GithubProfile} from './github-profile'; interface GithubContributors { login: string; @@ -35,7 +34,10 @@ export class AboutDoubtfireModalService { return this.http.get(`https://api.github.com/users/${handler}`); } - private findOrCreateContributor(data: AboutDialogData, profile: GithubContributors): ContributorData { + private findOrCreateContributor( + data: AboutDialogData, + profile: GithubContributors, + ): ContributorData { let contributor: ContributorData; contributor = data.allContributors.value.find((c) => { return c.login === profile.login; @@ -54,7 +56,7 @@ export class AboutDoubtfireModalService { const contributor = this.findOrCreateContributor(data, profile); contributor[key] = profile.contributions; }); - data.sortData({ active: 'contributions', direction: 'desc' }); + data.sortData({active: 'contributions', direction: 'desc'}); }); } @@ -62,7 +64,7 @@ export class AboutDoubtfireModalService { this.getContributors( 'https://api.github.com/repos/doubtfire-lms/doubtfire.io/contributors', data, - 'ioContributions' + 'ioContributions', ); } @@ -70,7 +72,7 @@ export class AboutDoubtfireModalService { this.getContributors( 'https://api.github.com/repos/doubtfire-lms/doubtfire-deploy/contributors', data, - 'deployContributions' + 'deployContributions', ); } @@ -78,7 +80,7 @@ export class AboutDoubtfireModalService { this.getContributors( 'https://api.github.com/repos/doubtfire-lms/doubtfire-web/contributors', data, - 'webContributions' + 'webContributions', ); } @@ -86,7 +88,7 @@ export class AboutDoubtfireModalService { this.getContributors( 'https://api.github.com/repos/doubtfire-lms/doubtfire-api/contributors', data, - 'apiContributions' + 'apiContributions', ); } } diff --git a/src/app/common/modals/about-doubtfire-modal/contributor-data.ts b/src/app/common/modals/about-doubtfire-modal/contributor-data.ts index 96f805cd2a..31ac133888 100644 --- a/src/app/common/modals/about-doubtfire-modal/contributor-data.ts +++ b/src/app/common/modals/about-doubtfire-modal/contributor-data.ts @@ -21,6 +21,11 @@ export class ContributorData { this.deployContributions = 0; } get totalContributions(): number { - return this.apiContributions + this.webContributions + this.ioContributions + this.deployContributions; + return ( + this.apiContributions + + this.webContributions + + this.ioContributions + + this.deployContributions + ); } } diff --git a/src/app/common/modals/about-doubtfire-modal/github-profile.ts b/src/app/common/modals/about-doubtfire-modal/github-profile.ts index 7e7364ddac..cddb26d0ae 100644 --- a/src/app/common/modals/about-doubtfire-modal/github-profile.ts +++ b/src/app/common/modals/about-doubtfire-modal/github-profile.ts @@ -3,4 +3,4 @@ export interface GithubProfile { name: string; html_url: string; login: string; -} \ No newline at end of file +} diff --git a/src/app/common/modals/calendar-modal/calendar-modal.component.html b/src/app/common/modals/calendar-modal/calendar-modal.component.html index cdd72ca70b..3af81bbb87 100644 --- a/src/app/common/modals/calendar-modal/calendar-modal.component.html +++ b/src/app/common/modals/calendar-modal/calendar-modal.component.html @@ -6,7 +6,9 @@

    Web calendar

    Web calendar
    @if (!webcal) { - - - - } + + + } + @if (webcal) { + Your web calendar is currently {{ webcal.enabled ? 'enabled' : 'disabled' }}. - Your web calendar is currently {{ webcal.enabled ? 'enabled' : 'disabled' }}. - - @if (!webcal.enabled) { -
    -

    - The web calendar displays due dates of your tasks as calendar events in an iCalendar that can be added to any - iCalendar client (e.g. Outlook/Google/iCloud calendar). -

    -
    - } - - - @if (webcal.enabled) { -
    -

    - The web calendar displays due dates of your tasks as calendar events. Use the following URL to subscribe to your - web calendar from your iCalendar client. -

    -
    -
    - {{ webcalUrl }} + @if (!webcal.enabled) { +
    +

    + The web calendar displays due dates of your tasks as calendar events in an iCalendar + that can be added to any iCalendar client (e.g. Outlook/Google/iCloud calendar). +

    -
    - - -
    -
    - + } + - -

    Options

    + @if (webcal.enabled) { +
    +

    + The web calendar displays due dates of your tasks as calendar events. Use the following + URL to subscribe to your web calendar from your iCalendar client. +

    +
    + +
    + + +
    +
    + -
    - Included units in my calendar: -
    + +

    Options

    -
    - - @for (project of includedProjects; track project) { - - {{ project.unit.code }} - cancel - - } @if (excludedProjects.length > 0) { - - add - - @for (project of excludedProjects; track project) { - +
    + Included units in my calendar: +
    + +
    + + @for (project of includedProjects; track project) { + + {{ project.unit.code }} + cancel + } - - - } - -
    - + @if (excludedProjects.length > 0) { + + add + + @for (project of excludedProjects; track project) { + + } + + + } +
    +
    + - - Remind me - - - Time - - - - Unit - - Weeks - Days - Hours - Minutes - - - before each event - - @if ( (!webcal.reminder && newReminderActive) || (webcal.reminder && (newReminderTime !== webcal.reminder.time - || newReminderUnit !== webcal.reminder.unit)) ) { - - - - } + @if ( + (!webcal.reminder && newReminderActive) || + (webcal.reminder && + (newReminderTime !== webcal.reminder.time || + newReminderUnit !== webcal.reminder.unit)) + ) { + + + } + -
    +
    - - Include task start dates in web calendar + + Include task start dates in web calendar -
    - +
    + +
    +
    -
    -
    + } + } - - } +
    diff --git a/src/app/common/modals/calendar-modal/calendar-modal.component.ts b/src/app/common/modals/calendar-modal/calendar-modal.component.ts index f66ed3779a..c9540a5250 100644 --- a/src/app/common/modals/calendar-modal/calendar-modal.component.ts +++ b/src/app/common/modals/calendar-modal/calendar-modal.component.ts @@ -1,15 +1,15 @@ -import {Component, OnInit, Inject, ViewChild, AfterViewInit} from '@angular/core'; -import {MAT_DIALOG_DATA} from '@angular/material/dialog'; -import {MatSlideToggle} from '@angular/material/slide-toggle'; import {Project, ProjectService, Webcal, WebcalService} from 'src/app/api/models/doubtfire-model'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {AfterViewInit, Component, Inject, OnInit, ViewChild} from '@angular/core'; +import {MAT_DIALOG_DATA} from '@angular/material/dialog'; +import {MatSlideToggle} from '@angular/material/slide-toggle'; import {AlertService} from '../../services/alert.service'; @Component({ - selector: 'calendar-modal', - templateUrl: './calendar-modal.component.html', - styleUrls: ['./calendar-modal.component.scss'], - standalone: false + selector: 'calendar-modal', + templateUrl: './calendar-modal.component.html', + styleUrls: ['./calendar-modal.component.scss'], + standalone: false, }) export class CalendarModalComponent implements OnInit, AfterViewInit { @ViewChild('webcalToggle') webcalToggle: MatSlideToggle; @@ -30,7 +30,7 @@ export class CalendarModalComponent implements OnInit, AfterViewInit { private constants: DoubtfireConstants, private alerts: AlertService, private projectService: ProjectService, - @Inject(MAT_DIALOG_DATA) public data: any, + @Inject(MAT_DIALOG_DATA) public data: object, ) {} ngOnInit() { diff --git a/src/app/common/modals/calendar-modal/calendar-modal.service.ts b/src/app/common/modals/calendar-modal/calendar-modal.service.ts index 37ddb1d51c..2f815ab338 100644 --- a/src/app/common/modals/calendar-modal/calendar-modal.service.ts +++ b/src/app/common/modals/calendar-modal/calendar-modal.service.ts @@ -1,6 +1,7 @@ -import { Injectable } from '@angular/core'; -import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog'; -import { CalendarModalComponent } from './calendar-modal.component'; +import {Task} from 'src/app/api/models/task'; +import {Injectable} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import {CalendarModalComponent} from './calendar-modal.component'; @Injectable({ providedIn: 'root', @@ -8,8 +9,7 @@ import { CalendarModalComponent } from './calendar-modal.component'; export class CalendarModalService { constructor(public dialog: MatDialog) {} - public show(task: any) { - let dialogRef: MatDialogRef; - dialogRef = this.dialog.open(CalendarModalComponent); + public show(_task?: Task) { + this.dialog.open(CalendarModalComponent); } } diff --git a/src/app/common/modals/comments-modal/comments-modal.component.html b/src/app/common/modals/comments-modal/comments-modal.component.html index 4236c93c2d..c4e73f0de0 100644 --- a/src/app/common/modals/comments-modal/comments-modal.component.html +++ b/src/app/common/modals/comments-modal/comments-modal.component.html @@ -1,7 +1,11 @@
    @if (taskComment.commentType === 'image') { - + Image attachment } @else if (taskComment.commentType === 'pdf') { - + }
    diff --git a/src/app/common/modals/comments-modal/comments-modal.component.ts b/src/app/common/modals/comments-modal/comments-modal.component.ts index ebad5e1695..671110b292 100644 --- a/src/app/common/modals/comments-modal/comments-modal.component.ts +++ b/src/app/common/modals/comments-modal/comments-modal.component.ts @@ -1,6 +1,6 @@ -import {Component, Input, Inject, OnInit} from '@angular/core'; -import {MAT_DIALOG_DATA} from '@angular/material/dialog'; import {TaskComment} from 'src/app/api/models/doubtfire-model'; +import {Component, Inject, Input, OnInit} from '@angular/core'; +import {MAT_DIALOG_DATA} from '@angular/material/dialog'; export interface CommentsModalData { comment: TaskComment; @@ -8,10 +8,10 @@ export interface CommentsModalData { } @Component({ - selector: 'comments-modal', - templateUrl: './comments-modal.component.html', - styleUrls: ['./comments-modal.component.scss'], - standalone: false + selector: 'comments-modal', + templateUrl: './comments-modal.component.html', + styleUrls: ['./comments-modal.component.scss'], + standalone: false, }) export class CommentsModalComponent implements OnInit { @Input() taskComment: TaskComment; diff --git a/src/app/common/modals/comments-modal/comments-modal.service.ts b/src/app/common/modals/comments-modal/comments-modal.service.ts index 353c9c6c37..c1a7d3e013 100644 --- a/src/app/common/modals/comments-modal/comments-modal.service.ts +++ b/src/app/common/modals/comments-modal/comments-modal.service.ts @@ -1,6 +1,6 @@ +import {TaskComment} from 'src/app/api/models/doubtfire-model'; import {Injectable} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; -import {TaskComment} from 'src/app/api/models/doubtfire-model'; import {CommentsModalComponent, CommentsModalData} from './comments-modal.component'; @Injectable({ diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts b/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts index 59607b84c2..dea3e5fad4 100644 --- a/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts +++ b/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts @@ -1,6 +1,6 @@ -import {Component, OnInit, Input, Inject} from '@angular/core'; -import {AlertService} from '../../services/alert.service'; +import {Component, Inject, Input, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {AlertService} from '../../services/alert.service'; export interface ConfirmationModalData { title: string; @@ -12,10 +12,10 @@ export interface ConfirmationModalData { } @Component({ - selector: 'confirmation-modal', - templateUrl: './confirmation-modal.component.html', - styleUrls: ['./confirmation-modal.component.scss'], - standalone: false + selector: 'confirmation-modal', + templateUrl: './confirmation-modal.component.html', + styleUrls: ['./confirmation-modal.component.scss'], + standalone: false, }) export class ConfirmationModalComponent implements OnInit { @Input() title: string; diff --git a/src/app/common/modals/csv-result-modal/csv-result-modal.component.html b/src/app/common/modals/csv-result-modal/csv-result-modal.component.html index 1de2d91f66..a08ab98d77 100644 --- a/src/app/common/modals/csv-result-modal/csv-result-modal.component.html +++ b/src/app/common/modals/csv-result-modal/csv-result-modal.component.html @@ -70,7 +70,7 @@

    {{ data.title }}

    } - + @if (dataSource.data.length > 0) { ([]); - private columnKeyById = new Map(); + public dataSource: MatTableDataSource = new MatTableDataSource([]); + private columnKeyById: Map = new Map(); @ViewChild(MatPaginator) paginator?: MatPaginator; - public readonly csvResponseSelections: { key: CsvResultSelection; label: string }[] = [ + public readonly csvResponseSelections: {key: CsvResultSelection; label: string}[] = [ {key: 'success', label: 'Success'}, {key: 'errors', label: 'Errors'}, {key: 'ignored', label: 'Ignored'}, @@ -115,7 +111,7 @@ export class CsvResultModalComponent implements AfterViewInit { private rebuildTableData(): void { const items = this.itemData(this.activeCsvResponseSelection); const rowObjects = items.map((item) => this.toRowObject(item.row)); - const keyCounts = new Map(); + const keyCounts: Map = new Map(); rowObjects.forEach((rowObject) => { if (!rowObject) { @@ -186,9 +182,7 @@ export class CsvResultModalComponent implements AfterViewInit { if (Array.isArray(row)) { const entries = row.filter( (entry): entry is [string, unknown] => - Array.isArray(entry) && - entry.length >= 2 && - typeof entry[0] === 'string', + Array.isArray(entry) && entry.length >= 2 && typeof entry[0] === 'string', ); if (entries.length === row.length && entries.length > 0) { diff --git a/src/app/common/modals/csv-result-modal/csv-result-modal.service.ts b/src/app/common/modals/csv-result-modal/csv-result-modal.service.ts index b73eea3341..20a41f3fb8 100644 --- a/src/app/common/modals/csv-result-modal/csv-result-modal.service.ts +++ b/src/app/common/modals/csv-result-modal/csv-result-modal.service.ts @@ -1,7 +1,7 @@ import {Injectable} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; -import {CsvResultModalComponent} from './csv-result-modal.component'; import {AlertService} from '../../services/alert.service'; +import {CsvResultModalComponent} from './csv-result-modal.component'; export interface CsvRow { row: unknown; diff --git a/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.ts b/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.ts index 6e3cfffaed..76d58e1ac6 100644 --- a/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.ts +++ b/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.ts @@ -6,9 +6,7 @@ export interface CsvUploadFileSpec { type: string; } -export interface CsvUploadFileMap { - [uploadName: string]: CsvUploadFileSpec; -} +export type CsvUploadFileMap = Record; export interface CsvUploadModalData { title: string; @@ -19,10 +17,10 @@ export interface CsvUploadModalData { } @Component({ - selector: 'f-csv-upload-modal', - templateUrl: './csv-upload-modal.component.html', - styleUrls: ['./csv-upload-modal.component.scss'], - standalone: false + selector: 'f-csv-upload-modal', + templateUrl: './csv-upload-modal.component.html', + styleUrls: ['./csv-upload-modal.component.scss'], + standalone: false, }) export class CsvUploadModalComponent { constructor( diff --git a/src/app/common/modals/date-change-modal/task-date-slider.component.html b/src/app/common/modals/date-change-modal/task-date-slider.component.html index a67015f78b..5cd73218b1 100644 --- a/src/app/common/modals/date-change-modal/task-date-slider.component.html +++ b/src/app/common/modals/date-change-modal/task-date-slider.component.html @@ -70,13 +70,13 @@
    @if (editMode) { @if (afterDeadline()) { -
    + + + +
    Name @if (editing(group)) { - + } @else { @@ -74,7 +74,7 @@ Tutorial @if (editing(group)) { - + @for (tutorial of unit.tutorials; track tutorial) { {{ tutorial.abbreviation }} @@ -96,7 +96,7 @@ @if (unitRole) { @if (editing(group)) { - + @if (isPartOfGroup(project, group)) { -
    Joined
    +
    Joined
    } @else if (project && group.hasSpace() && selectedGroupSet.allowStudentsToManageGroups) { -
    +
    @if (!group.locked && !selectedGroupSet.locked) {
    } -

    Units you teach

    -
    - @if (!unitRole.unit.teachingPeriod || unitRole.unit.teachingPeriod?.active) { -
    - - - {{ unitRole.unit?.name }} - {{ unitRole.unit?.code }} - - - - - - - {{ unitRole.teachingPeriod?.name || showDate(unitRole.unit.startDate) }} - - - {{ unitRole.role }} - - - - - - -
    - } -
    + @for (unitRole of unitRoles | isActiveUnitRole; track unitRole) { +
    + @if (!unitRole.unit.teachingPeriod || unitRole.unit.teachingPeriod?.active) { +
    + + + {{ unitRole.unit?.name }} + {{ unitRole.unit?.code }} + + + + + + + {{ unitRole.teachingPeriod?.name || showDate(unitRole.unit.startDate) }} + + + {{ unitRole.role }} + + + + + + +
    + } +
    + } Units you teach
    + @if (unitRoles.length && projects?.length) { + + }

    Enrolled units

    diff --git a/src/app/home/states/home/home.component.ts b/src/app/home/states/home/home.component.ts index 5ff49cd0e5..7e1d2ba99f 100644 --- a/src/app/home/states/home/home.component.ts +++ b/src/app/home/states/home/home.component.ts @@ -1,16 +1,16 @@ -import {Component, Inject, OnDestroy, OnInit} from '@angular/core'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Subscription} from 'rxjs'; +import {Project, UnitRole, User, UserService} from 'src/app/api/models/doubtfire-model'; import {DateService} from 'src/app/common/services/date.service'; -import {Router} from '@angular/router'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; -import {Project, UnitRole, User, UserService} from 'src/app/api/models/doubtfire-model'; -import {Subscription} from 'rxjs'; +import {Component, Inject, OnDestroy, OnInit} from '@angular/core'; +import {Router} from '@angular/router'; @Component({ - selector: 'home', - templateUrl: 'home.component.html', - styleUrls: ['home.component.scss'], - standalone: false + selector: 'home', + templateUrl: 'home.component.html', + styleUrls: ['home.component.scss'], + standalone: false, }) export class HomeComponent implements OnInit, OnDestroy { projects: Project[]; @@ -52,7 +52,6 @@ export class HomeComponent implements OnInit, OnDestroy { this.subscriptions.push( this.globalState.unitRolesSubject.subscribe({ next: (unitRoles) => this.unitRolesLoaded(unitRoles), - error: (err) => {}, }), ); @@ -62,7 +61,6 @@ export class HomeComponent implements OnInit, OnDestroy { projects = projects.filter((project) => project.unit.myRole === 'Student'); this.projectsLoaded(projects); }, - error: (err) => {}, }), ); diff --git a/src/app/home/states/lti-dashboard/lti-dashboard.component.html b/src/app/home/states/lti-dashboard/lti-dashboard.component.html index 0a31177529..880914025d 100644 --- a/src/app/home/states/lti-dashboard/lti-dashboard.component.html +++ b/src/app/home/states/lti-dashboard/lti-dashboard.component.html @@ -1,18 +1,18 @@ -
    -
    -
    +
    +
    +

    OnTrack

    @if (isLoading) { @if (unauthorised) { -
    +
    An error occurred. Please refresh the page.
    } @else { @@ -28,7 +28,7 @@

    OnTrack

    matTooltip="Sync enrolments" matTooltipPosition="above" aria-label="" - class="w-[60px] h-[60px] relative" + class="relative h-[60px] w-[60px]" [ngClass]="{'bg-gray-300': isSyncingEnrolments}" color="default" (click)="syncEnrolments()" @@ -36,7 +36,7 @@

    OnTrack

    @if (isSyncingEnrolments) { } people @@ -47,7 +47,7 @@

    OnTrack

    matTooltip="Sync grades" matTooltipPosition="above" aria-label="" - class="w-[60px] h-[60px] relative" + class="relative h-[60px] w-[60px]" [ngClass]="{'bg-gray-300': isSyncingGrades}" color="default" (click)="syncStudentsGrades()" @@ -57,7 +57,7 @@

    OnTrack

    @if (isSyncingGrades) { } @@ -67,19 +67,19 @@

    OnTrack

    mat-fab extended color="primary" - class="h-[50px] my-3 w-full max-w-lg" + class="my-3 h-[50px] w-full max-w-lg" (click)="launchApplication()" target="_blank" > rocket_launch Launch {{ linkedUnit ? linkedUnit.code : 'OnTrack' }} -
    +
    @if (linkedUnit) { {{ linkedUnit.code }} — {{ linkedUnit.name }} @if (currentUser?.systemRole === 'Convenor' || currentUser?.systemRole === 'Admin') {
    - } @@ -88,7 +88,7 @@

    OnTrack

    @if (currentUser?.systemRole === 'Convenor' || currentUser?.systemRole === 'Admin') {
    - } @else { diff --git a/src/app/home/states/lti-dashboard/lti-dashboard.component.ts b/src/app/home/states/lti-dashboard/lti-dashboard.component.ts index 4ae22095bc..222b359d9a 100644 --- a/src/app/home/states/lti-dashboard/lti-dashboard.component.ts +++ b/src/app/home/states/lti-dashboard/lti-dashboard.component.ts @@ -1,5 +1,3 @@ -import {AfterViewInit, Component, Input} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; import {ProjectService, User} from 'src/app/api/models/doubtfire-model'; import {Unit} from 'src/app/api/models/unit'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; @@ -10,12 +8,14 @@ import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal import {CsvResultModalService} from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {AfterViewInit, Component, Input} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; @Component({ - selector: 'f-lti-dashboard', - templateUrl: 'lti-dashboard.component.html', - styleUrls: ['lti-dashboard.component.scss'], - standalone: false + selector: 'f-lti-dashboard', + templateUrl: 'lti-dashboard.component.html', + styleUrls: ['lti-dashboard.component.scss'], + standalone: false, }) export class LtiDashboardComponent implements AfterViewInit { constructor( diff --git a/src/app/home/states/lti-unit-link/lti-unit-link.component.html b/src/app/home/states/lti-unit-link/lti-unit-link.component.html index 1020993ed1..9975e20cb0 100644 --- a/src/app/home/states/lti-unit-link/lti-unit-link.component.html +++ b/src/app/home/states/lti-unit-link/lti-unit-link.component.html @@ -1,11 +1,11 @@ -
    -
    -
    +
    +
    +

    OnTrack

    @@ -13,12 +13,12 @@

    OnTrack

    @if (loadingUnits) {

    Loading...

    } @else if (!activeUnits.length) { -

    +

    You must already be a Convenor or Admin to link a unit. You are not currently assigned to any units.

    } @else { -

    +

    Students will be automatically enrolled in this unit when they launch the OnTrack tool from this course.

    diff --git a/src/app/home/states/lti-unit-link/lti-unit-link.component.ts b/src/app/home/states/lti-unit-link/lti-unit-link.component.ts index 492151ab83..9eb9a5ff1f 100644 --- a/src/app/home/states/lti-unit-link/lti-unit-link.component.ts +++ b/src/app/home/states/lti-unit-link/lti-unit-link.component.ts @@ -1,5 +1,3 @@ -import {AfterViewInit, Component, Input} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; import {CreateNewUnitModal} from 'src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component'; import {Unit} from 'src/app/api/models/unit'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; @@ -8,12 +6,14 @@ import {UnitService} from 'src/app/api/services/unit.service'; import {UserService} from 'src/app/api/services/user.service'; import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {AfterViewInit, Component, Input} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; @Component({ - selector: 'f-lti-unit-link', - templateUrl: 'lti-unit-link.component.html', - styleUrls: ['lti-unit-link.component.scss'], - standalone: false + selector: 'f-lti-unit-link', + templateUrl: 'lti-unit-link.component.html', + styleUrls: ['lti-unit-link.component.scss'], + standalone: false, }) export class LtiUnitLinkComponent implements AfterViewInit { constructor( @@ -120,7 +120,7 @@ export class LtiUnitLinkComponent implements AfterViewInit { ); this.loadingUnits = false; }, - error: (error) => { + error: (_error) => { this.alertsService.error(`Failed to fetch units`, 6000); }, }); diff --git a/src/app/legacy-route-placeholder.component.html b/src/app/legacy-route-placeholder.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/legacy-route-placeholder.component.scss b/src/app/legacy-route-placeholder.component.scss new file mode 100644 index 0000000000..cc36f78bfa --- /dev/null +++ b/src/app/legacy-route-placeholder.component.scss @@ -0,0 +1,3 @@ +:host { + display: none; +} diff --git a/src/app/legacy-route-placeholder.component.ts b/src/app/legacy-route-placeholder.component.ts index d3e62d9fad..a08dfc603c 100644 --- a/src/app/legacy-route-placeholder.component.ts +++ b/src/app/legacy-route-placeholder.component.ts @@ -1,15 +1,9 @@ import {Component} from '@angular/core'; @Component({ - selector: 'legacy-route-placeholder', - template: '', - styles: [ - ` - :host { - display: none; - } - `, - ], - standalone: false + selector: 'legacy-route-placeholder', + templateUrl: './legacy-route-placeholder.component.html', + styleUrl: './legacy-route-placeholder.component.scss', + standalone: false, }) export class LegacyRoutePlaceholderComponent {} diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html index b450dfad58..a4c5164702 100644 --- a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html +++ b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html @@ -1,8 +1,8 @@ @if (project$ | async; as project) { -
    +
    - +

    @@ -13,10 +13,10 @@

    - + - -

    Targetting

    + +

    Targetting

    info @@ -37,12 +37,12 @@

    Targetting

    - + Your progress -
    +
    ; @@ -37,7 +37,7 @@ export class ProjectProgressDashboardComponent implements OnInit { protected targetGradeClicked(grade: number): void { this.project.targetGrade = grade; this.projectService.update(this.project).subscribe({ - next: (project) => { + next: (_project) => { this.alertService.success('Target grade updated'); }, error: (error) => { diff --git a/src/app/projects/project.resolver.ts b/src/app/projects/project.resolver.ts index d5f16b2d0e..e588b4f096 100644 --- a/src/app/projects/project.resolver.ts +++ b/src/app/projects/project.resolver.ts @@ -1,8 +1,8 @@ -import {ResolveFn} from '@angular/router'; import {Observable} from 'rxjs'; import {Project, ProjectService} from 'src/app/api/models/doubtfire-model'; -import {GlobalStateService, ViewType} from './states/index/global-state.service'; import {inject} from '@angular/core'; +import {ResolveFn} from '@angular/router'; +import {GlobalStateService, ViewType} from './states/index/global-state.service'; export const resolveProject: ResolveFn = (route, state) => { const projectService = inject(ProjectService); diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html index 66174425af..93df2d92d1 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html @@ -1,21 +1,21 @@ -
    -
    -

    +
    +
    +

    Progress Dashboard @if (tutor) { for {{ project.student.name }} }

    -
    +
    -
    - +
    +
    - + Target Grade @@ -23,7 +23,7 @@

    - +
    Select Target Grade @@ -41,7 +41,7 @@

    To change your target grade, use the - + Task Planner
    @@ -55,45 +55,45 @@

    -
    +
    -
    +
    -
    -

    Progress Burndown

    -

    +

    +

    Progress Burndown

    +

    The burndown chart shows how much work remains for you to achieve your target grade.

    -
    +
    -
    +
    Aim to keep your - Complete + Complete line close to or ahead of the - Target + Target line to keep on track.
    -
    +
    -
    -

    Task Statuses

    -

    +

    +

    Task Statuses

    +

    Breakdown summary of each of your task statuses.

    -
    +
    (); + @Output() doUpdateTargetGrade: EventEmitter = new EventEmitter(); tutor: boolean; grades = { diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts index 3bb062d0a3..2703e333bd 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts @@ -1,11 +1,11 @@ -import {Component, Input} from '@angular/core'; import {Project} from 'src/app/api/models/project'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-task-planner-card', - templateUrl: './task-planner-card.component.html', - styleUrl: './task-planner-card.component.scss', - standalone: false + selector: 'f-task-planner-card', + templateUrl: './task-planner-card.component.html', + styleUrl: './task-planner-card.component.scss', + standalone: false, }) export class TaskPlannerCardComponent { @Input() project: Project; diff --git a/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html b/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html index 39825c6d7b..287515fb59 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html +++ b/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.html @@ -1,14 +1,14 @@ -
    -
    +
    +
    Create Portfolio
    - person + person
    Create and submit your portfolio
    diff --git a/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.ts b/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.ts index 56c0b423d3..bf1ce95251 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.ts +++ b/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.ts @@ -1,11 +1,11 @@ +import {Project, Task} from 'src/app/api/models/doubtfire-model'; import {Component, Input} from '@angular/core'; -import { Project, Task } from 'src/app/api/models/doubtfire-model'; @Component({ - selector: 'create-portfolio-task-list-item', - templateUrl: 'create-portfolio-task-list-item.component.html', - styleUrls: ['create-portfolio-task-list-item.component.scss'], - standalone: false + selector: 'create-portfolio-task-list-item', + templateUrl: 'create-portfolio-task-list-item.component.html', + styleUrls: ['create-portfolio-task-list-item.component.scss'], + standalone: false, }) export class CreatePortfolioTaskListItemComponent { @Input() setSelectedTask: Task; diff --git a/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.html b/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.html index 763e84665a..46d732c34a 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.html +++ b/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.html @@ -1 +1,2 @@ -

    student-task-list works!

    , +

    student-task-list works!

    +, diff --git a/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.ts b/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.ts index 034627414a..fae6805595 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.ts +++ b/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.ts @@ -1,18 +1,11 @@ -import { CommonModule } from '@angular/common'; -import { ChangeDetectionStrategy, Component, type OnInit } from '@angular/core'; +import {ChangeDetectionStrategy, Component} from '@angular/core'; @Component({ selector: 'f-student-task-list', standalone: true, - imports: [ - CommonModule, - ], + imports: [], templateUrl: './student-task-list.component.html', styleUrl: './student-task-list.component.css', changeDetection: ChangeDetectionStrategy.OnPush, }) -export class StudentTaskListComponent implements OnInit { - - ngOnInit(): void { } - -} +export class StudentTaskListComponent {} diff --git a/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.tpl.html b/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.tpl.html index 93573d01c9..7b18638d41 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.tpl.html +++ b/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.tpl.html @@ -28,8 +28,8 @@

    {{task.definition.name}}

    {{task.definition.abbreviation}} - - {{gradeNames[task.definition.targetGrade]}} Task + > + {{task.definition.abbreviation}} - {{gradeNames[task.definition.targetGrade]}} Task {{task.timeToStart()}}{{task.definition.n {{task.numNewComments}} - +

    - {{task.gradeDesc()}} + + {{task.gradeDesc()}} + {{task.qualityQts}}{{task.definition.maxQualityPts}} - + {{task.definition.n > - + !
    @@ -77,7 +88,10 @@

    {{task.definition.n -
  • +
  • No tasks to display.
  • diff --git a/src/app/projects/states/dashboard/directives/student-task-list/task-list-item/task-list-item.component.ts b/src/app/projects/states/dashboard/directives/student-task-list/task-list-item/task-list-item.component.ts index d6f86ce886..c521cdbfb1 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/task-list-item/task-list-item.component.ts +++ b/src/app/projects/states/dashboard/directives/student-task-list/task-list-item/task-list-item.component.ts @@ -1,19 +1,19 @@ -import {Component, Input, OnInit} from '@angular/core'; import {Task} from 'src/app/api/models/doubtfire-model'; import {GradeService} from 'src/app/common/services/grade.service'; +import {Component, Input, OnInit} from '@angular/core'; @Component({ - selector: 'task-list-item', - templateUrl: 'task-list-item.component.html', - styleUrls: ['task-list-item.component.scss'], - standalone: false + selector: 'task-list-item', + templateUrl: 'task-list-item.component.html', + styleUrls: ['task-list-item.component.scss'], + standalone: false, }) export class TaskListItemComponent implements OnInit { @Input() task: Task; - @Input() setSelectedTask: any; - @Input() isSelectedTask: any; + @Input() setSelectedTask: (task: Task) => void; + @Input() isSelectedTask: (task: Task) => boolean; - public gradeNames: {}; + public gradeNames: GradeService['grades']; constructor(private gs: GradeService) {} diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html index 5636823212..781e0aa244 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.html @@ -1,4 +1,4 @@ -
    +
    comment

    Discussion Prompts for {{ project?.student?.name }}

    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts index 7acb2b19d7..43ae248427 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts @@ -1,10 +1,10 @@ import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-discussion-prompts-view', - templateUrl: './discussion-prompts-view.component.html', - styleUrls: ['./discussion-prompts-view.component.scss'], - standalone: false + selector: 'f-discussion-prompts-view', + templateUrl: './discussion-prompts-view.component.html', + styleUrls: ['./discussion-prompts-view.component.scss'], + standalone: false, }) export class DiscussionPromptsViewComponent { @Input() project; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html index f92fd644e5..92a3039c43 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html @@ -1,4 +1,4 @@ -
    +
    comment

    Staff Notes for {{ project?.student?.name }}

    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.ts index b10909f0f9..7f7d38039d 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.ts @@ -1,10 +1,10 @@ import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-staff-notes-view', - templateUrl: './staff-notes-view.component.html', - styleUrls: ['./staff-notes-view.component.scss'], - standalone: false + selector: 'f-staff-notes-view', + templateUrl: './staff-notes-view.component.html', + styleUrls: ['./staff-notes-view.component.scss'], + standalone: false, }) export class StaffNotesViewComponent { @Input() project; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.html index 54ca0810cb..7d56d7a386 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.html @@ -1,4 +1,7 @@ - + Assessment Information diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.spec.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.spec.ts index d9dc27547d..d1b100354a 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.spec.ts @@ -1,6 +1,5 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { TaskAssessmentCardComponent } from './task-assessment-card.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {TaskAssessmentCardComponent} from './task-assessment-card.component'; describe('TaskAssessmentCardComponent', () => { let component: TaskAssessmentCardComponent; @@ -8,9 +7,8 @@ describe('TaskAssessmentCardComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ TaskAssessmentCardComponent ] - }) - .compileComponents(); + declarations: [TaskAssessmentCardComponent], + }).compileComponents(); fixture = TestBed.createComponent(TaskAssessmentCardComponent); component = fixture.componentInstance; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.ts index 10204c7956..f8eb8557c2 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.ts @@ -1,16 +1,19 @@ -import { Component, Input } from '@angular/core'; -import { Task } from 'src/app/api/models/task'; -import { TaskService } from 'src/app/api/services/task.service'; -import { GradeService } from 'src/app/common/services/grade.service'; +import {Task} from 'src/app/api/models/task'; +import {TaskService} from 'src/app/api/services/task.service'; +import {GradeService} from 'src/app/common/services/grade.service'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-task-assessment-card', - templateUrl: './task-assessment-card.component.html', - styleUrls: ['./task-assessment-card.component.scss'], - standalone: false + selector: 'f-task-assessment-card', + templateUrl: './task-assessment-card.component.html', + styleUrls: ['./task-assessment-card.component.scss'], + standalone: false, }) export class TaskAssessmentCardComponent { - constructor(private taskService: TaskService, private gradeService: GradeService) {} + constructor( + private taskService: TaskService, + private gradeService: GradeService, + ) {} @Input() task: Task; gradeNames = this.gradeService.grades; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.tpl.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.tpl.html index c849365e0f..0aa6c58092 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.tpl.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.tpl.html @@ -1,4 +1,7 @@ -
    +

    Assessment Information

    @@ -7,38 +10,38 @@

    Assessment Information

    This task {{assessmentCards.hasBeenGraded ? 'has been' : 'will be'}} assigned a grade

    - This task will be graded against a grade standard. Your work will - be assessed and assigned a grade according to a Pass, Credit, - Distinction or High Distinction standard. + This task will be graded against a grade standard. Your work will be assessed and assigned + a grade according to a Pass, Credit, Distinction or High Distinction standard.

    Advice for achieving a {{task.project.targetGradeWord}}

    - As you are attempting to achieve a {{task.project.targetGradeWord}} in this unit, - you should attempt to achieve a {{task.project.targetGradeWord}} grade - on this task. Ask your tutor to find out more on what they are looking for when they are assessing - this work to a specific grade. + As you are attempting to achieve a {{task.project.targetGradeWord}} in this unit, you + should attempt to achieve a {{task.project.targetGradeWord}} grade on + this task. Ask your tutor to find out more on what they are looking for when they are + assessing this work to a specific grade.

    -
    +
    +
    Your tutor has marked you on this task to a {{task.gradeWord}} standard. -
    -
    -
    +
    + +
    + +
    This task will be assessed on a scale to {{task.definition.maxQualityPts}} - - This task has been assessed for quality - + This task has been assessed for quality

    This task will be graded against a quality scale from - 0 to {{task.definition.maxQualityPts}}. Your work will assessed - and assigned a star rating based on the quality of your submission. + 0 to {{task.definition.maxQualityPts}}. Your work will assessed and + assigned a star rating based on the quality of your submission.

    max="task.definition.maxQualityPts" state-on="'fa fa-star rating-outline'" state-off="'fa fa-star rating-disabled'" - readonly="true"> + readonly="true" + >

    You have been awarded out @@ -55,6 +59,9 @@

    avaliable points for this task.

    -
    -
    -
    +
    + +
    + +

    + diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html index b7548c3c90..acddda621a 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html @@ -1,6 +1,6 @@ -
    +
    {{ taskDef?.name }}
    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.ts index 0d4847623e..f01cb5131d 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.ts @@ -1,14 +1,13 @@ -import {Component, Input, Inject, EventEmitter, Output} from '@angular/core'; - import {Task, TaskDefinition, Unit} from 'src/app/api/models/doubtfire-model'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {GradeService} from 'src/app/common/services/grade.service'; +import {Component, EventEmitter, Inject, Input, Output} from '@angular/core'; @Component({ - selector: 'f-task-description-card', - templateUrl: 'task-description-card.component.html', - styleUrls: ['task-description-card.component.scss'], - standalone: false + selector: 'f-task-description-card', + templateUrl: 'task-description-card.component.html', + styleUrls: ['task-description-card.component.scss'], + standalone: false, }) export class TaskDescriptionCardComponent { @Output() switchView$: EventEmitter = new EventEmitter(); @@ -17,7 +16,10 @@ export class TaskDescriptionCardComponent { @Input() taskDef: TaskDefinition; @Input() unit: Unit; - public grades: {names: any; acronyms: any}; + public grades: { + names: GradeService['grades']; + acronyms: GradeService['gradeAcronyms']; + }; constructor( private GradeService: GradeService, diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html index 48fb963ad2..1bd23719a9 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html @@ -56,10 +56,12 @@ @if (task?.betweenDueDateAndDeadlineDate()) { - warning @if (flexibleDatesEnabled) { - Past Target Date By {{ task?.timePastDueDateDescription() }} + Past Target Date By {{ task?.timePastDueDateDescription() }} } @else { Past Due Date By {{ task?.timePastDueDateDescription() }} } @@ -116,7 +118,7 @@ @if (task?.isPastDeadline()) { - error Passed Due Date By {{ task?.timePastDueDateDescription() }} { let component: TaskDueCardComponent; @@ -8,9 +7,8 @@ describe('TaskDueCardComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ TaskDueCardComponent ] - }) - .compileComponents(); + declarations: [TaskDueCardComponent], + }).compileComponents(); fixture = TestBed.createComponent(TaskDueCardComponent); component = fixture.componentInstance; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.ts index 7c67cb9f57..6a491c6a67 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.ts @@ -1,17 +1,14 @@ -import {Component, Input, OnInit} from '@angular/core'; import {Task} from 'src/app/api/models/task'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-task-due-card', - templateUrl: './task-due-card.component.html', - styleUrls: ['./task-due-card.component.scss'], - standalone: false + selector: 'f-task-due-card', + templateUrl: './task-due-card.component.html', + styleUrls: ['./task-due-card.component.scss'], + standalone: false, }) -export class TaskDueCardComponent implements OnInit { +export class TaskDueCardComponent { @Input() task: Task; - constructor() {} - - ngOnInit(): void {} public get flexibleDatesEnabled(): boolean { return this.task?.unit?.allowFlexibleDates; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.tpl.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.tpl.html index 6f14f303b2..a4ea4b1999 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.tpl.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.tpl.html @@ -1,39 +1,47 @@ -
    -
    +
    + +
    +

    Aim To Complete Soon - Due in {{task.timeUntilDueDateDescription()}}

    -
    +
    +

    - This task's due date is {{task.localDueDateString()}}. - You should aim to complete this task before then to keep your progress on track. + This task's due date is {{task.localDueDateString()}}. You should aim to + complete this task before then to keep your progress on track.

    -
    +
    +

    - This task's due date is {{task.localDueDateString()}}. - Make sure to discuss this task with your tutor as soon as possible. + This task's due date is {{task.localDueDateString()}}. Make sure to + discuss this task with your tutor as soon as possible.

    - Tasks are only considered Completed once your tutor has Discussed your work - with you. + Tasks are only considered Completed once your tutor has + Discussed your work with you.

    -
    +
    +

    Past Due Date By {{task.timePastDueDateDescription()}}

    -
    +
    +

    - You should have completed this task by {{task.localDueDateString()}}. - Try and finish it as soon as possible to avoid falling behind. As you will submit this - task after the deadline for feedback, it will not be reviewed by a tutor and it is now - your sole responsibility to ensure that this submission meets the required standard. - The task will be assessed as part of the portfolio. + You should have completed this task by {{task.localDueDateString()}}. Try + and finish it as soon as possible to avoid falling behind. As you will submit this task + after the deadline for feedback, it will not be reviewed by a tutor and it is now your + sole responsibility to ensure that this submission meets the required standard. The task + will be assessed as part of the portfolio.

    Aim to submit future tasks before the deadline to make good use of the opportunity to @@ -41,11 +49,12 @@

    Past Due Date By {{task.timePastDueDateDescription()}}

    submission meets all the requirements.

    -
    +
    +

    You should have completed this task by {{task.localDueDateString()}}. - Make sure to discuss this task with your tutor as soon as possible. If this task remains on - this state for an extended period, it will be marked as Time Exceeded. + Make sure to discuss this task with your tutor as soon as possible. If this task remains + on this state for an extended period, it will be marked as Time Exceeded.

    Tasks are only considered completed once your tutor has @@ -53,33 +62,37 @@

    Past Due Date By {{task.timePastDueDateDescription()}}

    -
    +
    +

    Passed Due Date By {{task.timePastDueDateDescription()}}

    -
    +
    +

    You should have completed this task by {{task.localDueDateString()}}. - This task is now past the deadline and will be marked as Time Exceeded when submitted. You should - consult with the unit assessment details to determine the impact of failing to complete this task within - the allocated time. + This task is now past the deadline and will be marked as Time Exceeded when + submitted. You should consult with the unit assessment details to determine the impact of + failing to complete this task within the allocated time.

    -
    +
    +

    You should have completed this task by {{task.localDueDateString()}}. Make sure to discuss this task with your tutor as soon as possible.

    - Tasks are only considered Completed once it demonstrates the required standard, and it is - discussed with your tutor. + Tasks are only considered Completed once it demonstrates the required + standard, and it is discussed with your tutor.

    -
    +
    +

    Wait for Tutor Feedback

    @@ -87,8 +100,10 @@

    Wait for Tutor Feedback

    You have submitted this task and should now wait for feedback from your tutor. - Do not re-upload new files at this time as the status will be changed to - Time Exceeded. + Do not re-upload new files at this time as the status will be changed to + Time Exceeded.

    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.html index 31a7a8028b..6f0ae7a7bf 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.html @@ -10,10 +10,10 @@ @for (ilo of learningOutcomes; track ilo) { - - + + - - - - -
    {{ ilo.abbreviation }}
    {{ ilo.abbreviation }} {{ ilo.fullOutcomeDescription }} + @for (outcome of getLinkedOutcomes(ilo); track outcome.abbreviation) { {{ outcome.abbreviation diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.ts index 803e7ea998..719b99cd58 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.ts @@ -1,14 +1,14 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; import {LearningOutcome} from 'src/app/api/models/learning-outcome'; import {Project} from 'src/app/api/models/project'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; +import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; @Component({ - selector: 'f-task-ilos-card', - templateUrl: './task-ilos-card.component.html', - styleUrls: ['./task-ilos-card.component.scss'], - standalone: false + selector: 'f-task-ilos-card', + templateUrl: './task-ilos-card.component.html', + styleUrls: ['./task-ilos-card.component.scss'], + standalone: false, }) export class TaskIlosCardComponent implements OnInit, OnChanges { @Input() iloContextType: 'Unit' | 'TaskDefinition' | 'Course' | 'Global'; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html index ae35bec796..7b30d385d6 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html @@ -16,20 +16,18 @@

    -
    +
    @if (isLoading) { -
    +
    } @else if (errorMessage) { -
    +
    {{ errorMessage }}
    } @else if (compareMode) { @if (archiveBlob && comparedArchiveBlob) { -
    +
    [ngTemplateOutletContext]="{ number: data.assessmentNumber, isMostRecent: data.assessmentIsMostRecent, - timestamp: data.assessment.timestamp + timestamp: data.assessment.timestamp, }" > [ngTemplateOutletContext]="{ number: data.comparedWithNumber, isMostRecent: data.comparedWithIsMostRecent, - timestamp: data.comparedWith?.timestamp + timestamp: data.comparedWith?.timestamp, }" > @if (primaryArchiveParsed) {
    @if (!bothSelectionsReady) { -
    +
    Select a file in both submissions to compare.
    } @else if (canShowDiffEditor) { -
    +
    -
    +
    {{ primarySelectedFile?.path ?? primarySelectedFile?.name }}
    -
    +
    {{ comparedSelectedFile?.path ?? comparedSelectedFile?.name }}
    } @else { -
    +
    @@ -125,33 +121,29 @@

    } @else { -
    +
    Unable to load one or both submission archives.
    } } @else if (archiveBlob) { -
    +
    } @else { -
    +
    Unable to load submission files.
    } @@ -173,10 +165,10 @@

    - + {{ file?.path ?? file?.name }} @if (selectedFilesMatch !== null) { @@ -191,14 +183,14 @@

    @if (isArchiveCodeOrTextFile(file)) { } @else if (isArchivePdfFile(file)) { - + } @else if (isArchiveImageFile(file)) { -
    +
    />
    } @else { -
    +
    Preview not available for this file type.
    } diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts index 1fe0454725..0a8a802524 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts @@ -1,7 +1,4 @@ -import {HttpResponse} from '@angular/common/http'; -import {Component, Inject, OnDestroy, OnInit} from '@angular/core'; import * as monaco from 'monaco-editor'; -import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {OverseerAssessment} from 'src/app/api/models/doubtfire-model'; import { ArchiveFileEntry, @@ -11,6 +8,9 @@ import { } from 'src/app/common/archive-viewer/archive-viewer.helpers'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {HttpResponse} from '@angular/common/http'; +import {Component, Inject, OnDestroy, OnInit} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; export interface SubmissionFilesModalData { assessment: OverseerAssessment; @@ -22,10 +22,10 @@ export interface SubmissionFilesModalData { } @Component({ - selector: 'f-submission-files-modal', - templateUrl: './submission-files-modal.component.html', - styleUrls: ['./submission-files-modal.component.scss'], - standalone: false + selector: 'f-submission-files-modal', + templateUrl: './submission-files-modal.component.html', + styleUrls: ['./submission-files-modal.component.scss'], + standalone: false, }) export class SubmissionFilesModalComponent implements OnInit, OnDestroy { private readonly diffOriginalUri = monaco.Uri.parse('inmemory://submission-compare/original'); diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html index 233333462b..668fb5daaf 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html @@ -1,4 +1,4 @@ -
    +
    @@ -9,7 +9,7 @@ [disabled]="!oa.reportReady" [expanded]="oa.id === loadOverseerAssessmentId && oa.reportReady" > - + Submission {{ overseerAssessments.length - idx }}: {{ oa.timestamp | humanizedDate }} @@ -21,7 +21,7 @@ } @if (oa.reportReady) { -
    +
    {{ oa.passedSteps }} / {{ oa.totalSteps }} @if (oa.passedSteps === oa.totalSteps) { done @@ -67,7 +67,7 @@ }
    } @else { -
    +
    Tests In Progress
    @@ -77,7 +77,7 @@ @for (result of oa.stepResultsCache.values | async; track result.id; let idx = $index) { - + Step {{ idx + 1 }}: {{ result.overseerStep?.displayName }} @@ -92,7 +92,7 @@ @if (!result.pass) { -

    +

    {{ result.feedbackMessage }}

    } @@ -102,7 +102,7 @@ result.expectedOutput !== result.stdout && (result.overseerStep?.stepType === 'output_diff' || !result.overseerStep) ) { -
    +
    - } @else if (similarity.type === 'TiiTaskSimilarity') { +
    + @for (part of similarity.parts; track part; let i = $index) { + + + + {{ similarity.friendlyTypeName }} + + {{ part.description }} + @if (similarity.readyForViewer) { + @if (similarity.type === 'JplagTaskSimilarity') { + + } @else if (similarity.type === 'TiiTaskSimilarity') { + + } + } + @if (i === 0) { } - } - @if (i === 0) { - - } - - @if (part.panelOpenState) { - @if (part.format) { - @if (part.format === 'html' || part.format === 'pdf') { - - } @else if (part.format === 'jplag') { - + + @if (part.panelOpenState) { + @if (part.format) { + @if (part.format === 'html' || part.format === 'pdf') { + + } @else if (part.format === 'jplag') { + + } + } @else { +

    There is no local similarity file for this.

    } - } @else { -

    There is no local similarity file for this.

    } - } -
    - } + + } +
    } @empty { -
    +
    There are no similarities for this submission
    } diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.ts index 3f199793c7..1f060d2164 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.ts @@ -1,19 +1,19 @@ -import {HttpResponse} from '@angular/common/http'; -import {Component, Input, OnChanges, SimpleChanges, ViewChild} from '@angular/core'; -import {MatAccordion} from '@angular/material/expansion'; import {Task} from 'src/app/api/models/task'; import {TaskSimilarity} from 'src/app/api/models/task-similarity'; import {TaskSimilarityService} from 'src/app/api/services/task-similarity.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {JplagReportViewerComponent} from 'src/app/projects/states/jplag/jplag-report-viewer.component'; +import {HttpResponse} from '@angular/common/http'; +import {Component, Input, OnChanges, SimpleChanges, ViewChild} from '@angular/core'; +import {MatAccordion} from '@angular/material/expansion'; import {SelectedTaskService} from '../../../../selected-task.service'; @Component({ - selector: 'f-task-similarity-view', - templateUrl: './task-similarity-view.component.html', - styleUrls: ['./task-similarity-view.component.scss'], - standalone: false + selector: 'f-task-similarity-view', + templateUrl: './task-similarity-view.component.html', + styleUrls: ['./task-similarity-view.component.scss'], + standalone: false, }) export class TaskSimilarityViewComponent implements OnChanges { @Input() task: Task; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html index c417537eca..0be1833ddb 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html @@ -41,7 +41,7 @@
    {{ task?.statusLabel() }}
    } - +
    -
    +
    + +

    - Your submission is being processed and will be avaliable to view soon. You will also - be able to download your most recently submitted files. + Your submission is being processed and will be avaliable to view soon. You will also be able + to download your most recently submitted files.

    You can choose to download your previous @@ -18,15 +19,19 @@

    You uploaded this submission {{task.submissionDate | date: 'dd/MM/yyyy'}}.

    - If you feel there has been an error in your submission, you can request to - regenerate your submission under the "Actions" dropdown menu. + If you feel there has been an error in your submission, you can request to regenerate your + submission under the "Actions" dropdown menu.

    - If you would like to submit alternate evidence for use in your portfolio, you can - upload alternate files under the "Actions" dropdown menu. + If you would like to submit alternate evidence for use in your portfolio, you can upload + alternate files under the "Actions" dropdown menu.

    -

    - + + +
    -
    -
    +
    + +
    + +
    + diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.html index 808584c21a..456422ea90 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.html @@ -1,4 +1,4 @@ -
    +
    comment

    Tutor Notes for {{ unitRole?.user?.name }}

    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.ts index 1166595775..df83bb6cad 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.ts @@ -1,11 +1,11 @@ -import {Component, Input, OnChanges, SimpleChanges} from '@angular/core'; import {UnitRole} from 'src/app/api/models/unit-role'; +import {Component, Input, OnChanges, SimpleChanges} from '@angular/core'; @Component({ - selector: 'f-tutor-notes-view', - templateUrl: './tutor-notes-view.component.html', - styleUrls: ['./tutor-notes-view.component.scss'], - standalone: false + selector: 'f-tutor-notes-view', + templateUrl: './tutor-notes-view.component.html', + styleUrls: ['./tutor-notes-view.component.scss'], + standalone: false, }) export class TutorNotesViewComponent implements OnChanges { @Input() task?; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html index 94534f8249..c980e95db5 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html @@ -1,4 +1,4 @@ -
    +
    {{ task.project.staffNoteCount }} @@ -115,7 +115,7 @@ @case (DashboardViews.task) { @if (task && task.blockedByPrerequisiteTasks()) {
    warning Warning: This task has @@ -129,7 +129,7 @@ @if (task.definition.hasTaskSheet) { } @else { -
    +
    subtitles_off
    } @@ -138,7 +138,7 @@ @if (task.hasPdf) { } @else { -
    +
    subtitles_off
    } @@ -189,7 +189,7 @@ -
    +
    subtitles_off
    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.spec.ts index abd4a08b1f..4695f366d0 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.spec.ts @@ -1,6 +1,5 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { TaskDashboardComponent } from './task-dashboard.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {TaskDashboardComponent} from './task-dashboard.component'; describe('TaskDashboardComponent', () => { let component: TaskDashboardComponent; @@ -8,9 +7,8 @@ describe('TaskDashboardComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ TaskDashboardComponent ] - }) - .compileComponents(); + declarations: [TaskDashboardComponent], + }).compileComponents(); fixture = TestBed.createComponent(TaskDashboardComponent); component = fixture.componentInstance; diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts index cae632e9c5..d2783af283 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts @@ -1,5 +1,3 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; -import {ActivatedRoute} from '@angular/router'; import {UnitRole} from 'src/app/api/models/doubtfire-model'; import {Task} from 'src/app/api/models/task'; import {TaskService} from 'src/app/api/services/task.service'; @@ -7,22 +5,30 @@ import {UserService} from 'src/app/api/services/user.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {TaskAssessmentModalService} from 'src/app/common/modals/task-assessment-modal/task-assessment-modal.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import {MatTabChangeEvent} from '@angular/material/tabs'; +import {ActivatedRoute} from '@angular/router'; import {SelectedTaskService} from '../../selected-task.service'; import {DashboardViews} from '../../selected-task.service'; -import {MatTabChangeEvent} from '@angular/material/tabs'; @Component({ - selector: 'f-task-dashboard', - templateUrl: './task-dashboard.component.html', - styleUrls: ['./task-dashboard.component.scss'], - standalone: false + selector: 'f-task-dashboard', + templateUrl: './task-dashboard.component.html', + styleUrls: ['./task-dashboard.component.scss'], + standalone: false, }) export class TaskDashboardComponent implements OnInit, OnChanges { @Input() task: Task; @Input() pdfUrl: string; public DashboardViews = DashboardViews; - public taskStatusData: any; + public taskStatusData: { + keys: TaskService['markedStatuses']; + help: TaskService['helpDescriptions']; + icons: TaskService['statusIcons']; + labels: TaskService['statusLabels']; + class: TaskService['statusClass']; + }; public tutor = false; public urls: { taskSubmissionPdfAttachmentUrl: string; diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html index 769d93cbbb..b30e7dcc78 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html @@ -37,12 +37,12 @@ @if (project$ | async; as project) { -
    -
    +
    +
    @if (subs$ | async) { @if (isProjectTaskListReady(project)) { } @else { -
    +
    }
    } @if (selectedTaskDefinition$ | async; as selectedTaskDefinition) { -
    +
    -
    +
    } @else if (!isProjectTaskListReady(project)) { -
    +
    +
    } diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts index eaff580905..864a741cf6 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts @@ -1,7 +1,4 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import {CdkDragEnd, CdkDragMove, CdkDragStart} from '@angular/cdk/drag-drop'; -import {Component, Input, OnInit} from '@angular/core'; -import {ActivatedRoute} from '@angular/router'; import { BehaviorSubject, Observable, @@ -13,11 +10,14 @@ import { tap, withLatestFrom, } from 'rxjs'; +import {Project, TaskDefinition} from 'src/app/api/models/doubtfire-model'; import {ProjectService} from 'src/app/api/services/project.service'; import {UnitService} from 'src/app/api/services/unit.service'; -import {GlobalStateService, ViewType} from '../../index/global-state.service'; import {UserService} from 'src/app/api/services/user.service'; -import {Project, TaskDefinition} from 'src/app/api/models/doubtfire-model'; +import {CdkDragEnd, CdkDragMove, CdkDragStart} from '@angular/cdk/drag-drop'; +import {Component, Input, OnInit} from '@angular/core'; +import {ActivatedRoute} from '@angular/router'; +import {GlobalStateService, ViewType} from '../../index/global-state.service'; @Component({ selector: 'f-project-dashboard', @@ -37,10 +37,10 @@ export class ProjectDashboardComponent implements OnInit { subs$: Observable; readonly skeletonRows = Array.from({length: 10}, (_, index) => index); - private readonly projectSubject = new BehaviorSubject(null); + private readonly projectSubject: BehaviorSubject = new BehaviorSubject(null); - private leftComponentStartSize$ = new Subject(); - private dragMove$ = new Subject<{event: CdkDragMove; div: HTMLDivElement}>(); + private leftComponentStartSize$: Subject = new Subject(); + private dragMove$: Subject<{event: CdkDragMove; div: HTMLDivElement}> = new Subject(); private dragMoveAudited$; private projectReady = false; diff --git a/src/app/projects/states/dashboard/selected-task.service.spec.ts b/src/app/projects/states/dashboard/selected-task.service.spec.ts index 7883cf970a..c1ce156e72 100644 --- a/src/app/projects/states/dashboard/selected-task.service.spec.ts +++ b/src/app/projects/states/dashboard/selected-task.service.spec.ts @@ -1,6 +1,5 @@ -import { TestBed } from '@angular/core/testing'; - -import { SelectedTaskService } from './selected-task.service'; +import {TestBed} from '@angular/core/testing'; +import {SelectedTaskService} from './selected-task.service'; describe('SelectedTaskService', () => { let service: SelectedTaskService; diff --git a/src/app/projects/states/dashboard/selected-task.service.ts b/src/app/projects/states/dashboard/selected-task.service.ts index 50502d9a02..5da81dd06f 100644 --- a/src/app/projects/states/dashboard/selected-task.service.ts +++ b/src/app/projects/states/dashboard/selected-task.service.ts @@ -1,7 +1,7 @@ -import {Injectable} from '@angular/core'; import {BehaviorSubject, Subject} from 'rxjs'; import {Task} from 'src/app/api/models/task'; import {TaskService} from 'src/app/api/services/task.service'; +import {Injectable} from '@angular/core'; import {GlobalStateService} from '../index/global-state.service'; export enum DashboardViews { @@ -24,10 +24,12 @@ export class SelectedTaskService { private globalState: GlobalStateService, ) {} - private task$ = new BehaviorSubject(null); - public currentPdfUrl$ = new BehaviorSubject(null); + private task$: BehaviorSubject = new BehaviorSubject(null); + public currentPdfUrl$: BehaviorSubject = new BehaviorSubject(null); - public currentView$ = new BehaviorSubject(DashboardViews.submission); + public currentView$: BehaviorSubject = new BehaviorSubject( + DashboardViews.submission, + ); public get hasTaskSheet(): boolean { return this.task$.value?.definition?.hasTaskSheet; diff --git a/src/app/projects/states/discussion-prompts/discussion-prompts.component.html b/src/app/projects/states/discussion-prompts/discussion-prompts.component.html index 3b3a2b5ef2..4172ea915a 100644 --- a/src/app/projects/states/discussion-prompts/discussion-prompts.component.html +++ b/src/app/projects/states/discussion-prompts/discussion-prompts.component.html @@ -1,9 +1,9 @@ -
    +
    @for (prompt of discussionPrompts; track prompt) { - +
    diff --git a/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts b/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts index adcf938409..e5a020891c 100644 --- a/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts +++ b/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts @@ -1,16 +1,16 @@ -import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core'; import {DiscussionPrompt} from 'src/app/api/models/discussion-prompt'; import {Project, TaskDefinition, UserService} from 'src/app/api/models/doubtfire-model'; import {StaffNote} from 'src/app/api/models/staff-note'; import {DiscussionPromptService} from 'src/app/api/services/discussion-prompt.service'; import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core'; @Component({ - selector: 'f-discussion-prompts', - templateUrl: './discussion-prompts.component.html', - styleUrl: './discussion-prompts.component.scss', - standalone: false + selector: 'f-discussion-prompts', + templateUrl: './discussion-prompts.component.html', + styleUrl: './discussion-prompts.component.scss', + standalone: false, }) export class DiscussionPromptsComponent implements OnInit { @ViewChild('staffNotesContainer') staffNotesContainer!: ElementRef; diff --git a/src/app/projects/states/groups/project-groups-state.component.ts b/src/app/projects/states/groups/project-groups-state.component.ts index 9743733163..8f6478a508 100644 --- a/src/app/projects/states/groups/project-groups-state.component.ts +++ b/src/app/projects/states/groups/project-groups-state.component.ts @@ -1,14 +1,14 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; -import {ActivatedRoute} from '@angular/router'; import {Observable, Subscription, of} from 'rxjs'; import {GroupSet, Project} from 'src/app/api/models/doubtfire-model'; -import {GlobalStateService, ViewType} from '../index/global-state.service'; +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ActivatedRoute} from '@angular/router'; +import {GlobalStateService} from '../index/global-state.service'; @Component({ - selector: 'f-project-groups-state', - templateUrl: './project-groups-state.component.html', - styleUrls: ['./project-groups-state.component.scss'], - standalone: false + selector: 'f-project-groups-state', + templateUrl: './project-groups-state.component.html', + styleUrls: ['./project-groups-state.component.scss'], + standalone: false, }) export class ProjectGroupsStateComponent implements OnInit, OnDestroy { @Input() public project$: Observable; diff --git a/src/app/projects/states/groups/project-groups/project-groups.component.html b/src/app/projects/states/groups/project-groups/project-groups.component.html index 6fd3e49648..a375726a37 100644 --- a/src/app/projects/states/groups/project-groups/project-groups.component.html +++ b/src/app/projects/states/groups/project-groups/project-groups.component.html @@ -1,12 +1,12 @@ -
    +
    @if (unit.hasGroupwork()) { } @else { -
    +
    groups

    No Group Work

    -

    There is no group work enabled for this unit.

    +

    There is no group work enabled for this unit.

    }
    diff --git a/src/app/projects/states/groups/project-groups/project-groups.component.ts b/src/app/projects/states/groups/project-groups/project-groups.component.ts index 18cdaab12e..3f1d39eea3 100644 --- a/src/app/projects/states/groups/project-groups/project-groups.component.ts +++ b/src/app/projects/states/groups/project-groups/project-groups.component.ts @@ -1,13 +1,13 @@ -import {Component, Input} from '@angular/core'; import {GroupSet, Project} from 'src/app/api/models/doubtfire-model'; import {Unit} from 'src/app/api/models/unit'; +import {Component, Input} from '@angular/core'; // This component is only displayed to students (projects) @Component({ - selector: 'f-project-groups', - templateUrl: './project-groups.component.html', - styleUrl: './project-groups.component.scss', - standalone: false + selector: 'f-project-groups', + templateUrl: './project-groups.component.html', + styleUrl: './project-groups.component.scss', + standalone: false, }) export class ProjectGroupsComponent { @Input() unit: Unit; diff --git a/src/app/projects/states/index/global-state.service.ts b/src/app/projects/states/index/global-state.service.ts index 2692d712b5..65584df544 100644 --- a/src/app/projects/states/index/global-state.service.ts +++ b/src/app/projects/states/index/global-state.service.ts @@ -1,5 +1,3 @@ -import {Injectable, OnDestroy} from '@angular/core'; -import {Router} from '@angular/router'; import {MediaObserver} from 'ng-flex-layout'; import {EntityCache} from 'ngx-entity-service'; import {BehaviorSubject, Observable, Subject, skip, take} from 'rxjs'; @@ -16,8 +14,10 @@ import { UserService, } from 'src/app/api/models/doubtfire-model'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; -import {AlertService} from 'src/app/common/services/alert.service'; import {FeedbackTemplateService} from 'src/app/api/services/feedback-template.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {Injectable, OnDestroy} from '@angular/core'; +import {Router} from '@angular/router'; /** * The different types of views that can be shown. Used by the header to determine details to show. diff --git a/src/app/projects/states/jplag/jplag-report-viewer.component.html b/src/app/projects/states/jplag/jplag-report-viewer.component.html index c5c52c229e..4474b7d14e 100644 --- a/src/app/projects/states/jplag/jplag-report-viewer.component.html +++ b/src/app/projects/states/jplag/jplag-report-viewer.component.html @@ -4,6 +4,6 @@ src="/JPlag/" frameborder="0" style="overflow: hidden" - class="w-full h-screen overflow-hidden" + class="h-screen w-full overflow-hidden" [scrolling]="false" > diff --git a/src/app/projects/states/jplag/jplag-report-viewer.component.ts b/src/app/projects/states/jplag/jplag-report-viewer.component.ts index 09df22eb1b..844e46ce7e 100644 --- a/src/app/projects/states/jplag/jplag-report-viewer.component.ts +++ b/src/app/projects/states/jplag/jplag-report-viewer.component.ts @@ -1,10 +1,10 @@ -import {Component, ElementRef, Input, ViewChild} from '@angular/core'; import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, ElementRef, Input, ViewChild} from '@angular/core'; @Component({ - selector: 'f-jplag-report-viewer', - templateUrl: './jplag-report-viewer.component.html', - standalone: false + selector: 'f-jplag-report-viewer', + templateUrl: './jplag-report-viewer.component.html', + standalone: false, }) export class JplagReportViewerComponent { @ViewChild('jplagIframe', {static: true}) jplagIframe!: ElementRef; diff --git a/src/app/projects/states/plan/project-plan.component.html b/src/app/projects/states/plan/project-plan.component.html index a29342d512..a1e861bcbd 100644 --- a/src/app/projects/states/plan/project-plan.component.html +++ b/src/app/projects/states/plan/project-plan.component.html @@ -1,5 +1,5 @@ @if (project) { -
    +

    Task Planner

    @if (unit.allowFlexibleDates) { @@ -16,8 +16,8 @@

    Task Planner

    -
    -
    +
    +
    Target Grade ; diff --git a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html index 5291b43dc6..d75f59aa58 100644 --- a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html +++ b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html @@ -1,5 +1,5 @@ - + {{ taskDefinition.abbreviation }} {{ taskDefinition.name }} @@ -15,7 +15,7 @@ [task]="task" > @if (!task.hasPrerequisiteTasks()) { -
    This task has no prerequisites.
    +
    This task has no prerequisites.
    } @if (dependents.length) { @@ -71,7 +71,7 @@
    } @else { -
    +
    This task is not a prerequisite for any other tasks.
    } diff --git a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts index 1b19161dcf..af95011291 100644 --- a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts +++ b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts @@ -1,9 +1,9 @@ -import {Component, Inject, Input, OnInit} from '@angular/core'; -import {MAT_DIALOG_DATA} from '@angular/material/dialog'; -import {MatTableDataSource} from '@angular/material/table'; import {Project} from 'src/app/api/models/project'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {TaskPrerequisite} from 'src/app/api/models/task-prerequisite'; +import {Component, Inject, Input, OnInit} from '@angular/core'; +import {MAT_DIALOG_DATA} from '@angular/material/dialog'; +import {MatTableDataSource} from '@angular/material/table'; export interface TaskPlannerPrerequisitesModalData { taskDefinition: TaskDefinition; @@ -12,17 +12,17 @@ export interface TaskPlannerPrerequisitesModalData { } @Component({ - selector: 'f-task-planner-prerequisites-modal', - templateUrl: './task-planner-prerequisites-modal.component.html', - styleUrl: './task-planner-prerequisites-modal.component.scss', - standalone: false + selector: 'f-task-planner-prerequisites-modal', + templateUrl: './task-planner-prerequisites-modal.component.html', + styleUrl: './task-planner-prerequisites-modal.component.scss', + standalone: false, }) export class TaskPlannerPrerequisitesModalComponent implements OnInit { @Input() taskDefinition: TaskDefinition; @Input() project: Project; @Input() dependents: TaskPrerequisite[]; - public dataSource = new MatTableDataSource(); + public dataSource: MatTableDataSource = new MatTableDataSource(); public displayedColumns: string[] = ['task-definition', 'current-status', 'required-status']; public get task() { diff --git a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.service.ts b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.service.ts index 4f12f4fd1f..354c891350 100644 --- a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.service.ts +++ b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.service.ts @@ -1,11 +1,11 @@ +import {Project, TaskDefinition} from 'src/app/api/models/doubtfire-model'; +import {TaskPrerequisite} from 'src/app/api/models/task-prerequisite'; import {Injectable} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; -import {Project, TaskDefinition} from 'src/app/api/models/doubtfire-model'; import { TaskPlannerPrerequisitesModalComponent, TaskPlannerPrerequisitesModalData, } from './task-planner-prerequisites-modal.component'; -import {TaskPrerequisite} from 'src/app/api/models/task-prerequisite'; @Injectable({ providedIn: 'root', diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.html b/src/app/projects/states/plan/task-planner/task-planner.component.html index e17c06ff34..cc2a8e04fe 100644 --- a/src/app/projects/states/plan/task-planner/task-planner.component.html +++ b/src/app/projects/states/plan/task-planner/task-planner.component.html @@ -1,4 +1,4 @@ -
    +
    Show Task Dates
    @@ -39,12 +39,12 @@ class="flex items-center justify-between" [routerLink]="['/projects', project.id, 'dashboard', item.taskDefinition.abbreviation]" > -
    +
    -
    +
    {{ item.title }}
    @@ -79,13 +79,13 @@ [attr.data-gantt-id]="item.id" (mouseover)="onBarHover(item)" (mouseleave)="onBarLeave(item)" - class="gantt-bar w-full text-white flex gap-1 justify-between items-center p-1 h-[35px]" + class="gantt-bar flex h-[35px] w-full items-center justify-between gap-1 p-1 text-white" [ngClass]="getItemClasses(item)" [matTooltip]="getTooltip(item)" matTooltipShowDelay="500" matTooltipPosition="above" - >
    -
    + >
    +
    @if (unsavedChanges(item)) { change_circle } diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.ts b/src/app/projects/states/plan/task-planner/task-planner.component.ts index d0e17b5fb4..9a3bcb36a6 100644 --- a/src/app/projects/states/plan/task-planner/task-planner.component.ts +++ b/src/app/projects/states/plan/task-planner/task-planner.component.ts @@ -1,5 +1,3 @@ -import {Component, Input, OnInit, ViewChild} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; import { GanttBaselineItem, GanttDate, @@ -18,6 +16,8 @@ import {TaskPrerequisiteService} from 'src/app/api/services/task-prerequisite.se import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {GradeService} from 'src/app/common/services/grade.service'; +import {Component, Input, OnInit, ViewChild} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; import {TaskPlannerPrerequisitesModalService} from './task-planner-prerequisites-modal/task-planner-prerequisites-modal.service'; interface TaskGanttItem extends GanttItem { @@ -28,10 +28,10 @@ interface TaskGanttItem extends GanttItem { } @Component({ - selector: 'f-task-planner', - templateUrl: './task-planner.component.html', - styleUrl: './task-planner.component.scss', - standalone: false + selector: 'f-task-planner', + templateUrl: './task-planner.component.html', + styleUrl: './task-planner.component.scss', + standalone: false, }) export class TaskPlannerComponent implements OnInit { // Show a warning if the task's target end date is within this many days of the feedback deadline diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html index 84bd32601d..a596c34e0a 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html @@ -1,4 +1,4 @@ - + Upload Other Files @@ -10,7 +10,7 @@
      @for (file of extraFiles; track file) { -
    1. +
    2. {{ icons[file.kind] }} {{ file.name }} @@ -24,7 +24,7 @@ }
    -
    +
    Select type of file: @@ -45,7 +45,7 @@ > - + diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts index caaaff49ee..8e1afd4365 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts +++ b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts @@ -1,13 +1,13 @@ -import {Component, Input, OnInit} from '@angular/core'; -import {MatSelectChange} from '@angular/material/select'; import {Project} from 'src/app/api/models/project'; import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, Input, OnInit} from '@angular/core'; +import {MatSelectChange} from '@angular/material/select'; @Component({ - selector: 'f-portfolio-add-extra-files-step', - templateUrl: 'portfolio-add-extra-files-step.component.html', - styleUrls: ['portfolio-add-extra-files-step.component.scss'], - standalone: false + selector: 'f-portfolio-add-extra-files-step', + templateUrl: 'portfolio-add-extra-files-step.component.html', + styleUrls: ['portfolio-add-extra-files-step.component.scss'], + standalone: false, }) export class PortfolioAddExtraFilesStepComponent implements OnInit { @Input() project: Project; diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html index ce69d3dcb3..e74d70a357 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html @@ -1,5 +1,5 @@
    - + @@ -14,7 +14,7 @@

    Select Grade

    - + warning @@ -40,7 +40,7 @@

    Select Grade

    @if (agreedToAssessmentCriteria) { - + Grade Application diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts index 41d75520a1..208f989460 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts @@ -1,14 +1,14 @@ -import {Component, Input} from '@angular/core'; import {Project, Unit} from 'src/app/api/models/doubtfire-model'; import {ProjectService} from 'src/app/api/services/project.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {GradeService} from 'src/app/common/services/grade.service'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-portfolio-grade-select-step', - templateUrl: 'portfolio-grade-select-step.component.html', - styleUrls: ['portfolio-grade-select-step.component.scss'], - standalone: false + selector: 'f-portfolio-grade-select-step', + templateUrl: 'portfolio-grade-select-step.component.html', + styleUrls: ['portfolio-grade-select-step.component.scss'], + standalone: false, }) export class PortfolioGradeSelectStepComponent { @Input() project: Project; diff --git a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html index 74cb105802..00107890a2 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.html @@ -1,4 +1,4 @@ - + Learning Summary Report @@ -12,7 +12,7 @@ summary of what you have learnt in this unit. It consists of two sections:

    -
      +
      1. a self-assessment, and
      2. your reflections on the unit.
      @@ -30,13 +30,13 @@ @if ( projectHasDraftLearningSummaryReport && !forceLSRSubmit && !acceptUploadNewLearningSummary ) { -
      -

    } @else {

    construction - } @else { -
    - - } -
    -
    - +

    + } diff --git a/src/app/projects/states/tutorials/tutorials.component.ts b/src/app/projects/states/tutorials/tutorials.component.ts index 2ff72a61a2..0284fbca42 100644 --- a/src/app/projects/states/tutorials/tutorials.component.ts +++ b/src/app/projects/states/tutorials/tutorials.component.ts @@ -1,15 +1,15 @@ +import {Observable, Subscription, of} from 'rxjs'; +import {Project, Tutorial, Unit} from 'src/app/api/models/doubtfire-model'; import {Component, Input, OnDestroy, OnInit} from '@angular/core'; -import {ActivatedRoute} from '@angular/router'; import {Sort} from '@angular/material/sort'; import {MatTableDataSource} from '@angular/material/table'; -import {Observable, Subscription, of} from 'rxjs'; -import {Project, Tutorial, Unit} from 'src/app/api/models/doubtfire-model'; +import {ActivatedRoute} from '@angular/router'; @Component({ - selector: 'f-tutorials', - templateUrl: './tutorials.component.html', - styleUrls: ['./tutorials.component.scss'], - standalone: false + selector: 'f-tutorials', + templateUrl: './tutorials.component.html', + styleUrls: ['./tutorials.component.scss'], + standalone: false, }) export class TutorialsComponent implements OnInit, OnDestroy { @Input() public project$: Observable; @@ -30,7 +30,7 @@ export class TutorialsComponent implements OnInit, OnDestroy { 'actions', ]; - dataSource = new MatTableDataSource([]); + dataSource: MatTableDataSource = new MatTableDataSource([]); private projectSub?: Subscription; diff --git a/src/app/sessions/service-worker-updater/check-for-update.service.ts b/src/app/sessions/service-worker-updater/check-for-update.service.ts index 409e444719..302af93ef1 100644 --- a/src/app/sessions/service-worker-updater/check-for-update.service.ts +++ b/src/app/sessions/service-worker-updater/check-for-update.service.ts @@ -1,13 +1,14 @@ -import { ApplicationRef, Injectable } from '@angular/core'; -import { SwUpdate } from '@angular/service-worker'; -import { interval } from 'rxjs'; -import { MatSnackBar } from '@angular/material/snack-bar'; -import { delay } from 'rxjs/operators'; -import { concat } from 'rxjs'; +import {ApplicationRef, Injectable} from '@angular/core'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {SwUpdate} from '@angular/service-worker'; @Injectable() export class CheckForUpdateService { - constructor(appRef: ApplicationRef, private updates: SwUpdate, private _snackBar: MatSnackBar) { + constructor( + appRef: ApplicationRef, + private updates: SwUpdate, + private _snackBar: MatSnackBar, + ) { // Allow the app to stabilize first, before starting polling for updates with `interval()`. // const appIsStable$ = appRef.isStable.pipe(delay(10000)); @@ -22,15 +23,15 @@ export class CheckForUpdateService { if (updateEvent.type === 'VERSION_READY') { const snackBarRef = _snackBar.open( 'An update to the app has been found, would you like to refresh now?', - 'refresh' + 'refresh', ); - snackBarRef.onAction().subscribe((result) => { + snackBarRef.onAction().subscribe((_result) => { updates.activateUpdate().then(() => document.location.reload()); }); } }); - this.updates.unrecoverable.subscribe((event) => { + this.updates.unrecoverable.subscribe((_event) => { _snackBar.open('An error occurred during update, please refresh the page'); }); } diff --git a/src/app/sessions/states/sign-in/sign-in.component.html b/src/app/sessions/states/sign-in/sign-in.component.html index 1d6d66633f..5eeb9fa752 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.html +++ b/src/app/sessions/states/sign-in/sign-in.component.html @@ -1,9 +1,9 @@ -
    - -
    +
    + +
    @if (!isLoading) { @if (!isLoading) { -
    +
    Homepage Logo @@ -25,13 +25,13 @@

    class="sign-in-form flex flex-col" > @if (showCredentials) { - + Username } @if (showCredentials) { - + Password

    } } @else if (authMethodFailed) { -
    +
    } diff --git a/src/app/sessions/states/sign-in/sign-in.component.spec.ts b/src/app/sessions/states/sign-in/sign-in.component.spec.ts index e0d4c2f0d0..ccc7662322 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.spec.ts +++ b/src/app/sessions/states/sign-in/sign-in.component.spec.ts @@ -1,6 +1,5 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { SignInComponent } from './sign-in.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {SignInComponent} from './sign-in.component'; describe('SignInComponent', () => { let component: SignInComponent; @@ -8,9 +7,8 @@ describe('SignInComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ SignInComponent ] - }) - .compileComponents(); + declarations: [SignInComponent], + }).compileComponents(); }); beforeEach(() => { diff --git a/src/app/sessions/states/sign-in/sign-in.component.ts b/src/app/sessions/states/sign-in/sign-in.component.ts index eaecb6108f..7477ab3920 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.ts +++ b/src/app/sessions/states/sign-in/sign-in.component.ts @@ -1,17 +1,15 @@ -import {HttpClient} from '@angular/common/http'; -import {Component, Input, OnInit} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; import {BehaviorSubject} from 'rxjs'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {UserService} from 'src/app/api/services/user.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; +import {HttpClient} from '@angular/common/http'; +import {Component, Input, OnInit} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; // Add fallback to check url for query parameters -interface IParams { - [key: string]: string; -} +type IParams = Record; const paramReducer = (params: IParams, pair: string): IParams => { const [key, value] = `${pair}=`.split('=').map(decodeURIComponent); @@ -38,10 +36,10 @@ type signInData = autoLogin?: boolean; }; @Component({ - selector: 'f-sign-in', - templateUrl: './sign-in.component.html', - styleUrls: ['./sign-in.component.scss'], - standalone: false + selector: 'f-sign-in', + templateUrl: './sign-in.component.html', + styleUrls: ['./sign-in.component.scss'], + standalone: false, }) export class SignInComponent implements OnInit { public signingIn: boolean; @@ -130,11 +128,11 @@ export class SignInComponent implements OnInit { // wait 2 seconds with rxjs const wait = new Promise((resolve) => setTimeout(resolve, 3000)); this.http.get(`${this.constants.API_URL}/auth/method`).subscribe({ - next: (response: any) => { + next: (response: {redirect_to?: string}) => { this.isLoading = false; // if there is a string in response.data.redirect_to - this.SSOLoginUrl = response.redirect_to || false; + this.SSOLoginUrl = response.redirect_to || ''; if (this.authToken) { // We have an auth token - so attempt to convert to access token @@ -189,7 +187,7 @@ export class SignInComponent implements OnInit { return wait.then(); } }, - error: (err) => { + error: (_err) => { this.authMethodFailed = true; // this.error = err; diff --git a/src/app/sessions/transition-hooks.service.spec.ts b/src/app/sessions/transition-hooks.service.spec.ts index 90d821953b..3addee99f2 100644 --- a/src/app/sessions/transition-hooks.service.spec.ts +++ b/src/app/sessions/transition-hooks.service.spec.ts @@ -1,6 +1,5 @@ -import { TestBed } from '@angular/core/testing'; - -import { TransitionHooksService } from './transition-hooks.service'; +import {TestBed} from '@angular/core/testing'; +import {TransitionHooksService} from './transition-hooks.service'; describe('TransitionHooksService', () => { let service: TransitionHooksService; diff --git a/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.html b/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.html index ad6470153b..52898d0a79 100644 --- a/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.html +++ b/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.html @@ -17,7 +17,7 @@

    Request Feedback Review

    request will not be counted against your remaining total.

    - + Reason for review request - + Priority diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts index 331100ba99..ea9fbc10d2 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts @@ -1,6 +1,3 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; -import {UntypedFormControl, Validators} from '@angular/forms'; -import {MatTableDataSource} from '@angular/material/table'; import {Observable, Subscription} from 'rxjs'; import {DiscussionPrompt} from 'src/app/api/models/discussion-prompt'; import {Task} from 'src/app/api/models/task'; @@ -12,12 +9,15 @@ import {TaskDefinitionService} from 'src/app/api/services/task-definition.servic import {TaskPrerequisiteService} from 'src/app/api/services/task-prerequisite.service'; import {EntityFormComponent} from 'src/app/common/entity-form/entity-form.component'; import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import {UntypedFormControl, Validators} from '@angular/forms'; +import {MatTableDataSource} from '@angular/material/table'; @Component({ - selector: 'f-task-definition-discussion-prompts', - templateUrl: 'task-definition-discussion-prompts.component.html', - styleUrls: ['task-definition-discussion-prompts.component.scss'], - standalone: false + selector: 'f-task-definition-discussion-prompts', + templateUrl: 'task-definition-discussion-prompts.component.html', + styleUrls: ['task-definition-discussion-prompts.component.scss'], + standalone: false, }) export class TaskDefinitionDiscussionPromptsComponent extends EntityFormComponent @@ -31,7 +31,7 @@ export class TaskDefinitionDiscussionPromptsComponent private prereqSub?: Subscription; - public dataSource = new MatTableDataSource(); + public dataSource: MatTableDataSource = new MatTableDataSource(); creatingNewDiscussionPrompt: boolean = false; diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html index cca24f04c2..773af87979 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html @@ -1,4 +1,4 @@ -
    +

    Details for {{ taskDefinition.abbreviation }} - {{ taskDefinition.name }}

    @@ -9,7 +9,7 @@

    Details for {{ taskDefinition.abbreviation }} - {{ taskDefinition.name }} +

    Task Details

    -

    Name the task and set target grade

    +

    Name the task and set target grade

    Task Learning Outcomes

    -

    Add learning outcomes for this task

    +

    Add learning outcomes for this task

    Inbox

    -

    +

    Who assesses {{ unit.hasGroupwork() ? 'and submits ' : '' }}this task?

    @@ -63,45 +63,45 @@

    Inbox

    Due Dates

    -

    When is the task due?

    +

    When is the task due?

    Upload Requirements

    -

    What do students need to upload?

    +

    What do students need to upload?

    Task Resources

    -

    Upload task descriptions and resources

    +

    Upload task descriptions and resources

    Prerequisite Tasks

    -

    +

    Select which tasks need to be submitted before {{ taskDefinition.abbreviation }} {{ taskDefinition.name }} can be submitted @@ -112,12 +112,12 @@

    Prerequisite Tasks

    Discussion Prompts

    -

    +

    Discussion prompts for tutors to use when discussing student tasks in class

    @@ -127,24 +127,24 @@

    Discussion Prompts

    @if (overseerEnabled) {

    Task Assessment Automation

    -

    Configure automated assessment

    +

    Configure automated assessment

    }

    SCORM Test

    -

    +

    Upload the corresponding SCORM 2004 test (e.g. Numbas)

    @@ -152,12 +152,12 @@

    SCORM Test

    Optional Settings

    -

    Apply other options

    +

    Apply other options

    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.ts index 81ff3fb414..88063be511 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.ts @@ -1,3 +1,9 @@ +import {Subscription} from 'rxjs'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {Unit} from 'src/app/api/models/unit'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import { AfterViewInit, Component, @@ -12,12 +18,6 @@ import { ViewChild, ViewChildren, } from '@angular/core'; -import {Subscription} from 'rxjs'; -import {TaskDefinition} from 'src/app/api/models/task-definition'; -import {Unit} from 'src/app/api/models/unit'; -import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; -import {AlertService} from 'src/app/common/services/alert.service'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; type TaskDefinitionSectionId = | 'task-details' @@ -38,10 +38,10 @@ interface TaskDefinitionSection { } @Component({ - selector: 'f-task-definition-editor', - templateUrl: 'task-definition-editor.component.html', - styleUrls: ['task-definition-editor.component.scss'], - standalone: false + selector: 'f-task-definition-editor', + templateUrl: 'task-definition-editor.component.html', + styleUrls: ['task-definition-editor.component.scss'], + standalone: false, }) export class TaskDefinitionEditorComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy { @Input() taskDefinition: TaskDefinition; @@ -65,7 +65,7 @@ export class TaskDefinitionEditorComponent implements OnInit, AfterViewInit, OnC {id: 'optional-settings', label: 'Optional Settings'}, ]; - private sectionElementMap = new Map(); + private sectionElementMap: Map = new Map(); private sectionChangesSubscription?: Subscription; private overseerEnabledSubscription?: Subscription; private readonly scrollTopOffsetPx: number = 112; diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.ts index aad3e6d649..0ae8ea3283 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.ts @@ -1,18 +1,18 @@ -import { Component, Input } from '@angular/core'; -import { TaskDefinition } from 'src/app/api/models/task-definition'; -import { Unit } from 'src/app/api/models/unit'; -import { GradeService } from 'src/app/common/services/grade.service'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {Unit} from 'src/app/api/models/unit'; +import {GradeService} from 'src/app/common/services/grade.service'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-task-definition-general', - templateUrl: 'task-definition-general.component.html', - styleUrls: ['task-definition-general.component.scss'], - standalone: false + selector: 'f-task-definition-general', + templateUrl: 'task-definition-general.component.html', + styleUrls: ['task-definition-general.component.scss'], + standalone: false, }) export class TaskDefinitionGeneralComponent { @Input() taskDefinition: TaskDefinition; - public grades: { value: number; viewValue: string }[]; + public grades: {value: number; viewValue: string}[]; constructor(private gradeService: GradeService) { this.grades = this.gradeService.gradeViewData.filter((grade) => grade.value !== -1); diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html index 6a0b952c48..bd3109b9f2 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html @@ -1,5 +1,5 @@
    -
    +
    Restrict updates @@ -9,7 +9,7 @@
    -
    +
    -
    +
    Requires Discussion @@ -34,7 +34,7 @@
    -
    +
    Graded @@ -44,12 +44,12 @@
    -
    +
    Quality Stars - Provide a number of stars alongside the task status. Make sure you have a clear reason for each star within your task description. diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts index edba0f5051..16e5515a3a 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts @@ -1,13 +1,13 @@ -import {Component, Input} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-task-definition-options', - templateUrl: 'task-definition-options.component.html', - styleUrls: ['task-definition-options.component.scss'], - standalone: false + selector: 'f-task-definition-options', + templateUrl: 'task-definition-options.component.html', + styleUrls: ['task-definition-options.component.scss'], + standalone: false, }) export class TaskDefinitionOptionsComponent { @Input() taskDefinition: TaskDefinition; diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html index 99782d94b6..415d4a14a6 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html @@ -1,4 +1,4 @@ -
    +

    {{ data.taskDefinition.abbreviation }} {{ data.taskDefinition.name }}

    Overseer script

    @@ -9,6 +9,6 @@
    @if (!loading) { - + }
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts index 9f44236d77..ee5c0c1e46 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts @@ -1,15 +1,15 @@ +import {CodeModel} from '@ngstack/code-editor'; +import {AlertService} from 'src/app/common/services/alert.service'; import {HttpClient} from '@angular/common/http'; import {Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; -import {CodeModel} from '@ngstack/code-editor'; -import {AlertService} from 'src/app/common/services/alert.service'; import {OverseerScriptEditorModalData} from './overseer-script-editor-modal.service'; @Component({ - selector: 'f-overseer-script-editor-modal', - templateUrl: './overseer-script-editor-modal.component.html', - styleUrls: ['./overseer-script-editor-modal.component.scss'], - standalone: false + selector: 'f-overseer-script-editor-modal', + templateUrl: './overseer-script-editor-modal.component.html', + styleUrls: ['./overseer-script-editor-modal.component.scss'], + standalone: false, }) export class OverseerScriptEditorModalComponent implements OnInit { constructor( diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.service.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.service.ts index c238db3eaf..4964a97b4e 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.service.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.service.ts @@ -1,7 +1,7 @@ +import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Injectable} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {OverseerScriptEditorModalComponent} from './overseer-script-editor-modal.component'; -import {TaskDefinition} from 'src/app/api/models/task-definition'; export interface OverseerScriptEditorModalData { taskDefinition: TaskDefinition; diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html index df2173bf35..164bd31aaf 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html @@ -86,7 +86,7 @@ color="primary" [disabled]="!taskDefinition.id" (click)="testSubmission()" - class="flex-grow me-4" + class="me-4 flex-grow" > upload_file Test Submission @@ -94,7 +94,7 @@ mat-flat-button color="accent" (click)="testSubmissionHistory()" - class="flex-grow ms-4" + class="ms-4 flex-grow" [disabled]="!this.currentUserTask?.project" > preview Submission History @@ -118,7 +118,7 @@
    Overseer Steps
    @if (!newOverseerStep) { @@ -132,7 +132,7 @@ cdkDrag (click)="selectStep(step)" [ngClass]="{ - 'bg-gray-100': selectedOverseerStep?.id === step.id + 'bg-gray-100': selectedOverseerStep?.id === step.id, }" > drag_indicator @@ -153,9 +153,9 @@ @if (selectedOverseerStep) { - - -
    + + +
    Step Name @@ -182,7 +182,7 @@ @if (selectedOverseerStep.stepType === 'output_diff') { -
    +
    Script Input File @@ -234,7 +234,7 @@
    } -
    +
    Execution Script
    Language @@ -260,7 +260,7 @@ [(ngModel)]="selectedOverseerStep.decodedRunCommand" (ngModelChange)="onRunCommandChange(selectedOverseerStep, $event)" > - + @if (selectedOverseerStep.stepType === 'status_check') { This step passes only if the script exits with status 0. Any non-zero exit code marks the step as failed. @@ -270,7 +270,7 @@ }
    - + Time Limit (s) -
    +
    @@ -335,7 +335,7 @@
    -
    +
    Test Name @@ -353,7 +353,7 @@ Shown to student in overseer report
    - + Feedback message } @else { -
    +
    No steps selected tab_unselected
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts index 747ea313d5..e6dac66379 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts @@ -1,9 +1,6 @@ -import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop'; -import {HttpClient, HttpResponse} from '@angular/common/http'; -import {Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild} from '@angular/core'; +import * as monaco from 'monaco-editor'; import {Observable} from 'rxjs'; import { - OverseerAssessment, OverseerImage, OverseerImageService, Task, @@ -21,14 +18,17 @@ import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloa import {TaskAssessmentModalService} from 'src/app/common/modals/task-assessment-modal/task-assessment-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {TaskSubmissionService} from 'src/app/common/services/task-submission.service'; -import {OverseerScriptEditorModalService} from './overseer-script-editor-modal/overseer-script-editor-modal.service'; -import * as monaco from 'monaco-editor'; +import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop'; +import {HttpClient, HttpResponse} from '@angular/common/http'; +import {Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild} from '@angular/core'; import {MatSelectChange} from '@angular/material/select'; +import {OverseerScriptEditorModalService} from './overseer-script-editor-modal/overseer-script-editor-modal.service'; + @Component({ - selector: 'f-task-definition-overseer', - templateUrl: 'task-definition-overseer.component.html', - styleUrls: ['task-definition-overseer.component.scss'], - standalone: false + selector: 'f-task-definition-overseer', + templateUrl: 'task-definition-overseer.component.html', + styleUrls: ['task-definition-overseer.component.scss'], + standalone: false, }) export class TaskDefinitionOverseerComponent implements OnChanges, OnInit { @Input() taskDefinition: TaskDefinition; @@ -229,7 +229,7 @@ export class TaskDefinitionOverseerComponent implements OnChanges, OnInit { }, ) .subscribe({ - next: (result) => { + next: (_result) => { this.alerts.success('Saved overseer step', 3000); }, error: (error) => { @@ -301,7 +301,6 @@ export class TaskDefinitionOverseerComponent implements OnChanges, OnInit { if (!this.currentUserTask) return; this.submissions.getLatestSubmissionsTimestamps(this.currentUserTask).subscribe({ - next: (result: OverseerAssessment[]) => {}, error: (error) => { this.alerts.error('Error: ' + error, 6000); }, diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html index 492b9bd9ac..740b01959e 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html @@ -1,5 +1,5 @@
    -
    +
    @@ -60,7 +60,7 @@ @@ -65,7 +65,7 @@

    Manage Target Dates

    Manage Target Dates Manage Target Dates @@ -176,13 +176,13 @@

    Manage Target Dates

    @if ((taskDefinitionSource?.filteredData ?? []).length === 0) { -
    No task definitions to display
    +
    No task definitions to display
    } @for ( taskDefinition of taskDefinitionSource?.filteredData ?? []; track taskDefinition ) { - +
    Manage Target Dates > @if (!isTaskListCollapsed) { -
    -

    +
    +

    {{ taskDefinition.name }}

    @@ -255,7 +255,7 @@

    [unit]="unit" > } @else { -
    +

    Select a task definition

    Pick a task from the left list to edit its details.

    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts index e09a279757..e2ea1486b3 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts @@ -1,5 +1,3 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; -import {MatTableDataSource} from '@angular/material/table'; import {addWeeks} from 'date-fns'; import {Subscription} from 'rxjs'; import {Grade} from 'src/app/api/models/grade'; @@ -8,29 +6,34 @@ import {Unit} from 'src/app/api/models/unit'; import {FeedbackTemplateService} from 'src/app/api/services/feedback-template.service'; import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; -import {CsvResultModalService} from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; +import { + CsvResult, + CsvResultModalService, +} from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; import {CsvUploadModalService} from 'src/app/common/modals/csv-upload-modal/csv-upload-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {MatTableDataSource} from '@angular/material/table'; type GradeCol = 'p' | 'c' | 'd' | 'hd'; @Component({ - selector: 'f-unit-task-editor', - templateUrl: 'unit-task-editor.component.html', - styleUrls: ['unit-task-editor.component.scss'], - standalone: false + selector: 'f-unit-task-editor', + templateUrl: 'unit-task-editor.component.html', + styleUrls: ['unit-task-editor.component.scss'], + standalone: false, }) export class UnitTaskEditorComponent implements OnInit, OnDestroy { @Input() unit: Unit; - public taskDefinitionSource = new MatTableDataSource([]); + public taskDefinitionSource: MatTableDataSource = new MatTableDataSource([]); public filter: string = ''; public selectedTaskDefinition: TaskDefinition; public isTaskListCollapsed: boolean = false; public gradeColumns: string[] = ['p', 'c', 'd', 'hd']; public dueDateColumns: string[] = ['taskDefinition', 'p', 'c', 'd', 'hd']; - public dueDateSource = new MatTableDataSource([]); + public dueDateSource: MatTableDataSource = new MatTableDataSource([]); public manageDueDates: boolean = false; @@ -242,7 +245,7 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { 'Upload a CSV of task definitions.', {file: {name: 'Task Definition CSV Data', type: 'csv'}}, this.unit.getTaskDefinitionBatchUploadUrl(), - (response: any) => { + (response: CsvResult) => { // at least one student? this.csvResultModalService.show('Task Definition Import Results', response); if (response.success.length > 0) { @@ -258,7 +261,7 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { 'Upload a ZIP of task sheets and resources.', {file: {name: 'Task Sheets and Resources', type: 'zip'}}, this.unit.taskUploadUrl, - (response: any) => { + (response: CsvResult) => { // at least one student? this.csvResultModalService.show('Task Sheet and Resources Import Results', response); if (response.success.length > 0) { diff --git a/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.html b/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.html index e2fb26f382..0ae4331b86 100644 --- a/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.html +++ b/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.html @@ -1,39 +1,39 @@
    -
    -
    -

    {{ stream.name }} - {{ stream.abbreviation }}

    - -
    - - - - Name - - - - - - Abbreviation - - - - - - - -
    + @if (stream) { +
    + @if (!editingStream) { +
    +

    {{ stream.name }} - {{ stream.abbreviation }}

    + +
    + } @else { + + Name + + + - + + Abbreviation + + - + + + + } +
    + } @else {

    Tutorials without a stream

    - + }

    Task @if (staffView) { - + - - -} +
    + + +
    + } -
    +
    @if (taskDefinition.hasTaskResources) { -
    - - -
    -} +
    + + +
    + }
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.ts index 458e479a10..efea676697 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.ts @@ -1,15 +1,15 @@ -import {Component, Inject, Input} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-task-definition-resources', - templateUrl: 'task-definition-resources.component.html', - styleUrls: ['task-definition-resources.component.scss'], - standalone: false + selector: 'f-task-definition-resources', + templateUrl: 'task-definition-resources.component.html', + styleUrls: ['task-definition-resources.component.scss'], + standalone: false, }) export class TaskDefinitionResourcesComponent { @Input() taskDefinition: TaskDefinition; diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html index 1db7e15ffc..d05d59d67e 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html @@ -12,19 +12,24 @@ /> @if (taskDefinition.hasScormData) {
    - - -
    } -
    +
    Allow students to review completed test attempt @@ -45,7 +50,7 @@
    -
    +
    @if (taskDefinition.needsJplag) { -
    +
    Language used for JPLAG checks diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts index 11ad050c31..f1be61f3f3 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts @@ -1,14 +1,14 @@ -import { Component, Input, ViewChild } from '@angular/core'; -import { MatTable } from '@angular/material/table'; -import { TaskDefinition, UploadRequirement } from 'src/app/api/models/task-definition'; -import { Unit } from 'src/app/api/models/unit'; -import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; +import {TaskDefinition, UploadRequirement} from 'src/app/api/models/task-definition'; +import {Unit} from 'src/app/api/models/unit'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Component, Input, ViewChild} from '@angular/core'; +import {MatTable} from '@angular/material/table'; @Component({ - selector: 'f-task-definition-upload', - templateUrl: 'task-definition-upload.component.html', - styleUrls: ['task-definition-upload.component.scss'], - standalone: false + selector: 'f-task-definition-upload', + templateUrl: 'task-definition-upload.component.html', + styleUrls: ['task-definition-upload.component.scss'], + standalone: false, }) export class TaskDefinitionUploadComponent { @Input() public taskDefinition: TaskDefinition; diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html index 4f363e2b22..0a3be6d1ba 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html @@ -1,13 +1,13 @@ @if (unit.hasGroupwork()) { - - Is this an individual or group task? Select group that submits - - @for (gs of unit.groupSets; track gs) { - {{ gs.name }} -} - None - Individual Submission - - + + Is this an individual or group task? Select group that submits + + @for (gs of unit.groupSets; track gs) { + {{ gs.name }} + } + None - Individual Submission + + }
    @@ -19,8 +19,8 @@ (selectionChange)="onTutorialStreamChange()" > @for (stream of unit.tutorialStreams; track stream) { - {{ stream.name }} -} + {{ stream.name }} + } diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts index 7e4dd5e770..17d58c3484 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts @@ -1,12 +1,12 @@ -import { Component, Input } from '@angular/core'; -import { TaskDefinition } from 'src/app/api/models/task-definition'; -import { Unit } from 'src/app/api/models/unit'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {Unit} from 'src/app/api/models/unit'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-task-definition-who', - templateUrl: 'task-definition-who.component.html', - styleUrls: ['task-definition-who.component.scss'], - standalone: false + selector: 'f-task-definition-who', + templateUrl: 'task-definition-who.component.html', + styleUrls: ['task-definition-who.component.scss'], + standalone: false, }) export class TaskDefinitionWhoComponent { @Input() taskDefinition: TaskDefinition; diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html index 244ca01013..472c672b28 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html @@ -1,4 +1,4 @@ -
    +

    Task List

    @@ -29,7 +29,7 @@

    Task List

    -
    +
    @if (unit.allowFlexibleDates) { } @@ -56,8 +56,8 @@

    Manage Target Dates

    @for (g of gradeColumns; track g) { -
    -
    +
    +
    Tutorials without a stream @@ -99,14 +105,15 @@

    Tutorials without a stream

    @@ -149,10 +161,11 @@

    Tutorials without a stream

    @@ -205,14 +223,13 @@

    Tutorials without a stream

    - +
    Abbreviation -
    - {{ tutorial.abbreviation }} -
    - + @if (!editing(tutorial)) { +
    + {{ tutorial.abbreviation }} +
    + } @else { -
    + }
    @@ -67,29 +68,34 @@

    Tutorials without a stream

    Campus -
    - {{ tutorial.campus ? tutorial.campus.name : '' }} -
    - + @if (!editing(tutorial)) { +
    + {{ tutorial.campus ? tutorial.campus.name : '' }} +
    + } @else { Campus Not Specified - - {{ campus.name }} - + @for (campus of campuses; track campus) { + + {{ campus.name }} + + } -
    + }
    Campus Not Specified - - {{ campus.name }} - + @for (campus of campuses; track campus) { + + {{ campus.name }} + + } Location -
    - {{ tutorial.meetingLocation }} -
    - + @if (!editing(tutorial)) { +
    + {{ tutorial.meetingLocation }} +
    + } @else { -
    + }
    @@ -119,27 +126,32 @@

    Tutorials without a stream

    Day -
    - {{ tutorial.meetingDay }} -
    - + @if (!editing(tutorial)) { +
    + {{ tutorial.meetingDay }} +
    + } @else { Day - - {{ day }} - + @for (day of days; track day) { + + {{ day }} + + } -
    + }
    Day - - {{ day }} - + @for (day of days; track day) { + + {{ day }} + + } Time -
    - {{ tutorial.meetingTime }} -
    - + @if (!editing(tutorial)) { +
    + {{ tutorial.meetingTime }} +
    + } @else { Tutorials without a stream placeholder="Time" /> -
    + }
    @@ -175,27 +188,32 @@

    Tutorials without a stream

    Tutor -
    - {{ tutorial.tutor?.name }} -
    - + @if (!editing(tutorial)) { +
    + {{ tutorial.tutor?.name }} +
    + } @else { Tutor - - {{ tutor.name }} - + @for (tutor of unit.staffUsers; track tutor) { + + {{ tutor.name }} + + } -
    + }
    Tutor - - {{ tutor.name }} - + @for (tutor of unit.staffUsers; track tutor) { + + {{ tutor.name }} + + } Capacity -
    - {{ tutorial.numStudents }} / {{ tutorial.capacity }} -
    - + @if (!editing(tutorial)) { +
    {{ tutorial.numStudents }} / {{ tutorial.capacity }}
    + } @else { -
    + }
    @@ -225,12 +242,13 @@

    Tutorials without a stream

    -
    - -
    - + @if (!editing(tutorial)) { +
    + +
    + } @else {
    -
    + }
    diff --git a/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts b/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts index 6f87b1f1bf..f9c98dba88 100644 --- a/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts +++ b/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts @@ -1,21 +1,22 @@ -import {Component, Input, ViewChild, AfterViewInit} from '@angular/core'; -import {MatSort, Sort} from '@angular/material/sort'; -import {MatTableDataSource, MatTable} from '@angular/material/table'; +import {RequestOptions} from 'ngx-entity-service'; import { - Tutorial, - TutorialService, Campus, CampusService, - User, + Tutorial, + TutorialService, TutorialStream, TutorialStreamService, Unit, + User, } from 'src/app/api/models/doubtfire-model'; import {EntityFormComponent} from 'src/app/common/entity-form/entity-form.component'; -import {UntypedFormControl, Validators} from '@angular/forms'; -import {RequestOptions} from 'ngx-entity-service'; -import {AlertService} from 'src/app/common/services/alert.service'; import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {HttpErrorResponse} from '@angular/common/http'; +import {AfterViewInit, Component, Input, ViewChild} from '@angular/core'; +import {UntypedFormControl, Validators} from '@angular/forms'; +import {MatSort, Sort} from '@angular/material/sort'; +import {MatTable, MatTableDataSource} from '@angular/material/table'; @Component({ selector: 'df-unit-tutorials-list', @@ -27,7 +28,7 @@ export class UnitTutorialsListComponent extends EntityFormComponent implements AfterViewInit { - @ViewChild(MatTable, {static: true}) table: MatTable; + @ViewChild(MatTable, {static: true}) table: MatTable; @ViewChild(MatSort, {static: true}) sort: MatSort; @Input() stream: TutorialStream; @Input() unit: Unit; @@ -55,7 +56,7 @@ export class UnitTutorialsListComponent 'options', ]; tutorials: Tutorial[] = []; - dataSource = new MatTableDataSource(); + dataSource: MatTableDataSource = new MatTableDataSource(); private editingStream: boolean = false; @@ -120,7 +121,7 @@ export class UnitTutorialsListComponent this.editingStream = false; this.alerts.success('Stream updated successfully', 2000); }, - error: (error: any) => { + error: (error: HttpErrorResponse) => { this.alerts.error('Something went wrong - ' + JSON.stringify(error.error), 6000); }, }); @@ -146,7 +147,11 @@ export class UnitTutorialsListComponent // to the datasource private pushToTable(value: Tutorial | Tutorial[]) { if (!value) return; - value instanceof Array ? this.tutorials.push(...value) : this.tutorials.push(value); + if (value instanceof Array) { + this.tutorials.push(...value); + } else { + this.tutorials.push(value); + } this.renderTable(); } @@ -183,14 +188,14 @@ export class UnitTutorialsListComponent // tutorial. The function is bound to the compareFn attribute on the related // mat-selects. // See: https://angular.io/api/forms/SelectControlValueAccessor - compareSelection(aEntity: User | Campus | any, bEntity: User | Campus) { + compareSelection(aEntity: User | Campus | {user_id: number}, bEntity: User | Campus) { if (!aEntity || !bEntity) { return; } if (bEntity instanceof User) { - return aEntity.user_id === bEntity.id; + return 'user_id' in aEntity && aEntity.user_id === bEntity.id; } else { - return aEntity.id === bEntity.id; + return 'id' in aEntity && aEntity.id === bEntity.id; } } @@ -221,7 +226,7 @@ export class UnitTutorialsListComponent * Ensure that the unit is passed to the Tutorial entity when create it called. */ protected override optionsOnRequest( - kind: 'create' | 'update' | 'delete', + _kind: 'create' | 'update' | 'delete', ): RequestOptions { return { constructorParams: this.unit, diff --git a/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html b/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html index 752fb350e6..e56b409a73 100644 --- a/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html +++ b/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html @@ -4,16 +4,16 @@ } @empty {
    -
    +
    groups

    No Tutorials

    -

    +

    There are no tutorials yet. Create a tutorial stream to begin adding tutorials.

    } -
    +
    } -
    +
    @@ -164,10 +164,10 @@

    Mark portfolios

    Stats -
    +
    @for (bar of project.taskStats; track bar) {
    @if (bar.key === 'not_started') { - {{ bar.value }}% + {{ bar.value }}% } @if (bar.key === 'complete') { - {{ bar.value }}% + {{ bar.value }}% }
    } @@ -212,7 +212,7 @@

    Mark portfolios

    >
    No students foundNo students found
    diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts index 202acba79a..46e481e21a 100644 --- a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts @@ -1,3 +1,13 @@ +import {Project} from 'src/app/api/models/project'; +import {TaskStatusEnum} from 'src/app/api/models/task-status'; +import {Unit} from 'src/app/api/models/unit'; +import {TaskService} from 'src/app/api/services/task.service'; +import {UnitService} from 'src/app/api/services/unit.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GradeService} from 'src/app/common/services/grade.service'; import { AfterViewInit, Component, @@ -11,36 +21,26 @@ import {MatButtonToggleChange} from '@angular/material/button-toggle'; import {MatPaginator} from '@angular/material/paginator'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTableDataSource} from '@angular/material/table'; -import {Project} from 'src/app/api/models/project'; -import {TaskStatusEnum} from 'src/app/api/models/task-status'; -import {Unit} from 'src/app/api/models/unit'; -import {TaskService} from 'src/app/api/services/task.service'; -import {UnitService} from 'src/app/api/services/unit.service'; -import {UserService} from 'src/app/api/services/user.service'; -import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; -import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; -import {AlertService} from 'src/app/common/services/alert.service'; -import {GradeService} from 'src/app/common/services/grade.service'; import {D2lTransferModal} from '../../d2l-transfer-modal/d2l-transfer.component'; @Component({ - selector: 'f-portfolios-list', - templateUrl: './portfolios-list.component.html', - styleUrl: './portfolios-list.component.scss', - standalone: false + selector: 'f-portfolios-list', + templateUrl: './portfolios-list.component.html', + styleUrl: './portfolios-list.component.scss', + standalone: false, }) export class PortfoliosListComponent implements OnInit, AfterViewInit { @Input() unit: Unit; @Output() - public studentSelected = new EventEmitter(); + public studentSelected: EventEmitter = new EventEmitter(); displayedColumns: string[] = []; @ViewChild(MatPaginator) paginator!: MatPaginator; @ViewChild(MatSort) sort: MatSort; - dataSource = new MatTableDataSource([]); + dataSource: MatTableDataSource = new MatTableDataSource([]); public portfolioFilter: 'all' | 'submitted_only' = 'submitted_only'; public tutorialFilter: 'all' | 'mine' = 'all'; diff --git a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html index c885e73b1f..abe9bf9a51 100644 --- a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.html @@ -3,10 +3,10 @@

    Review portfolio of {{ project.student.name }}

    View or download portfolio for assessment.

    @if (project.portfolioAvailable) { - + } @else { -
    +
    menu_book

    No Portfolio Submitted

    diff --git a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts index 3a1a59d153..d05528d57d 100644 --- a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts @@ -1,11 +1,11 @@ -import {Component, Input} from '@angular/core'; import {Project} from 'src/app/api/models/project'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-portfolios-portfolio-view', - templateUrl: './portfolios-portfolio-view.component.html', - styleUrl: './portfolios-portfolio-view.component.scss', - standalone: false + selector: 'f-portfolios-portfolio-view', + templateUrl: './portfolios-portfolio-view.component.html', + styleUrl: './portfolios-portfolio-view.component.scss', + standalone: false, }) export class PortfoliosPortfolioViewComponent { @Input() project: Project; diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html index da4eacf5a9..cdbdb593de 100644 --- a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html @@ -1,15 +1,15 @@

    Review progress of {{ project.student.name }}

    Review the students progress through the unit's tasks.

    -
    -
    +
    +
    Target Grade -
    -
    +
    +
    @for (grade of gradeValues; track grade) { Review progress of {{ project.student.name }}

    Submitted Grade -
    -
    +
    +
    Review progress of {{ project.student.name }} > -
    +
    Task Summary Chart @@ -82,7 +82,7 @@

    Review progress of {{ project.student.name }}

    Burndown Chart
    -
    +
    {{ project.student.name }} has completed {{ taskStats.numberOfTasksCompleted }} tasks and have {{ taskStats.numberOfTasksRemaining }} left to complete to achieve their target of a diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts index f3583509b6..bb8234ce2b 100644 --- a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts @@ -1,16 +1,16 @@ -import {Component, Input} from '@angular/core'; import {Project} from 'src/app/api/models/project'; import {Unit} from 'src/app/api/models/unit'; import {ProjectService} from 'src/app/api/services/project.service'; import {TaskService} from 'src/app/api/services/task.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {GradeService} from 'src/app/common/services/grade.service'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-portfolios-project-progress', - templateUrl: './portfolios-project-progress.component.html', - styleUrl: './portfolios-project-progress.component.scss', - standalone: false + selector: 'f-portfolios-project-progress', + templateUrl: './portfolios-project-progress.component.html', + styleUrl: './portfolios-project-progress.component.scss', + standalone: false, }) export class PortfoliosProjectProgressComponent { @Input() project: Project; diff --git a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts index ec143203e6..b0033d1785 100644 --- a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts +++ b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts @@ -1,12 +1,12 @@ -import {Component, Input, OnInit} from '@angular/core'; import {Unit} from 'src/app/api/models/unit'; import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, Input, OnInit} from '@angular/core'; @Component({ - selector: 'f-download-staff-notes', - templateUrl: 'download-staff-notes.component.html', - styleUrl: 'download-staff-notes.component.scss', - standalone: false + selector: 'f-download-staff-notes', + templateUrl: 'download-staff-notes.component.html', + styleUrl: 'download-staff-notes.component.scss', + standalone: false, }) export class DownloadStaffNotesComponent implements OnInit { @Input() unit: Unit; diff --git a/src/app/units/states/portfolios/portfolios.component.html b/src/app/units/states/portfolios/portfolios.component.html index 29dcd42573..a4a05762a3 100644 --- a/src/app/units/states/portfolios/portfolios.component.html +++ b/src/app/units/states/portfolios/portfolios.component.html @@ -1,4 +1,4 @@ -
    +

    Student Portfolios

    @if (unit) { diff --git a/src/app/units/states/portfolios/portfolios.component.ts b/src/app/units/states/portfolios/portfolios.component.ts index 6b8bfc454c..398463d779 100644 --- a/src/app/units/states/portfolios/portfolios.component.ts +++ b/src/app/units/states/portfolios/portfolios.component.ts @@ -1,17 +1,17 @@ -import {Component, Input, OnInit, ViewChild} from '@angular/core'; -import {MatTabGroup} from '@angular/material/tabs'; -import {ActivatedRoute, Router} from '@angular/router'; import {Observable, first, of} from 'rxjs'; import {Project} from 'src/app/api/models/project'; import {Unit} from 'src/app/api/models/unit'; import {ProjectService} from 'src/app/api/services/project.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, Input, OnInit, ViewChild} from '@angular/core'; +import {MatTabGroup} from '@angular/material/tabs'; +import {ActivatedRoute, Router} from '@angular/router'; @Component({ - selector: 'f-portfolios', - templateUrl: './portfolios.component.html', - styleUrl: './portfolios.component.scss', - standalone: false + selector: 'f-portfolios', + templateUrl: './portfolios.component.html', + styleUrl: './portfolios.component.scss', + standalone: false, }) export class PortfoliosComponent implements OnInit { @Input() unit$: Observable; diff --git a/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts b/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts index 5665cda90e..500440b850 100644 --- a/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts +++ b/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts @@ -1,16 +1,16 @@ -import {Component, Input, OnInit} from '@angular/core'; import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; import {Unit} from 'src/app/api/models/unit'; import {CsvResultModalService} from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; import {CsvUploadModalService} from 'src/app/common/modals/csv-upload-modal/csv-upload-modal.service'; import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, Input, OnInit} from '@angular/core'; @Component({ - selector: 'f-upload-grades', - templateUrl: 'upload-grades.component.html', - styleUrl: 'upload-grades.component.scss', - standalone: false + selector: 'f-upload-grades', + templateUrl: 'upload-grades.component.html', + styleUrl: 'upload-grades.component.scss', + standalone: false, }) export class UploadGradesComponent implements OnInit { @Input() unit: Unit; diff --git a/src/app/units/states/rollover/rollover.component.html b/src/app/units/states/rollover/rollover.component.html index 323cc3e9b1..1f55d654a7 100644 --- a/src/app/units/states/rollover/rollover.component.html +++ b/src/app/units/states/rollover/rollover.component.html @@ -1,5 +1,5 @@ -
    - +
    + Copy {{ unit?.code }} {{ unit?.nameAndPeriod }} diff --git a/src/app/units/states/rollover/rollover.component.ts b/src/app/units/states/rollover/rollover.component.ts index bd2d7efbd2..ceaa70b338 100644 --- a/src/app/units/states/rollover/rollover.component.ts +++ b/src/app/units/states/rollover/rollover.component.ts @@ -1,17 +1,17 @@ -import {Component, Input, OnInit} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; import {TeachingPeriod} from 'src/app/api/models/teaching-period'; import {Unit} from 'src/app/api/models/unit'; import {TeachingPeriodService} from 'src/app/api/services/teaching-period.service'; import {UnitService} from 'src/app/api/services/unit.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; +import {Component, Input, OnInit} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; @Component({ - selector: 'f-rollover', - templateUrl: './rollover.component.html', - styleUrl: './rollover.component.scss', - standalone: false + selector: 'f-rollover', + templateUrl: './rollover.component.html', + styleUrl: './rollover.component.scss', + standalone: false, }) export class RolloverComponent implements OnInit { @Input() unitId: number; diff --git a/src/app/units/states/students-list/students-list.component.html b/src/app/units/states/students-list/students-list.component.html index e39309b75a..70d1d02aa5 100644 --- a/src/app/units/states/students-list/students-list.component.html +++ b/src/app/units/states/students-list/students-list.component.html @@ -1,4 +1,4 @@ -
    +

    Students

    @@ -21,7 +21,7 @@

    Students

    -
    +
    Students
    Stats -
    +
    @for (bar of project.taskStats; track bar.key) {
    +
    @if (task) {
    {{ task.project.staffNoteCount }} diff --git a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts index 9c91ae71ee..38f63cfb46 100644 --- a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts +++ b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts @@ -1,9 +1,9 @@ -import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core'; -import {MatTabChangeEvent} from '@angular/material/tabs'; import {UnitRole} from 'src/app/api/models/doubtfire-model'; import {Task} from 'src/app/api/models/task'; import {UserService} from 'src/app/api/services/user.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core'; +import {MatTabChangeEvent} from '@angular/material/tabs'; enum InboxDashboardTab { submission = 0, @@ -22,7 +22,7 @@ enum InboxDashboardTab { }) export class InboxDashboardComponent implements OnChanges { @Input() task: Task; - @Output() visiblePdfUrlChange = new EventEmitter(); + @Output() visiblePdfUrlChange: EventEmitter = new EventEmitter(); public readonly InboxDashboardTab = InboxDashboardTab; public currentTab: InboxDashboardTab = InboxDashboardTab.submission; diff --git a/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.ts b/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.ts index 22080d4703..94844b10bc 100644 --- a/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.ts +++ b/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.ts @@ -1,16 +1,16 @@ -import {Component, Inject, OnInit} from '@angular/core'; -import {ConfirmModerationModalData} from './confirm-moderation-modal.service'; -import {MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; -import {TaskService} from 'src/app/api/services/task.service'; -import {AlertService} from 'src/app/common/services/alert.service'; import {FeedbackModerationActionType} from 'src/app/api/models/task'; import {Task} from 'src/app/api/models/task'; +import {TaskService} from 'src/app/api/services/task.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, Inject, OnInit} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {ConfirmModerationModalData} from './confirm-moderation-modal.service'; @Component({ - selector: 'f-confirm-moderation-modal', - templateUrl: './confirm-moderation-modal.component.html', - styleUrl: './confirm-moderation-modal.component.scss', - standalone: false + selector: 'f-confirm-moderation-modal', + templateUrl: './confirm-moderation-modal.component.html', + styleUrl: './confirm-moderation-modal.component.scss', + standalone: false, }) export class ConfirmModerationModalComponent implements OnInit { task: Task; diff --git a/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.service.ts b/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.service.ts index bd271f321c..2fa14ab3ec 100644 --- a/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.service.ts +++ b/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.service.ts @@ -1,8 +1,8 @@ +import {FeedbackModerationActionType} from 'src/app/api/models/task'; +import {Task} from 'src/app/api/models/task'; import {Injectable} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; -import {FeedbackModerationActionType} from 'src/app/api/models/task'; import {ConfirmModerationModalComponent} from './confirm-moderation-modal.component'; -import {Task} from 'src/app/api/models/task'; export interface ConfirmModerationModalData { task: Task; diff --git a/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.html b/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.html index 29ed5137c1..ae11125495 100644 --- a/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.html +++ b/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.html @@ -1,5 +1,5 @@ - + @if (task.moderationType === 'random_sample' || task.moderationType === 'first_feedback') { @@ -22,7 +22,7 @@
    @if (collapsable) {
    -
    +
    Tutors @if (filteredTasks.length) { -
    {{ filteredTasks.length }} Tasks
    +
    {{ filteredTasks.length }} Tasks
    } -
    +

    @if (task.moderationType === 'escalation') { ; + @ViewChild('searchDialog') searchDialog: TemplateRef; @Input() task: Task; @Input() project: Project; @@ -71,7 +68,7 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { tutorials: Tutorial[]; forceStream: boolean; studentName: string; - tutorialIdSelected: any; + tutorialIdSelected: string | number; unitRoleIdSelected: number | string; taskDefinitionIdSelected: number | TaskDefinition; }>; @@ -101,7 +98,7 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { // hasJplagReport: boolean = false; - watchingTaskKey: any; + watchingTaskKey: boolean; panelOpenState = false; loading = true; @@ -123,7 +120,7 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { taskDefSort = 0; tutorialSort = 0; - originalFilteredTasks: any[] = null; + originalFilteredTasks: Task[] = null; allowHover = true; // Track if all tasks have already been fetched @@ -299,7 +296,7 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { this.sidekiqProgressModalService .show(`Downloading submission pdfs for ${taskDef.abbreviation}`, newJob.id) .subscribe({ - next: (job) => { + next: (_job) => { this.fileDownloaderService.downloadFile( `${AppInjector.get(DoubtfireConstants).API_URL}/submission/unit/${ this.unit.id @@ -322,7 +319,7 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { this.sidekiqProgressModalService .show(`Downloading submission files for ${taskDef.abbreviation}`, newJob.id) .subscribe({ - next: (job) => { + next: (_job) => { this.fileDownloaderService.downloadFile( `${AppInjector.get(DoubtfireConstants).API_URL}/submission/unit/${ this.unit.id @@ -405,7 +402,7 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { openDialog() { const dialogRef = this.dialog.open(this.searchDialog); - dialogRef.afterClosed().subscribe((result) => {}); + dialogRef.afterClosed().subscribe(); } refreshTasks(): void { @@ -452,9 +449,12 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { openTaskDefs() { // Automatically "open" the task definition select element if in task def mode - const selectEl: any = document.querySelector( + const selectEl = document.querySelector( 'select[ng-model="filters.taskDefinitionIdSelected"]', - ) as any; + ); + if (!selectEl) { + return; + } selectEl.size = 10; selectEl.focus(); } @@ -604,20 +604,20 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { } } - private scrollToTaskInList(task) { - const taskEl = document.querySelector(`#${task.taskKeyToIdString()}`) as any; + private scrollToTaskInList(task: Task) { + const taskEl = document.querySelector(`#${task.taskKeyToIdString()}`) as + | (HTMLElement & { + scrollIntoViewIfNeeded?: (options?: ScrollIntoViewOptions) => void; + }) + | null; if (!taskEl) { return; } - const funcName = taskEl.scrollIntoViewIfNeeded - ? 'scrollIntoViewIfNeeded' - : taskEl.scrollIntoView - ? 'scrollIntoView' - : ''; - if (!funcName) { - return; + if (taskEl.scrollIntoViewIfNeeded) { + taskEl.scrollIntoViewIfNeeded({behavior: 'smooth'}); + } else { + taskEl.scrollIntoView({behavior: 'smooth'}); } - taskEl[funcName]({behavior: 'smooth'}); } isSelectedTask(task: Task) { @@ -676,7 +676,11 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { return; } const refreshOrdering = () => this.applyFilters(); - task.pinned ? task.unpin(refreshOrdering) : task.pin(refreshOrdering); + if (task.pinned) { + task.unpin(refreshOrdering); + } else { + task.pin(refreshOrdering); + } } getWarningIcon(task: Task): 'warning' | 'overflow' | null { diff --git a/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.ts b/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.ts index 2b068096a4..574e38607c 100644 --- a/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.ts +++ b/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.ts @@ -1,16 +1,16 @@ -import {Component, Input} from '@angular/core'; -import {MatSnackBar} from '@angular/material/snack-bar'; import {Task} from 'src/app/api/models/task'; import {UnitRole} from 'src/app/api/models/unit-role'; import {TaskService} from 'src/app/api/services/task.service'; import {UserService} from 'src/app/api/services/user.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {Component, Input} from '@angular/core'; +import {MatSnackBar} from '@angular/material/snack-bar'; @Component({ - selector: 'f-task-claim', - templateUrl: './task-claim.component.html', - styleUrl: './task-claim.component.scss', - standalone: false + selector: 'f-task-claim', + templateUrl: './task-claim.component.html', + styleUrl: './task-claim.component.scss', + standalone: false, }) export class TaskClaimComponent { @Input() selectedTask: Task; diff --git a/src/app/units/states/tasks/inbox/inbox.component.html b/src/app/units/states/tasks/inbox/inbox.component.html index 1b29d83c9e..69d07a1205 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.html +++ b/src/app/units/states/tasks/inbox/inbox.component.html @@ -32,7 +32,7 @@ diff --git a/src/app/units/states/tasks/inbox/inbox.component.scss b/src/app/units/states/tasks/inbox/inbox.component.scss index 0b0bc8df17..f8432b637f 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.scss +++ b/src/app/units/states/tasks/inbox/inbox.component.scss @@ -1,42 +1,43 @@ -.staff-task-list {} +.staff-task-list { +} .task-comment-panel { - padding-left: 12px; - padding-bottom: 0px; + padding-left: 12px; + padding-bottom: 0px; - &.mobile { - padding-left: 0px; - padding-bottom: 0px; - margin-bottom: 10px; - } + &.mobile { + padding-left: 0px; + padding-bottom: 0px; + margin-bottom: 10px; + } } .resizer { - background-color: #f5f5f5; - z-index: 200; - width: 10px //css on hover + background-color: #f5f5f5; + z-index: 200; + width: 10px; //css on hover } .resizer:hover, .resizer.hovering { - cursor: col-resize; - background: linear-gradient(white, white) no-repeat center/2px 98%; + cursor: col-resize; + background: linear-gradient(white, white) no-repeat center/2px 98%; } .inbox-panel { - border-radius: 10px; - background-color: white; - padding: 8px; - min-width: 60px; - width: 350px; + border-radius: 10px; + background-color: white; + padding: 8px; + min-width: 60px; + width: 350px; - &.mobile { - max-width: 100%; - width: 100%; - padding: 0px; - } + &.mobile { + max-width: 100%; + width: 100%; + padding: 0px; + } } .task-comment-panel.inbox-panel { - // padding: 0px 0px 0px 5px !important; + // padding: 0px 0px 0px 5px !important; } diff --git a/src/app/units/states/tasks/inbox/inbox.component.spec.ts b/src/app/units/states/tasks/inbox/inbox.component.spec.ts index d90eb5cb30..9112a31a49 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.spec.ts +++ b/src/app/units/states/tasks/inbox/inbox.component.spec.ts @@ -1,6 +1,5 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { InboxComponent } from './inbox.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {InboxComponent} from './inbox.component'; describe('InboxComponent', () => { let component: InboxComponent; @@ -8,9 +7,8 @@ describe('InboxComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ InboxComponent ] - }) - .compileComponents(); + declarations: [InboxComponent], + }).compileComponents(); fixture = TestBed.createComponent(InboxComponent); component = fixture.componentInstance; diff --git a/src/app/units/states/tasks/inbox/inbox.component.ts b/src/app/units/states/tasks/inbox/inbox.component.ts index 1d0bd529d7..8ab1c89aa9 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.ts +++ b/src/app/units/states/tasks/inbox/inbox.component.ts @@ -1,37 +1,37 @@ -import {CdkDragEnd, CdkDragStart, CdkDragMove} from '@angular/cdk/drag-drop'; -import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import {HotkeysHelpComponent, HotkeysService} from '@ngneat/hotkeys'; import {MediaObserver} from 'ng-flex-layout'; -import {auditTime, merge, Observable, of, Subject, tap, withLatestFrom} from 'rxjs'; +import {Observable, Subject, auditTime, merge, of, tap, withLatestFrom} from 'rxjs'; +import {Tutorial} from 'src/app/api/models/doubtfire-model'; import {Task} from 'src/app/api/models/task'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; import {UnitRole} from 'src/app/api/models/unit-role'; +import {UserService} from 'src/app/api/services/user.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {SelectedTaskService} from 'src/app/projects/states/dashboard/selected-task.service'; -import {HotkeysService, HotkeysHelpComponent} from '@ngneat/hotkeys'; +import {CdkDragEnd, CdkDragMove, CdkDragStart} from '@angular/cdk/drag-drop'; +import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; -import {UserService} from 'src/app/api/services/user.service'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; -import {Tutorial} from 'src/app/api/models/doubtfire-model'; -import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Router} from '@angular/router'; @Component({ - selector: 'f-inbox', - templateUrl: './inbox.component.html', - styleUrls: ['./inbox.component.scss'], - standalone: false + selector: 'f-inbox', + templateUrl: './inbox.component.html', + styleUrls: ['./inbox.component.scss'], + standalone: false, }) export class InboxComponent implements OnInit, OnDestroy { @Input() unit: Unit; @Input() unitRole: UnitRole; - @Input() taskData: {selectedTask: Task; any}; + @Input() taskData: {selectedTask: Task}; @Input() loading = false; @Input() filters: Partial<{ taskDefinition: TaskDefinition; tutorials: Tutorial[]; forceStream: boolean; studentName: string; - tutorialIdSelected: any; + tutorialIdSelected: string | number; taskDefinitionIdSelected: number | TaskDefinition; }>; @Input() showSearchOptions: boolean; @@ -42,8 +42,8 @@ export class InboxComponent implements OnInit, OnDestroy { subs$: Observable; - private inboxStartSize$ = new Subject(); - private dragMove$ = new Subject<{event: CdkDragMove; div: HTMLDivElement}>(); + private inboxStartSize$: Subject = new Subject(); + private dragMove$: Subject<{event: CdkDragMove; div: HTMLDivElement}> = new Subject(); private dragMoveAudited$; // protected filters; diff --git a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html index fc283c02a6..066789a0b1 100644 --- a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html +++ b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html @@ -1,10 +1,10 @@ - + diff --git a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts index 7eaf74979d..67850ab1fe 100644 --- a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts +++ b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts @@ -1,5 +1,3 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; import {Observable, first, of, tap} from 'rxjs'; import { ProjectService, @@ -12,8 +10,10 @@ import { } from 'src/app/api/models/doubtfire-model'; import {Task} from 'src/app/api/models/task'; import {TaskService} from 'src/app/api/services/task.service'; -import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; import {SelectedTaskService} from 'src/app/projects/states/dashboard/selected-task.service'; +import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; export type UnitTaskViewType = 'inbox' | 'explorer' | 'moderation' | 'overflow'; export type UnitTaskRouteMode = 'inbox' | 'definition' | 'moderation' | 'overflow'; @@ -46,7 +46,7 @@ type TaskSource = ( }) export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { private static readonly UNIT_REFRESH_INTERVAL_MS = 60_000; - private static readonly lastUnitFetchAt = new Map(); + private static readonly lastUnitFetchAt: Map = new Map(); @Input() public unit$: Observable; @Input() public routeMode: UnitTaskRouteMode = 'inbox'; diff --git a/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.html b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.html index 5ca7a38d06..61c3af38a0 100644 --- a/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.html +++ b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.html @@ -1,4 +1,4 @@ -
    +
    - @switch (taskDef) { @case (taskDef) { @if (taskDef?.hasTaskSheet) { - - - - } @else { - -
    - subtitles_off No Task Sheet -
    - - } } } +
    + @switch (taskDef) { + @case (taskDef) { + @if (taskDef?.hasTaskSheet) { + + } @else { +
    + subtitles_off No Task Sheet +
    + } + } + } diff --git a/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.ts b/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.ts index 68df369f56..8c9460e9fd 100644 --- a/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.ts +++ b/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.ts @@ -1,13 +1,12 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { TaskDefinition } from 'src/app/api/models/task-definition'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {Component, Input} from '@angular/core'; @Component({ - selector: 'f-task-sheet-view', - templateUrl: './task-sheet-view.component.html', - styleUrls: ['./task-sheet-view.component.scss'], - standalone: false + selector: 'f-task-sheet-view', + templateUrl: './task-sheet-view.component.html', + styleUrls: ['./task-sheet-view.component.scss'], + standalone: false, }) export class FTaskSheetViewComponent { @Input() taskDef: TaskDefinition; - } diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index bd2daea1f6..3c473a0d1d 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -2,7 +2,7 @@
    -
    @@ -20,11 +20,11 @@
    -
    +
    @for (taskDef of filteredTaskDefinitions; track taskDef) { @if (taskDef) { -
    -
    -
    +
    +
    +
    {{ taskDef.name }}
    -
    +
    @if (taskDef.isGroupTask()) { - groups + groups } @else { - person + person } -
    +
    {{ taskDef.abbreviation }} - {{ gradeNames[taskDef.targetGrade] }} Task @@ -84,7 +84,7 @@
    @if (taskListItem(taskDef); as task) { -
    +
    @if (task.numNewComments > 0) { {{ task.numNewComments }} } @if (task.similaritiesDetected) { - visibility @@ -119,20 +119,20 @@ } @if (task.hasQualityPoints()) { - {{ task.qualityPts }} + {{ task.qualityPts }} - {{ + {{ task.definition.maxQualityPts }} } @if (task.isDueSoon() && !task.inFinalState()) { - schedule @@ -143,21 +143,21 @@ !task.inFinalState() ) { - schedule } @if (task.isPastDeadline() && !task.inFinalState()) { - schedule - ! + ! }
    @@ -167,12 +167,12 @@ } } @empty { -
    No tasks to display
    +
    No tasks to display
    } @if (mode === 'project' && project) { diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts index 3ac584b5e7..09f4be518b 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts @@ -1,6 +1,5 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { FUnitTaskListComponent } from './unit-task-list.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {FUnitTaskListComponent} from './unit-task-list.component'; describe('FUnitTaskListComponent', () => { let component: FUnitTaskListComponent; diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index 98b76d1036..f52eff58e5 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -1,16 +1,16 @@ +import {BehaviorSubject} from 'rxjs'; +import {Project, Task, TaskDefinition} from 'src/app/api/models/doubtfire-model'; +import {Grade} from 'src/app/api/models/grade'; +import {TaskDefinitionNamePipe} from 'src/app/common/filters/task-definition-name.pipe'; import {Location} from '@angular/common'; import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; -import {Grade} from 'src/app/api/models/grade'; -import {Project, TaskDefinition, Task} from 'src/app/api/models/doubtfire-model'; -import {TaskDefinitionNamePipe} from 'src/app/common/filters/task-definition-name.pipe'; -import {BehaviorSubject} from 'rxjs'; @Component({ - selector: 'f-unit-task-list', - templateUrl: './unit-task-list.component.html', - styleUrls: ['./unit-task-list.component.scss'], - standalone: false + selector: 'f-unit-task-list', + templateUrl: './unit-task-list.component.html', + styleUrls: ['./unit-task-list.component.scss'], + standalone: false, }) export class FUnitTaskListComponent implements OnChanges, OnInit { @Input() mode: 'project' | 'all-tasks'; @@ -152,9 +152,7 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { const unitId = this.route.parent?.snapshot.paramMap.get('unitId'); if (this.route.parent?.snapshot.data.unit && unitId) { return this.angularRouter.createUrlTree( - taskDef - ? ['/units', unitId, 'tasks', taskDef.abbreviation] - : ['/units', unitId, 'tasks'], + taskDef ? ['/units', unitId, 'tasks', taskDef.abbreviation] : ['/units', unitId, 'tasks'], ); } diff --git a/src/app/units/task-viewer/task-viewer-state.component.html b/src/app/units/task-viewer/task-viewer-state.component.html index 3b54723add..ed0f00290b 100644 --- a/src/app/units/task-viewer/task-viewer-state.component.html +++ b/src/app/units/task-viewer/task-viewer-state.component.html @@ -13,9 +13,9 @@
    -
    +
    @if (selectedTaskDefinition$ | async; as selectedTaskDef) { -
    +
    ; @@ -30,9 +30,9 @@ export class TaskViewerStateComponent { } /** - * Monitor and publish the selected task definition for child components. - * We monitor the task definition list for changes in selected task definition. - */ + * Monitor and publish the selected task definition for child components. + * We monitor the task definition list for changes in selected task definition. + */ selectedTaskDefinition$: BehaviorSubject = new BehaviorSubject( null, ); diff --git a/src/app/units/unit-root-state.component.html b/src/app/units/unit-root-state.component.html index 44c6a074e3..c3d939bb5b 100644 --- a/src/app/units/unit-root-state.component.html +++ b/src/app/units/unit-root-state.component.html @@ -2,7 +2,7 @@ } @else {

    Loading unit details...

    diff --git a/src/app/units/unit-root-state.component.ts b/src/app/units/unit-root-state.component.ts index 087b7a7ae4..bdd56dd07d 100644 --- a/src/app/units/unit-root-state.component.ts +++ b/src/app/units/unit-root-state.component.ts @@ -1,14 +1,14 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import {Component, Input, OnInit} from '@angular/core'; -import {ActivatedRoute} from '@angular/router'; import {Observable} from 'rxjs'; import {Unit} from 'src/app/api/models/doubtfire-model'; +import {Component, Input, OnInit} from '@angular/core'; +import {ActivatedRoute} from '@angular/router'; @Component({ - selector: 'f-unit-root-state', - templateUrl: './unit-root-state.component.html', - styleUrl: './unit-root-state.component.css', - standalone: false + selector: 'f-unit-root-state', + templateUrl: './unit-root-state.component.html', + styleUrl: './unit-root-state.component.css', + standalone: false, }) export class UnitRootStateComponent implements OnInit { @Input() public unit$: Observable; diff --git a/src/app/units/unit.resolver.ts b/src/app/units/unit.resolver.ts index 181cafe4fa..a6b42b5ec0 100644 --- a/src/app/units/unit.resolver.ts +++ b/src/app/units/unit.resolver.ts @@ -1,9 +1,9 @@ -import {inject} from '@angular/core'; -import {ResolveFn} from '@angular/router'; import {Observable, first} from 'rxjs'; import {Unit, UnitRole, UnitService, UserService} from 'src/app/api/models/doubtfire-model'; import {AlertService} from 'src/app/common/services/alert.service'; import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; +import {inject} from '@angular/core'; +import {ResolveFn} from '@angular/router'; export const resolveUnit: ResolveFn = (route, state) => { const unitService = inject(UnitService); diff --git a/src/app/visualisations/progress-burndown-chart.scss b/src/app/visualisations/progress-burndown-chart.scss index a3f5591bae..b18611e1f0 100644 --- a/src/app/visualisations/progress-burndown-chart.scss +++ b/src/app/visualisations/progress-burndown-chart.scss @@ -1,13 +1,17 @@ progress-burndown-chart { // Dashed for time line .dashed { - stroke-dasharray: 5,5; + stroke-dasharray: 5, 5; } // :last-child applies to hide time line from legend .nv-legendWrap .nv-series:last-child { display: none; } // since we're hiding time line we can move the rest right - .nv-legend{ transform: translate(50px, -15px); } - .nv-legendWrap{ transform: translate(50px, -15px); } + .nv-legend { + transform: translate(50px, -15px); + } + .nv-legendWrap { + transform: translate(50px, -15px); + } } diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index 25726a1383..15ed9a8795 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -1,6 +1,6 @@ -
    +
    = {}; constructor(public viewContainerRef: ViewContainerRef) { super(viewContainerRef); @@ -100,7 +121,7 @@ export class ProgressBurndownChartComponent extends ChartBaseComponent implement this.data = formattedData; } - onSelect(event): void { + onSelect(event: string | BurndownPoint): void { if (this.isLegend(event)) { const tempData = JSON.parse(JSON.stringify(this.data)); if (this.isDataShown(event)) { @@ -120,7 +141,7 @@ export class ProgressBurndownChartComponent extends ChartBaseComponent implement } } - isLegend(event: any): boolean { + isLegend(event: string | BurndownPoint): event is string { return typeof event === 'string'; } @@ -129,7 +150,7 @@ export class ProgressBurndownChartComponent extends ChartBaseComponent implement return series && series.series.some((point) => point.value !== 0); } - public formatPerc(input) { + public formatPerc(input: number) { return `${input}%`; } } diff --git a/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts index 9b53ff2a30..b7131a9c9a 100644 --- a/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts +++ b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts @@ -1,14 +1,14 @@ -import {Component, OnInit, Input, SimpleChanges} from '@angular/core'; import {Project, TaskStatus} from 'src/app/api/models/doubtfire-model'; import {ChartBaseComponent} from 'src/app/common/chart-base/chart-base-component/chart-base-component.component'; +import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; @Component({ - selector: 'f-task-status-pie-chart', - templateUrl: './task-status-pie-chart.component.html', - styleUrls: ['./task-status-pie-chart.component.scss'], - standalone: false + selector: 'f-task-status-pie-chart', + templateUrl: './task-status-pie-chart.component.html', + styleUrls: ['./task-status-pie-chart.component.scss'], + standalone: false, }) -export class TaskStatusPieChartComponent extends ChartBaseComponent implements OnInit { +export class TaskStatusPieChartComponent extends ChartBaseComponent implements OnChanges, OnInit { @Input() project: Project; @Input() grade: number; diff --git a/src/app/visualisations/task-visualisation/task-visualisation.component.ts b/src/app/visualisations/task-visualisation/task-visualisation.component.ts index 49327c71ff..98948da80d 100644 --- a/src/app/visualisations/task-visualisation/task-visualisation.component.ts +++ b/src/app/visualisations/task-visualisation/task-visualisation.component.ts @@ -1,13 +1,13 @@ -import {Component, OnInit, Input, SimpleChanges} from '@angular/core'; -import {Color} from 'd3'; -import {Project, TaskStatus, TaskStatusEnum} from 'src/app/api/models/doubtfire-model'; +import {Project, TaskStatus} from 'src/app/api/models/doubtfire-model'; +import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; + @Component({ - selector: 'f-task-visualisation', - templateUrl: './task-visualisation.component.html', - styleUrls: ['./task-visualisation.component.scss'], - standalone: false + selector: 'f-task-visualisation', + templateUrl: './task-visualisation.component.html', + styleUrls: ['./task-visualisation.component.scss'], + standalone: false, }) -export class TaskVisualisationComponent implements OnInit { +export class TaskVisualisationComponent implements OnChanges, OnInit { @Input() project: Project; @Input() grade: number; diff --git a/src/app/welcome/welcome.component.html b/src/app/welcome/welcome.component.html index 8d3222ed0d..427ebdb6e2 100644 --- a/src/app/welcome/welcome.component.html +++ b/src/app/welcome/welcome.component.html @@ -2,9 +2,15 @@
    -
    +
    -
    +
    Homepage Logo

    {{ externalName.value }}

    diff --git a/src/app/welcome/welcome.component.spec.ts b/src/app/welcome/welcome.component.spec.ts index 59c1c8d8ef..8c834e5b2b 100644 --- a/src/app/welcome/welcome.component.spec.ts +++ b/src/app/welcome/welcome.component.spec.ts @@ -1,5 +1,5 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { WelcomeComponent } from './welcome.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {WelcomeComponent} from './welcome.component'; describe('WelcomeComponent', () => { let component: WelcomeComponent; diff --git a/src/app/welcome/welcome.component.ts b/src/app/welcome/welcome.component.ts index 3509c456b6..994da25ff3 100644 --- a/src/app/welcome/welcome.component.ts +++ b/src/app/welcome/welcome.component.ts @@ -1,9 +1,9 @@ -import {Component, OnInit} from '@angular/core'; -import {Router} from '@angular/router'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; -import {GlobalStateService} from '../projects/states/index/global-state.service'; +import {Component, OnInit} from '@angular/core'; +import {Router} from '@angular/router'; import {UserService} from '../api/services/user.service'; +import {GlobalStateService} from '../projects/states/index/global-state.service'; @Component({ selector: 'f-welcome', diff --git a/src/assets/images/formatif-isolated-lottie.json b/src/assets/images/formatif-isolated-lottie.json index f934cfb0a7..9b32225328 100644 --- a/src/assets/images/formatif-isolated-lottie.json +++ b/src/assets/images/formatif-isolated-lottie.json @@ -1 +1,3019 @@ -{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.4.3","a":"","k":"","d":"","tc":""},"fr":24,"ip":0,"op":92,"w":3840,"h":2160,"nm":"icon - isolated","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"NULL","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1920,1080,0],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":33,"s":[100,100,100]},{"t":59,"s":[165,165,100]}],"ix":6}},"ao":0,"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":3,"nm":"main position","parent":1,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.167,"y":0.167},"t":36,"s":[50,50,0],"to":[0,0,0],"ti":[0,0,0]},{"t":54,"s":[464,50,0]}],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"scale","parent":2,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":23,"s":[200,200,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":35,"s":[118,118,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":38,"s":[90,90,100]},{"t":49,"s":[100,100,100]}],"ix":6}},"ao":0,"ip":23,"op":240,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":3,"nm":"arrow position","parent":3,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.107,"y":1},"o":{"x":0.533,"y":0},"t":23,"s":[50,-8,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.19,"y":0.642},"o":{"x":0.333,"y":0},"t":35,"s":[119.897,36,0],"to":[0,0,0],"ti":[392.376,75.374,0]},{"i":{"x":0.833,"y":0.874},"o":{"x":1,"y":0.713},"t":38,"s":[-307.61,-289.928,0],"to":[-832.969,-114.56,0],"ti":[20.667,921.704,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.115,"y":1},"t":49,"s":[-374,-134,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.538,"y":1},"o":{"x":1,"y":0},"t":53,"s":[-374,-175,0],"to":[0,0,0],"ti":[1.605,-28.883,0]},{"i":{"x":0.538,"y":1},"o":{"x":0.167,"y":0},"t":59,"s":[-374,37,0],"to":[0,0,0],"ti":[1.605,-28.883,0]},{"t":65,"s":[-374,-8,0]}],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":23,"op":243,"st":3,"bm":0},{"ddd":0,"ind":5,"ty":3,"nm":"rotation","parent":4,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.303],"y":[0]},"t":23,"s":[-45]},{"i":{"x":[0.773],"y":[0.886]},"o":{"x":[0.333],"y":[0]},"t":35,"s":[-45]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.06]},"t":38,"s":[-71]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.089]},"t":42,"s":[-118.941]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.087]},"t":45,"s":[-186.591]},{"t":49,"s":[-360]}],"ix":10},"p":{"a":0,"k":[18.883,127.949,0],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":23,"op":243,"st":3,"bm":0},{"ddd":0,"ind":6,"ty":3,"nm":"rough edges","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1920,1080,0],"ix":2},"a":{"a":0,"k":[1920,1080,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Roughen Edges","np":17,"mn":"ADBE Roughen Edges","ix":1,"en":1,"ef":[{"ty":7,"nm":"Edge Type","mn":"ADBE Roughen Edges-0001","ix":1,"v":{"a":0,"k":1,"ix":1}},{"ty":2,"nm":"Edge Color","mn":"ADBE Roughen Edges-0010","ix":2,"v":{"a":0,"k":[0.6,0.2,0,1],"ix":2}},{"ty":0,"nm":"Border","mn":"ADBE Roughen Edges-0002","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":12,"s":[17.4]},{"t":19,"s":[2.7]}],"ix":3}},{"ty":0,"nm":"Edge Sharpness","mn":"ADBE Roughen Edges-0003","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":12,"s":[1]},{"t":19,"s":[0.1]}],"ix":4}},{"ty":0,"nm":"Fractal Influence","mn":"ADBE Roughen Edges-0004","ix":5,"v":{"a":0,"k":1,"ix":5}},{"ty":0,"nm":"Scale","mn":"ADBE Roughen Edges-0005","ix":6,"v":{"a":0,"k":1000,"ix":6}},{"ty":0,"nm":"Stretch Width or Height","mn":"ADBE Roughen Edges-0006","ix":7,"v":{"a":0,"k":0,"ix":7}},{"ty":3,"nm":"Offset (Turbulence)","mn":"ADBE Roughen Edges-0007","ix":8,"v":{"a":0,"k":[0,0],"ix":8}},{"ty":0,"nm":"Complexity","mn":"ADBE Roughen Edges-0008","ix":9,"v":{"a":0,"k":2,"ix":9}},{"ty":0,"nm":"Evolution","mn":"ADBE Roughen Edges-0009","ix":10,"v":{"a":0,"k":0,"ix":10}},{"ty":6,"nm":"Evolution Options","mn":"ADBE Roughen Edges-0011","ix":11,"v":0},{"ty":7,"nm":"Cycle Evolution","mn":"ADBE Roughen Edges-0012","ix":12,"v":{"a":0,"k":0,"ix":12}},{"ty":0,"nm":"Cycle (in Revolutions)","mn":"ADBE Roughen Edges-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":0,"nm":"Random Seed","mn":"ADBE Roughen Edges-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Random Seed","mn":"ADBE Roughen Edges-0015","ix":15,"v":0}]}],"ip":0,"op":19,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"echo","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1920,1080,0],"ix":2},"a":{"a":0,"k":[1920,1080,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Echo","np":7,"mn":"ADBE Echo","ix":1,"en":1,"ef":[{"ty":0,"nm":"Echo Time (seconds)","mn":"ADBE Echo-0001","ix":1,"v":{"a":0,"k":-0.001,"ix":1}},{"ty":0,"nm":"Number Of Echoes","mn":"ADBE Echo-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":31,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":34,"s":[67]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[67]},{"t":53,"s":[10]}],"ix":2}},{"ty":0,"nm":"Starting Intensity","mn":"ADBE Echo-0003","ix":3,"v":{"a":0,"k":1,"ix":3}},{"ty":0,"nm":"Decay","mn":"ADBE Echo-0004","ix":4,"v":{"a":0,"k":1,"ix":4}},{"ty":7,"nm":"Echo Operator","mn":"ADBE Echo-0005","ix":5,"v":{"a":0,"k":5,"ix":5}}]}],"ip":31,"op":53,"st":3,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"top 2","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[73.565,-23.785,0],"ix":2},"a":{"a":0,"k":[1488.448,1026.164,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"ShapeNir Slider","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":100,"ix":1}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.17,"y":1},"o":{"x":0.167,"y":0},"t":58,"s":[{"i":[[0,0],[0,0],[-13.503,-13.506],[0,0],[9.065,-9.068],[0,0],[0,0],[9.068,9.071],[0,0],[0,0]],"o":[[0,0],[13.506,-13.506],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.074],[0,0],[0,0],[0,0]],"v":[[-61.716,-44.574],[-57.525,-48.766],[-21.582,-61.577],[-24.345,-64.482],[-24.342,-31.648],[-24.342,-31.648],[-24.342,-31.648],[-57.186,-31.645],[-65.907,-40.383],[-61.716,-44.574]],"c":false}]},{"t":64,"s":[{"i":[[0,0],[0,0],[-13.503,-13.506],[0,0],[9.065,-9.068],[0,0],[0,0],[9.068,9.071],[0,0],[0,0]],"o":[[0,0],[13.506,-13.506],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.074],[0,0],[0,0],[0,0]],"v":[[-74.672,-57.386],[-70.481,-61.577],[-21.582,-61.577],[72.063,32.066],[72.066,64.9],[72.066,64.9],[72.066,64.9],[39.223,64.903],[-78.863,-53.195],[-74.672,-57.386]],"c":false}]}],"ix":2},"nm":"Tracciato 1_forAnimation","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.211764708161,0.568627476692,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Riempimento 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1542.448,1082.164],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Gruppo 3","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\nvar mN01 = 52.2496645130989;\nvar mN02 = 100;\nvar mN01Edt = 52.2496645130989;\nvar mN02Edt = 98.6485408913042;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosF = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\nvar mN01 = 52.2496645130989;\nvar mN02 = 0;\nvar mN01Edt = 52.2496645130989;\nvar mN02Edt = 1.35145910869578;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosL = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Taglia tracciati 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":1,"k":[{"i":{"x":0.17,"y":1},"o":{"x":0.167,"y":0},"t":58,"s":[{"i":[[0,0],[5.418,5.419],[17.468,17.469],[25.537,-25.537]],"o":[[-3.662,6.731],[0,0],[-25.536,-25.537],[0,0]],"v":[[1518.105,1050.515],[1501.682,1034.099],[1545.158,1077.713],[1480.731,1037.589]],"c":false}]},{"t":64,"s":[{"i":[[0,0],[5.418,5.419],[17.468,17.469],[25.537,-25.537]],"o":[[-3.662,6.731],[0,0],[-25.536,-25.537],[0,0]],"v":[[1614.514,1147.064],[1598.091,1130.648],[1545.158,1077.713],[1467.776,1024.778]],"c":false}]}],"ix":2},"nm":"Tracciato 1_Bone","mn":"ADBE Vector Shape - Group","hd":false}],"ip":53,"op":126,"st":6,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"top_extra","parent":10,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":29,"s":[1502.093,1035.094,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":34,"s":[1495.062,1036.428,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":51,"s":[1495.062,1036.428,0],"to":[0,0,0],"ti":[0,0,0]},{"t":53,"s":[1502.312,1036.428,0]}],"ix":2},"a":{"a":0,"k":[-98.5,-102,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29,"s":[46.5,46.5,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32,"s":[50,50,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":49,"s":[50,50,100]},{"t":53,"s":[45.2,45.2,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[94,94],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Tracciato ellisse 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.211761474609,0.568603515625,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Riempimento 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-98.5,-102],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellisse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":29,"op":53,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"top","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[73.565,-23.785,0],"ix":2},"a":{"a":0,"k":[1488.448,1026.164,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"ShapeNir Slider","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.17],"y":[1]},"o":{"x":[0.55],"y":[0]},"t":6,"s":[0]},{"t":23,"s":[100]}],"ix":1}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.17,"y":1},"o":{"x":0.55,"y":0},"t":6,"s":[{"i":[[0,0],[0,0],[-13.503,-13.506],[0,0],[9.065,-9.068],[0,0],[0,0],[9.068,9.071],[0,0],[0,0]],"o":[[0,0],[13.506,-13.506],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.074],[0,0],[0,0],[0,0]],"v":[[-74.672,-57.386],[-70.481,-61.577],[-21.582,-61.577],[194.283,154.505],[194.286,187.34],[194.286,187.34],[194.286,187.34],[161.442,187.343],[-78.863,-53.195],[-74.672,-57.386]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.55,"y":0},"t":23,"s":[{"i":[[0,0],[0,0],[-13.503,-13.506],[0,0],[9.065,-9.068],[0,0],[0,0],[9.068,9.071],[0,0],[0,0]],"o":[[0,0],[13.506,-13.506],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.074],[0,0],[0,0],[0,0]],"v":[[-74.672,-57.386],[-70.481,-61.577],[-21.582,-61.577],[72.063,32.066],[72.066,64.9],[72.066,64.9],[72.066,64.9],[39.223,64.903],[-78.863,-53.195],[-74.672,-57.386]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0.167},"t":26,"s":[{"i":[[0,0],[0,0],[-13.503,-13.506],[0,0],[9.065,-9.068],[0,0],[0,0],[9.068,9.071],[2.122,2.171],[0,0]],"o":[[0,0],[13.506,-13.506],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.074],[0,0],[-2.122,-2.171],[0,0]],"v":[[-70.801,-53.558],[-66.61,-57.749],[-21.582,-61.577],[43.259,3.22],[43.262,36.055],[43.262,36.055],[43.262,36.055],[10.419,36.058],[-66.621,-43.95],[-70.801,-53.558]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":29,"s":[{"i":[[0,0],[0,0],[-13.503,-13.506],[0,0],[9.065,-9.068],[0,0],[0,0],[9.068,9.071],[0,0],[0,0]],"o":[[0,0],[13.506,-13.506],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.074],[0,0],[0,0],[0,0]],"v":[[-61.716,-44.574],[-57.525,-48.766],[-21.582,-61.577],[-24.345,-64.482],[-24.342,-31.648],[-24.342,-31.648],[-24.342,-31.648],[-57.186,-31.645],[-65.907,-40.383],[-61.716,-44.574]],"c":false}]},{"i":{"x":0.45,"y":1},"o":{"x":0.167,"y":0},"t":53,"s":[{"i":[[0,0],[0,0],[-13.503,-13.506],[0,0],[9.065,-9.068],[0,0],[0,0],[9.068,9.071],[0,0],[0,0]],"o":[[0,0],[13.506,-13.506],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.074],[0,0],[0,0],[0,0]],"v":[[-61.716,-44.574],[-57.525,-48.766],[-21.582,-61.577],[-24.345,-64.482],[-24.342,-31.648],[-24.342,-31.648],[-24.342,-31.648],[-57.186,-31.645],[-65.907,-40.383],[-61.716,-44.574]],"c":false}]},{"t":59,"s":[{"i":[[0,0],[0,0],[-13.503,-13.506],[0,0],[9.065,-9.068],[0,0],[0,0],[9.068,9.071],[0,0],[0,0]],"o":[[0,0],[13.506,-13.506],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.074],[0,0],[0,0],[0,0]],"v":[[-74.672,-57.386],[-70.481,-61.577],[-21.582,-61.577],[72.063,32.066],[72.066,64.9],[72.066,64.9],[72.066,64.9],[39.223,64.903],[-78.863,-53.195],[-74.672,-57.386]],"c":false}]}],"ix":2},"nm":"Tracciato 1_forAnimation","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.211764708161,0.568627476692,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Riempimento 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1542.448,1082.164],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Gruppo 3","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\nvar mN01 = 52.2496645130989;\nvar mN02 = 100;\nvar mN01Edt = 52.2496645130989;\nvar mN02Edt = 98.6485408913042;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosF = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\nvar mN01 = 52.2496645130989;\nvar mN02 = 0;\nvar mN01Edt = 52.2496645130989;\nvar mN02Edt = 1.35145910869578;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosL = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Taglia tracciati 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":1,"k":[{"i":{"x":0.17,"y":1},"o":{"x":0.55,"y":0},"t":6,"s":[{"i":[[0,0],[5.418,5.419],[17.468,17.469],[25.537,-25.537]],"o":[[-3.662,6.731],[0,0],[-25.536,-25.537],[0,0]],"v":[[1736.734,1269.504],[1720.31,1253.088],[1545.158,1077.713],[1467.776,1024.778]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.55,"y":0},"t":23,"s":[{"i":[[0,0],[5.418,5.419],[17.468,17.469],[25.537,-25.537]],"o":[[-3.662,6.731],[0,0],[-25.536,-25.537],[0,0]],"v":[[1614.514,1147.064],[1598.091,1130.648],[1545.158,1077.713],[1467.776,1024.778]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":29,"s":[{"i":[[0,0],[5.418,5.419],[17.468,17.469],[25.537,-25.537]],"o":[[-3.662,6.731],[0,0],[-25.536,-25.537],[0,0]],"v":[[1518.105,1050.515],[1501.682,1034.099],[1545.158,1077.713],[1480.731,1037.589]],"c":false}]},{"i":{"x":0.45,"y":1},"o":{"x":0.167,"y":0},"t":53,"s":[{"i":[[0,0],[5.418,5.419],[17.468,17.469],[25.537,-25.537]],"o":[[-3.662,6.731],[0,0],[-25.536,-25.537],[0,0]],"v":[[1518.105,1050.515],[1501.682,1034.099],[1545.158,1077.713],[1480.731,1037.589]],"c":false}]},{"t":59,"s":[{"i":[[0,0],[5.418,5.419],[17.468,17.469],[25.537,-25.537]],"o":[[-3.662,6.731],[0,0],[-25.536,-25.537],[0,0]],"v":[[1614.514,1147.064],[1598.091,1130.648],[1545.158,1077.713],[1467.776,1024.778]],"c":false}]}],"ix":2},"nm":"Tracciato 1_Bone","mn":"ADBE Vector Shape - Group","hd":false}],"ip":6,"op":29,"st":6,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"mid 2","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,16,0],"ix":2},"a":{"a":0,"k":[1429.883,1065.949,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"ShapeNir Slider","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":100,"ix":1}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.45,"y":1},"o":{"x":0.167,"y":0},"t":55.5,"s":[{"i":[[0,0],[0,0],[0,0],[6.673,-6.673],[0,0],[0,0],[6.673,6.673],[0,0],[0,0]],"o":[[0,0],[0,0],[6.671,6.673],[0,0],[0,0],[-6.673,6.671],[0,0],[0,0],[0,0]],"v":[[-30.953,-29.75],[-18.872,-41.83],[-9.362,-32.208],[-9.362,-8.045],[-9.362,-8.045],[-9.362,-8.045],[-33.522,-8.045],[-43.033,-17.67],[-30.953,-29.75]],"c":false}]},{"t":61.5,"s":[{"i":[[0,0],[0,0],[0,0],[9.068,-9.068],[0,0],[0,0],[9.068,9.068],[0,0],[0,0]],"o":[[0,0],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.065],[0,0],[0,0],[0,0]],"v":[[-36.143,-36.135],[-19.727,-52.551],[45.759,12.917],[45.759,45.751],[45.759,45.751],[45.759,45.751],[12.927,45.751],[-52.559,-19.719],[-36.143,-36.135]],"c":false}]}],"ix":2},"nm":"Tracciato 1_forAnimation","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.223529413342,0.223529413342,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Riempimento 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1464.883,1099.949],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Gruppo 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\nvar mN01 = 50.0000976522834;\nvar mN02 = 100;\nvar mN01Edt = 50.0000976522834;\nvar mN02Edt = 92.3777446239903;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosF = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\nvar mN01 = 50.0000976522834;\nvar mN02 = 0;\nvar mN01Edt = 50.0000976522834;\nvar mN02Edt = 7.62225537600966;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosL = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Taglia tracciati 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":1,"k":[{"i":{"x":0.45,"y":1},"o":{"x":0.167,"y":0},"t":55.5,"s":[{"i":[[0,0],[11.939,11.936],[0,0]],"o":[[-0.527,-16.874],[-7.951,-7.949],[0,0]],"v":[[1455.522,1091.904],[1458.026,1094.288],[1433.931,1070.199]],"c":false}]},{"t":61.5,"s":[{"i":[[0,0],[16.224,16.22],[0,0]],"o":[[-0.717,-22.93],[-10.805,-10.802],[0,0]],"v":[[1510.642,1145.701],[1461.483,1096.548],[1428.74,1063.814]],"c":false}]}],"ix":2},"nm":"Tracciato 1_Bone","mn":"ADBE Vector Shape - Group","hd":false}],"ip":53,"op":126,"st":3,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"mid_extra","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":29,"s":[1442.756,1079.784,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":34,"s":[1450.145,1086.357,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":51,"s":[1450.145,1086.357,0],"to":[0,0,0],"ti":[0,0,0]},{"t":53,"s":[1443.895,1080.232,0]}],"ix":2},"a":{"a":0,"k":[-120,40,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29,"s":[37.2,37.2,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":34,"s":[50,50,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":49,"s":[50,50,100]},{"t":53,"s":[35.7,35.7,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[93,93],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Tracciato ellisse 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.223510742188,0.223510742188,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Riempimento 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-120,40],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellisse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":29,"op":53,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"mid","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,16,0],"ix":2},"a":{"a":0,"k":[1429.883,1065.949,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"ShapeNir Slider","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.17],"y":[1]},"o":{"x":[0.55],"y":[0]},"t":3,"s":[0]},{"t":23,"s":[100]}],"ix":1}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.17,"y":1},"o":{"x":0.55,"y":0},"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[9.068,-9.068],[0,0],[0,0],[9.068,9.068],[0,0],[0,0]],"o":[[0,0],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.065],[0,0],[0,0],[0,0]],"v":[[-36.143,-36.135],[-19.727,-52.551],[119.506,86.956],[119.506,119.79],[119.506,119.79],[119.506,119.79],[86.674,119.79],[-52.559,-19.719],[-36.143,-36.135]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.55,"y":0},"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[9.068,-9.068],[0,0],[0,0],[9.068,9.068],[0,0],[0,0]],"o":[[0,0],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.065],[0,0],[0,0],[0,0]],"v":[[-36.143,-36.135],[-19.727,-52.551],[45.759,12.917],[45.759,45.751],[45.759,45.751],[45.759,45.751],[12.927,45.751],[-52.559,-19.719],[-36.143,-36.135]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[6.673,-6.673],[0,0],[0,0],[6.673,6.673],[0,0],[0,0]],"o":[[0,0],[0,0],[6.671,6.673],[0,0],[0,0],[-6.673,6.671],[0,0],[0,0],[0,0]],"v":[[-30.953,-29.75],[-18.872,-41.83],[-9.362,-32.208],[-9.362,-8.045],[-9.362,-8.045],[-9.362,-8.045],[-33.522,-8.045],[-43.033,-17.67],[-30.953,-29.75]],"c":false}]},{"i":{"x":0.45,"y":1},"o":{"x":0.167,"y":0},"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[6.673,-6.673],[0,0],[0,0],[6.673,6.673],[0,0],[0,0]],"o":[[0,0],[0,0],[6.671,6.673],[0,0],[0,0],[-6.673,6.671],[0,0],[0,0],[0,0]],"v":[[-30.953,-29.75],[-18.872,-41.83],[-9.362,-32.208],[-9.362,-8.045],[-9.362,-8.045],[-9.362,-8.045],[-33.522,-8.045],[-43.033,-17.67],[-30.953,-29.75]],"c":false}]},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[9.068,-9.068],[0,0],[0,0],[9.068,9.068],[0,0],[0,0]],"o":[[0,0],[0,0],[9.065,9.068],[0,0],[0,0],[-9.068,9.065],[0,0],[0,0],[0,0]],"v":[[-36.143,-36.135],[-19.727,-52.551],[45.759,12.917],[45.759,45.751],[45.759,45.751],[45.759,45.751],[12.927,45.751],[-52.559,-19.719],[-36.143,-36.135]],"c":false}]}],"ix":2},"nm":"Tracciato 1_forAnimation","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.223529413342,0.223529413342,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Riempimento 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1464.883,1099.949],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Gruppo 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\nvar mN01 = 50.0000976522834;\nvar mN02 = 100;\nvar mN01Edt = 50.0000976522834;\nvar mN02Edt = 92.3777446239903;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosF = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\nvar mN01 = 50.0000976522834;\nvar mN02 = 0;\nvar mN01Edt = 50.0000976522834;\nvar mN02Edt = 7.62225537600966;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosL = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Taglia tracciati 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":1,"k":[{"i":{"x":0.17,"y":1},"o":{"x":0.55,"y":0},"t":3,"s":[{"i":[[0,0],[16.224,16.22],[0,0]],"o":[[-0.717,-22.93],[-10.805,-10.802],[0,0]],"v":[[1584.389,1219.739],[1461.483,1096.548],[1428.74,1063.814]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.55,"y":0},"t":23,"s":[{"i":[[0,0],[16.224,16.22],[0,0]],"o":[[-0.717,-22.93],[-10.805,-10.802],[0,0]],"v":[[1510.642,1145.701],[1461.483,1096.548],[1428.74,1063.814]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":29,"s":[{"i":[[0,0],[11.939,11.936],[0,0]],"o":[[-0.527,-16.874],[-7.951,-7.949],[0,0]],"v":[[1455.522,1091.904],[1458.026,1094.288],[1433.931,1070.199]],"c":false}]},{"i":{"x":0.45,"y":1},"o":{"x":0.167,"y":0},"t":53,"s":[{"i":[[0,0],[11.939,11.936],[0,0]],"o":[[-0.527,-16.874],[-7.951,-7.949],[0,0]],"v":[[1455.522,1091.904],[1458.026,1094.288],[1433.931,1070.199]],"c":false}]},{"t":59,"s":[{"i":[[0,0],[16.224,16.22],[0,0]],"o":[[-0.717,-22.93],[-10.805,-10.802],[0,0]],"v":[[1510.642,1145.701],[1461.483,1096.548],[1428.74,1063.814]],"c":false}]}],"ix":2},"nm":"Tracciato 1_Bone","mn":"ADBE Vector Shape - Group","hd":false}],"ip":3,"op":29,"st":3,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"bottom 2","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.559,65.635,0],"ix":2},"a":{"a":0,"k":[1412.324,1115.584,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"ShapeNir Slider","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":100,"ix":1}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.45,"y":1},"o":{"x":0.167,"y":0},"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[6.334,6.334],[-6.333,6.334],[0,0],[0,0]],"o":[[0,0],[0,0],[-6.334,6.333],[-6.334,-6.334],[0,0],[0,0],[0,0]],"v":[[6.738,-2.735],[18.731,9.258],[7.38,20.609],[-16.081,20.083],[-16.606,-3.378],[-5.255,-14.728],[6.738,-2.735]],"c":false}]},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[9.068,9.068],[-9.068,9.068],[0,0],[0,0]],"o":[[0,0],[0,0],[-9.068,9.068],[-9.068,-9.068],[0,0],[0,0],[0,0]],"v":[[11.444,-11.445],[28.615,5.726],[12.364,21.977],[-21.225,21.225],[-21.977,-12.364],[-5.726,-28.615],[11.444,-11.445]],"c":false}]}],"ix":2},"nm":"Tracciato 1_forAnimation","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.337254911661,0.223529413342,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Riempimento 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1399.865,1127.029],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Gruppo 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\nvar mN01 = 50.0000191622908;\nvar mN02 = 100;\nvar mN01Edt = 50.0000191622908;\nvar mN02Edt = 85.6245824308121;\nvar mRatiosM = [\n 0,\n 0.1472024328579,\n 0.50257634091374,\n 1\n ];\nvar mRatiosF = [\n 0,\n 0.31314999326651,\n 0.62416910908086,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\nvar mN01 = 50.0000191622908;\nvar mN02 = 0;\nvar mN01Edt = 50.0000191622908;\nvar mN02Edt = 14.3754175691879;\nvar mRatiosM = [\n 0,\n 0.1472024328579,\n 0.50257634091374,\n 1\n ];\nvar mRatiosL = [\n 0,\n 0.31314966173997,\n 0.62416844828369,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Taglia tracciati 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":1,"k":[{"i":{"x":0.45,"y":1},"o":{"x":0.167,"y":0},"t":53,"s":[{"i":[[0,0],[-1.108,1.108],[-2.676,2.676],[-1.873,1.873],[0,0]],"o":[[0,0],[2.676,-2.676],[0,0],[1.873,-1.873],[0,0]],"v":[[1383.785,1147.112],[1387.144,1143.753],[1395.253,1135.644],[1400.928,1129.969],[1406.603,1124.294]],"c":false}]},{"t":59,"s":[{"i":[[0,0],[-1.587,1.587],[-3.831,3.831],[-2.681,2.681],[0,0]],"o":[[0,0],[3.831,-3.831],[0,0],[2.681,-2.681],[0,0]],"v":[[1378.641,1148.253],[1383.45,1143.444],[1395.059,1131.835],[1403.185,1123.709],[1411.31,1115.584]],"c":false}]}],"ix":2},"nm":"Tracciato 1_Bone","mn":"ADBE Vector Shape - Group","hd":false}],"ip":53,"op":126,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"bottom_extra","parent":16,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":29,"s":[1395.693,1135.648,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":34,"s":[1398.671,1131.534,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":51,"s":[1398.671,1131.534,0],"to":[0,0,0],"ti":[0,0,0]},{"t":53,"s":[1396.171,1134.409,0]}],"ix":2},"a":{"a":0,"k":[-114,181,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29,"s":[38.5,38.5,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":34,"s":[50,50,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":49,"s":[50,50,100]},{"t":53,"s":[37,37,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[91,91],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Tracciato ellisse 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.337249755859,0.223510742188,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Riempimento 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-114,181],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellisse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":29,"op":53,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"bottom","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.559,65.635,0],"ix":2},"a":{"a":0,"k":[1412.324,1115.584,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"ShapeNir Slider","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.17],"y":[1]},"o":{"x":[0.55],"y":[0]},"t":0,"s":[0]},{"t":23,"s":[100]}],"ix":1}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.17,"y":1},"o":{"x":0.55,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[9.068,9.068],[-9.068,9.068],[0,0],[0,0]],"o":[[0,0],[0,0],[-9.068,9.068],[-9.068,-9.068],[0,0],[0,0],[0,0]],"v":[[11.444,-11.445],[28.615,5.726],[-95.63,130.357],[-129.219,129.605],[-129.971,96.016],[-5.726,-28.615],[11.444,-11.445]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.55,"y":0},"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[9.068,9.068],[-9.068,9.068],[0,0],[0,0]],"o":[[0,0],[0,0],[-9.068,9.068],[-9.068,-9.068],[0,0],[0,0],[0,0]],"v":[[11.444,-11.445],[28.615,5.726],[12.364,21.977],[-21.225,21.225],[-21.977,-12.364],[-5.726,-28.615],[11.444,-11.445]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0.167},"t":28,"s":[{"i":[[-3.749,-3.55],[1.525,-6.804],[0,0],[6.838,6.838],[-6.838,6.838],[-5.985,0.184],[0,0]],"o":[[3.749,3.55],[-1.525,6.804],[-6.838,6.838],[-6.838,-6.838],[0,0],[5.985,-0.184],[0,0]],"v":[[12.19,-8.82],[20.555,8.606],[8.3,20.861],[-17.03,20.294],[-17.597,-5.036],[-5.342,-17.291],[12.19,-8.82]],"c":false}]},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[6.334,6.334],[-6.333,6.334],[0,0],[0,0]],"o":[[0,0],[0,0],[-6.334,6.333],[-6.334,-6.334],[0,0],[0,0],[0,0]],"v":[[6.738,-2.735],[18.731,9.258],[7.38,20.609],[-16.081,20.083],[-16.606,-3.378],[-5.255,-14.728],[6.738,-2.735]],"c":false}]}],"ix":2},"nm":"Tracciato 1_forAnimation","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.337254911661,0.223529413342,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Riempimento 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1399.865,1127.029],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Gruppo 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\nvar mN01 = 50.0000191622908;\nvar mN02 = 100;\nvar mN01Edt = 50.0000191622908;\nvar mN02Edt = 85.6245824308121;\nvar mRatiosM = [\n 0,\n 0.1472024328579,\n 0.50257634091374,\n 1\n ];\nvar mRatiosF = [\n 0,\n 0.31314999326651,\n 0.62416910908086,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\nvar mN01 = 50.0000191622908;\nvar mN02 = 0;\nvar mN01Edt = 50.0000191622908;\nvar mN02Edt = 14.3754175691879;\nvar mRatiosM = [\n 0,\n 0.1472024328579,\n 0.50257634091374,\n 1\n ];\nvar mRatiosL = [\n 0,\n 0.31314966173997,\n 0.62416844828369,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;"},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Taglia tracciati 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":1,"k":[{"i":{"x":0.17,"y":1},"o":{"x":0.55,"y":0},"t":0,"s":[{"i":[[0,0],[-1.587,1.587],[-3.831,3.831],[-2.681,2.681],[0,0]],"o":[[0,0],[3.831,-3.831],[0,0],[2.681,-2.681],[0,0]],"v":[[1270.646,1256.634],[1275.455,1251.825],[1287.065,1240.215],[1403.185,1123.709],[1411.31,1115.584]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.55,"y":0},"t":23,"s":[{"i":[[0,0],[-1.587,1.587],[-3.831,3.831],[-2.681,2.681],[0,0]],"o":[[0,0],[3.831,-3.831],[0,0],[2.681,-2.681],[0,0]],"v":[[1378.641,1148.253],[1383.45,1143.444],[1395.059,1131.835],[1403.185,1123.709],[1411.31,1115.584]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0.167},"t":28,"s":[{"i":[[0,0],[-1.197,1.197],[-2.889,2.889],[-2.022,2.022],[0,0]],"o":[[0,0],[2.889,-2.889],[0,0],[2.022,-2.022],[0,0]],"v":[[1382.835,1147.323],[1386.462,1143.696],[1395.217,1134.941],[1401.345,1128.813],[1412.057,1118.207]],"c":false}]},{"t":29,"s":[{"i":[[0,0],[-1.108,1.108],[-2.676,2.676],[-1.873,1.873],[0,0]],"o":[[0,0],[2.676,-2.676],[0,0],[1.873,-1.873],[0,0]],"v":[[1383.785,1147.112],[1387.144,1143.753],[1395.253,1135.644],[1400.928,1129.969],[1406.603,1124.294]],"c":false}]}],"ix":2},"nm":"Tracciato 1_Bone","mn":"ADBE Vector Shape - Group","hd":false}],"ip":0,"op":29,"st":0,"bm":0}],"markers":[]} \ No newline at end of file +{ + "v": "4.8.0", + "meta": {"g": "LottieFiles AE 3.4.3", "a": "", "k": "", "d": "", "tc": ""}, + "fr": 24, + "ip": 0, + "op": 92, + "w": 3840, + "h": 2160, + "nm": "icon - isolated", + "ddd": 0, + "assets": [], + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 3, + "nm": "NULL", + "sr": 1, + "ks": { + "o": {"a": 0, "k": 0, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": {"a": 0, "k": [1920, 1080, 0], "ix": 2}, + "a": {"a": 0, "k": [50, 50, 0], "ix": 1}, + "s": { + "a": 1, + "k": [ + { + "i": {"x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833]}, + "o": {"x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167]}, + "t": 33, + "s": [100, 100, 100] + }, + {"t": 59, "s": [165, 165, 100]} + ], + "ix": 6 + } + }, + "ao": 0, + "ip": 0, + "op": 240, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 2, + "ty": 3, + "nm": "main position", + "parent": 1, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 0, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": { + "a": 1, + "k": [ + { + "i": {"x": 0.2, "y": 1}, + "o": {"x": 0.167, "y": 0.167}, + "t": 36, + "s": [50, 50, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + {"t": 54, "s": [464, 50, 0]} + ], + "ix": 2 + }, + "a": {"a": 0, "k": [50, 50, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ip": 0, + "op": 240, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 3, + "ty": 3, + "nm": "scale", + "parent": 2, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 0, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": {"a": 0, "k": [50, 50, 0], "ix": 2}, + "a": {"a": 0, "k": [50, 50, 0], "ix": 1}, + "s": { + "a": 1, + "k": [ + { + "i": {"x": [0.667, 0.667, 0.667], "y": [1, 1, 1]}, + "o": {"x": [0.333, 0.333, 0.333], "y": [0, 0, 0]}, + "t": 23, + "s": [200, 200, 100] + }, + { + "i": {"x": [0.667, 0.667, 0.667], "y": [1, 1, 1]}, + "o": {"x": [0.333, 0.333, 0.333], "y": [0, 0, 0]}, + "t": 35, + "s": [118, 118, 100] + }, + { + "i": {"x": [0.667, 0.667, 0.667], "y": [1, 1, 1]}, + "o": {"x": [0.333, 0.333, 0.333], "y": [0, 0, 0]}, + "t": 38, + "s": [90, 90, 100] + }, + {"t": 49, "s": [100, 100, 100]} + ], + "ix": 6 + } + }, + "ao": 0, + "ip": 23, + "op": 240, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 4, + "ty": 3, + "nm": "arrow position", + "parent": 3, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 0, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": { + "a": 1, + "k": [ + { + "i": {"x": 0.107, "y": 1}, + "o": {"x": 0.533, "y": 0}, + "t": 23, + "s": [50, -8, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + { + "i": {"x": 0.19, "y": 0.642}, + "o": {"x": 0.333, "y": 0}, + "t": 35, + "s": [119.897, 36, 0], + "to": [0, 0, 0], + "ti": [392.376, 75.374, 0] + }, + { + "i": {"x": 0.833, "y": 0.874}, + "o": {"x": 1, "y": 0.713}, + "t": 38, + "s": [-307.61, -289.928, 0], + "to": [-832.969, -114.56, 0], + "ti": [20.667, 921.704, 0] + }, + { + "i": {"x": 0.667, "y": 1}, + "o": {"x": 0.115, "y": 1}, + "t": 49, + "s": [-374, -134, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + { + "i": {"x": 0.538, "y": 1}, + "o": {"x": 1, "y": 0}, + "t": 53, + "s": [-374, -175, 0], + "to": [0, 0, 0], + "ti": [1.605, -28.883, 0] + }, + { + "i": {"x": 0.538, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 59, + "s": [-374, 37, 0], + "to": [0, 0, 0], + "ti": [1.605, -28.883, 0] + }, + {"t": 65, "s": [-374, -8, 0]} + ], + "ix": 2 + }, + "a": {"a": 0, "k": [50, 50, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ip": 23, + "op": 243, + "st": 3, + "bm": 0 + }, + { + "ddd": 0, + "ind": 5, + "ty": 3, + "nm": "rotation", + "parent": 4, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 0, "ix": 11}, + "r": { + "a": 1, + "k": [ + {"i": {"x": [0.667], "y": [1]}, "o": {"x": [0.303], "y": [0]}, "t": 23, "s": [-45]}, + {"i": {"x": [0.773], "y": [0.886]}, "o": {"x": [0.333], "y": [0]}, "t": 35, "s": [-45]}, + { + "i": {"x": [0.833], "y": [0.833]}, + "o": {"x": [0.167], "y": [0.06]}, + "t": 38, + "s": [-71] + }, + { + "i": {"x": [0.833], "y": [0.833]}, + "o": {"x": [0.167], "y": [0.089]}, + "t": 42, + "s": [-118.941] + }, + { + "i": {"x": [0.667], "y": [1]}, + "o": {"x": [0.167], "y": [0.087]}, + "t": 45, + "s": [-186.591] + }, + {"t": 49, "s": [-360]} + ], + "ix": 10 + }, + "p": {"a": 0, "k": [18.883, 127.949, 0], "ix": 2}, + "a": {"a": 0, "k": [50, 50, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ip": 23, + "op": 243, + "st": 3, + "bm": 0 + }, + { + "ddd": 0, + "ind": 6, + "ty": 3, + "nm": "rough edges", + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": {"a": 0, "k": [1920, 1080, 0], "ix": 2}, + "a": {"a": 0, "k": [1920, 1080, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ef": [ + { + "ty": 5, + "nm": "Roughen Edges", + "np": 17, + "mn": "ADBE Roughen Edges", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 7, + "nm": "Edge Type", + "mn": "ADBE Roughen Edges-0001", + "ix": 1, + "v": {"a": 0, "k": 1, "ix": 1} + }, + { + "ty": 2, + "nm": "Edge Color", + "mn": "ADBE Roughen Edges-0010", + "ix": 2, + "v": {"a": 0, "k": [0.6, 0.2, 0, 1], "ix": 2} + }, + { + "ty": 0, + "nm": "Border", + "mn": "ADBE Roughen Edges-0002", + "ix": 3, + "v": { + "a": 1, + "k": [ + { + "i": {"x": [0.833], "y": [0.833]}, + "o": {"x": [0.167], "y": [0.167]}, + "t": 12, + "s": [17.4] + }, + {"t": 19, "s": [2.7]} + ], + "ix": 3 + } + }, + { + "ty": 0, + "nm": "Edge Sharpness", + "mn": "ADBE Roughen Edges-0003", + "ix": 4, + "v": { + "a": 1, + "k": [ + { + "i": {"x": [0.833], "y": [0.833]}, + "o": {"x": [0.167], "y": [0.167]}, + "t": 12, + "s": [1] + }, + {"t": 19, "s": [0.1]} + ], + "ix": 4 + } + }, + { + "ty": 0, + "nm": "Fractal Influence", + "mn": "ADBE Roughen Edges-0004", + "ix": 5, + "v": {"a": 0, "k": 1, "ix": 5} + }, + { + "ty": 0, + "nm": "Scale", + "mn": "ADBE Roughen Edges-0005", + "ix": 6, + "v": {"a": 0, "k": 1000, "ix": 6} + }, + { + "ty": 0, + "nm": "Stretch Width or Height", + "mn": "ADBE Roughen Edges-0006", + "ix": 7, + "v": {"a": 0, "k": 0, "ix": 7} + }, + { + "ty": 3, + "nm": "Offset (Turbulence)", + "mn": "ADBE Roughen Edges-0007", + "ix": 8, + "v": {"a": 0, "k": [0, 0], "ix": 8} + }, + { + "ty": 0, + "nm": "Complexity", + "mn": "ADBE Roughen Edges-0008", + "ix": 9, + "v": {"a": 0, "k": 2, "ix": 9} + }, + { + "ty": 0, + "nm": "Evolution", + "mn": "ADBE Roughen Edges-0009", + "ix": 10, + "v": {"a": 0, "k": 0, "ix": 10} + }, + {"ty": 6, "nm": "Evolution Options", "mn": "ADBE Roughen Edges-0011", "ix": 11, "v": 0}, + { + "ty": 7, + "nm": "Cycle Evolution", + "mn": "ADBE Roughen Edges-0012", + "ix": 12, + "v": {"a": 0, "k": 0, "ix": 12} + }, + { + "ty": 0, + "nm": "Cycle (in Revolutions)", + "mn": "ADBE Roughen Edges-0013", + "ix": 13, + "v": {"a": 0, "k": 1, "ix": 13} + }, + { + "ty": 0, + "nm": "Random Seed", + "mn": "ADBE Roughen Edges-0014", + "ix": 14, + "v": {"a": 0, "k": 0, "ix": 14} + }, + {"ty": 6, "nm": "Random Seed", "mn": "ADBE Roughen Edges-0015", "ix": 15, "v": 0} + ] + } + ], + "ip": 0, + "op": 19, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 7, + "ty": 3, + "nm": "echo", + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": {"a": 0, "k": [1920, 1080, 0], "ix": 2}, + "a": {"a": 0, "k": [1920, 1080, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ef": [ + { + "ty": 5, + "nm": "Echo", + "np": 7, + "mn": "ADBE Echo", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 0, + "nm": "Echo Time (seconds)", + "mn": "ADBE Echo-0001", + "ix": 1, + "v": {"a": 0, "k": -0.001, "ix": 1} + }, + { + "ty": 0, + "nm": "Number Of Echoes", + "mn": "ADBE Echo-0002", + "ix": 2, + "v": { + "a": 1, + "k": [ + { + "i": {"x": [0.833], "y": [0.833]}, + "o": {"x": [0.167], "y": [0.167]}, + "t": 31, + "s": [10] + }, + { + "i": {"x": [0.833], "y": [0.833]}, + "o": {"x": [0.167], "y": [0.167]}, + "t": 34, + "s": [67] + }, + { + "i": {"x": [0.833], "y": [0.833]}, + "o": {"x": [0.167], "y": [0.167]}, + "t": 49, + "s": [67] + }, + {"t": 53, "s": [10]} + ], + "ix": 2 + } + }, + { + "ty": 0, + "nm": "Starting Intensity", + "mn": "ADBE Echo-0003", + "ix": 3, + "v": {"a": 0, "k": 1, "ix": 3} + }, + { + "ty": 0, + "nm": "Decay", + "mn": "ADBE Echo-0004", + "ix": 4, + "v": {"a": 0, "k": 1, "ix": 4} + }, + { + "ty": 7, + "nm": "Echo Operator", + "mn": "ADBE Echo-0005", + "ix": 5, + "v": {"a": 0, "k": 5, "ix": 5} + } + ] + } + ], + "ip": 31, + "op": 53, + "st": 3, + "bm": 0 + }, + { + "ddd": 0, + "ind": 8, + "ty": 4, + "nm": "top 2", + "parent": 5, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": {"a": 0, "k": [73.565, -23.785, 0], "ix": 2}, + "a": {"a": 0, "k": [1488.448, 1026.164, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ef": [ + { + "ty": 5, + "nm": "ShapeNir Slider", + "np": 3, + "mn": "ADBE Slider Control", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 0, + "nm": "Slider", + "mn": "ADBE Slider Control-0001", + "ix": 1, + "v": {"a": 0, "k": 100, "ix": 1} + } + ] + } + ], + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.17, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 58, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [-13.503, -13.506], + [0, 0], + [9.065, -9.068], + [0, 0], + [0, 0], + [9.068, 9.071], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [13.506, -13.506], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.074], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-61.716, -44.574], + [-57.525, -48.766], + [-21.582, -61.577], + [-24.345, -64.482], + [-24.342, -31.648], + [-24.342, -31.648], + [-24.342, -31.648], + [-57.186, -31.645], + [-65.907, -40.383], + [-61.716, -44.574] + ], + "c": false + } + ] + }, + { + "t": 64, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [-13.503, -13.506], + [0, 0], + [9.065, -9.068], + [0, 0], + [0, 0], + [9.068, 9.071], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [13.506, -13.506], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.074], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-74.672, -57.386], + [-70.481, -61.577], + [-21.582, -61.577], + [72.063, 32.066], + [72.066, 64.9], + [72.066, 64.9], + [72.066, 64.9], + [39.223, 64.903], + [-78.863, -53.195], + [-74.672, -57.386] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_forAnimation", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": {"a": 0, "k": [0.211764708161, 0.568627476692, 1, 1], "ix": 4}, + "o": {"a": 0, "k": 100, "ix": 5}, + "r": 1, + "bm": 0, + "nm": "Riempimento 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": {"a": 0, "k": [1542.448, 1082.164], "ix": 2}, + "a": {"a": 0, "k": [0, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100], "ix": 3}, + "r": {"a": 0, "k": 0, "ix": 6}, + "o": {"a": 0, "k": 100, "ix": 7}, + "sk": {"a": 0, "k": 0, "ix": 4}, + "sa": {"a": 0, "k": 0, "ix": 5}, + "nm": "Transform" + } + ], + "nm": "Gruppo 3", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tm", + "s": { + "a": 0, + "k": 0, + "ix": 1, + "x": "var $bm_rt;\nvar mN01 = 52.2496645130989;\nvar mN02 = 100;\nvar mN01Edt = 52.2496645130989;\nvar mN02Edt = 98.6485408913042;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosF = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "e": { + "a": 0, + "k": 100, + "ix": 2, + "x": "var $bm_rt;\nvar mN01 = 52.2496645130989;\nvar mN02 = 0;\nvar mN01Edt = 52.2496645130989;\nvar mN02Edt = 1.35145910869578;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosL = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "o": {"a": 0, "k": 0, "ix": 3}, + "m": 1, + "ix": 2, + "nm": "Taglia tracciati 1", + "mn": "ADBE Vector Filter - Trim", + "hd": false + }, + { + "ind": 2, + "ty": "sh", + "ix": 3, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.17, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 58, + "s": [ + { + "i": [ + [0, 0], + [5.418, 5.419], + [17.468, 17.469], + [25.537, -25.537] + ], + "o": [ + [-3.662, 6.731], + [0, 0], + [-25.536, -25.537], + [0, 0] + ], + "v": [ + [1518.105, 1050.515], + [1501.682, 1034.099], + [1545.158, 1077.713], + [1480.731, 1037.589] + ], + "c": false + } + ] + }, + { + "t": 64, + "s": [ + { + "i": [ + [0, 0], + [5.418, 5.419], + [17.468, 17.469], + [25.537, -25.537] + ], + "o": [ + [-3.662, 6.731], + [0, 0], + [-25.536, -25.537], + [0, 0] + ], + "v": [ + [1614.514, 1147.064], + [1598.091, 1130.648], + [1545.158, 1077.713], + [1467.776, 1024.778] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_Bone", + "mn": "ADBE Vector Shape - Group", + "hd": false + } + ], + "ip": 53, + "op": 126, + "st": 6, + "bm": 0 + }, + { + "ddd": 0, + "ind": 9, + "ty": 4, + "nm": "top_extra", + "parent": 10, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 45, "ix": 10}, + "p": { + "a": 1, + "k": [ + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.167, "y": 0.167}, + "t": 29, + "s": [1502.093, 1035.094, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.167, "y": 0.167}, + "t": 34, + "s": [1495.062, 1036.428, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.167, "y": 0.167}, + "t": 51, + "s": [1495.062, 1036.428, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + {"t": 53, "s": [1502.312, 1036.428, 0]} + ], + "ix": 2 + }, + "a": {"a": 0, "k": [-98.5, -102, 0], "ix": 1}, + "s": { + "a": 1, + "k": [ + { + "i": {"x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833]}, + "o": {"x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167]}, + "t": 29, + "s": [46.5, 46.5, 100] + }, + { + "i": {"x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833]}, + "o": {"x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167]}, + "t": 32, + "s": [50, 50, 100] + }, + { + "i": {"x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833]}, + "o": {"x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167]}, + "t": 49, + "s": [50, 50, 100] + }, + {"t": 53, "s": [45.2, 45.2, 100]} + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": {"a": 0, "k": [94, 94], "ix": 2}, + "p": {"a": 0, "k": [0, 0], "ix": 3}, + "nm": "Tracciato ellisse 1", + "mn": "ADBE Vector Shape - Ellipse", + "hd": false + }, + { + "ty": "fl", + "c": {"a": 0, "k": [0.211761474609, 0.568603515625, 1, 1], "ix": 4}, + "o": {"a": 0, "k": 100, "ix": 5}, + "r": 1, + "bm": 0, + "nm": "Riempimento 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": {"a": 0, "k": [-98.5, -102], "ix": 2}, + "a": {"a": 0, "k": [0, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100], "ix": 3}, + "r": {"a": 0, "k": 0, "ix": 6}, + "o": {"a": 0, "k": 100, "ix": 7}, + "sk": {"a": 0, "k": 0, "ix": 4}, + "sa": {"a": 0, "k": 0, "ix": 5}, + "nm": "Transform" + } + ], + "nm": "Ellisse 1", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 29, + "op": 53, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 10, + "ty": 4, + "nm": "top", + "parent": 5, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": {"a": 0, "k": [73.565, -23.785, 0], "ix": 2}, + "a": {"a": 0, "k": [1488.448, 1026.164, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ef": [ + { + "ty": 5, + "nm": "ShapeNir Slider", + "np": 3, + "mn": "ADBE Slider Control", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 0, + "nm": "Slider", + "mn": "ADBE Slider Control-0001", + "ix": 1, + "v": { + "a": 1, + "k": [ + {"i": {"x": [0.17], "y": [1]}, "o": {"x": [0.55], "y": [0]}, "t": 6, "s": [0]}, + {"t": 23, "s": [100]} + ], + "ix": 1 + } + } + ] + } + ], + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.17, "y": 1}, + "o": {"x": 0.55, "y": 0}, + "t": 6, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [-13.503, -13.506], + [0, 0], + [9.065, -9.068], + [0, 0], + [0, 0], + [9.068, 9.071], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [13.506, -13.506], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.074], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-74.672, -57.386], + [-70.481, -61.577], + [-21.582, -61.577], + [194.283, 154.505], + [194.286, 187.34], + [194.286, 187.34], + [194.286, 187.34], + [161.442, 187.343], + [-78.863, -53.195], + [-74.672, -57.386] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.55, "y": 0}, + "t": 23, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [-13.503, -13.506], + [0, 0], + [9.065, -9.068], + [0, 0], + [0, 0], + [9.068, 9.071], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [13.506, -13.506], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.074], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-74.672, -57.386], + [-70.481, -61.577], + [-21.582, -61.577], + [72.063, 32.066], + [72.066, 64.9], + [72.066, 64.9], + [72.066, 64.9], + [39.223, 64.903], + [-78.863, -53.195], + [-74.672, -57.386] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 1}, + "o": {"x": 0.167, "y": 0.167}, + "t": 26, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [-13.503, -13.506], + [0, 0], + [9.065, -9.068], + [0, 0], + [0, 0], + [9.068, 9.071], + [2.122, 2.171], + [0, 0] + ], + "o": [ + [0, 0], + [13.506, -13.506], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.074], + [0, 0], + [-2.122, -2.171], + [0, 0] + ], + "v": [ + [-70.801, -53.558], + [-66.61, -57.749], + [-21.582, -61.577], + [43.259, 3.22], + [43.262, 36.055], + [43.262, 36.055], + [43.262, 36.055], + [10.419, 36.058], + [-66.621, -43.95], + [-70.801, -53.558] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 29, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [-13.503, -13.506], + [0, 0], + [9.065, -9.068], + [0, 0], + [0, 0], + [9.068, 9.071], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [13.506, -13.506], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.074], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-61.716, -44.574], + [-57.525, -48.766], + [-21.582, -61.577], + [-24.345, -64.482], + [-24.342, -31.648], + [-24.342, -31.648], + [-24.342, -31.648], + [-57.186, -31.645], + [-65.907, -40.383], + [-61.716, -44.574] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.45, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 53, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [-13.503, -13.506], + [0, 0], + [9.065, -9.068], + [0, 0], + [0, 0], + [9.068, 9.071], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [13.506, -13.506], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.074], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-61.716, -44.574], + [-57.525, -48.766], + [-21.582, -61.577], + [-24.345, -64.482], + [-24.342, -31.648], + [-24.342, -31.648], + [-24.342, -31.648], + [-57.186, -31.645], + [-65.907, -40.383], + [-61.716, -44.574] + ], + "c": false + } + ] + }, + { + "t": 59, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [-13.503, -13.506], + [0, 0], + [9.065, -9.068], + [0, 0], + [0, 0], + [9.068, 9.071], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [13.506, -13.506], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.074], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-74.672, -57.386], + [-70.481, -61.577], + [-21.582, -61.577], + [72.063, 32.066], + [72.066, 64.9], + [72.066, 64.9], + [72.066, 64.9], + [39.223, 64.903], + [-78.863, -53.195], + [-74.672, -57.386] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_forAnimation", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": {"a": 0, "k": [0.211764708161, 0.568627476692, 1, 1], "ix": 4}, + "o": {"a": 0, "k": 100, "ix": 5}, + "r": 1, + "bm": 0, + "nm": "Riempimento 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": {"a": 0, "k": [1542.448, 1082.164], "ix": 2}, + "a": {"a": 0, "k": [0, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100], "ix": 3}, + "r": {"a": 0, "k": 0, "ix": 6}, + "o": {"a": 0, "k": 100, "ix": 7}, + "sk": {"a": 0, "k": 0, "ix": 4}, + "sa": {"a": 0, "k": 0, "ix": 5}, + "nm": "Transform" + } + ], + "nm": "Gruppo 3", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tm", + "s": { + "a": 0, + "k": 0, + "ix": 1, + "x": "var $bm_rt;\nvar mN01 = 52.2496645130989;\nvar mN02 = 100;\nvar mN01Edt = 52.2496645130989;\nvar mN02Edt = 98.6485408913042;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosF = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "e": { + "a": 0, + "k": 100, + "ix": 2, + "x": "var $bm_rt;\nvar mN01 = 52.2496645130989;\nvar mN02 = 0;\nvar mN01Edt = 52.2496645130989;\nvar mN02Edt = 1.35145910869578;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosL = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "o": {"a": 0, "k": 0, "ix": 3}, + "m": 1, + "ix": 2, + "nm": "Taglia tracciati 1", + "mn": "ADBE Vector Filter - Trim", + "hd": false + }, + { + "ind": 2, + "ty": "sh", + "ix": 3, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.17, "y": 1}, + "o": {"x": 0.55, "y": 0}, + "t": 6, + "s": [ + { + "i": [ + [0, 0], + [5.418, 5.419], + [17.468, 17.469], + [25.537, -25.537] + ], + "o": [ + [-3.662, 6.731], + [0, 0], + [-25.536, -25.537], + [0, 0] + ], + "v": [ + [1736.734, 1269.504], + [1720.31, 1253.088], + [1545.158, 1077.713], + [1467.776, 1024.778] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 1}, + "o": {"x": 0.55, "y": 0}, + "t": 23, + "s": [ + { + "i": [ + [0, 0], + [5.418, 5.419], + [17.468, 17.469], + [25.537, -25.537] + ], + "o": [ + [-3.662, 6.731], + [0, 0], + [-25.536, -25.537], + [0, 0] + ], + "v": [ + [1614.514, 1147.064], + [1598.091, 1130.648], + [1545.158, 1077.713], + [1467.776, 1024.778] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 29, + "s": [ + { + "i": [ + [0, 0], + [5.418, 5.419], + [17.468, 17.469], + [25.537, -25.537] + ], + "o": [ + [-3.662, 6.731], + [0, 0], + [-25.536, -25.537], + [0, 0] + ], + "v": [ + [1518.105, 1050.515], + [1501.682, 1034.099], + [1545.158, 1077.713], + [1480.731, 1037.589] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.45, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 53, + "s": [ + { + "i": [ + [0, 0], + [5.418, 5.419], + [17.468, 17.469], + [25.537, -25.537] + ], + "o": [ + [-3.662, 6.731], + [0, 0], + [-25.536, -25.537], + [0, 0] + ], + "v": [ + [1518.105, 1050.515], + [1501.682, 1034.099], + [1545.158, 1077.713], + [1480.731, 1037.589] + ], + "c": false + } + ] + }, + { + "t": 59, + "s": [ + { + "i": [ + [0, 0], + [5.418, 5.419], + [17.468, 17.469], + [25.537, -25.537] + ], + "o": [ + [-3.662, 6.731], + [0, 0], + [-25.536, -25.537], + [0, 0] + ], + "v": [ + [1614.514, 1147.064], + [1598.091, 1130.648], + [1545.158, 1077.713], + [1467.776, 1024.778] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_Bone", + "mn": "ADBE Vector Shape - Group", + "hd": false + } + ], + "ip": 6, + "op": 29, + "st": 6, + "bm": 0 + }, + { + "ddd": 0, + "ind": 11, + "ty": 4, + "nm": "mid 2", + "parent": 5, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": {"a": 0, "k": [15, 16, 0], "ix": 2}, + "a": {"a": 0, "k": [1429.883, 1065.949, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ef": [ + { + "ty": 5, + "nm": "ShapeNir Slider", + "np": 3, + "mn": "ADBE Slider Control", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 0, + "nm": "Slider", + "mn": "ADBE Slider Control-0001", + "ix": 1, + "v": {"a": 0, "k": 100, "ix": 1} + } + ] + } + ], + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.45, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 55.5, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [6.673, -6.673], + [0, 0], + [0, 0], + [6.673, 6.673], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [6.671, 6.673], + [0, 0], + [0, 0], + [-6.673, 6.671], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-30.953, -29.75], + [-18.872, -41.83], + [-9.362, -32.208], + [-9.362, -8.045], + [-9.362, -8.045], + [-9.362, -8.045], + [-33.522, -8.045], + [-43.033, -17.67], + [-30.953, -29.75] + ], + "c": false + } + ] + }, + { + "t": 61.5, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [9.068, -9.068], + [0, 0], + [0, 0], + [9.068, 9.068], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.065], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-36.143, -36.135], + [-19.727, -52.551], + [45.759, 12.917], + [45.759, 45.751], + [45.759, 45.751], + [45.759, 45.751], + [12.927, 45.751], + [-52.559, -19.719], + [-36.143, -36.135] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_forAnimation", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": {"a": 0, "k": [0.223529413342, 0.223529413342, 1, 1], "ix": 4}, + "o": {"a": 0, "k": 100, "ix": 5}, + "r": 1, + "bm": 0, + "nm": "Riempimento 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": {"a": 0, "k": [1464.883, 1099.949], "ix": 2}, + "a": {"a": 0, "k": [0, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100], "ix": 3}, + "r": {"a": 0, "k": 0, "ix": 6}, + "o": {"a": 0, "k": 100, "ix": 7}, + "sk": {"a": 0, "k": 0, "ix": 4}, + "sa": {"a": 0, "k": 0, "ix": 5}, + "nm": "Transform" + } + ], + "nm": "Gruppo 2", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tm", + "s": { + "a": 0, + "k": 0, + "ix": 1, + "x": "var $bm_rt;\nvar mN01 = 50.0000976522834;\nvar mN02 = 100;\nvar mN01Edt = 50.0000976522834;\nvar mN02Edt = 92.3777446239903;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosF = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "e": { + "a": 0, + "k": 100, + "ix": 2, + "x": "var $bm_rt;\nvar mN01 = 50.0000976522834;\nvar mN02 = 0;\nvar mN01Edt = 50.0000976522834;\nvar mN02Edt = 7.62225537600966;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosL = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "o": {"a": 0, "k": 0, "ix": 3}, + "m": 1, + "ix": 2, + "nm": "Taglia tracciati 1", + "mn": "ADBE Vector Filter - Trim", + "hd": false + }, + { + "ind": 2, + "ty": "sh", + "ix": 3, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.45, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 55.5, + "s": [ + { + "i": [ + [0, 0], + [11.939, 11.936], + [0, 0] + ], + "o": [ + [-0.527, -16.874], + [-7.951, -7.949], + [0, 0] + ], + "v": [ + [1455.522, 1091.904], + [1458.026, 1094.288], + [1433.931, 1070.199] + ], + "c": false + } + ] + }, + { + "t": 61.5, + "s": [ + { + "i": [ + [0, 0], + [16.224, 16.22], + [0, 0] + ], + "o": [ + [-0.717, -22.93], + [-10.805, -10.802], + [0, 0] + ], + "v": [ + [1510.642, 1145.701], + [1461.483, 1096.548], + [1428.74, 1063.814] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_Bone", + "mn": "ADBE Vector Shape - Group", + "hd": false + } + ], + "ip": 53, + "op": 126, + "st": 3, + "bm": 0 + }, + { + "ddd": 0, + "ind": 12, + "ty": 4, + "nm": "mid_extra", + "parent": 13, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 45, "ix": 10}, + "p": { + "a": 1, + "k": [ + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.167, "y": 0.167}, + "t": 29, + "s": [1442.756, 1079.784, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.167, "y": 0.167}, + "t": 34, + "s": [1450.145, 1086.357, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.167, "y": 0.167}, + "t": 51, + "s": [1450.145, 1086.357, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + {"t": 53, "s": [1443.895, 1080.232, 0]} + ], + "ix": 2 + }, + "a": {"a": 0, "k": [-120, 40, 0], "ix": 1}, + "s": { + "a": 1, + "k": [ + { + "i": {"x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833]}, + "o": {"x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167]}, + "t": 29, + "s": [37.2, 37.2, 100] + }, + { + "i": {"x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833]}, + "o": {"x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167]}, + "t": 34, + "s": [50, 50, 100] + }, + { + "i": {"x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833]}, + "o": {"x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167]}, + "t": 49, + "s": [50, 50, 100] + }, + {"t": 53, "s": [35.7, 35.7, 100]} + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": {"a": 0, "k": [93, 93], "ix": 2}, + "p": {"a": 0, "k": [0, 0], "ix": 3}, + "nm": "Tracciato ellisse 1", + "mn": "ADBE Vector Shape - Ellipse", + "hd": false + }, + { + "ty": "fl", + "c": {"a": 0, "k": [0.223510742188, 0.223510742188, 1, 1], "ix": 4}, + "o": {"a": 0, "k": 100, "ix": 5}, + "r": 1, + "bm": 0, + "nm": "Riempimento 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": {"a": 0, "k": [-120, 40], "ix": 2}, + "a": {"a": 0, "k": [0, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100], "ix": 3}, + "r": {"a": 0, "k": 0, "ix": 6}, + "o": {"a": 0, "k": 100, "ix": 7}, + "sk": {"a": 0, "k": 0, "ix": 4}, + "sa": {"a": 0, "k": 0, "ix": 5}, + "nm": "Transform" + } + ], + "nm": "Ellisse 1", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 29, + "op": 53, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 13, + "ty": 4, + "nm": "mid", + "parent": 5, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": {"a": 0, "k": [15, 16, 0], "ix": 2}, + "a": {"a": 0, "k": [1429.883, 1065.949, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ef": [ + { + "ty": 5, + "nm": "ShapeNir Slider", + "np": 3, + "mn": "ADBE Slider Control", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 0, + "nm": "Slider", + "mn": "ADBE Slider Control-0001", + "ix": 1, + "v": { + "a": 1, + "k": [ + {"i": {"x": [0.17], "y": [1]}, "o": {"x": [0.55], "y": [0]}, "t": 3, "s": [0]}, + {"t": 23, "s": [100]} + ], + "ix": 1 + } + } + ] + } + ], + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.17, "y": 1}, + "o": {"x": 0.55, "y": 0}, + "t": 3, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [9.068, -9.068], + [0, 0], + [0, 0], + [9.068, 9.068], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.065], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-36.143, -36.135], + [-19.727, -52.551], + [119.506, 86.956], + [119.506, 119.79], + [119.506, 119.79], + [119.506, 119.79], + [86.674, 119.79], + [-52.559, -19.719], + [-36.143, -36.135] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 1}, + "o": {"x": 0.55, "y": 0}, + "t": 23, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [9.068, -9.068], + [0, 0], + [0, 0], + [9.068, 9.068], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.065], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-36.143, -36.135], + [-19.727, -52.551], + [45.759, 12.917], + [45.759, 45.751], + [45.759, 45.751], + [45.759, 45.751], + [12.927, 45.751], + [-52.559, -19.719], + [-36.143, -36.135] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 29, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [6.673, -6.673], + [0, 0], + [0, 0], + [6.673, 6.673], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [6.671, 6.673], + [0, 0], + [0, 0], + [-6.673, 6.671], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-30.953, -29.75], + [-18.872, -41.83], + [-9.362, -32.208], + [-9.362, -8.045], + [-9.362, -8.045], + [-9.362, -8.045], + [-33.522, -8.045], + [-43.033, -17.67], + [-30.953, -29.75] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.45, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 53, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [6.673, -6.673], + [0, 0], + [0, 0], + [6.673, 6.673], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [6.671, 6.673], + [0, 0], + [0, 0], + [-6.673, 6.671], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-30.953, -29.75], + [-18.872, -41.83], + [-9.362, -32.208], + [-9.362, -8.045], + [-9.362, -8.045], + [-9.362, -8.045], + [-33.522, -8.045], + [-43.033, -17.67], + [-30.953, -29.75] + ], + "c": false + } + ] + }, + { + "t": 59, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [9.068, -9.068], + [0, 0], + [0, 0], + [9.068, 9.068], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [9.065, 9.068], + [0, 0], + [0, 0], + [-9.068, 9.065], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [-36.143, -36.135], + [-19.727, -52.551], + [45.759, 12.917], + [45.759, 45.751], + [45.759, 45.751], + [45.759, 45.751], + [12.927, 45.751], + [-52.559, -19.719], + [-36.143, -36.135] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_forAnimation", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": {"a": 0, "k": [0.223529413342, 0.223529413342, 1, 1], "ix": 4}, + "o": {"a": 0, "k": 100, "ix": 5}, + "r": 1, + "bm": 0, + "nm": "Riempimento 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": {"a": 0, "k": [1464.883, 1099.949], "ix": 2}, + "a": {"a": 0, "k": [0, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100], "ix": 3}, + "r": {"a": 0, "k": 0, "ix": 6}, + "o": {"a": 0, "k": 100, "ix": 7}, + "sk": {"a": 0, "k": 0, "ix": 4}, + "sa": {"a": 0, "k": 0, "ix": 5}, + "nm": "Transform" + } + ], + "nm": "Gruppo 2", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tm", + "s": { + "a": 0, + "k": 0, + "ix": 1, + "x": "var $bm_rt;\nvar mN01 = 50.0000976522834;\nvar mN02 = 100;\nvar mN01Edt = 50.0000976522834;\nvar mN02Edt = 92.3777446239903;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosF = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "e": { + "a": 0, + "k": 100, + "ix": 2, + "x": "var $bm_rt;\nvar mN01 = 50.0000976522834;\nvar mN02 = 0;\nvar mN01Edt = 50.0000976522834;\nvar mN02Edt = 7.62225537600966;\nvar mRatiosM = [\n 0,\n 1\n ];\nvar mRatiosL = [\n 0,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "o": {"a": 0, "k": 0, "ix": 3}, + "m": 1, + "ix": 2, + "nm": "Taglia tracciati 1", + "mn": "ADBE Vector Filter - Trim", + "hd": false + }, + { + "ind": 2, + "ty": "sh", + "ix": 3, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.17, "y": 1}, + "o": {"x": 0.55, "y": 0}, + "t": 3, + "s": [ + { + "i": [ + [0, 0], + [16.224, 16.22], + [0, 0] + ], + "o": [ + [-0.717, -22.93], + [-10.805, -10.802], + [0, 0] + ], + "v": [ + [1584.389, 1219.739], + [1461.483, 1096.548], + [1428.74, 1063.814] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 1}, + "o": {"x": 0.55, "y": 0}, + "t": 23, + "s": [ + { + "i": [ + [0, 0], + [16.224, 16.22], + [0, 0] + ], + "o": [ + [-0.717, -22.93], + [-10.805, -10.802], + [0, 0] + ], + "v": [ + [1510.642, 1145.701], + [1461.483, 1096.548], + [1428.74, 1063.814] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 29, + "s": [ + { + "i": [ + [0, 0], + [11.939, 11.936], + [0, 0] + ], + "o": [ + [-0.527, -16.874], + [-7.951, -7.949], + [0, 0] + ], + "v": [ + [1455.522, 1091.904], + [1458.026, 1094.288], + [1433.931, 1070.199] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.45, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 53, + "s": [ + { + "i": [ + [0, 0], + [11.939, 11.936], + [0, 0] + ], + "o": [ + [-0.527, -16.874], + [-7.951, -7.949], + [0, 0] + ], + "v": [ + [1455.522, 1091.904], + [1458.026, 1094.288], + [1433.931, 1070.199] + ], + "c": false + } + ] + }, + { + "t": 59, + "s": [ + { + "i": [ + [0, 0], + [16.224, 16.22], + [0, 0] + ], + "o": [ + [-0.717, -22.93], + [-10.805, -10.802], + [0, 0] + ], + "v": [ + [1510.642, 1145.701], + [1461.483, 1096.548], + [1428.74, 1063.814] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_Bone", + "mn": "ADBE Vector Shape - Group", + "hd": false + } + ], + "ip": 3, + "op": 29, + "st": 3, + "bm": 0 + }, + { + "ddd": 0, + "ind": 14, + "ty": 4, + "nm": "bottom 2", + "parent": 5, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": {"a": 0, "k": [-2.559, 65.635, 0], "ix": 2}, + "a": {"a": 0, "k": [1412.324, 1115.584, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ef": [ + { + "ty": 5, + "nm": "ShapeNir Slider", + "np": 3, + "mn": "ADBE Slider Control", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 0, + "nm": "Slider", + "mn": "ADBE Slider Control-0001", + "ix": 1, + "v": {"a": 0, "k": 100, "ix": 1} + } + ] + } + ], + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.45, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 53, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [6.334, 6.334], + [-6.333, 6.334], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [-6.334, 6.333], + [-6.334, -6.334], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [6.738, -2.735], + [18.731, 9.258], + [7.38, 20.609], + [-16.081, 20.083], + [-16.606, -3.378], + [-5.255, -14.728], + [6.738, -2.735] + ], + "c": false + } + ] + }, + { + "t": 59, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [9.068, 9.068], + [-9.068, 9.068], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [-9.068, 9.068], + [-9.068, -9.068], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [11.444, -11.445], + [28.615, 5.726], + [12.364, 21.977], + [-21.225, 21.225], + [-21.977, -12.364], + [-5.726, -28.615], + [11.444, -11.445] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_forAnimation", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": {"a": 0, "k": [0.337254911661, 0.223529413342, 1, 1], "ix": 4}, + "o": {"a": 0, "k": 100, "ix": 5}, + "r": 1, + "bm": 0, + "nm": "Riempimento 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": {"a": 0, "k": [1399.865, 1127.029], "ix": 2}, + "a": {"a": 0, "k": [0, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100], "ix": 3}, + "r": {"a": 0, "k": 0, "ix": 6}, + "o": {"a": 0, "k": 100, "ix": 7}, + "sk": {"a": 0, "k": 0, "ix": 4}, + "sa": {"a": 0, "k": 0, "ix": 5}, + "nm": "Transform" + } + ], + "nm": "Gruppo 1", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tm", + "s": { + "a": 0, + "k": 0, + "ix": 1, + "x": "var $bm_rt;\nvar mN01 = 50.0000191622908;\nvar mN02 = 100;\nvar mN01Edt = 50.0000191622908;\nvar mN02Edt = 85.6245824308121;\nvar mRatiosM = [\n 0,\n 0.1472024328579,\n 0.50257634091374,\n 1\n ];\nvar mRatiosF = [\n 0,\n 0.31314999326651,\n 0.62416910908086,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "e": { + "a": 0, + "k": 100, + "ix": 2, + "x": "var $bm_rt;\nvar mN01 = 50.0000191622908;\nvar mN02 = 0;\nvar mN01Edt = 50.0000191622908;\nvar mN02Edt = 14.3754175691879;\nvar mRatiosM = [\n 0,\n 0.1472024328579,\n 0.50257634091374,\n 1\n ];\nvar mRatiosL = [\n 0,\n 0.31314966173997,\n 0.62416844828369,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "o": {"a": 0, "k": 0, "ix": 3}, + "m": 1, + "ix": 2, + "nm": "Taglia tracciati 1", + "mn": "ADBE Vector Filter - Trim", + "hd": false + }, + { + "ind": 2, + "ty": "sh", + "ix": 3, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.45, "y": 1}, + "o": {"x": 0.167, "y": 0}, + "t": 53, + "s": [ + { + "i": [ + [0, 0], + [-1.108, 1.108], + [-2.676, 2.676], + [-1.873, 1.873], + [0, 0] + ], + "o": [ + [0, 0], + [2.676, -2.676], + [0, 0], + [1.873, -1.873], + [0, 0] + ], + "v": [ + [1383.785, 1147.112], + [1387.144, 1143.753], + [1395.253, 1135.644], + [1400.928, 1129.969], + [1406.603, 1124.294] + ], + "c": false + } + ] + }, + { + "t": 59, + "s": [ + { + "i": [ + [0, 0], + [-1.587, 1.587], + [-3.831, 3.831], + [-2.681, 2.681], + [0, 0] + ], + "o": [ + [0, 0], + [3.831, -3.831], + [0, 0], + [2.681, -2.681], + [0, 0] + ], + "v": [ + [1378.641, 1148.253], + [1383.45, 1143.444], + [1395.059, 1131.835], + [1403.185, 1123.709], + [1411.31, 1115.584] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_Bone", + "mn": "ADBE Vector Shape - Group", + "hd": false + } + ], + "ip": 53, + "op": 126, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 15, + "ty": 4, + "nm": "bottom_extra", + "parent": 16, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 45, "ix": 10}, + "p": { + "a": 1, + "k": [ + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.167, "y": 0.167}, + "t": 29, + "s": [1395.693, 1135.648, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.167, "y": 0.167}, + "t": 34, + "s": [1398.671, 1131.534, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.167, "y": 0.167}, + "t": 51, + "s": [1398.671, 1131.534, 0], + "to": [0, 0, 0], + "ti": [0, 0, 0] + }, + {"t": 53, "s": [1396.171, 1134.409, 0]} + ], + "ix": 2 + }, + "a": {"a": 0, "k": [-114, 181, 0], "ix": 1}, + "s": { + "a": 1, + "k": [ + { + "i": {"x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833]}, + "o": {"x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167]}, + "t": 29, + "s": [38.5, 38.5, 100] + }, + { + "i": {"x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833]}, + "o": {"x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167]}, + "t": 34, + "s": [50, 50, 100] + }, + { + "i": {"x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833]}, + "o": {"x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167]}, + "t": 49, + "s": [50, 50, 100] + }, + {"t": 53, "s": [37, 37, 100]} + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": {"a": 0, "k": [91, 91], "ix": 2}, + "p": {"a": 0, "k": [0, 0], "ix": 3}, + "nm": "Tracciato ellisse 1", + "mn": "ADBE Vector Shape - Ellipse", + "hd": false + }, + { + "ty": "fl", + "c": {"a": 0, "k": [0.337249755859, 0.223510742188, 1, 1], "ix": 4}, + "o": {"a": 0, "k": 100, "ix": 5}, + "r": 1, + "bm": 0, + "nm": "Riempimento 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": {"a": 0, "k": [-114, 181], "ix": 2}, + "a": {"a": 0, "k": [0, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100], "ix": 3}, + "r": {"a": 0, "k": 0, "ix": 6}, + "o": {"a": 0, "k": 100, "ix": 7}, + "sk": {"a": 0, "k": 0, "ix": 4}, + "sa": {"a": 0, "k": 0, "ix": 5}, + "nm": "Transform" + } + ], + "nm": "Ellisse 1", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 29, + "op": 53, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 16, + "ty": 4, + "nm": "bottom", + "parent": 5, + "sr": 1, + "ks": { + "o": {"a": 0, "k": 100, "ix": 11}, + "r": {"a": 0, "k": 0, "ix": 10}, + "p": {"a": 0, "k": [-2.559, 65.635, 0], "ix": 2}, + "a": {"a": 0, "k": [1412.324, 1115.584, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100, 100], "ix": 6} + }, + "ao": 0, + "ef": [ + { + "ty": 5, + "nm": "ShapeNir Slider", + "np": 3, + "mn": "ADBE Slider Control", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 0, + "nm": "Slider", + "mn": "ADBE Slider Control-0001", + "ix": 1, + "v": { + "a": 1, + "k": [ + {"i": {"x": [0.17], "y": [1]}, "o": {"x": [0.55], "y": [0]}, "t": 0, "s": [0]}, + {"t": 23, "s": [100]} + ], + "ix": 1 + } + } + ] + } + ], + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.17, "y": 1}, + "o": {"x": 0.55, "y": 0}, + "t": 0, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [9.068, 9.068], + [-9.068, 9.068], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [-9.068, 9.068], + [-9.068, -9.068], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [11.444, -11.445], + [28.615, 5.726], + [-95.63, 130.357], + [-129.219, 129.605], + [-129.971, 96.016], + [-5.726, -28.615], + [11.444, -11.445] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.55, "y": 0}, + "t": 23, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [9.068, 9.068], + [-9.068, 9.068], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [-9.068, 9.068], + [-9.068, -9.068], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [11.444, -11.445], + [28.615, 5.726], + [12.364, 21.977], + [-21.225, 21.225], + [-21.977, -12.364], + [-5.726, -28.615], + [11.444, -11.445] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 1}, + "o": {"x": 0.167, "y": 0.167}, + "t": 28, + "s": [ + { + "i": [ + [-3.749, -3.55], + [1.525, -6.804], + [0, 0], + [6.838, 6.838], + [-6.838, 6.838], + [-5.985, 0.184], + [0, 0] + ], + "o": [ + [3.749, 3.55], + [-1.525, 6.804], + [-6.838, 6.838], + [-6.838, -6.838], + [0, 0], + [5.985, -0.184], + [0, 0] + ], + "v": [ + [12.19, -8.82], + [20.555, 8.606], + [8.3, 20.861], + [-17.03, 20.294], + [-17.597, -5.036], + [-5.342, -17.291], + [12.19, -8.82] + ], + "c": false + } + ] + }, + { + "t": 29, + "s": [ + { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [6.334, 6.334], + [-6.333, 6.334], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [-6.334, 6.333], + [-6.334, -6.334], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [6.738, -2.735], + [18.731, 9.258], + [7.38, 20.609], + [-16.081, 20.083], + [-16.606, -3.378], + [-5.255, -14.728], + [6.738, -2.735] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_forAnimation", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": {"a": 0, "k": [0.337254911661, 0.223529413342, 1, 1], "ix": 4}, + "o": {"a": 0, "k": 100, "ix": 5}, + "r": 1, + "bm": 0, + "nm": "Riempimento 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": {"a": 0, "k": [1399.865, 1127.029], "ix": 2}, + "a": {"a": 0, "k": [0, 0], "ix": 1}, + "s": {"a": 0, "k": [100, 100], "ix": 3}, + "r": {"a": 0, "k": 0, "ix": 6}, + "o": {"a": 0, "k": 100, "ix": 7}, + "sk": {"a": 0, "k": 0, "ix": 4}, + "sa": {"a": 0, "k": 0, "ix": 5}, + "nm": "Transform" + } + ], + "nm": "Gruppo 1", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tm", + "s": { + "a": 0, + "k": 0, + "ix": 1, + "x": "var $bm_rt;\nvar mN01 = 50.0000191622908;\nvar mN02 = 100;\nvar mN01Edt = 50.0000191622908;\nvar mN02Edt = 85.6245824308121;\nvar mRatiosM = [\n 0,\n 0.1472024328579,\n 0.50257634091374,\n 1\n ];\nvar mRatiosF = [\n 0,\n 0.31314999326651,\n 0.62416910908086,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosF[$bm_sub(i, 1)], mRatiosF[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "e": { + "a": 0, + "k": 100, + "ix": 2, + "x": "var $bm_rt;\nvar mN01 = 50.0000191622908;\nvar mN02 = 0;\nvar mN01Edt = 50.0000191622908;\nvar mN02Edt = 14.3754175691879;\nvar mRatiosM = [\n 0,\n 0.1472024328579,\n 0.50257634091374,\n 1\n ];\nvar mRatiosL = [\n 0,\n 0.31314966173997,\n 0.62416844828369,\n 1\n ];\nfunction mLinear(aInput, aInNumF, aInNumL, aOutNumF, aOutNumL) {\n var mInputLgt = $bm_sub(aInNumL, aInNumF);\n var mOutputLgt = $bm_sub(aOutNumL, aOutNumF);\n var mRatio = $bm_div(mOutputLgt, mInputLgt);\n if (aInNumF <= aInput && aInput <= aInNumL) {\n var mOutput = $bm_sum($bm_mul($bm_sub(aInput, aInNumF), mRatio), aOutNumF);\n } else {\n var mOutput = aInput;\n }\n return mOutput;\n}\nvar mSld = $bm_div(thisLayer('ADBE Effect Parade')('ShapeNir Slider')('ADBE Slider Control-0001'), 100);\nif (mSld <= 0) {\n var mRst = mN01;\n} else if (mSld >= 1) {\n var mRst = mN02;\n} else {\n for (var i = 1; i < mRatiosM.length; i++) {\n if (mRatiosM[i - 1] <= mSld && mSld < mRatiosM[i]) {\n var mCtl = mLinear(mSld, mRatiosM[$bm_sub(i, 1)], mRatiosM[i], mRatiosL[$bm_sub(i, 1)], mRatiosL[i]);\n break;\n }\n }\n var mRst = mLinear(mCtl, 0, 1, mN01Edt, mN02Edt);\n}\n$bm_rt = mRst;" + }, + "o": {"a": 0, "k": 0, "ix": 3}, + "m": 1, + "ix": 2, + "nm": "Taglia tracciati 1", + "mn": "ADBE Vector Filter - Trim", + "hd": false + }, + { + "ind": 2, + "ty": "sh", + "ix": 3, + "ks": { + "a": 1, + "k": [ + { + "i": {"x": 0.17, "y": 1}, + "o": {"x": 0.55, "y": 0}, + "t": 0, + "s": [ + { + "i": [ + [0, 0], + [-1.587, 1.587], + [-3.831, 3.831], + [-2.681, 2.681], + [0, 0] + ], + "o": [ + [0, 0], + [3.831, -3.831], + [0, 0], + [2.681, -2.681], + [0, 0] + ], + "v": [ + [1270.646, 1256.634], + [1275.455, 1251.825], + [1287.065, 1240.215], + [1403.185, 1123.709], + [1411.31, 1115.584] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 0.833}, + "o": {"x": 0.55, "y": 0}, + "t": 23, + "s": [ + { + "i": [ + [0, 0], + [-1.587, 1.587], + [-3.831, 3.831], + [-2.681, 2.681], + [0, 0] + ], + "o": [ + [0, 0], + [3.831, -3.831], + [0, 0], + [2.681, -2.681], + [0, 0] + ], + "v": [ + [1378.641, 1148.253], + [1383.45, 1143.444], + [1395.059, 1131.835], + [1403.185, 1123.709], + [1411.31, 1115.584] + ], + "c": false + } + ] + }, + { + "i": {"x": 0.833, "y": 1}, + "o": {"x": 0.167, "y": 0.167}, + "t": 28, + "s": [ + { + "i": [ + [0, 0], + [-1.197, 1.197], + [-2.889, 2.889], + [-2.022, 2.022], + [0, 0] + ], + "o": [ + [0, 0], + [2.889, -2.889], + [0, 0], + [2.022, -2.022], + [0, 0] + ], + "v": [ + [1382.835, 1147.323], + [1386.462, 1143.696], + [1395.217, 1134.941], + [1401.345, 1128.813], + [1412.057, 1118.207] + ], + "c": false + } + ] + }, + { + "t": 29, + "s": [ + { + "i": [ + [0, 0], + [-1.108, 1.108], + [-2.676, 2.676], + [-1.873, 1.873], + [0, 0] + ], + "o": [ + [0, 0], + [2.676, -2.676], + [0, 0], + [1.873, -1.873], + [0, 0] + ], + "v": [ + [1383.785, 1147.112], + [1387.144, 1143.753], + [1395.253, 1135.644], + [1400.928, 1129.969], + [1406.603, 1124.294] + ], + "c": false + } + ] + } + ], + "ix": 2 + }, + "nm": "Tracciato 1_Bone", + "mn": "ADBE Vector Shape - Group", + "hd": false + } + ], + "ip": 0, + "op": 29, + "st": 0, + "bm": 0 + } + ], + "markers": [] +} diff --git a/src/assets/wav-worker.js b/src/assets/wav-worker.js index 85948edd13..9f0f1651ec 100644 --- a/src/assets/wav-worker.js +++ b/src/assets/wav-worker.js @@ -72,4 +72,4 @@ onmessage = function (e) { } else if (e.data[0] === 'close') { self.close(); } -}; \ No newline at end of file +}; diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 3612073bc3..c9669790be 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,3 +1,3 @@ export const environment = { - production: true + production: true, }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 72cd63978b..85db3caf2d 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -3,7 +3,7 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false + production: false, }; /* diff --git a/src/i18n/resources-locale_default.js b/src/i18n/resources-locale_default.js index 40adeca3f1..02afa75d4b 100644 --- a/src/i18n/resources-locale_default.js +++ b/src/i18n/resources-locale_default.js @@ -1,4 +1,4 @@ [ - { "key":"_Home_", "value":"Home" }, - { "key":"_User_", "value":"User" } -] + {'key': '_Home_', 'value': 'Home'}, + {'key': '_User_', 'value': 'User'}, +]; diff --git a/src/i18n/resources-locale_en-AU.js b/src/i18n/resources-locale_en-AU.js index 6a2a83110e..02afa75d4b 100644 --- a/src/i18n/resources-locale_en-AU.js +++ b/src/i18n/resources-locale_en-AU.js @@ -1,4 +1,4 @@ [ - { "key":"_Home_", "value":"Home" }, - { "key":"_User_", "value":"User" } -] + {'key': '_Home_', 'value': 'Home'}, + {'key': '_User_', 'value': 'User'}, +]; diff --git a/src/i18n/resources-locale_en-GB.js b/src/i18n/resources-locale_en-GB.js index 40adeca3f1..02afa75d4b 100644 --- a/src/i18n/resources-locale_en-GB.js +++ b/src/i18n/resources-locale_en-GB.js @@ -1,4 +1,4 @@ [ - { "key":"_Home_", "value":"Home" }, - { "key":"_User_", "value":"User" } -] + {'key': '_Home_', 'value': 'Home'}, + {'key': '_User_', 'value': 'User'}, +]; diff --git a/src/i18n/resources-locale_en-US.js b/src/i18n/resources-locale_en-US.js index 40adeca3f1..02afa75d4b 100644 --- a/src/i18n/resources-locale_en-US.js +++ b/src/i18n/resources-locale_en-US.js @@ -1,4 +1,4 @@ [ - { "key":"_Home_", "value":"Home" }, - { "key":"_User_", "value":"User" } -] + {'key': '_Home_', 'value': 'Home'}, + {'key': '_User_', 'value': 'User'}, +]; diff --git a/src/main.ts b/src/main.ts index 75742be059..65f4e67189 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,5 @@ import {enableProdMode, provideZoneChangeDetection} from '@angular/core'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; - import {environment} from 'src/environments/environment'; import {DoubtfireAngularModule} from './app/doubtfire-angular.module'; diff --git a/src/polyfills.ts b/src/polyfills.ts index b602050f34..c5f35359ae 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -19,7 +19,7 @@ * Zone JS is required by default for Angular itself. */ import 'zone.js'; // Included with Angular CLI. -(window as any).global = window; +window.global = globalThis; /*************************************************************************************************** * APPLICATION IMPORTS diff --git a/src/styles/common/doubtfire-cards.scss b/src/styles/common/doubtfire-cards.scss index 6646ba5a2c..a2edcc816f 100644 --- a/src/styles/common/doubtfire-cards.scss +++ b/src/styles/common/doubtfire-cards.scss @@ -1,4 +1,3 @@ - @mixin doubtfire-card { border-radius: 10px; } diff --git a/src/styles/common/extensions/col-xl.scss b/src/styles/common/extensions/col-xl.scss index 2b1c99052e..e7cee6aff7 100644 --- a/src/styles/common/extensions/col-xl.scss +++ b/src/styles/common/extensions/col-xl.scss @@ -1,11 +1,11 @@ // From https://gist.github.com/juukie/d71133e69877b46f060e -$screen-xl: 1560px !default; -$screen-xl-min: $screen-xl !default; -$screen-xl-desktop: $screen-xl-min !default; -$screen-lg-max: ($screen-xl-min - 1) !default; -$container-xlarge-desktop: (1530px + $grid-gutter-width) !default; -$container-xl: $container-xlarge-desktop !default; +$screen-xl: 1560px !default; +$screen-xl-min: $screen-xl !default; +$screen-xl-desktop: $screen-xl-min !default; +$screen-lg-max: ($screen-xl-min - 1) !default; +$container-xlarge-desktop: (1530px + $grid-gutter-width) !default; +$container-xl: $container-xlarge-desktop !default; .container { // @include container-fixed; No need for, already done. @@ -26,7 +26,7 @@ $container-xl: $container-xlarge-desktop !default; @mixin make-xl-column($columns, $gutter: $grid-gutter-width) { position: relative; min-height: 1px; - padding-left: ($gutter / 2); + padding-left: ($gutter / 2); padding-right: ($gutter / 2); @media (min-width: $screen-xl-min) { @@ -50,16 +50,16 @@ $container-xl: $container-xlarge-desktop !default; } } -@mixin make-grid-columns($i: 1, $list: ".col-xl-#{$i}") { +@mixin make-grid-columns($i: 1, $list: '.col-xl-#{$i}') { @for $i from (1 + 1) through $grid-columns { - $list: "#{$list}, .col-xl-#{$i}"; + $list: '#{$list}, .col-xl-#{$i}'; } #{$list} { position: relative; // Prevent columns from collapsing when empty min-height: 1px; // Inner gutter via padding - padding-left: ($grid-gutter-width / 2); + padding-left: ($grid-gutter-width / 2); padding-right: ($grid-gutter-width / 2); } } diff --git a/src/styles/common/extensions/fa-document-o.scss b/src/styles/common/extensions/fa-document-o.scss index 3427b08681..62c97e0d4d 100644 --- a/src/styles/common/extensions/fa-document-o.scss +++ b/src/styles/common/extensions/fa-document-o.scss @@ -1,2 +1,4 @@ // Alias for .fa-file-pdf-o -.#{$fa-css-prefix}-file-document-o:before { content: $fa-var-file-pdf-o; } +.#{$fa-css-prefix}-file-document-o:before { + content: $fa-var-file-pdf-o; +} diff --git a/src/styles/common/extensions/panel-footer-toolbar.scss b/src/styles/common/extensions/panel-footer-toolbar.scss index 325dc960c8..dd6ffaa97d 100644 --- a/src/styles/common/extensions/panel-footer-toolbar.scss +++ b/src/styles/common/extensions/panel-footer-toolbar.scss @@ -1,37 +1,29 @@ -.panel .panel-footer -{ +.panel .panel-footer { // With buttons in a small screen - @media (max-width: $screen-sm) - { + @media (max-width: $screen-sm) { // Increase tapping area - & > * - { + & > * { width: 100%; } .btn-group, .btn, - input - { + input { height: 4em; width: 100%; } - .btn - { + .btn { margin-top: 1em; } - ul.pagination - { + ul.pagination { margin-top: 1em; width: 100%; flex: 1; display: flex; overflow: auto; - li - { + li { flex: 1; } - li > a - { + li > a { width: 100%; height: 4em; display: flex; diff --git a/src/styles/common/extensions/panel-heading-toolbar.scss b/src/styles/common/extensions/panel-heading-toolbar.scss index d3a2e6621c..cc8d10e8d2 100644 --- a/src/styles/common/extensions/panel-heading-toolbar.scss +++ b/src/styles/common/extensions/panel-heading-toolbar.scss @@ -6,7 +6,9 @@ & > * { width: 100%; } - .btn-group, .btn, input { + .btn-group, + .btn, + input { height: 4em; width: 100%; } @@ -17,7 +19,8 @@ width: 100%; text-align: left; } - .btn-group, .buttons > .btn { + .btn-group, + .buttons > .btn { @media (min-width: $screen-sm-max) { margin-right: 1ex; } @@ -33,7 +36,7 @@ float: right; clear: both; .btn { - flex: 1 + flex: 1; } .btn { @include flex-center; @@ -41,7 +44,7 @@ } } } - form[role="search"] { + form[role='search'] { float: right; margin-right: 1.5ex; @media (max-width: $screen-sm) { diff --git a/src/styles/common/extensions/pointer.scss b/src/styles/common/extensions/pointer.scss index 88a143e2c3..0840082215 100644 --- a/src/styles/common/extensions/pointer.scss +++ b/src/styles/common/extensions/pointer.scss @@ -1,6 +1,7 @@ // // All anchors are pointers, as well as anything with the .pointer class // -a, .pointer { +a, +.pointer { cursor: pointer; } diff --git a/src/styles/common/five-cols.scss b/src/styles/common/five-cols.scss index 8ce22d31a0..de94a27e74 100644 --- a/src/styles/common/five-cols.scss +++ b/src/styles/common/five-cols.scss @@ -1,25 +1,25 @@ .col-xs-15 { - width: 20%; - float: left; + width: 20%; + float: left; } @media (min-width: 768px) { -.col-sm-15 { - width: 20%; - float: left; - } + .col-sm-15 { + width: 20%; + float: left; + } } @media (min-width: 992px) { - .col-md-15 { - width: 20%; - float: left; - } + .col-md-15 { + width: 20%; + float: left; + } } @media (min-width: 1200px) { - .col-lg-15 { - width: 20%; - float: left; - } -} \ No newline at end of file + .col-lg-15 { + width: 20%; + float: left; + } +} diff --git a/src/styles/common/grade-colors.scss b/src/styles/common/grade-colors.scss index 84fccae215..45e498c0eb 100644 --- a/src/styles/common/grade-colors.scss +++ b/src/styles/common/grade-colors.scss @@ -9,7 +9,7 @@ // ******************************************************** // -$grade-color-p: color.adjust(#FF0000, $lightness: -10%); -$grade-color-c: color.adjust(#FF8000, $lightness: -5%); -$grade-color-d: color.adjust(#0080FF, $lightness: -10%); -$grade-color-hd: color.adjust(#80FF00, $lightness: -15%); +$grade-color-p: color.adjust(#ff0000, $lightness: -10%); +$grade-color-c: color.adjust(#ff8000, $lightness: -5%); +$grade-color-d: color.adjust(#0080ff, $lightness: -10%); +$grade-color-hd: color.adjust(#80ff00, $lightness: -15%); diff --git a/src/styles/common/hero-sidebar-layout.scss b/src/styles/common/hero-sidebar-layout.scss index aa5f6ac4fc..ce68a9efd7 100644 --- a/src/styles/common/hero-sidebar-layout.scss +++ b/src/styles/common/hero-sidebar-layout.scss @@ -77,7 +77,7 @@ f-welcome .content-container { .sidebar { display: none; /* Hide the element */ } - .wordmark{ + .wordmark { display: flex; /* Show the element */ } } diff --git a/src/styles/common/overrides/header-overrides.scss b/src/styles/common/overrides/header-overrides.scss index 970bfd5e06..cb4237edfc 100644 --- a/src/styles/common/overrides/header-overrides.scss +++ b/src/styles/common/overrides/header-overrides.scss @@ -2,6 +2,11 @@ // Sets all font weights to the headers as 400 // -h1, h2, h3, h4, h5, h6 { +h1, +h2, +h3, +h4, +h5, +h6 { font-weight: 400; } diff --git a/src/styles/common/overrides/panel-overrides.scss b/src/styles/common/overrides/panel-overrides.scss index 43c1472658..f1ed83d293 100644 --- a/src/styles/common/overrides/panel-overrides.scss +++ b/src/styles/common/overrides/panel-overrides.scss @@ -3,11 +3,13 @@ // // Global overrides for panels // -.panel-footer .pagination, .modal-footer .pagination { +.panel-footer .pagination, +.modal-footer .pagination { margin: 0; } -.panel-body + .panel-heading, .panel-body + * > .panel-heading { +.panel-body + .panel-heading, +.panel-body + * > .panel-heading { border-top: 1px solid #ddd !important; border-radius: 0 !important; } @@ -29,7 +31,9 @@ .panel > *:not(.panel-heading):not(.panel-footer):not(.panel-toolbar) { flex: 1; } - .panel-heading, .panel-body, .panel-footer { + .panel-heading, + .panel-body, + .panel-footer { width: 100%; } .panel + .panel { @@ -43,7 +47,8 @@ margin-top: 0; font-size: 1em; } - .panel .drop.well, .panel .file-uploader { + .panel .drop.well, + .panel .file-uploader { margin: 0; } } @@ -79,7 +84,8 @@ } // Two panel bodies next to eachother (include those with one nested in custom element) -.panel-body:not(.ng-hide) + * > .panel-body, .panel-body:not(.ng-hide) + .panel-body { +.panel-body:not(.ng-hide) + * > .panel-body, +.panel-body:not(.ng-hide) + .panel-body { padding-top: 0; } // Remove extra margin for callouts in padding @@ -93,7 +99,8 @@ // Full screen set of panels .panel-full-screen { height: $main-view-max-height; - & > *, & > * > .panel { + & > *, + & > * > .panel { height: 100%; } } diff --git a/src/styles/common/overrides/rating-overrides.scss b/src/styles/common/overrides/rating-overrides.scss index 56c8c806e2..0c9e44aa6f 100644 --- a/src/styles/common/overrides/rating-overrides.scss +++ b/src/styles/common/overrides/rating-overrides.scss @@ -1,7 +1,7 @@ @use 'sass:color'; // The generated from ui-bootstrap becomes this -span[role="slider"] { +span[role='slider'] { outline: none; } .rating-outline { diff --git a/src/styles/common/overrides/table-overrides.scss b/src/styles/common/overrides/table-overrides.scss index 4a9d444e8c..2b03bc8575 100644 --- a/src/styles/common/overrides/table-overrides.scss +++ b/src/styles/common/overrides/table-overrides.scss @@ -8,7 +8,8 @@ table.table-pointer { } table > tbody > tr { - & > td, & > th { + & > td, + & > th { vertical-align: middle !important; } } diff --git a/src/styles/common/text.scss b/src/styles/common/text.scss index 9b97f6c291..69586f5d2e 100644 --- a/src/styles/common/text.scss +++ b/src/styles/common/text.scss @@ -1,4 +1,4 @@ .with-icon { display: flex; align-items: center; -} \ No newline at end of file +} diff --git a/src/styles/common/typeface.scss b/src/styles/common/typeface.scss index dbd24f4d3c..c45e90c1aa 100644 --- a/src/styles/common/typeface.scss +++ b/src/styles/common/typeface.scss @@ -6,49 +6,70 @@ $roboto-path: '/assets/fonts/roboto'; font-family: 'Roboto'; font-style: normal; font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url('#{$roboto-path}/Roboto-Light.woff') format('woff'); + src: + local('Roboto Light'), + local('Roboto-Light'), + url('#{$roboto-path}/Roboto-Light.woff') format('woff'); } @font-face { font-family: 'Roboto'; font-style: normal; font-weight: 400; - src: local('Roboto'), local('Roboto-Regular'), url('#{$roboto-path}/Roboto-Regular.woff') format('woff'); + src: + local('Roboto'), + local('Roboto-Regular'), + url('#{$roboto-path}/Roboto-Regular.woff') format('woff'); } @font-face { font-family: 'Roboto'; font-style: normal; font-weight: 500; - src: local('Roboto Medium'), local('Roboto-Medium'), url('#{$roboto-path}/Roboto-Medium.woff') format('woff'); + src: + local('Roboto Medium'), + local('Roboto-Medium'), + url('#{$roboto-path}/Roboto-Medium.woff') format('woff'); } @font-face { font-family: 'Roboto'; font-style: normal; font-weight: 700; - src: local('Roboto Bold'), local('Roboto-Bold'), url('#{$roboto-path}/Roboto-Bold.woff') format('woff'); + src: + local('Roboto Bold'), + local('Roboto-Bold'), + url('#{$roboto-path}/Roboto-Bold.woff') format('woff'); } @font-face { font-family: 'Roboto'; font-style: italic; font-weight: 400; - src: local('Roboto Italic'), local('Roboto-Italic'), url('#{$roboto-path}/Roboto-Italic.woff') format('woff'); + src: + local('Roboto Italic'), + local('Roboto-Italic'), + url('#{$roboto-path}/Roboto-Italic.woff') format('woff'); } @font-face { font-family: 'Grotesk'; font-style: normal; - src: local('Grotesk'), url(/assets/fonts/grotesk/grotesk-regular.otf) format('opentype'); + src: + local('Grotesk'), + url(/assets/fonts/grotesk/grotesk-regular.otf) format('opentype'); } @font-face { font-family: 'Grotesk'; font-style: italic; - src: local('Grotesk'), url(/assets/fonts/grotesk/grotesk-italic.otf) format('opentype'); + src: + local('Grotesk'), + url(/assets/fonts/grotesk/grotesk-italic.otf) format('opentype'); } @font-face { font-family: 'Grotesk'; font-style: bold; - src: local('Grotesk'), url(/assets/fonts/grotesk/grotesk-bold.otf) format('opentype'); + src: + local('Grotesk'), + url(/assets/fonts/grotesk/grotesk-bold.otf) format('opentype'); } .mat-icon { diff --git a/src/styles/m3-theme.scss b/src/styles/m3-theme.scss index cc5594c47e..1e094b5f2f 100644 --- a/src/styles/m3-theme.scss +++ b/src/styles/m3-theme.scss @@ -129,45 +129,49 @@ $_palettes: ( $_rest: ( secondary: map.get($_palettes, secondary), neutral: map.get($_palettes, neutral), - neutral-variant: map.get($_palettes, neutral-variant), + neutral-variant: map.get($_palettes, neutral-variant), error: map.get($_palettes, error), ); $_primary: map.merge(map.get($_palettes, primary), $_rest); $_tertiary: map.merge(map.get($_palettes, tertiary), $_rest); -$light-theme: mat.define-theme(( - color: ( - theme-type: light, - primary: $_primary, - tertiary: $_tertiary, - use-system-variables: true, - system-variables-prefix: sys, - ), - typography: ( - use-system-variables: true, - system-variables-prefix: sys, - plain-family: "Inter, 'open-sans', 'Roboto'", - brand-family: "'Grotesk'", - bold-weight: 900, - medium-weight: 500, - regular-weight: 300, - ), -)); -$dark-theme: mat.define-theme(( - color: ( - theme-type: dark, - primary: $_primary, - tertiary: $_tertiary, - use-system-variables: true, - system-variables-prefix: sys, - ), - typography: ( - use-system-variables: true, - system-variables-prefix: sys, - plain-family: "Inter, 'open-sans', 'Roboto'", - brand-family: "'Grotesk'", - bold-weight: 900, - medium-weight: 500, - regular-weight: 300, - ), -)); +$light-theme: mat.define-theme( + ( + color: ( + theme-type: light, + primary: $_primary, + tertiary: $_tertiary, + use-system-variables: true, + system-variables-prefix: sys, + ), + typography: ( + use-system-variables: true, + system-variables-prefix: sys, + plain-family: "Inter, 'open-sans', 'Roboto'", + brand-family: "'Grotesk'", + bold-weight: 900, + medium-weight: 500, + regular-weight: 300, + ), + ) +); +$dark-theme: mat.define-theme( + ( + color: ( + theme-type: dark, + primary: $_primary, + tertiary: $_tertiary, + use-system-variables: true, + system-variables-prefix: sys, + ), + typography: ( + use-system-variables: true, + system-variables-prefix: sys, + plain-family: "Inter, 'open-sans', 'Roboto'", + brand-family: "'Grotesk'", + bold-weight: 900, + medium-weight: 500, + regular-weight: 300, + ), + ) +); diff --git a/src/styles/mixins/animations/fade-in.scss b/src/styles/mixins/animations/fade-in.scss index 9bf65d7f79..008d7a6ead 100644 --- a/src/styles/mixins/animations/fade-in.scss +++ b/src/styles/mixins/animations/fade-in.scss @@ -2,8 +2,12 @@ // A fade in animation // @keyframes animation-fade-in { - from { opacity: 0; } - to { opacity: 1; } + from { + opacity: 0; + } + to { + opacity: 1; + } } @mixin animation-fade-in($seconds) { animation: animation-fade-in $seconds; diff --git a/src/styles/mixins/animations/grow.scss b/src/styles/mixins/animations/grow.scss index 73222c87c6..e8cef776ce 100644 --- a/src/styles/mixins/animations/grow.scss +++ b/src/styles/mixins/animations/grow.scss @@ -4,7 +4,7 @@ @keyframes animation-grow { 0% { opacity: 0; - transform: scale(.3); + transform: scale(0.3); } 50% { @@ -13,7 +13,7 @@ } 70% { - transform: scale(.9); + transform: scale(0.9); } 100% { diff --git a/src/styles/mixins/animations/slide-down.scss b/src/styles/mixins/animations/slide-down.scss index cf741fc82b..1bb14c5d1c 100644 --- a/src/styles/mixins/animations/slide-down.scss +++ b/src/styles/mixins/animations/slide-down.scss @@ -2,8 +2,12 @@ // Slide animation from -2em to initial top // @keyframes animation-slide-down { - from { margin-top: -2em; } - to { margin-top: inherit; } + from { + margin-top: -2em; + } + to { + margin-top: inherit; + } } @mixin animation-slide-down($seconds) { animation: animation-slide-down $seconds; diff --git a/src/styles/mixins/animations/wobble.scss b/src/styles/mixins/animations/wobble.scss index 89f12fa8f3..e06fbdfecb 100644 --- a/src/styles/mixins/animations/wobble.scss +++ b/src/styles/mixins/animations/wobble.scss @@ -2,16 +2,24 @@ // Animation to wobble an element side to side // @keyframes animation-wobble { - 0%, 100% { transform: translateX(+5px); } - 25%, 75% { transform: translateX(0); } - 50% { transform: translateX(-5px); } + 0%, + 100% { + transform: translateX(+5px); + } + 25%, + 75% { + transform: translateX(0); + } + 50% { + transform: translateX(-5px); + } } @mixin animation-wobble { animation-duration: 1s; animation-fill-mode: both; animation-timing-function: ease-in-out; - animation-iteration-count:infinite; + animation-iteration-count: infinite; animation-name: animation-wobble; } @@ -19,9 +27,16 @@ // Animation to wobble an element side but only once // @keyframes animation-wobble-once { - 0%, 100% { transform: translateX(0); } - 25% { transform: translateX(+5px); } - 75% { transform: translateX(-5px); } + 0%, + 100% { + transform: translateX(0); + } + 25% { + transform: translateX(+5px); + } + 75% { + transform: translateX(-5px); + } } @mixin animation-wobble-once { diff --git a/src/styles/mixins/callout.scss b/src/styles/mixins/callout.scss index 44b66f66af..fa9d52c3b2 100644 --- a/src/styles/mixins/callout.scss +++ b/src/styles/mixins/callout.scss @@ -4,19 +4,25 @@ // A callout // @mixin callout($color, $bgcolor: color.adjust($color, $lightness: 35%)) { - display: block; - margin: 20px 0; - padding: 15px 30px 15px 15px; - border-left: 5px solid $color; - background-color: $bgcolor; - h1, h2, h3, h4, h5, h6 { - margin-top: 0; - color: $color; - } - p:last-child { - margin-bottom: 0; - } - code, .highlight { - background-color: #fff; - } + display: block; + margin: 20px 0; + padding: 15px 30px 15px 15px; + border-left: 5px solid $color; + background-color: $bgcolor; + h1, + h2, + h3, + h4, + h5, + h6 { + margin-top: 0; + color: $color; + } + p:last-child { + margin-bottom: 0; + } + code, + .highlight { + background-color: #fff; + } } diff --git a/src/styles/mixins/dropdown-selector.scss b/src/styles/mixins/dropdown-selector.scss index 01036b0cca..c5ca2742a2 100644 --- a/src/styles/mixins/dropdown-selector.scss +++ b/src/styles/mixins/dropdown-selector.scss @@ -6,7 +6,8 @@ & > button { height: 100%; width: 100%; - label, i { + label, + i { text-align: center; } label { diff --git a/src/styles/mixins/task-list.scss b/src/styles/mixins/task-list.scss index c33aca0065..f89e866b82 100644 --- a/src/styles/mixins/task-list.scss +++ b/src/styles/mixins/task-list.scss @@ -44,22 +44,30 @@ text-decoration: none; // background-color: $list-group-hover-bg; &.ready-for-feedback { - @include custom-box-shadow(color.adjust(task-status-color('ready-for-feedback'), $lightness: 15%)); + @include custom-box-shadow( + color.adjust(task-status-color('ready-for-feedback'), $lightness: 15%) + ); } &.not-started { @include custom-box-shadow(color.adjust(task-status-color('not-started'), $lightness: 5%)); } &.working-on-it { - @include custom-box-shadow(color.adjust(task-status-color('working-on-it'), $lightness: 15%)); + @include custom-box-shadow( + color.adjust(task-status-color('working-on-it'), $lightness: 15%) + ); } &.need-help { @include custom-box-shadow(color.adjust(task-status-color('need-help'), $lightness: 15%)); } &.fix-and-resubmit { - @include custom-box-shadow(color.adjust(task-status-color('fix-and-resubmit'), $lightness: 15%)); + @include custom-box-shadow( + color.adjust(task-status-color('fix-and-resubmit'), $lightness: 15%) + ); } &.feedback-exceeded { - @include custom-box-shadow(color.adjust(task-status-color('feedback-exceeded'), $lightness: 15%)); + @include custom-box-shadow( + color.adjust(task-status-color('feedback-exceeded'), $lightness: 15%) + ); } &.fail { @include custom-box-shadow(color.adjust(task-status-color('fail'), $lightness: 15%)); @@ -77,13 +85,19 @@ @include custom-box-shadow(color.adjust(task-status-color('complete'), $lightness: 15%)); } &.time-exceeded { - @include custom-box-shadow(color.adjust(task-status-color('time-exceeded'), $lightness: 15%)); + @include custom-box-shadow( + color.adjust(task-status-color('time-exceeded'), $lightness: 15%) + ); } &.assess-in-portfolio { - @include custom-box-shadow(color.adjust(task-status-color('assess-in-portfolio'), $lightness: 15%)); + @include custom-box-shadow( + color.adjust(task-status-color('assess-in-portfolio'), $lightness: 15%) + ); } &.attention-required { - @include custom-box-shadow(color.adjust(task-status-color('attention-required'), $lightness: 15%)); + @include custom-box-shadow( + color.adjust(task-status-color('attention-required'), $lightness: 15%) + ); } } &.selected { diff --git a/src/styles/modules/cards.scss b/src/styles/modules/cards.scss index 9b381e445e..2114a71f81 100644 --- a/src/styles/modules/cards.scss +++ b/src/styles/modules/cards.scss @@ -10,18 +10,35 @@ margin-bottom: $card-footer-padding; background-color: color.adjust(#fff, $lightness: -0.75%); - transition: box-shadow .25s; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), - 0 1px 5px 0 rgba(0, 0, 0, 0.12), - 0 3px 1px -2px rgba(0, 0, 0, 0.2); + transition: box-shadow 0.25s; + box-shadow: + 0 2px 2px 0 rgba(0, 0, 0, 0.14), + 0 1px 5px 0 rgba(0, 0, 0, 0.12), + 0 3px 1px -2px rgba(0, 0, 0, 0.2); - &.card-default > .card-heading { background-color: $panel-default-heading-bg; } - &.card-primary > .card-heading { background-color: $brand-primary; } - &.card-danger > .card-heading { background-color: $brand-danger; } - &.card-success > .card-heading { background-color: $brand-success; } - &.card-warning > .card-heading { background-color: $brand-warning; } - &.card-info > .card-heading { background-color: $brand-info; } - &.card-danger, &.card-success, &.card-warning, &.card-info, &.card-primary { + &.card-default > .card-heading { + background-color: $panel-default-heading-bg; + } + &.card-primary > .card-heading { + background-color: $brand-primary; + } + &.card-danger > .card-heading { + background-color: $brand-danger; + } + &.card-success > .card-heading { + background-color: $brand-success; + } + &.card-warning > .card-heading { + background-color: $brand-warning; + } + &.card-info > .card-heading { + background-color: $brand-info; + } + &.card-danger, + &.card-success, + &.card-warning, + &.card-info, + &.card-primary { .card-heading { color: #fff; .text-muted { diff --git a/src/styles/modules/doubtfire-logo.scss b/src/styles/modules/doubtfire-logo.scss index 395918c8e8..aaf9cf1fc9 100644 --- a/src/styles/modules/doubtfire-logo.scss +++ b/src/styles/modules/doubtfire-logo.scss @@ -19,9 +19,10 @@ i.logo { .welcome-to-doubtfire { margin-top: 6em; margin-bottom: 3em; - h1, p { + h1, + p { @include logo-font-rendering; - font-family: "Grotesk"; + font-family: 'Grotesk'; } p.lead { color: #000; diff --git a/src/styles/modules/panel-fullscreen.scss b/src/styles/modules/panel-fullscreen.scss index d9abc44ad3..7e6ff08b3e 100644 --- a/src/styles/modules/panel-fullscreen.scss +++ b/src/styles/modules/panel-fullscreen.scss @@ -37,7 +37,8 @@ padding: 0px; } - .panel, .panel-heading { + .panel, + .panel-heading { border-radius: 0; } @@ -51,7 +52,8 @@ font-size: 3em; text-align: center; font-weight: 300; - i, p { + i, + p { display: block; width: 100%; margin-bottom: 0.75em; diff --git a/src/styles/modules/tabset-icon.scss b/src/styles/modules/tabset-icon.scss index a1f721008d..0a1a4004d6 100644 --- a/src/styles/modules/tabset-icon.scss +++ b/src/styles/modules/tabset-icon.scss @@ -11,7 +11,8 @@ i:not(:last-child) { margin-right: 1ex; } - i:not(:last-child), i + i:last-child { + i:not(:last-child), + i + i:last-child { display: inline-block; width: inherit; } diff --git a/src/test.ts b/src/test.ts index 280230b87b..5f03b6f001 100644 --- a/src/test.ts +++ b/src/test.ts @@ -9,11 +9,15 @@ import 'zone.js/dist/fake-async-test'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; -// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. -declare const __karma__: any; +declare const __karma__: { + loaded: () => void; + start: () => void; +}; // Prevent Karma from running prematurely. -__karma__.loaded = () => {}; +__karma__.loaded = () => { + /* empty */ +}; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { diff --git a/src/theme.scss b/src/theme.scss index f0dd8c1d8c..e3bd33aba1 100644 --- a/src/theme.scss +++ b/src/theme.scss @@ -108,9 +108,27 @@ $font-family-primary: "'Grotesk'"; $font-family-accent: "Inter, 'open-sans', 'Roboto'"; $mat-typography-primary-config: mat.m2-define-typography-config( - $headline-1: mat.m2-define-typography-level(112px, 112px, 300, $font-family-primary, $letter-spacing: -0.05em), - $headline-2: mat.m2-define-typography-level(56px, 56px, 400, $font-family-primary, $letter-spacing: -0.02em), - $headline-3: mat.m2-define-typography-level(45px, 48px, 400, $font-family-primary, $letter-spacing: -0.005em), + $headline-1: mat.m2-define-typography-level( + 112px, + 112px, + 300, + $font-family-primary, + $letter-spacing: -0.05em + ), + $headline-2: mat.m2-define-typography-level( + 56px, + 56px, + 400, + $font-family-primary, + $letter-spacing: -0.02em + ), + $headline-3: mat.m2-define-typography-level( + 45px, + 48px, + 400, + $font-family-primary, + $letter-spacing: -0.005em + ), $headline-4: mat.m2-define-typography-level(34px, 40px, 400, $font-family-primary), $headline-5: mat.m2-define-typography-level(24px, 32px, 400, $font-family-primary), $headline-6: mat.m2-define-typography-level(20px, 32px, 500, $font-family-primary), diff --git a/src/tsconfig.spec.json b/src/tsconfig.spec.json index aabc7e3d73..70add2d529 100644 --- a/src/tsconfig.spec.json +++ b/src/tsconfig.spec.json @@ -2,17 +2,8 @@ "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/spec", - "types": [ - "jasmine", - "node" - ] + "types": ["jasmine", "node"] }, - "files": [ - "test.ts", - "polyfills.ts" - ], - "include": [ - "**/*.spec.ts", - "**/*.d.ts" - ] -} \ No newline at end of file + "files": ["test.ts", "polyfills.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts"] +} From b13b6461dd4c89fa4a72ecb48c4cce7d09a2a6a9 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 8 Jun 2026 12:58:27 +1000 Subject: [PATCH 1097/1531] chore: update README --- README.md | 248 ++---------------------------------------------------- 1 file changed, 5 insertions(+), 243 deletions(-) diff --git a/README.md b/README.md index 8a1f9dc167..b050cbf4a6 100644 --- a/README.md +++ b/README.md @@ -1,245 +1,14 @@ -![Doubtfire Logo](src/assets/icons/android-chrome-192x192.png) +

    + OnTrack logo +

    -# Doubtfire Web [![CI](https://img.shields.io/github/workflow/status/doubtfire-lms/doubtfire-web/Node.js%20CI?label=CI&logo=GitHub)](https://github.com/doubtfire-lms/doubtfire-web/actions/workflows/nodejs-ci.yml) +# OnTrack Web [![CI](https://img.shields.io/github/workflow/status/doubtfire-lms/doubtfire-web/Node.js%20CI?label=CI&logo=GitHub)](https://github.com/doubtfire-lms/doubtfire-web/actions/workflows/nodejs-ci.yml) A modern, lightweight learning management system. -> ## 🛠 Migration Status: In Development -> -> Doubtfire web migration from AngularJS/Coffeescript to Angular/Typescript, including refactoring all components, is currently in development. -> -> See the progress of component migration below. - -## Migration Progress - -Important: When completing a frontend migration, please update the below list regarding the component you have migrated. - -### SUMMARY: - -- `89 / 183` components migrated -- `19` components no longer in the doubtfire-lms/9.x branch - -### NO LONGER IN doubtfire-lms/9.x - -- [x] ./src/app/projects/states/all/directives/all-projects-list/all-projects-list.coffee -- [x] ./src/app/projects/states/all/all.coffee -- [x] ./src/app/groups/tutor-group-manager/tutor-group-manager.coffee -- [x] ./src/app/tasks/task-definition-selector/task-definition-selector.coffee -- [x] ./src/app/tasks/task-status-selector/task-status-selector.coffee -- [x] ./src/app/config/debug/debug.coffee -- [x] ./src/app/projects/states/all/directives/directives.coffee -- [x] ./src/app/projects/states/dashboard/directives/task-dashboard/directives/directives.coffee -- [x] ./src/app/projects/states/dashboard/directives/task-dashboard/directives/task-outcomes-card/task-outcomes-card.coffee -- [x] ./src/app/admin/states/states.coffee -- [x] ./src/app/admin/admin.coffee -- [x] ./src/app/units/states/tasks/viewer/directives/directives.coffee -- [x] ./src/app/units/states/tasks/viewer/viewer.coffee -- [x] ./src/app/units/states/all/directives/all-units-list/all-units-list.coffee -- [x] ./src/app/units/states/all/directives/directives.coffee -- [x] ./src/app/units/states/all/all.coffee -- [x] ./src/app/common/alert-list/alert-list.coffee -- [x] ./src/app/common/modals/progress-modal/progress-modal.coffee -- [x] ./src/app/errors/states/not-found/not-found.coffee -- [x] ./src/app/groups/tutor-group-manager/tutor-group-manager.coffee - -### MIGRATED: - -- [x] ./src/app/home/splash-screen/splash-screen.component.ts -- [x] ./src/app/home/states/home/home.component.ts -- [x] ./src/app/tasks/task-submission-history/task-submission-history.component.ts -- [x] ./src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts -- [x] ./src/app/tasks/task-comments-viewer/extension-comment/extension-comment.component.ts -- [x] ./src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-player.component.ts -- [x] ./src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-recorder/intelligent-discussion-recorder.component.ts -- [x] ./src/app/tasks/project-tasks-list/project-tasks-list.coffee -- [x] ./src/app/tasks/task-comments-viewer/pdf-image-comment/pdf-image-comment.component.ts -- [x] ./src/app/tasks/task-comments-viewer/comment-bubble-action/comment-bubble-action.component.ts -- [x] ./src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts -- [x] ./src/app/tasks/task-comment-composer/task-comment-composer.component.ts -- [x] ./src/app/tasks/task-comment-composer/discussion-prompt-composer/discussion-prompt-composer.component.ts -- [x] ./src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.ts -- [x] ./src/app/projects/states/dashboard/directives/student-task-list/task-list-item/task-list-item.component.ts -- [x] ./src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.ts -- [x] ./src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.ts -- [x] ./src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.ts -- [x] ./src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.ts -- [x] ./src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.ts -- [x] ./src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts -- [x] ./src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts -- [x] ./src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts -- [x] ./src/app/admin/institution-settings/institution-settings.component.ts -- [x] ./src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts -- [x] ./src/app/admin/institution-settings/activity-type-list/activity-type-list.component.ts -- [x] ./src/app/admin/tii-action-log/tii-action-log.component.ts -- [x] ./src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.ts -- [x] ./src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts -- [x] ./src/app/admin/modals/create-unit-modal/create-new-unit-modal.component.ts -- [x] ./src/app/eula/accept-eula/accept-eula.component.ts -- [x] ./src/app/welcome/welcome.component.ts -- [x] ./src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts -- [x] ./src/app/units/states/edit/directives/unit-students-editor/student-tutorial-select/student-tutorial-select.component.ts -- [x] ./src/app/units/states/edit/directives/unit-students-editor/unit-students-editor.component.ts -- [x] ./src/app/units/states/edit/directives/unit-students-editor/student-campus-select/student-campus-select.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.ts -- [x] ./src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts -- [x] ./src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts -- [x] ./src/app/units/states/analytics/unit-analytics-route.component.ts -- [x] ./src/app/common/footer/footer.component.ts -- [x] ./src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.ts -- [x] ./src/app/common/audio-recorder/audio/microphone-tester/microphone-tester.component.ts -- [x] ./src/app/common/audio-player/audio-player.component.ts -- [x] ./src/app/common/edit-profile-form/edit-profile-form.component.ts -- [x] ./src/app/common/file-drop/file-drop.component.ts -- [x] ./src/app/common/modals/extension-modal/extension-modal.component.ts -- [x] ./src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.component.ts -- [x] ./src/app/common/modals/calendar-modal/calendar-modal.component.ts -- [x] ./src/app/common/modals/task-assessment-modal/task-assessment-modal.component.ts -- [x] ./src/app/common/pdf-viewer/pdf-viewer.component.ts -- [x] ./src/app/common/obect-select/object-select.component.ts -- [x] ./src/app/common/hero-sidebar/hero-sidebar.component.ts -- [x] ./src/app/common/project-progress-bar/project-progress-bar.component.ts -- [x] ./src/app/common/f-chip/f-chip.component.ts -- [x] ./src/app/common/status-icon/status-icon.component.ts -- [x] ./src/app/common/user-badge/user-badge.component.ts -- [x] ./src/app/common/file-viewer/file-viewer.component.ts -- [x] ./src/app/common/user-icon/user-icon.component.ts -- [x] ./src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.ts -- [x] ./src/app/common/header/header.component.ts -- [x] ./src/app/common/header/task-dropdown/task-dropdown.component.ts -- [x] ./src/app/common/header/unit-dropdown/unit-dropdown.component.ts -- [x] ./src/app/common/services/alert.service.ts -- [x] ./src/app/sessions/states/sign-in/sign-in.component.ts -- [x] ./src/app/account/edit-profile/edit-profile.component.ts -- [x] ./src/app/tasks/modals/grade-task-modal/grade-task-modal.component.ts -- [x] ./src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts -- [x] ./src/app/visualisations/progress-burndown-chart/progressburndownchart.component.ts -- [x] ./src/app/config/privacy-policy/privacy-policy.coffee -- [x] ./src/app/units/states/tasks/viewer/directives/task-sheet-view/task-sheet-view.coffee -- [x] ./src/app/units/states/tasks/viewer/directives/task-details-view/task-details-view.coffee -- [x] ./src/app/units/states/tasks/viewer/directives/unit-task-list/unit-task-list.coffee -- [x] ./src/app/projects/states/dashboard/directives/student-task-list/student-task-list.coffee -- [x] ./src/app/units/states/tasks/inbox/inbox.coffee -- [x] ./src/app/admin/states/units/units.component.ts -- [x] ./src/app/admin/states/users/users.component.ts -- [x] ./src/app/common/grade-icon/grade-icon.component.ts -- [x] ./src/app/common/services/grade.service.ts -- [x] ./src/app/common/services/alert.service.ts -- [x] ./src/app/errors/states/unauthorised/unauthorised.component.ts -- [x] ./src/app/groups/group-set-selector/group-set-selector.component.ts -- [x] ./src/app/admin/modals/create-unit-modal/create-unit-modal.coffee -- [x] ./src/app/common/services/date.service.ts -- [x] ./src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.coffee (IN 10.0.x) -- [x] ./src/app/groups/group-member-list/group-member-list.coffee -- [x] ./src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.coffee -- [x] ./src/app/common/modals/confirmation-modal/confirmation-modal.coffee -- [x] ./src/app/common/modals/comments-modal/comments-modal.coffee (IN 10.0.x) -- [x] ./src/app/groups/group-selector/group-selector.coffee -- [x] ./src/app/groups/group-set-manager/group-set-manager.coffee -- [x] ./src/app/common/file-uploader/file-uploader.coffee -- [x] ./src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.coffee -- [x] ./src/app/sessions/auth/http-auth-injector.coffee -- [x] ./src/app/sessions/sessions.coffee -- [x] ./src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.coffee -- [x] ./src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.coffee -- [x] ./src/app/projects/project-progress-dashboard/project-progress-dashboard.coffee -- [x] ./src/app/units/states/portfolios/portfolios.coffee -- [x] ./src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.coffee -- [x] ./src/app/config/local-storage/local-storage.coffee (Removed in 10.0.x) -- [x] ./src/app/projects/states/tutorials/tutorials.coffee -- [x] ./src/app/admin/modals/modals.coffee -- [x] ./src/app/common/services/date-service.coffee -- [ ] ./src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment-modal/task-ilo-alignment-modal.coffee (Removed in 10.0.x) -- [x] ./src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment.coffee (Removed in 10.0.x) -- [x] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.coffee (Removed in 10.0.x) -- [x] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-rater/task-ilo-alignment-rater.coffee (Removed in 10.0.x) -- [x] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.coffee (Removed in 10.0.x) -- [x] ./src/app/tasks/task-ilo-alignment/task-ilo-alignment.coffee (Removed in 10.0.x) -- [x] ./src/app/projects/project-outcome-alignment/project-outcome-alignment.coffee (Removed in 10.0.x) -- [x] ./src/app/units/modals/unit-ilo-edit-modal/unit-ilo-edit-modal.coffee (Removed in 10.0.x) -- [x] ./src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.coffee (Removed in 10.0.x) -- [x] ./src/app/projects/states/outcomes/outcomes.coffee (Removed in 10.0.x) -- [x] ./src/app/projects/states/portfolio/directives/portfolio-tasks-step/portfolio-tasks-step.coffee (Removed in 10.0.x) -- [x] ./src/app/units/states/rollover/directives/directives.coffee -- [x] ./src/app/units/states/rollover/directives/unit-dates-selector/unit-dates-selector.coffee -- [x] ./src/app/units/states/rollover/rollover.coffee -- [x] ./src/app/visualisations/task-status-pie-chart.coffee -- [x] ./src/app/visualisations/student-task-status-pie-chart.coffee -- [ ] ./src/app/visualisations/achievement-box-plot.coffee (ILO Alignments removed) -- [ ] ./src/app/visualisations/achievement-custom-bar-chart.coffee (ILO Alignments removed) -- [ ] ./src/app/visualisations/alignment-bar-chart.coffee (ILO Alignments removed) -- [ ] ./src/app/visualisations/alignment-bullet-chart.coffee (ILO Alignments removed) -- [x] ./src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.coffee -- [x] ./src/app/groups/groups.coffee -- [x] ./src/app/common/modals/csv-result-modal/csv-result-modal.coffee -- [x] ./src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.coffee -- [x] ./src/app/units/states/students-list/students-list.coffee -- [x] ./src/app/common/modals/modals.coffee -- [x] ./src/app/tasks/modals/upload-submission-modal/upload-submission-modal.coffee -- [x] ./src/app/tasks/modals/modals.coffee -- [x] ./src/app/tasks/tasks.coffee -- [x] ./src/app/units/modals/modals.coffee -- [x] ./src/app/units/states/edit/directives/directives.coffee -- [x] ./src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.coffee (Migrate this in 10.0.x) -- [x] ./src/app/projects/states/portfolio/directives/directives.coffee -- [x] ./src/app/projects/states/portfolio/portfolio.coffee -- [x] ./src/app/units/states/tasks/definition/definition.coffee -- [x] ./src/app/units/states/tasks/tasks.coffee -- [x] ./src/app/units/states/tasks/moderation.coffee -- [x] ./src/app/units/states/tasks/overflow.coffee -- [x] ./src/app/errors/states/timeout/timeout.coffee -- [x] ./src/app/projects/states/groups/groups.coffee (State only -> "project-groups") -- [x] ./src/app/units/states/groups/groups.coffee (State only -> "unit-groups") -- [x] ./src/app/units/states/analytics/analytics.coffee (Just the routing, since the TypeScript f-analytics component has been expanded in 10.0.x) -- [x] ./src/app/projects/states/feedback/feedback.coffee -- [x] ./src/app/common/content-editable/content-editable.coffee -- [x] ./src/app/common/services/outcome-service.coffee -- [ ] ./src/app/common/filters/filters.coffee -- [x] ./src/app/common/services/analytics-service.coffee -- [x] ./src/app/config/analytics/analytics.coffee -- [x] ./src/app/common/services/recorder-service.coffee -- [x] ./src/app/projects/projects.coffee -- [x] ./src/app/projects/states/dashboard/dashboard.coffee -- [x] ./src/app/projects/states/dashboard/directives/directives.coffee -- [x] ./src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.coffee -- [x] ./src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.coffee -- [x] ./src/app/projects/states/index/index.coffee -- [x] ./src/app/projects/states/states.coffee -- [ ] ./src/app/common/services/listener-service.coffee -- [x] ./src/app/config/root-controller/root-controller.coffee -- [ ] ./src/app/config/vendor-dependencies/vendor-dependencies.coffee -- [x] ./src/app/common/services/media-service.coffee -- [x] ./src/app/common/services/services.coffee -- [x] ./src/app/common/common.coffee -- [x] ./src/app/config/routing/routing.coffee -- [x] ./src/app/config/runtime/runtime.coffee -- [x] ./src/app/errors/errors.coffee -- [x] ./src/app/errors/states/states.coffee -- [x] ./src/app/units/states/edit/edit.coffee -- [x] ./src/app/units/states/index/index.coffee -- [x] ./src/app/units/states/states.coffee -- [x] ./src/app/units/units.coffee -- [x] ./src/app/config/config.coffee - -### TODO: - -- [ ] ./src/app/visualisations/summary-task-status-scatter.coffee (Unit task status summary) -- [ ] ./src/app/visualisations/target-grade-pie-chart.coffee -- [ ] ./src/app/visualisations/task-completion-box-plot.coffee -- [ ] ./src/app/visualisations/visualisations.coffee - ## Table of Contents - [Doubtfire Web ![CI](https://github.com/doubtfire-lms/doubtfire-web/actions/workflows/nodejs-ci.yml)](#doubtfire-web-) - - [Migration Progress](#migration-progress) - [Table of Contents](#table-of-contents) - [Getting Started](#getting-started) - [Deployment](#deployment) @@ -332,18 +101,11 @@ You may prefix this command with the following environment variables: ## Resources -Doubtfire Web is an [Angular](http://angularjs.org) application built using [Bootstrap](http://getbootstrap.com). It uses many Open Source libraries, which you can read up on: +Doubtfire Web is an [Angular](https://angular.dev) application built using [Material UI]https://material.angular.dev). It uses many Open Source libraries, which you can read up on: - [Lodash](http://lodash.com/docs) - [Moment.js](http://momentjs.com) -- [Font Awesome](http://fontawesome.io) -- [UI Router](https://github.com/angular-ui/ui-router) -- [UI Bootstrap](http://angular-ui.github.io/bootstrap/versioned-docs/0.13.4/) -- [UI Select](https://github.com/angular-ui/ui-select) - [NVD3 Charts](http://krispo.github.io/angular-nvd3/#/) -- [Angular X-Editable](http://vitalets.github.io/angular-xeditable/) -- [Angular Filters](https://github.com/a8m/angular-filter) -- [Angular Markdown Filter](https://github.com/vpegado/angular-markdown-filter) ## Contributing From 82e5175ce74f009991470f85774bc16645a34daf Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 8 Jun 2026 14:12:44 +1000 Subject: [PATCH 1098/1531] chore(release): 11.0.0-21 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc9e5e4f89..a572423099 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-21](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-20...v11.0.0-21) (2026-06-08) + + +### Bug Fixes + +* ensure unit dates map correctly ([532f185](https://github.com/b0ink/doubtfire-deploy/commit/532f185d2bc6839549a06a2f9e625c676cc280a6)) + ## [11.0.0-20](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-19...v11.0.0-20) (2026-06-04) ## [11.0.0-19](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-18...v11.0.0-19) (2026-06-03) diff --git a/package-lock.json b/package-lock.json index 791cc1e7c4..96eec16671 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-20", + "version": "11.0.0-21", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-20", + "version": "11.0.0-21", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 933be8f1ac..92e285615b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-20", + "version": "11.0.0-21", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 2fa3b71b6635d1148a3a28deea53a587b422273b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 8 Jun 2026 14:26:13 +1000 Subject: [PATCH 1099/1531] chore: fix portfolio submission date sorting --- .../portfolios-list/portfolios-list.component.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts index 46e481e21a..9047047eda 100644 --- a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts @@ -193,6 +193,15 @@ export class PortfoliosListComponent implements OnInit, AfterViewInit { return (aValue < bValue ? -1 : 1) * (isAsc ? 1 : -1); } + private sortDateValue(value: Date | string | number | null | undefined): number { + if (value === null || value === undefined || value === '') { + return 0; + } + + const time = new Date(value).getTime(); + return Number.isFinite(time) ? time : 0; + } + sortTableData(sort: Sort) { if (!sort.active || sort.direction === '') { return; @@ -223,8 +232,8 @@ export class PortfoliosListComponent implements OnInit, AfterViewInit { return this.sortCompare(a.submittedGrade, b.submittedGrade, sort.direction === 'asc'); case 'submission-date': return this.sortCompare( - a.portfolioSubmissionDate?.getTime() ?? 0, - b.portfolioSubmissionDate?.getTime() ?? 0, + this.sortDateValue(a.portfolioSubmissionDate), + this.sortDateValue(b.portfolioSubmissionDate), sort.direction === 'asc', ); case 'has-portfolio': From b55bcfc8f84f381beb7d62f41031db3ba6a38193 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Tue, 9 Jun 2026 11:54:20 +1000 Subject: [PATCH 1100/1531] feat: communications system (#1239) * chore: init communication system editor * feat: add core communications logic * refactor: improve ui layout * refactor: preview email * refactor: ability to edit conditions and actions * refactor: clean up ui layout * feat: enable set execution * refactor: improve layout * refactor: improve ui layout * feat: add confirmation modals to execute rule and set * feat: add scheduling ui * chore: remove duplicate header * fix: ensure students are loaded * refactor: move buttons * fix: disable horizontal scrolling * refactor: improve ui * chore: revert full width change * chore: improve current week ui * chore: format * feat: add spec con days condition * feat: add task comment action * chore: fix layout * chore: remove unnecessary shortcuts * refactor: use server side current week number * refactor: modularise components * chore: fix styling --- src/app/api/models/communication.ts | 142 ++ src/app/api/models/doubtfire-model.ts | 5 + src/app/api/models/teaching-period.ts | 85 + .../models/tutorial-stream/tutorial-stream.ts | 1 + src/app/api/models/unit.ts | 33 + .../services/communication-action.service.ts | 49 + .../communication-condition.service.ts | 51 + .../services/communication-rule.service.ts | 67 + .../api/services/communication-set.service.ts | 67 + .../api/services/tutorial-stream.service.ts | 2 +- src/app/api/services/unit.service.ts | 1 + src/app/doubtfire-angular.module.ts | 40 +- .../change-target-grade-action.component.html | 23 + .../change-target-grade-action.component.ts | 15 + .../communication-actions.component.html | 194 +++ .../communication-actions.component.ts | 13 + .../email-staff-action.component.html | 122 ++ .../email-staff-action.component.ts | 15 + .../email-student-action.component.html | 113 ++ .../email-student-action.component.ts | 15 + .../task-comment-action.component.html | 86 ++ .../task-comment-action.component.ts | 15 + ...ommunication-schedule-modal.component.html | 91 ++ .../communication-schedule-modal.component.ts | 187 +++ .../communication-schedules.component.html | 71 + .../communication-schedules.component.ts | 13 + .../communication-conditions.component.html | 497 ++++++ .../communication-conditions.component.ts | 13 + .../unit-communications-editor.component.html | 345 +++++ .../unit-communications-editor.component.scss | 0 .../unit-communications-editor.component.ts | 1365 +++++++++++++++++ .../edit/unit-admin-state.component.html | 16 +- .../states/edit/unit-admin-state.component.ts | 4 +- 33 files changed, 3750 insertions(+), 6 deletions(-) create mode 100644 src/app/api/models/communication.ts create mode 100644 src/app/api/services/communication-action.service.ts create mode 100644 src/app/api/services/communication-condition.service.ts create mode 100644 src/app/api/services/communication-rule.service.ts create mode 100644 src/app/api/services/communication-set.service.ts create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.html create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.ts create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.html create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.ts create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.html create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.ts create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.html create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.ts create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.html create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.ts create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.html create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.ts create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.html create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.ts create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.html create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.ts create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.html create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.scss create mode 100644 src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.ts diff --git a/src/app/api/models/communication.ts b/src/app/api/models/communication.ts new file mode 100644 index 0000000000..cbc5990a96 --- /dev/null +++ b/src/app/api/models/communication.ts @@ -0,0 +1,142 @@ +import {Entity} from 'ngx-entity-service'; + +export type CommunicationScheduleRecurrence = 'none' | 'daily' | 'weekly' | 'monthly'; + +export class CommunicationSetSchedule extends Entity { + id?: number; + client_key?: string; + communication_set_id?: number; + name?: string; + active = true; + anchor_week = 1; + anchor_day = 'Monday'; + hour = 8; + minute = 0; + timezone = 'UTC'; + recurrence: CommunicationScheduleRecurrence = 'none'; + interval = 1; + repeat_count?: number; + until_at?: string; + ice_cube_schedule?: Record; + next_run_at?: string; + last_run_at?: string; + last_enqueued_at?: string; + + constructor(json?: Partial) { + super(); + Object.assign(this, json); + } +} + +export class CommunicationCondition extends Entity { + id: number; + type: string; + communication_rule_id: number; + operator: string; + target_grade?: number; + task_definition_id?: number; + task_statuses?: string[]; + task_status_count?: number; + task_target_grade?: number; + last_sign_in_at?: string; + spec_con_days?: number; + tutorial_id?: number; + tutorial_stream_id?: number; + campus_id?: number; + + constructor(json?: Partial) { + super(); + Object.assign(this, json); + } +} + +export interface CommunicationRulePreviewStudent { + first_name?: string; + last_name?: string; + preferred_name?: string; + full_name?: string; + username?: string; + student_id?: string; + campus?: string; + target_grade?: number; + spec_con_days?: number; + last_sign_in_at?: string; +} + +export interface CommunicationRulePreviewAllocation { + rule_id: number; + rule_name: string; + position: number; + students: CommunicationRulePreviewStudent[]; +} + +export interface CommunicationRulePreviewResponse { + target_rule_id: number; + allocations: CommunicationRulePreviewAllocation[]; +} + +export interface CommunicationSetPreviewResponse { + id: number; + unit_id: number; + name: string; + active: boolean; + schedules?: Partial[]; + rules: Partial[]; + previews: CommunicationRulePreviewResponse[]; +} + +export class CommunicationAction extends Entity { + id: number; + type: string; + communication_rule_id: number; + task_definition_id?: number; + subject?: string; + body?: string; + email_tutors?: boolean; + email_convenors?: boolean; + target_grade?: number; + + constructor(json?: Partial) { + super(); + Object.assign(this, json); + } +} + +export class CommunicationRule extends Entity { + id: number; + communication_set_id: number; + name: string; + operator: 'and' | 'or'; + position: number; + active: boolean; + send_log_to_convenors: boolean; + conditions: CommunicationCondition[] = []; + actions: CommunicationAction[] = []; + + constructor(json?: Partial) { + super(); + Object.assign(this, json); + + this.conditions = + json?.conditions?.map((condition) => new CommunicationCondition(condition)) ?? []; + this.actions = json?.actions?.map((action) => new CommunicationAction(action)) ?? []; + } +} + +export class CommunicationSet extends Entity { + id: number; + unit_id: number; + name: string; + active: boolean; + schedules: CommunicationSetSchedule[] = []; + rules: CommunicationRule[] = []; + + constructor(json?: Partial) { + super(); + Object.assign(this, json); + + this.schedules = + json?.schedules?.map((schedule) => new CommunicationSetSchedule(schedule)) ?? []; + this.rules = json?.rules?.map((rule) => new CommunicationRule(rule)) ?? []; + } +} diff --git a/src/app/api/models/doubtfire-model.ts b/src/app/api/models/doubtfire-model.ts index 200f234bee..9ee73db62a 100644 --- a/src/app/api/models/doubtfire-model.ts +++ b/src/app/api/models/doubtfire-model.ts @@ -38,6 +38,7 @@ export * from './test-attempt'; export * from './task-comment/scorm-comment'; export * from './task-comment/scorm-extension-comment'; export * from './feedback-template'; +export * from './communication'; // Users -- are students or staff export * from './user/user'; @@ -65,3 +66,7 @@ export * from '../../common/services/grade.service'; export * from '../services/test-attempt.service'; export * from '../models/d2l/d2l_assessment_mapping.service'; export * from '../services/feedback-template.service'; +export * from '../services/communication-set.service'; +export * from '../services/communication-rule.service'; +export * from '../services/communication-condition.service'; +export * from '../services/communication-action.service'; diff --git a/src/app/api/models/teaching-period.ts b/src/app/api/models/teaching-period.ts index f8e11f5f8e..0c676ccc05 100644 --- a/src/app/api/models/teaching-period.ts +++ b/src/app/api/models/teaching-period.ts @@ -110,4 +110,89 @@ export class TeachingPeriod extends Entity { }, ); } + + public weekNumber(date: Date | string): number | null { + if (!date || !this.startDate) return null; + + const targetDate = this.normalizeDay(date); + const startDate = this.normalizeDay(this.startDate); + if (!targetDate || !startDate) return null; + + const millisecondsPerWeek = 1000 * 60 * 60 * 24 * 7; + let result = Math.floor((targetDate.getTime() - startDate.getTime()) / millisecondsPerWeek) + 1; + + for (const teachingBreak of this.breaks) { + const breakStart = this.normalizeDay(teachingBreak.startDate); + const breakEnd = this.breakEndDate(teachingBreak); + const firstMonday = this.firstMonday(teachingBreak); + const mondayAfterBreak = this.mondayAfterBreak(teachingBreak); + + if (!breakStart || !breakEnd || !firstMonday || !mondayAfterBreak) continue; + + if (targetDate >= breakStart) { + if (targetDate >= breakEnd) { + result -= teachingBreak.numberOfWeeks; + } else if (targetDate.getTime() === breakStart.getTime()) { + if (targetDate >= firstMonday) { + result -= 1; + } + } else if (targetDate >= firstMonday) { + result -= Math.ceil((targetDate.getTime() - firstMonday.getTime()) / millisecondsPerWeek); + } + + if (targetDate >= breakEnd && targetDate < mondayAfterBreak) { + result += 1; + } + } + } + + return result; + } + + private normalizeDay(date: Date | string | null | undefined): Date | null { + if (!date) return null; + + const parsed = date instanceof Date ? date : new Date(date); + if (Number.isNaN(parsed.valueOf())) return null; + + return new Date(parsed.getFullYear(), parsed.getMonth(), parsed.getDate()); + } + + private breakEndDate(teachingBreak: TeachingPeriodBreak): Date | null { + const startDate = this.normalizeDay(teachingBreak.startDate); + if (!startDate || !teachingBreak.numberOfWeeks) return null; + + return new Date( + startDate.getFullYear(), + startDate.getMonth(), + startDate.getDate() + teachingBreak.numberOfWeeks * 7, + ); + } + + private firstMonday(teachingBreak: TeachingPeriodBreak): Date | null { + const startDate = this.normalizeDay(teachingBreak.startDate); + if (!startDate) return null; + + if (startDate.getDay() === 1) return startDate; + if (startDate.getDay() === 0) { + return new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 1); + } + + return new Date( + startDate.getFullYear(), + startDate.getMonth(), + startDate.getDate() + (8 - startDate.getDay()), + ); + } + + private mondayAfterBreak(teachingBreak: TeachingPeriodBreak): Date | null { + const firstMonday = this.firstMonday(teachingBreak); + if (!firstMonday || !teachingBreak.numberOfWeeks) return null; + + return new Date( + firstMonday.getFullYear(), + firstMonday.getMonth(), + firstMonday.getDate() + teachingBreak.numberOfWeeks * 7, + ); + } } diff --git a/src/app/api/models/tutorial-stream/tutorial-stream.ts b/src/app/api/models/tutorial-stream/tutorial-stream.ts index 2ba8c4db36..17c101fa0e 100644 --- a/src/app/api/models/tutorial-stream/tutorial-stream.ts +++ b/src/app/api/models/tutorial-stream/tutorial-stream.ts @@ -2,6 +2,7 @@ import {Entity} from 'ngx-entity-service'; import {Tutorial, Unit} from '../doubtfire-model'; export class TutorialStream extends Entity { + id: number; name: string; abbreviation: string; activityType: string; diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index a976538d4f..5bd4289862 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -58,6 +58,7 @@ export class Unit extends Entity { startDate: Date; //TODO: or string endDate: Date; //TODO: or string portfolioAutoGenerationDate: Date; + currentUnitWeek: number | null; assessmentEnabled: boolean; overseerImageId: number = null; // image needs to be lazy loadaed @@ -272,6 +273,38 @@ export class Unit extends Entity { return Math.ceil(this.totalDuration / (1000 * 60 * 60 * 24 * 7)); } + /** + * Calculate the teaching week number for a given date. + * Mirrors the Rails fallback in Unit#week_number when a teaching period + * helper is not being used on the frontend. + */ + public weekNumber(date: Date | string): number | null { + if (!date || !this.startDate) return null; + + if (this.teachingPeriod) { + return this.teachingPeriod.weekNumber(date); + } + + const targetDate = date instanceof Date ? date : new Date(date); + if (Number.isNaN(targetDate.valueOf())) return null; + const normalizedTargetDate = new Date( + targetDate.getFullYear(), + targetDate.getMonth(), + targetDate.getDate(), + ); + const normalizedStartDate = new Date( + this.startDate.getFullYear(), + this.startDate.getMonth(), + this.startDate.getDate(), + ); + const millisecondsPerWeek = 1000 * 60 * 60 * 24 * 7; + return ( + Math.floor( + (normalizedTargetDate.valueOf() - normalizedStartDate.valueOf()) / millisecondsPerWeek, + ) + 1 + ); + } + /** * Calculate how much time has elapsed in the teaching period, based on the start and * end date of the unit relative to the current date. diff --git a/src/app/api/services/communication-action.service.ts b/src/app/api/services/communication-action.service.ts new file mode 100644 index 0000000000..caa66352ca --- /dev/null +++ b/src/app/api/services/communication-action.service.ts @@ -0,0 +1,49 @@ +import {Observable, map} from 'rxjs'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {CommunicationAction} from '../models/communication'; + +@Injectable() +export class CommunicationActionService { + constructor(private httpClient: HttpClient) {} + + public getForRule(unitId: number, ruleId: number): Observable { + return this.httpClient + .get[]>(this.endpoint(unitId, ruleId)) + .pipe(map((actions) => actions.map((action) => new CommunicationAction(action)))); + } + + public create( + unitId: number, + ruleId: number, + action: Partial, + ): Observable { + return this.httpClient + .post>(this.endpoint(unitId, ruleId), { + communication_action: action, + }) + .pipe(map((created) => new CommunicationAction(created))); + } + + public delete(unitId: number, ruleId: number, actionId: number): Observable { + return this.httpClient.delete(`${this.endpoint(unitId, ruleId)}/${actionId}`); + } + + public update( + unitId: number, + ruleId: number, + actionId: number, + action: Partial, + ): Observable { + return this.httpClient + .put>(`${this.endpoint(unitId, ruleId)}/${actionId}`, { + communication_action: action, + }) + .pipe(map((updated) => new CommunicationAction(updated))); + } + + private endpoint(unitId: number, ruleId: number): string { + return `${API_URL}/units/${unitId}/communication_rules/${ruleId}/actions`; + } +} diff --git a/src/app/api/services/communication-condition.service.ts b/src/app/api/services/communication-condition.service.ts new file mode 100644 index 0000000000..f8811e21eb --- /dev/null +++ b/src/app/api/services/communication-condition.service.ts @@ -0,0 +1,51 @@ +import {Observable, map} from 'rxjs'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {CommunicationCondition} from '../models/communication'; + +@Injectable() +export class CommunicationConditionService { + constructor(private httpClient: HttpClient) {} + + public getForRule(unitId: number, ruleId: number): Observable { + return this.httpClient + .get[]>(this.endpoint(unitId, ruleId)) + .pipe( + map((conditions) => conditions.map((condition) => new CommunicationCondition(condition))), + ); + } + + public create( + unitId: number, + ruleId: number, + condition: Partial, + ): Observable { + return this.httpClient + .post>(this.endpoint(unitId, ruleId), { + communication_condition: condition, + }) + .pipe(map((created) => new CommunicationCondition(created))); + } + + public delete(unitId: number, ruleId: number, conditionId: number): Observable { + return this.httpClient.delete(`${this.endpoint(unitId, ruleId)}/${conditionId}`); + } + + public update( + unitId: number, + ruleId: number, + conditionId: number, + condition: Partial, + ): Observable { + return this.httpClient + .put>(`${this.endpoint(unitId, ruleId)}/${conditionId}`, { + communication_condition: condition, + }) + .pipe(map((updated) => new CommunicationCondition(updated))); + } + + private endpoint(unitId: number, ruleId: number): string { + return `${API_URL}/units/${unitId}/communication_rules/${ruleId}/conditions`; + } +} diff --git a/src/app/api/services/communication-rule.service.ts b/src/app/api/services/communication-rule.service.ts new file mode 100644 index 0000000000..a1f2d20c3c --- /dev/null +++ b/src/app/api/services/communication-rule.service.ts @@ -0,0 +1,67 @@ +import {Observable, map} from 'rxjs'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {CommunicationRule, CommunicationRulePreviewResponse} from '../models/communication'; +import {SidekiqJob} from '../models/sidekiq-job'; + +@Injectable() +export class CommunicationRuleService { + constructor(private httpClient: HttpClient) {} + + public getForSet(unitId: number, setId: number): Observable { + return this.httpClient + .get[]>(this.setEndpoint(unitId, setId)) + .pipe(map((rules) => rules.map((rule) => new CommunicationRule(rule)))); + } + + public createForSet( + unitId: number, + setId: number, + rule: Pick, + ): Observable { + return this.httpClient + .post>(this.setEndpoint(unitId, setId), { + communication_rule: rule, + }) + .pipe(map((created) => new CommunicationRule(created))); + } + + public updateForUnit( + unitId: number, + ruleId: number, + rule: Partial>, + ): Observable { + return this.httpClient + .put>(`${this.endpoint(unitId)}/${ruleId}`, { + communication_rule: rule, + }) + .pipe(map((updated) => new CommunicationRule(updated))); + } + + public deleteForUnit(unitId: number, ruleId: number): Observable { + return this.httpClient.delete(`${this.endpoint(unitId)}/${ruleId}`); + } + + public previewForUnit( + unitId: number, + ruleId: number, + ): Observable { + return this.httpClient.post( + `${this.endpoint(unitId)}/${ruleId}/preview`, + {}, + ); + } + + public executeForUnit(unitId: number, ruleId: number): Observable { + return this.httpClient.post(`${this.endpoint(unitId)}/${ruleId}/execute`, {}); + } + + private endpoint(unitId: number): string { + return `${API_URL}/units/${unitId}/communication_rules`; + } + + private setEndpoint(unitId: number, setId: number): string { + return `${API_URL}/units/${unitId}/communication_sets/${setId}/rules`; + } +} diff --git a/src/app/api/services/communication-set.service.ts b/src/app/api/services/communication-set.service.ts new file mode 100644 index 0000000000..eed9c7779c --- /dev/null +++ b/src/app/api/services/communication-set.service.ts @@ -0,0 +1,67 @@ +import {Observable, map} from 'rxjs'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import { + CommunicationSet, + CommunicationSetPreviewResponse, + CommunicationSetSchedule, +} from '../models/communication'; +import {SidekiqJob} from '../models/sidekiq-job'; + +@Injectable() +export class CommunicationSetService { + constructor(private httpClient: HttpClient) {} + + public getForUnit(unitId: number): Observable { + return this.httpClient + .get[]>(this.endpoint(unitId)) + .pipe(map((sets) => sets.map((set) => new CommunicationSet(set)))); + } + + public createForUnit( + unitId: number, + set: Pick & Partial>, + ): Observable { + return this.httpClient + .post>(this.endpoint(unitId), { + communication_set: set, + }) + .pipe(map((created) => new CommunicationSet(created))); + } + + public deleteForUnit(unitId: number, setId: number): Observable { + return this.httpClient.delete(`${this.endpoint(unitId)}/${setId}`); + } + + public updateForUnit( + unitId: number, + setId: number, + set: Partial> & { + schedules?: Partial[]; + }, + ): Observable { + return this.httpClient + .put>(`${this.endpoint(unitId)}/${setId}`, { + communication_set: set, + }) + .pipe(map((updated) => new CommunicationSet(updated))); + } + + public getForUnitById( + unitId: number, + setId: number, + ): Observable { + return this.httpClient.get( + `${this.endpoint(unitId)}/${setId}`, + ); + } + + public executeForUnit(unitId: number, setId: number): Observable { + return this.httpClient.post(`${this.endpoint(unitId)}/${setId}/execute`, {}); + } + + private endpoint(unitId: number): string { + return `${API_URL}/units/${unitId}/communication_sets`; + } +} diff --git a/src/app/api/services/tutorial-stream.service.ts b/src/app/api/services/tutorial-stream.service.ts index 0f17efcb7c..573d831854 100644 --- a/src/app/api/services/tutorial-stream.service.ts +++ b/src/app/api/services/tutorial-stream.service.ts @@ -11,7 +11,7 @@ export class TutorialStreamService extends CachedEntityService { constructor(httpClient: HttpClient) { super(httpClient, API_URL); - this.mapping.addKeys('name', 'abbreviation', 'activityType'); + this.mapping.addKeys('id', 'name', 'abbreviation', 'activityType'); this.mapping.mapAllKeysToJson(); } diff --git a/src/app/api/services/unit.service.ts b/src/app/api/services/unit.service.ts index 150f99ba38..8dafda21af 100644 --- a/src/app/api/services/unit.service.ts +++ b/src/app/api/services/unit.service.ts @@ -154,6 +154,7 @@ export class UnitService extends CachedEntityService { }, toJsonFn: MappingFunctions.mapDayToJson, }, + 'currentUnitWeek', { keys: 'portfolioAutoGenerationDate', toEntityFn: (data, key, _entity, _params?) => { diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index f6d671883d..4fefb44031 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -4,8 +4,6 @@ import {PickerModule} from '@ctrl/ngx-emoji-mart'; import {EmojiModule} from '@ctrl/ngx-emoji-mart/ngx-emoji'; import {CodeEditorModule} from '@ngstack/code-editor'; import {NgxChartsModule} from '@swimlane/ngx-charts'; -// import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; -// import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; import {GANTT_GLOBAL_CONFIG, GanttLinkLineType, NgxGanttModule} from '@worktile/gantt'; import {DateAdapter as CalendarDateAdapter, CalendarModule} from 'angular-calendar'; import {adapterFactory} from 'angular-calendar/date-adapters/date-fns'; @@ -31,6 +29,8 @@ import { TaskCommentComposerComponent, } from 'src/app/tasks/task-comment-composer/task-comment-composer.component'; import {environment} from 'src/environments/environment'; +// import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; +// import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; import {ClipboardModule} from '@angular/cdk/clipboard'; import {DragDropModule} from '@angular/cdk/drag-drop'; import {ScrollingModule} from '@angular/cdk/scrolling'; @@ -49,9 +49,9 @@ import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE, + MatNativeDateModule, MatOptionModule, } from '@angular/material/core'; -import {MatNativeDateModule} from '@angular/material/core'; import {MatDatepickerModule} from '@angular/material/datepicker'; import {MatDialogModule} from '@angular/material/dialog'; import {MatDividerModule} from '@angular/material/divider'; @@ -77,10 +77,16 @@ import {MatTableModule} from '@angular/material/table'; import {MatTabsModule} from '@angular/material/tabs'; import {MatToolbarModule} from '@angular/material/toolbar'; import {MatTooltipModule} from '@angular/material/tooltip'; +import {MatTreeModule} from '@angular/material/tree'; import {BrowserModule, DomSanitizer, Title} from '@angular/platform-browser'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {RouterModule} from '@angular/router'; import {ServiceWorkerModule} from '@angular/service-worker'; +// import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; +// import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; +// import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; +// import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; +import {UpgradeModule} from '@angular/upgrade/static'; import {take} from 'rxjs/operators'; import {EditProfileComponent} from './account/edit-profile/edit-profile.component'; import {ActivityTypeListComponent} from './admin/institution-settings/activity-type-list/activity-type-list.component'; @@ -122,6 +128,10 @@ import { UserService, WebcalService, } from './api/models/doubtfire-model'; +import {CommunicationActionService} from './api/services/communication-action.service'; +import {CommunicationConditionService} from './api/services/communication-condition.service'; +import {CommunicationRuleService} from './api/services/communication-rule.service'; +import {CommunicationSetService} from './api/services/communication-set.service'; import {DiscussionPromptService} from './api/services/discussion-prompt.service'; import {FeedbackTemplateService} from './api/services/feedback-template.service'; import {GroupService} from './api/services/group.service'; @@ -291,6 +301,15 @@ import {TaskSubmissionHistoryComponent} from './tasks/task-submission-history/ta import {UnitStudentEnrolmentModalComponent} from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component'; import {AnalyticsTutorTimesComponent} from './units/states/analytics/directives/analytics-tutor-times.component'; import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-route.component'; +import {ChangeTargetGradeActionComponent} from './units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component'; +import {CommunicationActionsComponent} from './units/states/edit/directives/unit-communications-editor/actions/communication-actions.component'; +import {EmailStaffActionComponent} from './units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component'; +import {EmailStudentActionComponent} from './units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component'; +import {TaskCommentActionComponent} from './units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component'; +import {CommunicationScheduleModalComponent} from './units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component'; +import {CommunicationSchedulesComponent} from './units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component'; +import {CommunicationConditionsComponent} from './units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component'; +import {UnitCommunicationsEditorComponent} from './units/states/edit/directives/unit-communications-editor/unit-communications-editor.component'; import { D2lUnitDetailsFormComponent, D2lUnitDetailsModal, @@ -576,6 +595,15 @@ const GANTT_CHART_CONFIG = { UploadSubmissionModalComponent, ConfirmModerationModalComponent, TaskClaimComponent, + ChangeTargetGradeActionComponent, + CommunicationActionsComponent, + CommunicationConditionsComponent, + CommunicationScheduleModalComponent, + CommunicationSchedulesComponent, + EmailStaffActionComponent, + EmailStudentActionComponent, + TaskCommentActionComponent, + UnitCommunicationsEditorComponent, TutorialsComponent, UnitStaffEditorComponent, PortfolioGradeSelectStepComponent, @@ -682,6 +710,10 @@ const GANTT_CHART_CONFIG = { OverseerStepService, OverseerStepResultService, TutorNoteService, + CommunicationActionService, + CommunicationConditionService, + CommunicationRuleService, + CommunicationSetService, CsvResultModalService, CsvUploadModalService, ], @@ -728,6 +760,8 @@ const GANTT_CHART_CONFIG = { MatExpansionModule, MatGridListModule, MatTabsModule, + MatTreeModule, + UpgradeModule, MatTableModule, MatChipsModule, MatSnackBarModule, diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.html b/src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.html new file mode 100644 index 0000000000..205949ae2f --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.html @@ -0,0 +1,23 @@ +@if (mode === 'edit') { + + Target grade + + @for (grade of editor.targetGrades; track grade.value) { + + {{ grade.label }} + + } + + +} @else { + + Target grade + + @for (grade of editor.targetGrades; track grade.value) { + + {{ grade.label }} + + } + + +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.ts new file mode 100644 index 0000000000..2dad58259f --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.ts @@ -0,0 +1,15 @@ +import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; +import {Component, Input} from '@angular/core'; +import type {UnitCommunicationsEditorComponent} from '../../unit-communications-editor.component'; + +@Component({ + selector: 'f-change-target-grade-action', + standalone: false, + templateUrl: './change-target-grade-action.component.html', + host: {class: 'flex w-full flex-col items-center'}, +}) +export class ChangeTargetGradeActionComponent { + @Input({required: true}) editor: UnitCommunicationsEditorComponent; + @Input({required: true}) rule: CommunicationRule; + @Input({required: true}) mode: 'add' | 'edit'; +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.html b/src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.html new file mode 100644 index 0000000000..bed8d2313f --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.html @@ -0,0 +1,194 @@ +
    + + @for (action of rule.actions; track action.id) { + + @if (editor.editingActionId[rule.id] === action.id) { +
    + + Action + + @for (type of editor.actionTypes; track type) { + + {{ editor.actionTypeLabel(type) }} + + } + + + @switch (editor.actionFor(rule).type) { + @case ('EmailStudentAction') { + + } + @case ('EmailStaffAction') { + + } + @case ('TaskCommentAction') { + + } + @case ('ChangeTargetGradeAction') { + + } + } +
    + + +
    +
    + } @else { +
    +
    +
    + {{ editor.actionTypeLabel(action.type) }} +
    +
    + @switch (action.type) { + @case ('ChangeTargetGradeAction') { + Change student's target grade to + + {{ editor.targetGradeName(action.target_grade) }} + + } + @case ('EmailStudentAction') { + @if (action.subject || action.body) { +
    + @if (action.subject) { +
    +
    Subject
    +
    +
    + } + @if (action.body) { +
    +
    Body
    +
    +
    + } +
    + } + } + @case ('EmailStaffAction') { + Send email to + + {{ editor.staffAudienceLabel(action) }} + + @if (action.subject || action.body) { +
    + @if (action.subject) { +
    +
    Subject
    +
    +
    + } + @if (action.body) { +
    +
    Body
    +
    +
    + } +
    + } + } + @case ('TaskCommentAction') { + Add comment to + + {{ editor.taskDefinitionLabel(action.task_definition_id) }} + + @if (action.body) { +
    +
    +
    Comment
    +
    +
    +
    + } + } + @default { + {{ editor.actionSummary(action) }} + } + } +
    +
    +
    + + +
    +
    + } +
    + } +
    + + @if (editor.actionFormOpen[rule.id] && !editor.editingActionId[rule.id]) { +
    + + Action + + @for (type of editor.actionTypes; track type) { + + {{ editor.actionTypeLabel(type) }} + + } + + + + @switch (editor.actionFor(rule).type) { + @case ('EmailStudentAction') { + + } + + @case ('EmailStaffAction') { + + } + + @case ('TaskCommentAction') { + + } + + @case ('ChangeTargetGradeAction') { + + } + } + + + + +
    + } @else { +
    + +
    + } +
    diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.ts new file mode 100644 index 0000000000..65e8dab8c5 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.ts @@ -0,0 +1,13 @@ +import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; +import {Component, Input} from '@angular/core'; +import type {UnitCommunicationsEditorComponent} from '../unit-communications-editor.component'; + +@Component({ + selector: 'f-communication-actions', + standalone: false, + templateUrl: './communication-actions.component.html', +}) +export class CommunicationActionsComponent { + @Input({required: true}) editor: UnitCommunicationsEditorComponent; + @Input({required: true}) rule: CommunicationRule; +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.html b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.html new file mode 100644 index 0000000000..f9b756c6fc --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.html @@ -0,0 +1,122 @@ +@if (mode === 'edit') { +
    + + Subject + + + + + @for (variable of editor.emailVariables; track variable.token) { + + } + + @if (editor.actionFor(rule).subject) { +
    +
    Subject Preview
    +
    +
    + } +
    + + Body + + + +
    +
    Body Preview
    +
    + @if (editor.actionFor(rule).body) { +
    + } @else { +
    Preview will appear here.
    + } +
    +
    +
    + + @for (variable of editor.emailVariables; track variable.token) { + + } + +
    + Tutors + Convenors +
    +
    Sent from the main convenor.
    +
    +} @else { +
    + + Subject + + + + + @for (variable of editor.emailVariables; track variable.token) { + + } + + + @if (editor.actionFor(rule).subject) { +
    +
    Subject Preview
    +
    +
    + } + +
    + + Body + + + +
    +
    Body Preview
    +
    + @if (editor.actionFor(rule).body) { +
    + } @else { +
    Preview will appear here.
    + } +
    +
    +
    + + @for (variable of editor.emailVariables; track variable.token) { + + } + + +
    + Tutors + Convenors +
    +
    Sent from the main convenor.
    +
    +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.ts new file mode 100644 index 0000000000..00f5f42d57 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.ts @@ -0,0 +1,15 @@ +import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; +import {Component, Input} from '@angular/core'; +import type {UnitCommunicationsEditorComponent} from '../../unit-communications-editor.component'; + +@Component({ + selector: 'f-email-staff-action', + standalone: false, + templateUrl: './email-staff-action.component.html', + host: {class: 'block w-full'}, +}) +export class EmailStaffActionComponent { + @Input({required: true}) editor: UnitCommunicationsEditorComponent; + @Input({required: true}) rule: CommunicationRule; + @Input({required: true}) mode: 'add' | 'edit'; +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.html b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.html new file mode 100644 index 0000000000..90bdbf0273 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.html @@ -0,0 +1,113 @@ +@if (mode === 'edit') { +
    + + Subject + + + + + @for (variable of editor.emailVariables; track variable.token) { + + } + + @if (editor.actionFor(rule).subject) { +
    +
    Subject Preview
    +
    +
    + } +
    + + Body + + + +
    +
    Body Preview
    +
    + @if (editor.actionFor(rule).body) { +
    + } @else { +
    Preview will appear here.
    + } +
    +
    +
    + + @for (variable of editor.emailVariables; track variable.token) { + + } + +
    Sent from the main convenor.
    +
    +} @else { +
    + + Subject + + + + + @for (variable of editor.emailVariables; track variable.token) { + + } + + + @if (editor.actionFor(rule).subject) { +
    +
    Subject Preview
    +
    +
    + } + +
    + + Body + + + +
    +
    Body Preview
    +
    + @if (editor.actionFor(rule).body) { +
    + } @else { +
    Preview will appear here.
    + } +
    +
    +
    + + @for (variable of editor.emailVariables; track variable.token) { + + } + +
    Sent from the main convenor.
    +
    +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.ts new file mode 100644 index 0000000000..d25b2bbe3f --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.ts @@ -0,0 +1,15 @@ +import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; +import {Component, Input} from '@angular/core'; +import type {UnitCommunicationsEditorComponent} from '../../unit-communications-editor.component'; + +@Component({ + selector: 'f-email-student-action', + standalone: false, + templateUrl: './email-student-action.component.html', + host: {class: 'block w-full'}, +}) +export class EmailStudentActionComponent { + @Input({required: true}) editor: UnitCommunicationsEditorComponent; + @Input({required: true}) rule: CommunicationRule; + @Input({required: true}) mode: 'add' | 'edit'; +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.html b/src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.html new file mode 100644 index 0000000000..ab8034b1a1 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.html @@ -0,0 +1,86 @@ +@if (mode === 'edit') { +
    + + Task + + @for (taskDefinition of editor.taskDefinitions; track taskDefinition.id) { + + {{ taskDefinition.abbreviation }} + {{ taskDefinition.name }} + + } + + +
    + + Comment + + + +
    +
    Comment Preview
    +
    + @if (editor.actionFor(rule).body) { +
    + } @else { +
    Preview will appear here.
    + } +
    +
    +
    + + @for (variable of editor.emailVariables; track variable.token) { + + } + +
    Sent from the main convenor.
    +
    +} @else { +
    + + Task + + @for (taskDefinition of editor.taskDefinitions; track taskDefinition.id) { + + {{ taskDefinition.abbreviation }} {{ taskDefinition.name }} + + } + + +
    + + Comment + + + +
    +
    Comment Preview
    +
    + @if (editor.actionFor(rule).body) { +
    + } @else { +
    Preview will appear here.
    + } +
    +
    +
    + + @for (variable of editor.emailVariables; track variable.token) { + + } + +
    Sent from the main convenor.
    +
    +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.ts new file mode 100644 index 0000000000..c95831579e --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.ts @@ -0,0 +1,15 @@ +import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; +import {Component, Input} from '@angular/core'; +import type {UnitCommunicationsEditorComponent} from '../../unit-communications-editor.component'; + +@Component({ + selector: 'f-task-comment-action', + standalone: false, + templateUrl: './task-comment-action.component.html', + host: {class: 'block w-full'}, +}) +export class TaskCommentActionComponent { + @Input({required: true}) editor: UnitCommunicationsEditorComponent; + @Input({required: true}) rule: CommunicationRule; + @Input({required: true}) mode: 'add' | 'edit'; +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.html b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.html new file mode 100644 index 0000000000..a4b227f91e --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.html @@ -0,0 +1,91 @@ +

    + {{ draft.id ? 'Edit communication schedule' : 'Add communication schedule' }} +

    + + +
    + + Name + + + + + Timezone + + +
    + + Schedule active + +
    + + Week + + + + + Day + + @for (weekday of weekdays; track weekday.value) { + {{ weekday.label }} + } + + + + + Hour + + + + + Minute + + +
    + + + Repeat + + One time only + Daily + Weekly + Monthly + + + + @if (draft.recurrence !== 'none') { +
    + + Every + + + + + Stop after runs + + + + + Or stop on + + +
    + } + +
    +
    Summary
    +
    {{ scheduleSummary() }}
    +
    + + +
    + + + + + diff --git a/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.ts new file mode 100644 index 0000000000..be1b88c489 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.ts @@ -0,0 +1,187 @@ +import { + Campus, + CampusService, + CommunicationSetSchedule, + Unit, +} from 'src/app/api/models/doubtfire-model'; +import {Component, Inject, OnInit} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; + +export interface CommunicationScheduleModalData { + schedule?: CommunicationSetSchedule; + unit?: Unit; +} + +export const SCHEDULE_WEEKDAYS = [ + {value: 0, label: 'Sunday', shortLabel: 'Sun'}, + {value: 1, label: 'Monday', shortLabel: 'Mon'}, + {value: 2, label: 'Tuesday', shortLabel: 'Tue'}, + {value: 3, label: 'Wednesday', shortLabel: 'Wed'}, + {value: 4, label: 'Thursday', shortLabel: 'Thu'}, + {value: 5, label: 'Friday', shortLabel: 'Fri'}, + {value: 6, label: 'Saturday', shortLabel: 'Sat'}, +] as const; + +@Component({ + selector: 'f-communication-schedule-modal', + standalone: false, + templateUrl: './communication-schedule-modal.component.html', +}) +export class CommunicationScheduleModalComponent implements OnInit { + readonly weekdays = SCHEDULE_WEEKDAYS; + campuses: Campus[] = []; + timezonePlaceholder = 'UTC'; + draft = new CommunicationSetSchedule({ + name: 'Schedule 1', + active: true, + anchor_week: 1, + anchor_day: 'Monday', + recurrence: 'none', + interval: 1, + timezone: 'UTC', + hour: 8, + minute: 0, + }); + untilDateTime = ''; + + constructor( + private campusService: CampusService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: CommunicationScheduleModalData, + ) { + if (data.schedule) { + this.draft = new CommunicationSetSchedule({ + ...data.schedule, + }); + } + + this.untilDateTime = this.asDateTimeLocal(this.draft.until_at); + } + + ngOnInit(): void { + this.campusService.query().subscribe((campuses) => { + this.campuses = campuses; + const defaultTimezone = campuses[0]?.timezone; + if (!defaultTimezone) return; + + this.timezonePlaceholder = defaultTimezone; + if (!this.draft.timezone || this.draft.timezone === 'UTC') { + this.draft.timezone = defaultTimezone; + } + }); + } + + canSave(): boolean { + return !!this.draft.anchor_week && !!this.draft.anchor_day; + } + + save(): void { + const schedule = new CommunicationSetSchedule({ + ...this.draft, + name: this.draft.name?.trim() || 'Untitled schedule', + until_at: this.untilDateTime || undefined, + anchor_week: Math.max(1, Number(this.draft.anchor_week || 1)), + anchor_day: this.draft.anchor_day || 'Monday', + hour: this.safeHour(), + minute: this.safeMinute(), + }); + + schedule.ice_cube_schedule = this.toIceCubePayload(schedule); + this.dialogRef.close(schedule); + } + + scheduleSummary(): string { + const parts: string[] = []; + parts.push( + `Starts Week ${this.draft.anchor_week || 1} ${this.draft.anchor_day || 'Monday'} at ${this.timeLabel(this.safeHour(), this.safeMinute())}`, + ); + + switch (this.draft.recurrence) { + case 'daily': + parts.push(`Repeats every ${this.draft.interval || 1} day(s)`); + break; + case 'weekly': + parts.push(`Repeats every ${this.draft.interval || 1} week(s)`); + break; + case 'monthly': + parts.push(`Repeats every ${this.draft.interval || 1} month(s)`); + break; + default: + parts.push('Runs once'); + } + + if (this.draft.repeat_count) parts.push(`up to ${this.draft.repeat_count} times`); + if (this.untilDateTime) parts.push(`until ${this.untilDateTime}`); + + return parts.join(' | '); + } + + iceCubePreview(): string { + return JSON.stringify(this.toIceCubePayload(this.draft), null, 2); + } + + private safeHour(): number { + return Math.min(23, Math.max(0, Number(this.draft.hour ?? 8))); + } + + private safeMinute(): number { + return Math.min(59, Math.max(0, Number(this.draft.minute ?? 0))); + } + + private toIceCubePayload(schedule: CommunicationSetSchedule): Record { + const payload: Record = { + timezone: schedule.timezone || 'UTC', + anchor: this.anchorPayload(schedule), + recurrence: schedule.recurrence, + interval: schedule.interval || 1, + limits: { + count: schedule.repeat_count || null, + until: schedule.until_at || null, + }, + rules: [], + }; + + const rules = payload.rules as Record[]; + switch (schedule.recurrence) { + case 'daily': + rules.push({ + type: 'daily', + interval: schedule.interval || 1, + }); + break; + case 'weekly': + rules.push({ + type: 'weekly', + interval: schedule.interval || 1, + }); + break; + case 'monthly': + rules.push({ + type: 'monthly', + interval: schedule.interval || 1, + }); + break; + default: + rules.push({type: 'one_off'}); + } + + return payload; + } + + private anchorPayload(schedule: CommunicationSetSchedule): Record { + return { + week: schedule.anchor_week || 1, + day: schedule.anchor_day || 'Monday', + time_of_day: this.timeLabel(schedule.hour || 0, schedule.minute || 0), + }; + } + + private asDateTimeLocal(value?: string): string { + if (!value) return ''; + return value.length >= 16 ? value.slice(0, 16) : value; + } + + private timeLabel(hour: number, minute: number): string { + return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`; + } +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.html b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.html new file mode 100644 index 0000000000..b2da72c454 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.html @@ -0,0 +1,71 @@ +@if (editor.setPreviewLoading) { + +} + +
    +
    +
    +
    Schedules
    +
    Build one-off or recurring schedules for this set.
    +
    + +
    + + @if ((set.schedules || []).length) { +
    + @for (schedule of set.schedules || []; track editor.scheduleTrackId(schedule)) { +
    +
    +
    +
    {{ schedule.name || 'Untitled schedule' }}
    +
    {{ editor.scheduleSummary(schedule) }}
    +
    + +
    + + {{ schedule.active ? 'Active' : 'Inactive' }} + + + +
    +
    + +
    +
    +
    Anchor
    +
    {{ editor.scheduleAnchorSummary(schedule) }}
    +
    +
    +
    Time
    +
    {{ editor.scheduleTimeSummary(schedule) }}
    +
    +
    +
    Next Run
    +
    {{ editor.scheduleNextRunSummary(schedule) }}
    +
    +
    +
    Last Run
    +
    {{ editor.scheduleLastRunSummary(schedule) }}
    +
    +
    +
    + } +
    + } @else { +
    + No schedules yet. Add one to run this set on a fixed date or on a repeating cadence. +
    + } +
    diff --git a/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.ts new file mode 100644 index 0000000000..b80c98e2f3 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.ts @@ -0,0 +1,13 @@ +import {CommunicationSet} from 'src/app/api/models/doubtfire-model'; +import {Component, Input} from '@angular/core'; +import type {UnitCommunicationsEditorComponent} from '../unit-communications-editor.component'; + +@Component({ + selector: 'f-communication-schedules', + standalone: false, + templateUrl: './communication-schedules.component.html', +}) +export class CommunicationSchedulesComponent { + @Input({required: true}) editor: UnitCommunicationsEditorComponent; + @Input({required: true}) set: CommunicationSet; +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.html b/src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.html new file mode 100644 index 0000000000..83c935cac4 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.html @@ -0,0 +1,497 @@ +
    +
    + + Conditions + + @for (option of editor.logicalOperatorOptions; track option.value) { + + {{ option.label }} + + } + + +
    + + + @for (condition of rule.conditions; track condition.id) { + + @if (editor.editingConditionId[rule.id] === condition.id) { +
    + + Condition + + @for (type of editor.conditionTypes; track type) { + + {{ editor.conditionTypeLabel(type) }} + + } + + + + @if (editor.conditionFor(rule).type === 'TaskDefinitionStatusCondition') { + + Task + + @for (taskDefinition of editor.taskDefinitions; track taskDefinition.id) { + + {{ taskDefinition.abbreviation }} {{ taskDefinition.name }} + + } + + + } + + + Operator + + @for ( + operator of editor.operatorsFor(editor.conditionFor(rule).type); + track operator + ) { + + {{ editor.operatorLabel(operator) }} + + } + + + + @if (editor.conditionFor(rule).type === 'TaskStatusCountCondition') { + + Count + + + + + Task grade + + @for (grade of editor.targetGrades; track grade.value) { + + {{ grade.label }} + + } + + + } + + @switch (editor.conditionFor(rule).type) { + @case ('TargetGradeCondition') { + + Target grade + + @for (grade of editor.targetGrades; track grade.value) { + + {{ grade.label }} + + } + + + } + @case ('TaskDefinitionStatusCondition') { + + Statuses + + @for (status of editor.taskStatuses; track status) { + + {{ editor.taskStatusLabel(status) }} + + } + + + } + @case ('TaskStatusCountCondition') { + + Statuses + + @for (status of editor.taskStatuses; track status) { + + {{ editor.taskStatusLabel(status) }} + + } + + + } + @case ('LoginStatusCondition') { + + Last sign in + + + } + @case ('SpecConCondition') { + + Days + + + } + @case ('TutorialEnrolmentCondition') { + + Tutorial + + @for (tutorial of editor.tutorials; track tutorial.id) { + + {{ tutorial.abbreviation }} {{ tutorial.description }} + + } + + + } + @case ('TutorialStreamEnrolmentCondition') { + + Tutorial stream + + @for (stream of editor.tutorialStreams; track stream.id) { + + {{ stream.abbreviation }} {{ stream.name }} + + } + + + } + @case ('CampusCondition') { + + Campus + + @for (campus of editor.campuses; track campus.id) { + + {{ campus.abbreviation }} {{ campus.name }} + + } + + + } + } + + + +
    + } @else { +
    +
    +
    + {{ editor.conditionTypeLabel(condition.type) }} +
    +
    + @switch (condition.type) { + @case ('TargetGradeCondition') { + Students with a + Target Grade + + {{ editor.operatorLabel(condition.operator) }} + + + {{ editor.targetGradeName(condition.target_grade) }} + + } + @case ('TaskDefinitionStatusCondition') { + Students that have + + {{ editor.taskDefinitionLabel(condition.task_definition_id) }} + + + {{ editor.taskStatusPredicate(condition.operator) }} + + + {{ editor.taskStatusesLabel(condition.task_statuses) }} + + } + @case ('TaskStatusCountCondition') { + Students with + Task Status Count + + {{ editor.operatorLabel(condition.operator) }} + + + {{ condition.task_status_count }} + + + {{ editor.targetGradeName(condition.task_target_grade) }} + + tasks in + + {{ editor.taskStatusesLabel(condition.task_statuses) }} + + } + @case ('LoginStatusCondition') { + Students with a + Last Sign In + + {{ editor.operatorLabel(condition.operator) }} + + + {{ editor.dateLabel(condition.last_sign_in_at) }} + + } + @case ('SpecConCondition') { + Students with + Special Consideration Days + + {{ editor.operatorLabel(condition.operator) }} + + + {{ condition.spec_con_days }} + + } + @case ('TutorialEnrolmentCondition') { + Students + + {{ editor.enrolmentPredicate(condition.operator) }} + + + {{ editor.tutorialLabel(condition.tutorial_id) }} + + } + @case ('TutorialStreamEnrolmentCondition') { + Students + + {{ editor.enrolmentPredicate(condition.operator) }} + + + {{ editor.tutorialStreamLabel(condition.tutorial_stream_id) }} + + } + @case ('CampusCondition') { + Students + + {{ editor.enrolmentPredicate(condition.operator) }} + + + {{ editor.campusLabel(condition.campus_id) }} + + } + @default { + {{ editor.operatorLabel(condition.operator) }} + {{ editor.labelFor(condition) }} + } + } +
    +
    +
    + + +
    +
    + } +
    + } +
    + + @if (editor.conditionFormOpen[rule.id] && !editor.editingConditionId[rule.id]) { +
    + + Condition + + @for (type of editor.conditionTypes; track type) { + + {{ editor.conditionTypeLabel(type) }} + + } + + + + @if (editor.conditionFor(rule).type === 'TaskDefinitionStatusCondition') { + + Task + + @for (taskDefinition of editor.taskDefinitions; track taskDefinition.id) { + + {{ taskDefinition.abbreviation }} {{ taskDefinition.name }} + + } + + + } + + + Operator + + @for (operator of editor.operatorsFor(editor.conditionFor(rule).type); track operator) { + + {{ editor.operatorLabel(operator) }} + + } + + + + @if (editor.conditionFor(rule).type === 'TaskStatusCountCondition') { + + Count + + + + + Task grade + + @for (grade of editor.targetGrades; track grade.value) { + + {{ grade.label }} + + } + + + } + + @switch (editor.conditionFor(rule).type) { + @case ('TargetGradeCondition') { + + Target grade + + @for (grade of editor.targetGrades; track grade.value) { + + {{ grade.label }} + + } + + + } + + @case ('TaskDefinitionStatusCondition') { + + Statuses + + @for (status of editor.taskStatuses; track status) { + + {{ editor.taskStatusLabel(status) }} + + } + + + } + + @case ('TaskStatusCountCondition') { + + Statuses + + @for (status of editor.taskStatuses; track status) { + + {{ editor.taskStatusLabel(status) }} + + } + + + } + + @case ('LoginStatusCondition') { + + Last sign in + + + } + @case ('SpecConCondition') { + + Days + + + } + + @case ('TutorialEnrolmentCondition') { + + Tutorial + + @for (tutorial of editor.tutorials; track tutorial.id) { + + {{ tutorial.abbreviation }} {{ tutorial.description }} + + } + + + } + + @case ('TutorialStreamEnrolmentCondition') { + + Tutorial stream + + @for (stream of editor.tutorialStreams; track stream.id) { + + {{ stream.abbreviation }} {{ stream.name }} + + } + + + } + + @case ('CampusCondition') { + + Campus + + @for (campus of editor.campuses; track campus.id) { + + {{ campus.abbreviation }} {{ campus.name }} + + } + + + } + } + + + + +
    + } @else { +
    + +
    + } +
    diff --git a/src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.ts new file mode 100644 index 0000000000..4d9d8003a7 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.ts @@ -0,0 +1,13 @@ +import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; +import {Component, Input} from '@angular/core'; +import type {UnitCommunicationsEditorComponent} from '../unit-communications-editor.component'; + +@Component({ + selector: 'f-communication-conditions', + standalone: false, + templateUrl: './communication-conditions.component.html', +}) +export class CommunicationConditionsComponent { + @Input({required: true}) editor: UnitCommunicationsEditorComponent; + @Input({required: true}) rule: CommunicationRule; +} diff --git a/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.html b/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.html new file mode 100644 index 0000000000..fe605bc0b5 --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.html @@ -0,0 +1,345 @@ +
    +
    +

    Current unit week: {{ currentUnitWeek <= 0 ? 'Not started' : currentUnitWeek }}

    +
    +
    + +
    + + @if (loading) { + + } + + + + + + + +
    +
    + + +
    +
    +
    + + +
    +
    + + + +
    + + @if (treeControl.isExpanded(node)) { +
    + + + +
    + } +
    +
    +
    +
    + + + @if (selectedSet(); as set) { +
    +
    +
    + @if (editingSetNameId === set.id) { + + Set name + + + + + } @else { +

    {{ set.name }}

    + + } +
    +
    + + + + +
    +
    + + +
    + + + @if (selectedRule(); as rule) { +
    +
    + @if (editingRuleNameId === rule.id) { + + Rule name + + + + + } @else { +
    +
    {{ rule.name }}
    + +
    + } +
    + +
    + +
    +
    + + + + + + + + + + + +
    + + Send action log to convenors after execution + + +
    + +
    +
    +
    + + +
    +
    + +
    + + @if (setPreviewLoading || previewLoading[rule.id]) { + + } @else if (previewLoaded[rule.id]) { +
    + Selected for {{ rule.name }} ({{ studentsFor(rule).length }}) +
    + + @if (studentsFor(rule).length === 0) { +
    No students currently match this rule.
    + } @else { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Preferred Name + {{ student.preferred_name || '-' }} + First Name + {{ student.first_name || '-' }} + Last Name + {{ student.last_name || '-' }} + Full Name + {{ student.full_name || '-' }} + Username + {{ student.username || '-' }} + Student ID + {{ student.student_id || '-' }} + Campus + {{ student.campus || '-' }} + Target Grade + {{ + student.target_grade ? targetGradeName(student.target_grade) : '-' + }} + Spec Con Days + {{ student.spec_con_days ?? '-' }} + Last Sign In + {{ + student.last_sign_in_at ? dateLabel(student.last_sign_in_at) : '-' + }} +
    + } + } @else { +
    + Preview data will load when you select a communication set. +
    + } +
    +
    +
    + } @else { +
    + Select a communication rule to edit its conditions, actions, and preview. +
    + } +
    +
    + } @else { +
    + Create or select a communication set to begin. +
    + } +
    +
    +
    diff --git a/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.scss b/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.ts new file mode 100644 index 0000000000..427dd2dc9c --- /dev/null +++ b/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.ts @@ -0,0 +1,1365 @@ +import {Subscription} from 'rxjs'; +import { + Campus, + CampusService, + CommunicationAction, + CommunicationActionService, + CommunicationCondition, + CommunicationConditionService, + CommunicationRule, + CommunicationRulePreviewAllocation, + CommunicationRulePreviewResponse, + CommunicationRulePreviewStudent, + CommunicationRuleService, + CommunicationSet, + CommunicationSetPreviewResponse, + CommunicationSetSchedule, + CommunicationSetService, + ProjectService, + TaskDefinition, + Tutorial, + TutorialStream, + Unit, +} from 'src/app/api/models/doubtfire-model'; +import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {NestedTreeControl} from '@angular/cdk/tree'; +import {Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import {MatTreeNestedDataSource} from '@angular/material/tree'; +import { + CommunicationScheduleModalComponent, + CommunicationScheduleModalData, +} from './communication-schedule-modal/communication-schedule-modal.component'; + +interface CommunicationTreeNode { + type: 'set' | 'rule'; + id: number; + label: string; + set?: CommunicationSet; + rule?: CommunicationRule; + children?: CommunicationTreeNode[]; +} + +@Component({ + selector: 'f-unit-communications-editor', + standalone: false, + templateUrl: './unit-communications-editor.component.html', + styleUrl: './unit-communications-editor.component.scss', +}) +export class UnitCommunicationsEditorComponent implements OnInit, OnChanges, OnDestroy { + @Input() unit: Unit; + + readonly editorContext = this; + sets: CommunicationSet[] = []; + selectedSetId?: number; + selectedRuleId?: number; + rules: CommunicationRule[] = []; + campuses: Campus[] = []; + taskDefinitions: readonly TaskDefinition[] = []; + tutorials: readonly Tutorial[] = []; + tutorialStreams: readonly TutorialStream[] = []; + loading = false; + setPreviewLoading = false; + readonly previewStudentColumns = [ + 'preferred_name', + 'first_name', + 'last_name', + 'full_name', + 'username', + 'student_id', + 'campus', + 'target_grade', + 'spec_con_days', + 'last_sign_in_at', + ]; + + readonly logicalOperators = ['and', 'or']; + readonly logicalOperatorOptions = [ + {value: 'and', label: 'All the following conditions'}, + {value: 'or', label: 'Any of the following conditions'}, + ] as const; + readonly conditionTypes = [ + 'TargetGradeCondition', + 'TaskDefinitionStatusCondition', + 'TaskStatusCountCondition', + 'LoginStatusCondition', + 'SpecConCondition', + 'TutorialEnrolmentCondition', + 'TutorialStreamEnrolmentCondition', + 'CampusCondition', + ]; + readonly conditionTypeLabels: Record = { + TargetGradeCondition: 'Target Grade', + TaskDefinitionStatusCondition: 'Task Status', + TaskStatusCountCondition: 'Task Status Count', + LoginStatusCondition: 'Login Status', + SpecConCondition: 'Special Consideration Days', + TutorialEnrolmentCondition: 'Tutorial Enrolment', + TutorialStreamEnrolmentCondition: 'Tutorial Stream Enrolment', + CampusCondition: 'Campus', + }; + readonly actionTypes = [ + 'EmailStudentAction', + 'EmailStaffAction', + 'ChangeTargetGradeAction', + 'TaskCommentAction', + ]; + readonly actionTypeLabels: Record = { + EmailStudentAction: 'Send email to student', + EmailStaffAction: 'Send email to staff', + ChangeTargetGradeAction: 'Change Target Grade', + TaskCommentAction: 'Task Comment', + }; + readonly gradeOperators = [ + 'greater_than', + 'greater_than_or_equal_to', + 'less_than', + 'less_than_or_equal_to', + 'equal_to', + 'not_equal_to', + ]; + readonly equalityOperators = ['equal_to', 'not_equal_to']; + readonly dateOperators = ['before', 'after']; + readonly enrolmentOperators = ['enrolled_in', 'not_enrolled_in']; + readonly operatorLabels: Record = { + greater_than: 'Greater Than', + greater_than_or_equal_to: 'Greater Than Or Equal To', + less_than: 'Less Than', + less_than_or_equal_to: 'Less Than Or Equal To', + equal_to: 'Equal To', + not_equal_to: 'Not Equal To', + before: 'Before', + after: 'After', + enrolled_in: 'Enrolled In', + not_enrolled_in: 'Not Enrolled In', + }; + readonly targetGrades = [ + {value: 0, label: 'P'}, + {value: 1, label: 'C'}, + {value: 2, label: 'D'}, + {value: 3, label: 'HD'}, + ]; + readonly targetGradeLabels: Record = { + 0: 'P', + 1: 'C', + 2: 'D', + 3: 'HD', + }; + readonly targetGradeNames: Record = { + 0: 'Pass', + 1: 'Credit', + 2: 'Distinction', + 3: 'High Distinction', + }; + readonly emailVariables = [ + {token: '{{student.first_name}}', label: 'Student First Name'}, + {token: '{{student.last_name}}', label: 'Student Last Name'}, + {token: '{{student.preferred_name}}', label: 'Student Preferred Name'}, + {token: '{{student.full_name}}', label: 'Student Full Name'}, + {token: '{{student.username}}', label: 'Student Username'}, + {token: '{{student.student_id}}', label: 'Student ID'}, + {token: '{{affected_students_count}}', label: 'Affected Students Count'}, + {token: '{{unit.code}}', label: 'Unit Code'}, + {token: '{{unit.name}}', label: 'Unit Name'}, + {token: '{{rule.name}}', label: 'Rule Name'}, + {token: '{{target_grade}}', label: 'Target Grade'}, + // {token: '{{conditions_summary}}', label: 'Conditions Summary'}, + // {token: '{{actions_summary}}', label: 'Actions Summary'}, + ]; + readonly taskStatuses = [ + 'not_started', + 'complete', + 'need_help', + 'working_on_it', + 'fix_and_resubmit', + 'feedback_exceeded', + 'redo', + 'discuss', + 'ready_for_feedback', + 'demonstrate', + 'fail', + 'time_exceeded', + 'assess_in_portfolio', + 'attention_required', + ]; + + newConditions: Record> = {}; + conditionFormOpen: Record = {}; + editingConditionId: Record = {}; + newActions: Record> = {}; + actionFormOpen: Record = {}; + editingActionId: Record = {}; + previewTabIndex: Record = {}; + previewLoading: Record = {}; + previewLoaded: Record = {}; + previewStudents: Record = {}; + previewAllocations: Record = {}; + editingSetNameId?: number; + editingRuleNameId?: number; + setNameDraft = ''; + ruleNameDraft = ''; + readonly treeControl: NestedTreeControl = new NestedTreeControl( + (node) => node.children, + ); + readonly treeDataSource: MatTreeNestedDataSource = + new MatTreeNestedDataSource(); + private expandedSetIds: Set = new Set(); + + private subscriptions: Subscription[] = []; + + get currentUnitWeek(): number | null { + return this.unit?.currentUnitWeek ?? null; + } + + constructor( + private ruleService: CommunicationRuleService, + private conditionService: CommunicationConditionService, + private actionService: CommunicationActionService, + private setService: CommunicationSetService, + private projectService: ProjectService, + private dialog: MatDialog, + private campusService: CampusService, + private alerts: AlertService, + private sidekiqProgressModalService: SidekiqProgressModalService, + private confirmationModalService: ConfirmationModalService, + ) {} + + ngOnInit(): void { + this.campusService.query().subscribe((campuses) => { + this.campuses = campuses; + }); + this.refreshUnitLookups(); + this.loadSets(); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes.unit && this.unit) { + this.refreshUnitLookups(); + this.loadSets(); + } + } + + addSet(): void { + if (!this.unit) return; + + const newSet = { + name: this.defaultSetName(), + active: true, + } as Pick & Partial>; + + this.setService.createForUnit(this.unit.id, newSet).subscribe({ + next: (set) => { + this.sets.push(set); + this.expandedSetIds.add(set.id); + this.selectedSetId = set.id; + this.selectSet(); + }, + error: (error) => this.showError(error), + }); + } + + deleteSet(set: CommunicationSet): void { + this.setService.deleteForUnit(this.unit.id, set.id).subscribe({ + next: () => { + this.sets = this.sets.filter((item) => item.id !== set.id); + this.expandedSetIds.delete(set.id); + if (this.selectedSetId === set.id) { + this.selectedSetId = undefined; + } + this.selectSet(); + }, + error: (error) => this.showError(error), + }); + } + + beginEditSetName(set: CommunicationSet): void { + this.editingSetNameId = set.id; + this.setNameDraft = set.name; + } + + cancelEditSetName(): void { + this.editingSetNameId = undefined; + this.setNameDraft = ''; + } + + saveSetName(set: CommunicationSet): void { + const name = this.setNameDraft.trim(); + if (!name) return; + + this.setService.updateForUnit(this.unit.id, set.id, {name}).subscribe({ + next: (updated) => { + set.name = updated.name; + const matchingSet = this.sets.find((item) => item.id === set.id); + if (matchingSet) { + matchingSet.name = updated.name; + } + this.cancelEditSetName(); + this.rebuildTree(); + }, + error: (error) => this.showError(error), + }); + } + + confirmExecuteSet(set: CommunicationSet): void { + this.confirmationModalService.show( + 'Execute Set?', + 'This will execute every rule in this set, in sequence. Once a student is matched by an earlier rule, they are removed from consideration for the remaining rules, so each student can only be picked up once during the set run.', + () => this.executeSet(set), + undefined, + 'Execute Set', + ); + } + + executeSet(set: CommunicationSet): void { + this.setService.executeForUnit(this.unit.id, set.id).subscribe({ + next: (job) => this.showExecutionProgress(job, `Executing ${set.name}`), + error: (error) => this.showError(error), + }); + } + + addSchedule(set: CommunicationSet): void { + this.openScheduleModal(set); + } + + editSchedule(set: CommunicationSet, schedule: CommunicationSetSchedule): void { + this.openScheduleModal(set, schedule); + } + + deleteSchedule(set: CommunicationSet, schedule: CommunicationSetSchedule): void { + const updatedSchedules = (set.schedules || []).filter( + (item) => (item.id || item.client_key) !== (schedule.id || schedule.client_key), + ); + this.persistSchedules(set, updatedSchedules, 'Schedule removed'); + } + + scheduleTrackId(schedule: CommunicationSetSchedule): string | number { + return ( + schedule.id || + schedule.client_key || + `${schedule.name || 'schedule'}-${schedule.anchor_week}-${schedule.anchor_day}` + ); + } + + scheduleSummary(schedule: CommunicationSetSchedule): string { + const cadence = this.scheduleCadence(schedule); + const ending = this.scheduleEnding(schedule); + return [cadence, ending].filter(Boolean).join(' | '); + } + + scheduleAnchorSummary(schedule: CommunicationSetSchedule): string { + return `Week ${schedule.anchor_week || 1} on ${schedule.anchor_day || 'Monday'}`; + } + + scheduleTimeSummary(schedule: CommunicationSetSchedule): string { + return `${this.formatTime(schedule.hour, schedule.minute)} ${schedule.timezone || 'UTC'}`; + } + + scheduleNextRunSummary(schedule: CommunicationSetSchedule): string { + return schedule.next_run_at ? this.dateLabel(schedule.next_run_at) : 'Not scheduled'; + } + + scheduleLastRunSummary(schedule: CommunicationSetSchedule): string { + return schedule.last_run_at ? this.dateLabel(schedule.last_run_at) : 'Not yet run'; + } + + iceCubePreview(schedule: CommunicationSetSchedule): string { + return JSON.stringify(schedule.ice_cube_schedule || {}, null, 2); + } + + selectSet(): void { + const set = this.selectedSet(); + if (set) { + this.activateSet(set); + } else { + this.rules = []; + this.selectedRuleId = undefined; + this.rebuildTree(); + } + } + + ngOnDestroy(): void { + this.subscriptions.forEach((subscription) => subscription.unsubscribe()); + } + + addRule(): void { + if (!this.unit) return; + const set = this.selectedSet(); + if (!set) return; + + const newRule = { + name: this.defaultRuleName(), + operator: 'and', + } as Pick; + + this.ruleService.createForSet(this.unit.id, set.id, newRule).subscribe({ + next: (rule) => { + this.rules.push(rule); + set.rules = this.rules; + this.selectedRuleId = rule.id; + this.expandedSetIds.add(set.id); + this.loadPreviewForSet(set); + }, + error: (error) => this.showError(error), + }); + } + + deleteRule(rule: CommunicationRule): void { + this.ruleService.deleteForUnit(this.unit.id, rule.id).subscribe({ + next: () => { + this.rules = this.rules.filter((item) => item.id !== rule.id); + const set = this.selectedSet(); + if (set) { + set.rules = this.rules; + this.selectedRuleId = this.rules[0]?.id; + this.loadPreviewForSet(set); + } + }, + error: (error) => this.showError(error), + }); + } + + updateRuleOperator(rule: CommunicationRule): void { + this.ruleService.updateForUnit(this.unit.id, rule.id, {operator: rule.operator}).subscribe({ + next: (updated) => { + rule.operator = updated.operator; + this.refreshPreview(rule); + }, + error: (error) => this.showError(error), + }); + } + + updateRule(rule: CommunicationRule): void { + this.ruleService + .updateForUnit(this.unit.id, rule.id, { + name: rule.name, + operator: rule.operator, + send_log_to_convenors: rule.send_log_to_convenors, + }) + .subscribe({ + next: (updated) => { + rule.name = updated.name; + rule.operator = updated.operator; + rule.send_log_to_convenors = updated.send_log_to_convenors; + const set = this.selectedSet(); + if (set) { + set.rules = this.rules; + } + this.refreshPreview(rule); + }, + error: (error) => this.showError(error), + }); + } + + beginEditRuleName(rule: CommunicationRule): void { + this.editingRuleNameId = rule.id; + this.ruleNameDraft = rule.name; + } + + cancelEditRuleName(): void { + this.editingRuleNameId = undefined; + this.ruleNameDraft = ''; + } + + saveRuleName(rule: CommunicationRule): void { + const name = this.ruleNameDraft.trim(); + if (!name) return; + + this.ruleService + .updateForUnit(this.unit.id, rule.id, { + name, + operator: rule.operator, + send_log_to_convenors: rule.send_log_to_convenors, + }) + .subscribe({ + next: (updated) => { + rule.name = updated.name; + const set = this.selectedSet(); + if (set) { + set.rules = this.rules; + } + this.cancelEditRuleName(); + this.rebuildTree(); + }, + error: (error) => this.showError(error), + }); + } + + confirmExecuteRule(rule: CommunicationRule): void { + this.confirmationModalService.show( + 'Execute Rule?', + 'This will execute only this rule. However, any earlier rules in the set are still taken into account first, so students who would already have been matched earlier are excluded before this rule is applied.', + () => this.executeRule(rule), + undefined, + 'Execute Rule', + ); + } + + executeRule(rule: CommunicationRule): void { + this.ruleService.executeForUnit(this.unit.id, rule.id).subscribe({ + next: (job) => this.showExecutionProgress(job, `Executing ${rule.name}`), + error: (error) => this.showError(error), + }); + } + + previewRule(rule: CommunicationRule, activateStudentsTab = true): void { + if (activateStudentsTab) { + this.previewTabIndex[rule.id] = 2; + } + } + + addCondition(rule: CommunicationRule): void { + const condition = this.newConditions[rule.id] || this.blankCondition(); + this.conditionService.create(this.unit.id, rule.id, condition).subscribe({ + next: (created) => { + rule.conditions ||= []; + rule.conditions.push(created); + this.newConditions[rule.id] = this.blankCondition(); + this.conditionFormOpen[rule.id] = false; + this.editingConditionId[rule.id] = undefined; + this.refreshPreview(rule); + }, + error: (error) => this.showError(error), + }); + } + + updateCondition(rule: CommunicationRule): void { + const conditionId = this.editingConditionId[rule.id]; + if (!conditionId) return; + + const condition = this.newConditions[rule.id] || this.blankCondition(); + this.conditionService.update(this.unit.id, rule.id, conditionId, condition).subscribe({ + next: (updated) => { + rule.conditions = rule.conditions.map((item) => (item.id === updated.id ? updated : item)); + this.newConditions[rule.id] = this.blankCondition(); + this.conditionFormOpen[rule.id] = false; + this.editingConditionId[rule.id] = undefined; + this.refreshPreview(rule); + }, + error: (error) => this.showError(error), + }); + } + + showConditionForm(rule: CommunicationRule): void { + this.newConditions[rule.id] = this.blankCondition(); + this.conditionFormOpen[rule.id] = true; + this.editingConditionId[rule.id] = undefined; + } + + cancelCondition(rule: CommunicationRule): void { + this.newConditions[rule.id] = this.blankCondition(); + this.conditionFormOpen[rule.id] = false; + this.editingConditionId[rule.id] = undefined; + } + + editCondition(rule: CommunicationRule, condition: CommunicationCondition): void { + this.newConditions[rule.id] = { + ...condition, + task_statuses: condition.task_statuses ? [...condition.task_statuses] : [], + }; + this.conditionFormOpen[rule.id] = true; + this.editingConditionId[rule.id] = condition.id; + } + + deleteCondition(rule: CommunicationRule, condition: CommunicationCondition): void { + this.conditionService.delete(this.unit.id, rule.id, condition.id).subscribe({ + next: () => { + rule.conditions = rule.conditions.filter((item) => item.id !== condition.id); + this.refreshPreview(rule); + }, + error: (error) => this.showError(error), + }); + } + + addAction(rule: CommunicationRule): void { + const action = this.newActions[rule.id] || this.blankAction(); + this.actionService.create(this.unit.id, rule.id, action).subscribe({ + next: (created) => { + rule.actions ||= []; + rule.actions.push(created); + this.newActions[rule.id] = this.blankAction(); + this.actionFormOpen[rule.id] = false; + this.editingActionId[rule.id] = undefined; + }, + error: (error) => this.showError(error), + }); + } + + updateAction(rule: CommunicationRule): void { + const actionId = this.editingActionId[rule.id]; + if (!actionId) return; + + const action = this.newActions[rule.id] || this.blankAction(); + this.actionService.update(this.unit.id, rule.id, actionId, action).subscribe({ + next: (updated) => { + rule.actions = rule.actions.map((item) => (item.id === updated.id ? updated : item)); + this.newActions[rule.id] = this.blankAction(); + this.actionFormOpen[rule.id] = false; + this.editingActionId[rule.id] = undefined; + }, + error: (error) => this.showError(error), + }); + } + + showActionForm(rule: CommunicationRule, _mode: 'standard' | 'post_execution' = 'standard'): void { + this.newActions[rule.id] = this.blankAction(); + this.actionFormOpen[rule.id] = true; + this.editingActionId[rule.id] = undefined; + } + + cancelAction(rule: CommunicationRule): void { + this.newActions[rule.id] = this.blankAction(); + this.actionFormOpen[rule.id] = false; + this.editingActionId[rule.id] = undefined; + } + + editAction(rule: CommunicationRule, action: CommunicationAction): void { + this.newActions[rule.id] = {...action}; + this.actionFormOpen[rule.id] = true; + this.editingActionId[rule.id] = action.id; + } + + deleteAction(rule: CommunicationRule, action: CommunicationAction): void { + this.actionService.delete(this.unit.id, rule.id, action.id).subscribe({ + next: () => { + rule.actions = rule.actions.filter((item) => item.id !== action.id); + }, + error: (error) => this.showError(error), + }); + } + + conditionFor(rule: CommunicationRule): Partial { + this.newConditions[rule.id] ||= this.blankCondition(); + return this.newConditions[rule.id]; + } + + actionFor(rule: CommunicationRule): Partial { + this.newActions[rule.id] ||= this.blankAction(); + return this.newActions[rule.id]; + } + + selectRule(rule: CommunicationRule): void { + this.selectedRuleId = rule.id; + } + + hasTreeChild = (_: number, node: CommunicationTreeNode): boolean => node.type === 'set'; + + isSelectedSetNode(node: CommunicationTreeNode): boolean { + return node.type === 'set' && node.id === this.selectedSetId; + } + + isSelectedRuleNode(node: CommunicationTreeNode): boolean { + return node.type === 'rule' && node.id === this.selectedRuleId; + } + + toggleSetNode(node: CommunicationTreeNode, event?: Event): void { + event?.stopPropagation(); + if (!node.set) return; + + if (this.treeControl.isExpanded(node)) { + this.treeControl.collapse(node); + this.expandedSetIds.delete(node.set.id); + } else { + this.treeControl.expand(node); + this.expandedSetIds.add(node.set.id); + } + } + + selectSetNode(set: CommunicationSet): void { + this.selectedSetId = set.id; + this.expandedSetIds.add(set.id); + this.activateSet(set); + } + + selectRuleNode(set: CommunicationSet, rule: CommunicationRule): void { + const setChanged = this.selectedSetId !== set.id; + this.selectedSetId = set.id; + this.expandedSetIds.add(set.id); + + if (setChanged) { + this.activateSet(set, rule.id); + return; + } + + this.selectedRuleId = rule.id; + } + + selectedRule(): CommunicationRule | undefined { + return this.rules.find((rule) => rule.id === this.selectedRuleId); + } + + onRuleTabChange(rule: CommunicationRule, index: number): void { + this.previewTabIndex[rule.id] = index; + } + + studentsFor(rule: CommunicationRule): CommunicationRulePreviewStudent[] { + return this.previewStudents[rule.id] || []; + } + + previewAllocationsFor(rule: CommunicationRule): CommunicationRulePreviewAllocation[] { + return this.previewAllocations[rule.id] || []; + } + + isTargetPreviewAllocation( + rule: CommunicationRule, + allocation: CommunicationRulePreviewAllocation, + ): boolean { + return allocation.rule_id === rule.id; + } + + studentsTabLabel(rule: CommunicationRule): string { + const matchedCount = this.previewLoaded[rule.id] ? this.studentsFor(rule).length : 0; + const totalStudents = this.availableStudentsForRule(rule); + + return `Students (${matchedCount}/${totalStudents})`; + } + + operatorsFor(conditionType: string): string[] { + switch (conditionType) { + case 'TargetGradeCondition': + case 'TaskStatusCountCondition': + case 'SpecConCondition': + return this.gradeOperators; + case 'TaskDefinitionStatusCondition': + return this.equalityOperators; + case 'LoginStatusCondition': + return this.dateOperators; + default: + return this.enrolmentOperators; + } + } + + labelFor(record: CommunicationCondition | CommunicationAction): string { + const hiddenKeys = this.hiddenKeysForRecord(record); + + return Object.entries(record) + .filter( + ([key, value]) => + !hiddenKeys.includes(key) && value !== undefined && value !== null && value !== '', + ) + .map(([key, value]) => `${this.prettyKey(key)}: ${this.prettyValue(key, value)}`) + .join(', '); + } + + conditionTypeLabel(type: string): string { + return this.conditionTypeLabels[type] || type; + } + + operatorLabel(operator: string): string { + return this.operatorLabels[operator] || operator; + } + + actionTypeLabel(type: string): string { + return this.actionTypeLabels[type] || type; + } + + actionSummary(action: CommunicationAction): string { + switch (action.type) { + case 'ChangeTargetGradeAction': + return `Change student's target grade to ${this.targetGradeName(action.target_grade)}`; + case 'EmailStudentAction': + return 'Send email to student'; + case 'EmailStaffAction': + return `Send email to ${this.staffAudienceLabel(action)}`; + case 'TaskCommentAction': + return `Add comment to ${this.taskDefinitionLabel(action.task_definition_id)}`; + default: + return this.actionTypeLabel(action.type); + } + } + + targetGradeName(targetGrade: number | undefined): string { + if (targetGrade === undefined || targetGrade === null) return ''; + + return this.targetGradeNames[targetGrade] || `${targetGrade}`; + } + + taskDefinitionLabel(taskDefinitionId: number | undefined): string { + if (taskDefinitionId === undefined || taskDefinitionId === null) { + return 'Task'; + } + + const taskDefinition = this.taskDefinitions.find((task) => task.id === taskDefinitionId); + + if (!taskDefinition) { + return `Task ${taskDefinitionId}`; + } + + return `Task ${taskDefinition.abbreviation} ${taskDefinition.name}`; + } + + taskStatusLabel(taskStatus: string): string { + return this.titleize(taskStatus); + } + + taskStatusesLabel(taskStatuses: string[] = []): string { + return taskStatuses.map((status) => this.taskStatusLabel(status)).join(', '); + } + + staffAudienceLabel(action: Partial): string { + const audiences: string[] = []; + if (action.email_tutors) audiences.push('tutors'); + if (action.email_convenors) audiences.push('convenors'); + return audiences.join(' and ') || 'staff'; + } + + insertActionVariable(rule: CommunicationRule, field: 'subject' | 'body', token: string): void { + const action = this.actionFor(rule); + const currentValue = action[field] ?? ''; + const separator = + currentValue && !currentValue.endsWith(' ') && !currentValue.endsWith('\n') ? ' ' : ''; + action[field] = `${currentValue}${separator}${token}`; + } + + renderTemplatePreview(value: string | undefined, rule: CommunicationRule): string { + if (!value) return ''; + + const escaped = this.escapeHtml(value); + const rendered = escaped.replace(/\{\{[\w.]+\}\}/g, (token) => { + const replacement = this.resolveTemplateVariable(token, rule) || token; + return `${this.escapeHtml(replacement)}`; + }); + + return rendered.replace(/\n/g, '
    '); + } + + refreshPreview(_rule: CommunicationRule): void { + const set = this.selectedSet(); + if (set) { + this.loadPreviewForSet(set); + } + } + + taskStatusPredicate(operator: string): string { + return operator === 'not_equal_to' ? 'Not In' : 'In'; + } + + tutorialLabel(tutorialId: number): string { + const tutorial = this.tutorials.find((item) => item.id === tutorialId); + return tutorial ? `${tutorial.abbreviation} ${tutorial.description}` : `Tutorial ${tutorialId}`; + } + + tutorialStreamLabel(tutorialStreamId: number): string { + const tutorialStream = this.tutorialStreams.find((item) => item.id === tutorialStreamId); + return tutorialStream + ? `${tutorialStream.abbreviation} ${tutorialStream.name}` + : `Tutorial Stream ${tutorialStreamId}`; + } + + campusLabel(campusId: number): string { + const campus = this.campuses.find((item) => item.id === campusId); + return campus ? campus.name : `Campus ${campusId}`; + } + + enrolmentPredicate(operator: string): string { + return operator === 'not_enrolled_in' ? 'Not Enrolled In' : 'Enrolled In'; + } + + dateLabel(value: string): string { + return value ? new Date(value).toLocaleString() : ''; + } + + onConditionTypeChange(rule: CommunicationRule): void { + const current = this.conditionFor(rule); + this.newConditions[rule.id] = { + type: current.type, + operator: this.operatorsFor(current.type)[0], + }; + + if (current.type === 'TaskDefinitionStatusCondition') { + this.newConditions[rule.id].task_statuses = []; + } + + if (current.type === 'TaskStatusCountCondition') { + this.newConditions[rule.id].task_statuses = []; + this.newConditions[rule.id].task_status_count = 2; + this.newConditions[rule.id].task_target_grade = 1; + } + + if (current.type === 'SpecConCondition') { + this.newConditions[rule.id].spec_con_days = 0; + } + } + + onActionTypeChange(rule: CommunicationRule): void { + const current = this.actionFor(rule); + this.newActions[rule.id] = { + type: current.type || 'EmailStudentAction', + email_tutors: false, + email_convenors: false, + }; + + if (current.type === 'TaskCommentAction') { + this.newActions[rule.id].body = ''; + this.newActions[rule.id].task_definition_id = this.taskDefinitions[0]?.id; + } + } + + private loadSets(): void { + if (!this.unit) return; + + this.loading = true; + this.setService.getForUnit(this.unit.id).subscribe({ + next: (sets) => { + this.sets = sets; + if (this.selectedSetId) { + this.expandedSetIds.add(this.selectedSetId); + } + this.rebuildTree(); + this.selectSet(); + this.loading = false; + }, + error: (error) => { + this.loading = false; + this.showError(error); + }, + }); + } + + private refreshUnitLookups(): void { + this.subscriptions.forEach((subscription) => subscription.unsubscribe()); + this.subscriptions = []; + + if (!this.unit) return; + + this.taskDefinitions = this.unit.taskDefinitionCache.currentValues; + this.tutorials = this.unit.tutorials; + this.tutorialStreams = this.unit.tutorialStreams; + this.subscriptions.push( + this.unit.taskDefinitionCache.values.subscribe((taskDefinitions) => { + this.taskDefinitions = taskDefinitions; + }), + ); + this.subscriptions.push( + // TODO: use spinner until students are loaded + this.projectService.loadStudents(this.unit, false, true).subscribe({ + error: (error) => this.showError(error), + }), + ); + } + + private defaultRuleName(): string { + return `Rule ${this.rules.length + 1}`; + } + + private defaultSetName(): string { + return `Set ${this.sets.length + 1}`; + } + + private defaultScheduleName(set: CommunicationSet): string { + return `Schedule ${(set.schedules?.length || 0) + 1}`; + } + + private activateSet(set: CommunicationSet, selectedRuleId?: number): void { + this.rules = set.rules ?? []; + this.selectedRuleId = selectedRuleId ?? this.rules[0]?.id; + this.loadPreviewForSet(set); + } + + selectedSet(): CommunicationSet | undefined { + return this.sets.find((set) => set.id === this.selectedSetId); + } + + private blankCondition(): Partial { + return { + type: 'TargetGradeCondition', + operator: 'greater_than_or_equal_to', + }; + } + + private blankAction(): Partial { + return { + type: 'EmailStudentAction', + email_tutors: false, + email_convenors: false, + }; + } + + private blankSchedule(set: CommunicationSet): CommunicationSetSchedule { + return new CommunicationSetSchedule({ + client_key: this.newScheduleClientKey(), + communication_set_id: set.id, + name: this.defaultScheduleName(set), + active: true, + anchor_week: 1, + anchor_day: 'Monday', + recurrence: 'none', + interval: 1, + timezone: 'UTC', + hour: 8, + minute: 0, + ice_cube_schedule: { + timezone: 'UTC', + recurrence: 'none', + rules: [{type: 'one_off'}], + }, + }); + } + + private loadPreviewForSet(set: CommunicationSet): void { + if (!this.unit) { + this.setPreviewLoading = false; + return; + } + + this.setPreviewLoading = true; + this.setService.getForUnitById(this.unit.id, set.id).subscribe({ + next: (setResponse) => { + this.applySetPreviewResponse(setResponse); + this.setPreviewLoading = false; + }, + error: (error) => { + this.setPreviewLoading = false; + this.showError(error); + }, + }); + } + + private applySetPreviewResponse(setResponse: CommunicationSetPreviewResponse): void { + const rules = (setResponse.rules || []).map((rule) => new CommunicationRule(rule)); + const existingSet = this.sets.find((set) => set.id === setResponse.id); + const schedules = + setResponse.schedules !== undefined + ? (setResponse.schedules || []).map((schedule) => new CommunicationSetSchedule(schedule)) + : existingSet?.schedules || []; + const updatedSet = new CommunicationSet({ + id: setResponse.id, + unit_id: setResponse.unit_id, + name: setResponse.name, + active: setResponse.active, + schedules, + rules, + }); + const setIndex = this.sets.findIndex((set) => set.id === updatedSet.id); + if (setIndex >= 0) { + this.sets[setIndex] = updatedSet; + } + + if (this.selectedSetId === updatedSet.id) { + this.rules = rules; + if (!this.rules.some((rule) => rule.id === this.selectedRuleId)) { + this.selectedRuleId = this.rules[0]?.id; + } + } + + this.rules.forEach((rule) => { + this.previewLoading[rule.id] = true; + }); + + setResponse.previews.forEach((preview) => { + this.previewAllocations[preview.target_rule_id] = preview.allocations || []; + this.previewStudents[preview.target_rule_id] = this.studentsForPreviewRule( + preview.target_rule_id, + preview, + ); + this.previewLoaded[preview.target_rule_id] = true; + this.previewLoading[preview.target_rule_id] = false; + }); + + this.rules.forEach((rule) => { + this.previewLoading[rule.id] = false; + }); + + this.rebuildTree(); + } + + private studentsForPreviewRule( + ruleId: number, + preview: CommunicationRulePreviewResponse, + ): CommunicationRulePreviewStudent[] { + return preview.allocations.find((allocation) => allocation.rule_id === ruleId)?.students || []; + } + + private availableStudentsForRule(rule: CommunicationRule): number { + const totalStudents = this.unit?.students?.length ?? 0; + if (!this.previewLoaded[rule.id]) return totalStudents; + + const claimedByPreviousRules = this.previewAllocationsFor(rule) + .filter((allocation) => allocation.rule_id !== rule.id) + .reduce((sum, allocation) => sum + allocation.students.length, 0); + + return Math.max(0, totalStudents - claimedByPreviousRules); + } + + private sampleStudentForRule( + rule: CommunicationRule, + ): CommunicationRulePreviewStudent | undefined { + return this.studentsFor(rule)[0]; + } + + private openScheduleModal(set: CommunicationSet, schedule?: CommunicationSetSchedule): void { + const dialogRef = this.dialog.open(CommunicationScheduleModalComponent, { + width: '960px', + maxWidth: '96vw', + data: { + schedule: schedule + ? new CommunicationSetSchedule({ + ...schedule, + }) + : this.blankSchedule(set), + unit: this.unit, + } satisfies CommunicationScheduleModalData, + }); + + dialogRef.afterClosed().subscribe((result) => { + if (!result) return; + + const hydrated = new CommunicationSetSchedule({ + ...result, + client_key: schedule?.client_key || result.client_key || this.newScheduleClientKey(), + communication_set_id: set.id, + }); + + const schedules = [...(set.schedules || [])]; + const existingIndex = schedules.findIndex( + (item) => (item.id || item.client_key) === (schedule?.id || schedule?.client_key), + ); + + if (existingIndex >= 0) { + schedules[existingIndex] = hydrated; + } else { + schedules.push(hydrated); + } + + this.persistSchedules(set, schedules, 'Schedule saved'); + }); + } + + private persistSchedules( + set: CommunicationSet, + schedules: CommunicationSetSchedule[], + successMessage: string, + ): void { + this.setService + .updateForUnit(this.unit.id, set.id, { + name: set.name, + active: set.active, + schedules: schedules.map((schedule) => ({ + id: schedule.id, + name: schedule.name, + active: schedule.active, + anchor_week: schedule.anchor_week, + anchor_day: schedule.anchor_day, + hour: schedule.hour, + minute: schedule.minute, + timezone: schedule.timezone, + recurrence: schedule.recurrence, + interval: schedule.interval, + repeat_count: schedule.repeat_count, + until_at: schedule.until_at, + })), + }) + .subscribe({ + next: (updatedSet) => { + set.schedules = updatedSet.schedules || []; + const setIndex = this.sets.findIndex((item) => item.id === set.id); + if (setIndex >= 0) { + this.sets[setIndex].schedules = updatedSet.schedules || []; + } + this.alerts.success(successMessage); + }, + error: (error) => this.showError(error), + }); + } + + private showError(error): void { + this.alerts.error(error?.message || error?.error || error || 'Communication update failed'); + } + + private showExecutionProgress(job: SidekiqJob, title: string): void { + if (!job?.id) { + this.alerts.error('Failed to start communication execution', 6000); + return; + } + + this.sidekiqProgressModalService.show(title, job.id).subscribe({ + error: (error) => this.showError(error), + }); + } + + private prettyKey(key: string): string { + const labels: Record = { + operator: 'Operator', + target_grade: 'Target Grade', + task_definition_id: 'Task', + task_statuses: 'Task Statuses', + task_status_count: 'Task Status Count', + task_target_grade: 'Task Target Grade', + last_sign_in_at: 'Last Sign In', + spec_con_days: 'Special Consideration Days', + tutorial_id: 'Tutorial', + tutorial_stream_id: 'Tutorial Stream', + campus_id: 'Campus', + subject: 'Subject', + body: 'Body', + email_tutors: 'Email Tutors', + email_convenors: 'Email Convenors', + }; + + return labels[key] || key; + } + + private prettyValue(key: string, value: unknown): string { + if (key === 'operator' && typeof value === 'string') { + return this.operatorLabel(value); + } + + if ((key === 'target_grade' || key === 'task_target_grade') && typeof value === 'number') { + return this.targetGradeLabels[value] || value.toString(); + } + + if (key === 'task_statuses' && Array.isArray(value)) { + return this.taskStatusesLabel(value); + } + + if (typeof value === 'boolean') { + return value ? 'Yes' : 'No'; + } + + return `${value}`; + } + + private escapeHtml(value: string): string { + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + + private resolveTemplateVariable(token: string, rule: CommunicationRule): string | undefined { + const student = this.sampleStudentForRule(rule); + + switch (token) { + case '{{student.first_name}}': + return student?.first_name; + case '{{student.last_name}}': + return student?.last_name; + case '{{student.preferred_name}}': + return student?.preferred_name || student?.first_name; + case '{{student.full_name}}': + return ( + student?.full_name || [student?.first_name, student?.last_name].filter(Boolean).join(' ') + ); + case '{{student.username}}': + return student?.username; + case '{{student.student_id}}': + return student?.student_id; + case '{{affected_students_count}}': + return this.studentsFor(rule).length.toString(); + case '{{unit.code}}': + return this.unit?.code; + case '{{unit.name}}': + return this.unit?.name; + case '{{rule.name}}': + return rule.name; + case '{{target_grade}}': + return student?.target_grade !== undefined && student?.target_grade !== null + ? this.targetGradeName(student.target_grade) + : undefined; + case '{{conditions_summary}}': + return this.conditionsSummary(rule); + case '{{actions_summary}}': + return this.actionsSummary(rule); + default: + return undefined; + } + } + + private hiddenKeysForRecord(record: CommunicationCondition | CommunicationAction): string[] { + const baseHiddenKeys = ['id', 'type', 'communication_rule_id', 'operator']; + + if (!('type' in record)) { + return baseHiddenKeys; + } + + switch (record.type) { + case 'ChangeTargetGradeAction': + return [...baseHiddenKeys, 'subject', 'body', 'email_tutors', 'email_convenors']; + case 'EmailStudentAction': + return [...baseHiddenKeys, 'target_grade', 'email_tutors', 'email_convenors']; + case 'EmailStaffAction': + return [...baseHiddenKeys, 'target_grade']; + default: + return baseHiddenKeys; + } + } + + conditionsSummary(rule: CommunicationRule): string { + return (rule.conditions || []) + .map((condition) => + `- ${this.conditionTypeLabel(condition.type)}: ${this.labelFor(condition)}`.trim(), + ) + .join('\n'); + } + + actionsSummary(rule: CommunicationRule): string { + return (rule.actions || []).map((action) => `- ${this.actionSummary(action)}`).join('\n'); + } + + private titleize(value: string): string { + return value + ?.split('_') + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); + } + + private scheduleCadence(schedule: CommunicationSetSchedule): string { + switch (schedule.recurrence) { + case 'daily': + return `Daily every ${schedule.interval || 1} day(s)`; + case 'weekly': + return `Weekly every ${schedule.interval || 1} week(s) from ${schedule.anchor_day || 'Monday'}`; + case 'monthly': + return `Monthly every ${schedule.interval || 1} month(s) from Week ${schedule.anchor_week || 1} ${schedule.anchor_day || 'Monday'}`; + default: + return 'One-off run'; + } + } + + private scheduleEnding(schedule: CommunicationSetSchedule): string { + if (schedule.repeat_count) { + return `Stops after ${schedule.repeat_count} run(s)`; + } + + if (schedule.until_at) { + return `Stops at ${this.dateLabel(schedule.until_at)}`; + } + + return 'No expiry'; + } + + private formatTime(hour = 0, minute = 0): string { + return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`; + } + + private newScheduleClientKey(): string { + return `schedule-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`; + } + + private rebuildTree(): void { + const treeData = this.sets.map((set) => ({ + type: 'set' as const, + id: set.id, + label: set.name, + set, + children: (set.rules ?? []).map((rule) => ({ + type: 'rule' as const, + id: rule.id, + label: rule.name, + set, + rule, + })), + })); + + this.treeDataSource.data = treeData; + treeData.forEach((node) => { + if (this.expandedSetIds.has(node.id) || node.id === this.selectedSetId) { + this.treeControl.expand(node); + } + }); + } +} diff --git a/src/app/units/states/edit/unit-admin-state.component.html b/src/app/units/states/edit/unit-admin-state.component.html index d165bf7c0c..6a06b1e487 100644 --- a/src/app/units/states/edit/unit-admin-state.component.html +++ b/src/app/units/states/edit/unit-admin-state.component.html @@ -1,6 +1,6 @@
    Groups
    } } + @case ('communication') { + @if (unit) { +
    +
    +

    Communication System

    +

    + Create communication sets and rules to target students and automate follow-up + actions. +

    +
    + +
    + } + } }
    diff --git a/src/app/units/states/edit/unit-admin-state.component.ts b/src/app/units/states/edit/unit-admin-state.component.ts index b22376951c..57972168df 100644 --- a/src/app/units/states/edit/unit-admin-state.component.ts +++ b/src/app/units/states/edit/unit-admin-state.component.ts @@ -12,7 +12,8 @@ type UnitAdminTabKey = | 'tutorials' | 'students' | 'tasks' - | 'groups'; + | 'groups' + | 'communication'; interface UnitAdminTab { label: string; @@ -35,6 +36,7 @@ export class UnitAdminStateComponent implements OnInit, OnDestroy { {label: 'Students', routeSegment: 'students'}, {label: 'Tasks', routeSegment: 'tasks'}, {label: 'Groups', routeSegment: 'groups'}, + {label: 'Communications', routeSegment: 'communication'}, ]; public unit: Unit | null = null; From 5381b13aecd7054354d2ebfbeeb68f5990054856 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 9 Jun 2026 12:17:17 +1000 Subject: [PATCH 1101/1531] chore(release): 11.0.0-22 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a572423099..57bb59d3ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-22](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-21...v11.0.0-22) (2026-06-09) + + +### Features + +* communications system ([#1239](https://github.com/b0ink/doubtfire-deploy/issues/1239)) ([b55bcfc](https://github.com/b0ink/doubtfire-deploy/commit/b55bcfc8f84f381beb7d62f41031db3ba6a38193)) + ## [11.0.0-21](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-20...v11.0.0-21) (2026-06-08) diff --git a/package-lock.json b/package-lock.json index 96eec16671..b9da13de65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-21", + "version": "11.0.0-22", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-21", + "version": "11.0.0-22", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.11", diff --git a/package.json b/package.json index 92e285615b..ff4a538506 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-21", + "version": "11.0.0-22", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From a9f2ef2ffc479da570bf830c48892b822b8d9486 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 9 Jun 2026 15:12:41 +1000 Subject: [PATCH 1102/1531] chore: update package-lock --- package-lock.json | 357 +++++----------------------------------------- 1 file changed, 34 insertions(+), 323 deletions(-) diff --git a/package-lock.json b/package-lock.json index b9da13de65..7ae9c7cf28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2872,48 +2872,6 @@ "listr2": "9.0.5" } }, - "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.1.tgz", - "integrity": "sha512-tpfN4kKrrMpQ+If1l8bhmoNkECJi0iOu6AEdrTJvWVC+32sLxTARX5Rsu579mPImRP9YFWfWgeRQ5oav7zApQQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.1.tgz", - "integrity": "sha512-+a2tTfc3rmWhLAolFUWRgJtpSuu+Fw/yjn4rF406NMxhfjbMuiOUTDRvRlMFV+DzyjkwnokisskHbCWkS3Ly5w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.1.tgz", - "integrity": "sha512-0EgcE6reYr8InjD7V37EgXcYrloqpxVPINy3ig1MwDSbl6LF/vXTYRH9OE1Ti1D8YZnB35ZH9aTcdfSb5lql2A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@lmdb/lmdb-linux-arm64": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.1.tgz", @@ -2928,48 +2886,6 @@ "linux" ] }, - "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.1.tgz", - "integrity": "sha512-SqNDY1+vpji7bh0sFH5wlWyFTOzjbDOl0/kB5RLLYDAFyd/uw3n7wyrmas3rYPpAW7z18lMOi1yKlTPv967E3g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-win32-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.1.tgz", - "integrity": "sha512-50v0O1Lt37cwrmR9vWZK5hRW0Aw+KEmxJJ75fge/zIYdvNKB/0bSMSVR5Uc2OV9JhosIUyklOmrEvavwNJ8D6w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.1.tgz", - "integrity": "sha512-qwosvPyl+zpUlp3gRb7UcJ3H8S28XHCzkv0Y0EgQToXjQP91ZD67EHSCDmaLjtKhe+GVIW5om1KUpzVLA0l6pg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@mattlewis92/dom-autoscroller": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@mattlewis92/dom-autoscroller/-/dom-autoscroller-2.4.2.tgz", @@ -3592,132 +3508,6 @@ "@parcel/watcher-win32-x64": "2.5.6" } }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", - "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", - "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", - "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", - "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", - "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", - "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@parcel/watcher-linux-arm64-glibc": { "version": "2.5.6", "cpu": [ @@ -3758,111 +3548,6 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", - "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", - "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", - "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", - "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", - "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@parcel/watcher/node_modules/node-addon-api": { "version": "7.1.1", "dev": true, @@ -4161,9 +3846,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", - "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.1.tgz", + "integrity": "sha512-bVWIOIk6pV01p4CdUbPP7CJ/434z+OooYjDuFcR+44N35YvKUC66G8MGnvcWx5mWKW3g61J+t74l3Kj15Kwn2Q==", "cpu": [ "x64" ], @@ -4508,6 +4193,15 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, + "node_modules/@swimlane/ngx-charts/node_modules/d3-time-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", + "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-time": "1 - 2" + } + }, "node_modules/@trivago/prettier-plugin-sort-imports": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-6.0.2.tgz", @@ -6942,12 +6636,15 @@ } }, "node_modules/d3-time-format": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", - "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", - "license": "BSD-3-Clause", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", "dependencies": { - "d3-time": "1 - 2" + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" } }, "node_modules/d3-time/node_modules/d3-array": { @@ -13111,6 +12808,20 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", + "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", From 9d71c05e54536f4c3c4a69a3ab2a906a4b94cad6 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 9 Jun 2026 15:20:54 +1000 Subject: [PATCH 1103/1531] chore: update package-lock --- package-lock.json | 9670 ++++++++++++++++++++++++++++----------------- 1 file changed, 5955 insertions(+), 3715 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7ae9c7cf28..9e5b8063a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -367,13 +367,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.2102.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2102.9.tgz", - "integrity": "sha512-OlPEtd5pPZSFdkXEIyZ93jsfBrkvUrVPb3xs4z2WPRnBRk9jyey40eKnmql86KRHfdn4WjHpmde4NDgtDpZRxQ==", + "version": "0.2102.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2102.14.tgz", + "integrity": "sha512-0+vjVsCkMyJdVjz5XkPW+Bdf/9TI8V2voomx/+o0o+oOaqqiEhptQWFnaIlLr7HasjB0LxXK5P9L0oQ61vxj8Q==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "21.2.9", + "@angular-devkit/core": "21.2.14", "rxjs": "7.8.2" }, "bin": { @@ -385,10 +385,10 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular-devkit/architect/node_modules/@angular-devkit/core": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.2.9.tgz", - "integrity": "sha512-04rdOGEzjLWFHlyAwqtuikginFeQ2jfXS5HqqKNP0VtG6Uu9NUDAEW5UDvXgqkEMfCDwGZbmg2iRHxp3AmAKVw==", + "node_modules/@angular-devkit/core": { + "version": "21.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.2.14.tgz", + "integrity": "sha512-RSOWXB9bFc2nwRWMxbIT0RbSNFUrwfBo4N5MNxbyQ69Ndc0gVm3h+3ArHv0qotH4d+pJYbm5ttXu8YqR2kc0CA==", "dev": true, "license": "MIT", "dependencies": { @@ -413,48 +413,14 @@ } } }, - "node_modules/@angular-devkit/architect/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular-devkit/architect/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-devkit/schematics": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-21.2.9.tgz", - "integrity": "sha512-Gyyuq2Vet70AMkbC+e0L6rjzjZWjSOyKTlOJvd99GjjyWQf6eezjd8IcF17ppKJsML6YUagO2I6AlWROq5yJmg==", + "version": "21.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-21.2.14.tgz", + "integrity": "sha512-KMJlQSBEzI4+Cy1Zh72gmGQNN2I1vY+nj9CoRcZPBIi1si+0ZAc49XT85eYl+eQumNTVQviUG7LQqgLDAHml+g==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "21.2.9", + "@angular-devkit/core": "21.2.14", "jsonc-parser": "3.3.1", "magic-string": "0.30.21", "ora": "9.3.0", @@ -466,68 +432,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.2.9.tgz", - "integrity": "sha512-04rdOGEzjLWFHlyAwqtuikginFeQ2jfXS5HqqKNP0VtG6Uu9NUDAEW5UDvXgqkEMfCDwGZbmg2iRHxp3AmAKVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.18.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/schematics/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-eslint/builder": { "version": "21.4.0", "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-21.4.0.tgz", @@ -544,68 +448,6 @@ "typescript": "*" } }, - "node_modules/@angular-eslint/builder/node_modules/@angular-devkit/core": { - "version": "21.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.2.14.tgz", - "integrity": "sha512-RSOWXB9bFc2nwRWMxbIT0RbSNFUrwfBo4N5MNxbyQ69Ndc0gVm3h+3ArHv0qotH4d+pJYbm5ttXu8YqR2kc0CA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.18.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular-eslint/builder/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular-eslint/builder/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-eslint/bundled-angular-compiler": { "version": "21.4.0", "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-21.4.0.tgz", @@ -669,78 +511,6 @@ "@angular/cli": ">= 21.0.0 < 22.0.0" } }, - "node_modules/@angular-eslint/schematics/node_modules/@angular-devkit/core": { - "version": "21.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.2.14.tgz", - "integrity": "sha512-RSOWXB9bFc2nwRWMxbIT0RbSNFUrwfBo4N5MNxbyQ69Ndc0gVm3h+3ArHv0qotH4d+pJYbm5ttXu8YqR2kc0CA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.18.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular-eslint/schematics/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular-eslint/schematics/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@angular-eslint/schematics/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-eslint/template-parser": { "version": "21.4.0", "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-21.4.0.tgz", @@ -772,9 +542,9 @@ } }, "node_modules/@angular/animations": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.2.11.tgz", - "integrity": "sha512-CpyK3XxcjuYj8cl/eaKZYxrIpVOG7Ci49YSPIzyY5bzxMv7znOoRuPnEMV/EENfiQ12IraWCBh9dd7g37PBjOw==", + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.2.16.tgz", + "integrity": "sha512-YPhph/OC1A0vkT95XZW6lXMNmi5ly91JeXi+5yeG8CCxfqscVfRNPsYbRWjSueO0cQT2HJ8U1CLteQ5a1OaoHA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -783,18 +553,18 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "21.2.11" + "@angular/core": "21.2.16" } }, "node_modules/@angular/build": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-21.2.9.tgz", - "integrity": "sha512-XYP5ALB56NWvcQisznmvQdVU6WJdUCAuCAEN2eDZNVd9X1IqRNfewQfFH6FyHo7SrK4GHDReqm6xWW6rs0+weQ==", + "version": "21.2.14", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-21.2.14.tgz", + "integrity": "sha512-l8JB326iIwum2WmbopUUFdiuYsbHchix6MH8o6F6FA7LJr8QLTvipwwbw+Jx31/RE50WkGmzsZ1fBDw/cMbmUw==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2102.9", + "@angular-devkit/architect": "0.2102.14", "@babel/core": "7.29.0", "@babel/helper-annotate-as-pure": "7.27.3", "@babel/helper-split-export-declaration": "7.24.7", @@ -837,7 +607,7 @@ "@angular/platform-browser": "^21.0.0", "@angular/platform-server": "^21.0.0", "@angular/service-worker": "^21.0.0", - "@angular/ssr": "^21.2.9", + "@angular/ssr": "^21.2.14", "karma": "^6.4.0", "less": "^4.2.0", "ng-packagr": "^21.0.0", @@ -886,251 +656,112 @@ } } }, - "node_modules/@angular/cdk": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-21.2.9.tgz", - "integrity": "sha512-0JXsr8f7xjV2815esTSq4+zGqWMa0CyNT/DV1F7lYS6qkYXcFdYUzGcd/WjNL05VKkajkSkWmTi6uyVsOpYdGA==", + "node_modules/@angular/build/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, "license": "MIT", "dependencies": { - "parse5": "^8.0.0", - "tslib": "^2.3.0" + "readdirp": "^4.0.1" }, - "peerDependencies": { - "@angular/common": "^21.0.0 || ^22.0.0", - "@angular/core": "^21.0.0 || ^22.0.0", - "@angular/platform-browser": "^21.0.0 || ^22.0.0", - "rxjs": "^6.5.3 || ^7.4.0" + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@angular/cli": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-21.2.9.tgz", - "integrity": "sha512-KldNb7vCEVOeyEUK57dguP3dTjYeikBmAohjAouu8JLtY8OOI+tf/TA31Gco/rxZ3nGqBwkvrqpD4rcDf5AhUA==", + "node_modules/@angular/build/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, "license": "MIT", - "dependencies": { - "@angular-devkit/architect": "0.2102.9", - "@angular-devkit/core": "21.2.9", - "@angular-devkit/schematics": "21.2.9", - "@inquirer/prompts": "7.10.1", - "@listr2/prompt-adapter-inquirer": "3.0.5", - "@modelcontextprotocol/sdk": "1.26.0", - "@schematics/angular": "21.2.9", - "@yarnpkg/lockfile": "1.1.0", - "algoliasearch": "5.48.1", - "ini": "6.0.0", - "jsonc-parser": "3.3.1", - "listr2": "9.0.5", - "npm-package-arg": "13.0.2", - "pacote": "21.3.1", - "parse5-html-rewriting-stream": "8.0.0", - "semver": "7.7.4", - "yargs": "18.0.0", - "zod": "4.3.6" - }, - "bin": { - "ng": "bin/ng.js" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/cli/node_modules/@angular-devkit/core": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.2.9.tgz", - "integrity": "sha512-04rdOGEzjLWFHlyAwqtuikginFeQ2jfXS5HqqKNP0VtG6Uu9NUDAEW5UDvXgqkEMfCDwGZbmg2iRHxp3AmAKVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.18.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular/cli/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@angular/cli/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@angular/cli/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular/cli/node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@angular/cli/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular/cli/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 20.19.0" + "engines": { + "node": ">= 14.18.0" }, "funding": { "type": "individual", "url": "https://paulmillr.com/funding/" } }, - "node_modules/@angular/cli/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/@angular/build/node_modules/sass": { + "version": "1.97.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz", + "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular/cli/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" + "bin": { + "sass": "sass.js" }, "engines": { - "node": ">=12" + "node": ">=14.0.0" }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, - "node_modules/@angular/cli/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, + "node_modules/@angular/cdk": { + "version": "21.2.14", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-21.2.14.tgz", + "integrity": "sha512-806REq/CLf37nEhmmd8Q+ILN8z/RVG2vk2n8YZ/4TdHpcBCi5ux4AxLbpMmduLwGPOzPagJ6ggRzE5fnX0rmcQ==", "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" + "parse5": "^8.0.0", + "tslib": "^2.3.0" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependencies": { + "@angular/common": "^21.0.0 || ^22.0.0", + "@angular/core": "^21.0.0 || ^22.0.0", + "@angular/platform-browser": "^21.0.0 || ^22.0.0", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@angular/cli/node_modules/yargs": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", - "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "node_modules/@angular/cli": { + "version": "21.2.14", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-21.2.14.tgz", + "integrity": "sha512-S8jExTjxPJILwpg2lu3DohSASVZ8DLhSNCmOe7z0qF9VskRSjC7SIQv1rq36tsJkenxuA72gjVOHZv+uSRT8HA==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" + "@angular-devkit/architect": "0.2102.14", + "@angular-devkit/core": "21.2.14", + "@angular-devkit/schematics": "21.2.14", + "@inquirer/prompts": "7.10.1", + "@listr2/prompt-adapter-inquirer": "3.0.5", + "@modelcontextprotocol/sdk": "1.26.0", + "@schematics/angular": "21.2.14", + "@yarnpkg/lockfile": "1.1.0", + "algoliasearch": "5.48.1", + "ini": "6.0.0", + "jsonc-parser": "3.3.1", + "listr2": "9.0.5", + "npm-package-arg": "13.0.2", + "pacote": "21.3.1", + "parse5-html-rewriting-stream": "8.0.0", + "semver": "7.7.4", + "yargs": "18.0.0", + "zod": "4.3.6" + }, + "bin": { + "ng": "bin/ng.js" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/@angular/cli/node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, "node_modules/@angular/common": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-21.2.11.tgz", - "integrity": "sha512-3Z3SABXpzM6fkX21WCRP6IwrjxNQVHM/3Fk2OXScExOAzpaOpS2bDgS4NB6rtCbmzKL/NFSp7ZPIZigfdqnWGw==", + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-21.2.16.tgz", + "integrity": "sha512-htHNepKzjIjkc5BQ7MKDN0bVDOfQpFr/fGUxa6irC0kFLfWt7idUTdNcxypRvjCCTuBYHkjr74fH4QKu+qvPXg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1139,14 +770,14 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "21.2.11", + "@angular/core": "21.2.16", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-21.2.11.tgz", - "integrity": "sha512-/KdE0kPQr24K/aNsdIDS2or555+8CrQxyRB5MxPKy3/8d6EvilEY/UN7pB7A5xgRQtUPMea08ZzLFJVp1qNbDA==", + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-21.2.16.tgz", + "integrity": "sha512-hVjp93gYgNj5aRbCQUK7L+pOfdqk96lCtmSL2hOL725Pmib9NyNIrA3ISfAQHN+Qo70763WUZahOiqBBOzfAcg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1156,9 +787,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-21.2.11.tgz", - "integrity": "sha512-qp/LgptDYJvpEHVVdwBEtkcbybre/ftanu0qJMpH3mu5FC4HEEOChl+9m7UVrmL4jC1ZkoZcgtzsGKAQr8mw2g==", + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-21.2.16.tgz", + "integrity": "sha512-w2ck3o+uw29AZEGK3HvOsF/ZRiPcfoq2TaDtiNjdH+svhwawt9PfMXrDbbIKF30prWzKLpT3UsCqTz1awv7Ubw==", "dev": true, "license": "MIT", "dependencies": { @@ -1179,7 +810,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "21.2.11", + "@angular/compiler": "21.2.16", "typescript": ">=5.9 <6.1" }, "peerDependenciesMeta": { @@ -1188,228 +819,70 @@ } } }, - "node_modules/@angular/compiler-cli/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, + "node_modules/@angular/core": { + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-21.2.16.tgz", + "integrity": "sha512-uufKORlB0jeYdqOvjAfMYgqIqmJentOj8XvTUxsFP5k85xxzXsDarSpP199YQz6jhJJQYNOWIloDkUTQJi5rNA==", "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "peerDependencies": { + "@angular/compiler": "21.2.16", + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.15.0 || ~0.16.0" + }, + "peerDependenciesMeta": { + "@angular/compiler": { + "optional": true + }, + "zone.js": { + "optional": true + } } }, - "node_modules/@angular/compiler-cli/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, + "node_modules/@angular/forms": { + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-21.2.16.tgz", + "integrity": "sha512-2djTJmTpg/MkQ2kdCI9k0LT4RL9/Hg03fDUNN2eN5c04FIk99D3yHXUJYLwiaErLuLQNkU8HaijluKHdH93cWQ==", "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "tslib": "^2.3.0" + }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@angular/common": "21.2.16", + "@angular/core": "21.2.16", + "@angular/platform-browser": "21.2.16", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@angular/compiler-cli/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "node_modules/@angular/language-service": { + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-21.2.16.tgz", + "integrity": "sha512-LBhoBmIVopMBfFVOoc5MDD2JWO+6+fHg7kNWc2Wy+YKhSndgsWVCo4F8MIgZh6HXxofZe3pEMXO0GfDPc0Ny3g==", "dev": true, "license": "MIT", - "dependencies": { - "readdirp": "^5.0.0" - }, "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/@angular/compiler-cli/node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@angular/compiler-cli/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular/compiler-cli/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular/compiler-cli/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular/compiler-cli/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@angular/compiler-cli/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@angular/compiler-cli/node_modules/yargs": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", - "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/@angular/compiler-cli/node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/@angular/core": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-21.2.11.tgz", - "integrity": "sha512-EULAfQ0m/I9hZJes74OFlrnfDWqlfV0esE0CkHehO5IEF9rd769+dfuGEAJAzrz+/6Q3PhS0bWDYiT68z1H8Ag==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/compiler": "21.2.11", - "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.15.0 || ~0.16.0" - }, - "peerDependenciesMeta": { - "@angular/compiler": { - "optional": true - }, - "zone.js": { - "optional": true - } - } - }, - "node_modules/@angular/forms": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-21.2.11.tgz", - "integrity": "sha512-F67V612wHxPXHrbp825VirYfGPKBUM8PvL9atN2Ku1fsdGSFPU3hTxu1HU8fKYLLBpKYVVuqFqzaU/qIpTXGYA==", - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/common": "21.2.11", - "@angular/core": "21.2.11", - "@angular/platform-browser": "21.2.11", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/language-service": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-21.2.11.tgz", - "integrity": "sha512-M5BVtsfgjUdR/9SkVFBQ/WoAoSSybeYOeAzuBThwmAz4CA+yvZtyuJNlaUQ2IaF7f5TCtg05Pg9YRgKOusK3HQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, - "node_modules/@angular/material": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-21.2.9.tgz", - "integrity": "sha512-uU5Sy0rSd4Y4WjqTcrqs3MpfY/Uy5tmDPSAAvwD0y5y4QVOLoV8uhTQDI/nNg2Lh9NoJKvykZE1ITRMvjfRALQ==", - "license": "MIT", + "node_modules/@angular/material": { + "version": "21.2.14", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-21.2.14.tgz", + "integrity": "sha512-fMQca8VRtei93JRRG9qQ+u08DCb0nga59Esoakq5yx3+A1NfdpFeUS1tBns56U04o8KAaIAwZK3NBqXz8ZKNqg==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/cdk": "21.2.9", + "@angular/cdk": "21.2.14", "@angular/common": "^21.0.0 || ^22.0.0", "@angular/core": "^21.0.0 || ^22.0.0", "@angular/forms": "^21.0.0 || ^22.0.0", @@ -1418,23 +891,23 @@ } }, "node_modules/@angular/material-date-fns-adapter": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@angular/material-date-fns-adapter/-/material-date-fns-adapter-21.2.9.tgz", - "integrity": "sha512-tZ48ToUMzGkrwRPsUxPElNsw4AHRtDo8wGjyihwPUAlDQRXU8Mx0oszHcceJFWlTeXSy5uK722jS4rOd+c1t0w==", + "version": "21.2.14", + "resolved": "https://registry.npmjs.org/@angular/material-date-fns-adapter/-/material-date-fns-adapter-21.2.14.tgz", + "integrity": "sha512-PvfX/Y+6ml8G+Zacgmp52nerI4fQmPtCKPDweUVA5Drm8Ygoo3zdVS9UnB+74KuH56I+AS5IZ8usJSwdV+z1UQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/core": "^21.0.0 || ^22.0.0", - "@angular/material": "21.2.9", + "@angular/material": "21.2.14", "date-fns": ">2.20.0 <5.0" } }, "node_modules/@angular/platform-browser": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.2.11.tgz", - "integrity": "sha512-Uz/KwGjSEvbE8J9kNSSetzxhBWjCXv9OuxH1w2WkW6jLNU3vgvzuKX7SXDyUys6KJv5TqkClJ9BLeU11QbmJdw==", + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.2.16.tgz", + "integrity": "sha512-59ToWYDb+O3fS0+Y4ubQqV0zY6sf2esLZ19AT7JKXN7Akqbz7aQ2/3k3PKmfhwKWek5o3lkuNz8YhxKQruNh8Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1443,9 +916,9 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/animations": "21.2.11", - "@angular/common": "21.2.11", - "@angular/core": "21.2.11" + "@angular/animations": "21.2.16", + "@angular/common": "21.2.16", + "@angular/core": "21.2.16" }, "peerDependenciesMeta": { "@angular/animations": { @@ -1454,9 +927,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-21.2.11.tgz", - "integrity": "sha512-wdlYzXkc6X6f8mj2jLlaDJlRiwmurffAf37NCXMNqgTTc0j0iD/DLd3JQScMVCJ9bZ0se02EF5X3Z82W0vmmPA==", + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-21.2.16.tgz", + "integrity": "sha512-WtTnkJOmKiGccHRQfBdkwODAkpTB4zbPN3IKhcqCjlezKaPqZB5tjrIu72Z5pmi5VIgJz1LmfO1LSVCMC5h7dA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1465,16 +938,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "21.2.11", - "@angular/compiler": "21.2.11", - "@angular/core": "21.2.11", - "@angular/platform-browser": "21.2.11" + "@angular/common": "21.2.16", + "@angular/compiler": "21.2.16", + "@angular/core": "21.2.16", + "@angular/platform-browser": "21.2.16" } }, "node_modules/@angular/router": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-21.2.11.tgz", - "integrity": "sha512-IB7/KuRDsxAjCOxYNccq2LdCTKuu59cx5MmOhrt+TarvkNE/xdlFkP7vtrCl44DJt0q7/tveWvsn5oqTw7rN7A==", + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-21.2.16.tgz", + "integrity": "sha512-0+Pyh0uT4vCLabKoGCARYWlwpz4DgZI9AE01n8s9u/nKAZuEMnJtLLnaUtHEMI8nJSqpgnS/5AthuJZdDEfkYw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1483,16 +956,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "21.2.11", - "@angular/core": "21.2.11", - "@angular/platform-browser": "21.2.11", + "@angular/common": "21.2.16", + "@angular/core": "21.2.16", + "@angular/platform-browser": "21.2.16", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/service-worker": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-21.2.11.tgz", - "integrity": "sha512-kRYl5LxSz2mJR8LJVC6SLmww8b01j/qUq/7W/Z4UtNxjHnxUWgKDoWCCfoCiIss33MIgEGQERrWnGGOwkVlOJQ==", + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-21.2.16.tgz", + "integrity": "sha512-Wwdc+40T4Zk+NokLEmTN9xzEt5Fg0CtUbPgC4exHYVezfzddmq5QESqyKzDHuHOBi+P+Pm6uBCT+his/F/5xbw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1504,14 +977,14 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "21.2.11", + "@angular/core": "21.2.16", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/upgrade": { - "version": "21.2.11", - "resolved": "https://registry.npmjs.org/@angular/upgrade/-/upgrade-21.2.11.tgz", - "integrity": "sha512-4FuJXAvkmP7fQVIv0cmpRZ0feo+JpH3jkXfwPNSFp4BA01Xoq89WplgYMZc40Sw82iLUqY0hiraVAWb//5S/dw==", + "version": "21.2.16", + "resolved": "https://registry.npmjs.org/@angular/upgrade/-/upgrade-21.2.16.tgz", + "integrity": "sha512-2deW5HHwZ0md4SiJPdy+mQHd7WoVzhZgjV/ruUxZBZE12YTZ0A0apl8kg70p0fxwlkXnyYMamIJmrPTPuVL/lQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1520,18 +993,20 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "21.2.11", - "@angular/core": "21.2.11", - "@angular/platform-browser": "21.2.11", - "@angular/platform-browser-dynamic": "21.2.11" + "@angular/compiler": "21.2.16", + "@angular/core": "21.2.16", + "@angular/platform-browser": "21.2.16", + "@angular/platform-browser-dynamic": "21.2.16" } }, "node_modules/@babel/code-frame": { - "version": "7.29.0", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -1540,9 +1015,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -1598,14 +1073,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -1628,14 +1103,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -1655,9 +1130,9 @@ } }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, "license": "MIT", "engines": { @@ -1665,29 +1140,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1710,9 +1185,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "engines": { @@ -1720,7 +1195,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { @@ -1728,9 +1205,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "engines": { @@ -1738,27 +1215,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.29.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -1768,33 +1245,33 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", "debug": "^4.3.1" }, "engines": { @@ -1802,14 +1279,14 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1817,6 +1294,8 @@ }, "node_modules/@colors/colors": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, "license": "MIT", "engines": { @@ -1824,15 +1303,15 @@ } }, "node_modules/@commitlint/cli": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.0.tgz", - "integrity": "sha512-yNkyN/tuKTJS3wdVfsZ2tXDM4G4Gi7z+jW54Cki8N8tZqwKBltbIvUUrSbT4hz1bhW/h0CdR+5sCSpXD+wMKaQ==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.3.tgz", + "integrity": "sha512-OJdL0EXWD5y9LPa0nr/geOwzaS8BsdaybKkcloB0JgsguGxNv2R+hC2FTPqrAcprg35zF33KOQerY0x8W1aesA==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/format": "^20.5.0", - "@commitlint/lint": "^20.5.0", - "@commitlint/load": "^20.5.0", + "@commitlint/lint": "^20.5.3", + "@commitlint/load": "^20.5.3", "@commitlint/read": "^20.5.0", "@commitlint/types": "^20.5.0", "tinyexec": "^1.0.0", @@ -1845,138 +1324,267 @@ "node": ">=v18" } }, - "node_modules/@commitlint/config-conventional": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.5.0.tgz", - "integrity": "sha512-t3Ni88rFw1XMa4nZHgOKJ8fIAT9M2j5TnKyTqJzsxea7FUetlNdYFus9dz+MhIRZmc16P0PPyEfh6X2d/qw8SA==", + "node_modules/@commitlint/cli/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "dependencies": { - "@commitlint/types": "^20.5.0", - "conventional-changelog-conventionalcommits": "^9.2.0" - }, "engines": { - "node": ">=v18" + "node": ">=8" } }, - "node_modules/@commitlint/config-validator": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-20.5.0.tgz", - "integrity": "sha512-T/Uh6iJUzyx7j35GmHWdIiGRQB+ouZDk0pwAaYq4SXgB54KZhFdJ0vYmxiW6AMYICTIWuyMxDBl1jK74oFp/Gw==", + "node_modules/@commitlint/cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^20.5.0", - "ajv": "^8.11.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=v18" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@commitlint/ensure": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.5.0.tgz", - "integrity": "sha512-IpHqAUesBeW1EDDdjzJeaOxU9tnogLAyXLRBn03SHlj1SGENn2JGZqSWGkFvBJkJzfXAuCNtsoYzax+ZPS+puw==", + "node_modules/@commitlint/cli/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@commitlint/types": "^20.5.0", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=v18" + "node": ">=12" } }, - "node_modules/@commitlint/execute-rule": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-20.0.0.tgz", - "integrity": "sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==", + "node_modules/@commitlint/cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=v18" + "node": ">=7.0.0" } }, - "node_modules/@commitlint/format": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-20.5.0.tgz", - "integrity": "sha512-TI9EwFU/qZWSK7a5qyXMpKPPv3qta7FO4tKW+Wt2al7sgMbLWTsAcDpX1cU8k16TRdsiiet9aOw0zpvRXNJu7Q==", + "node_modules/@commitlint/cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@commitlint/cli/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", - "dependencies": { - "@commitlint/types": "^20.5.0", - "picocolors": "^1.1.1" - }, "engines": { - "node": ">=v18" + "node": ">=8" } }, - "node_modules/@commitlint/is-ignored": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-20.5.0.tgz", - "integrity": "sha512-JWLarAsurHJhPozbuAH6GbP4p/hdOCoqS9zJMfqwswne+/GPs5V0+rrsfOkP68Y8PSLphwtFXV0EzJ+GTXTTGg==", + "node_modules/@commitlint/cli/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^20.5.0", - "semver": "^7.6.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=v18" + "node": ">=8" } }, - "node_modules/@commitlint/lint": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.5.0.tgz", - "integrity": "sha512-jiM3hNUdu04jFBf1VgPdjtIPvbuVfDTBAc6L98AWcoLjF5sYqkulBHBzlVWll4rMF1T5zeQFB6r//a+s+BBKlA==", + "node_modules/@commitlint/cli/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/is-ignored": "^20.5.0", - "@commitlint/parse": "^20.5.0", - "@commitlint/rules": "^20.5.0", - "@commitlint/types": "^20.5.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=v18" + "node": ">=8" } }, - "node_modules/@commitlint/load": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.5.0.tgz", - "integrity": "sha512-sLhhYTL/KxeOTZjjabKDhwidGZan84XKK1+XFkwDYL/4883kIajcz/dZFAhBJmZPtL8+nBx6bnkzA95YxPeDPw==", + "node_modules/@commitlint/cli/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^20.5.0", - "@commitlint/execute-rule": "^20.0.0", - "@commitlint/resolve-extends": "^20.5.0", - "@commitlint/types": "^20.5.0", - "cosmiconfig": "^9.0.1", - "cosmiconfig-typescript-loader": "^6.1.0", - "is-plain-obj": "^4.1.0", - "lodash.mergewith": "^4.6.2", - "picocolors": "^1.1.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=v18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@commitlint/load/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/@commitlint/cli/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@commitlint/cli/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", "engines": { "node": ">=12" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.5.3.tgz", + "integrity": "sha512-j34Qqeaa152chJgz2ysyk0BCpHenJn1lV0Rx0VXf8k3ccQcED+48EZrzMvo9jLmJUyBrrBwvu89I+2er4gW7QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "conventional-changelog-conventionalcommits": "^9.2.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-20.5.0.tgz", + "integrity": "sha512-T/Uh6iJUzyx7j35GmHWdIiGRQB+ouZDk0pwAaYq4SXgB54KZhFdJ0vYmxiW6AMYICTIWuyMxDBl1jK74oFp/Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/ensure": { + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.5.3.tgz", + "integrity": "sha512-4i4AgNvH62owG9MwSiWKrle7HGNpBHHdLnWFIp5fTsHUYe5kRuh15t08L/0pdbbrRk8JKXQxxN4hZQcn+szkrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "es-toolkit": "^1.46.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-20.0.0.tgz", + "integrity": "sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-20.5.0.tgz", + "integrity": "sha512-TI9EwFU/qZWSK7a5qyXMpKPPv3qta7FO4tKW+Wt2al7sgMbLWTsAcDpX1cU8k16TRdsiiet9aOw0zpvRXNJu7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-20.5.0.tgz", + "integrity": "sha512-JWLarAsurHJhPozbuAH6GbP4p/hdOCoqS9zJMfqwswne+/GPs5V0+rrsfOkP68Y8PSLphwtFXV0EzJ+GTXTTGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/lint": { + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.5.3.tgz", + "integrity": "sha512-M7JbWBNr2gXKaPc4i/KipsuW1gkDHpj35KPjWtKy3Z+2AQw5wu1gBi1LIO0uoaij67CqY4K8PxPZSGens4evCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/is-ignored": "^20.5.0", + "@commitlint/parse": "^20.5.0", + "@commitlint/rules": "^20.5.3", + "@commitlint/types": "^20.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.5.3.tgz", + "integrity": "sha512-1FDZWuKyu98Myb8i7Tp31jPU2rZpOwAdYRyJcy2KoGg7Xk2A+bgHN8smhMaaNSNkmE8fwt53BokywZq8Gv/5XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.5.0", + "@commitlint/execute-rule": "^20.0.0", + "@commitlint/resolve-extends": "^20.5.3", + "@commitlint/types": "^20.5.0", + "cosmiconfig": "^9.0.1", + "cosmiconfig-typescript-loader": "^6.1.0", + "es-toolkit": "^1.46.0", + "is-plain-obj": "^4.1.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" } }, "node_modules/@commitlint/message": { @@ -2022,17 +1630,17 @@ } }, "node_modules/@commitlint/resolve-extends": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.5.0.tgz", - "integrity": "sha512-3SHPWUW2v0tyspCTcfSsYml0gses92l6TlogwzvM2cbxDgmhSRc+fldDjvGkCXJrjSM87BBaWYTPWwwyASZRrg==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.5.3.tgz", + "integrity": "sha512-+ogW9v/u9JqpvAgTrLra/YTFo0KkjU6iNblF89pPsj4NebNc+DAWctsludwezI8YnsjBmfHpApSwcXprN/f/ew==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/config-validator": "^20.5.0", "@commitlint/types": "^20.5.0", - "global-directory": "^4.0.1", + "es-toolkit": "^1.46.0", + "global-directory": "^5.0.0", "import-meta-resolve": "^4.0.0", - "lodash.mergewith": "^4.6.2", "resolve-from": "^5.0.0" }, "engines": { @@ -2040,13 +1648,13 @@ } }, "node_modules/@commitlint/rules": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.5.0.tgz", - "integrity": "sha512-5NdQXQEdnDPT5pK8O39ZA7HohzPRHEsDGU23cyVCNPQy4WegAbAwrQk3nIu7p2sl3dutPk8RZd91yKTrMTnRkQ==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.5.3.tgz", + "integrity": "sha512-MPlMnb9D3wbszYMp+1hPtuhtPJndRo6I6yfkZVA4+jR8w7Kqp0u2u/Y+gzbaItx5Lltq5rw7FSZQWJMoXUC4NQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/ensure": "^20.5.0", + "@commitlint/ensure": "^20.5.3", "@commitlint/message": "^20.4.3", "@commitlint/to-lines": "^20.0.0", "@commitlint/types": "^20.5.0" @@ -2121,6 +1729,8 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "license": "MIT", "dependencies": { @@ -2132,6 +1742,8 @@ }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2141,6 +1753,8 @@ }, "node_modules/@ctrl/ngx-emoji-mart": { "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@ctrl/ngx-emoji-mart/-/ngx-emoji-mart-9.3.0.tgz", + "integrity": "sha512-9uFzAvlFT21OLsTfhL3ZEO5mp51qvL1F4ErIZVBIsvAlji46u6p2KGgVA60oIheFBX4JoZI7HBDGOkGnm9dTUQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -2149,1014 +1763,2122 @@ "@angular/core": ">=15.0.0-0" } }, - "node_modules/@esbuild/linux-arm64": { + "node_modules/@emnapi/core": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.0.tgz", + "integrity": "sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.0.tgz", + "integrity": "sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", "cpu": [ - "arm64" + "ppc64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" + "aix" ], "engines": { "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/config-array": { - "version": "0.21.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", - "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.7", - "debug": "^4.3.1", - "minimatch": "^3.1.5" - }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", - "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "ajv": "^6.14.0", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.5", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/@eslint/js": { - "version": "9.39.4", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", - "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" + "node": ">=18" } }, - "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", - "license": "Apache-2.0", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0", - "levn": "^0.4.1" - }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@gar/promise-retry": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", - "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/@harperfast/extended-iterable": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@harperfast/extended-iterable/-/extended-iterable-1.0.3.tgz", - "integrity": "sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==", + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "optional": true + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@hono/node-server": { - "version": "1.19.14", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", - "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "hono": "^4" + "node": ">=18" } }, - "node_modules/@humanfs/core": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", - "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", - "license": "Apache-2.0", - "dependencies": { - "@humanfs/types": "^0.15.0" - }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=18.18.0" + "node": ">=18" } }, - "node_modules/@humanfs/node": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", - "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.2", - "@humanfs/types": "^0.15.0", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/types": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", - "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "license": "Apache-2.0", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=18" } }, - "node_modules/@inquirer/ansi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", - "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { "node": ">=18" } }, - "node_modules/@inquirer/checkbox": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", - "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, + "optional": true, + "os": [ + "openharmony" + ], "engines": { "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } } }, - "node_modules/@inquirer/confirm": { - "version": "5.1.21", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", - "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } } }, - "node_modules/@inquirer/core": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", - "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.3" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } } }, - "node_modules/@inquirer/editor": { - "version": "4.2.23", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", - "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/external-editor": "^1.0.3", - "@inquirer/type": "^3.0.10" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } } }, - "node_modules/@inquirer/expand": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", - "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } } }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", - "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", - "dev": true, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "license": "MIT", "dependencies": { - "chardet": "^2.1.1", - "iconv-lite": "^0.7.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependencies": { - "@types/node": ">=18" + "funding": { + "url": "https://opencollective.com/eslint" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@inquirer/figures": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", - "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", - "dev": true, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "license": "MIT", "engines": { - "node": ">=18" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@inquirer/input": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", - "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", - "dev": true, - "license": "MIT", + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "license": "Apache-2.0", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@inquirer/number": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", - "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", - "dev": true, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "*" } }, - "node_modules/@inquirer/password": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", - "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", - "dev": true, - "license": "MIT", + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "license": "Apache-2.0", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@eslint/core": "^0.17.0" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@inquirer/prompts": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", - "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", - "dev": true, - "license": "MIT", + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "license": "Apache-2.0", "dependencies": { - "@inquirer/checkbox": "^4.3.2", - "@inquirer/confirm": "^5.1.21", - "@inquirer/editor": "^4.2.23", - "@inquirer/expand": "^4.0.23", - "@inquirer/input": "^4.3.1", - "@inquirer/number": "^3.0.23", - "@inquirer/password": "^4.0.23", - "@inquirer/rawlist": "^4.1.11", - "@inquirer/search": "^3.2.2", - "@inquirer/select": "^4.4.2" + "@types/json-schema": "^7.0.15" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@inquirer/rawlist": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", - "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", - "dev": true, + "node_modules/@eslint/eslintrc": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@inquirer/search": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", - "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@inquirer/select": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", - "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@inquirer/type": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", - "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "license": "MIT", "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": ">= 4" } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { - "minipass": "^7.0.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=18.0.0" + "node": "*" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", - "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", - "dev": true, + "node_modules/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "license": "MIT", "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@gar/promise-retry": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", + "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==", "dev": true, "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", + "node_modules/@harperfast/extended-iterable": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@harperfast/extended-iterable/-/extended-iterable-1.0.3.tgz", + "integrity": "sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "optional": true }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", + "node_modules/@hono/node-server": { + "version": "1.19.14", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", + "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", "dev": true, "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" } }, - "node_modules/@listr2/prompt-adapter-inquirer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-3.0.5.tgz", - "integrity": "sha512-WELs+hj6xcilkloBXYf9XXK8tYEnKsgLj01Xl5ONUJpKjmT5hGVUzNUS5tooUxs7pGMrw+jFD/41WpqW4V3LDA==", - "dev": true, - "license": "MIT", + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "license": "Apache-2.0", "dependencies": { - "@inquirer/type": "^3.0.8" + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { - "node": ">=20.0.0" + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" }, - "peerDependencies": { - "@inquirer/prompts": ">= 3 < 8", - "listr2": "9.0.5" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.1.tgz", - "integrity": "sha512-aoERa5B6ywXdyFeYGQ1gbQpkMkDbEo45qVoXE5QpIRavqjnyPwjOulMkmkypkmsbJ5z4Wi0TBztON8agCTG0Vg==", - "cpu": [ - "arm64" - ], + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@inquirer/ansi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@mattlewis92/dom-autoscroller": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@mattlewis92/dom-autoscroller/-/dom-autoscroller-2.4.2.tgz", - "integrity": "sha512-YbrUWREPGEjE/FU6foXcAT1YbVwqD/jkYnY1dFb0o4AxtP3s4xKBthlELjndZih8uwsDWgQZx1eNskRNe2BgZQ==", - "license": "MIT" + "engines": { + "node": ">=18" + } }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz", - "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==", + "node_modules/@inquirer/checkbox": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", + "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", "dev": true, "license": "MIT", "dependencies": { - "@hono/node-server": "^1.19.9", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.2.1", - "express-rate-limit": "^8.2.1", - "hono": "^4.11.4", - "jose": "^6.1.3", - "json-schema-typed": "^8.0.2", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.25 || ^4.0", - "zod-to-json-schema": "^3.25.1" + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" }, "engines": { "node": ">=18" }, "peerDependencies": { - "@cfworker/json-schema": "^4.1.1", - "zod": "^3.25 || ^4.0" + "@types/node": ">=18" }, "peerDependenciesMeta": { - "@cfworker/json-schema": { + "@types/node": { "optional": true - }, - "zod": { - "optional": false } } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "node_modules/@inquirer/confirm": { + "version": "5.1.21", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" }, "engines": { - "node": ">= 0.10" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@napi-rs/nice": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", - "integrity": "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==", + "node_modules/@inquirer/core": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", "dev": true, "license": "MIT", - "optional": true, + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.3" + }, "engines": { - "node": ">= 10" + "node": ">=18" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" + "peerDependencies": { + "@types/node": ">=18" }, - "optionalDependencies": { - "@napi-rs/nice-android-arm-eabi": "1.1.1", - "@napi-rs/nice-android-arm64": "1.1.1", - "@napi-rs/nice-darwin-arm64": "1.1.1", - "@napi-rs/nice-darwin-x64": "1.1.1", - "@napi-rs/nice-freebsd-x64": "1.1.1", - "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", - "@napi-rs/nice-linux-arm64-gnu": "1.1.1", - "@napi-rs/nice-linux-arm64-musl": "1.1.1", - "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", - "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", - "@napi-rs/nice-linux-s390x-gnu": "1.1.1", - "@napi-rs/nice-linux-x64-gnu": "1.1.1", - "@napi-rs/nice-linux-x64-musl": "1.1.1", - "@napi-rs/nice-openharmony-arm64": "1.1.1", - "@napi-rs/nice-win32-arm64-msvc": "1.1.1", - "@napi-rs/nice-win32-ia32-msvc": "1.1.1", - "@napi-rs/nice-win32-x64-msvc": "1.1.1" + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@napi-rs/nice-linux-arm64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz", - "integrity": "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==", - "cpu": [ - "arm64" - ], + "node_modules/@inquirer/editor": { + "version": "4.2.23", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", + "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/external-editor": "^1.0.3", + "@inquirer/type": "^3.0.10" + }, "engines": { - "node": ">= 10" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@napi-rs/nice-linux-arm64-musl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz", - "integrity": "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==", - "cpu": [ - "arm64" - ], + "node_modules/@inquirer/expand": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", + "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@ngneat/hotkeys": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - } - }, - "node_modules/@ngstack/code-editor": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@ngstack/code-editor/-/code-editor-9.0.0.tgz", - "integrity": "sha512-sioi0qyeo9Q8PIdhGFmUeuEx6LETqSjC/4A1Fnl9HFVYzCU7mDVdyeUITubu+4THjraH1mIAVw2t0R7rDgdHdA==", - "license": "MIT", "dependencies": { - "tslib": "^2.5.0" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" }, "peerDependencies": { - "@angular/common": ">=17.1.1", - "@angular/core": ">=17.1.1" + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@inquirer/external-editor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", + "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "chardet": "^2.1.1", + "iconv-lite": "^0.7.0" }, "engines": { - "node": ">= 8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", "dev": true, "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=18" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@inquirer/input": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", + "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" }, "engines": { - "node": ">= 8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@npmcli/agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.0.tgz", - "integrity": "sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==", + "node_modules/@inquirer/number": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", + "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^11.2.1", - "socks-proxy-agent": "^8.0.3" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@npmcli/agent/node_modules/lru-cache": { - "version": "11.5.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", - "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "node_modules/@inquirer/password": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", + "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, "engines": { - "node": "20 || >=22" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@npmcli/fs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-5.0.0.tgz", - "integrity": "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==", + "node_modules/@inquirer/prompts": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", + "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "semver": "^7.3.5" + "@inquirer/checkbox": "^4.3.2", + "@inquirer/confirm": "^5.1.21", + "@inquirer/editor": "^4.2.23", + "@inquirer/expand": "^4.0.23", + "@inquirer/input": "^4.3.1", + "@inquirer/number": "^3.0.23", + "@inquirer/password": "^4.0.23", + "@inquirer/rawlist": "^4.1.11", + "@inquirer/search": "^3.2.2", + "@inquirer/select": "^4.4.2" }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@npmcli/git": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.2.tgz", - "integrity": "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==", + "node_modules/@inquirer/rawlist": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", + "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "@gar/promise-retry": "^1.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "ini": "^6.0.0", - "lru-cache": "^11.2.1", - "npm-pick-manifest": "^11.0.1", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "which": "^6.0.0" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@npmcli/git/node_modules/isexe": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", - "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "node_modules/@inquirer/search": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", + "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, "engines": { - "node": ">=20" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", + "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", + "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@listr2/prompt-adapter-inquirer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-3.0.5.tgz", + "integrity": "sha512-WELs+hj6xcilkloBXYf9XXK8tYEnKsgLj01Xl5ONUJpKjmT5hGVUzNUS5tooUxs7pGMrw+jFD/41WpqW4V3LDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@inquirer/prompts": ">= 3 < 8", + "listr2": "9.0.5" + } + }, + "node_modules/@lmdb/lmdb-darwin-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.1.tgz", + "integrity": "sha512-tpfN4kKrrMpQ+If1l8bhmoNkECJi0iOu6AEdrTJvWVC+32sLxTARX5Rsu579mPImRP9YFWfWgeRQ5oav7zApQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@lmdb/lmdb-darwin-x64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.1.tgz", + "integrity": "sha512-+a2tTfc3rmWhLAolFUWRgJtpSuu+Fw/yjn4rF406NMxhfjbMuiOUTDRvRlMFV+DzyjkwnokisskHbCWkS3Ly5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.1.tgz", + "integrity": "sha512-0EgcE6reYr8InjD7V37EgXcYrloqpxVPINy3ig1MwDSbl6LF/vXTYRH9OE1Ti1D8YZnB35ZH9aTcdfSb5lql2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.1.tgz", + "integrity": "sha512-aoERa5B6ywXdyFeYGQ1gbQpkMkDbEo45qVoXE5QpIRavqjnyPwjOulMkmkypkmsbJ5z4Wi0TBztON8agCTG0Vg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-x64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.1.tgz", + "integrity": "sha512-SqNDY1+vpji7bh0sFH5wlWyFTOzjbDOl0/kB5RLLYDAFyd/uw3n7wyrmas3rYPpAW7z18lMOi1yKlTPv967E3g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-win32-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.1.tgz", + "integrity": "sha512-50v0O1Lt37cwrmR9vWZK5hRW0Aw+KEmxJJ75fge/zIYdvNKB/0bSMSVR5Uc2OV9JhosIUyklOmrEvavwNJ8D6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@lmdb/lmdb-win32-x64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.1.tgz", + "integrity": "sha512-qwosvPyl+zpUlp3gRb7UcJ3H8S28XHCzkv0Y0EgQToXjQP91ZD67EHSCDmaLjtKhe+GVIW5om1KUpzVLA0l6pg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", + "optional": true + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "optional": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/@mattlewis92/dom-autoscroller": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@mattlewis92/dom-autoscroller/-/dom-autoscroller-2.4.2.tgz", + "integrity": "sha512-YbrUWREPGEjE/FU6foXcAT1YbVwqD/jkYnY1dFb0o4AxtP3s4xKBthlELjndZih8uwsDWgQZx1eNskRNe2BgZQ==", + "license": "MIT" + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz", + "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@hono/node-server": "^1.19.9", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "hono": "^4.11.4", + "jose": "^6.1.3", + "json-schema-typed": "^8.0.2", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.25 || ^4.0", + "zod-to-json-schema": "^3.25.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@cfworker/json-schema": "^4.1.1", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "@cfworker/json-schema": { + "optional": true + }, + "zod": { + "optional": false + } + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz", + "integrity": "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz", + "integrity": "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz", + "integrity": "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz", + "integrity": "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.4.tgz", + "integrity": "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz", + "integrity": "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@napi-rs/nice": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", + "integrity": "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/nice-android-arm-eabi": "1.1.1", + "@napi-rs/nice-android-arm64": "1.1.1", + "@napi-rs/nice-darwin-arm64": "1.1.1", + "@napi-rs/nice-darwin-x64": "1.1.1", + "@napi-rs/nice-freebsd-x64": "1.1.1", + "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", + "@napi-rs/nice-linux-arm64-gnu": "1.1.1", + "@napi-rs/nice-linux-arm64-musl": "1.1.1", + "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", + "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", + "@napi-rs/nice-linux-s390x-gnu": "1.1.1", + "@napi-rs/nice-linux-x64-gnu": "1.1.1", + "@napi-rs/nice-linux-x64-musl": "1.1.1", + "@napi-rs/nice-openharmony-arm64": "1.1.1", + "@napi-rs/nice-win32-arm64-msvc": "1.1.1", + "@napi-rs/nice-win32-ia32-msvc": "1.1.1", + "@napi-rs/nice-win32-x64-msvc": "1.1.1" + } + }, + "node_modules/@napi-rs/nice-android-arm-eabi": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.1.1.tgz", + "integrity": "sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-android-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.1.1.tgz", + "integrity": "sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-darwin-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.1.1.tgz", + "integrity": "sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-darwin-x64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.1.1.tgz", + "integrity": "sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-freebsd-x64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.1.1.tgz", + "integrity": "sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.1.1.tgz", + "integrity": "sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz", + "integrity": "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm64-musl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz", + "integrity": "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-ppc64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.1.1.tgz", + "integrity": "sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-riscv64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.1.1.tgz", + "integrity": "sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-s390x-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.1.1.tgz", + "integrity": "sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-x64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.1.1.tgz", + "integrity": "sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-x64-musl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.1.1.tgz", + "integrity": "sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-openharmony-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-openharmony-arm64/-/nice-openharmony-arm64-1.1.1.tgz", + "integrity": "sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-arm64-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.1.1.tgz", + "integrity": "sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-ia32-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.1.1.tgz", + "integrity": "sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-x64-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.1.1.tgz", + "integrity": "sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@ngneat/hotkeys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ngneat/hotkeys/-/hotkeys-4.1.0.tgz", + "integrity": "sha512-bqtmK0wMGQOFtNnxmklnbhVbiUoOIp5rXY4UeWGRoMgf7RGvW6dO5moZSPzenJwp8pgi2EmSyo+xpQ8R512hIw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + } + }, + "node_modules/@ngstack/code-editor": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@ngstack/code-editor/-/code-editor-9.0.0.tgz", + "integrity": "sha512-sioi0qyeo9Q8PIdhGFmUeuEx6LETqSjC/4A1Fnl9HFVYzCU7mDVdyeUITubu+4THjraH1mIAVw2t0R7rDgdHdA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.5.0" + }, + "peerDependencies": { + "@angular/common": ">=17.1.1", + "@angular/core": ">=17.1.1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.2.tgz", + "integrity": "sha512-EUEuWAxnL07Sp5/iC/1X6Xj+XThUvnbei9zfRWZdEXa7lss9RTHMhAHBeg+MZ5To9s/gGaSI+UwZTPdYMvKSeg==", + "dev": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^11.2.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@npmcli/fs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-5.0.0.tgz", + "integrity": "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==", + "dev": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/git": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.2.tgz", + "integrity": "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==", + "dev": true, + "license": "ISC", + "dependencies": { + "@gar/promise-retry": "^1.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "ini": "^6.0.0", + "lru-cache": "^11.2.1", + "npm-pick-manifest": "^11.0.1", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "which": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/git/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" } }, "node_modules/@npmcli/git/node_modules/lru-cache": { @@ -3166,352 +3888,757 @@ "dev": true, "license": "BlueOak-1.0.0", "engines": { - "node": "20 || >=22" + "node": "20 || >=22" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz", + "integrity": "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^5.0.0", + "npm-normalize-package-bin": "^5.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-5.0.0.tgz", + "integrity": "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/package-json": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-7.0.5.tgz", + "integrity": "sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^7.0.0", + "glob": "^13.0.0", + "hosted-git-info": "^9.0.0", + "json-parse-even-better-errors": "^5.0.0", + "proc-log": "^6.0.0", + "semver": "^7.5.3", + "spdx-expression-parse": "^4.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@npmcli/package-json/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@npmcli/package-json/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/package-json/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", + "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "which": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/redact": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-4.0.0.tgz", + "integrity": "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@npmcli/git/node_modules/which": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", - "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "node_modules/@npmcli/run-script": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-10.0.4.tgz", + "integrity": "sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg==", "dev": true, "license": "ISC", "dependencies": { - "isexe": "^4.0.0" - }, - "bin": { - "node-which": "bin/which.js" + "@npmcli/node-gyp": "^5.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "node-gyp": "^12.1.0", + "proc-log": "^6.0.0" }, "engines": { "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@npmcli/installed-package-contents": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz", - "integrity": "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==", + "node_modules/@nx/nx-darwin-arm64": { + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-18.3.5.tgz", + "integrity": "sha512-4I5UpZ/x2WO9OQyETXKjaYhXiZKUTYcLPewruRMODWu6lgTM9hHci0SqMQB+TWe3f80K8VT8J8x3+uJjvllGlg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-darwin-x64": { + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-18.3.5.tgz", + "integrity": "sha512-Drn6jOG237AD/s6OWPt06bsMj0coGKA5Ce1y5gfLhptOGk4S4UPE/Ay5YCjq+/yhTo1gDHzCHxH0uW2X9MN9Fg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm64-gnu": { + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-18.3.5.tgz", + "integrity": "sha512-/Xd0Q3LBgJeigJqXC/Jck/9l5b+fK+FCM0nRFMXgPXrhZPhoxWouFkoYl2F1Ofr+AQf4jup4DkVTB5r98uxSCA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-gnu": { + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-18.3.5.tgz", + "integrity": "sha512-vYrikG6ff4I9cvr3Ysk3y3gjQ9cDcvr3iAr+4qqcQ4qVE+OLL2++JDS6xfPvG/TbS3GTQpyy2STRBwiHgxTeJw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-x64-msvc": { + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-18.3.5.tgz", + "integrity": "sha512-xFwKVTIXSgjdfxkpriqHv5NpmmFILTrWLEkUGSoimuRaAm1u15YWx/VmaUQ+UWuJnmgqvB/so4SMHSfNkq3ijA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.113.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.113.0.tgz", + "integrity": "sha512-Tp3XmgxwNQ9pEN9vxgJBAqdRamHibi76iowQ38O2I4PMpcvNRQNVsU2n1x1nv9yh0XoTrGFzf7cZSGxmixxrhA==", "dev": true, - "license": "ISC", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, "dependencies": { - "npm-bundled": "^5.0.0", - "npm-normalize-package-bin": "^5.0.0" + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" }, - "bin": { - "installed-package-contents": "bin/index.js" + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/installed-package-contents/node_modules/npm-normalize-package-bin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", - "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/node-gyp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-5.0.0.tgz", - "integrity": "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==", + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/package-json": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-7.0.5.tgz", - "integrity": "sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ==", + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^7.0.0", - "glob": "^13.0.0", - "hosted-git-info": "^9.0.0", - "json-parse-even-better-errors": "^5.0.0", - "proc-log": "^6.0.0", - "semver": "^7.5.3", - "spdx-expression-parse": "^4.0.0" + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/package-json/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "18 || 20 || >=22" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/package-json/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "18 || 20 || >=22" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/package-json/node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "18 || 20 || >=22" + "node": ">= 10.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/package-json/node_modules/json-parse-even-better-errors": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", - "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/package-json/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "18 || 20 || >=22" + "node": ">= 10.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/package-json/node_modules/spdx-expression-parse": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", - "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/promise-spawn": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", - "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "which": "^6.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@npmcli/promise-spawn/node_modules/isexe": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", - "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "node_modules/@parcel/watcher/node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", + "optional": true + }, + "node_modules/@pkgr/core": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=20" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" } }, - "node_modules/@npmcli/promise-spawn/node_modules/which": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", - "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.4.tgz", + "integrity": "sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^4.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@npmcli/redact": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-4.0.0.tgz", - "integrity": "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.4.tgz", + "integrity": "sha512-kFgEvkWLqt3YCgKB5re9RlIrx9bRsvyVUnaTakEpOPuLGzLpLapYxE9BufJNvPg8GjT6mB1alN4yN1NjzoeM8Q==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@npmcli/run-script": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-10.0.4.tgz", - "integrity": "sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.4.tgz", + "integrity": "sha512-JXmaOJGsL/+rsmMfutcDjxWM2fTaVgCHGoXS7nE8Z3c9NAYjGqHvXrAhMUZvMpHS/k7Mg+X7n/MVKb7NYWKKww==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^5.0.0", - "@npmcli/package-json": "^7.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "node-gyp": "^12.1.0", - "proc-log": "^6.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@nx/nx-darwin-arm64": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-18.3.5.tgz", - "integrity": "sha512-4I5UpZ/x2WO9OQyETXKjaYhXiZKUTYcLPewruRMODWu6lgTM9hHci0SqMQB+TWe3f80K8VT8J8x3+uJjvllGlg==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.4.tgz", + "integrity": "sha512-ep3Catd6sPnHTM0P4hNEvIv5arnDvk01PfyJIJ+J3wVCG1eEaPo09tvFqdtcaTrkwQy0VWR24uz+cb4IsK53Qw==", "cpu": [ - "arm64" + "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "darwin" + "freebsd" ], "engines": { - "node": ">= 10" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@nx/nx-darwin-x64": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-18.3.5.tgz", - "integrity": "sha512-Drn6jOG237AD/s6OWPt06bsMj0coGKA5Ce1y5gfLhptOGk4S4UPE/Ay5YCjq+/yhTo1gDHzCHxH0uW2X9MN9Fg==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.4.tgz", + "integrity": "sha512-LwA5ayKIpnsgXJEwWc3h8wPiS33NMIHd9BhsV92T8VetVAbGe2qXlJwNVDGHN5cOQ22R9uYvbrQir2AB+ntT2w==", "cpu": [ - "x64" + "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": ">= 10" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "18.3.5", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.4.tgz", + "integrity": "sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">= 10" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@nx/nx-linux-x64-gnu": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-18.3.5.tgz", - "integrity": "sha512-vYrikG6ff4I9cvr3Ysk3y3gjQ9cDcvr3iAr+4qqcQ4qVE+OLL2++JDS6xfPvG/TbS3GTQpyy2STRBwiHgxTeJw==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.4.tgz", + "integrity": "sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==", "cpu": [ - "x64" + "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">= 10" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@nx/nx-win32-x64-msvc": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-18.3.5.tgz", - "integrity": "sha512-xFwKVTIXSgjdfxkpriqHv5NpmmFILTrWLEkUGSoimuRaAm1u15YWx/VmaUQ+UWuJnmgqvB/so4SMHSfNkq3ijA==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.4.tgz", + "integrity": "sha512-DZaN1f0PGp/bSvKhtw50pPsnln4T13ycDq1FrDWRiHmWt1JeW+UtYg9touPFf8yt993p8tS2QjybpzKNTxYEwg==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": ">= 10" - } - }, - "node_modules/@oxc-project/types": { - "version": "0.113.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.113.0.tgz", - "integrity": "sha512-Tp3XmgxwNQ9pEN9vxgJBAqdRamHibi76iowQ38O2I4PMpcvNRQNVsU2n1x1nv9yh0XoTrGFzf7cZSGxmixxrhA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, - "node_modules/@parcel/watcher": { - "version": "2.5.6", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.3", - "is-glob": "^4.0.3", - "node-addon-api": "^7.0.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.6", - "@parcel/watcher-darwin-arm64": "2.5.6", - "@parcel/watcher-darwin-x64": "2.5.6", - "@parcel/watcher-freebsd-x64": "2.5.6", - "@parcel/watcher-linux-arm-glibc": "2.5.6", - "@parcel/watcher-linux-arm-musl": "2.5.6", - "@parcel/watcher-linux-arm64-glibc": "2.5.6", - "@parcel/watcher-linux-arm64-musl": "2.5.6", - "@parcel/watcher-linux-x64-glibc": "2.5.6", - "@parcel/watcher-linux-x64-musl": "2.5.6", - "@parcel/watcher-win32-arm64": "2.5.6", - "@parcel/watcher-win32-ia32": "2.5.6", - "@parcel/watcher-win32-x64": "2.5.6" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.6", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.4.tgz", + "integrity": "sha512-RnGxwZLN7fhMMAItnD6dZ7lvy+TI7ba+2V54UF4dhaWa/p8I/ys1E73KO6HmPmgz92ZkfD8TXS1IMV8+uhbR9g==", "cpu": [ - "arm64" + "x64" ], "dev": true, "license": "MIT", @@ -3520,17 +4647,13 @@ "linux" ], "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", - "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.4.tgz", + "integrity": "sha512-6lcI79+X8klGiGd8yHuTgQRjuuJYNggmEml+RsyN596P23l/zf9FVmJ7K0KVKkFAeYEdg0iMUKyIxiV5vebDNQ==", "cpu": [ "arm64" ], @@ -3538,39 +4661,33 @@ "license": "MIT", "optional": true, "os": [ - "linux" + "openharmony" ], "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@parcel/watcher/node_modules/node-addon-api": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/@pkgr/core": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", - "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.4.tgz", + "integrity": "sha512-wz7ohsKCAIWy91blZ/1FlpPdqrsm1xpcEOQVveWoL6+aSPKL4VUcoYmmzuLTssyZxRpEwzuIxL/GDsvpjaBtOw==", + "cpu": [ + "wasm32" + ], "dev": true, "license": "MIT", - "engines": { - "node": "^14.18.0 || >=16.0.0" + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.1" }, - "funding": { - "url": "https://opencollective.com/pkgr" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { + "node_modules/@rolldown/binding-win32-arm64-msvc": { "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.4.tgz", - "integrity": "sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.4.tgz", + "integrity": "sha512-cfiMrfuWCIgsFmcVG0IPuO6qTRHvF7NuG3wngX1RZzc6dU8FuBFb+J3MIR5WrdTNozlumfgL4cvz+R4ozBCvsQ==", "cpu": [ "arm64" ], @@ -3578,24 +4695,24 @@ "license": "MIT", "optional": true, "os": [ - "linux" + "win32" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-arm64-musl": { + "node_modules/@rolldown/binding-win32-x64-msvc": { "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.4.tgz", - "integrity": "sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.4.tgz", + "integrity": "sha512-p6UeR9y7ht82AH57qwGuFYn69S6CZ7LLKdCKy/8T3zS9VTrJei2/CGsTUV45Da4Z9Rbhc7G4gyWQ/Ioamqn09g==", "cpu": [ - "arm64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" + "win32" ], "engines": { "node": "^20.19.0 || >=22.12.0" @@ -3609,9 +4726,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", - "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.1.tgz", + "integrity": "sha512-JnBB8MdXj45cajvTuO5FmPlvFVJRQgvrz1uSEl3NwqFnReAPGwb8EanbGi4z2nRaqLzjJSv5/JmycoTKlRZxHA==", "cpu": [ "arm" ], @@ -3623,9 +4740,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", - "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.61.1.tgz", + "integrity": "sha512-Jx2g7iSjw4AOT0HDPHM9RV3GNjRXwybWtSFZiZAYUTjUwjVrYIwq3kBf+LnhqJlzXFAqTAh2F7IGI+O568exPw==", "cpu": [ "arm64" ], @@ -3637,9 +4754,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", - "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.61.1.tgz", + "integrity": "sha512-0F1L/Z3Eqv8mT2n3dCpeO8GcTvHvVqkP5/t6DMsn0KzhYVcg+s7Ncl5DS8qjKYEeio6Az0Gt6nyBORay5qIlCA==", "cpu": [ "arm64" ], @@ -3651,9 +4768,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", - "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.61.1.tgz", + "integrity": "sha512-qLttcH871ujY4YcVfUSShhOw+CsoTatYz8gRbHO7Bb92QH059/P0y5do1KMs41fY0BpD2x4AJH/gID0zFiqVKQ==", "cpu": [ "x64" ], @@ -3665,9 +4782,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", - "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.61.1.tgz", + "integrity": "sha512-fUI4RapGE0Oh3mb8mgfvC1O2nU1RpDZUKnDQm3xB1Ipg7C2wTs5Kstz7G2uWK99a8S2yTMq8/P4uycwNa0nJyw==", "cpu": [ "arm64" ], @@ -3679,9 +4796,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", - "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.61.1.tgz", + "integrity": "sha512-H5YrdvJaDtI/U9/emrD4b++xkvp3y/JvOe4rizHbxvkyMfRS/CiRYdji+Pl8D0brEaNFWUh1drQxgAGIl6Xudw==", "cpu": [ "x64" ], @@ -3693,9 +4810,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", - "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.61.1.tgz", + "integrity": "sha512-Q8CBCCQtDFrYtXoeUXSrnFXKOnyUhx6bz+SkL6A0E7V8kAiCJ5pamq1WtbfpVGhR5TSpXY6ak3avmDc5fHTyJA==", "cpu": [ "arm" ], @@ -3707,9 +4824,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", - "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.61.1.tgz", + "integrity": "sha512-nwnhk1581l0FBVellGcVCAT0Oi06onEA3WB53sf01VO3I0UPBkMH9sXONYME2K0ovXcNayJfNtHfm6mpJElatQ==", "cpu": [ "arm" ], @@ -3721,9 +4838,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", - "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.61.1.tgz", + "integrity": "sha512-x5Xr49hwt3hdW75UOZm3395YwwzPyauktslv29KpWL/T+vVAzoT3azLcTWv0eMciBNrx+DYjH4paehHoLpPvpg==", "cpu": [ "arm64" ], @@ -3734,9 +4851,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", - "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.61.1.tgz", + "integrity": "sha512-unMS3H73DpaoPyyEVPjGKleM/s0mkmsauTENpw4INQY8y4+IuLNjkueQ5QCtC0D3N38Y38yhAU8OoZ20S2Tm6w==", "cpu": [ "arm64" ], @@ -3748,9 +4865,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", - "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.61.1.tgz", + "integrity": "sha512-zNZzGRnAhwjFEYmvphJRV5XaQGjs62cCmeYYHUT//NbvEnHauw+I85nGG+SiVg5ld4GX8D1IbKIX+ozITQnhMQ==", "cpu": [ "loong64" ], @@ -3762,9 +4879,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", - "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.61.1.tgz", + "integrity": "sha512-LdpWGL8X209B2SIvWjqlc8VZgM6PKfontSerGepuldQmHYrAOtnMCXeJkxXGbC+PPZVOuu5czJo7fNV6aeW8rQ==", "cpu": [ "loong64" ], @@ -3776,9 +4893,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", - "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.61.1.tgz", + "integrity": "sha512-EC5kTtNaNGOmbMGqar8dvJy6y/hg99GAwjfBz++pxZhQATXGcRjd6c5en5wcbru0vkRmiMGsQKdMJOOf6sza4g==", "cpu": [ "ppc64" ], @@ -3790,9 +4907,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", - "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.61.1.tgz", + "integrity": "sha512-8hiwp6D4acEcNK78I4rP0/XtS1sknWIAMJBPdR4l6zUtyTm5KiTDr5bXmWt4foY7nAN7AThDHgkLIEZOWKbzWw==", "cpu": [ "ppc64" ], @@ -3804,9 +4921,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", - "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.61.1.tgz", + "integrity": "sha512-10dh/h/BqA7DuMPWSxkR8uks18FRwnwOEqr5zOTEl+NOwP/OMzKX8OFR/Of9xxDA7D5qef1Nzar5WDD2kCCr1g==", "cpu": [ "riscv64" ], @@ -3818,9 +4935,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", - "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.61.1.tgz", + "integrity": "sha512-YKJ5lg35DP17gcAOggnihe+APw9HLyj1Xn7gsmGumBJAUDa6NGXNixJzmkWLhcK9TOuuyQjdamzvJefkO7qHZQ==", "cpu": [ "riscv64" ], @@ -3832,9 +4949,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", - "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.61.1.tgz", + "integrity": "sha512-Mlil5G2Jj6a7B3LWGctg+XPL9vdXYuzCtNXfxOQ0nPjc2m6ueUktocPGH9bnAM0bNRKb/bAWTujUU7IJQdQA+g==", "cpu": [ "s390x" ], @@ -3859,9 +4976,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", - "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.61.1.tgz", + "integrity": "sha512-qy5pBvZbqNFheBz61R1rzsezjm0J7O2oNGoWtGoY89SZYLUfxAJTBAqDChqAIdB4rCiIbi9nF7yZ83GnNiLwSw==", "cpu": [ "x64" ], @@ -3873,9 +4990,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", - "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.61.1.tgz", + "integrity": "sha512-E83TXjI4zm0+5f2qO+UOudaCYIhYwpJ5jq6YCZNIZ+6CbfhKrkAGezeiASBL9ElxAxFsRS9ZhESv8mfnj6TKeg==", "cpu": [ "x64" ], @@ -3887,9 +5004,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", - "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.61.1.tgz", + "integrity": "sha512-fbWnKqVkjrJN38vNe3ahkbk6iejS/3b0Nt7EEtPpE6RBacZcGXNKbzfHN3GUUlXOPghUg0j6XUGrtjX9z1sIvA==", "cpu": [ "arm64" ], @@ -3901,9 +5018,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", - "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.61.1.tgz", + "integrity": "sha512-ArMl38iVAbk0New1ogihQNY6iphLi4ZaRsa037gUzv5yeKPY8TD3Dmy4x2RNC1VztU/uqm+G+/RwFrSka3Oy2g==", "cpu": [ "arm64" ], @@ -3915,9 +5032,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", - "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.61.1.tgz", + "integrity": "sha512-0mYtjHS9ucAbcATycCNK9IGBk/cCe/ma7EmSLGZdsxnOA8cjRIyU04wDpVAD9NiOfLUR9KTxdiO53uOkherqjQ==", "cpu": [ "ia32" ], @@ -3929,9 +5046,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", - "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.61.1.tgz", + "integrity": "sha512-gK1iCEPfpoSG9wfBihXxvBMi8ZfcWffYkEsC/Eih+iFENTaewvNcrEQ69lIOWYO5pePHKLHHO7nq5AILGO/HQQ==", "cpu": [ "x64" ], @@ -3943,9 +5060,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", - "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.1.tgz", + "integrity": "sha512-X+zaP2x+j4RXGfbp/seSoRHWnPxzApilDszisZxbYH5C/jTxFhCtDNdPGZb9lJyYPs24wGxruPF7Y+sIXt9Gzw==", "cpu": [ "x64" ], @@ -3958,18 +5075,20 @@ }, "node_modules/@scarf/scarf": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", "hasInstallScript": true, "license": "Apache-2.0" }, "node_modules/@schematics/angular": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-21.2.9.tgz", - "integrity": "sha512-1renEbBZz9Yw3A0GUOJ6x6E1jd2Vu/fX5tEGiFNbIoWaNwa71SlFTvKKqaYxiYQkrpc7oexVJ2ymuvOfgTbI1w==", + "version": "21.2.14", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-21.2.14.tgz", + "integrity": "sha512-rIEdtNTdCCTwuo7B4tMoq5qmbLXdBgmW6Ays1hyno//4OE+HFtvlWZd+hl6KceEyN00IcZ2HRaPnfd71E1JnoA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "21.2.9", - "@angular-devkit/schematics": "21.2.9", + "@angular-devkit/core": "21.2.14", + "@angular-devkit/schematics": "21.2.14", "jsonc-parser": "3.3.1" }, "engines": { @@ -3978,68 +5097,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { - "version": "21.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.2.9.tgz", - "integrity": "sha512-04rdOGEzjLWFHlyAwqtuikginFeQ2jfXS5HqqKNP0VtG6Uu9NUDAEW5UDvXgqkEMfCDwGZbmg2iRHxp3AmAKVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.18.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@schematics/angular/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@schematics/angular/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@sigstore/bundle": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-4.0.0.tgz", @@ -4054,9 +5111,9 @@ } }, "node_modules/@sigstore/core": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.0.tgz", - "integrity": "sha512-kxHrDQ9YgfrWUSXU0cjsQGv8JykOFZQ9ErNKbFPWzk3Hgpwu8x2hHrQ9IdA8yl+j9RTLTC3sAF3Tdq1IQCP4oA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.1.tgz", + "integrity": "sha512-qRsxPnCrbC/puegGxKuynfnxgLiHqWStrSjxkoB4YKqq3Z3s4cyZyj42ZdWFAEblNP65C+rBH8EuREHIXoi83g==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4106,14 +5163,14 @@ } }, "node_modules/@sigstore/verify": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.0.tgz", - "integrity": "sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.1.tgz", + "integrity": "sha512-qv7+G3J2cc6wwFj3yKvXOamzqhMwSk1ogPGmhpS8iXllcPrJaIIBA+4HbttlHVu1pqWTdmaCH/WE7UOC51kdoA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", + "@sigstore/core": "^3.2.1", "@sigstore/protobuf-specs": "^0.5.0" }, "engines": { @@ -4151,6 +5208,8 @@ }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", "dev": true, "license": "MIT" }, @@ -4193,15 +5252,6 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@swimlane/ngx-charts/node_modules/d3-time-format": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", - "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-time": "1 - 2" - } - }, "node_modules/@trivago/prettier-plugin-sort-imports": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-6.0.2.tgz", @@ -4245,21 +5295,29 @@ }, "node_modules/@tsconfig/node10": { "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true, "license": "MIT" }, @@ -4326,8 +5384,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/angular": { "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@types/angular/-/angular-1.5.11.tgz", + "integrity": "sha512-Nth2ys1RPMZfOQIs8yveTGBa/5dJ4PhSznm87dinYtQBKFzg7CBO4YqNWGuPibSkQ/uBbcYlnbBFHH7EdeMI3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4336,11 +5407,15 @@ }, "node_modules/@types/canvas-confetti": { "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@types/canvas-confetti/-/canvas-confetti-1.9.0.tgz", + "integrity": "sha512-aBGj/dULrimR1XDZLtG9JwxX1b4HPRF6CX9Yfwh3NvstZEm1ZL7RBnel4keCPSqs1ANRu1u2Aoz9R+VmtjYuTg==", "dev": true, "license": "MIT" }, "node_modules/@types/cors": { "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", "dev": true, "license": "MIT", "dependencies": { @@ -4349,6 +5424,8 @@ }, "node_modules/@types/d3": { "version": "3.5.53", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.53.tgz", + "integrity": "sha512-8yKQA9cAS6+wGsJpBysmnhlaaxlN42Qizqkw+h2nILSlS+MAG2z4JdO6p+PJrJ+ACvimkmLJL281h157e52psQ==", "dev": true, "license": "MIT" }, @@ -4360,13 +5437,15 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "license": "MIT" }, "node_modules/@types/file-saver": { "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.7.tgz", + "integrity": "sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==", "dev": true, "license": "MIT" }, @@ -4379,6 +5458,8 @@ }, "node_modules/@types/jasminewd2": { "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.13.tgz", + "integrity": "sha512-aJ3wj8tXMpBrzQ5ghIaqMisD8C3FIrcO6sDKHqFbuqAsI7yOxj0fA7MrRCPLZHIVUjERIwsMmGn/vB0UQ9u0Hg==", "dev": true, "license": "MIT", "dependencies": { @@ -4387,6 +5468,8 @@ }, "node_modules/@types/jquery": { "version": "1.10.45", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-1.10.45.tgz", + "integrity": "sha512-JvoVtPbu1wrcOldn5gvuyJqr7DLX6I657N68Fqj5S7AUutdYZqabQjfP7dY6Gee7/Afo1uajwcORVlQfnsjkLQ==", "dev": true, "license": "MIT" }, @@ -4397,12 +5480,16 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.23", + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.33", + "version": "20.19.42", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.42.tgz", + "integrity": "sha512-5L7SUaFC1RyDraj2yRhyBzHTobyXHmohD100CChNtyPyleoq37Mqab5Gn8XEKI04dfN/oqPdpHk38MgcQWHbZg==", "dev": true, "license": "MIT", "dependencies": { @@ -4411,11 +5498,15 @@ }, "node_modules/@types/q": { "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha512-qYi3YV9inU/REEfxwVcGZzbS3KG/Xs90lv0Pr+lDtuVjBPGd1A+eciXzVSaRvLify132BfcvhvEjeVahrUl0Ug==", "dev": true, "license": "MIT" }, "node_modules/@types/selenium-webdriver": { "version": "3.0.26", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.26.tgz", + "integrity": "sha512-dyIGFKXfUFiwkMfNGn1+F6b80ZjR3uSYv1j6xVJSDlft5waZ2cwkHW4e7zNzvq7hiEackcgvBpmnXZrI1GltPg==", "dev": true, "license": "MIT" }, @@ -4437,17 +5528,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz", - "integrity": "sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==", - "dev": true, + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", + "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/type-utils": "8.60.1", - "@typescript-eslint/utils": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/type-utils": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -4460,32 +5550,21 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.60.1", + "@typescript-eslint/parser": "^8.61.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.1.tgz", - "integrity": "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==", - "dev": true, + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.0.tgz", + "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3" }, "engines": { @@ -4501,13 +5580,13 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.0.tgz", - "integrity": "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", + "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.57.0", - "@typescript-eslint/types": "^8.57.0", + "@typescript-eslint/tsconfig-utils": "^8.61.0", + "@typescript-eslint/types": "^8.61.0", "debug": "^4.4.3" }, "engines": { @@ -4518,18 +5597,17 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz", - "integrity": "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==", - "dev": true, + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", + "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1" + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4540,9 +5618,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.0.tgz", - "integrity": "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", + "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4552,19 +5630,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz", - "integrity": "sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==", - "dev": true, + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", + "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1", - "@typescript-eslint/utils": "8.60.1", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -4581,9 +5658,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.1.tgz", - "integrity": "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz", + "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4594,16 +5671,15 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz", - "integrity": "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==", - "dev": true, + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", + "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.60.1", - "@typescript-eslint/tsconfig-utils": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/project-service": "8.61.0", + "@typescript-eslint/tsconfig-utils": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -4621,50 +5697,10 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.1.tgz", - "integrity": "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.60.1", - "@typescript-eslint/types": "^8.60.1", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz", - "integrity": "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, "license": "MIT", "engines": { "node": "18 || 20 || >=22" @@ -4674,7 +5710,6 @@ "version": "5.0.6", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -4687,7 +5722,6 @@ "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.5" @@ -4700,16 +5734,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.1.tgz", - "integrity": "sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==", - "dev": true, + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz", + "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1" + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4724,13 +5757,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz", - "integrity": "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==", - "dev": true, + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", + "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -4745,7 +5777,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", - "dev": true, "license": "Apache-2.0", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" @@ -4769,6 +5800,8 @@ }, "node_modules/@worktile/gantt": { "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@worktile/gantt/-/gantt-18.0.5.tgz", + "integrity": "sha512-LCcWaFBmeg5u9cVDEmREHdR+qJJHE3Ld4VxdoJpTXfhDkx2f19tp0wMR9MkwOLRwwTCx/5gGJ1kTbz4P0Zfc1Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -4788,22 +5821,26 @@ "dev": true, "license": "BSD-2-Clause" }, - "node_modules/accepts": { - "version": "1.3.8", + "node_modules/abbrev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, + "license": "ISC", "engines": { - "node": ">= 0.6" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/accepts/node_modules/negotiator": { - "version": "0.6.3", + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "dev": true, "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, "engines": { "node": ">= 0.6" } @@ -4830,7 +5867,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.4", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", "dev": true, "license": "MIT", "dependencies": { @@ -4841,7 +5880,9 @@ } }, "node_modules/adm-zip": { - "version": "0.5.16", + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.17.tgz", + "integrity": "sha512-+Ut8d9LLqwEvHHJl1+PIHqoyDxFgVN847JTVM3Izi3xHDWPE4UtzzXysMZQs64DMcrJfBeS/uoEP4AD3HQHnQQ==", "dev": true, "license": "MIT", "engines": { @@ -4928,6 +5969,8 @@ }, "node_modules/angular-calendar": { "version": "0.31.1", + "resolved": "https://registry.npmjs.org/angular-calendar/-/angular-calendar-0.31.1.tgz", + "integrity": "sha512-pjSIpoAaUzS/gx+14eOr4hPZhlQ8HxpiZypCSGqJNptq5PD+vOdVQ3h/Aaqnk86GraVcAQPXqfu64MtdKwTVNw==", "license": "MIT", "dependencies": { "@scarf/scarf": "^1.1.1", @@ -4988,70 +6031,10 @@ "typescript-eslint": "^8.0.0" } }, - "node_modules/angular-eslint/node_modules/@angular-devkit/core": { - "version": "21.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.2.14.tgz", - "integrity": "sha512-RSOWXB9bFc2nwRWMxbIT0RbSNFUrwfBo4N5MNxbyQ69Ndc0gVm3h+3ArHv0qotH4d+pJYbm5ttXu8YqR2kc0CA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.18.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/angular-eslint/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/angular-eslint/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/angular-markdown-filter": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/angular-markdown-filter/-/angular-markdown-filter-1.3.2.tgz", + "integrity": "sha512-2dr3IB/d9dyLTH36nE61Qkxm078sOpHvpd4Q863eXEgrwsre8YySxWsgaq1qooY3P7C7wQ1LhFGvh5rAA25wnA==", "license": "MIT", "dependencies": { "showdown": "^1.2.3" @@ -5070,6 +6053,8 @@ }, "node_modules/angular-nvd3": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/angular-nvd3/-/angular-nvd3-1.0.9.tgz", + "integrity": "sha512-FcGYVXeNejlDj+Yr6g3ydRT+kuLAzKY/KMuc4eiLJbSvRcSqfLJtrFZi6wFXGhW3OlbLHvCjAeFzDvTac3gNTQ==", "license": "MIT", "dependencies": { "angular": "^1.x", @@ -5106,23 +6091,28 @@ } }, "node_modules/ansi-regex": { - "version": "5.0.1", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { - "version": "4.3.0", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, "node_modules/any-promise": { @@ -5134,6 +6124,8 @@ }, "node_modules/anymatch": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "license": "ISC", "dependencies": { @@ -5157,6 +6149,43 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -5187,8 +6216,33 @@ "dev": true, "license": "MIT" }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/array-uniq": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, "license": "MIT", "engines": { @@ -5197,6 +6251,8 @@ }, "node_modules/asn1": { "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5205,6 +6261,8 @@ }, "node_modules/assert-plus": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, "license": "MIT", "engines": { @@ -5213,11 +6271,15 @@ }, "node_modules/asynckit": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true, "license": "MIT" }, "node_modules/autoprefixer": { "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha512-WKExI/eSGgGAkWAO+wMVdFObZV7hQen54UpD1kCCTN3tvlL3W1jL4+lPP/M7MwoP7Q4RHzKtO3JQ4HxYEcd+xQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5231,6 +6293,8 @@ }, "node_modules/autoprefixer/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, "license": "MIT", "engines": { @@ -5239,6 +6303,8 @@ }, "node_modules/autoprefixer/node_modules/ansi-styles": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true, "license": "MIT", "engines": { @@ -5247,6 +6313,9 @@ }, "node_modules/autoprefixer/node_modules/browserslist": { "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha512-qHJblDE2bXVRYzuDetv/wAeHOJyO97+9wxC1cdCtyzgNuSozOyRCiiLaCR1f71AN66lQdVVBipWm63V+a7bPOw==", + "deprecated": "Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools.", "dev": true, "license": "MIT", "dependencies": { @@ -5259,6 +6328,8 @@ }, "node_modules/autoprefixer/node_modules/chalk": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, "license": "MIT", "dependencies": { @@ -5274,30 +6345,18 @@ }, "node_modules/autoprefixer/node_modules/chalk/node_modules/supports-color": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" } }, - "node_modules/autoprefixer/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/autoprefixer/node_modules/has-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/autoprefixer/node_modules/postcss": { "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "license": "MIT", "dependencies": { @@ -5312,6 +6371,8 @@ }, "node_modules/autoprefixer/node_modules/source-map": { "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -5320,6 +6381,8 @@ }, "node_modules/autoprefixer/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, "license": "MIT", "dependencies": { @@ -5329,19 +6392,10 @@ "node": ">=0.10.0" } }, - "node_modules/autoprefixer/node_modules/supports-color": { - "version": "3.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^1.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/aws-sign2": { "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5350,6 +6404,8 @@ }, "node_modules/aws4": { "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", "dev": true, "license": "MIT" }, @@ -5365,10 +6421,14 @@ }, "node_modules/balanced-match": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, "node_modules/base64-arraybuffer": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", "license": "MIT", "engines": { "node": ">= 0.6.0" @@ -5376,6 +6436,8 @@ }, "node_modules/base64id": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true, "license": "MIT", "engines": { @@ -5383,9 +6445,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.10.33", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz", - "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==", + "version": "2.10.34", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.34.tgz", + "integrity": "sha512-IMDedajPifLnHNY0X9n8hKxRTQ6/eTHwr5bDo04WnuqxyKw6LYtQywCuuqPZwhl3aBXMvQpJov42GLCwRRdQzw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5397,6 +6459,8 @@ }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5426,6 +6490,8 @@ }, "node_modules/binary-extensions": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", "engines": { @@ -5437,6 +6503,8 @@ }, "node_modules/blocking-proxy": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", + "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", "dev": true, "license": "MIT", "dependencies": { @@ -5450,63 +6518,28 @@ } }, "node_modules/body-parser": { - "version": "1.20.5", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", - "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.15.1", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.4.24", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/body-parser/node_modules/on-finished": { - "version": "2.4.1", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "dev": true, "license": "MIT", "dependencies": { - "ee-first": "1.1.1" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/boolbase": { @@ -5528,6 +6561,8 @@ }, "node_modules/braces": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { @@ -5573,6 +6608,8 @@ }, "node_modules/browserstack": { "version": "1.6.1", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.6.1.tgz", + "integrity": "sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw==", "dev": true, "license": "MIT", "dependencies": { @@ -5581,6 +6618,8 @@ }, "node_modules/browserstack/node_modules/agent-base": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "license": "MIT", "dependencies": { @@ -5592,6 +6631,8 @@ }, "node_modules/browserstack/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5600,6 +6641,8 @@ }, "node_modules/browserstack/node_modules/https-proxy-agent": { "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -5619,6 +6662,8 @@ }, "node_modules/bytes": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, "license": "MIT", "engines": { @@ -5716,10 +6761,14 @@ }, "node_modules/calendar-utils": { "version": "0.10.4", + "resolved": "https://registry.npmjs.org/calendar-utils/-/calendar-utils-0.10.4.tgz", + "integrity": "sha512-gBK4xCJ42yjaUKwuUha6cZOfxAmGzvSgbdAaX3xLRioeKbYoOK1x1qeD6dch72rsMZlTgATPbBBx42bnkStqgQ==", "license": "MIT" }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5732,6 +6781,8 @@ }, "node_modules/call-bound": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { @@ -5747,6 +6798,8 @@ }, "node_modules/callsites": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "license": "MIT", "engines": { "node": ">=6" @@ -5754,6 +6807,8 @@ }, "node_modules/camelcase": { "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "license": "MIT", "engines": { "node": ">=6" @@ -5770,14 +6825,16 @@ } }, "node_modules/caniuse-db": { - "version": "1.0.30001769", + "version": "1.0.30001797", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001797.tgz", + "integrity": "sha512-wV1BrKS/ZUWGpO22bqFgYx0d51CVR5lgWNdvtF1Aib78DNXVyeIZUG2mMTr9Vuul2Qab/YNs94S3rRmeE9cQ8g==", "dev": true, "license": "CC-BY-4.0" }, "node_modules/caniuse-lite": { - "version": "1.0.30001793", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", - "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "version": "1.0.30001797", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001797.tgz", + "integrity": "sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w==", "dev": true, "funding": [ { @@ -5797,11 +6854,31 @@ }, "node_modules/canonical-path": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-0.0.2.tgz", + "integrity": "sha512-y8EIEvL+IW81S4hRQWCRFtly+g1cc1G+wxHpjhYR9jI2+JJjWiaKnkH8mmvNHOMOAd9fzgARDO3AEzjuR51qaA==", "dev": true, "license": "MIT" }, + "node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/canvas-confetti": { "version": "1.9.4", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz", + "integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==", "license": "ISC", "funding": { "type": "donate", @@ -5810,21 +6887,47 @@ }, "node_modules/caseless": { "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true, "license": "Apache-2.0" }, "node_modules/chalk": { - "version": "4.1.2", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=10" + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "engines": { + "node": ">=4" } }, "node_modules/chardet": { @@ -5835,26 +6938,19 @@ "license": "MIT" }, "node_modules/chokidar": { - "version": "3.6.0", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^5.0.0" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 20.19.0" }, "funding": { "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" } }, "node_modules/chownr": { @@ -5913,105 +7009,112 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">= 12" } }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", - "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", + "node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "get-east-asian-width": "^1.5.0", - "strip-ansi": "^7.1.2" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "node_modules/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "node_modules/cliui/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, - "license": "ISC", - "engines": { - "node": ">= 12" - } + "license": "MIT" }, - "node_modules/cliui": { - "version": "8.0.1", + "node_modules/cliui/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/color-convert": { - "version": "2.0.1", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "color-name": "1.1.3" } }, "node_modules/color-name": { - "version": "1.1.4", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "license": "MIT" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -6019,8 +7122,20 @@ "dev": true, "license": "MIT" }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/combined-stream": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "license": "MIT", "dependencies": { @@ -6032,6 +7147,8 @@ }, "node_modules/commander": { "version": "2.6.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", + "integrity": "sha512-PhbTMT+ilDXZKqH8xbvuUY2ZEQNef0Q7DKxgoEKb4ccytsdvVVJmYqR0sGbi96nxU6oGrwEIQnclpK2NBZuQlg==", "dev": true, "license": "MIT", "engines": { @@ -6051,10 +7168,14 @@ }, "node_modules/concat-map": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, "node_modules/concurrently": { "version": "3.6.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-3.6.1.tgz", + "integrity": "sha512-/+ugz+gwFSEfTGUxn0KHkY+19XPRTXR8+7oUK/HxgiN1n7FjeJmkrbSiXAJfyQ0zORgJYPaenmymwon51YXH9Q==", "dev": true, "license": "MIT", "dependencies": { @@ -6076,127 +7197,111 @@ "node": ">=4.0.0" } }, - "node_modules/concurrently/node_modules/ansi-styles": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/concurrently/node_modules/chalk": { - "version": "2.4.2", + "node_modules/concurrently/node_modules/date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/concurrently/node_modules/chalk/node_modules/has-flag": { - "version": "3.0.0", + "node_modules/confbox": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" }, "engines": { - "node": ">=4" + "node": ">= 0.10.0" } }, - "node_modules/concurrently/node_modules/color-convert": { - "version": "1.9.3", + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/concurrently/node_modules/color-name": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/concurrently/node_modules/date-fns": { - "version": "1.30.1", - "dev": true, - "license": "MIT" - }, - "node_modules/concurrently/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" + "ms": "2.0.0" } }, - "node_modules/concurrently/node_modules/has-flag": { - "version": "1.0.0", + "node_modules/connect/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "3.2.3", + "node_modules/connect/node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^1.0.0" + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=0.8.0" + "node": ">= 0.8" } }, - "node_modules/confbox": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", - "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, - "node_modules/connect": { - "version": "3.7.0", + "node_modules/connect/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "dev": true, "license": "MIT", "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" + "ee-first": "1.1.1" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 0.8" } }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", + "node_modules/connect/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">= 0.6" } }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", + "optional": true }, "node_modules/content-disposition": { "version": "1.1.0", @@ -6214,6 +7319,8 @@ }, "node_modules/content-type": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, "license": "MIT", "engines": { @@ -6272,6 +7379,8 @@ }, "node_modules/cookie": { "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, "license": "MIT", "engines": { @@ -6289,7 +7398,9 @@ } }, "node_modules/core-js": { - "version": "3.48.0", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", + "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -6298,11 +7409,15 @@ } }, "node_modules/core-util-is": { - "version": "1.0.2", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, "node_modules/cors": { "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", "dev": true, "license": "MIT", "dependencies": { @@ -6318,9 +7433,9 @@ } }, "node_modules/cosmiconfig": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", - "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", + "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", "dev": true, "license": "MIT", "dependencies": { @@ -6362,23 +7477,17 @@ "typescript": ">=5" } }, - "node_modules/cosmiconfig-typescript-loader/node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, "node_modules/create-require": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true, "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -6391,6 +7500,8 @@ }, "node_modules/css-line-break": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", "license": "MIT", "dependencies": { "utrie": "^1.0.2" @@ -6441,11 +7552,15 @@ }, "node_modules/custom-event": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", "dev": true, "license": "MIT" }, "node_modules/d3": { "version": "3.5.17", + "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", + "integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg==", "license": "BSD-3-Clause" }, "node_modules/d3-array": { @@ -6589,6 +7704,12 @@ "d3-path": "1" } }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, "node_modules/d3-scale": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", @@ -6627,27 +7748,27 @@ } }, "node_modules/d3-time": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz", - "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-array": "2" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", "license": "ISC", "dependencies": { - "d3-time": "1 - 3" + "d3-array": "2 - 3" }, "engines": { "node": ">=12" } }, - "node_modules/d3-time/node_modules/d3-array": { + "node_modules/d3-time-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", + "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-time": "1 - 2" + } + }, + "node_modules/d3-time-format/node_modules/d3-array": { "version": "2.12.1", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", @@ -6656,6 +7777,21 @@ "internmap": "^1.0.0" } }, + "node_modules/d3-time-format/node_modules/d3-time": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz", + "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "2" + } + }, + "node_modules/d3-time-format/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, "node_modules/d3-timer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", @@ -6686,6 +7822,8 @@ }, "node_modules/dashdash": { "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, "license": "MIT", "dependencies": { @@ -6697,6 +7835,8 @@ }, "node_modules/date-fns": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", "license": "MIT", "funding": { "type": "github", @@ -6705,6 +7845,8 @@ }, "node_modules/date-format": { "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", "dev": true, "license": "MIT", "engines": { @@ -6713,6 +7855,8 @@ }, "node_modules/debug": { "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -6728,17 +7872,36 @@ }, "node_modules/decamelize": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/deep-is": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "license": "MIT" }, "node_modules/del": { "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha512-Z4fzpbIRjOu7lO5jCETSWoqUDVe0IPOlfugBsF6suen2LKDlVb4QZpKEM9P+buNJ4KI1eN7I083w/pbKUpsrWQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6754,43 +7917,10 @@ "node": ">=0.10.0" } }, - "node_modules/del/node_modules/array-union": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/arrify": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/del/node_modules/pify": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, "license": "MIT", "engines": { @@ -6799,6 +7929,9 @@ }, "node_modules/del/node_modules/rimraf": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -6810,14 +7943,25 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, "node_modules/depd": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", "engines": { @@ -6826,6 +7970,8 @@ }, "node_modules/destroy": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "license": "MIT", "engines": { @@ -6835,7 +7981,8 @@ }, "node_modules/detect-libc": { "version": "2.1.2", - "dev": true, + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", "optional": true, "engines": { @@ -6844,6 +7991,8 @@ }, "node_modules/di": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", "dev": true, "license": "MIT" }, @@ -6854,8 +8003,20 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dijkstrajs": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", "license": "MIT" }, "node_modules/dlv": { @@ -6867,6 +8028,8 @@ }, "node_modules/dom-serialize": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6959,6 +8122,8 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, "license": "MIT", "dependencies": { @@ -6972,6 +8137,8 @@ }, "node_modules/ecc-jsbn": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, "license": "MIT", "dependencies": { @@ -6981,22 +8148,28 @@ }, "node_modules/ee-first": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true, "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.368", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.368.tgz", - "integrity": "sha512-7RckJJK4uESJF9PxvfMWd3TGqIiieUTG4HxnKaKuIpGbcr+r2ZEB3g2gAhCP3Fqm42vJSzLfgab9eva/C4/XVw==", + "version": "1.5.369", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.369.tgz", + "integrity": "sha512-XM22K9FNaaCOvMMrBn1caIc8v0g6+pKt660ZbfQqUZvfil0hEzr8ZoiY7VcSLGM3L/x3rz5PqZrk+bKOOmVM9w==", "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/encodeurl": { - "version": "1.0.2", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", "engines": { @@ -7027,12 +8200,61 @@ }, "node_modules/engine.io-parser": { "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" } }, + "node_modules/engine.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/enhanced-resolve": { "version": "5.23.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.23.0.tgz", @@ -7049,6 +8271,8 @@ }, "node_modules/ent": { "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.2.tgz", + "integrity": "sha512-kKvD1tO6BM+oK9HzCPpUdRb4vKFQY/FPTFmurMvh6LlN68VMrdj77w8yp51/kDbpkFOS9J8w5W6zIzgM2H8/hw==", "dev": true, "license": "MIT", "dependencies": { @@ -7076,6 +8300,8 @@ }, "node_modules/env-paths": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "license": "MIT", "engines": { @@ -7104,6 +8330,8 @@ }, "node_modules/error-ex": { "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7112,6 +8340,8 @@ }, "node_modules/es-define-property": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", "engines": { @@ -7120,6 +8350,8 @@ }, "node_modules/es-errors": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, "license": "MIT", "engines": { @@ -7127,7 +8359,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.1.1", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "dev": true, "license": "MIT", "dependencies": { @@ -7137,8 +8371,21 @@ "node": ">= 0.4" } }, + "node_modules/es-toolkit": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.47.0.tgz", + "integrity": "sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw==", + "dev": true, + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/es5-shim": { "version": "4.6.7", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.6.7.tgz", + "integrity": "sha512-jg21/dmlrNQI7JyyA2w7n+yifSxBng0ZralnSfVZjoCawgNTCnS+yBCyVM9DL5itm7SUnDGgv7hcq2XCZX4iRQ==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -7146,11 +8393,15 @@ }, "node_modules/es6-promise": { "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", "dev": true, "license": "MIT" }, "node_modules/es6-promisify": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7201,6 +8452,8 @@ }, "node_modules/escalade": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -7209,17 +8462,19 @@ }, "node_modules/escape-html": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true, "license": "MIT" }, "node_modules/escape-string-regexp": { - "version": "4.0.0", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.8.0" } }, "node_modules/eslint": { @@ -7368,6 +8623,8 @@ }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -7392,6 +8649,21 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", @@ -7402,6 +8674,52 @@ "concat-map": "0.0.1" } }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/eslint-scope": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", @@ -7430,18 +8748,28 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { - "node": ">=10.13.0" + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "license": "MIT" }, "node_modules/eslint/node_modules/minimatch": { @@ -7453,7 +8781,19 @@ "brace-expansion": "^1.1.7" }, "engines": { - "node": "*" + "node": "*" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/espree": { @@ -7487,6 +8827,8 @@ }, "node_modules/esquery": { "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" @@ -7497,6 +8839,8 @@ }, "node_modules/esrecurse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" @@ -7507,6 +8851,8 @@ }, "node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -7523,6 +8869,8 @@ }, "node_modules/etag": { "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, "license": "MIT", "engines": { @@ -7531,6 +8879,8 @@ }, "node_modules/eventemitter3": { "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true, "license": "MIT" }, @@ -7548,9 +8898,9 @@ } }, "node_modules/eventsource-parser": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.8.tgz", - "integrity": "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.0.tgz", + "integrity": "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==", "dev": true, "license": "MIT", "engines": { @@ -7559,6 +8909,8 @@ }, "node_modules/exit": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { "node": ">= 0.8.0" @@ -7634,243 +8986,6 @@ "express": ">= 4.11" } }, - "node_modules/express/node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", - "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/finalhandler": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express/node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express/node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/express/node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express/node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/type-is": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", - "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", - "dev": true, - "license": "MIT", - "dependencies": { - "content-type": "^2.0.0", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express/node_modules/type-is/node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/exsolve": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", @@ -7880,11 +8995,15 @@ }, "node_modules/extend": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true, "license": "MIT" }, "node_modules/extsprintf": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "dev": true, "engines": [ "node >=0.6.0" @@ -7893,6 +9012,8 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, "node_modules/fast-diff": { @@ -7919,12 +9040,29 @@ "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "license": "MIT" }, "node_modules/fast-uri": { @@ -7956,6 +9094,8 @@ }, "node_modules/fdir": { "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", "engines": { "node": ">=12.0.0" @@ -7983,51 +9123,49 @@ }, "node_modules/file-saver": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", "license": "MIT" }, "node_modules/fill-range": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/find-up": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "license": "MIT", "dependencies": { "locate-path": "^6.0.0", @@ -8082,6 +9220,8 @@ }, "node_modules/font-awesome": { "version": "4.7.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", + "integrity": "sha512-U6kGnykA/6bFmg1M/oT9EkFeIYv7JlX3bozwQJWiiLz6L0w3F5vBVPxHlwyX/vtNq1ckcpRKOB9f2Qal/VtFpg==", "license": "(OFL-1.1 AND MIT)", "engines": { "node": ">=0.10.3" @@ -8089,6 +9229,8 @@ }, "node_modules/forever-agent": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -8097,6 +9239,8 @@ }, "node_modules/form-data": { "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8108,6 +9252,29 @@ "node": ">= 0.12" } }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -8118,6 +9285,31 @@ "node": ">= 0.6" } }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/fs-minipass": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", @@ -8133,7 +9325,9 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "dev": true, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "devOptional": true, "license": "ISC" }, "node_modules/fsevents": { @@ -8153,12 +9347,91 @@ }, "node_modules/function-bind": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", + "optional": true + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -8171,15 +9444,17 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-east-asian-width": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", - "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", "dev": true, "license": "MIT", "engines": { @@ -8191,6 +9466,8 @@ }, "node_modules/get-intrinsic": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8214,6 +9491,8 @@ }, "node_modules/get-proto": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, "license": "MIT", "dependencies": { @@ -8226,6 +9505,8 @@ }, "node_modules/getpass": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, "license": "MIT", "dependencies": { @@ -8254,7 +9535,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -8272,14 +9553,15 @@ } }, "node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, "node_modules/glob-to-regexp": { @@ -8293,7 +9575,7 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -8304,7 +9586,7 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -8314,31 +9596,21 @@ } }, "node_modules/global-directory": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", - "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-5.0.0.tgz", + "integrity": "sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==", "dev": true, "license": "MIT", "dependencies": { - "ini": "4.1.1" + "ini": "6.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/global-directory/node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -8351,8 +9623,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha512-HJRTIH2EeH44ka+LWig+EqT2ONSYpVlNfx6pyd592/VF1TbfljJ7elwie7oSwcViLGqOdWocSdu2txwBF9bjmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/globby/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/gopd": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", "engines": { @@ -8364,11 +9666,15 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, "license": "ISC" }, "node_modules/har-schema": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", "dev": true, "license": "ISC", "engines": { @@ -8377,6 +9683,9 @@ }, "node_modules/har-validator": { "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", "dev": true, "license": "MIT", "dependencies": { @@ -8406,11 +9715,15 @@ }, "node_modules/har-validator/node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/has-ansi": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", "dev": true, "license": "MIT", "dependencies": { @@ -8422,6 +9735,8 @@ }, "node_modules/has-ansi/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, "license": "MIT", "engines": { @@ -8429,14 +9744,19 @@ } }, "node_modules/has-flag": { - "version": "4.0.0", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/has-symbols": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", "engines": { @@ -8448,6 +9768,8 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "license": "MIT", "dependencies": { @@ -8460,8 +9782,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, "node_modules/hasown": { - "version": "2.0.2", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "dev": true, "license": "MIT", "dependencies": { @@ -8472,9 +9803,9 @@ } }, "node_modules/hono": { - "version": "4.12.23", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.23.tgz", - "integrity": "sha512-eIaZ9qDgu7XV0pxOCrg7/WhnQ6Ivm22UcxhXx/A3dcbqbbYgBEkc6e/J/s7j2tS96zoB0S9VBdLwQNCWwUo4LA==", + "version": "4.12.25", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.25.tgz", + "integrity": "sha512-2NFaIyNVgJmBs/ecmtGzlmluTFs5cHEWGTdu0t1HBwYzoGXOL5nUQBRMXsXWla5i4KkG//QMzVP88m1+I3fdAQ==", "dev": true, "license": "MIT", "engines": { @@ -8506,11 +9837,15 @@ }, "node_modules/html-escaper": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, "license": "MIT" }, "node_modules/html2canvas": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", "license": "MIT", "dependencies": { "css-line-break": "^2.1.0", @@ -8522,6 +9857,8 @@ }, "node_modules/html5-qrcode": { "version": "2.3.8", + "resolved": "https://registry.npmjs.org/html5-qrcode/-/html5-qrcode-2.3.8.tgz", + "integrity": "sha512-jsr4vafJhwoLVEDW3n1KvPnCCXWaQfRng0/EEYk1vNcQGcG/htAdhJX0be8YyqMoSz7+hZvOZSTAepsabiuhiQ==", "license": "Apache-2.0" }, "node_modules/htmlparser2": { @@ -8566,6 +9903,8 @@ }, "node_modules/http-errors": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8583,16 +9922,10 @@ "url": "https://opencollective.com/express" } }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/http-proxy": { "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8620,6 +9953,8 @@ }, "node_modules/http-signature": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8648,6 +9983,8 @@ }, "node_modules/husky": { "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true, "license": "MIT", "bin": { @@ -8678,9 +10015,9 @@ } }, "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "license": "MIT", "engines": { "node": ">= 4" @@ -8740,6 +10077,8 @@ }, "node_modules/immediate": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", "license": "MIT" }, "node_modules/immutable": { @@ -8751,6 +10090,8 @@ }, "node_modules/import-fresh": { "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -8765,6 +10106,8 @@ }, "node_modules/import-fresh/node_modules/resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "license": "MIT", "engines": { "node": ">=4" @@ -8783,6 +10126,8 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "license": "MIT", "engines": { "node": ">=0.8.19" @@ -8790,7 +10135,10 @@ }, "node_modules/inflight": { "version": "1.0.6", - "dev": true, + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "devOptional": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -8799,6 +10147,8 @@ }, "node_modules/inherits": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, "node_modules/ini": { @@ -8812,13 +10162,18 @@ } }, "node_modules/internmap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", - "license": "ISC" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } }, "node_modules/ip": { "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", "dev": true, "license": "MIT" }, @@ -8844,11 +10199,15 @@ }, "node_modules/is-arrayish": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, "license": "MIT" }, "node_modules/is-binary-path": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", "dependencies": { @@ -8859,11 +10218,13 @@ } }, "node_modules/is-core-module": { - "version": "2.16.1", + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "hasown": "^2.0.3" }, "engines": { "node": ">= 0.4" @@ -8874,20 +10235,33 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-glob": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -8911,6 +10285,8 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", "engines": { @@ -8929,6 +10305,8 @@ }, "node_modules/is-path-cwd": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha512-cnS56eR9SPAscL77ik76ATVqoPARTqPIVkMDVxRaWH06zT+6+CzIroYRJ0VVvm0Z1zfAvxvz9i/D3Ppjaqt5Nw==", "dev": true, "license": "MIT", "engines": { @@ -8937,6 +10315,8 @@ }, "node_modules/is-path-in-cwd": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8946,8 +10326,10 @@ "node": ">=0.10.0" } }, - "node_modules/is-path-in-cwd/node_modules/is-path-inside": { + "node_modules/is-path-inside": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==", "dev": true, "license": "MIT", "dependencies": { @@ -8957,8 +10339,30 @@ "node": ">=0.10.0" } }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", "dependencies": { @@ -8976,6 +10380,8 @@ }, "node_modules/is-typedarray": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true, "license": "MIT" }, @@ -9000,6 +10406,8 @@ }, "node_modules/isbinaryfile": { "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", "dev": true, "license": "MIT", "engines": { @@ -9011,15 +10419,21 @@ }, "node_modules/isexe": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, "node_modules/isstream": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true, "license": "MIT" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -9045,6 +10459,8 @@ }, "node_modules/istanbul-lib-report": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9056,8 +10472,33 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/istanbul-lib-source-maps": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9073,6 +10514,8 @@ }, "node_modules/istanbul-lib-source-maps/node_modules/istanbul-lib-coverage": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -9081,6 +10524,8 @@ }, "node_modules/istanbul-lib-source-maps/node_modules/make-dir": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "license": "MIT", "dependencies": { @@ -9093,6 +10538,8 @@ }, "node_modules/istanbul-lib-source-maps/node_modules/pify": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, "license": "MIT", "engines": { @@ -9101,6 +10548,9 @@ }, "node_modules/istanbul-lib-source-maps/node_modules/rimraf": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -9112,6 +10562,8 @@ }, "node_modules/istanbul-lib-source-maps/node_modules/semver": { "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "license": "ISC", "bin": { @@ -9120,6 +10572,8 @@ }, "node_modules/istanbul-lib-source-maps/node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -9128,6 +10582,8 @@ }, "node_modules/istanbul-reports": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9140,6 +10596,8 @@ }, "node_modules/jasmine": { "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha512-KbdGQTf5jbZgltoHs31XGiChAPumMSY64OZMWLNYnEnMfG5uwGBhffePwuskexjT+/Jea/gU3qAU8344hNohSw==", "dev": true, "license": "MIT", "dependencies": { @@ -9153,32 +10611,32 @@ }, "node_modules/jasmine-core": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.1.1.tgz", + "integrity": "sha512-lmUfT5XcK9KKvt3lLYzn93hc4MGzlUBowExFVgzbSW0ZCrdeyS574dfsyfRhxbg81Wj4gk+RxUiTnj7KBfDA1g==", "dev": true, "license": "MIT" }, "node_modules/jasmine-spec-reporter": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-5.0.2.tgz", + "integrity": "sha512-6gP1LbVgJ+d7PKksQBc2H0oDGNRQI3gKUsWlswKaQ2fif9X5gzhQcgM5+kiJGCQVurOG09jqNhk7payggyp5+g==", "dev": true, "license": "Apache-2.0", "dependencies": { "colors": "1.4.0" } }, - "node_modules/jasmine-spec-reporter/node_modules/colors": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/jasmine/node_modules/jasmine-core": { "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha512-SNkOkS+/jMZvLhuSx1fjhcNWUC/KG6oVyFUGkSBEr9n1axSNduWU8GlI7suaHXr4yxjet6KjrUZxUTE5WzzWwQ==", "dev": true, "license": "MIT" }, "node_modules/jasminewd2": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha512-Rn0nZe4rfDhzA63Al3ZGh0E+JTmM6ESZYXJGKuqKGZObsAB9fwXPD03GjtIEvJBDOhN94T5MzbwZSqzFHSQPzg==", "dev": true, "license": "MIT", "engines": { @@ -9193,9 +10651,9 @@ "license": "MIT" }, "node_modules/jiti": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", - "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "devOptional": true, "license": "MIT", "bin": { @@ -9220,11 +10678,15 @@ }, "node_modules/js-base64": { "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/js-tokens": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, "license": "MIT" }, @@ -9252,6 +10714,8 @@ }, "node_modules/jsbn": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true, "license": "MIT" }, @@ -9276,26 +10740,32 @@ }, "node_modules/json-parse-better-errors": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", - "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", + "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", "dev": true, "license": "MIT", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/json-schema": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true, "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, "license": "MIT" }, @@ -9308,15 +10778,21 @@ }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true, "license": "ISC" }, "node_modules/json5": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", "bin": { @@ -9333,6 +10809,16 @@ "dev": true, "license": "MIT" }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -9345,6 +10831,8 @@ }, "node_modules/jsprim": { "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, "license": "MIT", "dependencies": { @@ -9359,6 +10847,8 @@ }, "node_modules/jszip": { "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "license": "(MIT OR GPL-3.0-or-later)", "dependencies": { "lie": "~3.3.0", @@ -9367,28 +10857,10 @@ "setimmediate": "^1.0.5" } }, - "node_modules/jszip/node_modules/readable-stream": { - "version": "2.3.8", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/jszip/node_modules/string_decoder": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/karma": { "version": "6.4.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.4.tgz", + "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", "dev": true, "license": "MIT", "dependencies": { @@ -9426,6 +10898,8 @@ }, "node_modules/karma-chrome-launcher": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz", + "integrity": "sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9434,6 +10908,8 @@ }, "node_modules/karma-chrome-launcher/node_modules/which": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "license": "ISC", "dependencies": { @@ -9445,6 +10921,8 @@ }, "node_modules/karma-coverage-istanbul-reporter": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-3.0.3.tgz", + "integrity": "sha512-wE4VFhG/QZv2Y4CdAYWDbMmcAHeS926ZIji4z+FkB2aF/EposRb6DP6G5ncT/wXhqUfAb/d7kZrNKPonbvsATw==", "dev": true, "license": "MIT", "dependencies": { @@ -9484,6 +10962,8 @@ }, "node_modules/karma-jasmine": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-4.0.2.tgz", + "integrity": "sha512-ggi84RMNQffSDmWSyyt4zxzh2CQGwsxvYYsprgyR1j8ikzIduEdOlcLvXjZGwXG/0j41KUXOWsUCBfbEHPWP9g==", "dev": true, "license": "MIT", "dependencies": { @@ -9498,6 +10978,8 @@ }, "node_modules/karma-jasmine-html-reporter": { "version": "1.7.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz", + "integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -9508,9 +10990,62 @@ }, "node_modules/karma-jasmine/node_modules/jasmine-core": { "version": "3.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz", + "integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==", "dev": true, "license": "MIT" }, + "node_modules/karma/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/karma/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/karma/node_modules/body-parser": { + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/karma/node_modules/brace-expansion": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", @@ -9522,8 +11057,35 @@ "concat-map": "0.0.1" } }, + "node_modules/karma/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/karma/node_modules/cliui": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "license": "ISC", "dependencies": { @@ -9532,6 +11094,105 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/karma/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/karma/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/karma/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/karma/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/karma/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/karma/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/karma/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/karma/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/karma/node_modules/minimatch": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", @@ -9545,16 +11206,111 @@ "node": "*" } }, + "node_modules/karma/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/karma/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/karma/node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/karma/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/karma/node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" } }, "node_modules/karma/node_modules/wrap-ansi": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { @@ -9571,6 +11327,8 @@ }, "node_modules/karma/node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "license": "MIT", "dependencies": { @@ -9586,6 +11344,16 @@ "node": ">=10" } }, + "node_modules/karma/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -9597,6 +11365,8 @@ }, "node_modules/levn": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", @@ -9608,6 +11378,8 @@ }, "node_modules/lie": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "license": "MIT", "dependencies": { "immediate": "~3.0.5" @@ -9628,6 +11400,8 @@ }, "node_modules/lines-and-columns": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, "license": "MIT" }, @@ -9649,19 +11423,6 @@ "node": ">=20.0.0" } }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/listr2/node_modules/ansi-styles": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", @@ -9707,22 +11468,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/listr2/node_modules/wrap-ansi": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", @@ -9772,6 +11517,8 @@ }, "node_modules/load-json-file": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, "license": "MIT", "dependencies": { @@ -9786,6 +11533,8 @@ }, "node_modules/load-json-file/node_modules/parse-json": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, "license": "MIT", "dependencies": { @@ -9816,6 +11565,8 @@ }, "node_modules/locate-path": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "license": "MIT", "dependencies": { "p-locate": "^5.0.0" @@ -9840,50 +11591,10 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", - "license": "MIT" - }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true, + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "license": "MIT" }, "node_modules/log-symbols": { @@ -9923,19 +11634,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/log-update/node_modules/ansi-styles": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", @@ -9956,22 +11654,6 @@ "dev": true, "license": "MIT" }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/log-update/node_modules/slice-ansi": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", @@ -10007,22 +11689,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/log-update/node_modules/wrap-ansi": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", @@ -10043,6 +11709,8 @@ }, "node_modules/log4js": { "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -10058,6 +11726,8 @@ }, "node_modules/lottie-web": { "version": "5.13.0", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.13.0.tgz", + "integrity": "sha512-+gfBXl6sxXMPe8tKQm7qzLnUy5DUPJPKIyRHwtpCpyUEYjHYRJC/5gjUvdkuO2c3JllrPtHXH5UJJK8LRYl5yQ==", "license": "MIT" }, "node_modules/lru-cache": { @@ -10082,6 +11752,8 @@ }, "node_modules/make-dir": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "license": "MIT", "dependencies": { @@ -10096,13 +11768,15 @@ }, "node_modules/make-error": { "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true, "license": "ISC" }, "node_modules/make-fetch-happen": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.5.tgz", - "integrity": "sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg==", + "version": "15.0.6", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.6.tgz", + "integrity": "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw==", "dev": true, "license": "ISC", "dependencies": { @@ -10137,6 +11811,8 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, "license": "MIT", "engines": { @@ -10144,15 +11820,19 @@ } }, "node_modules/media-typer": { - "version": "0.3.0", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/memorystream": { "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", "dev": true, "engines": { "node": ">= 0.10.0" @@ -10223,6 +11903,8 @@ }, "node_modules/mime": { "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, "license": "MIT", "bin": { @@ -10233,7 +11915,9 @@ } }, "node_modules/mime-db": { - "version": "1.52.0", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", "engines": { @@ -10241,14 +11925,20 @@ } }, "node_modules/mime-types": { - "version": "2.1.35", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/mimic-function": { @@ -10264,6 +11954,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "9.0.9", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", @@ -10282,6 +11985,8 @@ }, "node_modules/minimist": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "license": "MIT", "funding": { @@ -10423,6 +12128,8 @@ }, "node_modules/mkdirp": { "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", "dependencies": { @@ -10466,6 +12173,8 @@ }, "node_modules/moment": { "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "license": "MIT", "engines": { "node": "*" @@ -10505,12 +12214,14 @@ }, "node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/msgpackr": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.10.tgz", - "integrity": "sha512-iCZNq+HszvF+fC3anCm4nBmWEnbeIAfpDs6IStAEKhQ2YSgkjzVG2FF9XJqwwQh5bH3N9OUTUt4QwVN6MLMLtA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.12.1.tgz", + "integrity": "sha512-4EUH9tQHnMmEgzW/MdAP0KIfa1T9AF+htl0ffe2n5vb2EKn9y2co8ccpgWko6S52Jy1PQZKwRnx5/KkYjtd9MQ==", "dev": true, "license": "MIT", "optional": true, @@ -10519,9 +12230,9 @@ } }, "node_modules/msgpackr-extract": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", - "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.4.tgz", + "integrity": "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -10533,12 +12244,12 @@ "download-msgpackr-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" } }, "node_modules/mute-stream": { @@ -10563,6 +12274,13 @@ "thenify-all": "^1.0.0" } }, + "node_modules/nan": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.27.0.tgz", + "integrity": "sha512-hC+0LidcL3XE4rp1C4H54KujgXKzbfyTngZTwBByQxsOxCEKZT0MPQ4hOKUH2jU1OYstqdDH4onyHPDzcV0XdQ==", + "license": "MIT", + "optional": true + }, "node_modules/nanoid": { "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", @@ -10584,6 +12302,8 @@ }, "node_modules/natural-compare": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "license": "MIT" }, "node_modules/negotiator": { @@ -10612,6 +12332,8 @@ }, "node_modules/ng-flex-layout": { "version": "17.3.7-beta.1", + "resolved": "https://registry.npmjs.org/ng-flex-layout/-/ng-flex-layout-17.3.7-beta.1.tgz", + "integrity": "sha512-MTjlQUldB/hEsn0DY/RoY2SKBQoyaKltlOOFjCjH2OfcYA3COHhkJS3PZe9NAjR7TBDb9Ve989m18bSucRzACQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -10648,6 +12370,8 @@ }, "node_modules/ngx-lottie": { "version": "11.0.2", + "resolved": "https://registry.npmjs.org/ngx-lottie/-/ngx-lottie-11.0.2.tgz", + "integrity": "sha512-sQhCTxfrzWpjN2HVFCSyAQYQg8ZjZVtO1xIhOkrJNHY3/TR/zZkVrhakWcaM5bVxyA7gfUnK3ox+iK59Yd8Bsw==", "license": "MIT", "dependencies": { "@scarf/scarf": "^1.1.1", @@ -10693,10 +12417,31 @@ "license": "MIT", "optional": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-gyp": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.3.0.tgz", - "integrity": "sha512-QNcUWM+HgJplcPzBvFBZ9VXacyGZ4+VTOb80PwWR+TlVzoHbRKULNEzpRsnaoxG3Wzr7Qh7BYxGDU3CbKib2Yg==", + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.4.0.tgz", + "integrity": "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw==", "dev": true, "license": "MIT", "dependencies": { @@ -10734,16 +12479,6 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, - "node_modules/node-gyp/node_modules/abbrev": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", - "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/node-gyp/node_modules/isexe": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", @@ -10754,22 +12489,6 @@ "node": ">=20" } }, - "node_modules/node-gyp/node_modules/nopt": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", - "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^4.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/node-gyp/node_modules/undici": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.26.0.tgz", @@ -10806,8 +12525,56 @@ "node": ">=18" } }, + "node_modules/nopt": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^4.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/normalize-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", "engines": { @@ -10816,6 +12583,8 @@ }, "node_modules/normalize-range": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, "license": "MIT", "engines": { @@ -10835,16 +12604,6 @@ "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm-bundled/node_modules/npm-normalize-package-bin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", - "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/npm-install-checks": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", @@ -10859,13 +12618,13 @@ } }, "node_modules/npm-normalize-package-bin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", - "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", + "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", "dev": true, "license": "ISC", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm-package-arg": { @@ -10914,16 +12673,6 @@ "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", - "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/npm-registry-fetch": { "version": "19.1.1", "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", @@ -10946,6 +12695,8 @@ }, "node_modules/npm-run-all2": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-7.0.2.tgz", + "integrity": "sha512-7tXR+r9hzRNOPNTvXegM+QzCuMjzUIIq66VDunL6j60O4RrExx32XUhlrS7UK4VcdGw5/Wxzb3kfNcFix9JKDA==", "dev": true, "license": "MIT", "dependencies": { @@ -10971,6 +12722,8 @@ }, "node_modules/npm-run-all2/node_modules/ansi-styles": { "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", "engines": { @@ -10982,6 +12735,8 @@ }, "node_modules/npm-run-all2/node_modules/isexe": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz", + "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -10990,6 +12745,8 @@ }, "node_modules/npm-run-all2/node_modules/which": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { @@ -11002,6 +12759,20 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -11017,11 +12788,15 @@ }, "node_modules/num2fraction": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==", "dev": true, "license": "MIT" }, "node_modules/nvd3": { "version": "1.8.6", + "resolved": "https://registry.npmjs.org/nvd3/-/nvd3-1.8.6.tgz", + "integrity": "sha512-YGQ9hAQHuQCF0JmYkT2GhNMHb5pA+vDfQj6C2GdpQPzdRPj/srPG3mh/3fZzUFt+at1NusLk/RqICUWkxm4viQ==", "license": "Apache-2.0", "peerDependencies": { "d3": "^3.4.4" @@ -11029,6 +12804,8 @@ }, "node_modules/oauth-sign": { "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -11037,7 +12814,9 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "dev": true, + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11055,6 +12834,8 @@ }, "node_modules/object-inspect": { "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { @@ -11065,7 +12846,9 @@ } }, "node_modules/on-finished": { - "version": "2.3.0", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "license": "MIT", "dependencies": { @@ -11077,7 +12860,9 @@ }, "node_modules/once": { "version": "1.4.0", - "dev": true, + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "devOptional": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -11101,6 +12886,8 @@ }, "node_modules/optionator": { "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "license": "MIT", "dependencies": { "deep-is": "^0.1.3", @@ -11137,19 +12924,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/ora/node_modules/chalk": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", @@ -11163,39 +12937,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ora/node_modules/string-width": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", - "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.5.0", - "strip-ansi": "^7.1.2" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/ordered-binary": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.1.tgz", @@ -11206,6 +12947,8 @@ }, "node_modules/os-tmpdir": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, "license": "MIT", "engines": { @@ -11214,6 +12957,8 @@ }, "node_modules/p-limit": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -11227,6 +12972,8 @@ }, "node_modules/p-locate": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "license": "MIT", "dependencies": { "p-limit": "^3.0.2" @@ -11253,6 +13000,8 @@ }, "node_modules/p-try": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "license": "MIT", "engines": { "node": ">=6" @@ -11292,10 +13041,14 @@ }, "node_modules/pako": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "license": "(MIT AND Zlib)" }, "node_modules/parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -11316,6 +13069,8 @@ }, "node_modules/parse-json": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "dependencies": { @@ -11333,6 +13088,8 @@ }, "node_modules/parse-json/node_modules/json-parse-even-better-errors": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, "license": "MIT" }, @@ -11410,6 +13167,8 @@ }, "node_modules/parseurl": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, "license": "MIT", "engines": { @@ -11418,6 +13177,8 @@ }, "node_modules/path-exists": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "license": "MIT", "engines": { "node": ">=8" @@ -11425,7 +13186,9 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", - "dev": true, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11433,11 +13196,15 @@ }, "node_modules/path-is-inside": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", "dev": true, "license": "(WTFPL OR MIT)" }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "license": "MIT", "engines": { "node": ">=8" @@ -11445,6 +13212,8 @@ }, "node_modules/path-parse": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, "license": "MIT" }, @@ -11486,6 +13255,19 @@ "url": "https://opencollective.com/express" } }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/path2d-polyfill": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz", @@ -11518,11 +13300,15 @@ }, "node_modules/performance-now": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "dev": true, "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -11539,7 +13325,9 @@ } }, "node_modules/pidtree": { - "version": "0.6.0", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.1.tgz", + "integrity": "sha512-e0F9AOF1JMrCfBsyJOwU9lNvQ0WtXTq0j/4jk0BQ5JSI9VAybPXmDpPRw/2FQ3e5d3ZFN1mLh7jW99m/jjaptw==", "dev": true, "license": "MIT", "bin": { @@ -11551,6 +13339,8 @@ }, "node_modules/pify": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, "license": "MIT", "engines": { @@ -11559,6 +13349,8 @@ }, "node_modules/pinkie": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "dev": true, "license": "MIT", "engines": { @@ -11567,6 +13359,8 @@ }, "node_modules/pinkie-promise": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dev": true, "license": "MIT", "dependencies": { @@ -11623,6 +13417,8 @@ }, "node_modules/pngjs": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", "license": "MIT", "engines": { "node": ">=10.13.0" @@ -11630,6 +13426,8 @@ }, "node_modules/positioning": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/positioning/-/positioning-2.0.1.tgz", + "integrity": "sha512-DsAgM42kV/ObuwlRpAzDTjH9E8fGKkMDJHWFX+kfNXSxh7UCCQxEmdjv/Ws5Ft1XDnt3JT8fIDYeKNSE2TbttA==", "license": "MIT" }, "node_modules/postcss": { @@ -11817,6 +13615,8 @@ }, "node_modules/postcss-scss": { "version": "0.1.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-0.1.9.tgz", + "integrity": "sha512-FkLd8Pxci394edesXqewjAd6eMnYGUPK5bgkYbYHX7YPeJDcuaKMuHnXsd0i3tnXJOLTuX+L+m3edda1IKMrbQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11825,6 +13625,8 @@ }, "node_modules/postcss-scss/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, "license": "MIT", "engines": { @@ -11833,6 +13635,8 @@ }, "node_modules/postcss-scss/node_modules/ansi-styles": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true, "license": "MIT", "engines": { @@ -11841,6 +13645,8 @@ }, "node_modules/postcss-scss/node_modules/chalk": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, "license": "MIT", "dependencies": { @@ -11856,30 +13662,18 @@ }, "node_modules/postcss-scss/node_modules/chalk/node_modules/supports-color": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" } }, - "node_modules/postcss-scss/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/postcss-scss/node_modules/has-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/postcss-scss/node_modules/postcss": { "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "license": "MIT", "dependencies": { @@ -11894,6 +13688,8 @@ }, "node_modules/postcss-scss/node_modules/source-map": { "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -11902,6 +13698,8 @@ }, "node_modules/postcss-scss/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, "license": "MIT", "dependencies": { @@ -11911,17 +13709,6 @@ "node": ">=0.10.0" } }, - "node_modules/postcss-scss/node_modules/supports-color": { - "version": "3.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^1.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/postcss-selector-parser": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", @@ -11938,11 +13725,15 @@ }, "node_modules/postcss-value-parser": { "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true, "license": "MIT" }, "node_modules/prelude-ls": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "license": "MIT", "engines": { "node": ">= 0.8.0" @@ -11989,6 +13780,8 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, "node_modules/promise-retry": { @@ -12007,6 +13800,9 @@ }, "node_modules/protractor": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz", + "integrity": "sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==", + "deprecated": "We have news to share - Protractor is deprecated and will reach end-of-life by Summer 2023. To learn more and find out about other options please refer to this post on the Angular blog. Thank you for using and contributing to Protractor. https://goo.gle/state-of-e2e-in-angular", "dev": true, "license": "MIT", "dependencies": { @@ -12036,6 +13832,8 @@ }, "node_modules/protractor/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, "license": "MIT", "engines": { @@ -12044,6 +13842,8 @@ }, "node_modules/protractor/node_modules/ansi-styles": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true, "license": "MIT", "engines": { @@ -12052,6 +13852,8 @@ }, "node_modules/protractor/node_modules/chalk": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, "license": "MIT", "dependencies": { @@ -12067,6 +13869,8 @@ }, "node_modules/protractor/node_modules/cliui": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "license": "ISC", "dependencies": { @@ -12077,6 +13881,8 @@ }, "node_modules/protractor/node_modules/cliui/node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { @@ -12085,6 +13891,8 @@ }, "node_modules/protractor/node_modules/cliui/node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { @@ -12094,16 +13902,10 @@ "node": ">=8" } }, - "node_modules/protractor/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/protractor/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", "dependencies": { @@ -12114,8 +13916,20 @@ "node": ">=8" } }, + "node_modules/protractor/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/protractor/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", "dependencies": { @@ -12127,6 +13941,8 @@ }, "node_modules/protractor/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { @@ -12141,6 +13957,8 @@ }, "node_modules/protractor/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", "dependencies": { @@ -12152,6 +13970,8 @@ }, "node_modules/protractor/node_modules/source-map": { "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -12160,14 +13980,56 @@ }, "node_modules/protractor/node_modules/source-map-support": { "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "license": "MIT", "dependencies": { "source-map": "^0.5.6" } }, + "node_modules/protractor/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/protractor/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, "license": "MIT", "dependencies": { @@ -12179,6 +14041,8 @@ }, "node_modules/protractor/node_modules/supports-color": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, "license": "MIT", "engines": { @@ -12187,11 +14051,15 @@ }, "node_modules/protractor/node_modules/y18n": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true, "license": "ISC" }, "node_modules/protractor/node_modules/yargs": { "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "license": "MIT", "dependencies": { @@ -12213,6 +14081,8 @@ }, "node_modules/protractor/node_modules/yargs-parser": { "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "license": "ISC", "dependencies": { @@ -12239,6 +14109,8 @@ }, "node_modules/psl": { "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", "dev": true, "license": "MIT", "dependencies": { @@ -12250,6 +14122,8 @@ }, "node_modules/psl/node_modules/punycode": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { @@ -12258,6 +14132,8 @@ }, "node_modules/punycode": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true, "license": "MIT" }, @@ -12275,6 +14151,8 @@ }, "node_modules/qjobs": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", "dev": true, "license": "MIT", "engines": { @@ -12283,6 +14161,8 @@ }, "node_modules/qrcode": { "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", "license": "MIT", "dependencies": { "dijkstrajs": "^1.0.1", @@ -12296,8 +14176,19 @@ "node": ">=10.13.0" } }, + "node_modules/qrcode/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/qrcode/node_modules/cliui": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -12307,6 +14198,8 @@ }, "node_modules/qrcode/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -12316,8 +14209,19 @@ "node": ">=8" } }, + "node_modules/qrcode/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/qrcode/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -12328,6 +14232,8 @@ }, "node_modules/qrcode/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -12341,6 +14247,8 @@ }, "node_modules/qrcode/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -12349,12 +14257,42 @@ "node": ">=8" } }, + "node_modules/qrcode/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/qrcode/node_modules/y18n": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "license": "ISC" }, "node_modules/qrcode/node_modules/yargs": { "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "license": "MIT", "dependencies": { "cliui": "^6.0.0", @@ -12375,6 +14313,8 @@ }, "node_modules/qrcode/node_modules/yargs-parser": { "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "license": "ISC", "dependencies": { "camelcase": "^5.0.0", @@ -12440,6 +14380,8 @@ }, "node_modules/range-parser": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "license": "MIT", "engines": { @@ -12447,28 +14389,19 @@ } }, "node_modules/raw-body": { - "version": "2.5.3", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "dev": true, "license": "MIT", "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", + "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" }, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, "node_modules/read-cache": { @@ -12493,6 +14426,8 @@ }, "node_modules/read-package-json-fast": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", + "integrity": "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==", "dev": true, "license": "ISC", "dependencies": { @@ -12503,76 +14438,68 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/read-pkg": { - "version": "3.0.0", + "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", "dev": true, "license": "MIT", - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "dev": true, - "license": "ISC" - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", + "node_modules/read-package-json-fast/node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/read-pkg/node_modules/path-type": { + "node_modules/read-pkg": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, "license": "MIT", "dependencies": { - "pify": "^3.0.0" + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "dev": true, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">= 20.19.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/reflect-metadata": { @@ -12584,6 +14511,9 @@ }, "node_modules/request": { "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -12609,7 +14539,30 @@ "uuid": "^3.3.2" }, "engines": { - "node": ">= 6" + "node": ">= 6" + } + }, + "node_modules/request/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/request/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" } }, "node_modules/request/node_modules/qs": { @@ -12624,6 +14577,8 @@ }, "node_modules/require-directory": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -12631,6 +14586,8 @@ }, "node_modules/require-from-string": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "license": "MIT", "engines": { @@ -12639,21 +14596,26 @@ }, "node_modules/require-main-filename": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "license": "ISC" }, "node_modules/requires-port": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true, "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -12669,6 +14631,8 @@ }, "node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", "engines": { @@ -12715,11 +14679,16 @@ }, "node_modules/rfdc": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "license": "MIT" }, "node_modules/rimraf": { "version": "3.0.2", - "dev": true, + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "devOptional": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -12764,13 +14733,13 @@ } }, "node_modules/rollup": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", - "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.1.tgz", + "integrity": "sha512-I4KW6iuRpuu2uHBLraZ1wNZe0DP7lnRha+VJ9tNaYVaVgKhW0aI3h4RYnoRPeql0flHm/Co55b7snEDcOfOJrA==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@types/estree": "1.0.9" }, "bin": { "rollup": "dist/bin/rollup" @@ -12780,48 +14749,34 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.2", - "@rollup/rollup-android-arm64": "4.60.2", - "@rollup/rollup-darwin-arm64": "4.60.2", - "@rollup/rollup-darwin-x64": "4.60.2", - "@rollup/rollup-freebsd-arm64": "4.60.2", - "@rollup/rollup-freebsd-x64": "4.60.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", - "@rollup/rollup-linux-arm-musleabihf": "4.60.2", - "@rollup/rollup-linux-arm64-gnu": "4.60.2", - "@rollup/rollup-linux-arm64-musl": "4.60.2", - "@rollup/rollup-linux-loong64-gnu": "4.60.2", - "@rollup/rollup-linux-loong64-musl": "4.60.2", - "@rollup/rollup-linux-ppc64-gnu": "4.60.2", - "@rollup/rollup-linux-ppc64-musl": "4.60.2", - "@rollup/rollup-linux-riscv64-gnu": "4.60.2", - "@rollup/rollup-linux-riscv64-musl": "4.60.2", - "@rollup/rollup-linux-s390x-gnu": "4.60.2", - "@rollup/rollup-linux-x64-gnu": "4.60.2", - "@rollup/rollup-linux-x64-musl": "4.60.2", - "@rollup/rollup-openbsd-x64": "4.60.2", - "@rollup/rollup-openharmony-arm64": "4.60.2", - "@rollup/rollup-win32-arm64-msvc": "4.60.2", - "@rollup/rollup-win32-ia32-msvc": "4.60.2", - "@rollup/rollup-win32-x64-gnu": "4.60.2", - "@rollup/rollup-win32-x64-msvc": "4.60.2", + "@rollup/rollup-android-arm-eabi": "4.61.1", + "@rollup/rollup-android-arm64": "4.61.1", + "@rollup/rollup-darwin-arm64": "4.61.1", + "@rollup/rollup-darwin-x64": "4.61.1", + "@rollup/rollup-freebsd-arm64": "4.61.1", + "@rollup/rollup-freebsd-x64": "4.61.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.61.1", + "@rollup/rollup-linux-arm-musleabihf": "4.61.1", + "@rollup/rollup-linux-arm64-gnu": "4.61.1", + "@rollup/rollup-linux-arm64-musl": "4.61.1", + "@rollup/rollup-linux-loong64-gnu": "4.61.1", + "@rollup/rollup-linux-loong64-musl": "4.61.1", + "@rollup/rollup-linux-ppc64-gnu": "4.61.1", + "@rollup/rollup-linux-ppc64-musl": "4.61.1", + "@rollup/rollup-linux-riscv64-gnu": "4.61.1", + "@rollup/rollup-linux-riscv64-musl": "4.61.1", + "@rollup/rollup-linux-s390x-gnu": "4.61.1", + "@rollup/rollup-linux-x64-gnu": "4.61.1", + "@rollup/rollup-linux-x64-musl": "4.61.1", + "@rollup/rollup-openbsd-x64": "4.61.1", + "@rollup/rollup-openharmony-arm64": "4.61.1", + "@rollup/rollup-win32-arm64-msvc": "4.61.1", + "@rollup/rollup-win32-ia32-msvc": "4.61.1", + "@rollup/rollup-win32-x64-gnu": "4.61.1", + "@rollup/rollup-win32-x64-msvc": "4.61.1", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", - "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -12839,13 +14794,6 @@ "node": ">= 18" } }, - "node_modules/router/node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true, - "license": "MIT" - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -12872,6 +14820,8 @@ }, "node_modules/rx": { "version": "2.3.24", + "resolved": "https://registry.npmjs.org/rx/-/rx-2.3.24.tgz", + "integrity": "sha512-Ue4ZB7Dzbn2I9sIj8ws536nOP2S53uypyCkCz9q0vlYD5Kn6/pu4dE+wt2ZfFzd9m73hiYKnnCb1OyKqc+MRkg==", "dev": true }, "node_modules/rxjs": { @@ -12885,10 +14835,14 @@ }, "node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, "node_modules/safe-regex-test": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", "dependencies": { @@ -12905,56 +14859,36 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT" }, "node_modules/sass": { - "version": "1.97.3", + "version": "1.100.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz", + "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", "dev": true, "license": "MIT", "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", + "chokidar": "^5.0.0", + "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { "sass": "sass.js" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.19.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" } }, - "node_modules/sass/node_modules/chokidar": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/sass/node_modules/readdirp": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/saucelabs": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", + "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", "dev": true, "dependencies": { "https-proxy-agent": "^2.2.1" @@ -12965,6 +14899,8 @@ }, "node_modules/saucelabs/node_modules/agent-base": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "license": "MIT", "dependencies": { @@ -12976,6 +14912,8 @@ }, "node_modules/saucelabs/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12984,6 +14922,8 @@ }, "node_modules/saucelabs/node_modules/https-proxy-agent": { "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -12995,7 +14935,9 @@ } }, "node_modules/sax": { - "version": "1.4.4", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -13004,6 +14946,8 @@ }, "node_modules/selenium-webdriver": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -13018,6 +14962,9 @@ }, "node_modules/selenium-webdriver/node_modules/rimraf": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -13029,6 +14976,8 @@ }, "node_modules/selenium-webdriver/node_modules/tmp": { "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==", "dev": true, "license": "MIT", "dependencies": { @@ -13050,21 +14999,76 @@ "node": ">=10" } }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/set-blocking": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "license": "ISC" }, "node_modules/setimmediate": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "license": "MIT" }, "node_modules/setprototypeof": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true, "license": "ISC" }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -13075,13 +15079,17 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shell-quote": { - "version": "1.8.3", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz", + "integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==", "dev": true, "license": "MIT", "engines": { @@ -13093,6 +15101,8 @@ }, "node_modules/showdown": { "version": "1.9.1", + "resolved": "https://registry.npmjs.org/showdown/-/showdown-1.9.1.tgz", + "integrity": "sha512-9cGuS382HcvExtf5AHk7Cb4pAeQQ+h0eTr33V1mu+crYWV4KvWAw6el92bDrqGEk5d46Ai/fhbEUwqJ/mTCNEA==", "license": "BSD-3-Clause", "dependencies": { "yargs": "^14.2" @@ -13103,23 +15113,17 @@ }, "node_modules/showdown/node_modules/ansi-regex": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/showdown/node_modules/ansi-styles": { - "version": "3.2.1", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/showdown/node_modules/cliui": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "license": "ISC", "dependencies": { "string-width": "^3.1.0", @@ -13127,23 +15131,16 @@ "wrap-ansi": "^5.1.0" } }, - "node_modules/showdown/node_modules/color-convert": { - "version": "1.9.3", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/showdown/node_modules/color-name": { - "version": "1.1.3", - "license": "MIT" - }, "node_modules/showdown/node_modules/emoji-regex": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "license": "MIT" }, "node_modules/showdown/node_modules/find-up": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "license": "MIT", "dependencies": { "locate-path": "^3.0.0" @@ -13154,6 +15151,8 @@ }, "node_modules/showdown/node_modules/is-fullwidth-code-point": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "license": "MIT", "engines": { "node": ">=4" @@ -13161,6 +15160,8 @@ }, "node_modules/showdown/node_modules/locate-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "license": "MIT", "dependencies": { "p-locate": "^3.0.0", @@ -13172,6 +15173,8 @@ }, "node_modules/showdown/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -13185,6 +15188,8 @@ }, "node_modules/showdown/node_modules/p-locate": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "license": "MIT", "dependencies": { "p-limit": "^2.0.0" @@ -13195,6 +15200,8 @@ }, "node_modules/showdown/node_modules/path-exists": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "license": "MIT", "engines": { "node": ">=4" @@ -13202,6 +15209,8 @@ }, "node_modules/showdown/node_modules/string-width": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "license": "MIT", "dependencies": { "emoji-regex": "^7.0.1", @@ -13214,6 +15223,8 @@ }, "node_modules/showdown/node_modules/strip-ansi": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "license": "MIT", "dependencies": { "ansi-regex": "^4.1.0" @@ -13224,6 +15235,8 @@ }, "node_modules/showdown/node_modules/wrap-ansi": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "license": "MIT", "dependencies": { "ansi-styles": "^3.2.0", @@ -13236,10 +15249,14 @@ }, "node_modules/showdown/node_modules/y18n": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "license": "ISC" }, "node_modules/showdown/node_modules/yargs": { "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", "license": "MIT", "dependencies": { "cliui": "^5.0.0", @@ -13257,6 +15274,8 @@ }, "node_modules/showdown/node_modules/yargs-parser": { "version": "15.0.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz", + "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==", "license": "ISC", "dependencies": { "camelcase": "^5.0.0", @@ -13264,13 +15283,15 @@ } }, "node_modules/side-channel": { - "version": "1.1.0", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, @@ -13282,12 +15303,14 @@ } }, "node_modules/side-channel-list": { - "version": "1.0.0", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" @@ -13298,6 +15321,8 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", "dependencies": { @@ -13315,6 +15340,8 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { @@ -13345,23 +15372,56 @@ } }, "node_modules/sigstore": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.0.tgz", - "integrity": "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.1.tgz", + "integrity": "sha512-endqECJkfhozrXMK5ngu/UAA0xVcVEFdnHJCElGaExypjW+HK5i6zu3NteLoaX/iFbRUbC3+DjttQs0GARr+5w==", "dev": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", + "@sigstore/core": "^3.2.1", "@sigstore/protobuf-specs": "^0.5.0", - "@sigstore/sign": "^4.1.0", - "@sigstore/tuf": "^4.0.1", - "@sigstore/verify": "^3.1.0" + "@sigstore/sign": "^4.1.1", + "@sigstore/tuf": "^4.0.2", + "@sigstore/verify": "^3.1.1" }, "engines": { "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/slice-ansi": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", @@ -13392,22 +15452,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -13421,6 +15465,8 @@ }, "node_modules/socket.io": { "version": "4.8.3", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz", + "integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==", "dev": true, "license": "MIT", "dependencies": { @@ -13461,10 +15507,57 @@ "node": ">=10.0.0" } }, + "node_modules/socket.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/socks": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.8.tgz", - "integrity": "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", "dev": true, "license": "MIT", "dependencies": { @@ -13503,6 +15596,8 @@ }, "node_modules/source-map-js": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -13532,10 +15627,14 @@ }, "node_modules/spawn-command": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", "dev": true }, "node_modules/spdx-correct": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -13543,13 +15642,28 @@ "spdx-license-ids": "^3.0.0" } }, + "node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, "node_modules/spdx-exceptions": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true, "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { - "version": "3.0.1", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13558,12 +15672,16 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.22", + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", "dev": true, "license": "CC0-1.0" }, "node_modules/sshpk": { "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13600,11 +15718,13 @@ } }, "node_modules/statuses": { - "version": "1.5.0", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/stdin-discarder": { @@ -13617,75 +15737,70 @@ "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/streamroller": { - "version": "3.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/streamroller/node_modules/fs-extra": { - "version": "8.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/streamroller/node_modules/jsonfile": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/streamroller/node_modules/universalify": { - "version": "0.1.2", + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", "dev": true, "license": "MIT", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, "engines": { - "node": ">= 4.0.0" + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" } }, "node_modules/string-width": { - "version": "4.2.3", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", + "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", + "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" }, "engines": { - "node": ">=8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/strip-ansi": { - "version": "6.0.1", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.2.2" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/strip-bom": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "license": "MIT", "engines": { @@ -13694,6 +15809,8 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "license": "MIT", "engines": { "node": ">=8" @@ -13736,17 +15853,22 @@ } }, "node_modules/supports-color": { - "version": "7.2.0", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "has-flag": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.8.0" } }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "license": "MIT", "engines": { @@ -13828,17 +15950,42 @@ "node": ">=14.0.0" } }, - "node_modules/tailwindcss/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/tailwindcss/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/tailwindcss/node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.3" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10.13.0" + "node": ">= 6" } }, "node_modules/tailwindcss/node_modules/jiti": { @@ -13851,6 +15998,32 @@ "jiti": "bin/jiti.js" } }, + "node_modules/tailwindcss/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tailwindcss/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/tapable": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", @@ -13866,9 +16039,9 @@ } }, "node_modules/tar": { - "version": "7.5.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz", - "integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==", + "version": "7.5.16", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz", + "integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -13894,6 +16067,8 @@ }, "node_modules/text-segmentation": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", "license": "MIT", "dependencies": { "utrie": "^1.0.2" @@ -13923,9 +16098,9 @@ } }, "node_modules/tinyexec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", - "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, "license": "MIT", "engines": { @@ -13934,6 +16109,8 @@ }, "node_modules/tinyglobby": { "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -13958,6 +16135,8 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13969,6 +16148,8 @@ }, "node_modules/toidentifier": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "license": "MIT", "engines": { @@ -13977,6 +16158,8 @@ }, "node_modules/tough-cookie": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13989,14 +16172,25 @@ }, "node_modules/tough-cookie/node_modules/punycode": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT", + "optional": true + }, "node_modules/tree-kill": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, "license": "MIT", "bin": { @@ -14024,6 +16218,8 @@ }, "node_modules/ts-md5": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/ts-md5/-/ts-md5-1.3.1.tgz", + "integrity": "sha512-DiwiXfwvcTeZ5wCE0z+2A9EseZsztaiZtGrtSaY5JOD7ekPnR/GoIVD5gXZAlK9Na9Kvpo9Waz5rW64WKAWApg==", "license": "MIT", "engines": { "node": ">=12" @@ -14031,6 +16227,8 @@ }, "node_modules/ts-node": { "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14073,19 +16271,15 @@ }, "node_modules/ts-node/node_modules/arg": { "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true, "license": "MIT" }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.4", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/tslib": { "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/tuf-js": { @@ -14105,6 +16299,8 @@ }, "node_modules/tunnel-agent": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -14116,11 +16312,15 @@ }, "node_modules/tweetnacl": { "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true, "license": "Unlicense" }, "node_modules/type-check": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" @@ -14130,285 +16330,78 @@ } }, "node_modules/type-is": { - "version": "1.6.18", - "dev": true, - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.57.0.tgz", - "integrity": "sha512-W8GcigEMEeB07xEZol8oJ26rigm3+bfPHxHvwbYUlu1fUDsGuQ7Hiskx5xGW/xM4USc9Ephe3jtv7ZYPQntHeA==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.57.0", - "@typescript-eslint/parser": "8.57.0", - "@typescript-eslint/typescript-estree": "8.57.0", - "@typescript-eslint/utils": "8.57.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.0.tgz", - "integrity": "sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ==", - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.57.0", - "@typescript-eslint/type-utils": "8.57.0", - "@typescript-eslint/utils": "8.57.0", - "@typescript-eslint/visitor-keys": "8.57.0", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.57.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.57.0.tgz", - "integrity": "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.57.0", - "@typescript-eslint/types": "8.57.0", - "@typescript-eslint/typescript-estree": "8.57.0", - "@typescript-eslint/visitor-keys": "8.57.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.0.tgz", - "integrity": "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.57.0", - "@typescript-eslint/visitor-keys": "8.57.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.57.0.tgz", - "integrity": "sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.57.0", - "@typescript-eslint/typescript-estree": "8.57.0", - "@typescript-eslint/utils": "8.57.0", - "debug": "^4.4.3", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.0.tgz", - "integrity": "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==", - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.0.tgz", - "integrity": "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.57.0", - "@typescript-eslint/tsconfig-utils": "8.57.0", - "@typescript-eslint/types": "8.57.0", - "@typescript-eslint/visitor-keys": "8.57.0", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.0.tgz", - "integrity": "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==", - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.57.0", - "@typescript-eslint/types": "8.57.0", - "@typescript-eslint/typescript-estree": "8.57.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.0.tgz", - "integrity": "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", + "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.57.0", - "eslint-visitor-keys": "^5.0.0" + "content-type": "^2.0.0", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 18" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://opencollective.com/express" } }, - "node_modules/typescript-eslint/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "node_modules/type-is/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "dev": true, "license": "MIT", "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/typescript-eslint/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" + "node": ">=18" }, - "engines": { - "node": "18 || 20 || >=22" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/typescript-eslint/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/typescript-eslint/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "license": "MIT", "engines": { - "node": ">= 4" + "node": ">=14.17" } }, - "node_modules/typescript-eslint/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "license": "BlueOak-1.0.0", + "node_modules/typescript-eslint": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.0.tgz", + "integrity": "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==", + "license": "MIT", "dependencies": { - "brace-expansion": "^5.0.5" + "@typescript-eslint/eslint-plugin": "8.61.0", + "@typescript-eslint/parser": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0" }, "engines": { - "node": "18 || 20 || >=22" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/ua-parser-js": { "version": "0.7.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.41.tgz", + "integrity": "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==", "dev": true, "funding": [ { @@ -14448,6 +16441,8 @@ }, "node_modules/underscore.string": { "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha512-hbD5MibthuDAu4yA5wxes5bzFgqd3PpBJuClbRxaNddxfdsz+qf+1kHwrGQFrmchmDHb9iNU+6EHDn8uj0xDJg==", "engines": { "node": "*" } @@ -14464,11 +16459,25 @@ }, "node_modules/undici-types": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, "license": "MIT", "engines": { @@ -14477,6 +16486,8 @@ }, "node_modules/update-browserslist-db": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -14506,6 +16517,8 @@ }, "node_modules/uri-js": { "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -14513,6 +16526,8 @@ }, "node_modules/uri-js/node_modules/punycode": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "license": "MIT", "engines": { "node": ">=6" @@ -14520,10 +16535,14 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, "license": "MIT", "engines": { @@ -14532,6 +16551,8 @@ }, "node_modules/utrie": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", "license": "MIT", "dependencies": { "base64-arraybuffer": "^1.0.2" @@ -14539,6 +16560,9 @@ }, "node_modules/uuid": { "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "dev": true, "license": "MIT", "bin": { @@ -14547,11 +16571,15 @@ }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true, "license": "MIT" }, "node_modules/validate-npm-package-license": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -14559,6 +16587,17 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, "node_modules/validate-npm-package-name": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz", @@ -14571,6 +16610,8 @@ }, "node_modules/vary": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "license": "MIT", "engines": { @@ -14579,6 +16620,8 @@ }, "node_modules/verror": { "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "dev": true, "engines": [ "node >=0.6.0" @@ -14590,6 +16633,13 @@ "extsprintf": "^1.2.0" } }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT" + }, "node_modules/vite": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", @@ -14667,6 +16717,8 @@ }, "node_modules/void-elements": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", "dev": true, "license": "MIT", "engines": { @@ -14697,6 +16749,8 @@ }, "node_modules/webdriver-js-extender": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", + "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14709,6 +16763,8 @@ }, "node_modules/webdriver-manager": { "version": "12.1.9", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.9.tgz", + "integrity": "sha512-Yl113uKm8z4m/KMUVWHq1Sjtla2uxEBtx2Ue3AmIlnlPAKloDn/Lvmy6pqWCUersVISpdMeVpAaGbNnvMuT2LQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14733,6 +16789,8 @@ }, "node_modules/webdriver-manager/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, "license": "MIT", "engines": { @@ -14741,6 +16799,8 @@ }, "node_modules/webdriver-manager/node_modules/ansi-styles": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true, "license": "MIT", "engines": { @@ -14749,6 +16809,8 @@ }, "node_modules/webdriver-manager/node_modules/chalk": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, "license": "MIT", "dependencies": { @@ -14762,21 +16824,18 @@ "node": ">=0.10.0" } }, - "node_modules/webdriver-manager/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/webdriver-manager/node_modules/ini": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, "license": "ISC" }, "node_modules/webdriver-manager/node_modules/rimraf": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -14788,6 +16847,8 @@ }, "node_modules/webdriver-manager/node_modules/semver": { "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "license": "ISC", "bin": { @@ -14796,6 +16857,8 @@ }, "node_modules/webdriver-manager/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, "license": "MIT", "dependencies": { @@ -14807,14 +16870,36 @@ }, "node_modules/webdriver-manager/node_modules/supports-color": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -14828,10 +16913,72 @@ }, "node_modules/which-module": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "license": "ISC" }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -14839,6 +16986,8 @@ }, "node_modules/wrap-ansi": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -14849,9 +16998,88 @@ "node": ">=8" } }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrappy": { "version": "1.0.2", - "dev": true, + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "devOptional": true, "license": "ISC" }, "node_modules/ws": { @@ -14878,6 +17106,8 @@ }, "node_modules/xml2js": { "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", "dev": true, "license": "MIT", "dependencies": { @@ -14890,6 +17120,8 @@ }, "node_modules/xmlbuilder": { "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "dev": true, "license": "MIT", "engines": { @@ -14898,6 +17130,8 @@ }, "node_modules/y18n": { "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "license": "ISC", "engines": { @@ -14911,59 +17145,63 @@ "dev": true, "license": "ISC" }, - "node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/yargs": { - "version": "17.7.2", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^8.0.1", + "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", + "string-width": "^7.2.0", "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "yargs-parser": "^22.0.0" }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs-parser": { - "version": "20.2.9", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "dev": true, "license": "ISC", "engines": { - "node": ">=10" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", + "node_modules/yargs/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, - "license": "ISC", + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=12" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/yn": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, "license": "MIT", "engines": { @@ -14972,6 +17210,8 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "license": "MIT", "engines": { "node": ">=10" From 0348f06a615887dbf6d2f6d534cb37e99e9f3769 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:28:46 +1000 Subject: [PATCH 1104/1531] chore: ignore formatting commit in git blame --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..8af4e23280 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# 8 June 2026: Repository-wide formatting and lint configuration +26b4962794d16e90587fb179aab966b39459050c From ba7910a59460a4d4139273b272e99625e5efc518 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:54:21 +1000 Subject: [PATCH 1105/1531] fix: avoid loading rendering all students at the same time --- .../units/states/students-list/students-list.component.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/app/units/states/students-list/students-list.component.ts b/src/app/units/states/students-list/students-list.component.ts index 2876bae073..a0a4de5b8f 100644 --- a/src/app/units/states/students-list/students-list.component.ts +++ b/src/app/units/states/students-list/students-list.component.ts @@ -83,6 +83,7 @@ export class StudentsListComponent implements OnInit, AfterViewInit, OnDestroy { ngAfterViewInit(): void { this.dataSource.paginator = this.paginator; + this.updateDataSource(); } ngOnDestroy(): void { @@ -157,6 +158,10 @@ export class StudentsListComponent implements OnInit, AfterViewInit, OnDestroy { } private updateDataSource(resetPagination: boolean = false): void { + if (!this.paginator) { + return; + } + const students = this.filteredProjects(); this.dataSource.data = students; From df6a6ecc73d01dd2ef449270bc7c6de446d93884 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 10 Jun 2026 11:08:04 +1000 Subject: [PATCH 1106/1531] fix: apply status color --- .../tasks/project-tasks-list/project-tasks-list.component.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/tasks/project-tasks-list/project-tasks-list.component.html b/src/app/tasks/project-tasks-list/project-tasks-list.component.html index 28db724d6d..243bba9805 100644 --- a/src/app/tasks/project-tasks-list/project-tasks-list.component.html +++ b/src/app/tasks/project-tasks-list/project-tasks-list.component.html @@ -19,6 +19,9 @@
    {{ grouping.name }}
    (click)="selectChip(task)" class="task-status chip truncate text-center" [ngClass]="newTaskService.statusClass(task.status)" + [style.--mat-chip-elevated-container-color]=" + newTaskService.statusColors.get(task.status) + " > @if (task.similarityFlag) { From 21d3e9510825c155f595a5c069ff450b895bd780 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 10 Jun 2026 11:29:48 +1000 Subject: [PATCH 1107/1531] refactor: add skeleton ui to students and portfolios route --- .../portfolios-list.component.html | 85 ++++++++++++++++++- .../portfolios-list.component.ts | 12 ++- .../portfolios/portfolios.component.html | 4 +- .../states/portfolios/portfolios.component.ts | 7 +- .../students-list.component.html | 54 +++++++++++- .../students-list/students-list.component.ts | 14 ++- 6 files changed, 158 insertions(+), 18 deletions(-) diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html index 23e3f17566..ea67268a4d 100644 --- a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html @@ -5,12 +5,19 @@

    Mark portfolios

    Filter - + Mark portfolios hideSingleSelectionIndicator [(ngModel)]="tutorialFilter" (change)="onTutorialFilterChange($event)" + [disabled]="loading" > Mark portfolios hideSingleSelectionIndicator [(ngModel)]="gradeFilter" (change)="onGradeFilterChange($event)" + [disabled]="loading" > Mark portfolios
    - @@ -81,6 +90,7 @@

    Mark portfolios

    matTooltip="Downloading all portfolios may take a long time" matTooltipShowDelay="500" matTooltipPosition="above" + [disabled]="loading" > downloadDownload Portfolios @@ -89,12 +99,73 @@

    Mark portfolios

    @if (hasD2lMapping()) { - }
    + @if (loading) { +
    +
    +
    + @for ( + width of [ + '110px', + '170px', + '150px', + '130px', + '80px', + '110px', + '180px', + '400px', + '80px', + '50px', + ]; + track $index + ) { + + } +
    + + @for (row of [0, 1, 2, 3, 4, 5, 6, 7]; track row) { +
    + @for ( + width of [ + '110px', + '170px', + '150px', + '130px', + '80px', + '110px', + '180px', + '400px', + '80px', + '50px', + ]; + track $index + ) { + + } +
    + } +
    +
    + } + Mark portfolios matSortDisableClear class="f-table selectable" (matSortChange)="sortTableData($event)" + [hidden]="loading" > @@ -216,5 +288,10 @@

    Mark portfolios

    Student
    - +
    diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts index 9047047eda..3f3c314edb 100644 --- a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts @@ -13,8 +13,9 @@ import { Component, EventEmitter, Input, - OnInit, + OnChanges, Output, + SimpleChanges, ViewChild, } from '@angular/core'; import {MatButtonToggleChange} from '@angular/material/button-toggle'; @@ -29,8 +30,9 @@ import {D2lTransferModal} from '../../d2l-transfer-modal/d2l-transfer.component' styleUrl: './portfolios-list.component.scss', standalone: false, }) -export class PortfoliosListComponent implements OnInit, AfterViewInit { +export class PortfoliosListComponent implements OnChanges, AfterViewInit { @Input() unit: Unit; + @Input() loading = true; @Output() public studentSelected: EventEmitter = new EventEmitter(); @@ -62,8 +64,10 @@ export class PortfoliosListComponent implements OnInit, AfterViewInit { this.dataSource.sort = this.sort; } - ngOnInit(): void { - this.updateDataSource(); + ngOnChanges(changes: SimpleChanges): void { + if (!this.loading && this.unit && (changes.loading || changes.unit)) { + this.updateDataSource(); + } } openProject(event: Event, project: Project) { diff --git a/src/app/units/states/portfolios/portfolios.component.html b/src/app/units/states/portfolios/portfolios.component.html index a4a05762a3..9ab91ac774 100644 --- a/src/app/units/states/portfolios/portfolios.component.html +++ b/src/app/units/states/portfolios/portfolios.component.html @@ -5,6 +5,7 @@

    Student Portfolios

    @@ -38,8 +39,5 @@

    Student Portfolios

    } - } @else { - -
    Loading unit...
    }
    diff --git a/src/app/units/states/portfolios/portfolios.component.ts b/src/app/units/states/portfolios/portfolios.component.ts index 398463d779..a8aeda7118 100644 --- a/src/app/units/states/portfolios/portfolios.component.ts +++ b/src/app/units/states/portfolios/portfolios.component.ts @@ -19,6 +19,7 @@ export class PortfoliosComponent implements OnInit { // Exposed to child components public unit: Unit = null; public selectedProject: Project; + public loadingStudents = true; @ViewChild('tabs') tabs!: MatTabGroup; @@ -48,10 +49,12 @@ export class PortfoliosComponent implements OnInit { this.unit$ = this.unit$ ?? of(this.route.parent.snapshot.data.unit); this.unit$?.pipe(first()).subscribe({ next: (unit) => { + this.unit = unit; + this.unit.loadD2lMapping().subscribe(); + this.projectService.loadStudents(unit, false).subscribe({ next: () => { - this.unit = unit; - this.unit.loadD2lMapping().subscribe(); + this.loadingStudents = false; }, error: (error) => { this.alertService.error(`Failed to load unit: ${error}`, 6000); diff --git a/src/app/units/states/students-list/students-list.component.html b/src/app/units/states/students-list/students-list.component.html index 70d1d02aa5..89cd97d026 100644 --- a/src/app/units/states/students-list/students-list.component.html +++ b/src/app/units/states/students-list/students-list.component.html @@ -12,6 +12,7 @@

    Students

    [(ngModel)]="searchText" (ngModelChange)="onSearchChange()" [matAutocomplete]="studentSearch" + [disabled]="loadingStudents" /> @for (suggestion of filteredSuggestions; track suggestion) { @@ -26,13 +27,53 @@

    Students

    [ngModel]="staffFilter" class="w-full max-w-lg" (ngModelChange)="setStaffFilter($event)" + [disabled]="loadingStudents" > All Tutorials My Tutorials
    -
    + @if (loadingStudents) { +
    +
    + @for (width of ['4%', '10%', '16%', '28%', '8%', '8%', '8%', '10%', '10%']; track $index) { + + } +
    + + @for (row of [0, 1, 2, 3, 4, 5, 6, 7]; track row) { +
    + + + + + @for (column of [0, 1, 2, 3, 4]; track column) { + + } +
    + } +
    + } + +
    Students
    - - @@ -168,6 +215,7 @@

    Students

    diff --git a/src/app/units/states/students-list/students-list.component.ts b/src/app/units/states/students-list/students-list.component.ts index a0a4de5b8f..5b1a7cff5c 100644 --- a/src/app/units/states/students-list/students-list.component.ts +++ b/src/app/units/states/students-list/students-list.component.ts @@ -1,4 +1,4 @@ -import {Observable, Subscription, first, of} from 'rxjs'; +import {Observable, Subscription, finalize, first, of} from 'rxjs'; import { Project, ProjectService, @@ -42,6 +42,7 @@ export class StudentsListComponent implements OnInit, AfterViewInit, OnDestroy { searchText = ''; staffFilter: 'all' | 'mine' = 'all'; filteredSuggestions: string[] = []; + loadingStudents = true; unit: Unit; private subscriptions: Subscription[] = []; @@ -61,6 +62,7 @@ export class StudentsListComponent implements OnInit, AfterViewInit, OnDestroy { this.subscriptions.push( this.unit$?.pipe(first()).subscribe((unit) => { if (!unit) { + this.loadingStudents = false; return; } @@ -76,7 +78,15 @@ export class StudentsListComponent implements OnInit, AfterViewInit, OnDestroy { this.updateSuggestions(); this.updateDataSource(); - this.projectService.loadStudents(this.unit).pipe(first()).subscribe(); + this.projectService + .loadStudents(this.unit) + .pipe( + first(), + finalize(() => { + this.loadingStudents = false; + }), + ) + .subscribe(); }), ); } From c812b8c117c9f45c2874301df835a8ecfc3177ba Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 10 Jun 2026 14:38:01 +1000 Subject: [PATCH 1108/1531] chore: default tooltip position to above elements --- src/app/doubtfire-angular.module.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 4fefb44031..482788d626 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -77,6 +77,7 @@ import {MatTableModule} from '@angular/material/table'; import {MatTabsModule} from '@angular/material/tabs'; import {MatToolbarModule} from '@angular/material/toolbar'; import {MatTooltipModule} from '@angular/material/tooltip'; +import {MAT_TOOLTIP_DEFAULT_OPTIONS, MatTooltipDefaultOptions} from '@angular/material/tooltip'; import {MatTreeModule} from '@angular/material/tree'; import {BrowserModule, DomSanitizer, Title} from '@angular/platform-browser'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; @@ -407,6 +408,13 @@ const GANTT_CHART_CONFIG = { }, }; +const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { + showDelay: 0, + hideDelay: 0, + touchendHideDelay: 1500, + position: 'above', +}; + @NgModule({ // Components we declare declarations: [ @@ -716,6 +724,10 @@ const GANTT_CHART_CONFIG = { CommunicationSetService, CsvResultModalService, CsvUploadModalService, + { + provide: MAT_TOOLTIP_DEFAULT_OPTIONS, + useValue: DEFAULT_TOOLTIP_OPTIONS, + }, ], imports: [ FlexLayoutModule, From be0fcbaee9c7be5ed399b5c88cdfb7b4618abc83 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 10 Jun 2026 15:23:41 +1000 Subject: [PATCH 1109/1531] chore: improve task list padding --- .../directives/unit-task-list/unit-task-list.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index 3c473a0d1d..f237e2f7c6 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -1,4 +1,4 @@ -
    +
    From 2f327f1b8cb098767571b491599780412317e6cc Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 10 Jun 2026 16:31:38 +1000 Subject: [PATCH 1110/1531] chore: add subtitle --- .../directives/staff-notes-view/staff-notes-view.component.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html index 92a3039c43..5b52d8d214 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.html @@ -3,6 +3,7 @@ comment

    Staff Notes for {{ project?.student?.name }}

    +

    Use these notes for private staff discussions about the student. Students cannot view them.

    From 7ebe61bc555f8e45b3cc5b82ef00ff57bd8a7fe3 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 10 Jun 2026 16:43:41 +1000 Subject: [PATCH 1111/1531] refactor: disable feedback submissions after deadline --- .../submission-type-modal.component.html | 26 +++++++++++++++---- .../submission-type-modal.component.ts | 13 +++++++++- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.html b/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.html index bb5d44c08a..42044d1858 100644 --- a/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.html +++ b/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.html @@ -4,16 +4,19 @@

    Select submission type

    This task won't be marked as complete by your tutor. It will be assessed as part of your final portfolio.

    -

    - You can submit it for feedback before the deadline, but you'll need to resubmit it later for - portfolio assessment. -

    + @if (!isPastFeedbackDeadline) { +

    + You can submit it for feedback before the deadline, but you'll need to resubmit it later for + portfolio assessment. +

    + }
    - @if (selectedTransition === 'ready_for_feedback') { + @if (isPastFeedbackDeadline) { + + } @else if (selectedTransition === 'ready_for_feedback') {

    You've made progress on this task and would like feedback, clarification, or to discuss questions with your tutor. diff --git a/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.ts b/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.ts index 5b3621d837..a1bb60da68 100644 --- a/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.ts +++ b/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.ts @@ -16,12 +16,20 @@ export interface SubmissionTypeModalData { export class SubmissionTypeModalComponent { selectedTransition: 'ready_for_feedback' | 'assess_in_portfolio' = null; + public get isPastFeedbackDeadline(): boolean { + return Date.now() > this.data.task.localDeadlineDate().getTime(); + } + constructor( @Inject(MAT_DIALOG_DATA) public data: SubmissionTypeModalData, private dialogRef: MatDialogRef, ) {} public selectRff() { + if (this.isPastFeedbackDeadline) { + return; + } + this.selectedTransition = 'ready_for_feedback'; } @@ -30,7 +38,10 @@ export class SubmissionTypeModalComponent { } public submit() { - if (this.selectedTransition === null) { + if ( + this.selectedTransition === null || + (this.selectedTransition === 'ready_for_feedback' && this.isPastFeedbackDeadline) + ) { return; } From ac015c5d7c50de7d60e7c081c6bbfbab7e327c2f Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 10 Jun 2026 16:50:54 +1000 Subject: [PATCH 1112/1531] refactor: rename tutor notes to moderation notes --- src/app/common/header/header.component.html | 2 +- .../header/task-dropdown/task-dropdown.component.html | 3 ++- .../tutor-notes-view/tutor-notes-view.component.html | 2 +- .../directives/task-dashboard/task-dashboard.component.html | 4 ++-- .../unit-staff-editor/unit-staff-editor.component.html | 6 +++++- .../inbox-dashboard/inbox-dashboard.component.html | 2 +- .../inbox/directives/moderation/moderation.component.ts | 2 +- 7 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/app/common/header/header.component.html b/src/app/common/header/header.component.html index 715d74c1bf..549c5189db 100644 --- a/src/app/common/header/header.component.html +++ b/src/app/common/header/header.component.html @@ -46,7 +46,7 @@ } @if (currentUnit && currentUnitRole && currentUnitRole.tutorNoteCount > 0) { - diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.html index 456422ea90..7cfe442732 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.html @@ -1,7 +1,7 @@

    comment -

    Tutor Notes for {{ unitRole?.user?.name }}

    +

    Moderation Notes for {{ unitRole?.user?.name }}

    @if (task) {

    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html index c980e95db5..de593aa7b3 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html @@ -33,7 +33,7 @@ - Staff Notes + Student Notes @if (task.project.staffNoteCount) { @if (canAccessTutorNotes) { - + } } diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html index 34ebd4db13..d01957ae86 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html @@ -106,7 +106,11 @@

    Unit Staff

    + + + + + @@ -82,6 +92,12 @@
    Actions
    - -
    - -
    + +
    + + +
    + @if (task.numNewComments > 0) { + + {{ task.numNewComments }} + + } + @if (task.similaritiesDetected) { + + + visibility + + + } +
    + +
    + @if (task.hasGrade()) { + + {{ task.gradeDesc() }} + + } + @if (task.hasQualityPoints()) { + + {{ task.qualityPts }} + + {{ task.definition.maxQualityPts }} + + } + @if (task.isDueSoon() && !task.inFinalState()) { + + + schedule + + + } + @if (task.betweenDueDateAndDeadlineDate() && !task.isPastDeadline() && !task.inFinalState()) { + + + schedule + + + } + @if (task.isPastDeadline() && !task.inFinalState()) { + + + schedule + + ! + + }
    +
    + +
    + @if (!isCollapsed) { +
    +
    + +
    + +
    +
    +
    + } -
    @for (taskDef of filteredTaskDefinitions; track taskDef) { @@ -33,137 +117,78 @@ }" > @if (taskDef) { -
    -
    -
    -
    -
    {{ taskDef.name }}
    + @if (isCollapsed) { +
    + + {{ taskDef.abbreviation }} + + @if (taskListItem(taskDef); as task) { + + } +
    + } @else { +
    +
    +
    +
    +
    {{ taskDef.name }}
    -
    - @if (taskDef.isGroupTask()) { - groups - } @else { - person - } +
    + @if (taskDef.isGroupTask()) { + groups + } @else { + person + } -
    - {{ taskDef.abbreviation }} - - - {{ gradeNames[taskDef.targetGrade] }} Task -
    - @if (taskListItem(taskDef); as task) { - - @if (!task.isBeforeStartDate() && !task.inSubmittedState()) { - - hourglass_bottomhourglass_top + {{ task.timeToStart() }} + + } --> + @if (!task.isBeforeStartDate() && !task.inSubmittedState()) { + - {{ task.timeToDue() }} - + + hourglass_bottom + + {{ task.timeToDue() }} + + } } - } +
    + @if (taskListItem(taskDef); as task) { + + }
    - @if (taskListItem(taskDef); as task) { -
    - - -
    - @if (task.numNewComments > 0) { - - {{ task.numNewComments }} - - } - @if (task.similaritiesDetected) { - - visibility - - } -
    - -
    - @if (task.hasGrade()) { - - {{ task.gradeDesc() }} - - } - @if (task.hasQualityPoints()) { - - {{ task.qualityPts }} - - {{ - task.definition.maxQualityPts - }} - - } - @if (task.isDueSoon() && !task.inFinalState()) { - - schedule - - } - @if ( - task.betweenDueDateAndDeadlineDate() && - !task.isPastDeadline() && - !task.inFinalState() - ) { - - schedule - - } - @if (task.isPastDeadline() && !task.inFinalState()) { - - schedule - ! - - } -
    -
    - } -
    + } } } @empty { @@ -176,7 +201,27 @@ [disableRipple]="true" [ngClass]="project.portfolioTaskStatusClass()" > - + @if (isCollapsed) { + + + history_edu + +
    + +
    +
    + } @else { + + } } diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss index 652d53cb6f..6838d99b48 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.scss @@ -10,6 +10,18 @@ $my-palette: mat.m2-define-palette($md-formatif); padding-right: 8px; } +:host(.collapsed) { + padding-right: 0; + + .mat-mdc-list-item { + overflow: visible; + } + + ::ng-deep .mdc-list-item__content { + overflow: visible; + } +} + ::ng-deep .cdk-virtual-scroll-content-wrapper { width: 100%; } diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index 588bdbc475..f4e4c4e4d1 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -1,5 +1,5 @@ import {Location} from '@angular/common'; -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import {Component, HostBinding, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {BehaviorSubject} from 'rxjs'; import {Project, Task, TaskDefinition} from 'src/app/api/models/doubtfire-model'; @@ -17,6 +17,12 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { @Input() project: Project; @Input() taskDefinitions: TaskDefinition[]; @Input() tasks: Task[]; + @Input() isCollapsed = false; + + @HostBinding('class.collapsed') + public get collapsedHostClass(): boolean { + return this.isCollapsed; + } // What is the selected task definition @Input() selectedTaskDefinition$: BehaviorSubject; From 42fd95d73da8c466a5e304fe2653f4f0ea67a604 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:51:16 +1000 Subject: [PATCH 1122/1531] refactor: add project dashboard in portfolios progress view --- ...portfolios-project-progress.component.html | 109 ++++++++++-------- .../portfolios-project-progress.component.ts | 92 ++++++++++++++- 2 files changed, 148 insertions(+), 53 deletions(-) diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html index cdbdb593de..250032c055 100644 --- a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html @@ -1,58 +1,65 @@

    Review progress of {{ project.student.name }}

    Review the students progress through the unit's tasks.

    -
    -
    - - - Target Grade - - -
    -
    - - @for (grade of gradeValues; track grade) { - - - - } - -
    - {{ gradeWord(project.targetGrade) ?? 'N/A' }} + + + +
    diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts index eadf0c3f47..8ffa907fa2 100644 --- a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts @@ -1,4 +1,5 @@ -import {Component, Input} from '@angular/core'; +import {Component, ElementRef, HostListener, Input, OnChanges} from '@angular/core'; +import {BehaviorSubject} from 'rxjs'; import {Project} from 'src/app/api/models/project'; import {Unit} from 'src/app/api/models/unit'; import {ProjectService} from 'src/app/api/services/project.service'; @@ -12,22 +13,64 @@ import {GradeService} from 'src/app/common/services/grade.service'; styleUrl: './portfolios-project-progress.component.scss', standalone: false, }) -export class PortfoliosProjectProgressComponent { +export class PortfoliosProjectProgressComponent implements OnChanges { @Input() project: Project; @Input() unit: Unit; + public project$: BehaviorSubject = new BehaviorSubject(null); + public taskStats: {numberOfTasksCompleted: number; numberOfTasksRemaining: number} = { numberOfTasksCompleted: 0, numberOfTasksRemaining: 0, }; constructor( + private elementRef: ElementRef, private gradeService: GradeService, private projectService: ProjectService, private alertService: AlertService, private taskService: TaskService, ) {} + @HostListener('wheel', ['$event']) + public prioritisePageScroll(event: WheelEvent): void { + if (event.deltaY === 0 || !(event.target instanceof HTMLElement)) { + return; + } + + const projectDashboard = event.target.closest('f-project-dashboard'); + if (!projectDashboard || !this.elementRef.nativeElement.contains(projectDashboard)) { + return; + } + + if (event.target.closest('f-unit-task-list')) { + return; + } + + const innerScrollContainer = this.findInnerScrollContainer(event.target, projectDashboard); + if ( + event.deltaY < 0 && + innerScrollContainer && + this.canScroll(innerScrollContainer, event.deltaY) + ) { + return; + } + + const scrollContainer = this.findOuterScrollContainer(projectDashboard); + if (!scrollContainer || !this.canScroll(scrollContainer, event.deltaY)) { + return; + } + + event.preventDefault(); + scrollContainer.scrollBy({top: event.deltaY}); + } + + ngOnChanges(): void { + if (this.project) { + this.project$.next(this.project); + } + } + public get gradeValues() { return this.gradeService.gradeValues; } @@ -80,4 +123,49 @@ export class PortfoliosProjectProgressComponent { }, }); } + + private findInnerScrollContainer(target: HTMLElement, root: Element): HTMLElement | null { + let element: HTMLElement | null = target; + + while (element && element !== root) { + if (this.isScrollable(element)) { + return element; + } + + element = element.parentElement; + } + + return null; + } + + private findOuterScrollContainer(projectDashboard: Element): HTMLElement { + let parent = projectDashboard.parentElement; + + while (parent) { + if (this.isScrollable(parent)) { + return parent; + } + + parent = parent.parentElement; + } + + return document.scrollingElement as HTMLElement; + } + + private isScrollable(element: HTMLElement): boolean { + if (element.scrollHeight <= element.clientHeight) { + return false; + } + + const overflowY = getComputedStyle(element).overflowY; + return overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay'; + } + + private canScroll(element: HTMLElement, deltaY: number): boolean { + if (deltaY > 0) { + return element.scrollTop + element.clientHeight < element.scrollHeight; + } + + return element.scrollTop > 0; + } } From f8d514261c7eca5465ac3af95da33b95a39d3f23 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:20:44 +1000 Subject: [PATCH 1123/1531] fix: use either portfolio available field --- .../directives/portfolios-list/portfolios-list.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts index 8eaeeb4de1..36b7a1dc0b 100644 --- a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts @@ -120,7 +120,9 @@ export class PortfoliosListComponent implements OnChanges, AfterViewInit { const currentUser = this.userService.currentUser; const students = this.unit.students - .filter((p) => (this.portfolioFilter === 'submitted_only' ? p.hasPortfolio : true)) + .filter((p) => + this.portfolioFilter === 'submitted_only' ? p.hasPortfolio || p.portfolioAvailable : true, + ) .filter((p) => (this.tutorialFilter === 'mine' ? p.hasTutor(currentUser) : true)) .filter((p) => (this.gradeFilter !== null ? p.submittedGrade === this.gradeFilter : true)); From 39a62f1b722dc525af928fb01b854ab4854673e5 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:21:52 +1000 Subject: [PATCH 1124/1531] refactor: add routing system to portfolios navigation --- src/app/app.routes.ts | 15 ++ .../project-dashboard.component.html | 1 + .../project-dashboard.component.ts | 1 + .../portfolios-list.component.html | 2 +- ...portfolios-project-progress.component.html | 1 + .../portfolios-project-progress.component.ts | 2 + .../portfolios/portfolios.component.html | 79 ++++---- .../states/portfolios/portfolios.component.ts | 173 ++++++++++++++---- .../unit-task-list.component.ts | 7 + 9 files changed, 214 insertions(+), 67 deletions(-) diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 6122dd6101..e96ce8ce6c 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -117,6 +117,21 @@ export const routes: Routes = [ component: PortfoliosComponent, data: {task: 'Student Portfolios'}, }, + { + path: 'students/portfolios/:projectId', + component: PortfoliosComponent, + data: {task: 'Student Portfolios'}, + }, + { + path: 'students/portfolios/:projectId/:tab', + component: PortfoliosComponent, + data: {task: 'Student Portfolios'}, + }, + { + path: 'students/portfolios/:projectId/:tab/:taskAbbreviation', + component: PortfoliosComponent, + data: {task: 'Student Portfolios'}, + }, {path: 'students', component: StudentsListComponent, data: {task: 'Student List'}}, { path: 'admin', diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html index f275aad740..a54a599425 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html @@ -51,6 +51,7 @@ [tasks]="project.tasks" [selectedTaskDefinition$]="selectedTaskDefinition$" [isCollapsed]="taskListCollapsed" + [selectionUrlBase]="taskSelectionUrlBase" > } @else {
    diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts index 83ca228bcc..189b177e34 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts @@ -28,6 +28,7 @@ import {GlobalStateService, ViewType} from '../../index/global-state.service'; export class ProjectDashboardComponent implements OnInit { @Input() public project$: Observable; @Input() public defaultTaskListCollapsed = false; + @Input() public taskSelectionUrlBase: unknown[] | null = null; /** * The currently selected task definition - selected in the unit task list. diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html index ea67268a4d..cce514ee07 100644 --- a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html @@ -1,4 +1,4 @@ -
    +

    Mark portfolios

    Assess student portfolios

    diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html index 250032c055..acc95740ce 100644 --- a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html @@ -56,6 +56,7 @@

    Review progress of {{ project.student.name }}

    class="block min-h-fit min-w-0" [project$]="project$" [defaultTaskListCollapsed]="true" + [taskSelectionUrlBase]="taskSelectionUrlBase" > - - - @if (selectedProject) { - + @case ('progress') { + @if (selectedProject) { + + } } - - - @if (selectedProject) { - + @case ('staff-notes') { + @if (selectedProject) { + + } } - - - @if (selectedProject) { - + @case ('portfolio') { + @if (selectedProject) { + + } } - - + @case ('assessment') { + @if (selectedProject) { + + } + } + } +
    }
    diff --git a/src/app/units/states/portfolios/portfolios.component.ts b/src/app/units/states/portfolios/portfolios.component.ts index 4811403780..7144b754d5 100644 --- a/src/app/units/states/portfolios/portfolios.component.ts +++ b/src/app/units/states/portfolios/portfolios.component.ts @@ -1,27 +1,45 @@ -import {Component, Input, OnInit, ViewChild} from '@angular/core'; -import {MatTabGroup} from '@angular/material/tabs'; +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {MatTabChangeEvent} from '@angular/material/tabs'; import {ActivatedRoute, Router} from '@angular/router'; -import {Observable, first, of} from 'rxjs'; +import {BehaviorSubject, Observable, Subscription, first, of} from 'rxjs'; import {Project} from 'src/app/api/models/project'; import {Unit} from 'src/app/api/models/unit'; import {ProjectService} from 'src/app/api/services/project.service'; import {AlertService} from 'src/app/common/services/alert.service'; +type PortfolioTabKey = 'select' | 'progress' | 'staff-notes' | 'portfolio' | 'assessment'; + +interface PortfolioTab { + label: string; + routeSegment: PortfolioTabKey; + requiresProject: boolean; +} + @Component({ selector: 'f-portfolios', templateUrl: './portfolios.component.html', styleUrl: './portfolios.component.scss', standalone: false, }) -export class PortfoliosComponent implements OnInit { +export class PortfoliosComponent implements OnInit, OnDestroy { @Input() unit$: Observable; - // Exposed to child components + public readonly tabs: PortfolioTab[] = [ + {label: 'Select Student', routeSegment: 'select', requiresProject: false}, + {label: 'View Progress', routeSegment: 'progress', requiresProject: true}, + {label: 'View Staff Notes', routeSegment: 'staff-notes', requiresProject: true}, + {label: 'View Portfolio', routeSegment: 'portfolio', requiresProject: true}, + {label: 'Assess Portfolio', routeSegment: 'assessment', requiresProject: true}, + ]; + public unit: Unit = null; - public selectedProject: Project; + public selectedProject: Project | null = null; + public selectedProject$: BehaviorSubject = new BehaviorSubject(null); public loadingStudents = true; + public currentTab: PortfolioTab = this.tabs[0]; - @ViewChild('tabs') tabs!: MatTabGroup; + private subscriptions: Subscription[] = []; + private selectedProjectId: number | null = null; constructor( private projectService: ProjectService, @@ -30,42 +48,133 @@ export class PortfoliosComponent implements OnInit { private alertService: AlertService, ) {} - studentSelected(project: Project) { - this.selectedProject = null; + public ngOnInit(): void { + this.unit$ = this.unit$ ?? of(this.route.parent.snapshot.data.unit); + this.subscriptions.push( + this.unit$.pipe(first()).subscribe({ + next: (unit) => { + this.unit = unit; + this.unit.loadD2lMapping().subscribe(); + this.loadStudents(); + this.subscriptions.push( + this.route.paramMap.subscribe((params) => { + this.updateCurrentTabFromState(params.get('tab'), params.get('projectId')); + }), + ); + }, + error: (error) => { + this.alertService.error(`Failed to load unit: ${error}`, 6000); + this.router.navigateByUrl('/home'); + }, + }), + ); + } + + public ngOnDestroy(): void { + this.subscriptions.forEach((subscription) => subscription.unsubscribe()); + } + + public get currentIndex(): number { + const index = this.tabs.findIndex((tab) => tab.routeSegment === this.currentTab.routeSegment); + return index >= 0 ? index : 0; + } + + public get progressTaskSelectionUrlBase(): unknown[] | null { + if (!this.unit || !this.selectedProject) { + return null; + } - this.projectService.loadProject(project, this.unit).subscribe({ + return ['/units', this.unit.id, 'students', 'portfolios', this.selectedProject.id, 'progress']; + } + + public studentSelected(project: Project): void { + this.navigateToProject(project.id, 'progress'); + } + + public onTabChange(event: MatTabChangeEvent): void { + const nextTab = this.tabs[event.index] ?? this.tabs[0]; + this.currentTab = nextTab; + + if (nextTab.routeSegment === 'select' || !this.selectedProject) { + this.router.navigate(['/units', this.unit.id, 'students', 'portfolios'], {replaceUrl: true}); + return; + } + + this.navigateToProject(this.selectedProject.id, nextTab.routeSegment); + } + + private loadStudents(): void { + this.projectService.loadStudents(this.unit, false).subscribe({ + next: () => { + this.loadingStudents = false; + }, + error: (error) => { + this.alertService.error(`Failed to load unit: ${error}`, 6000); + this.router.navigateByUrl('/home'); + }, + }); + } + + private updateCurrentTabFromState( + tabParam?: string | null, + projectIdParam?: string | null, + ): void { + const projectId = projectIdParam ? Number(projectIdParam) : null; + const requestedTab = this.tabFromRoute(tabParam, !!projectId); + + this.currentTab = requestedTab; + + if (!projectId) { + this.selectedProjectId = null; + this.selectedProject = null; + this.selectedProject$.next(null); + return; + } + + if (this.selectedProject?.id === projectId) { + return; + } + + this.loadProject(projectId); + } + + private tabFromRoute(tabParam: string | null, hasProject: boolean): PortfolioTab { + if (!hasProject) { + return this.tabs[0]; + } + + const routeTab = this.tabs.find( + (tab) => tab.routeSegment === tabParam && tab.routeSegment !== 'select', + ); + + return routeTab ?? this.tabs.find((tab) => tab.routeSegment === 'progress') ?? this.tabs[0]; + } + + private loadProject(projectId: number): void { + this.selectedProjectId = projectId; + + this.projectService.loadProject(projectId, this.unit).subscribe({ next: (project) => { + if (this.selectedProjectId !== project.id) { + return; + } + this.selectedProject = project; - this.tabs.selectedIndex = 1; + this.selectedProject$.next(project); }, error: (error) => { + this.selectedProjectId = null; + this.selectedProject = null; + this.selectedProject$.next(null); this.alertService.error(`Failed to load project: ${error}`, 6000); console.error(error); }, }); } - ngOnInit(): void { - this.unit$ = this.unit$ ?? of(this.route.parent.snapshot.data.unit); - this.unit$?.pipe(first()).subscribe({ - next: (unit) => { - this.unit = unit; - this.unit.loadD2lMapping().subscribe(); - - this.projectService.loadStudents(unit, false).subscribe({ - next: () => { - this.loadingStudents = false; - }, - error: (error) => { - this.alertService.error(`Failed to load unit: ${error}`, 6000); - this.router.navigateByUrl('/home'); - }, - }); - }, - error: (error) => { - this.alertService.error(`Failed to load unit: ${error}`, 6000); - this.router.navigateByUrl('/home'); - }, + private navigateToProject(projectId: number, tab: PortfolioTabKey): void { + this.router.navigate(['/units', this.unit.id, 'students', 'portfolios', projectId, tab], { + replaceUrl: true, }); } } diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index f4e4c4e4d1..044f6a0b6b 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -18,6 +18,7 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { @Input() taskDefinitions: TaskDefinition[]; @Input() tasks: Task[]; @Input() isCollapsed = false; + @Input() selectionUrlBase: unknown[] | null = null; @HostBinding('class.collapsed') public get collapsedHostClass(): boolean { @@ -155,6 +156,12 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { } private buildSelectionUrlTree(taskDef: TaskDefinition | null) { + if (this.selectionUrlBase) { + return this.angularRouter.createUrlTree( + taskDef ? [...this.selectionUrlBase, taskDef.abbreviation] : this.selectionUrlBase, + ); + } + const unitId = this.route.parent?.snapshot.paramMap.get('unitId'); if (this.route.parent?.snapshot.data.unit && unitId) { return this.angularRouter.createUrlTree( From 0a9e7e4e807858686b7d66596e32aec0141b9ad3 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:03:36 +1000 Subject: [PATCH 1125/1531] refactor: move charts to mat cards --- .../progress-dashboard.component.html | 60 ++++++++----------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html index 93df2d92d1..02ac242529 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html @@ -56,50 +56,42 @@

    - -
    -
    -
    -

    Progress Burndown

    -

    - The burndown chart shows how much work remains for you to achieve your target grade. -

    -
    -
    -
    + + + Progress Burndown + + The burndown chart shows how much work remains for you to achieve your target grade. + + + -
    -
    - Aim to keep your - Complete - line close to or ahead of the - Target - line to keep on track. -
    -
    - - -
    -
    -
    -

    Task Statuses

    -

    - Breakdown summary of each of your task statuses. -

    +
    + Aim to keep your + Complete + line close to or ahead of the + Target + line to keep on track.
    -
    -
    + + + + + + Task Statuses + Breakdown summary of each of your task statuses + + -
    -
    + +
    From 4ff55627566f9004872c915658bd91bc348dd8e8 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:32:06 +1000 Subject: [PATCH 1126/1531] feat: check access token expiry locally before attempting request (#1270) --- src/app/api/models/user/user.ts | 1 + .../api/services/authentication.service.ts | 2 + .../common/services/http-error.interceptor.ts | 50 ++++++++++++------- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/app/api/models/user/user.ts b/src/app/api/models/user/user.ts index f020d22d54..df4d7c5846 100644 --- a/src/app/api/models/user/user.ts +++ b/src/app/api/models/user/user.ts @@ -21,6 +21,7 @@ export class User extends Entity { public receiveFeedbackNotifications: boolean; public hasRunFirstTimeSetup: boolean; public authenticationToken: string; + public authenticationTokenExpiry: string; public pronouns: string | null; public acceptedTiiEula: boolean; diff --git a/src/app/api/services/authentication.service.ts b/src/app/api/services/authentication.service.ts index b99fa5c05b..1f4ed2b7ff 100644 --- a/src/app/api/services/authentication.service.ts +++ b/src/app/api/services/authentication.service.ts @@ -14,6 +14,7 @@ import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global interface AuthResponse { user: object; auth_token: string; + auth_token_expiry: string; lti_token?: string; } @@ -175,6 +176,7 @@ export class AuthenticationService { // Set the user's authentication token for access to api. user.authenticationToken = response['auth_token']; + user.authenticationTokenExpiry = response['auth_token_expiry']; // Record the current user this.userService.currentUser = user; diff --git a/src/app/common/services/http-error.interceptor.ts b/src/app/common/services/http-error.interceptor.ts index 3de001b7ed..1e0264220e 100644 --- a/src/app/common/services/http-error.interceptor.ts +++ b/src/app/common/services/http-error.interceptor.ts @@ -37,27 +37,19 @@ export class HttpErrorInterceptor implements HttpInterceptor { } intercept(request: HttpRequest, next: HttpHandler): Observable> { - // const retryTimes: number = 3; - // const delayDuration: number = 100; + const request$ = this.isAccessTokenExpired(request) + ? throwError(() => new HttpErrorResponse({status: 419})) + : next.handle(request); - // TODO: Check for access token / refresh token expiration before trying the initial request - // .. This way we can avoid spamming console with 409 errors - - return next.handle(request).pipe( - // retryWhen(errors => errors - // .pipe( - // concatMap((error, count) => { - // if (count < retryTimes && (error.status === 400 || error.status === 0)) { - // return of(error.status); - // } - // return throwError(error); - // }), - // delay(delayDuration) - // ) - // ), + return request$.pipe( catchError((error: HttpErrorResponse) => { if (this.isAuthError(error)) { + if (this.isAccessTokenRequest(request)) { + return throwError(() => this.extractErrorMessage(error)); + } + if (!this.refreshTokenInProgress) { + console.log('Refreshing access token'); this.refreshTokenInProgress = true; this.refreshTokenSubject.next(null); return this.attemptRefresh$().pipe( @@ -70,6 +62,9 @@ export class HttpErrorInterceptor implements HttpInterceptor { if (this.isAuthError(err)) { this.authenticationService.timeoutAuthentication(); } + if (!(err instanceof HttpErrorResponse)) { + return throwError(() => err); + } return throwError(() => this.extractErrorMessage(err)); }), finalize(() => (this.refreshTokenInProgress = false)), @@ -78,8 +73,9 @@ export class HttpErrorInterceptor implements HttpInterceptor { return this.refreshTokenSubject.pipe( filter((result) => result !== null), take(1), - switchMap((_res) => { - return next.handle(this.injectToken(request)); + switchMap(() => next.handle(this.injectToken(request))), + catchError((err: HttpErrorResponse) => { + return throwError(() => this.extractErrorMessage(err)); }), ); } @@ -94,6 +90,22 @@ export class HttpErrorInterceptor implements HttpInterceptor { return error.status === 419 || (error.status === 403 && this.userService.isAnonymousUser()); } + private isAccessTokenExpired(request: HttpRequest) { + const user = this.userService.currentUser; + const expiry = Date.parse(user.authenticationTokenExpiry); + + return ( + !this.isAccessTokenRequest(request) && + !!user.authenticationToken && + !Number.isNaN(expiry) && + expiry <= Date.now() + ); + } + + private isAccessTokenRequest(request: HttpRequest) { + return request.url.endsWith('/auth/access-token'); + } + private extractErrorMessage(error: HttpErrorResponse) { let errorMessage: string; let logMessage: string = ''; From 5c95b4718e0ee01bf4db1e7e645c3f2f953d62ef Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:28:32 +1000 Subject: [PATCH 1127/1531] refactor: prevent camera running in background (#1210) * refactor: prevent camera running in background * refactor: improve ui scaling of tutor mobile view * chore: improve ui * fix: ensure scanner works after route loads * chore: improve ui * refactor: hide qr scanner in header if already in tutor discussion route * fix: ensure scanner works after route loads --- src/app/common/header/header.component.html | 2 +- src/app/common/header/header.component.ts | 4 + .../tutor-discussion.component.html | 6 +- .../tutor-discussion.component.ts | 169 ++++++++++++++---- 4 files changed, 142 insertions(+), 39 deletions(-) diff --git a/src/app/common/header/header.component.html b/src/app/common/header/header.component.html index 549c5189db..4f479836ec 100644 --- a/src/app/common/header/header.component.html +++ b/src/app/common/header/header.component.html @@ -52,7 +52,7 @@ > } - @if (currentUnit) { + @if (currentUnit && !isTutorDiscussionRoute) { diff --git a/src/app/common/header/header.component.ts b/src/app/common/header/header.component.ts index db60bca5b4..68ebc4dd99 100644 --- a/src/app/common/header/header.component.ts +++ b/src/app/common/header/header.component.ts @@ -182,6 +182,10 @@ export class HeaderComponent implements OnInit, OnDestroy { } } + public get isTutorDiscussionRoute(): boolean { + return this.router.url.split('?')[0].endsWith('/discussion'); + } + showSidekiqJob() { this.sidekiqJobsModalService.show(); } diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html index 2512e09030..843c67695b 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html @@ -48,7 +48,7 @@ }
    -
    +
    @if (project && project?.student) {
    @@ -66,8 +66,8 @@
    Click the QR code to open the scanner..
    } -
    diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts index 39ceefd689..99ca6117dd 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts @@ -1,5 +1,14 @@ import {Html5QrcodeScanner, Html5QrcodeScannerState} from 'html5-qrcode'; -import {AfterViewInit, Component, Input, ViewChild, ViewEncapsulation} from '@angular/core'; +import {DOCUMENT} from '@angular/common'; +import { + AfterViewInit, + Component, + Inject, + Input, + OnDestroy, + ViewChild, + ViewEncapsulation, +} from '@angular/core'; import {MatSelectionList} from '@angular/material/list'; import {MatTabChangeEvent} from '@angular/material/tabs'; import {ActivatedRoute, Router} from '@angular/router'; @@ -34,8 +43,10 @@ enum TutorDiscussionTabView { encapsulation: ViewEncapsulation.None, standalone: false, }) -export class TutorDiscussionComponent implements AfterViewInit { +export class TutorDiscussionComponent implements AfterViewInit, OnDestroy { private readonly discussedInClassNotePrefix = `I'm manually marking this discussed in class because...`; + private readonly mobileDiscussionViewportContent = + 'width=device-width, initial-scale=0.8, maximum-scale=5'; @Input() unitId: number; @Input() username: string; @@ -55,7 +66,9 @@ export class TutorDiscussionComponent implements AfterViewInit { public scanningQr: boolean = false; public loadingStudentData: boolean = false; - private html5QrcodeScanner: Html5QrcodeScanner; + private html5QrcodeScanner?: Html5QrcodeScanner; + private originalViewportContent: string | null = null; + private mobileDiscussionZoomApplied = false; private _unitId: number; private _username: string; @@ -64,6 +77,7 @@ export class TutorDiscussionComponent implements AfterViewInit { public footerTabView: TutorDiscussionTabView = TutorDiscussionTabView.SHOW_COMMENTS; constructor( + @Inject(DOCUMENT) private document: Document, private unitService: UnitService, private authService: AuthenticationService, private userService: UserService, @@ -78,6 +92,11 @@ export class TutorDiscussionComponent implements AfterViewInit { private taskService: TaskService, ) {} + public ngOnDestroy(): void { + this.stopQrScanner(); + this.restoreViewportZoom(); + } + public currentUserTutorsInStream(tutorialStream: TutorialStream): boolean { const user = this.userService.currentUser; const tutorials = this.unit.tutorials.filter( @@ -142,7 +161,7 @@ export class TutorDiscussionComponent implements AfterViewInit { this._username = this.username; this.getStudentTasks(); } else { - this.scanQrCode(); + setTimeout(() => this.scanQrCode()); } } else { this.getUnit().then((u) => { @@ -183,6 +202,7 @@ export class TutorDiscussionComponent implements AfterViewInit { public closeQrReader(): void { if (!this.project) { // Exiting the route entirely + this.stopQrScanner(); if (this.unitId) { this.router.navigate(['/units', this.unitId, 'tasks', 'inbox']); } else { @@ -191,11 +211,12 @@ export class TutorDiscussionComponent implements AfterViewInit { } else { // Close the camera view this.scanningQr = false; + this.stopQrScanner(); } } private changeProject() { - this.html5QrcodeScanner.pause(true); + this.html5QrcodeScanner?.pause(true); this.loadingStudentData = true; setTimeout(() => { try { @@ -205,14 +226,112 @@ export class TutorDiscussionComponent implements AfterViewInit { this.loadingStudentData = false; setTimeout(() => { - this.html5QrcodeScanner.resume(); + this.html5QrcodeScanner?.resume(); }, 2000); } }); } + private applyMobileDiscussionZoom(): void { + if (!window.matchMedia('(max-width: 768px)').matches) { + return; + } + + const viewport = this.document.querySelector('meta[name="viewport"]'); + if (!viewport) { + return; + } + + this.originalViewportContent ??= viewport.getAttribute('content'); + viewport.setAttribute('content', this.mobileDiscussionViewportContent); + this.mobileDiscussionZoomApplied = true; + } + + private restoreViewportZoom(): void { + if (!this.mobileDiscussionZoomApplied) { + return; + } + + const viewport = this.document.querySelector('meta[name="viewport"]'); + if (viewport && this.originalViewportContent) { + viewport.setAttribute('content', this.originalViewportContent); + } + + this.mobileDiscussionZoomApplied = false; + } + hideQrScannerBloat: boolean = true; + private async stopQrScanner(): Promise { + if (!this.html5QrcodeScanner) { + return; + } + + try { + await this.html5QrcodeScanner.clear(); + } catch (_e) { + // The scanner may already be stopped by its own controls. + } finally { + this.html5QrcodeScanner = undefined; + } + } + + private async getCameraPermissionState(): Promise { + if (!navigator.permissions?.query) { + return null; + } + + try { + const permissionStatus = await navigator.permissions.query({ + name: 'camera' as PermissionName, + }); + return permissionStatus.state; + } catch (_e) { + return null; + } + } + + private async prepareQrScannerCamera(): Promise { + const cachedScannerData = localStorage.getItem('HTML5_QRCODE_DATA'); + const cameraPermissionState = await this.getCameraPermissionState(); + if (cachedScannerData) { + try { + const html5QrcodeData = JSON.parse(cachedScannerData); + if (html5QrcodeData?.hasPermission && cameraPermissionState === 'granted') { + this.hideQrScannerBloat = html5QrcodeData.lastUsedCameraId ? true : false; + return; + } + } catch (_e) { + localStorage.removeItem('HTML5_QRCODE_DATA'); + } + } + + // Trigger video permissions once so device labels are available for back camera selection. + // Stopping these tracks releases the camera; the browser keeps the permission grant. + const stream = await navigator.mediaDevices.getUserMedia({video: true}); + + try { + const devices = await navigator.mediaDevices.enumerateDevices(); + + // Find the deviceId of the back camera + const backCameras = devices.filter( + (d) => d.kind === 'videoinput' && d.label.toLowerCase().includes('back camera'), + ); + + const html5QrcodeData = { + hasPermission: true, + lastUsedCameraId: backCameras[0]?.deviceId ?? null, + }; + localStorage.setItem('HTML5_QRCODE_DATA', JSON.stringify(html5QrcodeData)); + + // Hide most of the UI if we found and set the back camera + // Otherwise, we need to reveal the UI so that the user can select which camera to use + this.hideQrScannerBloat = html5QrcodeData.lastUsedCameraId ? true : false; + } finally { + stream.getTracks().forEach((track) => track.stop()); + } + } + public scanQrCode() { if (this.attendance && !this.selectedTaskDefinition) { this.alertService.error('You must select a task first', 3000); @@ -222,39 +341,13 @@ export class TutorDiscussionComponent implements AfterViewInit { this.scanningQr = true; this.loadingStudentData = false; - if ( - this.html5QrcodeScanner && - this.html5QrcodeScanner.getState() === Html5QrcodeScannerState.PAUSED - ) { + if (this.html5QrcodeScanner?.getState() === Html5QrcodeScannerState.PAUSED) { this.html5QrcodeScanner.resume(); } else { - this.html5QrcodeScanner?.clear(); - - // Trigger video permissions - // If we call getUserMedia when html5QrcodeScanner is already active, the scanner will break on iOS - navigator.mediaDevices - .getUserMedia({video: true}) + this.stopQrScanner() + .then(() => this.prepareQrScannerCamera()) .then(() => { - return navigator.mediaDevices.enumerateDevices(); - }) - .then((devices) => { - // Find the deviceId of the back camera - const backCameras = devices.filter( - (d) => d.kind === 'videoinput' && d.label.toLowerCase().includes('back camera'), - ); - - const html5QrcodeData = { - hasPermission: true, - lastUsedCameraId: backCameras[0]?.deviceId ?? null, - }; - localStorage.setItem('HTML5_QRCODE_DATA', JSON.stringify(html5QrcodeData)); - - // Hide most of the UI if we found and set the back camera - // Otherwise, we need to reveal the UI so that the user can select which camera to use - this.hideQrScannerBloat = html5QrcodeData.lastUsedCameraId ? true : false; - setTimeout(() => { - // Only init the scanner once and let it run in the background this.html5QrcodeScanner = new Html5QrcodeScanner( 'qr-reader', // id of the div in the html {fps: 10, qrbox: 250}, @@ -270,6 +363,10 @@ export class TutorDiscussionComponent implements AfterViewInit { }, ); }); + }) + .catch((_e) => { + this.scanningQr = false; + this.alertService.error('Camera permission is required to scan QR codes', 3000); }); } } @@ -534,6 +631,8 @@ export class TutorDiscussionComponent implements AfterViewInit { this.project = project; this.scanningQr = false; this.loadingStudentData = false; + this.stopQrScanner(); + this.applyMobileDiscussionZoom(); }) .catch((e) => { console.error(e); From 4cdae07eb5bef0f9866927892e92b6b80dde0c74 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:36:05 +1000 Subject: [PATCH 1128/1531] feat: submission history (#1269) * feat: submission history * refactor: improve tab order * refactor: merge history components * chore: format * fix: add task status fallbacks * fix: manually add back code block styling --- src/app/api/models/doubtfire-model.ts | 2 + .../models/overseer/overseer-assessment.ts | 4 +- src/app/api/models/submission-history.ts | 34 ++ src/app/api/models/task-definition.ts | 1 + src/app/api/models/task-status.ts | 2 +- .../services/overseer-assessment.service.ts | 1 + .../services/submission-history.service.ts | 44 +++ .../api/services/task-definition.service.ts | 3 + .../status-icon/status-icon.component.html | 8 +- .../status-icon/status-icon.component.ts | 27 +- src/app/doubtfire-angular.module.ts | 4 +- .../submission-files-modal.component.ts | 8 +- .../task-overseer-report.component.html | 353 ++++++++++-------- .../task-overseer-report.component.ts | 129 ++++--- .../task-dashboard.component.html | 10 +- .../task-dashboard.component.ts | 71 +--- .../states/dashboard/selected-task.service.ts | 8 +- .../task-submission-history.component.html | 43 --- .../task-submission-history.component.scss | 188 ---------- .../task-submission-history.component.ts | 110 ------ .../task-definition-upload.component.html | 16 + .../task-definition-upload.component.ts | 17 +- 22 files changed, 432 insertions(+), 651 deletions(-) create mode 100644 src/app/api/models/submission-history.ts create mode 100644 src/app/api/services/submission-history.service.ts delete mode 100644 src/app/tasks/task-submission-history/task-submission-history.component.html delete mode 100644 src/app/tasks/task-submission-history/task-submission-history.component.scss delete mode 100644 src/app/tasks/task-submission-history/task-submission-history.component.ts diff --git a/src/app/api/models/doubtfire-model.ts b/src/app/api/models/doubtfire-model.ts index 9ee73db62a..4c04633b82 100644 --- a/src/app/api/models/doubtfire-model.ts +++ b/src/app/api/models/doubtfire-model.ts @@ -18,6 +18,7 @@ export * from './unit'; export * from './project'; export * from './task'; export * from './task-definition'; +export * from './submission-history'; export * from './learning-outcome'; export * from './tutorial-enrolment'; export * from './unit-role'; @@ -53,6 +54,7 @@ export * from '../services/task.service'; export * from '../services/tutorial.service'; export * from '../services/tutorial-stream.service'; export * from '../services/overseer-assessment.service'; +export * from '../services/submission-history.service'; export * from '../services/campus.service'; export * from '../services/user.service'; export * from '../services/unit-role.service'; diff --git a/src/app/api/models/overseer/overseer-assessment.ts b/src/app/api/models/overseer/overseer-assessment.ts index f658c57986..20e5d959d3 100644 --- a/src/app/api/models/overseer/overseer-assessment.ts +++ b/src/app/api/models/overseer/overseer-assessment.ts @@ -2,9 +2,10 @@ import {Entity, EntityCache, EntityMapping} from 'ngx-entity-service'; import {AppInjector} from 'src/app/app-injector'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {Task} from '../doubtfire-model'; +import {SubmissionArchive} from '../submission-history'; import {OverseerStepResult} from './overseer-step-result'; -export class OverseerAssessment extends Entity { +export class OverseerAssessment extends Entity implements SubmissionArchive { id: number; // overseerStepId: number; timestamp: Date; @@ -16,6 +17,7 @@ export class OverseerAssessment extends Entity { createdAt?: Date; updatedAt?: Date; taskId?: number; + submissionHistoryId?: number; totalSteps: number; passedSteps: number; diff --git a/src/app/api/models/submission-history.ts b/src/app/api/models/submission-history.ts new file mode 100644 index 0000000000..d65888b64a --- /dev/null +++ b/src/app/api/models/submission-history.ts @@ -0,0 +1,34 @@ +import {Entity} from 'ngx-entity-service'; +import {AppInjector} from 'src/app/app-injector'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Task} from './task'; + +export interface SubmissionArchive { + id: number; + task?: Task; + timestamp: Date; + timestampString: string; + hasSubmissionFiles?: boolean; + submissionFilesUrl(): string; +} + +export class SubmissionHistory extends Entity implements SubmissionArchive { + id: number; + task?: Task; + taskId?: number; + timestamp: Date; + timestampString: string; + createdAt?: Date; + hasSubmissionFiles?: boolean; + overseerAssessmentId?: number; + + constructor(task?: Task) { + super(); + this.task = task; + } + + public submissionFilesUrl(): string { + const constants = AppInjector.get(DoubtfireConstants); + return `${constants.API_URL}/projects/${this.task.project.id}/task_def_id/${this.task.definition.id}/submission_histories/${this.id}/files`; + } +} diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index d884b4b78f..e128d60cfc 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -17,6 +17,7 @@ export interface UploadRequirement { type: string; tiiCheck?: boolean; tiiPct?: number; + submissionHistory?: boolean; } export interface SimilarityCheck { diff --git a/src/app/api/models/task-status.ts b/src/app/api/models/task-status.ts index d2894a4478..a452b22d5c 100644 --- a/src/app/api/models/task-status.ts +++ b/src/app/api/models/task-status.ts @@ -482,6 +482,6 @@ export class TaskStatus { } public static statusClass(status: TaskStatusEnum | undefined): string { - return status?.replace(new RegExp('_', 'g'), '-'); + return status?.replace(new RegExp('_', 'g'), '-') ?? 'not-started'; } } diff --git a/src/app/api/services/overseer-assessment.service.ts b/src/app/api/services/overseer-assessment.service.ts index 1200c13a35..c206952ec5 100644 --- a/src/app/api/services/overseer-assessment.service.ts +++ b/src/app/api/services/overseer-assessment.service.ts @@ -24,6 +24,7 @@ export class OverseerAssessmentService extends EntityService 'id', 'submissionTimestamp', 'taskId', + 'submissionHistoryId', 'createdAt', 'updatedAt', ['taskStatus', 'result_task_status'], diff --git a/src/app/api/services/submission-history.service.ts b/src/app/api/services/submission-history.service.ts new file mode 100644 index 0000000000..e65d1053ce --- /dev/null +++ b/src/app/api/services/submission-history.service.ts @@ -0,0 +1,44 @@ +import {EntityService} from 'ngx-entity-service'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {Observable} from 'rxjs'; +import {SubmissionHistory} from 'src/app/api/models/submission-history'; +import {Task} from 'src/app/api/models/task'; +import API_URL from 'src/app/config/constants/apiUrl'; + +@Injectable() +export class SubmissionHistoryService extends EntityService { + protected readonly endpointFormat = + 'projects/:project_id:/task_def_id/:td_id:/submission_histories/:id:'; + + constructor(httpClient: HttpClient) { + super(httpClient, API_URL); + + this.mapping.addKeys( + 'id', + 'taskId', + 'createdAt', + 'hasSubmissionFiles', + 'overseerAssessmentId', + { + keys: ['timestamp', 'submission_timestamp'], + toEntityFn: (data) => new Date(Number(data['submission_timestamp']) * 1000), + }, + ['timestampString', 'submission_timestamp'], + ); + } + + public createInstanceFrom(_json: object, task?: Task): SubmissionHistory { + return new SubmissionHistory(task); + } + + public queryForTask(task: Task): Observable { + return this.query( + { + project_id: task.project.id, + td_id: task.definition.id, + }, + {constructorParams: task}, + ); + } +} diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 5bb0e6baca..578b0838e6 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -66,6 +66,7 @@ export class TaskDefinitionService extends CachedEntityService { type: upreq.type, tii_check: upreq.tiiCheck, tii_pct: upreq.tiiPct, + submission_history: upreq.submissionHistory, }; }), ); @@ -78,6 +79,7 @@ export class TaskDefinitionService extends CachedEntityService { type: string; tii_check: boolean; tii_pct: number; + submission_history: boolean; }[] )?.map((upreq) => { return { @@ -86,6 +88,7 @@ export class TaskDefinitionService extends CachedEntityService { type: upreq.type, tiiCheck: upreq.tii_check, tiiPct: upreq.tii_pct, + submissionHistory: upreq.submission_history, }; }); }, diff --git a/src/app/common/status-icon/status-icon.component.html b/src/app/common/status-icon/status-icon.component.html index 0165a2d2a4..45bd7cbd89 100644 --- a/src/app/common/status-icon/status-icon.component.html +++ b/src/app/common/status-icon/status-icon.component.html @@ -1,6 +1,6 @@
    {{ statusIcon(status) }}{{ statusIcon }}
    diff --git a/src/app/common/status-icon/status-icon.component.ts b/src/app/common/status-icon/status-icon.component.ts index e2794943bf..56e2cf060a 100644 --- a/src/app/common/status-icon/status-icon.component.ts +++ b/src/app/common/status-icon/status-icon.component.ts @@ -8,20 +8,31 @@ import {TaskStatus, TaskStatusEnum} from 'src/app/api/models/task-status'; standalone: false, }) export class StatusIconComponent implements OnInit { - @Input() status: TaskStatusEnum = 'not_started'; + @Input() status?: TaskStatusEnum = 'not_started'; @Input() showTooltip: boolean; @Input() compact = false; - statusIcon: (status: TaskStatusEnum) => string; - statusLabel: (status: TaskStatusEnum) => string; - statusClass: (status: TaskStatusEnum) => string; - ngOnInit(): void { if (this.showTooltip == null) { this.showTooltip = true; } - this.statusIcon = (status: TaskStatusEnum) => TaskStatus.STATUS_MATERIAL_ICONS.get(status); - this.statusLabel = (status: TaskStatusEnum) => TaskStatus.STATUS_LABELS.get(status); - this.statusClass = (status: TaskStatusEnum) => TaskStatus.statusClass(status); + } + + get statusIcon(): string { + return TaskStatus.STATUS_MATERIAL_ICONS.get(this.resolvedStatus) ?? 'pause'; + } + + get statusLabel(): string { + return TaskStatus.STATUS_LABELS.get(this.resolvedStatus) ?? 'Not Started'; + } + + get statusClass(): string { + return TaskStatus.statusClass(this.resolvedStatus); + } + + get resolvedStatus(): TaskStatusEnum { + return this.status && TaskStatus.STATUS_KEYS.includes(this.status) + ? this.status + : 'not_started'; } } diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index ca76573084..518f8f3eb5 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -122,6 +122,7 @@ import { OverseerAssessmentService, OverseerImageService, ProjectService, + SubmissionHistoryService, TaskCommentService, TaskService, TaskSimilarityService, @@ -303,7 +304,6 @@ import {ScormCommentComponent} from './tasks/task-comments-viewer/scorm-comment/ import {ScormExtensionCommentComponent} from './tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component'; import {TaskAssessmentCommentComponent} from './tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component'; import {TaskCommentsViewerComponent} from './tasks/task-comments-viewer/task-comments-viewer.component'; -import {TaskSubmissionHistoryComponent} from './tasks/task-submission-history/task-submission-history.component'; import {UnitStudentEnrolmentModalComponent} from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component'; import {AnalyticsTutorTimesComponent} from './units/states/analytics/directives/analytics-tutor-times.component'; import {UnitAnalyticsComponent} from './units/states/analytics/unit-analytics-route.component'; @@ -497,7 +497,6 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { StatusIconComponent, TaskAssessmentCommentComponent, TaskAssessmentModalComponent, - TaskSubmissionHistoryComponent, GradeIconComponent, HeaderComponent, UnitDropdownComponent, @@ -666,6 +665,7 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { ActivityTypeService, OverseerImageService, OverseerAssessmentService, + SubmissionHistoryService, EmojiService, FileDownloaderService, CheckForUpdateService, diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts index 00a8e1588d..47d19f2a7e 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts @@ -2,7 +2,7 @@ import * as monaco from 'monaco-editor'; import {HttpResponse} from '@angular/common/http'; import {Component, Inject, OnDestroy, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; -import {OverseerAssessment} from 'src/app/api/models/doubtfire-model'; +import {SubmissionArchive} from 'src/app/api/models/submission-history'; import { ArchiveFileEntry, isArchiveCodeOrTextFile, @@ -13,10 +13,10 @@ import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloa import {AlertService} from 'src/app/common/services/alert.service'; export interface SubmissionFilesModalData { - assessment: OverseerAssessment; + assessment: SubmissionArchive; assessmentNumber?: number; assessmentIsMostRecent?: boolean; - comparedWith?: OverseerAssessment; + comparedWith?: SubmissionArchive; comparedWithNumber?: number; comparedWithIsMostRecent?: boolean; } @@ -151,7 +151,7 @@ export class SubmissionFilesModalComponent implements OnInit, OnDestroy { } } - private downloadSubmissionArchive(assessment: OverseerAssessment): Promise { + private downloadSubmissionArchive(assessment: SubmissionArchive): Promise { return new Promise((resolve, reject) => { this.fileDownloader.downloadBlob( assessment.submissionFilesUrl(), diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html index 668fb5daaf..4d8eaaad19 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.html @@ -1,55 +1,79 @@
    - +
    - - @for (oa of overseerAssessments; track oa; let idx = $index) { - - - - - Submission {{ overseerAssessments.length - idx }}: {{ oa.timestamp | humanizedDate }} - @if (idx === 0) { - (Most recent) - } - @if (isComparisonSource(oa)) { - (Selected for comparison) - } - - @if (oa.reportReady) { +@if (loading) { +
    + +
    +} @else { + + @for (history of histories; track history.id; let idx = $index) { + + + + @if (assessmentFor(history); as oa) { + + } +
    +
    + Submission {{ histories.length - idx }} + @if (idx === 0) { + (Most recent) + } + @if (isComparisonSource(history)) { + (Selected for comparison) + } +
    +
    + {{ history.timestamp | date: 'dd/MM/yyyy HH:mm' }} +
    +
    +
    +
    - {{ oa.passedSteps }} / {{ oa.totalSteps }} - @if (oa.passedSteps === oa.totalSteps) { - done - } @else { - cancel + @if (assessmentFor(history); as oa) { + @if (oa.reportReady) { + Click to view Overseer report + {{ oa.passedSteps }} / {{ oa.totalSteps }} + @if (oa.passedSteps === oa.totalSteps) { + done + } @else { + cancel + } + } @else { + + Tests In Progress + + + } } - @if (oa.hasSubmissionFiles && currentUnitRole) { + + @if (history.hasSubmissionFiles && currentUnitRole) { -
    - - @if (hasComparisonSourceFor(oa)) { - - } @else if (isComparisonSource(oa)) { + } @else if (isComparisonSource(history)) {
    - } @else { -
    - Tests In Progress - -
    - } -
    +
    - - @for (result of oa.stepResultsCache.values | async; track result.id; let idx = $index) { - - - - Step {{ idx + 1 }}: {{ result.overseerStep?.displayName }} - @if (result.pass) { - done - } @else { - cancel - } - + @if (assessmentFor(history); as oa) { + + @for (result of oa.stepResultsCache.values | async; track result.id; let idx = $index) { + + + + Step {{ idx + 1 }}: {{ result.overseerStep?.displayName }} + @if (result.pass) { + done + } @else { + cancel + } + - - + + - @if (!result.pass) { -

    - {{ result.feedbackMessage }} -

    - } + @if (!result.pass) { +

    + {{ result.feedbackMessage }} +

    + } - @if ( - result.expectedOutput && - result.expectedOutput !== result.stdout && - (result.overseerStep?.stepType === 'output_diff' || !result.overseerStep) - ) { -
    - + @if ( + result.expectedOutput && + result.expectedOutput !== result.stdout && + (result.overseerStep?.stepType === 'output_diff' || !result.overseerStep) + ) { +
    + - - + + - -
    - @if (viewOutput === 'diff' || viewOutput === 'split_diff') { - @if (result.expectedOutput !== result.stdout) { - + +
    + @if (viewOutput === 'diff' || viewOutput === 'split_diff') { + @if (result.expectedOutput !== result.stdout) { + + } + } @else if (viewOutput === 'your_output') { + + } @else if (viewOutput === 'expected_output') { + + } + } @else if (result.stdout) { +
    {{result.stdout}}
    + } @else if (result.pass) { +
    + SUCCESS +
    +
    + (No Output) +
    } - } @else if (viewOutput === 'your_output') { - - } @else if (viewOutput === 'expected_output') { - - } - } @else if (result.stdout) { -
    {{result.stdout}}
    - } @else if (result.pass) { -
    SUCCESS
    -
    - (No Output) -
    +
    } -
    - } - @if (loadingAssessments.has(oa.id)) { -
    - -
    - } @else { - @for (skipped of oa.stepsSkipped; track skipped.id; let idx = $index) { - - - - - - Step {{ oa.stepResultsCache.currentValues.length + idx + 1 }}: - {{ skipped?.displayName ?? '-' }} - (Skipped) - + @if (loadingAssessments.has(oa.id)) { +
    + +
    + } @else { + @for (skipped of oa.stepsSkipped; track skipped.id; let idx = $index) { + + + + + + Step {{ oa.stepResultsCache.currentValues.length + idx + 1 }}: + {{ skipped?.displayName ?? '-' }} + (Skipped) + - pause - - - } + pause +
    +
    + } + } +
    } -
    - - } @empty { -
    - subtitles_off -
    No submission reports for this task.
    -
    - } - + + } @empty { +
    + subtitles_off +
    No retained submissions for this task.
    +
    + } + +} diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts index c017ed3fe2..d9868ab3ef 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts @@ -1,12 +1,14 @@ import {Component, Input, OnInit} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {MatMenuTrigger} from '@angular/material/menu'; +import {forkJoin} from 'rxjs'; import {OverseerAssessment, UnitRole, UserService} from 'src/app/api/models/doubtfire-model'; +import {SubmissionHistory} from 'src/app/api/models/submission-history'; import {Task} from 'src/app/api/models/task'; import {OverseerAssessmentService} from 'src/app/api/services/overseer-assessment.service'; import {OverseerStepResultService} from 'src/app/api/services/overseer-step-result.service'; +import {SubmissionHistoryService} from 'src/app/api/services/submission-history.service'; import {AlertService} from 'src/app/common/services/alert.service'; -import {TaskSubmissionService} from 'src/app/common/services/task-submission.service'; import {SubmissionFilesModalComponent} from './submission-files-modal/submission-files-modal.component'; @Component({ @@ -18,11 +20,14 @@ import {SubmissionFilesModalComponent} from './submission-files-modal/submission export class TaskOverseerReportComponent implements OnInit { @Input() task: Task; @Input() loadOverseerAssessmentId?: number; - public comparisonSourceAssessmentId: number | null = null; + public histories: SubmissionHistory[] = []; + public overseerAssessments: OverseerAssessment[] = []; + public comparisonSourceHistoryId: number | null = null; + public loading = false; constructor( private alerts: AlertService, - private submissions: TaskSubmissionService, + private submissionHistoryService: SubmissionHistoryService, private overseerAssessmentService: OverseerAssessmentService, private overseerStepResultsService: OverseerStepResultService, private dialog: MatDialog, @@ -98,38 +103,38 @@ export class TaskOverseerReportComponent implements OnInit { this.viewOutput = 'expected_output'; } - public overseerAssessments: OverseerAssessment[] = []; - - public get comparisonSourceAssessment(): OverseerAssessment | null { - if (!this.comparisonSourceAssessmentId) { + public get comparisonSourceHistory(): SubmissionHistory | null { + if (!this.comparisonSourceHistoryId) { return null; } - return ( - this.overseerAssessments.find( - (assessment) => assessment.id === this.comparisonSourceAssessmentId, - ) ?? null - ); + return this.histories.find((history) => history.id === this.comparisonSourceHistoryId) ?? null; } ngOnInit(): void { - this.loadAssessments(); + this.loadHistory(); } - loadAssessments(isRefresh: boolean = false) { + loadHistory(isRefresh: boolean = false) { if (isRefresh) { this.loadOverseerAssessmentId = null; } - this.overseerAssessmentService.queryForTask(this.task).subscribe({ - next: (assessments) => { + this.loading = true; + + forkJoin({ + histories: this.submissionHistoryService.queryForTask(this.task), + assessments: this.overseerAssessmentService.queryForTask(this.task), + }).subscribe({ + next: ({histories, assessments}) => { + this.histories = histories; this.overseerAssessments = assessments; + if ( - this.comparisonSourceAssessmentId && - !this.overseerAssessments.some( - (assessment) => assessment.id === this.comparisonSourceAssessmentId, - ) + this.comparisonSourceHistoryId && + !this.histories.some((history) => history.id === this.comparisonSourceHistoryId) ) { - this.comparisonSourceAssessmentId = null; + this.comparisonSourceHistoryId = null; } + for (const oa of this.overseerAssessments) { for (const result of oa.stepResultsCache.currentValues) { result.overseerStep = this.task.definition.overseerStepsCache.currentValues.find( @@ -137,26 +142,39 @@ export class TaskOverseerReportComponent implements OnInit { ); } } + this.loading = false; }, error: (error) => { - this.alerts.error(`Failed to load overseer reports: ${error}`, 6000); + this.loading = false; + this.alerts.error(`Failed to load submission history: ${error}`, 6000); }, }); } loadingAssessments: Set = new Set(); - onAssessmentOpen(overseerAssesment: OverseerAssessment) { - if (this.loadOverseerAssessmentId === overseerAssesment.id) { + assessmentFor(history: SubmissionHistory): OverseerAssessment | undefined { + return this.overseerAssessments.find( + (assessment) => assessment.submissionHistoryId === history.id, + ); + } + + onHistoryOpen(history: SubmissionHistory) { + const overseerAssessment = this.assessmentFor(history); + if (!overseerAssessment) { + return; + } + + if (this.loadOverseerAssessmentId === overseerAssessment.id) { setTimeout(() => { - const el = document.getElementById(`oa-panel-${overseerAssesment.id}`); + const el = document.getElementById(`history-panel-${history.id}`); el?.scrollIntoView({behavior: 'smooth', block: 'start'}); }, 250); } - this.loadingAssessments.add(overseerAssesment.id); + this.loadingAssessments.add(overseerAssessment.id); - this.overseerStepResultsService.getOverseerStepResults(overseerAssesment).subscribe({ + this.overseerStepResultsService.getOverseerStepResults(overseerAssessment).subscribe({ next: () => { for (const oa of this.overseerAssessments) { for (const result of oa.stepResultsCache.currentValues) { @@ -165,11 +183,11 @@ export class TaskOverseerReportComponent implements OnInit { ); } } - this.loadingAssessments.delete(overseerAssesment.id); + this.loadingAssessments.delete(overseerAssessment.id); }, error: (error) => { console.error(error); - this.loadingAssessments.delete(overseerAssesment.id); + this.loadingAssessments.delete(overseerAssessment.id); }, }); } @@ -178,66 +196,55 @@ export class TaskOverseerReportComponent implements OnInit { event.stopPropagation(); } - isComparisonSource(assessment: OverseerAssessment): boolean { - return this.comparisonSourceAssessmentId === assessment.id; + isComparisonSource(history: SubmissionHistory): boolean { + return this.comparisonSourceHistoryId === history.id; } - hasComparisonSourceFor(assessment: OverseerAssessment): boolean { - return ( - this.comparisonSourceAssessmentId !== null && - this.comparisonSourceAssessmentId !== assessment.id - ); + hasComparisonSourceFor(history: SubmissionHistory): boolean { + return this.comparisonSourceHistoryId !== null && this.comparisonSourceHistoryId !== history.id; } - selectComparisonSource( - assessment: OverseerAssessment, - event?: Event, - menuTrigger?: MatMenuTrigger, - ) { + selectComparisonSource(history: SubmissionHistory, event?: Event, menuTrigger?: MatMenuTrigger) { event?.stopPropagation(); - this.comparisonSourceAssessmentId = assessment.id; + this.comparisonSourceHistoryId = history.id; menuTrigger?.closeMenu(); - this.alerts.message(`Selected submission ${assessment.timestampString} for comparison.`, 3500); + this.alerts.message(`Selected submission ${history.timestampString} for comparison.`, 3500); } clearComparisonSource(event?: Event) { event?.stopPropagation(); - this.comparisonSourceAssessmentId = null; + this.comparisonSourceHistoryId = null; } - compareWithSelected(assessment: OverseerAssessment, event?: Event) { + compareWithSelected(history: SubmissionHistory, event?: Event) { event?.stopPropagation(); - const selected = this.comparisonSourceAssessment; - if (!selected || selected.id === assessment.id) { + const selected = this.comparisonSourceHistory; + if (!selected || selected.id === history.id) { return; } - this.openSubmissionFilesDialog(assessment, selected); + this.openSubmissionFilesDialog(history, selected); } - viewSubmissionFiles(assessment: OverseerAssessment, event?: Event) { + viewSubmissionFiles(history: SubmissionHistory, event?: Event) { event?.stopPropagation(); - this.openSubmissionFilesDialog(assessment); + this.openSubmissionFilesDialog(history); } - private openSubmissionFilesDialog( - assessment: OverseerAssessment, - comparedWith?: OverseerAssessment, - ) { - const assessmentIndex = this.overseerAssessments.findIndex((item) => item.id === assessment.id); + private openSubmissionFilesDialog(history: SubmissionHistory, comparedWith?: SubmissionHistory) { + const historyIndex = this.histories.findIndex((item) => item.id === history.id); const comparedWithIndex = comparedWith - ? this.overseerAssessments.findIndex((item) => item.id === comparedWith.id) + ? this.histories.findIndex((item) => item.id === comparedWith.id) : -1; this.dialog.open(SubmissionFilesModalComponent, { data: { - assessment, - assessmentNumber: - assessmentIndex >= 0 ? this.overseerAssessments.length - assessmentIndex : undefined, - assessmentIsMostRecent: assessmentIndex === 0, + assessment: history, + assessmentNumber: historyIndex >= 0 ? this.histories.length - historyIndex : undefined, + assessmentIsMostRecent: historyIndex === 0, comparedWith, comparedWithNumber: - comparedWithIndex >= 0 ? this.overseerAssessments.length - comparedWithIndex : undefined, + comparedWithIndex >= 0 ? this.histories.length - comparedWithIndex : undefined, comparedWithIsMostRecent: comparedWithIndex === 0, }, maxWidth: '95vw', diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html index de593aa7b3..e4ad3411dd 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html @@ -19,6 +19,7 @@ @if (canAccessStaffViews) { + @@ -29,7 +30,6 @@ - @@ -69,12 +69,6 @@ folder_zip Download submitted files - @if (overseerEnabled) { - - }
    @@ -150,7 +144,7 @@
    } } - @case (DashboardViews.overseer) { + @case (DashboardViews.submission_history) { @if (canAccessStaffViews) {
    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts index 70f8e8febf..7aecf1173d 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts @@ -6,8 +6,6 @@ import {Task} from 'src/app/api/models/task'; import {TaskService} from 'src/app/api/services/task.service'; import {UserService} from 'src/app/api/services/user.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; -import {TaskAssessmentModalService} from 'src/app/common/modals/task-assessment-modal/task-assessment-modal.service'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {SelectedTaskService} from '../../selected-task.service'; import {DashboardViews} from '../../selected-task.service'; @@ -36,41 +34,28 @@ export class TaskDashboardComponent implements OnInit, OnChanges { taskSheetPdfUrl?: string; taskSubmissionPdfUrl?: string; }; - public overseerEnabledObs = this.doubtfire.IsOverseerEnabled; public currentView: DashboardViews; - - public currentIndex; + public currentIndex = 0; + + private readonly tabViews: DashboardViews[] = [ + DashboardViews.details, + DashboardViews.task, + DashboardViews.submission, + DashboardViews.submission_history, + DashboardViews.similarity, + DashboardViews.staff_notes, + DashboardViews.tutor_notes, + ]; onTabChange(event: MatTabChangeEvent) { - switch (event.index) { - case 0: - this.setSelectedDashboardView(DashboardViews.details); - break; - case 1: - this.setSelectedDashboardView(DashboardViews.task); - break; - case 2: - this.setSelectedDashboardView(DashboardViews.submission); - break; - case 3: - this.setSelectedDashboardView(DashboardViews.similarity); - break; - case 4: - this.setSelectedDashboardView(DashboardViews.overseer); - break; - case 5: - this.setSelectedDashboardView(DashboardViews.staff_notes); - break; - case 6: - this.setSelectedDashboardView(DashboardViews.tutor_notes); - break; + const view = this.tabViews[event.index]; + if (view !== undefined) { + this.setSelectedDashboardView(view); } } constructor( - private doubtfire: DoubtfireConstants, private taskService: TaskService, - private taskAssessmentModal: TaskAssessmentModalService, private fileDownloader: FileDownloaderService, private route: ActivatedRoute, private userService: UserService, @@ -116,28 +101,14 @@ export class TaskDashboardComponent implements OnInit, OnChanges { } private tabIndexForView(view: DashboardViews): number { - switch (view) { - case DashboardViews.task: - return 1; - case DashboardViews.submission: - return 2; - case DashboardViews.similarity: - return this.canAccessStaffViews ? 3 : 0; - case DashboardViews.overseer: - return this.canAccessStaffViews ? 4 : 0; - case DashboardViews.staff_notes: - return this.canAccessStaffViews ? 5 : 0; - case DashboardViews.tutor_notes: - return this.canAccessTutorNotes ? 6 : 0; - default: - return 0; - } + const index = this.tabViews.indexOf(view); + return index >= 0 ? index : 0; } private canAccessDashboardView(view: DashboardViews): boolean { switch (view) { case DashboardViews.similarity: - case DashboardViews.overseer: + case DashboardViews.submission_history: case DashboardViews.staff_notes: case DashboardViews.discussion_prompts: return this.canAccessStaffViews; @@ -148,10 +119,6 @@ export class TaskDashboardComponent implements OnInit, OnChanges { } } - public get overseerEnabled() { - return this.doubtfire.IsOverseerEnabled.value && this.task?.overseerEnabled; - } - public get canAccessStaffViews(): boolean { return this.tutor || !!this.currentUnitRole; } @@ -184,10 +151,6 @@ export class TaskDashboardComponent implements OnInit, OnChanges { ); } - showSubmissionHistoryModal() { - this.taskAssessmentModal.show(this.task); - } - downloadSubmission() { this.fileDownloader.downloadFile(this.urls.taskSubmissionPdfAttachmentUrl, 'submission.pdf'); } diff --git a/src/app/projects/states/dashboard/selected-task.service.ts b/src/app/projects/states/dashboard/selected-task.service.ts index e130494610..5d770fd253 100644 --- a/src/app/projects/states/dashboard/selected-task.service.ts +++ b/src/app/projects/states/dashboard/selected-task.service.ts @@ -12,7 +12,7 @@ export enum DashboardViews { staff_notes, tutor_notes, discussion_prompts, - overseer, + submission_history, } @Injectable({ @@ -84,7 +84,11 @@ export class SelectedTaskService { } public showOverseerReports() { - this.currentView$.next(DashboardViews.overseer); + this.currentView$.next(DashboardViews.submission_history); + } + + public showSubmissionHistory() { + this.currentView$.next(DashboardViews.submission_history); } public showDiscussionPrompts() { diff --git a/src/app/tasks/task-submission-history/task-submission-history.component.html b/src/app/tasks/task-submission-history/task-submission-history.component.html deleted file mode 100644 index 4bf56849ca..0000000000 --- a/src/app/tasks/task-submission-history/task-submission-history.component.html +++ /dev/null @@ -1,43 +0,0 @@ -
    -
    -
    -
    Submissions
    - - @for (tab of tabs; track tab) { - -
    -
    - {{ tab.timestamp | humanizedDate }} -
    - @if (tab.status === 'pre_queued') { - schedule - } @else { - - } -
    -
    - } -
    -
    -
    - - @for (selTab of selectedTab.content; track selTab) { - -
    {{ selTab.result }} 
    - -
    - } -
    -
    -
    -
    diff --git a/src/app/tasks/task-submission-history/task-submission-history.component.scss b/src/app/tasks/task-submission-history/task-submission-history.component.scss deleted file mode 100644 index b6884f11bf..0000000000 --- a/src/app/tasks/task-submission-history/task-submission-history.component.scss +++ /dev/null @@ -1,188 +0,0 @@ -@use 'sass:color'; - -// @import "src/styles/mixins/flex-center"; -//== Media queries breakpoints -// -//## Define the breakpoints at which your layout will change, adapting to different screen sizes. - -// Extra small screen / phone -//** Deprecated `$screen-xs` as of v3.0.1 -// $screen-xs: 480px !default; -// //** Deprecated `$screen-xs-min` as of v3.2.0 -// $screen-xs-min: $screen-xs !default; -// //** Deprecated `$screen-phone` as of v3.0.1 -// $screen-phone: $screen-xs-min !default; - -// // Small screen / tablet -// //** Deprecated `$screen-sm` as of v3.0.1 -// $screen-sm: 768px !default; -// $screen-sm-min: $screen-sm !default; -// //** Deprecated `$screen-tablet` as of v3.0.1 -// $screen-tablet: $screen-sm-min !default; - -// // Medium screen / desktop -// //** Deprecated `$screen-md` as of v3.0.1 -// $screen-md: 992px !default; -// $screen-md-min: $screen-md !default; -// //** Deprecated `$screen-desktop` as of v3.0.1 -// $screen-desktop: $screen-md-min !default; - -// // Large screen / wide desktop -// //** Deprecated `$screen-lg` as of v3.0.1 -// $screen-lg: 1200px !default; -// $screen-lg-min: $screen-lg !default; -// //** Deprecated `$screen-lg-desktop` as of v3.0.1 -// $screen-lg-desktop: $screen-lg-min !default; - -// // So media queries don't overlap when required, provide a maximum -// $screen-xs-max: ($screen-sm-min - 1) !default; -// $screen-sm-max: ($screen-md-min - 1) !default; -// $screen-md-max: ($screen-lg-min - 1) !default; - -.submission-wrap { - height: 100%; - display: flex; -} - -.submission-main { - flex: 1; - display: flex; - width: 100%; -} - -@media (max-width: 992px) { - .submission-main { - flex-direction: column; - } -} - -.submission-sidenav, -.submisson-result { - overflow-y: scroll; - padding: 1em 1em 0 1em; -} - -/*TODO(mdc-migration): The following rule targets internal classes of list that may no longer apply for the MDC version.*/ -/*TODO(mdc-migration): The following rule targets internal classes of list that may no longer apply for the MDC version.*/ -mat-list.list-group { - overflow-y: scroll; -} - -.terminal-output { - padding: 10px; - margin: 1em 0 0 0; - // margin-bottom: 0; -} - -.submission-sidenav { - flex: 1; - width: 100%; - padding: 0; - display: inline-block; - line-height: 1; -} - -.submission-sidenav.panel.panel-primary { - margin-bottom: 0; -} - -@media (max-width: 992px) { - .submission-sidenav.panel.panel-primary { - margin-bottom: 2em; - } -} - -.submission-sidenav .panel-heading { - line-height: 2; -} - -.submisson-result { - flex: 3; - height: 100%; - padding-top: 0; - - padding-right: 0; -} -@media (max-width: 992px) { - .submisson-result { - padding-left: 0; - } -} - -.panel-heading.panel-title.submission-heading { - position: sticky; - top: 0; - z-index: 2; -} - -pre { - white-space: pre-wrap; -} - -/*TODO(mdc-migration): The following rule targets internal classes of list that may no longer apply for the MDC version.*/ -/*TODO(mdc-migration): The following rule targets internal classes of list that may no longer apply for the MDC version.*/ -mat-list, -mat-nav-list { - padding-top: 0; - border-bottom-width: 1px; - padding-bottom: 1px; -} - -/*TODO(mdc-migration): The following rule targets internal classes of tabs that may no longer apply for the MDC version.*/ -/*TODO(mdc-migration): The following rule targets internal classes of tabs that may no longer apply for the MDC version.*/ -mat-tab-header.mat-mdc-tab-header { - margin-bottom: 5px; - position: sticky; - top: 0; - z-index: 2; - background: white; -} - -/*TODO(mdc-migration): The following rule targets internal classes of tabs that may no longer apply for the MDC version.*/ -/*TODO(mdc-migration): The following rule targets internal classes of tabs that may no longer apply for the MDC version.*/ -mat-tab-body.mat-mdc-tab-body.mat-tab-body-active { - z-index: 1; -} - -.submission-heading { - border-radius: 0; - background-color: #337ab7; - color: white; -} - -@mixin custom-box-shadow($color) { - box-shadow: -15px 0 $color inset; -} - -/*TODO(mdc-migration): The following rule targets internal classes of list that may no longer apply for the MDC version.*/ -/*TODO(mdc-migration): The following rule targets internal classes of list that may no longer apply for the MDC version.*/ -mat-list-item { - border-bottom-width: 1px !important; - border-color: #f5f5f5; - transition: all 200ms ease-out; - transition-property: box-shadow, padding-right; - display: flex; - &:hover, - &:focus { - cursor: pointer; - text-decoration: none; - background-color: #f5f5f5; - @include custom-box-shadow(color.adjust(#0079d8, $lightness: 15%)); - } - &.selected { - background-color: rgb(231, 231, 231); - @include custom-box-shadow(#0079d8); - } -} - -.panel > .list-group:last-child .list-group-item:last-child, -.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { - border-color: #f5f5f5; - border-style: solid; - border-radius: 0; -} - -.panel .panel-heading { - margin-bottom: 0; - padding: 6px 15px; -} diff --git a/src/app/tasks/task-submission-history/task-submission-history.component.ts b/src/app/tasks/task-submission-history/task-submission-history.component.ts deleted file mode 100644 index 9f98d50832..0000000000 --- a/src/app/tasks/task-submission-history/task-submission-history.component.ts +++ /dev/null @@ -1,110 +0,0 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; -import {Subject} from 'rxjs'; -import {OverseerAssessmentService, Task} from 'src/app/api/models/doubtfire-model'; -import {OverseerAssessment} from 'src/app/api/models/doubtfire-model'; -import {AlertService} from 'src/app/common/services/alert.service'; -import {TaskSubmissionService} from 'src/app/common/services/task-submission.service'; - -@Component({ - selector: 'f-task-submission-history', - templateUrl: './task-submission-history.component.html', - styleUrls: ['./task-submission-history.component.scss'], - standalone: false, -}) -export class TaskSubmissionHistoryComponent implements OnInit { - @Input() task: Task; - @Output() hasNoData: EventEmitter = new EventEmitter(); - tabs: OverseerAssessment[]; - // timestamps: string[]; - selectedTab: OverseerAssessment = new OverseerAssessment(); - @Input() refreshTrigger: Subject; - - constructor( - private alerts: AlertService, - private submissions: TaskSubmissionService, - private overseerAssessmentService: OverseerAssessmentService, - ) {} - - ngOnInit() { - this.fillTabs(); - - this.refreshTrigger.subscribe(() => { - this.fillTabs(); - }); - } - - private handleError(error: Error) { - this.alerts.error('Error: ' + error, 6000); - } - - fillTabs(): void { - // this.submissions.getLatestSubmissionsTimestamps(this.task); - // let transformedData = this.overseerAssessmentService.queryForTask(this.task).pipe( - // map(data => { - // return data.map((ts: any) => { - // let result = new SubmissionTab(); - // timestamp: new Date(ts.submission_timestamp * 1000), - // content: '', - // timestampString: ts.submission_timestamp, - // taskStatus: ts.result_task_status, - // submissionStatus: ts.status, - // createdAt: ts.created_at, - // updatedAt: ts.updated_at, - // taskId: ts.task_id}; - // }); - // }) - // ); - - this.overseerAssessmentService.queryForTask(this.task).subscribe( - (tabs) => { - if (tabs.length === 0) { - this.tabs = [new OverseerAssessment()]; - this.selectedTab.content = [ - {label: 'No Data', result: 'There are no submissions for this task at the moment.'}, - ]; - } else { - this.tabs = tabs; - } - // if (this.selectedTab.timestampString) { - // this.openSubmission(tabs.filter(x => x.timestampString === this.selectedTab.timestampString)[0]); - // } else { - // this.openSubmission(tabs[0]); - // } - }, - (error) => { - this.handleError(error); - }, - ); - } - - triggerOverseer(tab: OverseerAssessment) { - this.overseerAssessmentService.triggerOverseer(tab).subscribe( - (_response: OverseerAssessment) => { - this.alerts.success('Overseer assessment will be run again.', 2000); - }, - (_response: Error) => { - this.alerts.error('Error requesting overseer assessment.', 6000); - }, - ); - } - - openSubmission(tab: OverseerAssessment) { - this.selectedTab = tab; - // this.selectedTab.timestamp = tab.timestamp; - // this.selectedTab.timestampString = tab.timestampString; - // this.selectedTab.taskStatus = tab.taskStatus; - // this.selectedTab.submissionStatus = tab.submissionStatus; - - this.submissions.getSubmissionByTimestamp(this.task, tab.timestampString).subscribe( - (sub) => { - this.selectedTab.content = sub; - this.hasNoData.emit(false); - }, - (error) => { - // TODO: make error handling more readable... - this.selectedTab.content = [{label: 'Error', result: error?.error?.error}]; - this.hasNoData.emit(true); - }, - ); - } -} diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html index 8b28d600bf..0649d98406 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html @@ -22,6 +22,16 @@
    Submission History + + Check Similarity
    +@if (missingOverseerSubmissionHistory) { +
    + Overseer requires at least one upload requirement to be retained in submission history. +
    +} + @if (taskDefinition.needsJplag) {
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts index 69c8e51fb2..3cbb9a03ed 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts @@ -14,7 +14,14 @@ export class TaskDefinitionUploadComponent { @Input() public taskDefinition: TaskDefinition; @ViewChild('upreqTable', {static: true}) table: MatTable; - public columns: string[] = ['file-name', 'file-type', 'tii-check', 'flag-pct', 'row-actions']; + public columns: string[] = [ + 'file-name', + 'file-type', + 'submission-history', + 'tii-check', + 'flag-pct', + 'row-actions', + ]; constructor(private constants: DoubtfireConstants) {} @@ -30,6 +37,7 @@ export class TaskDefinitionUploadComponent { name: '', tiiCheck: false, tiiPct: 30, + submissionHistory: false, }); this.table.renderRows(); } @@ -38,6 +46,13 @@ export class TaskDefinitionUploadComponent { return this.constants.IsTiiEnabled.value; } + public get missingOverseerSubmissionHistory(): boolean { + return ( + this.taskDefinition.assessmentEnabled && + !this.taskDefinition.uploadRequirements.some((requirement) => requirement.submissionHistory) + ); + } + public removeUpReq(upreq: UploadRequirement) { this.taskDefinition.uploadRequirements = this.taskDefinition.uploadRequirements.filter( (anUpReq) => anUpReq.key != upreq.key, From 1ffc7ad7b9dc18f22be32bf6313bfde97957dd2f Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:11:59 +1000 Subject: [PATCH 1129/1531] refactor: sort attributes (#1280) --- eslint.config.js | 14 +++ .../edit-profile/edit-profile.component.html | 2 +- .../activity-type-list.component.html | 50 ++++---- .../campus-list/campus-list.component.html | 88 +++++++------- .../overseer-image-list.component.html | 68 +++++------ ...eate-new-unit-modal-content.component.html | 18 +-- .../new-teaching-period-dialog.component.html | 38 +++--- .../teaching-period-list.component.html | 44 +++---- .../teaching-period-unit-import.dialog.html | 36 +++--- .../admin/states/units/units.component.html | 44 +++---- .../admin/states/users/users.component.html | 50 ++++---- .../tii-action-log.component.html | 44 +++---- .../archive-viewer.component.html | 24 ++-- .../audio-player/audio-player.component.html | 4 +- .../audio-comment-recorder.html | 24 ++-- .../microphone-tester-component.html | 14 +-- .../edit-profile-form.component.html | 78 ++++++------ .../feedback-template-editor.component.html | 70 +++++------ .../common/file-drop/file-drop.component.html | 14 +-- .../file-uploader.component.html | 14 +-- .../file-viewer/file-viewer.component.html | 12 +- src/app/common/footer/footer.component.html | 76 ++++++------ .../grade-icon/grade-icon.component.html | 4 +- src/app/common/header/header.component.html | 38 +++--- .../task-dropdown.component.html | 38 +++--- .../unit-dropdown.component.html | 30 ++--- .../hero-sidebar/hero-sidebar.component.html | 4 +- .../learning-outcome-editor.component.html | 52 ++++---- .../nested-csv-download-modal.component.html | 4 +- .../calendar-modal.component.html | 28 ++--- .../comments-modal.component.html | 2 +- .../confirmation-modal.component.html | 4 +- .../csv-result-modal.component.html | 24 ++-- .../csv-upload-modal.component.html | 4 +- .../task-date-slider.component.html | 6 +- ...ussed-in-class-reason-modal.component.html | 6 +- .../extension-modal.component.html | 22 ++-- .../modals/qr-modal/qr-modal.component.html | 2 +- .../scorm-extension-modal.component.html | 16 +-- .../sidekiq-jobs-modal.component.html | 4 +- .../sidekiq-progress-modal.component.html | 2 +- .../spec-con-modal.component.html | 10 +- .../task-assessment-modal.component.html | 8 +- .../obect-select/object-select.component.html | 4 +- .../pdf-viewer-panel.component.html | 4 +- .../pdf-viewer/pdf-viewer.component.html | 30 ++--- .../project-progress-gauge.component.html | 18 +-- src/app/common/services/alert.component.html | 2 +- .../status-icon/status-icon.component.html | 6 +- .../submission-files-download.component.html | 8 +- .../common/unit-code/unit-code.component.html | 2 +- .../user-badge/user-badge.component.html | 18 +-- .../common/user-icon/user-icon.component.html | 2 +- .../unauthorised/unauthorised.component.html | 2 +- .../unavailable-card.component.html | 2 +- .../accept-eula/accept-eula.component.html | 4 +- ...ember-contribution-assigner.component.html | 26 ++-- .../group-member-list.component.html | 22 ++-- .../group-selector.component.html | 40 +++---- .../group-set-manager.component.html | 24 ++-- .../group-set-selector.component.html | 2 +- src/app/home/states/home/home.component.html | 34 +++--- .../lti-dashboard.component.html | 39 +++--- .../lti-unit-link.component.html | 11 +- .../project-progress-dashboard.component.html | 8 +- .../progress-dashboard.component.html | 12 +- .../task-planner-card.component.html | 2 +- .../task-list-item.component.html | 8 +- .../task-assessment-card.component.html | 8 +- .../task-description-card.component.html | 6 +- .../submission-files-modal.component.html | 22 ++-- .../task-prerequisites-card.component.html | 2 +- .../task-scorm-card.component.html | 10 +- .../task-similarity-view.component.html | 18 +-- .../task-status-card.component.html | 14 +-- .../task-submission-card.component.html | 10 +- .../task-dashboard.component.html | 12 +- .../project-dashboard.component.html | 20 ++-- .../discussion-prompts.component.html | 2 +- .../project-groups-state.component.html | 2 +- .../project-groups.component.html | 2 +- .../jplag/jplag-report-viewer.component.html | 6 +- .../states/plan/project-plan.component.html | 2 +- ...planner-prerequisites-modal.component.html | 20 ++-- .../task-planner/task-planner.component.html | 44 +++---- ...tfolio-add-extra-files-step.component.html | 10 +- ...portfolio-grade-select-step.component.html | 8 +- ...earning-summary-report-step.component.html | 8 +- .../portfolio-review-step.component.html | 8 +- .../portfolio-welcome-step.component.html | 2 +- .../portfolio/portfolio-state.component.html | 16 +-- .../staff-notes/staff-notes.component.html | 22 ++-- .../tutor-discussion.component.html | 51 ++++---- .../tutor-notes/tutor-notes.component.html | 28 ++--- .../states/tutorials/tutorials.component.html | 42 +++---- .../states/sign-in/sign-in.component.html | 8 +- .../feedback-appeal-modal.component.html | 8 +- .../grade-task-modal.component.html | 18 +-- .../submission-type-modal.component.html | 10 +- .../upload-submission-modal.component.html | 36 +++--- .../project-tasks-list.component.html | 4 +- ...achment-confirmation-dialog.component.html | 6 +- .../discussion-prompt-composer-dialog.html | 10 +- .../discussion-prompt-composer.component.html | 20 ++-- .../task-comment-composer.component.html | 102 ++++++++-------- .../task-feedback-templates.component.html | 28 ++--- .../comment-bubble-action.component.html | 20 ++-- .../extension-comment.component.html | 6 +- .../intelligent-discussion-dialog.html | 38 +++--- ...telligent-discussion-player.component.html | 10 +- ...lligent-discussion-recorder.component.html | 2 +- .../pdf-image-comment.component.html | 2 +- .../scorm-comment.component.html | 10 +- .../scorm-extension-comment.component.html | 4 +- .../task-assessment-comment.component.html | 6 +- .../task-comments-viewer.component.html | 70 +++++------ ...nit-student-enrolment-modal.component.html | 4 +- .../analytics-tutor-times.component.html | 24 ++-- .../unit-analytics-route.component.html | 2 +- .../communication-actions.component.html | 26 ++-- ...ommunication-schedule-modal.component.html | 16 +-- .../communication-schedules.component.html | 2 +- .../communication-conditions.component.html | 30 ++--- .../unit-communications-editor.component.html | 90 +++++++------- .../d2l-unit-details-form.component.html | 14 +-- .../unit-details-editor.component.html | 18 +-- .../unit-group-set-editor.component.html | 58 ++++----- .../bulk-import-staff-modal.component.html | 10 +- .../unit-staff-editor.component.html | 76 ++++++------ .../student-campus-select.component.html | 2 +- .../student-tutorial-select.component.html | 2 +- .../unit-students-editor.component.html | 48 ++++---- .../task-definition-dates.component.html | 8 +- ...finition-discussion-prompts.component.html | 24 ++-- .../task-definition-editor.component.html | 36 +++--- .../task-definition-general.component.html | 10 +- .../task-definition-options.component.html | 4 +- ...verseer-script-editor-modal.component.html | 2 +- .../task-definition-overseer.component.html | 64 +++++----- ...sk-definition-prerequisites.component.html | 34 +++--- .../task-definition-resources.component.html | 18 +-- .../task-definition-scorm.component.html | 18 +-- .../task-definition-upload.component.html | 46 +++---- .../task-definition-who.component.html | 4 +- .../unit-task-editor.component.html | 48 ++++---- .../unit-tutorials-list.component.html | 112 +++++++++--------- .../unit-tutorials-manager.component.html | 4 +- .../edit/unit-admin-state.component.html | 4 +- .../unit-groups/unit-groups.component.html | 2 +- .../d2l-transfer.component.html | 12 +- .../portfolios-assessment.component.html | 8 +- .../portfolios-list.component.html | 96 +++++++-------- ...portfolios-project-progress.component.html | 2 +- .../download-staff-notes.component.html | 2 +- .../portfolios/portfolios.component.html | 8 +- .../upload-grades.component.html | 2 +- .../states/rollover/rollover.component.html | 6 +- .../students-list.component.html | 78 ++++++------ .../inbox-dashboard.component.html | 6 +- .../confirm-moderation-modal.component.html | 4 +- .../moderation/moderation.component.html | 36 +++--- ...ch-feedback-workflow-dialog.component.html | 2 +- .../staff-task-list.component.html | 77 ++++++------ .../task-claim/task-claim.component.html | 6 +- .../states/tasks/inbox/inbox.component.html | 46 +++---- .../unit-task-inbox-state.component.html | 8 +- .../task-details-view.component.html | 4 +- .../unit-task-list.component.html | 14 +-- .../task-viewer-state.component.html | 18 +-- .../progress-burndown-chart.component.html | 12 +- .../task-status-pie-chart.component.html | 6 +- .../task-visualisation.component.html | 2 +- src/app/welcome/welcome.component.html | 8 +- src/index.html | 16 +-- 174 files changed, 1812 insertions(+), 1804 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 6267e075a4..f724f8a890 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -102,6 +102,20 @@ module.exports = tseslint.config( // and inline templates as long as we have the `processor` set on our TypeScript config above) files: ['**/*.html'], rules: { + '@angular-eslint/template/attributes-order': [ + 'error', + { + alphabetical: true, + order: [ + 'STRUCTURAL_DIRECTIVE', + 'TEMPLATE_REFERENCE', + 'ATTRIBUTE_BINDING', + 'INPUT_BINDING', + 'TWO_WAY_BINDING', + 'OUTPUT_BINDING', + ], + }, + ], '@angular-eslint/template/prefer-control-flow': 'error', // TODO: remove below eslint rule ignores to improve accessibility '@angular-eslint/template/label-has-associated-control': 'off', diff --git a/src/app/account/edit-profile/edit-profile.component.html b/src/app/account/edit-profile/edit-profile.component.html index a7b9c7b6e9..43c2d6788c 100644 --- a/src/app/account/edit-profile/edit-profile.component.html +++ b/src/app/account/edit-profile/edit-profile.component.html @@ -1,6 +1,6 @@
    -
    +
    @if (!loading) { } diff --git a/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.html b/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.html index 1827e2e139..9322c53928 100644 --- a/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.html +++ b/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.html @@ -6,64 +6,64 @@

    Activities

    - - - + - - - - + - - - + - - - - + + +
    Name + + Name @if (!editing(activityType)) {
    {{ activityType.name }}
    } @else { - + }
    + - + Abbreviation + + Abbreviation @if (!editing(activityType)) {
    {{ activityType.abbreviation }}
    } @else { - + }
    + - + + @if (!editing(activityType)) {
    @@ -71,21 +71,21 @@

    Activities

    } @else {
    - @@ -93,7 +93,7 @@

    Activities

    }
    +
    diff --git a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html index 5045f1adcf..4985f3bb05 100644 --- a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html +++ b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.html @@ -7,58 +7,58 @@

    Campuses

    - - - + - - - - + - - - - + - - + - - - - + - - - + - - - - + + +
    Name + + Name @if (!editing(campus)) {
    {{ campus.name }}
    } @else { - + }
    + - + Abbreviation + + Abbreviation @if (!editing(campus)) {
    {{ campus.abbreviation }}
    } @else { - + }
    + - + Default Sync Mode + + Default Sync Mode @if (!editing(campus)) {
    {{ campus.mode | titlecase }} @@ -66,7 +66,7 @@

    Campuses

    } @else { Default Sync Mode - + @for (mode of syncModes; track mode) { {{ mode | titlecase }} @@ -76,10 +76,10 @@

    Campuses

    }
    + Default Sync Mode - + @for (mode of syncModes; track mode) { {{ mode | titlecase }} @@ -91,9 +91,9 @@

    Campuses

    - -
    Timezone + + Timezone @if (!editing(campus)) {
    {{ campus.timezone }} @@ -102,46 +102,46 @@

    Campuses

    Timezone - + }
    + Timezone - + Active + + Active @if (!editing(campus)) {
    - +
    } @else { - + }
    + + @if (!editing(campus)) {
    - @@ -149,22 +149,22 @@

    Campuses

    } @else {
    - @@ -172,7 +172,7 @@

    Campuses

    }
    +
    diff --git a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html index 62667efd70..50283a5848 100644 --- a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html +++ b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.html @@ -17,86 +17,86 @@

    - - - + - - - - + - - - + - + - - + - + - - + - + - - + - - - - + + +
    Name + + Name @if (!editing(overseerImage)) {
    {{ overseerImage.name }}
    } @else { - + }
    + - + Tag + + Tag @if (!editing(overseerImage)) {
    {{ overseerImage.tag }}
    } @else { - + }
    + - + + @if (!editing(overseerImage)) {
    -
    }
    Last Pulled + Last Pulled @if (!editing(overseerImage)) {
    {{ overseerImage.lastPulledDate | humanizedDate }}
    }
    Status + Status @if (!editing(overseerImage)) {
    }
    + @if (!editing(overseerImage)) {
    @@ -159,20 +159,20 @@

    } @else {
    - - -
    }

    +
    diff --git a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.html b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.html index dc3993eba3..466d9ab2e3 100644 --- a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.html +++ b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.html @@ -1,29 +1,29 @@

    Create Unit

    Unit Code - + Unit Name - + Teaching Period Custom teaching period @for (tp of teachingPeriods; track tp; let i = $index) { @@ -40,11 +40,11 @@

    Create Unit

    - + DD/MM/YYYY - DD/MM/YYYY @@ -53,7 +53,7 @@

    Create Unit

    } - +
    diff --git a/src/app/admin/states/teaching-periods/teaching-period-list/new-teaching-period-dialog.component.html b/src/app/admin/states/teaching-periods/teaching-period-list/new-teaching-period-dialog.component.html index b8ae10c207..3fc90d09f4 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-list/new-teaching-period-dialog.component.html +++ b/src/app/admin/states/teaching-periods/teaching-period-list/new-teaching-period-dialog.component.html @@ -1,9 +1,9 @@ -
    +
    - + @@ -12,8 +12,8 @@ -->
    - - +
    @@ -24,21 +24,21 @@ Teaching Period Name Teaching Period Year @@ -47,17 +47,17 @@ @@ -69,10 +69,10 @@ Active Until DD/MM/YYYY @@ -106,10 +106,10 @@

    Teaching Breaks for {{ newOrSelectedTeachingPeriod.name }}

    Break Start Date MM/DD/YYYY @@ -120,18 +120,18 @@

    Teaching Breaks for {{ newOrSelectedTeachingPeriod.name }}

    Number of weeks
    - - + - - + + - - + + - - + + - - + + - - + - - - + +
    Active - + Active + Name{{ element.name }}Name{{ element.name }} Start Date{{ element.startDate | date }}Start Date{{ element.startDate | date }} End date{{ element.endDate | date }}End date{{ element.endDate | date }} Active until{{ element.activeUntil | date }}Active until{{ element.activeUntil | date }} Actions + Actions
    - @@ -63,7 +63,7 @@

    Teaching periods

    +
    diff --git a/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.html b/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.html index 0860ef83b0..275098a43d 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.html +++ b/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.html @@ -2,8 +2,8 @@

    Import Units Into {{ data.teachingPeriod.name }}

    - - + - + - + - + - + - - + - - + +
    Unit Code + Unit Code Import Units Into {{ data.teachingPeriod.name }} - Source Unit + Source Unit Import Units Into {{ data.teachingPeriod.name }} - Unit Name + Unit Name @if (unitToImport.sourceUnit) { {{ unitToImport.sourceUnit.name }} } @if (!unitToImport.sourceUnit) { @@ -41,12 +41,12 @@

    Import Units Into {{ data.teachingPeriod.name }}

    -
    Main Convenor + Main Convenor Import Units Into {{ data.teachingPeriod.name }} - Status + Status {{ statusForUnit(unitToImport) }} +
    -
    +
    Unit Code(s) - + - +
    diff --git a/src/app/admin/states/units/units.component.html b/src/app/admin/states/units/units.component.html index 769db63c2d..d334c47c1c 100644 --- a/src/app/admin/states/units/units.component.html +++ b/src/app/admin/states/units/units.component.html @@ -15,66 +15,66 @@

    {{ title }}

    - - + - - + + - - - + - - + + - - + + - - + - + @if (mode === 'tutor') { } @if (mode === 'admin') { } @if (mode === 'student') { } @@ -123,7 +123,7 @@

    {{ title }}

    @if (mode === 'admin') { - diff --git a/src/app/admin/states/users/users.component.html b/src/app/admin/states/users/users.component.html index d301a4b144..fb093e9401 100644 --- a/src/app/admin/states/users/users.component.html +++ b/src/app/admin/states/users/users.component.html @@ -1,6 +1,6 @@
    -
    +

    {{ externalName }} Users

    Users Administration View

    @@ -9,9 +9,9 @@

    Users Administration View

    @@ -20,76 +20,76 @@

    Users Administration View

    Unit Code + Unit Code Name{{ element.name }}Name{{ element.name }} Unit Role + {{ element.unit_role }} Teaching Period + Teaching Period {{ element.teaching_period }} Start Date{{ element.start_date | date: 'EEE d MMM y' }}Start Date{{ element.start_date | date: 'EEE d MMM y' }} End Date{{ element.end_date | date: 'EEE d MMM y' }}End Date{{ element.end_date | date: 'EEE d MMM y' }} Active + Active @if (element.teachingPeriod) { @if (element.teachingPeriod.active && element.active) { @@ -96,25 +96,25 @@

    {{ title }}

    - - + - - + + - - + + - - + + - - + - - + + - - + +
    - + + First Name{{ user.firstName }}First Name{{ user.firstName }} Last Name{{ user.lastName }}Last Name{{ user.lastName }} Username{{ user.username }}Username{{ user.username }} Email + Email {{ user.email }} System Role{{ user.systemRole }}System Role{{ user.systemRole }}
    - + - + Bulk users operations
    diff --git a/src/app/admin/tii-action-log/tii-action-log.component.html b/src/app/admin/tii-action-log/tii-action-log.component.html index 9d1e9d85d3..4590ee9977 100644 --- a/src/app/admin/tii-action-log/tii-action-log.component.html +++ b/src/app/admin/tii-action-log/tii-action-log.component.html @@ -6,9 +6,9 @@

    Turnitin Actions

    @@ -17,58 +17,58 @@

    Turnitin Actions

    - - + - - + - - + - - + - - + - - + - - + - - + + - +
    Action Type + Action Type {{ action.description }} Last Run + Last Run {{ action.lastRun ? (action.lastRun | date: 'd LLL y') : '' }} Retries + Retries {{ action.retries }} Retry? + Retry? {{ action.retry }} Error Code + Error Code {{ action.errorCode }} Complete? + Complete? {{ action.complete }} Error Message + Error Message {{ action.errorMessage }} + @if (!(action.complete || action.retry)) { - } @@ -77,13 +77,13 @@

    Turnitin Actions

    -
    diff --git a/src/app/common/archive-viewer/archive-viewer.component.html b/src/app/common/archive-viewer/archive-viewer.component.html index 5368148a38..2b081b24ec 100644 --- a/src/app/common/archive-viewer/archive-viewer.component.html +++ b/src/app/common/archive-viewer/archive-viewer.component.html @@ -23,11 +23,11 @@ @if (!readOnly && saveEndpoint) {
    @@ -131,7 +131,7 @@ insert_drive_file

    This file type cannot be previewed.

    - @@ -143,7 +143,7 @@ } - + @for (node of nodes; track trackTreeNode($index, node)) { @if (node.isDirectory) {
    } @else { diff --git a/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html b/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html index 1638aeb89d..7e2f11bdd9 100644 --- a/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html +++ b/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html @@ -6,48 +6,48 @@
    diff --git a/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester-component.html b/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester-component.html index aca754db86..70df258499 100644 --- a/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester-component.html +++ b/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester-component.html @@ -6,14 +6,14 @@

    Step 1. Record some audio!

    - @@ -25,21 +25,21 @@

    Step 1. Record some audio!

    -
    +

    Step 2. Stop the recording, and playback the audio to make sure it's audible:

    -
    +

    Step 3. Check the "Ready to go" cehckbox below if you're all set!

    diff --git a/src/app/common/edit-profile-form/edit-profile-form.component.html b/src/app/common/edit-profile-form/edit-profile-form.component.html index f314ea254c..a51b79fee2 100644 --- a/src/app/common/edit-profile-form/edit-profile-form.component.html +++ b/src/app/common/edit-profile-form/edit-profile-form.component.html @@ -1,9 +1,9 @@
    @@ -11,7 +11,7 @@
    -
    @@ -21,7 +21,7 @@

    {{ user?.firstName }}

    -
    +
    - + Username - +
    -
    - +
    + First Name - +
    - + Second Name - +
    -
    +
    - + Preferred Name - +
    - + Custom Pronouns @if (user.systemRole === 'Student') { Student ID - + } Email - + @if (canSeeSystemRole) { - + System Role Administrator Convenor @@ -112,55 +112,55 @@

    {{ user?.firstName }}

    } -
    +
    Receive notifications for new messages
    Receive notifications when your portfolio is ready
    Receive notifications when new tasks are available
    -
    - + Send anonymous research statistics
    @if (tiiEnabled) { -
    +
    Accepted TurnItIn EULA
    } -
    +
    } @if (mode === 'edit') { diff --git a/src/app/common/feedback-template-editor/feedback-template-editor.component.html b/src/app/common/feedback-template-editor/feedback-template-editor.component.html index 1def23d307..c8fe0c13a1 100644 --- a/src/app/common/feedback-template-editor/feedback-template-editor.component.html +++ b/src/app/common/feedback-template-editor/feedback-template-editor.component.html @@ -7,17 +7,17 @@

    Edit Feedback Templates for Outcom #templateTable class="f-table selectable flex-grow" mat-table - [dataSource]="templateSource" matSort + [dataSource]="templateSource" (matSortChange)="sortTemplateData($event)" > -

    @if (feedbackTemplate.type === 'group') { folder @@ -28,60 +28,60 @@

    Edit Feedback Templates for Outcom

    ParentParent {{ getParentChipText(feedbackTemplate.parentChipId) }} Chip TextChip Text {{ feedbackTemplate.chipText }} DescriptionDescription {{ feedbackTemplate.description }} Comment TextComment Text {{ feedbackTemplate.commentText }} Summary TextSummary Text {{ feedbackTemplate.type === 'group' ? '' : feedbackTemplate.summaryText }} Task StatusTask Status @if (feedbackTemplate.taskStatus) { @@ -95,26 +95,26 @@

    Edit Feedback Templates for Outcom

    @if (feedbackTemplateHasChanges(feedbackTemplate)) { }
    @@ -133,7 +133,7 @@

    Edit Feedback Templates for Outcom
    - +
    Edit Feedback Templates for Outcom } -
    @@ -190,11 +190,11 @@

    Edit Template

    Chip Text @@ -202,11 +202,11 @@

    Edit Template

    Description
    @@ -216,10 +216,10 @@

    Edit Template

    Comment Text @@ -229,10 +229,10 @@

    Edit Template

    Summary Text @@ -253,8 +253,8 @@

    Edit Template

    @@ -24,11 +24,11 @@
    Select {{ upload.display.name }}
    } @if (asButton) { - + }
    } @@ -151,7 +151,7 @@
    Upload Summary

    Error Message: {{ uploadingInfo.error }}

    - diff --git a/src/app/common/file-viewer/file-viewer.component.html b/src/app/common/file-viewer/file-viewer.component.html index 537049c15b..88ad9162d4 100644 --- a/src/app/common/file-viewer/file-viewer.component.html +++ b/src/app/common/file-viewer/file-viewer.component.html @@ -7,21 +7,21 @@ > } } @if (fileType === 'html') {
    - +
    }
    diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index 8e470d155d..03f306d20b 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -15,12 +15,12 @@ @if (selectedTask?.definition?.assessInPortfolioOnly) { -->
    @if (!selectedTask?.hasPdf && selectedTask?.status === 'ready_for_feedback') { } } @if (currentUnit && currentUnitRole && currentUnitRole.tutorNoteCount > 0) { - @@ -60,10 +60,10 @@ @if (currentUser.role === 'Admin' || currentUser.role === 'Convenor') { diff --git a/src/app/common/header/task-dropdown/task-dropdown.component.html b/src/app/common/header/task-dropdown/task-dropdown.component.html index 05d42af095..5f7e239d25 100644 --- a/src/app/common/header/task-dropdown/task-dropdown.component.html +++ b/src/app/common/header/task-dropdown/task-dropdown.component.html @@ -44,7 +44,7 @@ } @if (currentActivity) { chevron_right - @if (currentProject !== null && currentView === 'PROJECT') { - - - - - } @if (unitRole && currentView === 'UNIT') { - - @if (isMentor || unitRole.role === 'Convenor') { - } @if (canMarkOverflowTask) { - } - - - - - - - - @if ( unitRole.role === 'Convenor' || unitRole.role === 'Admin' || unitRole.role === 'Auditor' ) { - diff --git a/src/app/common/header/unit-dropdown/unit-dropdown.component.html b/src/app/common/header/unit-dropdown/unit-dropdown.component.html index 7c0afe82e5..3bf5b0c19f 100644 --- a/src/app/common/header/unit-dropdown/unit-dropdown.component.html +++ b/src/app/common/header/unit-dropdown/unit-dropdown.component.html @@ -1,19 +1,19 @@
    @if (unit) { {{ menuState.menuOpen ? 'arrow_drop_up' : 'arrow_drop_down' }} } @if (!unit) { - } diff --git a/src/app/common/hero-sidebar/hero-sidebar.component.html b/src/app/common/hero-sidebar/hero-sidebar.component.html index 12145dfff4..09a24f8278 100644 --- a/src/app/common/hero-sidebar/hero-sidebar.component.html +++ b/src/app/common/hero-sidebar/hero-sidebar.component.html @@ -2,10 +2,10 @@
    Homepage Logo

    {{ externalName.value }}

    diff --git a/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html b/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html index 34110a1323..c8c668aabe 100644 --- a/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html +++ b/src/app/common/learning-outcome-editor/learning-outcome-editor.component.html @@ -3,45 +3,45 @@ #outcomeTable class="f-table selectable flex-grow" mat-table - [dataSource]="outcomeSource" matSort + [dataSource]="outcomeSource" (matSortChange)="sortOutcomeData($event)" > - Abbreviation + Abbreviation {{ learningOutcome.abbreviation }} - Short Description + Short Description {{ learningOutcome.shortDescription }} - Full Outcome Description + Full Outcome Description {{ learningOutcome.fullOutcomeDescription }} - Connected Learning Outcomes + Connected Learning Outcomes @for (outcome of getLinkedOutcomes(learningOutcome); track outcome.abbreviation) { @@ -52,26 +52,26 @@ - + @if (learningOutcomeHasChanges(learningOutcome)) { } - + @if (selectedOutcome) { @@ -126,10 +126,10 @@

    Edit Outcome

    Abbreviation @@ -137,8 +137,8 @@

    Edit Outcome

    Short Description @@ -148,8 +148,8 @@

    Edit Outcome

    Full Outcome Description @@ -169,15 +169,15 @@

    Edit Outcome

    } @for (outcome of filteredOutcomes(); track outcome) { @@ -191,7 +191,7 @@

    Edit Outcome

    -
    diff --git a/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.html b/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.html index d236474d37..9ce06782e4 100644 --- a/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.html +++ b/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.html @@ -8,7 +8,7 @@

    Download the {{ data.type }} CSV

    -
    +
    - +
    diff --git a/src/app/common/modals/calendar-modal/calendar-modal.component.html b/src/app/common/modals/calendar-modal/calendar-modal.component.html index 3af81bbb87..d7fe452d00 100644 --- a/src/app/common/modals/calendar-modal/calendar-modal.component.html +++ b/src/app/common/modals/calendar-modal/calendar-modal.component.html @@ -4,14 +4,14 @@

    Web calendar

    @@ -50,7 +50,7 @@

    Web calendar

    URL to subscribe to your web calendar from your iCalendar client.

    -
    +
    @@ -79,7 +79,7 @@

    Web calendar

    Options

    -
    +
    Included units in my calendar: @@ -89,8 +89,8 @@

    Options

    @for (project of includedProjects; track project) { {{ project.unit.code }} @@ -114,9 +114,9 @@

    Options

    Remind me @@ -124,15 +124,15 @@

    Options

    Time Unit - + Weeks Days Hours @@ -151,11 +151,11 @@

    Options

    newReminderUnit !== webcal.reminder.unit)) ) { +
    diff --git a/src/app/common/modals/comments-modal/comments-modal.component.html b/src/app/common/modals/comments-modal/comments-modal.component.html index c4e73f0de0..86be41b59f 100644 --- a/src/app/common/modals/comments-modal/comments-modal.component.html +++ b/src/app/common/modals/comments-modal/comments-modal.component.html @@ -1,9 +1,9 @@
    @if (taskComment.commentType === 'image') { Image attachment } @else if (taskComment.commentType === 'pdf') { diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.component.html b/src/app/common/modals/confirmation-modal/confirmation-modal.component.html index 4232cf08ee..894582f3c8 100644 --- a/src/app/common/modals/confirmation-modal/confirmation-modal.component.html +++ b/src/app/common/modals/confirmation-modal/confirmation-modal.component.html @@ -12,9 +12,9 @@

    {{ message }} - - +

    diff --git a/src/app/common/modals/csv-result-modal/csv-result-modal.component.html b/src/app/common/modals/csv-result-modal/csv-result-modal.component.html index a08ab98d77..6c963b1cc6 100644 --- a/src/app/common/modals/csv-result-modal/csv-result-modal.component.html +++ b/src/app/common/modals/csv-result-modal/csv-result-modal.component.html @@ -2,13 +2,12 @@

    {{ data.title }}

    @for (selection of csvResponseSelections; track selection.key) { {{ selection.label }} ({{ itemData(selection.key).length }}) @@ -33,10 +33,10 @@

    {{ data.title }}

    No data to show

    } @else {
    - +
    - - + - + - + - - + +
    Message + Message
    {{ displayMessage(row.item) }}
    @@ -45,8 +45,8 @@

    {{ data.title }}

    @for (columnId of dynamicColumnIds; track columnId) { -
    {{ headerForColumn(columnId) }} + {{ headerForColumn(columnId) }}
    {{ rowValueForColumn(row.rowObject, columnId) }}
    @@ -55,16 +55,16 @@

    {{ data.title }}

    } -
    Other + Other
    {{ row.otherData || '-' }}
    } @@ -81,5 +81,5 @@

    {{ data.title }}

    } - + diff --git a/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.html b/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.html index b4ccd4a6e2..11b7db0a4d 100644 --- a/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.html +++ b/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.html @@ -5,10 +5,10 @@

    {{ data.title }}

    {{ data.message }}

    } - +
    - + diff --git a/src/app/common/modals/date-change-modal/task-date-slider.component.html b/src/app/common/modals/date-change-modal/task-date-slider.component.html index 5cd73218b1..3471580e68 100644 --- a/src/app/common/modals/date-change-modal/task-date-slider.component.html +++ b/src/app/common/modals/date-change-modal/task-date-slider.component.html @@ -8,12 +8,12 @@ } @else { } - + @@ -21,8 +21,8 @@ @if (task.unit.allowFlexibleDates) { diff --git a/src/app/common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.component.html b/src/app/common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.component.html index dea3973f11..5eb196bf48 100644 --- a/src/app/common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.component.html +++ b/src/app/common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.component.html @@ -11,10 +11,10 @@

    {{ data.title }}

    Reason @if (reasonBody.length > 0 && !hasReasonBody) { Please enter at least {{ minimumReasonLength }} characters. @@ -27,7 +27,7 @@

    {{ data.title }}

    - diff --git a/src/app/common/modals/extension-modal/extension-modal.component.html b/src/app/common/modals/extension-modal/extension-modal.component.html index 50d7666b53..30beb590e5 100644 --- a/src/app/common/modals/extension-modal/extension-modal.component.html +++ b/src/app/common/modals/extension-modal/extension-modal.component.html @@ -5,14 +5,14 @@

    Extension request

    request shortly.

    - + Reason {{ extensionData.controls.extensionReason.value.length }} / {{ reasonMaxLength }}Extension request Choose a date @@ -44,13 +44,13 @@

    Extension request

    - +
    - + - + +
    diff --git a/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.html b/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.html index 5fb4608cbe..af7491923d 100644 --- a/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.html +++ b/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.html @@ -31,7 +31,7 @@

    @if (job?.status !== 'working' && job?.result) { - + }

    diff --git a/src/app/common/modals/spec-con-modal/spec-con-modal.component.html b/src/app/common/modals/spec-con-modal/spec-con-modal.component.html index 7bb56e4b07..182c88c0f6 100644 --- a/src/app/common/modals/spec-con-modal/spec-con-modal.component.html +++ b/src/app/common/modals/spec-con-modal/spec-con-modal.component.html @@ -6,18 +6,18 @@

    Grant Extension / Special Consideration

    Number of days - +
    - + } - +
    diff --git a/src/app/common/obect-select/object-select.component.html b/src/app/common/obect-select/object-select.component.html index 376fa15760..a94a68f337 100644 --- a/src/app/common/obect-select/object-select.component.html +++ b/src/app/common/obect-select/object-select.component.html @@ -3,10 +3,10 @@ {{ label }} } @if (placeholder) { diff --git a/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.html b/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.html index fa076921b2..2e65ecfe24 100644 --- a/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.html +++ b/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.html @@ -11,11 +11,11 @@
    @if (resourcesUrl) { - + download Resources } -
    diff --git a/src/app/common/pdf-viewer/pdf-viewer.component.html b/src/app/common/pdf-viewer/pdf-viewer.component.html index 1319e1642d..6cd74b6e19 100644 --- a/src/app/common/pdf-viewer/pdf-viewer.component.html +++ b/src/app/common/pdf-viewer/pdf-viewer.component.html @@ -1,45 +1,45 @@
    - -
    - + search @@ -51,21 +51,21 @@ @if (pdfBlobUrl) { @if (useNativePdfViewer) { @if (pdfBlobUrl) { - PDF Preview + PDF Preview } } @else { } } @else { - + }
    diff --git a/src/app/common/project-progress/project-progress-gauge.component.html b/src/app/common/project-progress/project-progress-gauge.component.html index 4ccf5a81a5..c1a7ba8dca 100644 --- a/src/app/common/project-progress/project-progress-gauge.component.html +++ b/src/app/common/project-progress/project-progress-gauge.component.html @@ -1,17 +1,17 @@ diff --git a/src/app/common/services/alert.component.html b/src/app/common/services/alert.component.html index e84b05de0c..e565e82c95 100644 --- a/src/app/common/services/alert.component.html +++ b/src/app/common/services/alert.component.html @@ -4,7 +4,7 @@ {{ data?.message }} - + diff --git a/src/app/common/status-icon/status-icon.component.html b/src/app/common/status-icon/status-icon.component.html index 45bd7cbd89..e50b255d47 100644 --- a/src/app/common/status-icon/status-icon.component.html +++ b/src/app/common/status-icon/status-icon.component.html @@ -1,10 +1,10 @@
    check_circle + check_circle

    Submitted files downloaded.

    - } @case ('failed') { - error + error

    Could not download submitted files.

    - diff --git a/src/app/common/unit-code/unit-code.component.html b/src/app/common/unit-code/unit-code.component.html index 3440a343ff..cd8724577c 100644 --- a/src/app/common/unit-code/unit-code.component.html +++ b/src/app/common/unit-code/unit-code.component.html @@ -1,5 +1,5 @@ -
    +
    @if (isDualBadge && shiftBetweenBadges) { @for (part of unitCodeParts; track part; let i = $index) { @if (i === currentIndex) { diff --git a/src/app/common/user-badge/user-badge.component.html b/src/app/common/user-badge/user-badge.component.html index 1d7a5b7806..4baab5ced6 100644 --- a/src/app/common/user-badge/user-badge.component.html +++ b/src/app/common/user-badge/user-badge.component.html @@ -1,32 +1,32 @@
    -
    +
    -

    +

    {{ selectedTask?.project.student.firstName }} {{ selectedTask?.project.student.lastName }}

    {{ selectedTask?.definition.name }}

    diff --git a/src/app/common/user-icon/user-icon.component.html b/src/app/common/user-icon/user-icon.component.html index 541a185dbe..82690f70c2 100644 --- a/src/app/common/user-icon/user-icon.component.html +++ b/src/app/common/user-icon/user-icon.component.html @@ -1,4 +1,4 @@ - + @if (unselected) { account_circle } diff --git a/src/app/errors/states/unauthorised/unauthorised.component.html b/src/app/errors/states/unauthorised/unauthorised.component.html index b8e7445b81..5f1e2da7ac 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.html +++ b/src/app/errors/states/unauthorised/unauthorised.component.html @@ -4,5 +4,5 @@

    Unauthorised

    You do not have sufficient permissions to access this resource, or your session has expired.

    - +
    diff --git a/src/app/errors/unavailable-card/unavailable-card.component.html b/src/app/errors/unavailable-card/unavailable-card.component.html index 6ff11c0f03..7ffa8ef259 100644 --- a/src/app/errors/unavailable-card/unavailable-card.component.html +++ b/src/app/errors/unavailable-card/unavailable-card.component.html @@ -1,6 +1,6 @@
    Temporarily Unavailable
    engineering diff --git a/src/app/eula/accept-eula/accept-eula.component.html b/src/app/eula/accept-eula/accept-eula.component.html index 621b43cb59..5de43cf604 100644 --- a/src/app/eula/accept-eula/accept-eula.component.html +++ b/src/app/eula/accept-eula/accept-eula.component.html @@ -7,10 +7,10 @@

    End User License Agreements

    -
    diff --git a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.html b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.html index 4fa53bfb59..3006223a53 100644 --- a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.html +++ b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.html @@ -1,35 +1,33 @@ - - + - - + - - + - - + +
    Team Member + Team Member {{ member.project.student.name }} Target Grade + Target Grade Contribution + Contribution @for (i of [].constructor(numStars); track $index) { person @@ -46,6 +46,6 @@
    diff --git a/src/app/groups/group-member-list/group-member-list.component.html b/src/app/groups/group-member-list/group-member-list.component.html index 164f335c9e..883b9b50a6 100644 --- a/src/app/groups/group-member-list/group-member-list.component.html +++ b/src/app/groups/group-member-list/group-member-list.component.html @@ -10,8 +10,8 @@ } @else { - - + - + - - + - + - - + +
    {{ unitRole ? 'Student ID' : '' }} + {{ unitRole ? 'Student ID' : '' }} @if (unitRole) { {{ member.student.username || 'N/A' }} } @@ -19,15 +19,15 @@ - Name + Name {{ member.student.name }} {{ unitRole ? 'Target Grade' : '' }} + {{ unitRole ? 'Target Grade' : '' }} @if (unitRole) { } @@ -35,11 +35,11 @@ - {{ canRemoveMembers ? 'Actions' : '' }} + {{ canRemoveMembers ? 'Actions' : '' }} @if (canRemoveMembers) { @if (!project && unitRole) { - } @else if (project && project.id === member.id) { @@ -49,7 +49,7 @@
    } diff --git a/src/app/groups/group-selector/group-selector.component.html b/src/app/groups/group-selector/group-selector.component.html index e5a6b7c5a0..ccc01c2506 100644 --- a/src/app/groups/group-selector/group-selector.component.html +++ b/src/app/groups/group-selector/group-selector.component.html @@ -12,7 +12,7 @@ @if (showGroupSetSelector) { - + @for (gs of unit.groupSets; track gs.id) { {{ gs.name }} } @@ -30,7 +30,7 @@ (ngModelChange)="onGroupNameChange()" /> -
    @@ -56,13 +56,13 @@

    There are no groups in this set

    } @else { - +
    - - + - + - - + - - - + +
    Name + Name @if (editing(group)) { - + } @else { {{ group.name || 'Not set' }} @@ -71,8 +71,8 @@ - Tutorial + Tutorial @if (editing(group)) { @@ -88,20 +88,20 @@ - + @if (unitRole) { Capacity Adjustment } + @if (unitRole) { @if (editing(group)) { } @else { @@ -112,8 +112,8 @@ - Capacity + Capacity @if (group.hasSpace()) { Available } @else { @@ -123,12 +123,12 @@ - + @if (unitRole || (project && selectedGroupSet.allowStudentsToManageGroups)) { Actions } + @if (isPartOfGroup(project, group)) {
    Joined
    } @else if (project && group.hasSpace() && selectedGroupSet.allowStudentsToManageGroups) { @@ -136,8 +136,8 @@ @if (!group.locked && !selectedGroupSet.locked) { @@ -172,7 +172,7 @@ lock_open } - } @@ -181,8 +181,8 @@
    } diff --git a/src/app/groups/group-set-manager/group-set-manager.component.html b/src/app/groups/group-set-manager/group-set-manager.component.html index b860cb4b14..72ecb5fec7 100644 --- a/src/app/groups/group-set-manager/group-set-manager.component.html +++ b/src/app/groups/group-set-manager/group-set-manager.component.html @@ -1,36 +1,36 @@
    @if (selectedGroup) { - + Members of @if (!editingGroupName) { {{ selectedGroup?.name }} @if (unitRole || selectedGroup.groupSet?.allowStudentsToManageGroups) { - } } @else { @if (unitRole || selectedGroup.groupSet?.allowStudentsToManageGroups) { - + - - } @@ -43,21 +43,21 @@ @if (unitRole) { - + @for (gs of unit.groupSets; track gs.id) { {{ gs.name }} } diff --git a/src/app/home/states/home/home.component.html b/src/app/home/states/home/home.component.html index e8ade77311..cdeeb9af4e 100644 --- a/src/app/home/states/home/home.component.html +++ b/src/app/home/states/home/home.component.html @@ -1,4 +1,4 @@ -
    +

    You are not enrolled in {{ externalName.value }}.

    Contact your unit convenor or tutor to enrol you in a subject.

    @@ -12,14 +12,14 @@

    You are not enrolled in any {{ externalName.value }} }

    Units you teach

    -
    - +
    +
    -
    +
    @for (unitRole of unitRoles | isActiveUnitRole; track unitRole) {
    @if (!unitRole.unit.teachingPeriod || unitRole.unit.teachingPeriod?.active) { -
    +
    {{ unitRole.unit?.name }} @@ -64,12 +64,12 @@

    Units you teach

    diff --git a/src/app/home/states/lti-dashboard/lti-dashboard.component.html b/src/app/home/states/lti-dashboard/lti-dashboard.component.html index 880914025d..430556fe2c 100644 --- a/src/app/home/states/lti-dashboard/lti-dashboard.component.html +++ b/src/app/home/states/lti-dashboard/lti-dashboard.component.html @@ -1,11 +1,10 @@ -
    +

    OnTrack

    @@ -23,53 +22,53 @@

    OnTrack

    @if (currentUser?.systemRole === 'Convenor' || currentUser?.systemRole === 'Admin') { }
    } @@ -88,7 +87,7 @@

    OnTrack

    @if (currentUser?.systemRole === 'Convenor' || currentUser?.systemRole === 'Admin') {
    - } @else { diff --git a/src/app/home/states/lti-unit-link/lti-unit-link.component.html b/src/app/home/states/lti-unit-link/lti-unit-link.component.html index 9975e20cb0..ff232c1bf8 100644 --- a/src/app/home/states/lti-unit-link/lti-unit-link.component.html +++ b/src/app/home/states/lti-unit-link/lti-unit-link.component.html @@ -1,11 +1,10 @@ -
    +

    OnTrack

    @@ -33,11 +32,11 @@

    OnTrack

    diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html index a4c5164702..35c49cf9fa 100644 --- a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html +++ b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.html @@ -21,11 +21,11 @@

    Targetting

    info - + Target grade @for (grade of grades; track grade) { - {{ + {{ grade.viewValue }} } @@ -45,14 +45,14 @@

    Targetting

    diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html index 02ac242529..cc01407796 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html @@ -10,7 +10,7 @@

    - +
    @@ -28,9 +28,9 @@

    Select Target Grade @for (grade of grades.values; track grade) { @@ -41,7 +41,7 @@

    To change your target grade, use the - + Task Planner
    @@ -52,7 +52,7 @@

    - +
    @@ -66,9 +66,9 @@

    Aim to keep your @@ -87,8 +87,8 @@

    diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.html index ee040cde96..c11ab4c597 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.html @@ -19,7 +19,7 @@ --> diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html index 7b30d385d6..a5cf691e16 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html @@ -13,7 +13,7 @@

    - +

    @@ -41,10 +41,10 @@

    @@ -63,10 +63,10 @@

    @@ -95,9 +95,9 @@

    } @else { @@ -138,8 +138,8 @@

    } @else { @@ -151,8 +151,8 @@

    @@ -162,7 +162,7 @@

    - +
    @if (isArchiveCodeOrTextFile(file)) { } @else if (isArchivePdfFile(file)) { @@ -193,8 +193,8 @@

    } @else { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-prerequisites-card/task-prerequisites-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-prerequisites-card/task-prerequisites-card.component.html index e8a1f50991..e5489003ec 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-prerequisites-card/task-prerequisites-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-prerequisites-card/task-prerequisites-card.component.html @@ -9,8 +9,8 @@ {{ taskDefinition.abbreviation }} {{ taskDefinition.name }}. diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html index 221c1f15fb..929ecc556e 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.html @@ -61,29 +61,29 @@ diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html index 69c416c606..4893c99cb4 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html @@ -22,8 +22,8 @@

    Similarities

    @for (part of similarity.parts; track part; let i = $index) { @@ -33,18 +33,18 @@

    Similarities

    @if (similarity.readyForViewer) { @if (similarity.type === 'JplagTaskSimilarity') { } @else if (similarity.type === 'TiiTaskSimilarity') { @@ -64,7 +64,7 @@
    {{ task?.statusLabel() }}

    -
    diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.html index 218a7cf028..90dd00e1d5 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.html @@ -36,10 +36,10 @@ Download submission @@ -49,8 +49,8 @@ - - diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html index e4ad3411dd..0c9ac2b5b4 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.html @@ -2,8 +2,8 @@
    @@ -52,10 +52,10 @@ @@ -77,17 +77,17 @@ @case (DashboardViews.details) {
    diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html index a54a599425..27ec1c0f3f 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html @@ -38,20 +38,20 @@ @if (project$ | async; as project) {
    -
    +
    @if (subs$ | async) { @if (isProjectTaskListReady(project)) { } @else {
    @@ -61,13 +61,13 @@
    } diff --git a/src/app/projects/states/discussion-prompts/discussion-prompts.component.html b/src/app/projects/states/discussion-prompts/discussion-prompts.component.html index 4172ea915a..05f56f7cd3 100644 --- a/src/app/projects/states/discussion-prompts/discussion-prompts.component.html +++ b/src/app/projects/states/discussion-prompts/discussion-prompts.component.html @@ -4,8 +4,8 @@
    {{ prompt.taskDefinition.abbreviation }}
    diff --git a/src/app/projects/states/groups/project-groups-state.component.html b/src/app/projects/states/groups/project-groups-state.component.html index 452af94217..e02214e8b7 100644 --- a/src/app/projects/states/groups/project-groups-state.component.html +++ b/src/app/projects/states/groups/project-groups-state.component.html @@ -1,7 +1,7 @@ @if (project) { } diff --git a/src/app/projects/states/groups/project-groups/project-groups.component.html b/src/app/projects/states/groups/project-groups/project-groups.component.html index a375726a37..7eca48477b 100644 --- a/src/app/projects/states/groups/project-groups/project-groups.component.html +++ b/src/app/projects/states/groups/project-groups/project-groups.component.html @@ -1,6 +1,6 @@
    @if (unit.hasGroupwork()) { - + } @else {
    diff --git a/src/app/projects/states/jplag/jplag-report-viewer.component.html b/src/app/projects/states/jplag/jplag-report-viewer.component.html index 4474b7d14e..1b5e99f233 100644 --- a/src/app/projects/states/jplag/jplag-report-viewer.component.html +++ b/src/app/projects/states/jplag/jplag-report-viewer.component.html @@ -1,9 +1,9 @@ diff --git a/src/app/projects/states/plan/project-plan.component.html b/src/app/projects/states/plan/project-plan.component.html index a1e861bcbd..733eda3558 100644 --- a/src/app/projects/states/plan/project-plan.component.html +++ b/src/app/projects/states/plan/project-plan.component.html @@ -21,8 +21,8 @@

    Task Planner

    Target Grade @for (grade of gradeValues; track grade) { diff --git a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html index d75f59aa58..8bc5faa0fc 100644 --- a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html +++ b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.html @@ -11,8 +11,8 @@

    {{ taskDefinition.description }}

    @if (!task.hasPrerequisiteTasks()) {
    This task has no prerequisites.
    @@ -34,15 +34,15 @@ - - + - - + - + - - + +
    Task + Task {{ link.taskDefinition?.abbreviation }} {{ link.taskDefinition?.name }} Submission Open + Submission Open @if (link.taskDefinition.projectTask(project).blockedByPrerequisiteTasks()) { block_outlined } @else { @@ -56,17 +56,17 @@ - Required Status + Required Status
    diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.html b/src/app/projects/states/plan/task-planner/task-planner.component.html index c4b4ee33c9..f30b4efdc0 100644 --- a/src/app/projects/states/plan/task-planner/task-planner.component.html +++ b/src/app/projects/states/plan/task-planner/task-planner.component.html @@ -4,14 +4,14 @@
    @if (unit.allowFlexibleDates) {
    - @@ -20,19 +20,19 @@ }
    @@ -44,8 +44,8 @@ >
    {{ item.title }} @@ -58,19 +58,19 @@ @if (showDatesColumn) { - + {{ toDateString(item.start) }} - + {{ toDateString(item.end) }} - + {{ item.task.localDeadlineDate() ? toDateString(item.task.localDeadlineDate()) : 'N/A' }} @@ -78,15 +78,15 @@
    @if (unsavedChanges(item)) { diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html index a596c34e0a..315af39ff8 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.html @@ -15,7 +15,7 @@ {{ icons[file.kind] }} {{ file.name }}
    - @@ -36,17 +36,17 @@
    - + diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html index e74d70a357..e8ce666a9a 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.html @@ -1,4 +1,4 @@ -
    +
    @@ -61,8 +61,8 @@

    Select Grade

    > @for (grade of gradeValues; track grade) { @@ -82,10 +82,10 @@

    Select Grade

    - + --> - +
    }
    @@ -79,10 +79,10 @@
    } diff --git a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.component.html index 661f2cb884..889d52931e 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.component.html @@ -111,11 +111,11 @@ - diff --git a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.html b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.html index baedcd729a..26ec79f3a3 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.html +++ b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.html @@ -18,6 +18,6 @@

    - + diff --git a/src/app/projects/states/portfolio/portfolio-state.component.html b/src/app/projects/states/portfolio/portfolio-state.component.html index 148fd8477a..e464e313b9 100644 --- a/src/app/projects/states/portfolio/portfolio-state.component.html +++ b/src/app/projects/states/portfolio/portfolio-state.component.html @@ -1,15 +1,15 @@ @if (project) {
    @for (tab of orderedTabs; track tab.seq) { } @@ -20,29 +20,29 @@ } @if (activeTab === tabs.gradeStep) { } @if (activeTab === tabs.summaryStep) { } @if (activeTab === tabs.otherFilesStep) { } @if (activeTab === tabs.reviewStep) { }
    diff --git a/src/app/projects/states/staff-notes/staff-notes.component.html b/src/app/projects/states/staff-notes/staff-notes.component.html index 641eb63700..a806cf2c6f 100644 --- a/src/app/projects/states/staff-notes/staff-notes.component.html +++ b/src/app/projects/states/staff-notes/staff-notes.component.html @@ -32,12 +32,12 @@
    } -
    +
    @if (note.authorIsMe) { edit } @@ -46,14 +46,14 @@
    - + {{ note.user?.firstName }} {{ note.user?.lastName }}
    {{ note.createdAt | humanizedDate }}
    @@ -64,15 +64,15 @@ Update Note
    - - +
    @@ -115,12 +115,12 @@ Staff Note
    - +
    diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html index 843c67695b..52f7807b52 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html @@ -1,15 +1,15 @@
    @if (loadingStudentData) { }
    -
    +
    @@ -33,8 +33,8 @@ @for (td of unit?.taskDefinitionCache.values | async; track td) { {{ td.abbreviation }} - {{ td.name }} @@ -42,7 +42,7 @@ @if (selectedTaskDefinition) { - + }
    } @@ -66,7 +66,7 @@
    Click the QR code to open the scanner..
    } -
    @@ -74,10 +74,9 @@ @if (project && !filteredTasks.length) {
    No tasks to discuss.
    } - + @for (task of filteredTasks; track task) { @if (task) {
    - +

    {{ task.definition.name }}

    @@ -118,17 +118,17 @@

    {{ task.definition.name }}

    } } @else { - } @@ -168,8 +168,8 @@

    {{ task.definition.name }}

    @if (attendance) {
    diff --git a/src/app/projects/states/tutor-notes/tutor-notes.component.html b/src/app/projects/states/tutor-notes/tutor-notes.component.html index 6cc373d047..4a69c31a30 100644 --- a/src/app/projects/states/tutor-notes/tutor-notes.component.html +++ b/src/app/projects/states/tutor-notes/tutor-notes.component.html @@ -32,13 +32,13 @@
    }
    -
    +
    @if (note.authorIsMe) { edit } @@ -47,7 +47,7 @@
    @if (!note.readByUnitRole) { @if (note.noteIsForMe) { - } @@ -58,14 +58,14 @@
    - + {{ note.user?.firstName }} {{ note.user?.lastName }}
    {{ note.createdAt | humanizedDate }}
    @@ -94,15 +94,15 @@ Update Note
    - - +
    @@ -123,7 +123,7 @@
    - + @for (option of taskDefinitionFilters; track option) { {{ option }} @@ -163,12 +163,12 @@ Tutor note
    - +
    diff --git a/src/app/projects/states/tutorials/tutorials.component.html b/src/app/projects/states/tutorials/tutorials.component.html index 7a2dca17ff..b953b21592 100644 --- a/src/app/projects/states/tutorials/tutorials.component.html +++ b/src/app/projects/states/tutorials/tutorials.component.html @@ -9,16 +9,16 @@

    Tutorials

    - - + - + - - + - - + - - + - - + - - + - - + - - + +
    Stream + Stream @if (unit.tutorialStreamsCache.size > 0) {
    {{ tutorial.tutorialStream?.name || 'All' }}
    } @else { @@ -28,49 +28,49 @@

    Tutorials

    -
    Campus + Campus {{ tutorial.campus?.name || 'All' }} Code + Code {{ tutorial.abbreviation }} Day + Day {{ tutorial.meetingDay }} Time + Time {{ shortTime(tutorial.meetingTime) }} Room + Room {{ tutorial.meetingLocation }} Tutor + Tutor {{ tutorial.tutorName }} Actions + Actions @if (project.isEnrolledIn(tutorial)) { @if (unit.allowStudentChangeTutorial) { @@ -101,8 +101,8 @@

    Tutorials

    }
    } diff --git a/src/app/sessions/states/sign-in/sign-in.component.html b/src/app/sessions/states/sign-in/sign-in.component.html index 5eeb9fa752..2c57ca1db0 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.html +++ b/src/app/sessions/states/sign-in/sign-in.component.html @@ -6,7 +6,7 @@
    - Homepage Logo + Homepage Logo

    {{ externalName.value }}

    @@ -14,6 +14,7 @@

    autoLogin: autoLogin, }) " - class="sign-in-form flex flex-col" > @if (showCredentials) { @@ -34,10 +34,10 @@

    Password @@ -52,8 +52,8 @@

    diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.html b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.html index c67f8463e5..30ae42e4c5 100644 --- a/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.html +++ b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.html @@ -14,19 +14,19 @@ @for (idx of gradeValues; track idx) { @@ -44,7 +44,7 @@ {{ task.definition.abbreviation }}

    - +
    @@ -57,10 +57,10 @@ diff --git a/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.html b/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.html index 42044d1858..4938fc354e 100644 --- a/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.html +++ b/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.html @@ -12,9 +12,9 @@

    Select submission type

    }

    I would like feedback
    @if (isGroupStage) { @@ -174,11 +174,11 @@

    Declaration

    @if (isDetailsStage && showCommentsSection) { @@ -194,12 +194,12 @@

    Declaration

    @if ((!showCommentsSection && isDetailsStage) || isCommentsStage) { diff --git a/src/app/tasks/project-tasks-list/project-tasks-list.component.html b/src/app/tasks/project-tasks-list/project-tasks-list.component.html index 243bba9805..ed091e545e 100644 --- a/src/app/tasks/project-tasks-list/project-tasks-list.component.html +++ b/src/app/tasks/project-tasks-list/project-tasks-list.component.html @@ -14,14 +14,14 @@
    {{ grouping.name }}
    ) { @if (task.similarityFlag) { diff --git a/src/app/tasks/task-comment-composer/attachment-confirmation-dialog/attachment-confirmation-dialog.component.html b/src/app/tasks/task-comment-composer/attachment-confirmation-dialog/attachment-confirmation-dialog.component.html index 30c3f7ed38..7a518ce359 100644 --- a/src/app/tasks/task-comment-composer/attachment-confirmation-dialog/attachment-confirmation-dialog.component.html +++ b/src/app/tasks/task-comment-composer/attachment-confirmation-dialog/attachment-confirmation-dialog.component.html @@ -8,8 +8,8 @@

    Post Attachment?

    @if (isImage) { } @else if (isPdf) {
    @@ -28,7 +28,7 @@

    Post Attachment?

    {{ file.type || 'Audio file' }}
    - +
    } @else {
    @@ -51,5 +51,5 @@

    Post Attachment?

    - + diff --git a/src/app/tasks/task-comment-composer/discussion-prompt-composer-dialog.html b/src/app/tasks/task-comment-composer/discussion-prompt-composer-dialog.html index 4257317bc5..153184e21f 100644 --- a/src/app/tasks/task-comment-composer/discussion-prompt-composer-dialog.html +++ b/src/app/tasks/task-comment-composer/discussion-prompt-composer-dialog.html @@ -1,15 +1,15 @@ - - + Introduction
    Discussion Splash Image

    Discussions are a great way for both you and your students to gauge student's understanding @@ -30,7 +30,7 @@

    -
    @@ -41,7 +41,7 @@
    -
    diff --git a/src/app/tasks/task-comment-composer/discussion-prompt-composer/discussion-prompt-composer.component.html b/src/app/tasks/task-comment-composer/discussion-prompt-composer/discussion-prompt-composer.component.html index f6d9dc8112..ed00a23c44 100644 --- a/src/app/tasks/task-comment-composer/discussion-prompt-composer/discussion-prompt-composer.component.html +++ b/src/app/tasks/task-comment-composer/discussion-prompt-composer/discussion-prompt-composer.component.html @@ -1,11 +1,11 @@

    Step 1. Record and add up to 3 prompts.

    -
    +
    @@ -59,12 +59,12 @@

    Prompt {{ i + 1 }}

    Step 3. Send.

    diff --git a/src/app/tasks/task-comment-composer/task-comment-composer.component.html b/src/app/tasks/task-comment-composer/task-comment-composer.component.html index 4e0d18d1da..9a5788207f 100644 --- a/src/app/tasks/task-comment-composer/task-comment-composer.component.html +++ b/src/app/tasks/task-comment-composer/task-comment-composer.component.html @@ -1,11 +1,11 @@ @@ -13,10 +13,10 @@
    @@ -31,10 +31,10 @@
    @@ -45,14 +45,14 @@ } @for (emoji of emojiSearchResults; track emoji) {
    - +
    {{ emoji.name }}
    {{ emoji.colons }}
    @@ -63,34 +63,34 @@ @if (task) { } -
    +
    @if ($userIsTyping | async) { @@ -113,13 +113,13 @@ @if (isStaff) { @if (!isEditing) { @@ -152,13 +152,13 @@ @if (!isEditing) { - +
    }
    diff --git a/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-dialog.html b/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-dialog.html index bc55f2507a..c4cb615fae 100644 --- a/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-dialog.html +++ b/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-dialog.html @@ -1,14 +1,14 @@ - - + Introduction
    Discussion Splash Image

    Your tutor would like to discuss some topics with you regarding this task Discussions are a @@ -27,7 +27,7 @@

    -
    @@ -36,21 +36,20 @@ Test everything is working -
    - + Ready to go! @@ -61,9 +60,9 @@ Discussion
    @@ -73,9 +72,9 @@
    diff --git a/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-player.component.html b/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-player.component.html index f0d129e741..9ed3747a9f 100644 --- a/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-player.component.html +++ b/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-player.component.html @@ -13,47 +13,47 @@

    }
    P1 @if (discussion.numberOfPrompts > 1) { P2 } @if (discussion.numberOfPrompts > 2) { P3 } Response diff --git a/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-recorder/intelligent-discussion-recorder.component.html b/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-recorder/intelligent-discussion-recorder.component.html index 91e633240a..675f751ba0 100644 --- a/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-recorder/intelligent-discussion-recorder.component.html +++ b/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-recorder/intelligent-discussion-recorder.component.html @@ -6,8 +6,8 @@
    diff --git a/src/app/tasks/task-comments-viewer/pdf-image-comment/pdf-image-comment.component.html b/src/app/tasks/task-comments-viewer/pdf-image-comment/pdf-image-comment.component.html index 8127bf8e59..01448c6420 100644 --- a/src/app/tasks/task-comments-viewer/pdf-image-comment/pdf-image-comment.component.html +++ b/src/app/tasks/task-comments-viewer/pdf-image-comment/pdf-image-comment.component.html @@ -1,6 +1,6 @@ @if (comment.commentType === 'image' && resourceUrl) { - Image attachment preview + Image attachment preview } @if (comment.commentType === 'pdf') {

    picture_as_pdf view pdf

    diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html index 6ea723e8dc..7fac5712c3 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.html @@ -1,10 +1,10 @@
    @@ -15,18 +15,18 @@ } diff --git a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html index cdc4a33b1e..a47e71f63a 100644 --- a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html +++ b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.html @@ -15,10 +15,10 @@

    @if (isNotStudent) { diff --git a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.html b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.html index 6ded1e08e2..1d45b3f397 100644 --- a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.html +++ b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.html @@ -28,20 +28,20 @@ > } @else if (comment.overseerStatus === 'failed') { highlight_off_outline } @else if (comment.overseerStatus === 'pre_queued') { - + } @if (comment.overseerStatus !== 'pre_queued') { diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html index f4088e9d6c..5c0be3594a 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html @@ -1,18 +1,18 @@
    -
    - +
    +
    @if (!task || task.comments.length === 0) { @@ -26,10 +26,10 @@ @for (comment of task.comments; track comment) {
    @if (comment.shouldShowTimestamp) {

    @@ -39,22 +39,22 @@ }

    @if (!comment.authorIsMe && shouldShowAuthorIcon(comment.commentType)) {
    @if (comment.shouldShowAvatar && shouldShowAuthorIcon(comment.commentType)) { } @@ -63,16 +63,16 @@
    @switch (comment.commentType) { @case ('status') {

    @@ -81,18 +81,18 @@ @case ('discussed_in_class') {
    - + group {{ comment.text }} @@ -103,18 +103,18 @@ @case ('feedback_review_request') {
    - + comment {{ comment.text }} @@ -125,18 +125,18 @@ @case ('checked_in') {
    - + how_to_reg {{ comment.text }} @@ -154,8 +154,8 @@
    @if (overseerEnabled) { }
    @@ -164,7 +164,7 @@ @case ('scorm') {
    @if (scormEnabled) { - + }
    } @@ -173,8 +173,8 @@ diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html index 3b9cd48700..13afa33ac6 100644 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.html @@ -32,10 +32,10 @@
    diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html index 4e844cabda..6298d27683 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html @@ -8,10 +8,10 @@

    Tutor Times Session Summary

    @if (role === 'Convenor') { @@ -19,10 +19,10 @@

    Tutor Times Session Summary

    @@ -31,11 +31,11 @@

    Tutor Times Session Summary

    - - +
    @@ -98,17 +98,17 @@

    Tutor Times Session Summary

    }
    diff --git a/src/app/units/states/analytics/unit-analytics-route.component.html b/src/app/units/states/analytics/unit-analytics-route.component.html index e821247f5b..39b3461d24 100644 --- a/src/app/units/states/analytics/unit-analytics-route.component.html +++ b/src/app/units/states/analytics/unit-analytics-route.component.html @@ -19,7 +19,7 @@

    Unit Statistics

    - +
    - +
    - } @else {

    {{ set.name }}

    - }
    -
    @@ -160,23 +160,23 @@

    {{ set.name }}

    - } @else {
    {{ rule.name }}
    @@ -190,9 +190,9 @@

    {{ set.name }}

    @@ -204,12 +204,12 @@

    {{ set.name }}

    - + Send action log to convenors after execution
    - @@ -221,10 +221,10 @@

    {{ set.name }}

    + } -
    @@ -70,7 +70,7 @@

    Unit Details

    Draft Learning Summary - + None @for (td of taskDefinitions; track td) { {{ td.abbreviation }} - {{ td.name }} @@ -96,9 +96,9 @@

    Unit Details

    Feedback warning after (days) @@ -111,9 +111,9 @@

    Unit Details

    Show task in overflow queue after (days) @@ -150,8 +150,8 @@

    Unit Details

    Has tasks assessed in portfolio

    @@ -240,7 +240,7 @@

    Unit Details

    }
    -

    > Copy - +
    diff --git a/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.component.html b/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.component.html index c072bf1999..4bdc0d0ce9 100644 --- a/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.component.html +++ b/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.component.html @@ -8,7 +8,7 @@

    A group set is a set of related group-work. A unit can have multiple group sets for various kinds of group work which has multiple teams. -

    @@ -16,10 +16,10 @@ @if (showHelp) {
    @@ -44,11 +44,11 @@

    No Group Sets Created

    } @else { - - + - + - + - + - + - +
    Name + Name @if (editingGroupSetId === groupSet.id && editingGroupSetModel) { - + } @else { {{ groupSet.name || 'No Name Set' }} @@ -57,14 +57,14 @@

    No Group Sets Created

    -
    Capacity + Capacity @if (editingGroupSetId === groupSet.id && editingGroupSetModel) { @@ -75,8 +75,8 @@

    No Group Sets Created

    -
    Create Groups + Create Groups @if (editingGroupSetId === groupSet.id && editingGroupSetModel) { @@ -92,8 +92,8 @@

    No Group Sets Created

    -
    Manage Groups + Manage Groups @if (editingGroupSetId === groupSet.id && editingGroupSetModel) { @@ -109,8 +109,8 @@

    No Group Sets Created

    -
    Restrict to Tutorials + Restrict to Tutorials @if (editingGroupSetId === groupSet.id && editingGroupSetModel) { @@ -126,11 +126,11 @@

    No Group Sets Created

    -
    Actions + Actions
    @if (editingGroupSetId === groupSet.id) { - @@ -151,7 +151,7 @@

    No Group Sets Created

    {{ groupSet.locked ? 'lock' : 'lock_open' }} {{ groupSet.locked ? 'Unlock' : 'Lock' }} - @@ -161,7 +161,6 @@

    No Group Sets Created

    } - @@ -200,9 +200,9 @@

    No Group Sets Created

    @if (selectedGroupSet && unit.groupSets.length > 0) {
    @@ -234,12 +234,12 @@

    No Group Sets Created

    @@ -271,12 +271,12 @@

    No Group Sets Created

    diff --git a/src/app/units/states/edit/directives/unit-staff-editor/bulk-import-staff-modal/bulk-import-staff-modal.component.html b/src/app/units/states/edit/directives/unit-staff-editor/bulk-import-staff-modal/bulk-import-staff-modal.component.html index 32c44da5da..8240189388 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/bulk-import-staff-modal/bulk-import-staff-modal.component.html +++ b/src/app/units/states/edit/directives/unit-staff-editor/bulk-import-staff-modal/bulk-import-staff-modal.component.html @@ -3,20 +3,20 @@

    Bulk Import Staff

    Paste one staff email per line to add them to this unit as tutors.

    - + Staff emails
    -
    - - +
    diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html index d01957ae86..1573f1b960 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.html @@ -3,52 +3,52 @@

    Unit Staff

    Manage unit staff by adding members and assigning them as convenors or tutors.

    - +
    - + - - - + - - + - + - - + - - + - + - - + +
    NameName +
    - {{ unitRole.user.name }}
    Role + Role Tutor Convenor Main Convenor + Main Convenor @if (unitRole?.role === 'Convenor') { Observer Only + Observer Only Overflow Marking + Overflow Marking Mentor + Mentor (None) @for (unitRole of unitStaff; track unitRole) { @@ -103,8 +103,8 @@

    Unit Staff

    -
    Actions + Actions
    -
    - + @for (staff of filteredStaff; track staff) { @@ -145,10 +145,10 @@

    Unit Staff

    - - + - - + - - + - - + - - + @@ -65,16 +65,16 @@

    Enrolled Students

    - - + - - + - + - - - + + +
    Username + Username {{ project.student.username }} First Name + First Name {{ project.student.firstName }} Last Name + Last Name {{ project.student.lastName }} Email + Email {{ project.student.email }} Campus + Campus Tutorial - + Tutorial + Enrolled + Enrolled Enrolled Students - +
    +
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.html index 093ab2b77b..f94c7e6037 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.html @@ -4,9 +4,9 @@ @@ -18,9 +18,9 @@ @@ -30,11 +30,11 @@ Final Feedback Date diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.html index 9828b6297a..b3d0eb258b 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.html @@ -2,22 +2,22 @@
    - - + - - + - + - - + +
    Discussion Prompt + Discussion Prompt @if (!editing(prompt)) { {{ prompt.content }} } @else { Discussion Prompt - + } Priority + Priority @if (!editing(prompt)) { {{ prompt.priorityLabel }} } @else { @@ -37,8 +37,8 @@ - Actions + Actions
    @if (editing(prompt)) {
    @if (!dataSource.data.length) { @@ -68,7 +68,7 @@ } @if (!creatingNewDiscussionPrompt) {
    -
    @@ -82,8 +82,8 @@ Discussion Prompt
    @@ -99,7 +99,7 @@
    - +
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html index 773af87979..8c01e34614 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.html @@ -1,4 +1,4 @@ -
    +

    Details for {{ taskDefinition.abbreviation }} - {{ taskDefinition.name }}

    @@ -8,8 +8,8 @@

    Details for {{ taskDefinition.abbreviation }} - {{ taskDefinition.name }} @for (section of visibleSections; track section.id) {

    -
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.html index cc9e2ed2b8..e302e6d17d 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.html @@ -1,7 +1,7 @@
    Grade where task appears - + @for (grade of grades; track grade) { {{ grade.viewValue }} } @@ -10,21 +10,21 @@ Abbreviation - Week, sequence, and grade. eg 1.1P - + Weight - Effort relative to other tasks. - +
    Descriptive task name - + Task description - + diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html index bd3109b9f2..92a1002ce2 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.html @@ -11,10 +11,10 @@
    Assess in Portfolio Only @@ -47,7 +47,7 @@
    Quality Stars - + Provide a number of stars alongside the task status. Make sure you have a clear reason for diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html index 415d4a14a6..38d28433b3 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.html @@ -9,6 +9,6 @@
    @if (!loading) { - + }
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html index 164bd31aaf..54f0c3a87b 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.html @@ -3,8 +3,8 @@ Automation Enabled @@ -15,9 +15,9 @@
    - + Docker Image - + @for (image of images | async; track image) { {{ image.description }} } @@ -26,24 +26,24 @@ @if (taskDefinition.hasTaskAssessmentResources) {
    - - @@ -109,14 +109,14 @@
    @if (this.selectedOverseerStep) { - - + + }
    - +
    @@ -128,12 +128,12 @@
    @for (step of overseerSteps; track step.id) {
    drag_indicator {{ step.sortOrder }}. {{ step.name ?? 'Untitled Step' }} @@ -141,9 +141,9 @@ } @if (newOverseerStep) {
    {{ newOverseerStep.sortOrder }}. {{ newOverseerStep.name || 'Untitled Step' }} @@ -158,7 +158,7 @@
    Step Name - + Visible to staff only @@ -166,8 +166,8 @@ Visible to staff only @@ -175,7 +175,7 @@ Step Type - + Custom Script Input/Output @@ -198,7 +198,7 @@ runs. - + Show input file to student
    @@ -214,15 +214,15 @@ Program output must exactly match this file to pass. Show expected output file to student
    Partial Output Comparison
    @@ -274,10 +274,10 @@ Time Limit (s) How long the code can execute for before overseer automatically kills the @@ -342,14 +342,14 @@ Shown to student in overseer report Description - + Shown to student in overseer report
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html index 740b01959e..530d31da43 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html @@ -2,10 +2,10 @@
    - + - - - + +
    TaskTask {{ link.prerequisite?.abbreviation }} {{ link.prerequisite?.name }} @@ -13,7 +13,7 @@ - + @if (staffView) { Minimum Required Status } @else { @@ -21,8 +21,8 @@ } @if (!staffView) { @@ -33,10 +33,10 @@ } @else { @if (link.taskStatus) { @for (state of stateOptions; track state) { @@ -51,20 +51,20 @@ - + @if (staffView) { Actions } @else { Required Status } + @if (staffView) {
    @@ -87,20 +87,20 @@
    -
    @@ -19,21 +19,21 @@
    @if (taskDefinition.hasTaskResources) {
    - diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html index d05d59d67e..10a029b6ba 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.html @@ -5,25 +5,25 @@ @if (taskDefinition.scormEnabled) { @if (taskDefinition.hasScormData) {
    - -
    @@ -42,8 +42,8 @@ Limit to this number of attempts - 0 is unlimited @@ -52,11 +52,11 @@
    Enable incremental time delays between test attempts diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html index 0649d98406..9c15a2ce78 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.html @@ -1,18 +1,18 @@ - +
    - - + - - + - + - - + - + - + - - - + + +
    Filename + Filename - + Type + Type Code Document @@ -23,19 +23,19 @@ - Submission History + Submission History Check Similarity + Check Similarity @if (upreq.type === 'document' && tiiEnabled()) { TurnItIn } @@ -47,11 +47,11 @@ - Flag At + Flag At @if (upreq.type === 'document' && upreq.tiiCheck) { - +  % } @@ -60,12 +60,12 @@ - + + - @@ -87,9 +87,9 @@
    @if (missingOverseerSubmissionHistory) { @@ -127,7 +127,7 @@ Similarity percent to flag for JPLAG checks - +
    diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html index 0a3be6d1ba..65dee44436 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html @@ -43,11 +43,11 @@ @if (taskDefinition.tutorialStream?.tutorialsIn(unit).length > 3) {
    @if (!showAllTutorials) { - } @else { - } diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html index 472c672b28..72d7153562 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html @@ -33,7 +33,7 @@

    Task List

    @if (unit.allowFlexibleDates) { } - +
    @if (unit.allowFlexibleDates) { @@ -46,22 +46,22 @@

    Manage Target Dates

    Modify or add target dates for each target grade

    - +
    - - + @for (g of gradeColumns; track g) { - - - + +
    Task + Task {{ td.abbreviation }} {{ td.name }} +
    +
    Manage Target Dates Start Date @@ -94,13 +94,13 @@

    Manage Target Dates

    Target Date @if (isStartAfterTarget(td, g)) { @@ -115,8 +115,8 @@

    Manage Target Dates

    } -
    } @@ -140,9 +140,9 @@

    Manage Target Dates

    >
    @if (!isTaskListCollapsed) {
    @@ -185,14 +185,14 @@

    Manage Target Dates

    Manage Target Dates

    [ngClass]="{'justify-center': isTaskListCollapsed}" > @if (!isTaskListCollapsed) { @@ -220,18 +220,18 @@

    > @if (taskDefinitionHasChanges(taskDefinition)) { } - } @@ -37,37 +37,37 @@

    Tutorials without a stream

    - - - + - - - - + - - + - - - - + - - + - - - - + - - + - - - + - - - - + + +
    Abbreviation + + Abbreviation @if (!editing(tutorial)) {
    {{ tutorial.abbreviation }}
    } @else { - + }
    + - + Campus + + Campus @if (!editing(tutorial)) {
    {{ tutorial.campus ? tutorial.campus.name : '' }} @@ -75,7 +75,7 @@

    Tutorials without a stream

    } @else { Campus - + Not Specified @for (campus of campuses; track campus) { @@ -86,7 +86,7 @@

    Tutorials without a stream

    }
    + Campus @@ -102,30 +102,30 @@

    Tutorials without a stream

    - -
    Location + + Location @if (!editing(tutorial)) {
    {{ tutorial.meetingLocation }}
    } @else { - + }
    + - + Day + + Day @if (!editing(tutorial)) {
    {{ tutorial.meetingDay }} @@ -133,7 +133,7 @@

    Tutorials without a stream

    } @else { Day - + @for (day of days; track day) { {{ day }} @@ -143,10 +143,10 @@

    Tutorials without a stream

    }
    + Day - + @for (day of days; track day) { {{ day }} @@ -158,9 +158,9 @@

    Tutorials without a stream

    - -
    Time + + Time @if (!editing(tutorial)) {
    {{ tutorial.meetingTime }} @@ -168,26 +168,26 @@

    Tutorials without a stream

    } @else { }
    + - + Tutor + + Tutor @if (!editing(tutorial)) {
    {{ tutorial.tutor?.name }} @@ -195,7 +195,7 @@

    Tutorials without a stream

    } @else { Tutor - + @for (tutor of unit.staffUsers; track tutor) { {{ tutor.name }} @@ -205,10 +205,10 @@

    Tutorials without a stream

    }
    + Tutor - + @for (tutor of unit.staffUsers; track tutor) { {{ tutor.name }} @@ -220,28 +220,28 @@

    Tutorials without a stream

    - -
    Capacity + + Capacity @if (!editing(tutorial)) {
    {{ tutorial.numStudents }} / {{ tutorial.capacity }}
    } @else { - + }
    + - + + @if (!editing(tutorial)) {
    } @else {
    - - -
    }
    +
    -
    diff --git a/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html b/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html index e56b409a73..a37505ec5d 100644 --- a/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html +++ b/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.html @@ -1,7 +1,7 @@
    @for (stream of unit.tutorialStreams; track stream) { - + } @empty {
    @@ -14,7 +14,7 @@

    No Tutorials

    }
    - diff --git a/src/app/units/states/edit/unit-admin-state.component.html b/src/app/units/states/edit/unit-admin-state.component.html index 6a06b1e487..d808b3d7f1 100644 --- a/src/app/units/states/edit/unit-admin-state.component.html +++ b/src/app/units/states/edit/unit-admin-state.component.html @@ -1,8 +1,8 @@
    @for (tab of tabs; track tab.routeSegment) { @@ -33,7 +33,7 @@

    Unit Learning Outcomes

    @case ('staff') { @if (unit) {
    - +
    } } diff --git a/src/app/units/states/groups/unit-groups/unit-groups.component.html b/src/app/units/states/groups/unit-groups/unit-groups.component.html index 26576c5042..9696d512a3 100644 --- a/src/app/units/states/groups/unit-groups/unit-groups.component.html +++ b/src/app/units/states/groups/unit-groups/unit-groups.component.html @@ -1,6 +1,6 @@ @if (unit.hasGroupwork()) {
    - +
    } @else { diff --git a/src/app/units/states/portfolios/d2l-transfer-modal/d2l-transfer.component.html b/src/app/units/states/portfolios/d2l-transfer-modal/d2l-transfer.component.html index ccf3c460a1..d5f194b3c2 100644 --- a/src/app/units/states/portfolios/d2l-transfer-modal/d2l-transfer.component.html +++ b/src/app/units/states/portfolios/d2l-transfer-modal/d2l-transfer.component.html @@ -15,7 +15,7 @@

    D2L Grade Transfer

    1. -
      @@ -27,7 +27,7 @@

      D2L Grade Transfer

    2. -
      @@ -36,7 +36,7 @@

      D2L Grade Transfer

    3. -
      @@ -49,7 +49,7 @@

      D2L Grade Transfer

    4. -
      @@ -61,7 +61,7 @@

      D2L Grade Transfer

    5. -
      @@ -79,5 +79,5 @@

      D2L Grade Transfer

      - + diff --git a/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.html b/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.html index ffb0504623..73fe7e03fb 100644 --- a/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.html @@ -3,7 +3,7 @@

      Grade for {{ project.student.name }}

      Assign grade for this project.

      Rationale - + @for (group of gradeResults; track group) {
      @@ -15,11 +15,11 @@

      Grade for {{ project.student.name }}

      @for (score of group.scores; track score) { @@ -29,10 +29,10 @@

      Grade for {{ project.student.name }}

      }
      diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html index cce514ee07..f638212138 100644 --- a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.html @@ -6,72 +6,72 @@

      Mark portfolios

      Filter public menu_book account_balance edit All @for (grade of gradeValues; track grade) { @@ -86,11 +86,11 @@

      Mark portfolios

      @@ -106,7 +106,7 @@

      Mark portfolios

      @if (loading) { -
      +
      @for ( @@ -167,86 +167,86 @@

      Mark portfolios

      } - - + - - + - - + - - + - - + - - + - - + - - + - - + - + - - + - + - +
      Student + Student {{ project.student.studentId || project.student.username }} Name + Name {{ project.student.name }} Tutor + Tutor {{ project.tutorNames() }} Tutorial + Tutorial {{ project.shortTutorialDescription() }} Target + Target Submitted as + Submitted as Submission Date + Submission Date {{ project.portfolioSubmissionDate | date: 'EEE d MMM y, h:mm a' }} Has Portfolio + Has Portfolio {{ project.hasPortfolio ? 'Yes' : 'No' }} Stats + Stats
      @for (bar of project.taskStats; track bar) {
      @if (bar.key === 'not_started') { {{ bar.value }}% @@ -261,37 +261,37 @@

      Mark portfolios

      -
      Grade + Grade {{ project.grade }} View + View
      No students found
      diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html index acc95740ce..788f4d9502 100644 --- a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.html @@ -54,8 +54,8 @@

      Review progress of {{ project.student.name }}

      --> diff --git a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html index 2d454fd43c..89963fcfef 100644 --- a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html +++ b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.html @@ -1,3 +1,3 @@ - diff --git a/src/app/units/states/portfolios/portfolios.component.html b/src/app/units/states/portfolios/portfolios.component.html index a13d2cf25d..da789dafe0 100644 --- a/src/app/units/states/portfolios/portfolios.component.html +++ b/src/app/units/states/portfolios/portfolios.component.html @@ -2,12 +2,12 @@ @if (unit) { @for (tab of tabs; track tab.routeSegment) { - + } @@ -15,18 +15,18 @@ @switch (currentTab.routeSegment) { @case ('select') { } @case ('progress') { @if (selectedProject) { } } diff --git a/src/app/units/states/portfolios/upload-grades/upload-grades.component.html b/src/app/units/states/portfolios/upload-grades/upload-grades.component.html index a95e240410..f42a9a62a0 100644 --- a/src/app/units/states/portfolios/upload-grades/upload-grades.component.html +++ b/src/app/units/states/portfolios/upload-grades/upload-grades.component.html @@ -1,3 +1,3 @@ - diff --git a/src/app/units/states/rollover/rollover.component.html b/src/app/units/states/rollover/rollover.component.html index 1f55d654a7..a6f4ed56f2 100644 --- a/src/app/units/states/rollover/rollover.component.html +++ b/src/app/units/states/rollover/rollover.component.html @@ -40,17 +40,17 @@ } @else { {{ teachingPeriod.name }} Start Date - + {{ teachingPeriod.name }} End Date - + }
      - + diff --git a/src/app/units/states/students-list/students-list.component.html b/src/app/units/states/students-list/students-list.component.html index 89cd97d026..73be5a3f61 100644 --- a/src/app/units/states/students-list/students-list.component.html +++ b/src/app/units/states/students-list/students-list.component.html @@ -9,10 +9,10 @@

      Students

      Search for students or tutors... @for (suggestion of filteredSuggestions; track suggestion) { @@ -24,18 +24,18 @@

      Students

      - All Tutorials - My Tutorials + All Tutorials + My Tutorials
      @if (loadingStudents) { -
      +
      @for (width of ['4%', '10%', '16%', '28%', '8%', '8%', '8%', '10%', '10%']; track $index) { Students
      - - + - - + - - + - - + - + - - + - + - + - + - + - + @@ -201,8 +201,8 @@

      Students

      Export CSV diff --git a/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.html b/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.html index 2524617f84..1b680fae11 100644 --- a/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.html +++ b/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.html @@ -36,8 +36,8 @@

      } - - + diff --git a/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.html b/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.html index ae11125495..3862dc4a8b 100644 --- a/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.html +++ b/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.html @@ -2,57 +2,57 @@ @if (task.moderationType === 'random_sample' || task.moderationType === 'first_feedback') { } @else if (task.moderationType === 'escalation') { diff --git a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html index 7b284ba2f7..d797a552a4 100644 --- a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html +++ b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.html @@ -5,29 +5,29 @@ [ngClass]="{expanded: showSearchOptions, mobile: mobile}" >
      -
      @if (collapsable) { }
      @@ -195,7 +194,7 @@ -
      +
      @@ -206,7 +205,7 @@ [ngClass]="isNarrow ? 'narrow-width' : 'full-width'" >
      -
      @@ -227,9 +226,9 @@ [ngClass]="isNarrow ? 'justify-center gap-0 px-[5px]' : 'gap-[10px] pl-[6px] pr-[8px]'" >
      @@ -276,8 +275,8 @@ } @if (task) { @@ -290,11 +289,11 @@ }" >
      - +

      @if (task.moderationType === 'escalation') { gavel } @if (getWarningIcon(task) === 'warning') { warning } @else if (getWarningIcon(task) === 'overflow') { watch_later @@ -358,15 +357,15 @@

      }
      - -
      -
      +
      @if (loading) { } @else { diff --git a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html index 066789a0b1..1aba157340 100644 --- a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html +++ b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.html @@ -1,10 +1,10 @@ diff --git a/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.html b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.html index 61c3af38a0..ffa6367f9b 100644 --- a/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.html +++ b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.html @@ -2,8 +2,8 @@
      Task Details @@ -15,7 +15,7 @@
      -
      +
      subtitles_off
      diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index fce6d21874..39af419726 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -1,6 +1,6 @@
      - +
      @@ -110,11 +110,11 @@ @if (taskDef) { @if (isCollapsed) { @@ -214,8 +214,8 @@
      diff --git a/src/app/units/task-viewer/task-viewer-state.component.html b/src/app/units/task-viewer/task-viewer-state.component.html index ed0f00290b..33a824d88e 100644 --- a/src/app/units/task-viewer/task-viewer-state.component.html +++ b/src/app/units/task-viewer/task-viewer-state.component.html @@ -1,14 +1,14 @@ @if (unit$ | async; as unit) {
      -
      -
      +
      +
      -
      +
      @@ -29,26 +29,26 @@
      -
      +
      -
      +
      -
      +
      diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index 15ed9a8795..d4406f7937 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -1,22 +1,22 @@
      diff --git a/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.html b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.html index dfcdad3104..b4c56c857b 100644 --- a/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.html +++ b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.html @@ -1,12 +1,12 @@
      diff --git a/src/app/visualisations/task-visualisation/task-visualisation.component.html b/src/app/visualisations/task-visualisation/task-visualisation.component.html index b54fdb86be..b5311d2fab 100644 --- a/src/app/visualisations/task-visualisation/task-visualisation.component.html +++ b/src/app/visualisations/task-visualisation/task-visualisation.component.html @@ -1,6 +1,6 @@ diff --git a/src/app/welcome/welcome.component.html b/src/app/welcome/welcome.component.html index 427ebdb6e2..49f3552f95 100644 --- a/src/app/welcome/welcome.component.html +++ b/src/app/welcome/welcome.component.html @@ -1,17 +1,17 @@
      - +
      - Homepage Logo + Homepage Logo

      {{ externalName.value }}

      Welcome to {{ externalName.value }}

      diff --git a/src/index.html b/src/index.html index b1c567c8e4..f2d5aa9c95 100644 --- a/src/index.html +++ b/src/index.html @@ -19,23 +19,23 @@ rel="stylesheet" /> Loading... - + - - + + - - + + - + - + From 6d005653d2c5026b14538b4ff303e6a3047cbe94 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:12:58 +1000 Subject: [PATCH 1130/1531] chore: ignore formatting commit from git blame --- .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 8af4e23280..260dc5e2fd 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,2 +1,5 @@ # 8 June 2026: Repository-wide formatting and lint configuration 26b4962794d16e90587fb179aab966b39459050c + +# 17 June 2026: Repository-wide sorting of HTML attributes +1ffc7ad7b9dc18f22be32bf6313bfde97957dd2f From d6b704908ba79827d94bf55d815fda390248c754 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:15:48 +1000 Subject: [PATCH 1131/1531] chore(release): 11.0.0-24 --- CHANGELOG.md | 14 ++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa9e011908..68b40a39eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-24](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-23...v11.0.0-24) (2026-06-17) + + +### Features + +* check access token expiry locally before attempting request ([#1270](https://github.com/b0ink/doubtfire-deploy/issues/1270)) ([4ff5562](https://github.com/b0ink/doubtfire-deploy/commit/4ff55627566f9004872c915658bd91bc348dd8e8)) +* submission history ([#1269](https://github.com/b0ink/doubtfire-deploy/issues/1269)) ([4cdae07](https://github.com/b0ink/doubtfire-deploy/commit/4cdae07eb5bef0f9866927892e92b6b80dde0c74)) +* upgrade gantt chart and add screenshotting ability ([#1263](https://github.com/b0ink/doubtfire-deploy/issues/1263)) ([08a8eee](https://github.com/b0ink/doubtfire-deploy/commit/08a8eee9337331aa328960e206722f8905c2a0f9)) + + +### Bug Fixes + +* use either portfolio available field ([f8d5142](https://github.com/b0ink/doubtfire-deploy/commit/f8d514261c7eca5465ac3af95da33b95a39d3f23)) + ## [11.0.0-23](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-22...v11.0.0-23) (2026-06-11) diff --git a/package-lock.json b/package-lock.json index 730fade0f0..9a65211e7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-23", + "version": "11.0.0-24", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-23", + "version": "11.0.0-24", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.17", diff --git a/package.json b/package.json index 45843a3301..437fef8080 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-23", + "version": "11.0.0-24", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From 1fb4637cd2386f1aeff227043e0002bf9b77837b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 17 Jun 2026 17:25:14 +1000 Subject: [PATCH 1132/1531] feat: add day of week to gantt chart --- src/app/doubtfire-angular.module.ts | 31 ++++- .../task-planner/task-planner.component.scss | 23 ++++ .../task-planner/task-planner.component.ts | 106 +++++++++++++++++- 3 files changed, 152 insertions(+), 8 deletions(-) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 518f8f3eb5..f968ab15a7 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -6,9 +6,11 @@ import {CodeEditorModule} from '@ngstack/code-editor'; import {NgxChartsModule} from '@swimlane/ngx-charts'; import { GANTT_GLOBAL_CONFIG, - GanttI18nLocale, + GANTT_I18N_LOCALE_TOKEN, + type GanttI18nLocaleConfig, GanttLinkLineType, NgxGanttModule, + enUsLocale, } from '@worktile/gantt'; import {DateAdapter as CalendarDateAdapter, CalendarModule} from 'angular-calendar'; import {adapterFactory} from 'angular-calendar/date-adapters/date-fns'; @@ -388,10 +390,33 @@ const MY_DATE_FORMAT = { }, }; +const DOUBTFIRE_GANTT_LOCALE = 'doubtfire-en-au'; + +const DOUBTFIRE_GANTT_LOCALE_CONFIG: GanttI18nLocaleConfig = { + ...enUsLocale, + id: DOUBTFIRE_GANTT_LOCALE, + views: { + ...enUsLocale.views, + day: { + ...enUsLocale.views.day, + tickFormats: { + ...enUsLocale.views.day.tickFormats, + unit: 'd EEE', + }, + }, + }, +}; + +const GANTT_CHART_LOCALE_CONFIG = { + provide: GANTT_I18N_LOCALE_TOKEN, + useValue: DOUBTFIRE_GANTT_LOCALE_CONFIG, + multi: true, +}; + const GANTT_CHART_CONFIG = { provide: GANTT_GLOBAL_CONFIG, useValue: { - locale: GanttI18nLocale.enUs, + locale: DOUBTFIRE_GANTT_LOCALE, dateOptions: { weekStartsOn: 1, }, @@ -400,6 +425,7 @@ const GANTT_CHART_CONFIG = { lineType: GanttLinkLineType.curve, }, styleOptions: { + headerHeight: 52, // lineHeight: '25', // barHeight: '23', // headerHeight: '50px', @@ -712,6 +738,7 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { TaskPrerequisiteService, MarkingSessionService, DiscussionPromptService, + GANTT_CHART_LOCALE_CONFIG, GANTT_CHART_CONFIG, TaskPlannerPrerequisitesModalService, OverseerStepService, diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.scss b/src/app/projects/states/plan/task-planner/task-planner.component.scss index ddf668e57b..df94c4a868 100644 --- a/src/app/projects/states/plan/task-planner/task-planner.component.scss +++ b/src/app/projects/states/plan/task-planner/task-planner.component.scss @@ -9,6 +9,29 @@ pointer-events: none; } +:host ::ng-deep gantt-calendar-header .secondary-text { + font-size: 11px; + line-height: 1.15; + transform: translateY(-0.45em); + white-space: pre-line; +} + +:host ::ng-deep gantt-calendar-header .today-rect { + display: flex; + height: 28px !important; + transform: translateY(-0.35rem); + flex-direction: column; + align-items: center; + justify-content: center; + gap: 1px; + line-height: 1; +} + +:host ::ng-deep gantt-calendar-header .today-weekday { + font-size: 9px; + font-weight: 500; +} + .gantt-bar { background-color: var(--bar-bg); } diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.ts b/src/app/projects/states/plan/task-planner/task-planner.component.ts index 207caf2d51..fa36cd35c6 100644 --- a/src/app/projects/states/plan/task-planner/task-planner.component.ts +++ b/src/app/projects/states/plan/task-planner/task-planner.component.ts @@ -9,7 +9,15 @@ import { GanttViewType, NgxGanttComponent, } from '@worktile/gantt'; -import {Component, Input, OnInit, ViewChild} from '@angular/core'; +import { + AfterViewInit, + Component, + ElementRef, + Input, + OnDestroy, + OnInit, + ViewChild, +} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {Project} from 'src/app/api/models/project'; import {Task} from 'src/app/api/models/task'; @@ -37,9 +45,11 @@ interface TaskGanttItem extends GanttItem { providers: [GanttPrintService], standalone: false, }) -export class TaskPlannerComponent implements OnInit { +export class TaskPlannerComponent implements OnInit, AfterViewInit, OnDestroy { // Show a warning if the task's target end date is within this many days of the feedback deadline public readonly CLOSE_TO_FEEDBACK_DEADLINE_THRESHOLD = 7; + private readonly svgNamespace = 'http://www.w3.org/2000/svg'; + private ganttHeaderObserver?: MutationObserver; @Input() project: Project; @Input() targetGrade: number; @@ -66,6 +76,7 @@ export class TaskPlannerComponent implements OnInit { } constructor( + private elementRef: ElementRef, private gradeService: GradeService, private alertService: AlertService, private confirmationModalService: ConfirmationModalService, @@ -76,6 +87,14 @@ export class TaskPlannerComponent implements OnInit { private ganttPrintService: GanttPrintService, ) {} + ngAfterViewInit(): void { + setTimeout(() => this.setupGanttHeaderObserver()); + } + + ngOnDestroy(): void { + this.ganttHeaderObserver?.disconnect(); + } + public get gradeValues() { return this.gradeService.gradeValues; } @@ -534,10 +553,7 @@ export class TaskPlannerComponent implements OnInit { precisionUnit: 'day', start: new GanttDate(this.earliestStartDate), end: new GanttDate(this.latestEndDate), - tickFormats: { - period: 'yyyy MMM', - unit: 'd', - }, + unitWidth: 40, dragTooltipFormat: 'MMM dd', }; @@ -574,6 +590,84 @@ export class TaskPlannerComponent implements OnInit { }); } + private setupGanttHeaderObserver(): void { + const ganttElement = this.elementRef.nativeElement.querySelector('ngx-gantt'); + + if (!ganttElement) { + return; + } + + this.ganttHeaderObserver?.disconnect(); + this.ganttHeaderObserver = new MutationObserver(() => this.formatGanttHeaderLabels()); + this.ganttHeaderObserver.observe(ganttElement, { + childList: true, + subtree: true, + characterData: true, + }); + this.formatGanttHeaderLabels(); + } + + private formatGanttHeaderLabels(): void { + this.formatGanttDayLabels(); + this.formatGanttTodayLabel(); + } + + private formatGanttDayLabels(): void { + const dayLabels = this.elementRef.nativeElement.querySelectorAll( + 'gantt-calendar-header .secondary-text', + ); + + dayLabels.forEach((label) => { + if (label.querySelector('tspan')) { + return; + } + + const [date, day] = label.textContent?.trim().split(/\s+/) ?? []; + + if (!date || !day) { + return; + } + + const x = label.getAttribute('x') ?? '0'; + const dateLine = document.createElementNS(this.svgNamespace, 'tspan'); + dateLine.setAttribute('x', x); + dateLine.textContent = date; + + const dayLine = document.createElementNS(this.svgNamespace, 'tspan'); + dayLine.setAttribute('x', x); + dayLine.setAttribute('dy', '1.15em'); + dayLine.textContent = day; + + label.textContent = ''; + label.append(dateLine, dayLine); + }); + } + + private formatGanttTodayLabel(): void { + const todayLabel = this.elementRef.nativeElement.querySelector( + 'gantt-calendar-header .today-rect', + ); + + if (!todayLabel || todayLabel.querySelector('.today-weekday')) { + return; + } + + const today = new Date(); + const date = todayLabel.textContent?.trim() || today.getDate().toString(); + const day = new Intl.DateTimeFormat('en-US', {weekday: 'short'}).format(today); + + todayLabel.replaceChildren(); + + const dateLine = document.createElement('span'); + dateLine.textContent = date; + + const dayLine = document.createElement('span'); + dayLine.classList.add('today-weekday'); + dayLine.textContent = day; + + todayLabel.append(dateLine, dayLine); + } + refreshItems(scroll: boolean = true) { this.taskPrerequisites = this.allTaskPrerequisites.filter((pre) => this.taskDefs().find((td) => td.id === pre.taskDefinitionId), From 83b6d5ea381604ae88585195314eafd239880632 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Thu, 18 Jun 2026 09:53:59 +1000 Subject: [PATCH 1133/1531] fix: web calendar (#1282) * refactor: improve calendar ui/ux * refactor: improve ui * chore: add install guide * chore: correct google calendar * fix: copy to clipboard * chore: add mock ics extension * feat: open web cal from task planner --- .../calendar-modal.component.html | 316 ++++++++++-------- .../calendar-modal.component.scss | 27 -- .../calendar-modal.component.ts | 36 +- .../calendar-modal/calendar-modal.service.ts | 7 +- .../states/plan/project-plan.component.html | 12 +- .../states/plan/project-plan.component.ts | 6 + 6 files changed, 221 insertions(+), 183 deletions(-) diff --git a/src/app/common/modals/calendar-modal/calendar-modal.component.html b/src/app/common/modals/calendar-modal/calendar-modal.component.html index d7fe452d00..c6ae782ace 100644 --- a/src/app/common/modals/calendar-modal/calendar-modal.component.html +++ b/src/app/common/modals/calendar-modal/calendar-modal.component.html @@ -1,11 +1,11 @@ -
      -
      -
      +
      +
      +

      Web calendar

      Web calendar

      > - -
      +
      @if (!webcal) { - + } - @if (webcal) { Your web calendar is currently {{ webcal.enabled ? 'enabled' : 'disabled' }}. @@ -41,7 +34,6 @@

      Web calendar

      } - @if (webcal.enabled) {
      @@ -49,150 +41,184 @@

      Web calendar

      The web calendar displays due dates of your tasks as calendar events. Use the following URL to subscribe to your web calendar from your iCalendar client.

      -
      - -
      - - + } + + + } + +
      + + - refresh - -
      -
      - + Remind me + + + Time + + + + Unit + + Weeks + Days + Hours + Minutes + + + before each event - -

      Options

      + + @if ( + (!webcal.reminder && newReminderActive) || + (webcal.reminder && + (newReminderTime !== webcal.reminder.time || + newReminderUnit !== webcal.reminder.unit)) + ) { + + + } +
      -
      - Included units in my calendar: -
      + Include task start dates in web calendar + + +
      +
      + + + + + -
      - - @for (project of includedProjects; track project) { - - {{ project.unit.code }} - cancel - +
      + @switch (selectedCalendarProviderIndex) { + @case (0) { + In Google Calendar, choose Add other calendars, choose + From URL, then paste the URL below. } - @if (excludedProjects.length > 0) { - - add - - @for (project of excludedProjects; track project) { - - } - - + @case (1) { + In Apple Calendar, choose File, + New Calendar Subscription, then paste the URL below. } - + @case (2) { + In Outlook Calendar, choose Add calendar, + Subscribe from web, then paste the URL below. + } + }
      - - - Remind me - - - Time - - - - Unit - - Weeks - Days - Hours - Minutes - - - before each event - - @if ( - (!webcal.reminder && newReminderActive) || - (webcal.reminder && - (newReminderTime !== webcal.reminder.time || - newReminderUnit !== webcal.reminder.unit)) - ) { - - - } - - -
      - - - Include task start dates in web calendar - -
      - +
      +
      +
      +
      + link{{ webcalUrl }}.ics +
      +
      +
      + + +
      +
      - +
      } - } -
      - + +
      + +
      diff --git a/src/app/common/modals/calendar-modal/calendar-modal.component.scss b/src/app/common/modals/calendar-modal/calendar-modal.component.scss index f5e8c6f195..e69de29bb2 100644 --- a/src/app/common/modals/calendar-modal/calendar-modal.component.scss +++ b/src/app/common/modals/calendar-modal/calendar-modal.component.scss @@ -1,27 +0,0 @@ -.calendar-modal-component { - max-width: 600px; - overflow-x: hidden; - - .webcal-progress-spinner { - margin: 0 auto; - } - - .webcal-url-container { - display: flex; - align-items: center; - } - - .webcal-options-card { - margin-top: 1em; - box-shadow: none; - padding: 0; - } - - .webcal-options-inclusions { - padding: 0.8em 0 0.4em 0; - } - - .webcal-options-inclusions-chips { - padding-bottom: 1em; - } -} diff --git a/src/app/common/modals/calendar-modal/calendar-modal.component.ts b/src/app/common/modals/calendar-modal/calendar-modal.component.ts index c0d2ac0dff..40e5856c6e 100644 --- a/src/app/common/modals/calendar-modal/calendar-modal.component.ts +++ b/src/app/common/modals/calendar-modal/calendar-modal.component.ts @@ -4,6 +4,7 @@ import {MatSlideToggle} from '@angular/material/slide-toggle'; import {Project, ProjectService, Webcal, WebcalService} from 'src/app/api/models/doubtfire-model'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {AlertService} from '../../services/alert.service'; +import {ConfirmationModalService} from '../confirmation-modal/confirmation-modal.service'; @Component({ selector: 'calendar-modal', @@ -17,6 +18,7 @@ export class CalendarModalComponent implements OnInit, AfterViewInit { webcal: Webcal | null; working: boolean = true; copying: boolean = false; + selectedCalendarProviderIndex: number = 0; projects: Project[] = []; // Used to store user interaction with the reminder option. These values aren't bound directly to `this.webcal` @@ -31,6 +33,7 @@ export class CalendarModalComponent implements OnInit, AfterViewInit { private alerts: AlertService, private projectService: ProjectService, @Inject(MAT_DIALOG_DATA) public data: object, + private confirmationModal: ConfirmationModalService, ) {} ngOnInit() { @@ -66,8 +69,21 @@ export class CalendarModalComponent implements OnInit, AfterViewInit { * Invoked when the user toggles the webcal. */ onWebcalToggle() { + if (this.webcal.enabled) { + this.confirmationModal.show( + 'Disable web calendar', + 'Disabling your web calendar will expire the current subscription URL. Any calendar apps using this URL will stop updating, and a new URL will be generated if you enable the calendar again.', + () => this.updateWebcalEnabled(false), + ); + return; + } + + this.updateWebcalEnabled(true); + } + + private updateWebcalEnabled(enabled: boolean) { this.working = true; - this.webcal.enabled = !this.webcal.enabled; + this.webcal.enabled = enabled; this.webcalService.update(this.webcal).subscribe((webcal) => { this.loadWebcal(webcal); @@ -93,12 +109,18 @@ export class CalendarModalComponent implements OnInit, AfterViewInit { * Invoked when the user requests their webcal URL to be changed. */ onChangeWebcalUrl() { - this.working = true; - this.webcal.shouldChangeGuid = true; - this.webcalService.update(this.webcal).subscribe((webcal) => { - this.loadWebcal(webcal); - this.working = false; - }); + this.confirmationModal.show( + 'Regenerate URL', + 'Regenerating your calendar URL will disable the current subscription link. Any calendar apps using the old URL will stop updating until you subscribe again with the new one.', + () => { + this.working = true; + this.webcal.shouldChangeGuid = true; + this.webcalService.update(this.webcal).subscribe((webcal) => { + this.loadWebcal(webcal); + this.working = false; + }); + }, + ); } /** diff --git a/src/app/common/modals/calendar-modal/calendar-modal.service.ts b/src/app/common/modals/calendar-modal/calendar-modal.service.ts index f26164d57d..fd1c6bec9f 100644 --- a/src/app/common/modals/calendar-modal/calendar-modal.service.ts +++ b/src/app/common/modals/calendar-modal/calendar-modal.service.ts @@ -10,6 +10,11 @@ export class CalendarModalService { constructor(public dialog: MatDialog) {} public show(_task?: Task) { - this.dialog.open(CalendarModalComponent); + this.dialog.open(CalendarModalComponent, { + height: 'h-min', + maxHeight: '90vh', + width: '800px', + maxWidth: '95vw', + }); } } diff --git a/src/app/projects/states/plan/project-plan.component.html b/src/app/projects/states/plan/project-plan.component.html index 733eda3558..863382897d 100644 --- a/src/app/projects/states/plan/project-plan.component.html +++ b/src/app/projects/states/plan/project-plan.component.html @@ -14,9 +14,6 @@

      Task Planner

      Click on a task in the timeline to see how it connects to other tasks. This will show you which tasks must be completed before it, and which tasks depend on it being completed first.

      - - -
      Target Grade @@ -31,6 +28,15 @@

      Task Planner

      +

      + Subscribe to your unit calendar to be reminded about your due dates. + +

      +
      + +
      } diff --git a/src/app/projects/states/plan/project-plan.component.ts b/src/app/projects/states/plan/project-plan.component.ts index 995a101df5..28129d6469 100644 --- a/src/app/projects/states/plan/project-plan.component.ts +++ b/src/app/projects/states/plan/project-plan.component.ts @@ -3,6 +3,7 @@ import {MatSelectChange} from '@angular/material/select'; import {ActivatedRoute} from '@angular/router'; import {Observable, Subscription, of} from 'rxjs'; import {Project, ProjectService} from 'src/app/api/models/doubtfire-model'; +import {CalendarModalService} from 'src/app/common/modals/calendar-modal/calendar-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {GradeService} from 'src/app/common/services/grade.service'; import {TaskPlannerComponent} from './task-planner/task-planner.component'; @@ -45,6 +46,7 @@ export class ProjectPlanComponent implements OnInit, OnDestroy { private projectService: ProjectService, private alertService: AlertService, private route: ActivatedRoute, + private calendarModal: CalendarModalService, ) {} ngOnInit(): void { @@ -64,6 +66,10 @@ export class ProjectPlanComponent implements OnInit, OnDestroy { this.projectSub?.unsubscribe(); } + openCalendar(): void { + this.calendarModal.show(null); + } + onTargetGradeChange(event: MatSelectChange) { const previousTargetGrade = this.project.targetGrade; this.project.targetGrade = event.value; From 38c0e85ebe698c71ea087f3aeecc6d7ca24c86d7 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 18 Jun 2026 10:01:25 +1000 Subject: [PATCH 1134/1531] feat: show students name if viewing other project --- .../progress-dashboard.component.html | 2 +- .../progress-dashboard.component.ts | 11 +++++++++-- .../projects/states/plan/project-plan.component.html | 7 ++++++- .../projects/states/plan/project-plan.component.ts | 10 +++++++++- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html index cc01407796..68901ff1fb 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html @@ -2,7 +2,7 @@

      Progress Dashboard - @if (tutor) { + @if (viewingOtherStudentProject) { for {{ project.student.name }} }

      diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts index 5e5efd8a66..621544ee18 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts @@ -1,6 +1,7 @@ import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; import {Project} from 'src/app/api/models/project'; import {ProjectService} from 'src/app/api/services/project.service'; +import {UserService} from 'src/app/api/services/user.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {GradeService} from 'src/app/common/services/grade.service'; @@ -14,7 +15,6 @@ export class ProgressDashboardComponent implements OnInit { @Input() project: Project; @Output() doUpdateTargetGrade: EventEmitter = new EventEmitter(); - tutor: boolean; grades = { names: this.gradeService.grades, values: this.gradeService.gradeValues, @@ -28,12 +28,19 @@ export class ProgressDashboardComponent implements OnInit { private gradeService: GradeService, private projectService: ProjectService, private alertService: AlertService, + private userService: UserService, ) {} ngOnInit(): void { this.updateTaskCompletionValues(); this.project?.refreshBurndownChartData(); - this.tutor = this.project.myRole === 'Tutor' ? true : false; + } + + public get viewingOtherStudentProject(): boolean { + const role = this.project?.unit?.myRole; + const currentUser = this.userService.currentUser; + + return !!role && role !== 'Student' && this.project?.student?.id !== currentUser?.id; } updateTargetGrade(newGrade: number): void { diff --git a/src/app/projects/states/plan/project-plan.component.html b/src/app/projects/states/plan/project-plan.component.html index 863382897d..50714cdf88 100644 --- a/src/app/projects/states/plan/project-plan.component.html +++ b/src/app/projects/states/plan/project-plan.component.html @@ -1,6 +1,11 @@ @if (project) {
      -

      Task Planner

      +

      + Task Planner + @if (viewingOtherStudentProject) { + for {{ project.student.name }} + } +

      @if (unit.allowFlexibleDates) { View and adjust the due dates for your tasks. Remember to leave time to get and respond to diff --git a/src/app/projects/states/plan/project-plan.component.ts b/src/app/projects/states/plan/project-plan.component.ts index 28129d6469..8a2a591ea9 100644 --- a/src/app/projects/states/plan/project-plan.component.ts +++ b/src/app/projects/states/plan/project-plan.component.ts @@ -2,7 +2,7 @@ import {Component, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; import {MatSelectChange} from '@angular/material/select'; import {ActivatedRoute} from '@angular/router'; import {Observable, Subscription, of} from 'rxjs'; -import {Project, ProjectService} from 'src/app/api/models/doubtfire-model'; +import {Project, ProjectService, UserService} from 'src/app/api/models/doubtfire-model'; import {CalendarModalService} from 'src/app/common/modals/calendar-modal/calendar-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {GradeService} from 'src/app/common/services/grade.service'; @@ -47,6 +47,7 @@ export class ProjectPlanComponent implements OnInit, OnDestroy { private alertService: AlertService, private route: ActivatedRoute, private calendarModal: CalendarModalService, + private userService: UserService, ) {} ngOnInit(): void { @@ -70,6 +71,13 @@ export class ProjectPlanComponent implements OnInit, OnDestroy { this.calendarModal.show(null); } + public get viewingOtherStudentProject(): boolean { + const role = this.project?.unit?.myRole; + const currentUser = this.userService.currentUser; + + return !!role && role !== 'Student' && this.project?.student?.id !== currentUser?.id; + } + onTargetGradeChange(event: MatSelectChange) { const previousTargetGrade = this.project.targetGrade; this.project.targetGrade = event.value; From 7a754dcc82ca228f5688abab4480774df75a007e Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:23:04 +1000 Subject: [PATCH 1135/1531] feat: engagement passport (#1257) * feat: engagement passport * feat: connect engagements to backend * feat: view engagement comments * chore: render evidence url * chore: open engagement dialog from tutor discussion * chore: format * refactor: use placeholder text and default note if left empty * chore: swap occurred at and created at dates * chore: improve layout * chore: format * fix: prevent mobile devices from zooming in on modal inputs * chore: reorder engagement types * refactor: rename negative to needs attention --- src/app/api/models/doubtfire-model.ts | 3 + src/app/api/models/engagement.ts | 69 +++++ src/app/api/models/project.ts | 2 + .../services/engagement-comment.service.ts | 116 +++++++ src/app/api/services/engagement.service.ts | 177 +++++++++++ src/app/doubtfire-angular.module.ts | 10 + .../add-engagement-dialog.component.html | 121 ++++++++ .../add-engagement-dialog.component.scss | 12 + .../add-engagement-dialog.component.ts | 168 ++++++++++ .../engagement-detail-dialog.component.html | 288 ++++++++++++++++++ .../engagement-detail-dialog.component.scss | 14 + .../engagement-detail-dialog.component.ts | 178 +++++++++++ .../engagement-passport-card.component.html | 100 ++++++ .../engagement-passport-card.component.scss | 0 .../engagement-passport-card.component.ts | 195 ++++++++++++ .../progress-dashboard.component.html | 5 + .../tutor-discussion.component.html | 10 +- .../tutor-discussion.component.ts | 54 +++- 18 files changed, 1509 insertions(+), 13 deletions(-) create mode 100644 src/app/api/models/engagement.ts create mode 100644 src/app/api/services/engagement-comment.service.ts create mode 100644 src/app/api/services/engagement.service.ts create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.html create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.scss create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.ts create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.html create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.scss create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.ts create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.html create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.scss create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.ts diff --git a/src/app/api/models/doubtfire-model.ts b/src/app/api/models/doubtfire-model.ts index 4c04633b82..60b3bfb8b9 100644 --- a/src/app/api/models/doubtfire-model.ts +++ b/src/app/api/models/doubtfire-model.ts @@ -40,6 +40,7 @@ export * from './task-comment/scorm-comment'; export * from './task-comment/scorm-extension-comment'; export * from './feedback-template'; export * from './communication'; +export * from './engagement'; // Users -- are students or staff export * from './user/user'; @@ -72,3 +73,5 @@ export * from '../services/communication-set.service'; export * from '../services/communication-rule.service'; export * from '../services/communication-condition.service'; export * from '../services/communication-action.service'; +export * from '../services/engagement.service'; +export * from '../services/engagement-comment.service'; diff --git a/src/app/api/models/engagement.ts b/src/app/api/models/engagement.ts new file mode 100644 index 0000000000..369fe42745 --- /dev/null +++ b/src/app/api/models/engagement.ts @@ -0,0 +1,69 @@ +import {Entity, EntityCache} from 'ngx-entity-service'; +import {AppInjector} from 'src/app/app-injector'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Project, User, UserService} from './doubtfire-model'; + +export class Engagement extends Entity { + id: number; + project: Project; + user: User; + engagementType: string; + note: string; + occurredAt: Date; + evidenceUrl?: string; + contentType?: 'image' | 'pdf'; + hasAttachment: boolean; + attachmentFileName?: string; + commentCount: number; + createdAt: Date; + updatedAt: Date; + + readonly commentCache: EntityCache = new EntityCache(); + + constructor(project?: Project) { + super(); + this.project = project; + } + + get comments(): readonly EngagementComment[] { + return this.commentCache.currentValues; + } + + get attachmentUrl(): string { + return `${AppInjector.get(DoubtfireConstants).API_URL}/projects/${this.project.id}/engagements/${this.id}/attachment`; + } +} + +export class EngagementComment extends Entity { + private static readonly EDIT_WINDOW_MS = 10 * 60 * 1000; + + id: number; + engagement: Engagement; + user: User; + comment: string; + replyToId?: number; + replyTo?: EngagementComment; + createdAt: Date; + updatedAt: Date; + + constructor(engagement?: Engagement) { + super(); + this.engagement = engagement; + } + + get authorIsMe(): boolean { + return this.user.id === AppInjector.get(UserService).currentUser.id; + } + + get currentUserCanEdit(): boolean { + return ( + this.authorIsMe && + this.createdAt instanceof Date && + Date.now() - this.createdAt.getTime() <= EngagementComment.EDIT_WINDOW_MS + ); + } + + get currentUserCanDelete(): boolean { + return this.authorIsMe || this.engagement.project.unit.myRole === 'Convenor'; + } +} diff --git a/src/app/api/models/project.ts b/src/app/api/models/project.ts index 4d4e2f3dd8..574ec84ed1 100644 --- a/src/app/api/models/project.ts +++ b/src/app/api/models/project.ts @@ -21,6 +21,7 @@ import { Unit, User, } from './doubtfire-model'; +import {Engagement} from './engagement'; import {StaffNote} from './staff-note'; import {TaskOutcomeAlignment} from './task-outcome-alignment'; @@ -55,6 +56,7 @@ export class Project extends Entity { public burndownChartData: {key: string; values: number[]}[]; public readonly taskCache: EntityCache = new EntityCache(); public readonly staffNoteCache: EntityCache = new EntityCache(); + public readonly engagementCache: EntityCache = new EntityCache(); public readonly tutorialEnrolmentsCache: EntityCache = new EntityCache(); public readonly groupCache: EntityCache = new EntityCache(); public readonly taskOutcomeAlignmentsCache: EntityCache = diff --git a/src/app/api/services/engagement-comment.service.ts b/src/app/api/services/engagement-comment.service.ts new file mode 100644 index 0000000000..bceb22511e --- /dev/null +++ b/src/app/api/services/engagement-comment.service.ts @@ -0,0 +1,116 @@ +import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {Observable, tap} from 'rxjs'; +import {Engagement, EngagementComment, UserService} from 'src/app/api/models/doubtfire-model'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {MappingFunctions} from './mapping-fn'; + +@Injectable() +export class EngagementCommentService extends CachedEntityService { + protected readonly endpointFormat = + 'projects/:projectId:/engagements/:engagementId:/comments/:id:'; + + constructor( + httpClient: HttpClient, + private userService: UserService, + ) { + super(httpClient, API_URL); + + this.mapping.addKeys( + 'id', + 'comment', + 'replyToId', + { + keys: 'user', + toEntityFn: (data: object, key: string) => { + return this.userService.cache.getOrCreate(data[key].id, this.userService, data[key]); + }, + }, + { + keys: 'createdAt', + toEntityFn: MappingFunctions.mapDate, + }, + { + keys: 'updatedAt', + toEntityFn: MappingFunctions.mapDate, + }, + ); + } + + createInstanceFrom(_json: object, other?: Engagement): EngagementComment { + return new EngagementComment(other); + } + + addComment( + engagement: Engagement, + comment: string, + replyTo?: EngagementComment, + ): Observable { + const options: RequestOptions = { + endpointFormat: this.endpointFormat, + cache: engagement.commentCache, + constructorParams: engagement, + body: { + comment, + ...(replyTo ? {reply_to_id: replyTo.id} : {}), + }, + }; + + return this.create( + { + projectId: engagement.project.id, + engagementId: engagement.id, + }, + options, + ).pipe( + tap(() => { + engagement.commentCount++; + this.updateCommentReplies(engagement.comments); + }), + ); + } + + updateComment(comment: EngagementComment, text: string): Observable { + return this.put( + { + projectId: comment.engagement.project.id, + engagementId: comment.engagement.id, + id: comment.id, + }, + { + endpointFormat: this.endpointFormat, + cache: comment.engagement.commentCache, + constructorParams: comment.engagement, + body: {comment: text}, + }, + ); + } + + deleteComment(comment: EngagementComment): Observable { + return this.delete( + { + projectId: comment.engagement.project.id, + engagementId: comment.engagement.id, + id: comment.id, + }, + { + endpointFormat: this.endpointFormat, + cache: comment.engagement.commentCache, + }, + ).pipe( + tap(() => { + comment.engagement.commentCount--; + this.updateCommentReplies(comment.engagement.comments); + }), + ); + } + + updateCommentReplies(comments: readonly EngagementComment[]): void { + for (const comment of comments) { + comment.replyTo = comment.replyToId + ? comments.find((candidate) => candidate.id === comment.replyToId) + : undefined; + } + } +} diff --git a/src/app/api/services/engagement.service.ts b/src/app/api/services/engagement.service.ts new file mode 100644 index 0000000000..89c63a189a --- /dev/null +++ b/src/app/api/services/engagement.service.ts @@ -0,0 +1,177 @@ +import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {Observable} from 'rxjs'; +import { + Engagement, + EngagementCommentService, + Project, + UserService, +} from 'src/app/api/models/doubtfire-model'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {MappingFunctions} from './mapping-fn'; + +export interface EngagementData { + engagementType: string; + note: string; + occurredAt: Date; + evidenceUrl?: string; + attachment?: File; +} + +export interface EngagementUpdate extends Partial { + removeEvidence?: boolean; +} + +@Injectable() +export class EngagementService extends CachedEntityService { + protected readonly endpointFormat = 'projects/:projectId:/engagements/:id:'; + + constructor( + httpClient: HttpClient, + private userService: UserService, + private engagementCommentService: EngagementCommentService, + ) { + super(httpClient, API_URL); + + this.mapping.addKeys( + 'id', + 'engagementType', + 'note', + 'evidenceUrl', + 'contentType', + 'hasAttachment', + 'attachmentFileName', + 'commentCount', + { + keys: 'user', + toEntityFn: (data: object, key: string) => { + return this.userService.cache.getOrCreate(data[key].id, this.userService, data[key]); + }, + }, + { + keys: 'occurredAt', + toEntityFn: MappingFunctions.mapDate, + }, + { + keys: 'createdAt', + toEntityFn: MappingFunctions.mapDate, + }, + { + keys: 'updatedAt', + toEntityFn: MappingFunctions.mapDate, + }, + { + keys: 'comments', + toEntityOp: (data: object, key: string, engagement: Engagement) => { + engagement.commentCache.clear(); + data[key]?.forEach((comment) => { + engagement.commentCache.getOrCreate( + comment.id, + this.engagementCommentService, + comment, + {constructorParams: engagement}, + ); + }); + this.engagementCommentService.updateCommentReplies(engagement.comments); + }, + }, + ); + } + + createInstanceFrom(_json: object, other?: Project): Engagement { + return new Engagement(other); + } + + loadEngagements(project: Project, refresh: boolean = false): Observable { + const options: RequestOptions = { + endpointFormat: this.endpointFormat, + cache: project.engagementCache, + sourceCache: project.engagementCache, + cacheBehaviourOnGet: 'cacheQuery', + constructorParams: project, + }; + const pathIds = {projectId: project.id}; + + return refresh ? this.fetchAll(pathIds, options) : this.query(pathIds, options); + } + + loadEngagement(engagement: Engagement): Observable { + return this.fetch( + { + projectId: engagement.project.id, + id: engagement.id, + }, + { + endpointFormat: this.endpointFormat, + cache: engagement.project.engagementCache, + constructorParams: engagement.project, + }, + ); + } + + createEngagement(project: Project, data: EngagementData): Observable { + return this.create( + {projectId: project.id}, + { + endpointFormat: this.endpointFormat, + cache: project.engagementCache, + constructorParams: project, + body: this.toFormData(data), + }, + ); + } + + updateEngagement(engagement: Engagement, data: EngagementUpdate): Observable { + return this.put( + { + projectId: engagement.project.id, + id: engagement.id, + }, + { + endpointFormat: this.endpointFormat, + cache: engagement.project.engagementCache, + constructorParams: engagement.project, + body: this.toFormData(data), + }, + ); + } + + deleteEngagement(engagement: Engagement): Observable { + return this.delete( + { + projectId: engagement.project.id, + id: engagement.id, + }, + { + endpointFormat: this.endpointFormat, + cache: engagement.project.engagementCache, + }, + ); + } + + private toFormData(data: EngagementUpdate): FormData { + const body = new FormData(); + + if (data.engagementType !== undefined) { + body.append('engagement_type', data.engagementType); + } + if (data.note !== undefined) { + body.append('note', data.note); + } + if (data.occurredAt !== undefined) { + body.append('occurred_at', data.occurredAt.toISOString()); + } + if (data.evidenceUrl !== undefined) { + body.append('evidence_url', data.evidenceUrl); + } + if (data.attachment !== undefined) { + body.append('attachment', data.attachment); + } + if (data.removeEvidence !== undefined) { + body.append('remove_evidence', String(data.removeEvidence)); + } + + return body; + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index f968ab15a7..f64afd172d 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -119,6 +119,8 @@ import { AuthenticationService, CampusService, D2lAssessmentMappingService, + EngagementCommentService, + EngagementService, GroupSetService, LearningOutcomeService, OverseerAssessmentService, @@ -245,6 +247,9 @@ import {LtiDashboardComponent} from './home/states/lti-dashboard/lti-dashboard.c import {LtiUnitLinkComponent} from './home/states/lti-unit-link/lti-unit-link.component'; import {LegacyRoutePlaceholderComponent} from './legacy-route-placeholder.component'; import {ProjectProgressDashboardComponent} from './projects/project-progress-dashboard/project-progress-dashboard.component'; +import {AddEngagementDialogComponent} from './projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component'; +import {EngagementDetailDialogComponent} from './projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component'; +import {EngagementPassportCardComponent} from './projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component'; import {ProgressDashboardComponent} from './projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component'; import {TaskPlannerCardComponent} from './projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component'; import {CreatePortfolioTaskListItemComponent} from './projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component'; @@ -446,6 +451,9 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { AppComponent, TaskStatusPieChartComponent, AlertComponent, + AddEngagementDialogComponent, + EngagementPassportCardComponent, + EngagementDetailDialogComponent, ProgressDashboardComponent, UnitStudentEnrolmentModalComponent, AboutDoubtfireModalContent, @@ -701,6 +709,8 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { {provide: DateAdapter, useClass: DateFnsAdapter, deps: [MAT_DATE_LOCALE]}, {provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMAT}, TaskCommentService, + EngagementCommentService, + EngagementService, { provide: HTTP_INTERCEPTORS, useClass: HttpAuthenticationInterceptor, diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.html new file mode 100644 index 0000000000..234ea67dff --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.html @@ -0,0 +1,121 @@ +

      Add Engagement Stamp

      + + + + + Engagement type + + + @for (type of engagementTypes; track type) { + {{ type }} + } + + Choose a suggestion or enter another type. + @if (form.controls.engagementType.hasError('required')) { + Enter an engagement type. + } + + + + Note + + {{ form.controls.note.value.length }} / 4095 + + +
      + + Date + + + + @if (form.controls.occurredDate.hasError('required')) { + Select when the engagement occurred. + } + + + + Time + + @if (form.controls.occurredTime.hasError('required')) { + Select a time. + } + +
      + + + Evidence + + No evidence + External URL + Upload image or PDF + + + + @if (form.controls.evidenceMode.value === 'url') { + + Evidence URL + + @if ( + form.controls.evidenceUrl.hasError('pattern') || + (form.controls.evidenceUrl.touched && !form.controls.evidenceUrl.value.trim()) + ) { + Enter a valid HTTP or HTTPS URL. + } + + } + + @if (form.controls.evidenceMode.value === 'attachment') { +
      + + +

      Maximum file size: 30 MB.

      + @if (attachmentError) { +

      {{ attachmentError }}

      + } +
      + } + +
      + + + + + diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.scss b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.scss new file mode 100644 index 0000000000..cdca2a91a1 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.scss @@ -0,0 +1,12 @@ +// Prevent mobile devices from zooming in engagement stamp modal inputs +@media (max-width: 768px) { + :host ::ng-deep { + .mat-mdc-input-element, + .mat-mdc-select, + .mat-mdc-select-value, + .mat-mdc-select-trigger, + .mat-mdc-select-min-line { + font-size: 20px !important; + } + } +} diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.ts new file mode 100644 index 0000000000..f3e3019c7a --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.ts @@ -0,0 +1,168 @@ +import {Component, Inject} from '@angular/core'; +import {FormControl, FormGroup, Validators} from '@angular/forms'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {Engagement, EngagementService, Project} from 'src/app/api/models/doubtfire-model'; +import {AlertService} from 'src/app/common/services/alert.service'; + +type EvidenceMode = 'none' | 'url' | 'attachment'; + +interface AddEngagementForm { + engagementType: FormControl; + note: FormControl; + occurredDate: FormControl; + occurredTime: FormControl; + evidenceMode: FormControl; + evidenceUrl: FormControl; +} + +@Component({ + selector: 'f-add-engagement-dialog', + templateUrl: './add-engagement-dialog.component.html', + styleUrl: './add-engagement-dialog.component.scss', + standalone: false, +}) +export class AddEngagementDialogComponent { + readonly engagementTypes = ['Discuss', 'Attendance', 'Forum', 'Email', 'Attention']; + readonly notePlaceholders: Record = { + attendance: 'Attended tutorial and participated in class activities.', + discuss: 'Discussed tasks during tutorial.', + discussion: 'Discussed tasks during tutorial.', + forum: 'Posted to the unit forum and engaged with discussion.', + email: 'Discussed unit progress with the teaching team via email.', + attention: 'Engagement concern noted for follow-up.', + }; + readonly maxAttachmentSize = 30 * 1024 * 1024; + readonly form: FormGroup; + + attachment?: File; + attachmentError?: string; + saving = false; + + constructor( + @Inject(MAT_DIALOG_DATA) readonly data: {project: Project}, + private dialogRef: MatDialogRef, + private engagementService: EngagementService, + private alerts: AlertService, + ) { + const now = new Date(); + this.form = new FormGroup({ + engagementType: new FormControl('', { + nonNullable: true, + validators: [Validators.required, Validators.maxLength(255)], + }), + note: new FormControl('', { + nonNullable: true, + validators: [Validators.maxLength(4095)], + }), + occurredDate: new FormControl(now, { + nonNullable: true, + validators: [Validators.required], + }), + occurredTime: new FormControl(this.formatTime(now), { + nonNullable: true, + validators: [Validators.required], + }), + evidenceMode: new FormControl('none', {nonNullable: true}), + evidenceUrl: new FormControl('', { + nonNullable: true, + validators: [Validators.pattern(/^https?:\/\/.+/i)], + }), + }); + } + + get canSubmit(): boolean { + if (this.form.invalid || this.saving || this.attachmentError !== undefined) return false; + + const mode = this.form.controls.evidenceMode.value; + if (mode === 'url') return this.form.controls.evidenceUrl.value.trim().length > 0; + if (mode === 'attachment') return this.attachment !== undefined; + + return true; + } + + get notePlaceholder(): string { + const engagementType = this.form.controls.engagementType.value.trim().toLowerCase(); + return ( + this.notePlaceholders[engagementType] ?? 'Describe how the student engaged with the unit.' + ); + } + + engagementTypeSelected(input: HTMLInputElement): void { + window.setTimeout(() => input.blur()); + } + + evidenceModeChanged(): void { + const mode = this.form.controls.evidenceMode.value; + + if (mode !== 'url') { + this.form.controls.evidenceUrl.setValue(''); + } + this.attachment = undefined; + this.attachmentError = undefined; + } + + fileSelected(event: Event): void { + const input = event.target as HTMLInputElement; + const file = input.files?.[0]; + + this.attachment = undefined; + this.attachmentError = undefined; + + if (!file) return; + if (file.size === 0) { + this.attachmentError = 'The selected file is empty.'; + input.value = ''; + return; + } + if (file.size > this.maxAttachmentSize) { + this.attachmentError = 'The selected file must be no larger than 30 MB.'; + input.value = ''; + return; + } + if (file.type !== 'application/pdf' && !file.type.startsWith('image/')) { + this.attachmentError = 'Select an image or PDF file.'; + input.value = ''; + return; + } + + this.attachment = file; + } + + submit(): void { + if (!this.canSubmit) { + this.form.markAllAsTouched(); + return; + } + + const values = this.form.getRawValue(); + const occurredAt = new Date(values.occurredDate); + const [hours, minutes] = values.occurredTime.split(':').map(Number); + occurredAt.setHours(hours, minutes, 0, 0); + + this.saving = true; + this.engagementService + .createEngagement(this.data.project, { + engagementType: values.engagementType.trim(), + note: values.note.trim() || this.notePlaceholder, + occurredAt, + evidenceUrl: values.evidenceMode === 'url' ? values.evidenceUrl.trim() : undefined, + attachment: values.evidenceMode === 'attachment' ? this.attachment : undefined, + }) + .subscribe({ + next: (engagement: Engagement) => { + this.alerts.success('Engagement stamp added.'); + this.dialogRef.close(engagement); + }, + error: (error) => { + this.saving = false; + this.alerts.error(error?.error ?? 'Unable to add the engagement stamp.'); + }, + }); + } + + private formatTime(date: Date): string { + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + return `${hours}:${minutes}`; + } +} diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.html new file mode 100644 index 0000000000..9eb0fe65b9 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.html @@ -0,0 +1,288 @@ +
      +
      +
      +
      +
      {{ engagement.engagementType }} Engagement
      +

      + Added by {{ engagement.user?.firstName }} {{ engagement.user?.lastName }} + · + + {{ engagement.occurredAt | humanizedDate }} + +

      +
      + + +
      +
      + + + @if (loading) { +
      + +
      + } @else if (loadFailed) { +

      Unable to load this engagement.

      + } @else { +
      + +
      + + + + {{ engagement.user?.firstName }} {{ engagement.user?.lastName }} + + +
      + + {{ engagement.createdAt | humanizedDate }} + +
      +
      + + +
      {{ engagement.note }}
      + + @if (engagement.evidenceUrl || engagement.hasAttachment) { +
      +

      Evidence

      + + @if (engagement.evidenceUrl) { + + link + {{ engagement.evidenceUrl }} + + } + + @if (engagement.hasAttachment && engagement.contentType === 'image') { + @if (evidenceLoading) { +
      + +
      + } @else if (evidenceBlobUrl) { + + } + } @else if (engagement.hasAttachment) { + + } + + @if (evidenceLoadFailed) { +

      Unable to load the attached evidence.

      + } +
      + } +
      +
      + + @for (comment of comments; track comment.id) { + @if (comment.replyToId) { +
      +
      + reply +
      + @if (comment.replyTo) { + + Replying to {{ comment.replyTo.user?.preferredName }} + {{ comment.replyTo.user?.lastName }} + + {{ comment.replyTo.comment }} + } @else { + Replying to: Deleted comment + } +
      +
      +
      + } + + +
      + @if (comment.currentUserCanEdit) { + + edit + + } + + reply + + @if (comment.currentUserCanDelete) { + + delete + + } +
      + +
      + + + {{ comment.user?.firstName }} {{ comment.user?.lastName }} + +
      + + {{ comment.createdAt | humanizedDate }} + +
      +
      + + + @if (editingComment?.id === comment.id) { + + Update Comment + +
      + + +
      +
      + } @else { +
      + } +
      +
      + } + + @if (comments.length === 0) { +

      No comments yet.

      + } + + +
      + } +
      + + @if (!loading && !loadFailed) { +
      + @if (replyingToComment) { +
      +
      +
      + reply +
      + + Replying to {{ replyingToComment.user?.preferredName }} + {{ replyingToComment.user?.lastName }} + + + {{ replyingToComment.comment }} + +
      +
      + +
      +
      + } + + + Comment + +
      + +
      +
      +
      + } +
      diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.scss b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.scss new file mode 100644 index 0000000000..684d95154b --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.scss @@ -0,0 +1,14 @@ +.action .mat-icon { + color: #9696969d; + font-size: 20px; + width: 20px; + height: 20px; + cursor: pointer; + vertical-align: middle; + text-align: center; + margin-left: 0.3em; +} + +.action .mat-icon:hover { + color: black; +} diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.ts new file mode 100644 index 0000000000..d86b756544 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.ts @@ -0,0 +1,178 @@ +import {Component, ElementRef, Inject, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import {MAT_DIALOG_DATA} from '@angular/material/dialog'; +import { + Engagement, + EngagementComment, + EngagementCommentService, + EngagementService, +} from 'src/app/api/models/doubtfire-model'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; + +@Component({ + selector: 'f-engagement-detail-dialog', + templateUrl: './engagement-detail-dialog.component.html', + styleUrl: './engagement-detail-dialog.component.scss', + standalone: false, +}) +export class EngagementDetailDialogComponent implements OnInit, OnDestroy { + @ViewChild('commentsEnd') commentsEnd?: ElementRef; + + engagement: Engagement; + commentText = ''; + loading = true; + loadFailed = false; + submitting = false; + replyingToComment?: EngagementComment; + hoveredCommentId?: number; + editingComment?: EngagementComment; + editingCommentText = ''; + evidenceBlobUrl?: string; + evidenceLoading = false; + evidenceLoadFailed = false; + + constructor( + @Inject(MAT_DIALOG_DATA) readonly data: {engagement: Engagement}, + private engagementService: EngagementService, + private engagementCommentService: EngagementCommentService, + private fileDownloader: FileDownloaderService, + private alerts: AlertService, + private confirmationModal: ConfirmationModalService, + ) { + this.engagement = data.engagement; + } + + get comments(): readonly EngagementComment[] { + return [...this.engagement.comments].sort( + (first, second) => first.createdAt.getTime() - second.createdAt.getTime(), + ); + } + + ngOnInit(): void { + this.engagementService.loadEngagement(this.engagement).subscribe({ + next: (engagement) => { + this.engagement = engagement; + this.loading = false; + this.loadAttachment(); + this.scrollToBottom(); + }, + error: () => { + this.loadFailed = true; + this.loading = false; + }, + }); + } + + ngOnDestroy(): void { + if (this.evidenceBlobUrl) this.fileDownloader.releaseBlob(this.evidenceBlobUrl); + } + + openAttachment(): void { + if (this.evidenceBlobUrl) window.open(this.evidenceBlobUrl, '_blank', 'noopener,noreferrer'); + } + + submitComment(): void { + const comment = this.commentText.trim(); + if (!comment || this.submitting) return; + + this.submitting = true; + this.engagementCommentService + .addComment(this.engagement, comment, this.replyingToComment) + .subscribe({ + next: () => { + this.commentText = ''; + this.submitting = false; + this.replyingToComment = undefined; + this.scrollToBottom(); + }, + error: (error) => { + this.submitting = false; + this.alerts.error(error?.error ?? 'Unable to add your comment.'); + }, + }); + } + + replyToComment(comment: EngagementComment): void { + this.replyingToComment = comment; + } + + cancelReply(): void { + this.replyingToComment = undefined; + } + + editComment(comment: EngagementComment): void { + if (!comment.currentUserCanEdit) return; + + this.editingComment = comment; + this.editingCommentText = comment.comment; + } + + cancelEdit(): void { + this.editingComment = undefined; + this.editingCommentText = ''; + } + + updateComment(): void { + const text = this.editingCommentText.trim(); + if (!this.editingComment || !text) return; + + this.engagementCommentService.updateComment(this.editingComment, text).subscribe({ + next: () => this.cancelEdit(), + error: (error) => this.alerts.error(error?.error ?? 'Unable to update this comment.'), + }); + } + + deleteComment(comment: EngagementComment): void { + if (!comment.currentUserCanDelete) return; + + this.confirmationModal.show( + 'Delete comment', + 'Are you sure you want to delete this engagement comment?', + () => { + this.engagementCommentService.deleteComment(comment).subscribe({ + next: () => { + if (this.replyingToComment?.id === comment.id) this.cancelReply(); + }, + error: (error) => this.alerts.error(error?.error ?? 'Unable to delete this comment.'), + }); + }, + ); + } + + scrollToComment(comment?: EngagementComment): void { + if (!comment) return; + + const element = document.getElementById(`engagement-comment-${comment.id}`); + element?.scrollIntoView({behavior: 'smooth', block: 'center'}); + } + + private loadAttachment(): void { + if (!this.engagement.hasAttachment) return; + + this.evidenceLoading = true; + this.fileDownloader.downloadBlob( + this.engagement.attachmentUrl, + (blobUrl) => { + this.evidenceBlobUrl = blobUrl; + this.evidenceLoading = false; + this.scrollToBottom(); + }, + () => { + this.evidenceLoadFailed = true; + this.evidenceLoading = false; + }, + ); + } + + scrollToBottom(): void { + requestAnimationFrame(() => { + requestAnimationFrame(() => { + const container = this.commentsEnd?.nativeElement.closest( + '.mat-mdc-dialog-content', + ) as HTMLElement | null; + container?.scrollTo({top: container.scrollHeight}); + }); + }); + } +} diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.html new file mode 100644 index 0000000000..aa79b48871 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.html @@ -0,0 +1,100 @@ + + +
      +
      + Engagement Passport + + A semester view of your engagement with the unit and teaching team. + +
      + + @if (currentUserCanAddEngagement) { + + } +
      +
      + + +
      + @for (item of legend; track item.type) { +
      + + + + {{ item.label }} +
      + } +
      + + @if (loading) { +
      + +
      + } @else { +
      +
      + @for (week of weeks; track week.week) { +
      +
      + @for (column of stampColumns(week.stamps); track $index) { +
      + @for (stamp of column; track $index) { + + } +
      + } +
      + +
      + Week + {{ week.week }} +
      +
      + } +
      +
      + } + + @if (loadFailed) { +

      Unable to load engagement stamps.

      + } + +

      + Each stamp records a moment of engagement. Hover over or focus a stamp for more detail. +

      +
      +
      diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.scss b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.ts new file mode 100644 index 0000000000..8ef0cc2706 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.ts @@ -0,0 +1,195 @@ +import {Component, Input, OnChanges} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import { + Engagement, + EngagementService, + Project, + UserService, +} from 'src/app/api/models/doubtfire-model'; +import {AddEngagementDialogComponent} from './add-engagement-dialog/add-engagement-dialog.component'; +import {EngagementDetailDialogComponent} from './engagement-detail-dialog/engagement-detail-dialog.component'; + +interface EngagementPresentation { + label: string; + icon: string; + classes: string; +} + +interface EngagementStamp { + engagement: Engagement; + type: string; + label: string; + icon: string; + classes: string; +} + +interface EngagementWeek { + week: number; + stamps: EngagementStamp[]; +} + +interface EngagementLegendItem extends EngagementPresentation { + type: string; +} + +@Component({ + selector: 'f-engagement-passport-card', + templateUrl: './engagement-passport-card.component.html', + styleUrl: './engagement-passport-card.component.scss', + standalone: false, +}) +export class EngagementPassportCardComponent implements OnChanges { + @Input() project: Project; + + loading = false; + loadFailed = false; + weeks: EngagementWeek[] = []; + + private readonly fallbackPresentation: EngagementPresentation = { + label: 'Other engagement', + icon: 'star', + classes: 'border-gray-300 bg-gray-50 text-gray-700', + }; + + private readonly presentations: Record = { + attendance: { + label: 'Class attendance', + icon: 'groups', + classes: 'border-green-300 bg-green-50 text-green-700', + }, + discussion: { + label: 'Discussion', + icon: 'record_voice_over', + classes: 'border-cyan-300 bg-cyan-50 text-cyan-700', + }, + forum: { + label: 'Forum post', + icon: 'forum', + classes: 'border-blue-300 bg-blue-50 text-blue-700', + }, + email: { + label: 'Tutor email', + icon: 'mail', + classes: 'border-violet-300 bg-violet-50 text-violet-700', + }, + attention: { + label: 'Needs attention', + icon: 'feedback', + classes: 'border-yellow-300 bg-yellow-50 text-yellow-700', + }, + }; + + readonly legend: EngagementLegendItem[] = Object.entries(this.presentations).map( + ([type, presentation]) => ({type, ...presentation}), + ); + + constructor( + private engagementService: EngagementService, + private dialog: MatDialog, + private userService: UserService, + ) {} + + get currentWeek(): number | null { + return this.project?.unit?.currentUnitWeek ?? null; + } + + get currentUserCanAddEngagement(): boolean { + const currentUserId = this.userService.currentUser?.id; + return ( + currentUserId !== undefined && + this.project?.unit?.staff.some((unitRole) => unitRole.user.id === currentUserId) + ); + } + + ngOnChanges(): void { + if (!this.project?.id) return; + + const cachedEngagements = this.project.engagementCache.currentValues; + this.buildWeeks(cachedEngagements); + this.loading = cachedEngagements.length === 0; + this.loadFailed = false; + + this.engagementService.loadEngagements(this.project, true).subscribe({ + next: (engagements) => { + this.buildWeeks(engagements); + this.loading = false; + }, + error: () => { + this.loadFailed = true; + this.loading = false; + }, + }); + } + + stampColumns(stamps: EngagementStamp[]): EngagementStamp[][] { + const columns: EngagementStamp[][] = []; + + for (let index = 0; index < stamps.length; index += 5) { + columns.push(stamps.slice(index, index + 5)); + } + + return columns; + } + + weekWidth(stamps: EngagementStamp[]): number { + const columnCount = Math.max(1, Math.ceil(stamps.length / 5)); + const stampWidth = 35; + const columnGap = 5; + const horizontalPadding = 16; + + return Math.max( + 58, + columnCount * stampWidth + (columnCount - 1) * columnGap + horizontalPadding, + ); + } + + openAddEngagementDialog(): void { + const dialogRef = this.dialog.open(AddEngagementDialogComponent, { + data: {project: this.project}, + width: 'calc(100vw - 32px)', + maxWidth: '640px', + autoFocus: false, + }); + + dialogRef.afterClosed().subscribe((engagement?: Engagement) => { + if (engagement) this.buildWeeks(this.project.engagementCache.currentValues); + }); + } + + openEngagement(engagement: Engagement): void { + this.dialog.open(EngagementDetailDialogComponent, { + data: {engagement}, + width: 'calc(100vw - 32px)', + maxWidth: '900px', + autoFocus: false, + }); + } + + private buildWeeks(engagements: readonly Engagement[]): void { + const totalWeeks = Math.max(1, this.project.unit.totalWeeks); + this.weeks = Array.from({length: totalWeeks}, (_, index) => ({ + week: index + 1, + stamps: [], + })); + + for (const engagement of engagements) { + const weekNumber = this.project.unit.weekNumber(engagement.occurredAt); + if (weekNumber === null || weekNumber < 1 || weekNumber > totalWeeks) continue; + + const type = this.normalizeEngagementType(engagement.engagementType); + const presentation = this.presentations[type] ?? this.fallbackPresentation; + this.weeks[weekNumber - 1].stamps.push({ + engagement, + type, + label: engagement.note, + icon: presentation.icon, + classes: presentation.classes, + }); + } + } + + private normalizeEngagementType(engagementType: string): string { + const type = engagementType?.trim().toLowerCase(); + return type === 'discuss' ? 'discussion' : type; + } +} diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html index 68901ff1fb..726788dc39 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html @@ -55,6 +55,11 @@

      + +
      + +
      +
      diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html index 52f7807b52..d41f5095af 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html @@ -50,7 +50,15 @@
      @if (project && project?.student) { -
      +
      {{ project?.student?.firstName }} {{ project?.student?.lastName }} diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts index 99ca6117dd..bc6819ee40 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts @@ -9,6 +9,7 @@ import { ViewChild, ViewEncapsulation, } from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; import {MatSelectionList} from '@angular/material/list'; import {MatTabChangeEvent} from '@angular/material/tabs'; import {ActivatedRoute, Router} from '@angular/router'; @@ -30,6 +31,7 @@ import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal import {DiscussedInClassReasonModalService} from 'src/app/common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {GradeService} from 'src/app/common/services/grade.service'; +import {AddEngagementDialogComponent} from '../dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component'; enum TutorDiscussionTabView { SHOW_COMMENTS, @@ -90,6 +92,7 @@ export class TutorDiscussionComponent implements AfterViewInit, OnDestroy { private discussedInClassReasonModal: DiscussedInClassReasonModalService, private taskCommentService: TaskCommentService, private taskService: TaskService, + private dialog: MatDialog, ) {} public ngOnDestroy(): void { @@ -133,17 +136,17 @@ export class TutorDiscussionComponent implements AfterViewInit, OnDestroy { } public ngAfterViewInit(): void { - this.unitId = - this.unitId ?? - Number( - this.activatedRoute.parent?.snapshot.paramMap.get('unitId') ?? - this.activatedRoute.snapshot.queryParamMap.get('unitId'), - ); - this.username = this.username ?? this.activatedRoute.snapshot.queryParamMap.get('username'); - this.attendance = - this.attendance ?? - this.activatedRoute.snapshot.data.attendance ?? - this.activatedRoute.snapshot.queryParamMap.get('attendance') === 'true'; + // this.unitId = + // this.unitId ?? + // Number( + // this.activatedRoute.parent?.snapshot.paramMap.get('unitId') ?? + // this.activatedRoute.snapshot.queryParamMap.get('unitId'), + // ); + // this.username = this.username ?? this.activatedRoute.snapshot.queryParamMap.get('username'); + // this.attendance = + // this.attendance ?? + // this.activatedRoute.snapshot.data.attendance ?? + // this.activatedRoute.snapshot.queryParamMap.get('attendance') === 'true'; this.authService.afterAuthCall((result) => { if (!result) { @@ -153,6 +156,10 @@ export class TutorDiscussionComponent implements AfterViewInit, OnDestroy { // Avoid prompting students for camera permissions before redirecting to unauthorised state return; } + this._unitId = 1; + this.unitId = 1; + this._username = 'student_9'; + this.username = 'student_9'; if (this.unitId) { this._unitId = Number(this.unitId); if (!this.attendance) { @@ -163,6 +170,17 @@ export class TutorDiscussionComponent implements AfterViewInit, OnDestroy { } else { setTimeout(() => this.scanQrCode()); } + + setTimeout(() => { + this.changeProject(); + }, 2000); + + // if (this.username) { + // this._username = this.username; + // this.getStudentTasks(); + // } else { + // this.scanQrCode(); + // } } else { this.getUnit().then((u) => { this.unit = u; @@ -216,7 +234,8 @@ export class TutorDiscussionComponent implements AfterViewInit, OnDestroy { } private changeProject() { - this.html5QrcodeScanner?.pause(true); + // this.html5QrcodeScanner?.pause(true); + // this.html5QrcodeScanner.pause(true); this.loadingStudentData = true; setTimeout(() => { try { @@ -371,6 +390,17 @@ export class TutorDiscussionComponent implements AfterViewInit, OnDestroy { } } + public openAddEngagementDialog(): void { + if (!this.project) return; + + this.dialog.open(AddEngagementDialogComponent, { + data: {project: this.project}, + width: 'calc(100vw - 32px)', + maxWidth: '640px', + autoFocus: false, + }); + } + public loadTaskComments(event: MouseEvent, task: Task) { event.stopPropagation(); this.selectedTask = task; From e73d68274ccde94cfc23bb81a2216f8ff83fbf75 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:30:26 +1000 Subject: [PATCH 1136/1531] chore: inform staff that students can access engagements --- .../add-engagement-dialog.component.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.html index 234ea67dff..15d8a2d71d 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.html @@ -1,6 +1,10 @@

      Add Engagement Stamp

      +

      + Students can see engagement stamps, including any notes and evidence you add. They can also + leave comments under each engagement. +

      Engagement type From 1ba5d1e42d302218520f8be4c0875673ad5d7a3f Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:38:20 +1000 Subject: [PATCH 1137/1531] fix: ensure dashboard dropdown switches from task details view --- .../directives/unit-task-list/unit-task-list.component.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index 044f6a0b6b..19b0e9c736 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -1,4 +1,3 @@ -import {Location} from '@angular/common'; import {Component, HostBinding, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {BehaviorSubject} from 'rxjs'; @@ -37,7 +36,6 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { protected gradeNames: string[] = Grade.GRADES; constructor( - private location: Location, private angularRouter: Router, private route: ActivatedRoute, ) {} @@ -152,7 +150,7 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { return; } - this.location.replaceState(this.angularRouter.serializeUrl(urlTree)); + this.angularRouter.navigateByUrl(urlTree, {replaceUrl: true}); } private buildSelectionUrlTree(taskDef: TaskDefinition | null) { From 2ea216b1b090575697de7aa27be5bfca7220615d Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 18 Jun 2026 12:19:40 +1000 Subject: [PATCH 1138/1531] chore(release): 11.0.0-25 --- CHANGELOG.md | 15 +++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68b40a39eb..de1a8686cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [11.0.0-25](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-24...v11.0.0-25) (2026-06-18) + + +### Features + +* add day of week to gantt chart ([1fb4637](https://github.com/b0ink/doubtfire-deploy/commit/1fb4637cd2386f1aeff227043e0002bf9b77837b)) +* engagement passport ([#1257](https://github.com/b0ink/doubtfire-deploy/issues/1257)) ([7a754dc](https://github.com/b0ink/doubtfire-deploy/commit/7a754dcc82ca228f5688abab4480774df75a007e)) +* show students name if viewing other project ([38c0e85](https://github.com/b0ink/doubtfire-deploy/commit/38c0e85ebe698c71ea087f3aeecc6d7ca24c86d7)) + + +### Bug Fixes + +* ensure dashboard dropdown switches from task details view ([1ba5d1e](https://github.com/b0ink/doubtfire-deploy/commit/1ba5d1e42d302218520f8be4c0875673ad5d7a3f)) +* web calendar ([#1282](https://github.com/b0ink/doubtfire-deploy/issues/1282)) ([83b6d5e](https://github.com/b0ink/doubtfire-deploy/commit/83b6d5ea381604ae88585195314eafd239880632)) + ## [11.0.0-24](https://github.com/b0ink/doubtfire-deploy/compare/v11.0.0-23...v11.0.0-24) (2026-06-17) diff --git a/package-lock.json b/package-lock.json index 9a65211e7c..547ed63e77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doubtfire", - "version": "11.0.0-24", + "version": "11.0.0-25", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "doubtfire", - "version": "11.0.0-24", + "version": "11.0.0-25", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^21.2.17", diff --git a/package.json b/package.json index 437fef8080..35e3ae4c28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doubtfire", - "version": "11.0.0-24", + "version": "11.0.0-25", "homepage": "http://github.com/doubtfire-lms/", "description": "Learning and feedback tool.", "license": "AGPL-3.0", From d48af3740f1acbf2c2120e83edb565347474d705 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jun 2026 02:22:07 +0000 Subject: [PATCH 1139/1531] chore(deps-dev): bump ip from 1.1.9 to 2.0.1 Bumps [ip](https://github.com/indutny/node-ip) from 1.1.9 to 2.0.1. - [Commits](https://github.com/indutny/node-ip/compare/v1.1.9...v2.0.1) --- updated-dependencies: - dependency-name: ip dependency-version: 2.0.1 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 547ed63e77..104b5c1641 100644 --- a/package-lock.json +++ b/package-lock.json @@ -99,7 +99,7 @@ "eslint-plugin-prettier": "^5.5.6", "eslint-plugin-tailwindcss": "^3.18.3", "husky": "~8", - "ip": "^1.1.2", + "ip": "^2.0.1", "jasmine-core": "~4.1.0", "jasmine-spec-reporter": "~5.0.0", "karma": "^6.3.4", @@ -10044,9 +10044,9 @@ } }, "node_modules/ip": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", - "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index 35e3ae4c28..6762d1d408 100644 --- a/package.json +++ b/package.json @@ -115,7 +115,7 @@ "eslint-plugin-prettier": "^5.5.6", "eslint-plugin-tailwindcss": "^3.18.3", "husky": "~8", - "ip": "^1.1.2", + "ip": "^2.0.1", "jasmine-core": "~4.1.0", "jasmine-spec-reporter": "~5.0.0", "karma": "^6.3.4", From d356de31b76f9de7692bc9a57909846cf0720d3d Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 18 Jun 2026 12:37:59 +1000 Subject: [PATCH 1140/1531] chore: bump ngx-lottie from 11.0.2 to 21.2.0 --- package-lock.json | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 104b5c1641..d666c71457 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55,7 +55,7 @@ "ng-flex-layout": "^17.3.7-beta.1", "ng2-pdf-viewer": "10.2.2", "ngx-entity-service": "^0.0.43", - "ngx-lottie": "^11.0.2", + "ngx-lottie": "^21.2.0", "ngx-monaco-editor-v2": "^21", "ngx-skeleton-loader": "^12.0.0", "nvd3": "1.8.6", @@ -12237,16 +12237,16 @@ } }, "node_modules/ngx-lottie": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/ngx-lottie/-/ngx-lottie-11.0.2.tgz", - "integrity": "sha512-sQhCTxfrzWpjN2HVFCSyAQYQg8ZjZVtO1xIhOkrJNHY3/TR/zZkVrhakWcaM5bVxyA7gfUnK3ox+iK59Yd8Bsw==", + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/ngx-lottie/-/ngx-lottie-21.2.0.tgz", + "integrity": "sha512-x0EaM0CXT98/gDVw7cxbvo46mOTg6QeZxUqzTelpszCy6J66zFryy/++x8cg4q8QKTfpTKvlpFDV4rZACpTQOQ==", "license": "MIT", "dependencies": { "@scarf/scarf": "^1.1.1", "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/core": ">=17", + "@angular/core": ">=21", "lottie-web": ">=5.9.2" } }, diff --git a/package.json b/package.json index 6762d1d408..12cfd69870 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "ng-flex-layout": "^17.3.7-beta.1", "ng2-pdf-viewer": "10.2.2", "ngx-entity-service": "^0.0.43", - "ngx-lottie": "^11.0.2", + "ngx-lottie": "^21.2.0", "ngx-monaco-editor-v2": "^21", "ngx-skeleton-loader": "^12.0.0", "nvd3": "1.8.6", From edab0928c3419cb7babb3363cc1c2046decb3c0b Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Thu, 18 Jun 2026 13:26:38 +1000 Subject: [PATCH 1141/1531] chore: remove unused/deprecated bootstrap styles (#1266) --- src/styles/common/center-full-screen.scss | 9 - src/styles/common/doubtfire-cards.scss | 7 - src/styles/common/extensions/col-xl.scss | 110 --------- .../common/extensions/fa-document-o.scss | 4 - .../extensions/panel-footer-toolbar.scss | 35 --- .../extensions/panel-heading-toolbar.scss | 58 ----- src/styles/common/extensions/pointer.scss | 7 - src/styles/common/extensions/strong.scss | 6 - src/styles/common/five-cols.scss | 25 -- src/styles/common/grade-colors.scss | 15 -- .../common/overrides/badge-overrides.scss | 8 - .../common/overrides/body-overrides.scss | 36 --- .../common/overrides/header-overrides.scss | 12 - .../common/overrides/label-overrides.scss | 11 - .../common/overrides/nav-tabs-overrides.scss | 16 -- .../overrides/nvd3-graph-overrides.scss | 6 - .../common/overrides/panel-overrides.scss | 127 ----------- .../common/overrides/rating-overrides.scss | 17 -- .../common/overrides/table-overrides.scss | 15 -- src/styles/common/text.scss | 4 - src/styles/config/font-awesome.scss | 7 - src/styles/mixins/animations/fade-in.scss | 14 -- src/styles/mixins/animations/grow.scss | 28 --- src/styles/mixins/animations/slide-down.scss | 14 -- src/styles/mixins/animations/wobble.scss | 47 ---- src/styles/mixins/callout.scss | 28 --- src/styles/mixins/dropdown-selector.scss | 50 ---- src/styles/mixins/flex-center.scss | 11 - src/styles/mixins/flex-panel.scss | 8 - src/styles/mixins/large-notice-block.scss | 22 -- src/styles/mixins/logo-font-rendering.scss | 9 - src/styles/mixins/no-select.scss | 4 - src/styles/mixins/remove-list-padding.scss | 4 - src/styles/modules/callout.scss | 25 -- src/styles/modules/cards.scss | 86 ------- src/styles/modules/doubtfire-logo.scss | 34 --- src/styles/modules/drilldown-visualiser.scss | 22 -- src/styles/modules/panel-fullscreen.scss | 63 ------ src/styles/modules/project-task-bar.scss | 104 --------- src/styles/modules/rationale-wrapper.scss | 30 --- src/styles/modules/tabset-icon.scss | 19 -- src/styles/modules/task-status.scss | 214 ------------------ src/styles/vendor-config/bootstrap.scss | 13 -- src/styles/vendor-config/font-awesome.scss | 7 - 44 files changed, 1391 deletions(-) delete mode 100644 src/styles/common/center-full-screen.scss delete mode 100644 src/styles/common/doubtfire-cards.scss delete mode 100644 src/styles/common/extensions/col-xl.scss delete mode 100644 src/styles/common/extensions/fa-document-o.scss delete mode 100644 src/styles/common/extensions/panel-footer-toolbar.scss delete mode 100644 src/styles/common/extensions/panel-heading-toolbar.scss delete mode 100644 src/styles/common/extensions/pointer.scss delete mode 100644 src/styles/common/extensions/strong.scss delete mode 100644 src/styles/common/five-cols.scss delete mode 100644 src/styles/common/grade-colors.scss delete mode 100644 src/styles/common/overrides/badge-overrides.scss delete mode 100644 src/styles/common/overrides/body-overrides.scss delete mode 100644 src/styles/common/overrides/header-overrides.scss delete mode 100644 src/styles/common/overrides/label-overrides.scss delete mode 100644 src/styles/common/overrides/nav-tabs-overrides.scss delete mode 100644 src/styles/common/overrides/nvd3-graph-overrides.scss delete mode 100644 src/styles/common/overrides/panel-overrides.scss delete mode 100644 src/styles/common/overrides/rating-overrides.scss delete mode 100644 src/styles/common/overrides/table-overrides.scss delete mode 100644 src/styles/common/text.scss delete mode 100644 src/styles/config/font-awesome.scss delete mode 100644 src/styles/mixins/animations/fade-in.scss delete mode 100644 src/styles/mixins/animations/grow.scss delete mode 100644 src/styles/mixins/animations/slide-down.scss delete mode 100644 src/styles/mixins/animations/wobble.scss delete mode 100644 src/styles/mixins/callout.scss delete mode 100644 src/styles/mixins/dropdown-selector.scss delete mode 100644 src/styles/mixins/flex-center.scss delete mode 100644 src/styles/mixins/flex-panel.scss delete mode 100644 src/styles/mixins/large-notice-block.scss delete mode 100644 src/styles/mixins/logo-font-rendering.scss delete mode 100644 src/styles/mixins/no-select.scss delete mode 100644 src/styles/mixins/remove-list-padding.scss delete mode 100644 src/styles/modules/callout.scss delete mode 100644 src/styles/modules/cards.scss delete mode 100644 src/styles/modules/doubtfire-logo.scss delete mode 100644 src/styles/modules/drilldown-visualiser.scss delete mode 100644 src/styles/modules/panel-fullscreen.scss delete mode 100644 src/styles/modules/project-task-bar.scss delete mode 100644 src/styles/modules/rationale-wrapper.scss delete mode 100644 src/styles/modules/tabset-icon.scss delete mode 100644 src/styles/modules/task-status.scss delete mode 100644 src/styles/vendor-config/bootstrap.scss delete mode 100644 src/styles/vendor-config/font-awesome.scss diff --git a/src/styles/common/center-full-screen.scss b/src/styles/common/center-full-screen.scss deleted file mode 100644 index 0ddbddf36d..0000000000 --- a/src/styles/common/center-full-screen.scss +++ /dev/null @@ -1,9 +0,0 @@ -// -// Ensures an element takes up the full screen and centered -// -.center-full-screen { - @include flex-center; - @media (min-width: $screen-sm) { - height: 100vh; - } -} diff --git a/src/styles/common/doubtfire-cards.scss b/src/styles/common/doubtfire-cards.scss deleted file mode 100644 index a2edcc816f..0000000000 --- a/src/styles/common/doubtfire-cards.scss +++ /dev/null @@ -1,7 +0,0 @@ -@mixin doubtfire-card { - border-radius: 10px; -} - -.mat-mdc-card.danger-card { - @include doubtfire-card(); -} diff --git a/src/styles/common/extensions/col-xl.scss b/src/styles/common/extensions/col-xl.scss deleted file mode 100644 index e7cee6aff7..0000000000 --- a/src/styles/common/extensions/col-xl.scss +++ /dev/null @@ -1,110 +0,0 @@ -// From https://gist.github.com/juukie/d71133e69877b46f060e - -$screen-xl: 1560px !default; -$screen-xl-min: $screen-xl !default; -$screen-xl-desktop: $screen-xl-min !default; -$screen-lg-max: ($screen-xl-min - 1) !default; -$container-xlarge-desktop: (1530px + $grid-gutter-width) !default; -$container-xl: $container-xlarge-desktop !default; - -.container { - // @include container-fixed; No need for, already done. - @media (min-width: $screen-xl-min) { - width: $container-xl; - } -} - -// xLarge grid -// -// Columns, offsets, pushes, and pulls for the large desktop device range. - -@media (min-width: $screen-xl-min) { - @include make-grid(xl); -} - -// Generate the xlarge columns -@mixin make-xl-column($columns, $gutter: $grid-gutter-width) { - position: relative; - min-height: 1px; - padding-left: ($gutter / 2); - padding-right: ($gutter / 2); - - @media (min-width: $screen-xl-min) { - float: left; - width: percentage(($columns / $grid-columns)); - } -} -@mixin make-xl-column-offset($columns) { - @media (min-width: $screen-xl-min) { - margin-left: percentage(($columns / $grid-columns)); - } -} -@mixin make-xl-column-push($columns) { - @media (min-width: $screen-xl-min) { - left: percentage(($columns / $grid-columns)); - } -} -@mixin make-xl-column-pull($columns) { - @media (min-width: $screen-xl-min) { - right: percentage(($columns / $grid-columns)); - } -} - -@mixin make-grid-columns($i: 1, $list: '.col-xl-#{$i}') { - @for $i from (1 + 1) through $grid-columns { - $list: '#{$list}, .col-xl-#{$i}'; - } - #{$list} { - position: relative; - // Prevent columns from collapsing when empty - min-height: 1px; - // Inner gutter via padding - padding-left: ($grid-gutter-width / 2); - padding-right: ($grid-gutter-width / 2); - } -} - -@include make-grid-columns; - -@include responsive-invisibility('.visible-xl'); - -.visible-xl-block, -.visible-xl-inline, -.visible-xl-inline-block { - display: none !important; -} - -@media (min-width: $screen-xl-min) { - @include responsive-invisibility('.visible-lg'); - @include responsive-visibility('.visible-xl'); -} -.visible-xl-block { - @media (min-width: $screen-xl-min) { - display: block !important; - } -} -.visible-xl-inline { - @media (min-width: $screen-xl-min) { - display: inline !important; - } -} -.visible-xl-inline-block { - @media (min-width: $screen-xl-min) { - display: inline-block !important; - } -} - -@media (min-width: $screen-lg-min) and (max-width: $screen-lg-max) { - @include responsive-invisibility('.hidden-lg'); -} - -@media (min-width: $screen-xl-min) { - @include responsive-invisibility('.hidden-xl'); - @include responsive-visibility('.hidden-lg'); - - .visible-lg-block, - .visible-lg-inline, - .visible-lg-inline-block { - display: none !important; - } -} diff --git a/src/styles/common/extensions/fa-document-o.scss b/src/styles/common/extensions/fa-document-o.scss deleted file mode 100644 index 62c97e0d4d..0000000000 --- a/src/styles/common/extensions/fa-document-o.scss +++ /dev/null @@ -1,4 +0,0 @@ -// Alias for .fa-file-pdf-o -.#{$fa-css-prefix}-file-document-o:before { - content: $fa-var-file-pdf-o; -} diff --git a/src/styles/common/extensions/panel-footer-toolbar.scss b/src/styles/common/extensions/panel-footer-toolbar.scss deleted file mode 100644 index dd6ffaa97d..0000000000 --- a/src/styles/common/extensions/panel-footer-toolbar.scss +++ /dev/null @@ -1,35 +0,0 @@ -.panel .panel-footer { - // With buttons in a small screen - @media (max-width: $screen-sm) { - // Increase tapping area - & > * { - width: 100%; - } - .btn-group, - .btn, - input { - height: 4em; - width: 100%; - } - .btn { - margin-top: 1em; - } - ul.pagination { - margin-top: 1em; - width: 100%; - flex: 1; - display: flex; - overflow: auto; - li { - flex: 1; - } - li > a { - width: 100%; - height: 4em; - display: flex; - align-items: center; - justify-content: center; - } - } - } -} diff --git a/src/styles/common/extensions/panel-heading-toolbar.scss b/src/styles/common/extensions/panel-heading-toolbar.scss deleted file mode 100644 index cc8d10e8d2..0000000000 --- a/src/styles/common/extensions/panel-heading-toolbar.scss +++ /dev/null @@ -1,58 +0,0 @@ -// For all panel headings -.panel .panel-heading { - // With buttons in a small screen - @media (max-width: $screen-sm) { - // Increase tapping area - & > * { - width: 100%; - } - .btn-group, - .btn, - input { - height: 4em; - width: 100%; - } - } - .toolbar { - @media (max-width: $screen-sm) { - margin: 1.5em auto; - width: 100%; - text-align: left; - } - .btn-group, - .buttons > .btn { - @media (min-width: $screen-sm-max) { - margin-right: 1ex; - } - } - .buttons { - float: right; - @media (max-width: $screen-sm) { - width: 100%; - .btn-group { - margin-top: 1em; - display: flex; - float: left; - float: right; - clear: both; - .btn { - flex: 1; - } - .btn { - @include flex-center; - } - } - } - } - form[role='search'] { - float: right; - margin-right: 1.5ex; - @media (max-width: $screen-sm) { - margin-right: 0; - width: 100%; - margin-top: 1em; - padding: 0 !important; - } - } - } -} diff --git a/src/styles/common/extensions/pointer.scss b/src/styles/common/extensions/pointer.scss deleted file mode 100644 index 0840082215..0000000000 --- a/src/styles/common/extensions/pointer.scss +++ /dev/null @@ -1,7 +0,0 @@ -// -// All anchors are pointers, as well as anything with the .pointer class -// -a, -.pointer { - cursor: pointer; -} diff --git a/src/styles/common/extensions/strong.scss b/src/styles/common/extensions/strong.scss deleted file mode 100644 index bb400cbf84..0000000000 --- a/src/styles/common/extensions/strong.scss +++ /dev/null @@ -1,6 +0,0 @@ -// -// Strong font weight using a .strong class -// -.strong { - font-weight: bold; -} diff --git a/src/styles/common/five-cols.scss b/src/styles/common/five-cols.scss deleted file mode 100644 index de94a27e74..0000000000 --- a/src/styles/common/five-cols.scss +++ /dev/null @@ -1,25 +0,0 @@ -.col-xs-15 { - width: 20%; - float: left; -} - -@media (min-width: 768px) { - .col-sm-15 { - width: 20%; - float: left; - } -} - -@media (min-width: 992px) { - .col-md-15 { - width: 20%; - float: left; - } -} - -@media (min-width: 1200px) { - .col-lg-15 { - width: 20%; - float: left; - } -} diff --git a/src/styles/common/grade-colors.scss b/src/styles/common/grade-colors.scss deleted file mode 100644 index 45e498c0eb..0000000000 --- a/src/styles/common/grade-colors.scss +++ /dev/null @@ -1,15 +0,0 @@ -@use 'sass:color'; - -// -// Colors for associated grades -// -// ******************************************************** -// IMPORTANT: Grade colours must also be matched -// in the grade-service.coffee file -// ******************************************************** -// - -$grade-color-p: color.adjust(#ff0000, $lightness: -10%); -$grade-color-c: color.adjust(#ff8000, $lightness: -5%); -$grade-color-d: color.adjust(#0080ff, $lightness: -10%); -$grade-color-hd: color.adjust(#80ff00, $lightness: -15%); diff --git a/src/styles/common/overrides/badge-overrides.scss b/src/styles/common/overrides/badge-overrides.scss deleted file mode 100644 index 32057cdf12..0000000000 --- a/src/styles/common/overrides/badge-overrides.scss +++ /dev/null @@ -1,8 +0,0 @@ -// -// Overrides for all badges -// -.badge { - border-radius: 1em; - text-align: center; - display: inline-block; -} diff --git a/src/styles/common/overrides/body-overrides.scss b/src/styles/common/overrides/body-overrides.scss deleted file mode 100644 index c2b92ccf27..0000000000 --- a/src/styles/common/overrides/body-overrides.scss +++ /dev/null @@ -1,36 +0,0 @@ -// -// Overrides for the body (i.e., global overrdies) -// -$main-view-top-padding: 30px; -$main-view-bottom-padding: $main-view-top-padding; - -$main-view-max-height: calc((var(--vh, 1vh) * (100)) - 85px); - -/* override browser default */ -html, -body { - margin: 0; - padding: 0; - // background-color: #f5f5f5; -} - -/* use viewport-relative units to cover page fully */ -body { - height: 100vh; - height: $main-view-max-height; - width: 100vw; - // font-family: 'Roboto', Helvetica; - // font-size: 1.2em; - // line-height: 2; - // font-weight: normal; -} - -/* include border and padding in element width and height */ -* { - box-sizing: border-box; -} - -// body>[ui-view="header"]:not(:empty)+[ui-view="main"] { -// padding-top: $main-view-top-padding; -// padding-bottom: $main-view-bottom-padding; -// } diff --git a/src/styles/common/overrides/header-overrides.scss b/src/styles/common/overrides/header-overrides.scss deleted file mode 100644 index cb4237edfc..0000000000 --- a/src/styles/common/overrides/header-overrides.scss +++ /dev/null @@ -1,12 +0,0 @@ -// -// Sets all font weights to the headers as 400 -// - -h1, -h2, -h3, -h4, -h5, -h6 { - font-weight: 400; -} diff --git a/src/styles/common/overrides/label-overrides.scss b/src/styles/common/overrides/label-overrides.scss deleted file mode 100644 index 3280c214cb..0000000000 --- a/src/styles/common/overrides/label-overrides.scss +++ /dev/null @@ -1,11 +0,0 @@ -// -// Overrides for the font size to make labels larger -// -.label { - font-size: 100% !important; -} - -.label.label-unit { - @include label-variant($label-info-bg); - margin-right: 1ex; -} diff --git a/src/styles/common/overrides/nav-tabs-overrides.scss b/src/styles/common/overrides/nav-tabs-overrides.scss deleted file mode 100644 index 8a20557cf2..0000000000 --- a/src/styles/common/overrides/nav-tabs-overrides.scss +++ /dev/null @@ -1,16 +0,0 @@ -// -// Override nav tabs's content to be separated -// -.nav.nav-tabs + .tab-content { - margin-top: 1.5em; -} - -// Support badges in nav pills -.nav.nav-pills tab-heading { - display: flex; - justify-content: center; - align-items: center; - .comment-count { - margin-left: 1ex; - } -} diff --git a/src/styles/common/overrides/nvd3-graph-overrides.scss b/src/styles/common/overrides/nvd3-graph-overrides.scss deleted file mode 100644 index 108d0fe58a..0000000000 --- a/src/styles/common/overrides/nvd3-graph-overrides.scss +++ /dev/null @@ -1,6 +0,0 @@ -// -// Override to center all nvd3 SVGs -// -svg.nvd3-svg { - margin: 0 auto; -} diff --git a/src/styles/common/overrides/panel-overrides.scss b/src/styles/common/overrides/panel-overrides.scss deleted file mode 100644 index f1ed83d293..0000000000 --- a/src/styles/common/overrides/panel-overrides.scss +++ /dev/null @@ -1,127 +0,0 @@ -@use 'sass:color'; - -// -// Global overrides for panels -// -.panel-footer .pagination, -.modal-footer .pagination { - margin: 0; -} - -.panel-body + .panel-heading, -.panel-body + * > .panel-heading { - border-top: 1px solid #ddd !important; - border-radius: 0 !important; -} - -.panel-heading > .pull-left { - padding-left: 0 !important; // Override for col-sm-* -} -.panel-heading > .pull-right { - padding-right: 0 !important; // Override for col-sm-* -} - -@mixin panel-row { - display: flex; - .panel { - flex: 1; - display: flex; - flex-direction: column; - } - .panel > *:not(.panel-heading):not(.panel-footer):not(.panel-toolbar) { - flex: 1; - } - .panel-heading, - .panel-body, - .panel-footer { - width: 100%; - } - .panel + .panel { - margin-left: $panel-body-padding; - } - // Panels with file dropzones - .panel-footer .well { - background-color: #fff; - } - .panel h3.file-title { - margin-top: 0; - font-size: 1em; - } - .panel .drop.well, - .panel .file-uploader { - margin: 0; - } -} -.panel-row { - @include panel-row(); -} - -// New panel loading panel -.panel-body.panel-loading { - @extend .text-muted; - @extend .text-center; - @extend .strong; - font-size: 1.3em; - padding-top: $panel-body-padding * 4; - padding-bottom: $panel-body-padding * 4; - i { - margin-right: 0.9ex; - } -} - -.panel.panel-scrollable { - overflow: hidden; - .panel-body { - overflow: scroll; - height: 100%; - padding-bottom: $panel-body-padding * 3; - } -} - -// Search options panel -.panel-body.panel-collapseable { - background-color: color.adjust($gray-lighter, $lightness: 2%); -} - -// Two panel bodies next to eachother (include those with one nested in custom element) -.panel-body:not(.ng-hide) + * > .panel-body, -.panel-body:not(.ng-hide) + .panel-body { - padding-top: 0; -} -// Remove extra margin for callouts in padding -.panel-body > .callout:first-child { - margin-top: 0; -} -.panel-body > .callout:last-child { - margin-bottom: 0; -} - -// Full screen set of panels -.panel-full-screen { - height: $main-view-max-height; - & > *, - & > * > .panel { - height: 100%; - } -} - -.panel-marking-context { - padding: 0; - .panel { - margin: 0; - border: none; - border-radius: 0; - background-color: transparent; - } - .panel-submission-marking-context .panel-body { - padding: 60px; - } -} - -.panel.panel-pdf { - @include flex-panel; - .panel-body.has-pdf { - padding: 0; - position: relative; - } -} diff --git a/src/styles/common/overrides/rating-overrides.scss b/src/styles/common/overrides/rating-overrides.scss deleted file mode 100644 index 0c9e44aa6f..0000000000 --- a/src/styles/common/overrides/rating-overrides.scss +++ /dev/null @@ -1,17 +0,0 @@ -@use 'sass:color'; - -// The generated from ui-bootstrap becomes this -span[role='slider'] { - outline: none; -} -.rating-outline { - color: color.adjust($brand-warning, $lightness: 30%); - -webkit-text-stroke-width: 1px; - -webkit-text-stroke-color: $brand-warning; -} -.rating-disabled { - color: color.adjust($text-muted, $lightness: 30%); -} -.rating-star::before { - content: 'star'; -} diff --git a/src/styles/common/overrides/table-overrides.scss b/src/styles/common/overrides/table-overrides.scss deleted file mode 100644 index 2b03bc8575..0000000000 --- a/src/styles/common/overrides/table-overrides.scss +++ /dev/null @@ -1,15 +0,0 @@ -// -// Global overrides for tables -// -table.table-pointer { - tr { - cursor: pointer; - } -} - -table > tbody > tr { - & > td, - & > th { - vertical-align: middle !important; - } -} diff --git a/src/styles/common/text.scss b/src/styles/common/text.scss deleted file mode 100644 index 69586f5d2e..0000000000 --- a/src/styles/common/text.scss +++ /dev/null @@ -1,4 +0,0 @@ -.with-icon { - display: flex; - align-items: center; -} diff --git a/src/styles/config/font-awesome.scss b/src/styles/config/font-awesome.scss deleted file mode 100644 index 87945b4a94..0000000000 --- a/src/styles/config/font-awesome.scss +++ /dev/null @@ -1,7 +0,0 @@ -// -// This config file provides overrides for bootstrap and is injected before -// font awesome is imported -// - -// Provide the font path to the fa-fonts -$fa-font-path: './fonts/font-awesome'; diff --git a/src/styles/mixins/animations/fade-in.scss b/src/styles/mixins/animations/fade-in.scss deleted file mode 100644 index 008d7a6ead..0000000000 --- a/src/styles/mixins/animations/fade-in.scss +++ /dev/null @@ -1,14 +0,0 @@ -// -// A fade in animation -// -@keyframes animation-fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@mixin animation-fade-in($seconds) { - animation: animation-fade-in $seconds; -} diff --git a/src/styles/mixins/animations/grow.scss b/src/styles/mixins/animations/grow.scss deleted file mode 100644 index e8cef776ce..0000000000 --- a/src/styles/mixins/animations/grow.scss +++ /dev/null @@ -1,28 +0,0 @@ -// -// Grow animation from 0 scale to 1 scale -// -@keyframes animation-grow { - 0% { - opacity: 0; - transform: scale(0.3); - } - - 50% { - opacity: 1; - transform: scale(1.05); - } - - 70% { - transform: scale(0.9); - } - - 100% { - transform: scale(1); - } -} - -@mixin animation-grow($time: 0.5s) { - animation-name: animation-grow; - animation-duration: $time; - animation-fill-mode: both; -} diff --git a/src/styles/mixins/animations/slide-down.scss b/src/styles/mixins/animations/slide-down.scss deleted file mode 100644 index 1bb14c5d1c..0000000000 --- a/src/styles/mixins/animations/slide-down.scss +++ /dev/null @@ -1,14 +0,0 @@ -// -// Slide animation from -2em to initial top -// -@keyframes animation-slide-down { - from { - margin-top: -2em; - } - to { - margin-top: inherit; - } -} -@mixin animation-slide-down($seconds) { - animation: animation-slide-down $seconds; -} diff --git a/src/styles/mixins/animations/wobble.scss b/src/styles/mixins/animations/wobble.scss deleted file mode 100644 index e06fbdfecb..0000000000 --- a/src/styles/mixins/animations/wobble.scss +++ /dev/null @@ -1,47 +0,0 @@ -// -// Animation to wobble an element side to side -// -@keyframes animation-wobble { - 0%, - 100% { - transform: translateX(+5px); - } - 25%, - 75% { - transform: translateX(0); - } - 50% { - transform: translateX(-5px); - } -} - -@mixin animation-wobble { - animation-duration: 1s; - animation-fill-mode: both; - animation-timing-function: ease-in-out; - animation-iteration-count: infinite; - animation-name: animation-wobble; -} - -// -// Animation to wobble an element side but only once -// -@keyframes animation-wobble-once { - 0%, - 100% { - transform: translateX(0); - } - 25% { - transform: translateX(+5px); - } - 75% { - transform: translateX(-5px); - } -} - -@mixin animation-wobble-once { - animation-duration: 0.15s; - animation-fill-mode: both; - animation-iteration-count: 2; - animation-name: animation-wobble-once; -} diff --git a/src/styles/mixins/callout.scss b/src/styles/mixins/callout.scss deleted file mode 100644 index fa9d52c3b2..0000000000 --- a/src/styles/mixins/callout.scss +++ /dev/null @@ -1,28 +0,0 @@ -@use 'sass:color'; - -// -// A callout -// -@mixin callout($color, $bgcolor: color.adjust($color, $lightness: 35%)) { - display: block; - margin: 20px 0; - padding: 15px 30px 15px 15px; - border-left: 5px solid $color; - background-color: $bgcolor; - h1, - h2, - h3, - h4, - h5, - h6 { - margin-top: 0; - color: $color; - } - p:last-child { - margin-bottom: 0; - } - code, - .highlight { - background-color: #fff; - } -} diff --git a/src/styles/mixins/dropdown-selector.scss b/src/styles/mixins/dropdown-selector.scss deleted file mode 100644 index c5ca2742a2..0000000000 --- a/src/styles/mixins/dropdown-selector.scss +++ /dev/null @@ -1,50 +0,0 @@ -@mixin dropdown-selector { - height: 100%; - padding-left: 0px; - padding-right: 0px; - // first button - & > button { - height: 100%; - width: 100%; - label, - i { - text-align: center; - } - label { - font-size: 1.5em; - margin: 0px; - } - label.label.label-info { - font-size: 1em; - margin-left: 0.5ex; - cursor: pointer; - } - // not a split button group - span.caret { - margin-left: 1ex; - } - } - // open button - &.open > button { - border-bottom-left-radius: 0px; - border-bottom-right-radius: 0px; - } - // menu underneath - .dropdown-menu { - margin-top: 0px; - border-top-left-radius: 0px; - border-top-right-radius: 0px; - @media (max-width: $screen-sm) { - position: relative; - bottom: 0; - left: 0; - right: 0; - top: 0; - width: 100%; - } - } -} - -.dropdown-selector { - @include dropdown-selector; -} diff --git a/src/styles/mixins/flex-center.scss b/src/styles/mixins/flex-center.scss deleted file mode 100644 index e741a95c92..0000000000 --- a/src/styles/mixins/flex-center.scss +++ /dev/null @@ -1,11 +0,0 @@ -// -// Uses flex to align the div contents in the center -// -@mixin flex-center { - display: flex; - flex-wrap: wrap; - align-items: center; - align-content: center; - justify-content: center; - height: 100%; -} diff --git a/src/styles/mixins/flex-panel.scss b/src/styles/mixins/flex-panel.scss deleted file mode 100644 index a74cd163fd..0000000000 --- a/src/styles/mixins/flex-panel.scss +++ /dev/null @@ -1,8 +0,0 @@ -@mixin flex-panel { - display: flex; - flex-wrap: wrap; - flex-direction: column; - .panel-body { - flex: 1; - } -} diff --git a/src/styles/mixins/large-notice-block.scss b/src/styles/mixins/large-notice-block.scss deleted file mode 100644 index 7f138f6551..0000000000 --- a/src/styles/mixins/large-notice-block.scss +++ /dev/null @@ -1,22 +0,0 @@ -// -// A large notice block is a large text with an icon -// -@mixin large-notice-block { - @include flex-center; - font-size: 2em; - text-align: center; - font-weight: 300; - & > * { - display: block; - width: 100%; - margin-top: 0.75em; - margin-bottom: 0.75em; - } - &.panel-body { - padding: 30px; - } -} - -.large-notice-block { - @include large-notice-block; -} diff --git a/src/styles/mixins/logo-font-rendering.scss b/src/styles/mixins/logo-font-rendering.scss deleted file mode 100644 index 68624bc823..0000000000 --- a/src/styles/mixins/logo-font-rendering.scss +++ /dev/null @@ -1,9 +0,0 @@ -// -// Font rendering for the DF logo -// - -@mixin logo-font-rendering { - -webkit-font-smoothing: antialiased; - letter-spacing: -1px; - font-weight: 300; -} diff --git a/src/styles/mixins/no-select.scss b/src/styles/mixins/no-select.scss deleted file mode 100644 index cb2ed50433..0000000000 --- a/src/styles/mixins/no-select.scss +++ /dev/null @@ -1,4 +0,0 @@ -@mixin no-select { - user-select: none; - cursor: default; -} diff --git a/src/styles/mixins/remove-list-padding.scss b/src/styles/mixins/remove-list-padding.scss deleted file mode 100644 index 1b5a1b0690..0000000000 --- a/src/styles/mixins/remove-list-padding.scss +++ /dev/null @@ -1,4 +0,0 @@ -@mixin remove-list-padding { - -webkit-padding-start: 0; - padding-left: 0; -} diff --git a/src/styles/modules/callout.scss b/src/styles/modules/callout.scss deleted file mode 100644 index 389ccdbb73..0000000000 --- a/src/styles/modules/callout.scss +++ /dev/null @@ -1,25 +0,0 @@ -@use 'sass:color'; -@use 'styles/mixins/callout' as *; - -// -// Callouts used for standout information -// -.callout-primary { - @include callout($brand-primary, color.adjust($brand-primary, $lightness: 45%)); -} - -.callout-danger { - @include callout($brand-danger, color.adjust($brand-danger, $lightness: 30%)); -} - -.callout-warning { - @include callout($brand-warning, color.adjust($brand-warning, $lightness: 30%)); -} - -.callout-info { - @include callout($brand-info, color.adjust($brand-info, $lightness: 30%)); -} - -.callout-success { - @include callout($brand-success, color.adjust($brand-success, $lightness: 30%)); -} diff --git a/src/styles/modules/cards.scss b/src/styles/modules/cards.scss deleted file mode 100644 index 2114a71f81..0000000000 --- a/src/styles/modules/cards.scss +++ /dev/null @@ -1,86 +0,0 @@ -@use 'sass:color'; - -.card { - $card-height-lg: 500px; - $card-height-md: $card-height-lg / 2; - $card-height-sm: $card-height-md / 2; - $card-body-padding: $panel-body-padding; - $card-footer-padding: $card-body-padding + 5px; - $card-header-padding: $card-body-padding $card-footer-padding; - - margin-bottom: $card-footer-padding; - background-color: color.adjust(#fff, $lightness: -0.75%); - transition: box-shadow 0.25s; - box-shadow: - 0 2px 2px 0 rgba(0, 0, 0, 0.14), - 0 1px 5px 0 rgba(0, 0, 0, 0.12), - 0 3px 1px -2px rgba(0, 0, 0, 0.2); - - &.card-default > .card-heading { - background-color: $panel-default-heading-bg; - } - &.card-primary > .card-heading { - background-color: $brand-primary; - } - &.card-danger > .card-heading { - background-color: $brand-danger; - } - &.card-success > .card-heading { - background-color: $brand-success; - } - &.card-warning > .card-heading { - background-color: $brand-warning; - } - &.card-info > .card-heading { - background-color: $brand-info; - } - &.card-danger, - &.card-success, - &.card-warning, - &.card-info, - &.card-primary { - .card-heading { - color: #fff; - .text-muted { - color: color.adjust(#fff, $lightness: -1%); - } - } - } - .card-heading { - padding: $card-header-padding; - border-bottom: 1px solid rgba(160, 160, 160, 0.2); - } - .card-body { - padding: $card-body-padding; - } - .card-footer { - position: relative; - background-color: inherit; - padding: $card-footer-padding; - border-top: 1px solid rgba(160, 160, 160, 0.2); - } - - &.card-lg { - min-height: $card-height-lg; - } - &.card-md { - min-height: $card-height-md; - } - &.card-sm { - min-height: $card-height-sm; - } - - & > .list-group { - margin-bottom: 0; - .list-group-item { - border-width: 1px 0; - border-radius: 0; - &:first-child { - border-top-width: 0; - } - &:last-child { - border-bottom-width: 0; - } - } - } -} diff --git a/src/styles/modules/doubtfire-logo.scss b/src/styles/modules/doubtfire-logo.scss deleted file mode 100644 index aaf9cf1fc9..0000000000 --- a/src/styles/modules/doubtfire-logo.scss +++ /dev/null @@ -1,34 +0,0 @@ -// -// Styles for the Doubtfire Logo -// - -h1.logo { - @include logo-font-rendering; - font-size: 4em; -} -i.logo { - display: inline-block; - width: 1em; - height: 1em; - background-image: url('/assets/images/logo.svg'); - background-size: 100%; - background-repeat: no-repeat; - background-position: center; -} - -.welcome-to-doubtfire { - margin-top: 6em; - margin-bottom: 3em; - h1, - p { - @include logo-font-rendering; - font-family: 'Grotesk'; - } - p.lead { - color: #000; - } - i.logo { - width: 10em; - height: 10em; - } -} diff --git a/src/styles/modules/drilldown-visualiser.scss b/src/styles/modules/drilldown-visualiser.scss deleted file mode 100644 index 5f382b2719..0000000000 --- a/src/styles/modules/drilldown-visualiser.scss +++ /dev/null @@ -1,22 +0,0 @@ -// -// A drilldown for visualisations to click into graphs and see more -// about those graphs -// -.drilldown-visualiser { - .overview-chart { - cursor: pointer; - } - .overview-charts .overview-chart { - height: 250px; - cursor: pointer; - .no-data-to-display { - height: 60%; - text-align: center; - padding-top: 30%; - border: 1px dashed #ddd; - color: #ddd; - border-radius: 1em; - margin: 10%; - } - } -} diff --git a/src/styles/modules/panel-fullscreen.scss b/src/styles/modules/panel-fullscreen.scss deleted file mode 100644 index 7e6ff08b3e..0000000000 --- a/src/styles/modules/panel-fullscreen.scss +++ /dev/null @@ -1,63 +0,0 @@ -// -// Fullscreen panel mode styles -// -.panel.fullscreen { - border-radius: 0; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - margin: 0; - z-index: 4; - border-bottom: none; - - // Flex stuff - display: flex; - flex-direction: column; - - .panel-heading { - border-radius: 0; - } - - .panel-body.student-list { - height: 20vh; - resize: vertical; - max-height: 40vh; - overflow: scroll; - border-bottom: 2px solid #428bca; - box-shadow: 1px 1px 3px; - } - .panel-body.project-show { - overflow-y: scroll; - flex: 1; - position: relative; - - &.no-padding { - padding: 0px; - } - - .panel, - .panel-heading { - border-radius: 0; - } - - .nothing-selected { - @include large-notice-block; - position: absolute; - bottom: 0; - top: 0; - left: 0; - right: 0; - font-size: 3em; - text-align: center; - font-weight: 300; - i, - p { - display: block; - width: 100%; - margin-bottom: 0.75em; - } - } - } -} diff --git a/src/styles/modules/project-task-bar.scss b/src/styles/modules/project-task-bar.scss deleted file mode 100644 index 771c60ce4e..0000000000 --- a/src/styles/modules/project-task-bar.scss +++ /dev/null @@ -1,104 +0,0 @@ -@use 'styles/mixins/task-status-colors-generator' as *; - -// -// Student's progress bar styling -// -.task-progress { - tr { - vertical-align: middle; - } - - margin-bottom: 0px; -} - -.progress-bar { - span { - font-size: 8pt; - } - - &[aria-valuenow='1'], - &[aria-valuenow='2'] { - min-width: 0px; - } - - &[aria-valuenow='0'] { - min-width: 0px; - } -} - -.task-progress-bar { - min-width: 128px; - width: 360px; - - .panel-group { - margin-bottom: 0px; - } -} - -.task-progress-accordion, -.progress-progress-bar { - .panel-heading { - padding-top: 5px; - padding-bottom: 5px; - padding-left: 10px; - padding-right: 10px; - } -} - -.progress-bar-ready-for-feedback { - @include task-status-color-ready-for-feedback; -} -.progress-bar-not-started { - @include task-status-color-not-started; -} -.progress-bar-working-on-it { - @include task-status-color-working-on-it; -} -.progress-bar-need-help { - @include task-status-color-need-help; -} -.progress-bar-fix-and-resubmit { - @include task-status-color-fix-and-resubmit; -} -.progress-bar-feedback-exceeded { - @include task-status-color-feedback-exceeded; -} -.progress-bar-fail { - @include task-status-color-fail; -} -.progress-bar-redo { - @include task-status-color-redo; -} -.progress-bar-discuss { - @include task-status-color-discuss; -} -.progress-bar-demonstrate { - @include task-status-color-demonstrate; -} -.progress-bar-complete { - @include task-status-color-complete; -} -.progress-bar-assess-in-portfolio { - @include task-status-color-assess-in-portfolio; -} -.progress-bar-attention-required { - @include task-status-color-attention-required; -} - -.progress-bar-not-started { - @include task-status-color-not-started; -} -.progress-bar-one-week-late { - @include task-status-color-working-on-it; -} -.progress-bar-two-weeks-late { - @include task-status-color-fail; -} -.progress-bar-on-time { - @include task-status-color-complete; -} - -.progress-progress-bar { - height: 30px; - margin-bottom: 0px; -} diff --git a/src/styles/modules/rationale-wrapper.scss b/src/styles/modules/rationale-wrapper.scss deleted file mode 100644 index 08693f7810..0000000000 --- a/src/styles/modules/rationale-wrapper.scss +++ /dev/null @@ -1,30 +0,0 @@ -// -// Text editor for rationale-providers -// -.rationale-wrapper { - display: table; - margin-top: 2em; -} -.rationale { - display: table-cell; - height: 200px; - overflow: scroll; - padding: 30px; - border-radius: 6px; - font-size: 1.5em; - cursor: pointer; - label { - font-size: 0.75em; - text-transform: uppercase; - } - &.no-rationale { - border: 1px dashed #aaa; - vertical-align: middle; - text-align: center; - color: #aaa; - } - &:hover { - border-color: #428bca; - color: #428bca; - } -} diff --git a/src/styles/modules/tabset-icon.scss b/src/styles/modules/tabset-icon.scss deleted file mode 100644 index 0a1a4004d6..0000000000 --- a/src/styles/modules/tabset-icon.scss +++ /dev/null @@ -1,19 +0,0 @@ -// -// Styling for tab headers with icons in them -// -.tabset-icon tab-heading { - text-align: center; - i { - display: block; - width: 100%; - padding-bottom: 5px; - } - i:not(:last-child) { - margin-right: 1ex; - } - i:not(:last-child), - i + i:last-child { - display: inline-block; - width: inherit; - } -} diff --git a/src/styles/modules/task-status.scss b/src/styles/modules/task-status.scss deleted file mode 100644 index 7592e018ec..0000000000 --- a/src/styles/modules/task-status.scss +++ /dev/null @@ -1,214 +0,0 @@ -@use 'sass:color'; -@use 'styles/mixins/task-status-colors-generator' as *; - -// -// Styling for all task status classes -// -.task-status { - &.ready-for-feedback { - @include task-status-color-ready-for-feedback; - } - &.not-started { - @include task-status-color-not-started; - } - &.working-on-it { - @include task-status-color-working-on-it; - } - &.need-help { - @include task-status-color-need-help; - } - &.fix-and-resubmit { - @include task-status-color-fix-and-resubmit; - } - &.feedback-exceeded { - @include task-status-color-feedback-exceeded; - } - &.fail { - @include task-status-color-fail; - } - &.redo { - @include task-status-color-redo; - } - &.discuss { - @include task-status-color-discuss; - } - &.demonstrate { - @include task-status-color-demonstrate; - } - &.complete { - @include task-status-color-complete; - } - &.time-exceeded { - @include task-status-color-time-exceeded; - } - &.assess-in-portfolio { - @include task-status-color-assess-in-portfolio; - } - &.attention-required { - @include task-status-color-attention-required; - } - - &.ready-for-feedback:hover { - background-color: task-status-color('ready-for-feedback'); - } - &.not-started:hover { - background-color: task-status-color('not-started'); - } - &.working-on-it:hover { - background-color: task-status-color('working-on-it'); - } - &.need-help:hover { - background-color: task-status-color('need-help'); - } - &.fix-and-resubmit:hover { - background-color: task-status-color('fix-and-resubmit'); - } - &.feedback-exceeded:hover { - background-color: task-status-color('feedback-exceeded'); - } - &.fail:hover { - background-color: task-status-color('fail'); - } - &.redo:hover { - background-color: task-status-color('redo'); - } - &.discuss:hover { - background-color: task-status-color('discuss'); - } - &.demonstrate:hover { - background-color: task-status-color('demonstrate'); - } - &.complete:hover { - background-color: task-status-color('complete'); - } - &.time-exceeded:hover { - background-color: task-status-color('time-exceeded'); - } - &.assess-in-portfolio:hover { - background-color: task-status-color('assess-in-portfolio'); - } - &.attention-required:hover { - background-color: task-status-color('attention-required'); - } -} - -.task-status > .btn-default { - &.ready-for-feedback, - &.ready-for-feedback.active, - &.ready-for-feedback:hover { - @include task-status-color-ready-for-feedback; - } - &.not-started, - &.not-started.active, - &.not-started:hover { - @include task-status-color-not-started; - } - &.working-on-it, - &.working-on-it.active, - &.working-on-it:hover { - @include task-status-color-working-on-it; - } - &.need-help, - &.need-help.active, - &.need-help:hover { - @include task-status-color-need-help; - } - &.fix-and-resubmit, - &.fix-and-resubmit.active, - &.fix-and-resubmit:hover { - @include task-status-color-fix-and-resubmit; - } - &.feedback-exceeded, - &.feedback-exceeded.active, - &.feedback-exceeded:hover { - @include task-status-color-feedback-exceeded; - } - &.fail, - &.fail.active, - &.fail:hover { - @include task-status-color-fail; - } - &.redo, - &.redo.active, - &.redo:hover { - @include task-status-color-redo; - } - &.discuss, - &.discuss.active, - &.discuss:hover { - @include task-status-color-discuss; - } - &.demonstrate, - &.demonstrate.active, - &.demonstrate:hover { - @include task-status-color-demonstrate; - } - &.complete, - &.complete.active, - &.complete:hover { - @include task-status-color-complete; - } - &.time-exceeded, - &.time-exceeded.active, - &.time-exceeded:hover { - @include task-status-color-time-exceeded; - } - &.assess-in-portfolio, - &.assess-in-portfolio.active, - &.assess-in-portfolio:hover { - @include task-status-color-assess-in-portfolio; - } - &.attention-required, - &.attention-required.active, - &.attention-required:hover { - @include task-status-color-attention-required; - } - - &.ready-for-feedback { - background-color: color.adjust(task-status-color('ready-for-feedback'), $lightness: 15%); - } - &.not-started { - background-color: color.adjust(task-status-color('not-started'), $lightness: 15%); - } - &.working-on-it { - background-color: color.adjust(task-status-color('working-on-it'), $lightness: 15%); - } - &.need-help { - background-color: color.adjust(task-status-color('need-help'), $lightness: 10%); - } - &.fix-and-resubmit { - background-color: color.adjust(task-status-color('fix-and-resubmit'), $lightness: 15%); - } - &.feedback-exceeded { - background-color: color.adjust(task-status-color('feedback-exceeded'), $lightness: 15%); - } - &.fail { - background-color: color.adjust(task-status-color('fail'), $lightness: 15%); - } - &.redo { - background-color: color.adjust(task-status-color('redo'), $lightness: 15%); - } - &.discuss { - background-color: color.adjust(task-status-color('discuss'), $lightness: 15%); - } - &.demonstrate { - background-color: color.adjust(task-status-color('demonstrate'), $lightness: 15%); - } - &.complete { - background-color: color.adjust(task-status-color('complete'), $lightness: 15%); - } - &.time-exceeded { - background-color: color.adjust(task-status-color('time-exceeded'), $lightness: 15%); - } - &.assess-in-portfolio { - background-color: color.adjust(task-status-color('assess-in-portfolio'), $lightness: 15%); - } - &.attention-required { - background-color: color.adjust(task-status-color('attention-required'), $lightness: 15%); - } -} - -i.task-status-icon { - display: block; - margin-bottom: 7px; -} diff --git a/src/styles/vendor-config/bootstrap.scss b/src/styles/vendor-config/bootstrap.scss deleted file mode 100644 index e086df4bd0..0000000000 --- a/src/styles/vendor-config/bootstrap.scss +++ /dev/null @@ -1,13 +0,0 @@ -// -// This config file provides overrides for bootstrap and is injected before -// bootstrap is imported -// - -// Provide the font path to the glyphicons -$icon-font-path: './fonts/bootstrap/'; - -// (Re)definition of screen sizes -$screen-xl: 1900px !default; -$screen-xl-min: $screen-xl !default; -$screen-lg: 1400px !default; -$screen-lg-max: ($screen-xl-min - 1) !default; diff --git a/src/styles/vendor-config/font-awesome.scss b/src/styles/vendor-config/font-awesome.scss deleted file mode 100644 index e073ddedf2..0000000000 --- a/src/styles/vendor-config/font-awesome.scss +++ /dev/null @@ -1,7 +0,0 @@ -// -// This config file provides overrides for bootstrap and is injected before -// font awesome is imported -// - -// Provide the font path to the glyphicons -$fa-font-path: './fonts/font-awesome'; From 356b3b871cb22f8d22172f4257ac730e4b296767 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Thu, 18 Jun 2026 14:23:10 +1000 Subject: [PATCH 1142/1531] refactor: add staff notes header in portfolio view --- .../units/states/portfolios/portfolios.component.html | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/units/states/portfolios/portfolios.component.html b/src/app/units/states/portfolios/portfolios.component.html index da789dafe0..3c6aa16b18 100644 --- a/src/app/units/states/portfolios/portfolios.component.html +++ b/src/app/units/states/portfolios/portfolios.component.html @@ -32,7 +32,15 @@ } @case ('staff-notes') { @if (selectedProject) { - +
      +

      Staff Notes for {{ selectedProject.student.name }}

      +

      + Use these notes for private staff discussions about the student. Students cannot + view them. +

      + + +
      } } @case ('portfolio') { From 5555e27db610aba47b385a095e71d7f72c26a68d Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:31:55 +1000 Subject: [PATCH 1143/1531] refactor: replace karma with vitest (#1274) * chore: replace karma with vitest and remove empty tests * ci: add test workflow * test: add test for welcome component * chore: restore default tests * chore: format * chore: add missing imports --- .github/workflows/test.yml | 19 + angular.json | 21 +- package-lock.json | 3162 ++++++++--------- package.json | 18 +- .../edit-profile.component.spec.ts | 18 +- .../teaching-period-list.component.spec.ts | 20 +- .../states/units/units.component.spec.ts | 39 + .../tii-action-log.component.spec.ts | 23 +- .../api/services/spec/campus.service.spec.ts | 23 +- .../api/services/spec/user.service.spec.ts | 146 +- src/app/api/services/tii.service.spec.ts | 1 + .../directives/drag-drop.directive.spec.ts | 1 + .../edit-profile-form.component.spec.ts | 26 +- src/app/common/f-chip/chip.component.spec.ts | 1 + .../file-viewer/file-viewer.component.spec.ts | 1 + .../common/footer/footer.component.spec.ts | 32 +- .../grade-icon/grade-icon.component.spec.ts | 67 +- .../common/header/header.component.spec.ts | 80 +- .../task-dropdown.component.spec.ts | 1 + .../unit-dropdown.component.spec.ts | 19 +- .../hero-sidebar.component.spec.ts | 1 + .../edit-profile-dialog.service.spec.ts | 1 + .../sidekiq-progress-modal.component.spec.ts | 27 +- .../pdf-viewer-panel.component.spec.ts | 26 +- .../common/pipes/humanized-date.pipe.spec.ts | 1 + src/app/common/pipes/marked.pipe.spec.ts | 1 + src/app/common/pipes/safe.pipe.spec.ts | 2 + .../project-progress-bar.component.spec.ts | 10 +- .../scorm-player.component.spec.ts | 25 +- .../services/alert-service.service.spec.ts | 1 + .../common/services/confetti.service.spec.ts | 1 + src/app/common/services/date.service.spec.ts | 1 + src/app/common/services/grade.service.spec.ts | 1 + .../status-icon/status-icon.component.spec.ts | 17 +- .../user-badge/user-badge.component.spec.ts | 10 +- .../privacy-policy/privacy-policy.spec.ts | 22 +- .../unauthorised.component.spec.ts | 12 +- .../accept-eula/accept-eula.component.spec.ts | 29 +- .../splash-screen.component.spec.ts | 34 +- .../task-assessment-card.component.spec.ts | 18 +- .../task-due-card.component.spec.ts | 10 +- .../task-status-card.component.spec.ts | 34 +- .../task-submission-card.component.spec.ts | 20 +- .../task-dashboard.component.spec.ts | 24 +- .../dashboard/selected-task.service.spec.ts | 13 +- .../staff-notes/staff-notes.component.spec.ts | 24 +- .../tutor-discussion.component.spec.ts | 43 +- .../states/sign-in/sign-in.component.spec.ts | 27 +- .../sessions/transition-hooks.service.spec.ts | 15 - .../grade-task-modal.component.spec.ts | 57 +- .../comment-bubble-action.component.spec.ts | 54 +- .../task-comments-viewer.component.spec.ts | 87 +- src/app/test.service.spec.ts | 1 + .../unit-student-enrolment-modal.spec.ts | 31 +- .../staff-task-list.component.spec.ts | 120 +- .../tasks/inbox/inbox.component.spec.ts | 38 +- .../task-sheet-view.component.spec.ts | 27 + .../unit-task-list.component.spec.ts | 22 +- src/app/welcome/welcome.component.spec.ts | 63 + src/karma-ci.conf.js | 32 - src/karma.conf.js | 40 - src/test.ts | 27 - src/tsconfig.spec.json | 6 +- src/vitest-setup.ts | 1 + 64 files changed, 2494 insertions(+), 2280 deletions(-) create mode 100644 .github/workflows/test.yml delete mode 100644 src/app/sessions/transition-hooks.service.spec.ts delete mode 100644 src/karma-ci.conf.js delete mode 100644 src/karma.conf.js delete mode 100644 src/test.ts create mode 100644 src/vitest-setup.ts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000000..5a5dc93556 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,19 @@ +name: Test CI + +on: + push: + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + - run: npm ci + - run: npm run test:ci diff --git a/angular.json b/angular.json index 2f517eeb5b..cbb09abdb1 100644 --- a/angular.json +++ b/angular.json @@ -93,6 +93,13 @@ "extractLicenses": false, "sourceMap": true }, + "testing": { + "aot": false, + "optimization": false, + "extractLicenses": false, + "sourceMap": true, + "polyfills": ["zone.js"] + }, "devcontainer": { "optimization": false, "extractLicenses": false, @@ -137,18 +144,12 @@ } }, "test": { - "builder": "@angular/build:karma", + "builder": "@angular/build:unit-test", "options": { - "main": "src/test.ts", - "polyfills": "src/polyfills.ts", + "buildTarget": "doubtfire:build:testing", "tsConfig": "src/tsconfig.spec.json", - "karmaConfig": "src/karma.conf.js", - "styles": [], - "stylePreprocessorOptions": { - "includePaths": ["src"] - }, - "scripts": [], - "assets": ["src/favicon.ico", "src/assets", "src/manifest.webmanifest"] + "runner": "vitest", + "setupFiles": ["src/vitest-setup.ts"] } }, "lint": { diff --git a/package-lock.json b/package-lock.json index 0591296990..e8e4016114 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,7 +65,7 @@ "tslib": "^2.8.1", "typescript-eslint": "^8.12.0", "underscore.string": "2.3.3", - "zone.js": "~0.15.1" + "zone.js": "~0.16.2" }, "devDependencies": { "@angular-eslint/builder": "^21.4.0", @@ -84,8 +84,6 @@ "@types/canvas-confetti": "^1.6.0", "@types/d3": "^3.5.17", "@types/file-saver": "^2.0.1", - "@types/jasmine": "~6.0.0", - "@types/jasminewd2": "~2.0.3", "@types/lodash": "^4.14.115", "@types/node": "^20.9.0", "@typescript-eslint/eslint-plugin": "^8.60.1", @@ -100,23 +98,17 @@ "eslint-plugin-tailwindcss": "^3.18.3", "husky": "~8", "ip": "^2.0.1", - "jasmine-core": "~4.1.0", - "jasmine-spec-reporter": "~5.0.0", - "karma": "^6.3.4", - "karma-chrome-launcher": "~3.1.0", - "karma-coverage-istanbul-reporter": "~3.0.2", - "karma-jasmine": "~4.0.0", - "karma-jasmine-html-reporter": "^1.5.0", + "jsdom": "^29.1.1", "npm-run-all2": "^7.0", "postcss": "^8.5.10", "postcss-scss": "^0.1.7", "prettier": "^3.8.3", - "protractor": "~7.0.0", "sass": "^1.48.0", "tailwindcss": "~3.4.17", "ts-node": "~10.9", "typescript": "~5.9.3", - "underscore": "^1.8.3" + "underscore": "^1.8.3", + "vitest": "^4.1.8" }, "engines": { "node": ">=20.9.0" @@ -1001,6 +993,57 @@ "@angular/platform-browser-dynamic": "21.2.17" } }, + "node_modules/@asamuzakjp/css-color": { + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", + "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@csstools/css-calc": "^3.2.0", + "@csstools/css-color-parser": "^4.1.0", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz", + "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/generational-cache": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz", + "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -1294,12 +1337,27 @@ "node": ">=6.9.0" } }, + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0" + }, + "bin": { + "specificity": "bin/cli.js" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.1.90" } @@ -1767,6 +1825,146 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@csstools/color-helpers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.1.tgz", + "integrity": "sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.7.tgz", + "integrity": "sha512-CmjJFQTFQx/U/xNJhSjCQ0ilpesPmNQ8+eOUeM/+kDOVW33qsIjeOXc27vrQDdWVkf83ZSWwtg7kXSUvKDJ8cQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.0.2", + "@csstools/css-calc": "^3.2.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.5.tgz", + "integrity": "sha512-oNjBvzLq2GPZtJphCjLqXow/cHySHSgtxvKZb7OqSZ/xHgw6NWNhfad+6AB9cLeVm6eA9d/qMll3JdEHjy6M+A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, "node_modules/@ctrl/ngx-emoji-mart": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@ctrl/ngx-emoji-mart/-/ngx-emoji-mart-9.3.0.tgz", @@ -2408,6 +2606,24 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, + "node_modules/@exodus/bytes": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, "node_modules/@gar/promise-retry": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", @@ -5180,7 +5396,9 @@ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/@standard-schema/spec": { "version": "1.1.0", @@ -5381,12 +5599,25 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/cors": { "version": "2.8.19", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@types/node": "*" } @@ -5398,6 +5629,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/esrecurse": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", @@ -5417,23 +5655,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/jasmine": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-6.0.0.tgz", - "integrity": "sha512-18lgGsLmEh3VJk9eZ5wAjTISxdqzl6YOwu8UdMpolajN57QOCNbl+AbHUd+Yu9ItrsFdB+c8LSZSGNg8nHaguw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jasminewd2": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.13.tgz", - "integrity": "sha512-aJ3wj8tXMpBrzQ5ghIaqMisD8C3FIrcO6sDKHqFbuqAsI7yOxj0fA7MrRCPLZHIVUjERIwsMmGn/vB0UQ9u0Hg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/jasmine": "*" - } - }, "node_modules/@types/jquery": { "version": "1.10.45", "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-1.10.45.tgz", @@ -5464,20 +5685,6 @@ "undici-types": "~6.21.0" } }, - "node_modules/@types/q": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", - "integrity": "sha512-qYi3YV9inU/REEfxwVcGZzbS3KG/Xs90lv0Pr+lDtuVjBPGd1A+eciXzVSaRvLify132BfcvhvEjeVahrUl0Ug==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/selenium-webdriver": { - "version": "3.0.26", - "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.26.tgz", - "integrity": "sha512-dyIGFKXfUFiwkMfNGn1+F6b80ZjR3uSYv1j6xVJSDlft5waZ2cwkHW4e7zNzvq7hiEackcgvBpmnXZrI1GltPg==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -5491,6 +5698,8 @@ "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@types/node": "*" } @@ -5766,6 +5975,126 @@ "vite": "^6.0.0 || ^7.0.0" } }, + "node_modules/@vitest/expect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz", + "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz", + "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.8", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz", + "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz", + "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.8", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz", + "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.8", + "@vitest/utils": "4.1.8", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz", + "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz", + "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.8", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/@worktile/gantt": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@worktile/gantt/-/gantt-21.0.0.tgz", @@ -5848,16 +6177,6 @@ "node": ">=0.4.0" } }, - "node_modules/adm-zip": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.17.tgz", - "integrity": "sha512-+Ut8d9LLqwEvHHJl1+PIHqoyDxFgVN847JTVM3Izi3xHDWPE4UtzzXysMZQs64DMcrJfBeS/uoEP4AD3HQHnQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0" - } - }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -6186,66 +6505,16 @@ "dev": true, "license": "MIT" }, - "node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", - "dependencies": { - "array-uniq": "^1.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, - "license": "MIT" - }, "node_modules/autoprefixer": { "version": "6.7.7", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", @@ -6362,23 +6631,6 @@ "node": ">=0.10.0" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", - "dev": true, - "license": "MIT" - }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -6404,12 +6656,37 @@ "node": ">= 0.6.0" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": "^4.5.0 || >= 5.9" } @@ -6427,16 +6704,6 @@ "node": ">=6.0.0" } }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/beasties": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.4.1.tgz", @@ -6458,6 +6725,16 @@ "node": ">=18.0.0" } }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -6471,20 +6748,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/blocking-proxy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", - "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "blocking-proxy": "built/lib/bin.js" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=6.9.x" + "node": ">= 6" } }, "node_modules/body-parser": { @@ -6576,51 +6868,31 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/browserstack": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.6.1.tgz", - "integrity": "sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "https-proxy-agent": "^2.2.1" - } - }, - "node_modules/browserstack/node_modules/agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es6-promisify": "^5.0.0" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/browserstack/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/browserstack/node_modules/https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "engines": { - "node": ">= 4.5.0" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "node_modules/buffer-from": { @@ -6831,19 +7103,20 @@ "license": "MIT" }, "node_modules/canvas": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", - "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-3.2.3.tgz", + "integrity": "sha512-PzE5nJZPz72YUAfo8oTp0u3fqqY7IzlTubneAihqDYAUcBk7ryeCmBbdJBEdaH0bptSOe2VT2Zwcb3UaFyaSWw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.17.0", - "simple-get": "^3.0.3" + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.3" }, "engines": { - "node": ">=6" + "node": "^18.12.0 || >= 20.9.0" } }, "node_modules/canvas-confetti": { @@ -6856,12 +7129,24 @@ "url": "https://www.paypal.me/kirilvatev" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "node_modules/canvas/node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "dev": true, - "license": "Apache-2.0" + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/chalk": { "version": "2.4.2", @@ -7093,29 +7378,6 @@ "dev": true, "license": "MIT" }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", @@ -7141,8 +7403,8 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "devOptional": true, - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/concurrently": { "version": "3.6.1", @@ -7189,6 +7451,8 @@ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", @@ -7205,6 +7469,8 @@ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ms": "2.0.0" } @@ -7215,6 +7481,8 @@ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.8" } @@ -7225,6 +7493,8 @@ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -7243,7 +7513,9 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/connect/node_modules/on-finished": { "version": "2.3.0", @@ -7251,6 +7523,8 @@ "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ee-first": "1.1.1" }, @@ -7264,6 +7538,8 @@ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -7496,6 +7772,20 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, "node_modules/css-what": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-7.0.0.tgz", @@ -7527,7 +7817,9 @@ "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/d3": { "version": "3.5.17", @@ -7792,17 +8084,18 @@ "d3-selection": "2 - 3" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "node_modules/data-urls": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", "dev": true, "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0" + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" }, "engines": { - "node": ">=0.10" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/date-fns": { @@ -7821,6 +8114,8 @@ "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=4.0" } @@ -7851,17 +8146,41 @@ "node": ">=0.10.0" } }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, "node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { - "mimic-response": "^2.0.0" + "mimic-response": "^3.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4.0.0" } }, "node_modules/deep-is": { @@ -7870,74 +8189,21 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "license": "MIT" }, - "node_modules/del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha512-Z4fzpbIRjOu7lO5jCETSWoqUDVe0IPOlfugBsF6suen2LKDlVb4QZpKEM9P+buNJ4KI1eN7I083w/pbKUpsrWQ==", + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", - "dependencies": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" - }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "license": "MIT", - "optional": true - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" + "node": ">= 0.8" } }, "node_modules/destroy": { @@ -7946,6 +8212,8 @@ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -7966,7 +8234,9 @@ "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/didyoumean": { "version": "1.2.2", @@ -8004,6 +8274,8 @@ "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "custom-event": "~1.0.0", "ent": "~2.2.0", @@ -8107,17 +8379,6 @@ "node": ">= 0.4" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -8148,12 +8409,26 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/engine.io": { "version": "6.6.8", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.8.tgz", "integrity": "sha512-2agL3ueZhqxoVrfmntO8yuVj+uNSlIOnhykYHk3Cq0ShYPdUjjUiSJrQvXjq01I9jAuI0Zl2YO8Evv5Mqytm5g==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", @@ -8176,6 +8451,8 @@ "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=10.0.0" } @@ -8186,6 +8463,8 @@ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -8200,6 +8479,8 @@ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -8210,6 +8491,8 @@ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -8223,6 +8506,8 @@ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -8247,6 +8532,8 @@ "integrity": "sha512-kKvD1tO6BM+oK9HzCPpUdRb4vKFQY/FPTFmurMvh6LlN68VMrdj77w8yp51/kDbpkFOS9J8w5W6zIzgM2H8/hw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -8330,6 +8617,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", @@ -8363,23 +8657,6 @@ "node": ">=0.4.0" } }, - "node_modules/es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es6-promise": "^4.0.3" - } - }, "node_modules/esbuild": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", @@ -8756,6 +9033,16 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -8780,7 +9067,9 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/eventsource": { "version": "3.0.7", @@ -8805,13 +9094,26 @@ "node": ">=18.0.0" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">= 0.8.0" + "node": ">=12.0.0" } }, "node_modules/exponential-backoff": { @@ -8896,17 +9198,9 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true, - "license": "MIT" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -9107,6 +9401,8 @@ } ], "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=4.0" }, @@ -9125,54 +9421,6 @@ "node": ">=0.10.3" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/form-data/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/form-data/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -9193,12 +9441,23 @@ "node": ">= 0.8" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -9225,8 +9484,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "devOptional": true, - "license": "ISC" + "license": "ISC", + "optional": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -9401,16 +9660,6 @@ "node": ">= 0.4" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/git-raw-commits": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-5.0.1.tgz", @@ -9428,13 +9677,22 @@ "node": ">=18" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "devOptional": true, "license": "ISC", + "optional": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -9473,8 +9731,8 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", - "devOptional": true, "license": "MIT", + "optional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -9484,8 +9742,8 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "devOptional": true, "license": "ISC", + "optional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -9509,34 +9767,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha512-HJRTIH2EeH44ka+LWig+EqT2ONSYpVlNfx6pyd592/VF1TbfljJ7elwie7oSwcViLGqOdWocSdu2txwBF9bjmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -9557,55 +9787,6 @@ "dev": true, "license": "ISC" }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/har-validator/node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/har-validator/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, "node_modules/has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -9658,6 +9839,8 @@ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -9721,12 +9904,18 @@ "node": "20 || >=22" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } }, "node_modules/html2canvas": { "version": "1.0.0-rc.7", @@ -9813,6 +10002,8 @@ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -9836,22 +10027,6 @@ "node": ">= 14" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", @@ -9899,6 +10074,29 @@ "url": "https://opencollective.com/express" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true, + "peer": true + }, "node_modules/ignore": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", @@ -10025,8 +10223,8 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "devOptional": true, "license": "ISC", + "optional": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -10190,42 +10388,6 @@ "node": ">=8" } }, - "node_modules/is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha512-cnS56eR9SPAscL77ik76ATVqoPARTqPIVkMDVxRaWH06zT+6+CzIroYRJ0VVvm0Z1zfAvxvz9i/D3Ppjaqt5Nw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-path-inside": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-is-inside": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -10239,6 +10401,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -10252,6 +10421,8 @@ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", @@ -10265,13 +10436,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true, - "license": "MIT" - }, "node_modules/is-unicode-supported": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", @@ -10297,6 +10461,8 @@ "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 8.0.0" }, @@ -10310,13 +10476,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true, - "license": "MIT" - }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -10344,192 +10503,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jasmine": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", - "integrity": "sha512-KbdGQTf5jbZgltoHs31XGiChAPumMSY64OZMWLNYnEnMfG5uwGBhffePwuskexjT+/Jea/gU3qAU8344hNohSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "exit": "^0.1.2", - "glob": "^7.0.6", - "jasmine-core": "~2.8.0" - }, - "bin": { - "jasmine": "bin/jasmine.js" - } - }, - "node_modules/jasmine-core": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.1.1.tgz", - "integrity": "sha512-lmUfT5XcK9KKvt3lLYzn93hc4MGzlUBowExFVgzbSW0ZCrdeyS574dfsyfRhxbg81Wj4gk+RxUiTnj7KBfDA1g==", - "dev": true, - "license": "MIT" - }, - "node_modules/jasmine-spec-reporter": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-5.0.2.tgz", - "integrity": "sha512-6gP1LbVgJ+d7PKksQBc2H0oDGNRQI3gKUsWlswKaQ2fif9X5gzhQcgM5+kiJGCQVurOG09jqNhk7payggyp5+g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "colors": "1.4.0" - } - }, - "node_modules/jasmine/node_modules/jasmine-core": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", - "integrity": "sha512-SNkOkS+/jMZvLhuSx1fjhcNWUC/KG6oVyFUGkSBEr9n1axSNduWU8GlI7suaHXr4yxjet6KjrUZxUTE5WzzWwQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/jasminewd2": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", - "integrity": "sha512-Rn0nZe4rfDhzA63Al3ZGh0E+JTmM6ESZYXJGKuqKGZObsAB9fwXPD03GjtIEvJBDOhN94T5MzbwZSqzFHSQPzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.9.x" - } - }, "node_modules/javascript-natural-sort": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", @@ -10600,12 +10573,79 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "node_modules/jsdom": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz", + "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^5.1.11", + "@asamuzakjp/dom-selector": "^7.1.1", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.3", + "@exodus/bytes": "^1.15.0", + "css-tree": "^3.2.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.3.5", + "parse5": "^8.0.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.1", + "undici": "^7.25.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.1", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/jsdom/node_modules/tough-cookie": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/jsdom/node_modules/undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } }, "node_modules/jsesc": { "version": "3.1.0", @@ -10643,13 +10683,6 @@ "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true, - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -10670,13 +10703,6 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "license": "MIT" }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "license": "ISC" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -10703,6 +10729,8 @@ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -10717,22 +10745,6 @@ ], "license": "MIT" }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -10751,6 +10763,8 @@ "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@colors/colors": "1.5.0", "body-parser": "^1.19.0", @@ -10784,111 +10798,14 @@ "node": ">= 10" } }, - "node_modules/karma-chrome-launcher": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz", - "integrity": "sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "which": "^1.2.1" - } - }, - "node_modules/karma-chrome-launcher/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/karma-coverage-istanbul-reporter": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-3.0.3.tgz", - "integrity": "sha512-wE4VFhG/QZv2Y4CdAYWDbMmcAHeS926ZIji4z+FkB2aF/EposRb6DP6G5ncT/wXhqUfAb/d7kZrNKPonbvsATw==", - "dev": true, - "license": "MIT", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^3.0.6", - "istanbul-reports": "^3.0.2", - "minimatch": "^3.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/mattlewis92" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/karma-jasmine": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-4.0.2.tgz", - "integrity": "sha512-ggi84RMNQffSDmWSyyt4zxzh2CQGwsxvYYsprgyR1j8ikzIduEdOlcLvXjZGwXG/0j41KUXOWsUCBfbEHPWP9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "jasmine-core": "^3.6.0" - }, - "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "karma": "*" - } - }, - "node_modules/karma-jasmine-html-reporter": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz", - "integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "jasmine-core": ">=3.8", - "karma": ">=0.9", - "karma-jasmine": ">=1.1" - } - }, - "node_modules/karma-jasmine/node_modules/jasmine-core": { - "version": "3.99.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz", - "integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==", - "dev": true, - "license": "MIT" - }, - "node_modules/karma/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/karma/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -10899,6 +10816,8 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -10915,6 +10834,8 @@ "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", @@ -10940,6 +10861,8 @@ "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -10951,6 +10874,8 @@ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -10976,6 +10901,8 @@ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -10988,6 +10915,8 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -11000,7 +10929,9 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/karma/node_modules/debug": { "version": "2.6.9", @@ -11008,6 +10939,8 @@ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ms": "2.0.0" } @@ -11018,6 +10951,8 @@ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -11031,6 +10966,8 @@ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -11044,6 +10981,8 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -11054,6 +10993,8 @@ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -11064,6 +11005,8 @@ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -11074,6 +11017,8 @@ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -11087,6 +11032,8 @@ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -11099,7 +11046,9 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/karma/node_modules/picomatch": { "version": "2.3.2", @@ -11107,6 +11056,8 @@ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8.6" }, @@ -11120,6 +11071,8 @@ "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", @@ -11136,6 +11089,8 @@ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -11149,6 +11104,8 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -11159,6 +11116,8 @@ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -11174,6 +11133,8 @@ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -11187,6 +11148,8 @@ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -11201,6 +11164,8 @@ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -11219,6 +11184,8 @@ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -11238,6 +11205,8 @@ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "engines": { "node": ">=10" } @@ -11595,6 +11564,8 @@ "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", "dev": true, "license": "Apache-2.0", + "optional": true, + "peer": true, "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", @@ -11632,22 +11603,6 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -11701,6 +11656,13 @@ "node": ">= 0.4" } }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/media-typer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", @@ -11789,6 +11751,8 @@ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "bin": { "mime": "cli.js" }, @@ -11837,13 +11801,15 @@ } }, "node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -12014,6 +11980,8 @@ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -12021,6 +11989,15 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/mlly": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", @@ -12182,6 +12159,15 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -12291,6 +12277,21 @@ "@angular/core": ">=19.0.0" } }, + "node_modules/node-abi": { + "version": "3.92.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-addon-api": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", @@ -12320,6 +12321,31 @@ } } }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT", + "optional": true + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-gyp": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.4.0.tgz", @@ -12684,16 +12710,6 @@ "d3": "^3.4.4" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -12727,6 +12743,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz", + "integrity": "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -12827,16 +12857,6 @@ "license": "MIT", "optional": true }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -13071,19 +13091,12 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "devOptional": true, "license": "MIT", + "optional": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", - "dev": true, - "license": "(WTFPL OR MIT)" - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -13181,76 +13194,100 @@ "path2d-polyfill": "^2.0.1" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "node_modules/pdfjs-dist/node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "hasInstallScript": true, "license": "MIT", - "engines": { - "node": ">=12" + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "engines": { + "node": ">=6" } }, - "node_modules/pidtree": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.1.tgz", - "integrity": "sha512-e0F9AOF1JMrCfBsyJOwU9lNvQ0WtXTq0j/4jk0BQ5JSI9VAybPXmDpPRw/2FQ3e5d3ZFN1mLh7jW99m/jjaptw==", - "dev": true, + "node_modules/pdfjs-dist/node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" + "optional": true, + "dependencies": { + "mimic-response": "^2.0.0" }, "engines": { - "node": ">=0.10" + "node": ">=8" } }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, + "node_modules/pdfjs-dist/node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", "license": "MIT", + "optional": true, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "node_modules/pdfjs-dist/node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "node_modules/pidtree": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.1.tgz", + "integrity": "sha512-e0F9AOF1JMrCfBsyJOwU9lNvQ0WtXTq0j/4jk0BQ5JSI9VAybPXmDpPRw/2FQ3e5d3ZFN1mLh7jW99m/jjaptw==", "dev": true, "license": "MIT", - "dependencies": { - "pinkie": "^2.0.0" + "bin": { + "pidtree": "bin/pidtree.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" } }, "node_modules/pirates": { @@ -13613,6 +13650,36 @@ "dev": true, "license": "MIT" }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -13678,302 +13745,7 @@ "retry": "^0.12.0" }, "engines": { - "node": ">=10" - } - }, - "node_modules/protractor": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz", - "integrity": "sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==", - "deprecated": "We have news to share - Protractor is deprecated and will reach end-of-life by Summer 2023. To learn more and find out about other options please refer to this post on the Angular blog. Thank you for using and contributing to Protractor. https://goo.gle/state-of-e2e-in-angular", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/q": "^0.0.32", - "@types/selenium-webdriver": "^3.0.0", - "blocking-proxy": "^1.0.0", - "browserstack": "^1.5.1", - "chalk": "^1.1.3", - "glob": "^7.0.3", - "jasmine": "2.8.0", - "jasminewd2": "^2.1.0", - "q": "1.4.1", - "saucelabs": "^1.5.0", - "selenium-webdriver": "3.6.0", - "source-map-support": "~0.4.0", - "webdriver-js-extender": "2.1.0", - "webdriver-manager": "^12.1.7", - "yargs": "^15.3.1" - }, - "bin": { - "protractor": "bin/protractor", - "webdriver-manager": "bin/webdriver-manager" - }, - "engines": { - "node": ">=10.13.x" - } - }, - "node_modules/protractor/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/protractor/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/protractor/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/protractor/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/protractor/node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/protractor/node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/protractor/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/protractor/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/protractor/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/protractor/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/protractor/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/protractor/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/protractor/node_modules/source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "source-map": "^0.5.6" - } - }, - "node_modules/protractor/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/protractor/node_modules/string-width/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/protractor/node_modules/string-width/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/protractor/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/protractor/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/protractor/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/protractor/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/protractor/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" + "node": ">=10" } }, "node_modules/proxy-addr": { @@ -13990,27 +13762,17 @@ "node": ">= 0.10" } }, - "node_modules/psl": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", - "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "punycode": "^2.3.1" - }, - "funding": { - "url": "https://github.com/sponsors/lupomontero" - } - }, - "node_modules/psl/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, "node_modules/punycode": { @@ -14018,19 +13780,9 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true, - "license": "MIT" - }, - "node_modules/q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha512-/CdEdaw49VZVmyIDGUQKDDT53c7qBkO6g5CefWz91Ae+l4+cRtcDYwMTXh6me4O8TMldeGHG3N2Bl84V78Ywbg==", - "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", - "dev": true, "license": "MIT", - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } + "optional": true, + "peer": true }, "node_modules/qjobs": { "version": "1.2.0", @@ -14038,6 +13790,8 @@ "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.9" } @@ -14287,6 +14041,45 @@ "node": ">= 0.10" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "peer": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -14392,72 +14185,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/request/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz", - "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.6" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -14488,7 +14215,9 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/resolve": { "version": "1.22.12", @@ -14571,8 +14300,8 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", - "devOptional": true, "license": "ISC", + "optional": true, "dependencies": { "glob": "^7.1.3" }, @@ -14728,6 +14457,8 @@ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -14768,106 +14499,17 @@ "@parcel/watcher": "^2.4.1" } }, - "node_modules/saucelabs": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", - "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", - "dev": true, - "dependencies": { - "https-proxy-agent": "^2.2.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/saucelabs/node_modules/agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es6-promisify": "^5.0.0" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/saucelabs/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/saucelabs/node_modules/https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/sax": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", - "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=11.0.0" - } - }, - "node_modules/selenium-webdriver": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", - "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "jszip": "^3.1.3", - "rimraf": "^2.5.4", - "tmp": "0.0.30", - "xml2js": "^0.4.17" - }, - "engines": { - "node": ">= 6.9.0" - } - }, - "node_modules/selenium-webdriver/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, "license": "ISC", "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/selenium-webdriver/node_modules/tmp": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", - "integrity": "sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.1" + "xmlchars": "^2.2.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=v12.22.7" } }, "node_modules/semver": { @@ -15241,6 +14883,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -15294,13 +14943,29 @@ "optional": true }, "node_modules/simple-get": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", - "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", "optional": true, + "peer": true, "dependencies": { - "decompress-response": "^4.2.0", + "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } @@ -15352,6 +15017,8 @@ "integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -15371,6 +15038,8 @@ "integrity": "sha512-e0LyK91f3cUxTmv95/KzoLg47+zF+s/sbxRGDNsyG4dmIP8ZSX8ax6byOxfJXeNNtS/8AZlfD+uP7gBeR7DLlg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "debug": "~4.4.1", "ws": "~8.20.1" @@ -15382,6 +15051,8 @@ "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1" @@ -15396,6 +15067,8 @@ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -15410,6 +15083,8 @@ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -15420,6 +15095,8 @@ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -15433,6 +15110,8 @@ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -15561,32 +15240,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ssri": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.1.tgz", @@ -15600,6 +15253,13 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -15610,6 +15270,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/stdin-discarder": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.3.2.tgz", @@ -15629,6 +15296,8 @@ "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", @@ -15762,6 +15431,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, "node_modules/synckit": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", @@ -15936,7 +15612,67 @@ "yallist": "^5.0.0" }, "engines": { - "node": ">=18" + "node": ">=18" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/tar/node_modules/yallist": { @@ -15972,6 +15708,13 @@ "node": ">=0.8" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyexec": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", @@ -15998,12 +15741,44 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.2.tgz", + "integrity": "sha512-kCwffuaH8ntKtygnWe1b4BJKWiCUH30n5KfoTr6IchcXOwR7chAOFJxFrH3vjANafUYrIA4a7SDL+nn7SiR4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^7.4.2" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.2.tgz", + "integrity": "sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==", + "dev": true, + "license": "MIT" + }, "node_modules/tmp": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=14.14" } @@ -16031,21 +15806,20 @@ "node": ">=0.6" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "punycode": "^2.3.1" }, "engines": { - "node": ">=0.8" + "node": ">=20" } }, - "node_modules/tough-cookie/node_modules/punycode": { + "node_modules/tr46/node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", @@ -16055,13 +15829,6 @@ "node": ">=6" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT", - "optional": true - }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -16178,6 +15945,8 @@ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, "license": "Apache-2.0", + "optional": true, + "peer": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -16185,13 +15954,6 @@ "node": "*" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true, - "license": "Unlicense" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -16293,6 +16055,8 @@ } ], "license": "MIT", + "optional": true, + "peer": true, "bin": { "ua-parser-js": "script/cli.js" }, @@ -16345,6 +16109,8 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 4.0.0" } @@ -16420,21 +16186,12 @@ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -16484,28 +16241,6 @@ "node": ">= 0.8" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true, - "license": "MIT" - }, "node_modules/vite": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", @@ -16581,16 +16316,121 @@ } } }, + "node_modules/vitest": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz", + "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.8", + "@vitest/mocker": "4.1.8", + "@vitest/pretty-format": "4.1.8", + "@vitest/runner": "4.1.8", + "@vitest/snapshot": "4.1.8", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.8", + "@vitest/browser-preview": "4.1.8", + "@vitest/browser-webdriverio": "4.1.8", + "@vitest/coverage-istanbul": "4.1.8", + "@vitest/coverage-v8": "4.1.8", + "@vitest/ui": "4.1.8", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, "node_modules/void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/watchpack": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", @@ -16613,153 +16453,39 @@ "license": "MIT", "optional": true }, - "node_modules/webdriver-js-extender": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", - "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/selenium-webdriver": "^3.0.0", - "selenium-webdriver": "^3.0.1" - }, - "engines": { - "node": ">=6.9.x" - } - }, - "node_modules/webdriver-manager": { - "version": "12.1.9", - "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.9.tgz", - "integrity": "sha512-Yl113uKm8z4m/KMUVWHq1Sjtla2uxEBtx2Ue3AmIlnlPAKloDn/Lvmy6pqWCUersVISpdMeVpAaGbNnvMuT2LQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "adm-zip": "^0.5.2", - "chalk": "^1.1.1", - "del": "^2.2.0", - "glob": "^7.0.3", - "ini": "^1.3.4", - "minimist": "^1.2.0", - "q": "^1.4.1", - "request": "^2.87.0", - "rimraf": "^2.5.2", - "semver": "^5.3.0", - "xml2js": "^0.4.17" - }, - "bin": { - "webdriver-manager": "bin/webdriver-manager" - }, - "engines": { - "node": ">=6.9.x" - } - }, - "node_modules/webdriver-manager/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webdriver-manager/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=0.10.0" + "node": ">=20" } }, - "node_modules/webdriver-manager/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webdriver-manager/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/webdriver-manager/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/webdriver-manager/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" + "node": ">=20" } }, - "node_modules/webdriver-manager/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "node_modules/whatwg-url": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" + "@exodus/bytes": "^1.11.0", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webdriver-manager/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause", - "optional": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "optional": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/which": { @@ -16783,6 +16509,23 @@ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "license": "ISC" }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -16954,6 +16697,8 @@ "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=10.0.0" }, @@ -16970,29 +16715,22 @@ } } }, - "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, - "license": "MIT", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, + "license": "Apache-2.0", "engines": { - "node": ">=4.0.0" + "node": ">=18" } }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0" - } + "license": "MIT" }, "node_modules/y18n": { "version": "5.0.8", @@ -17133,9 +16871,9 @@ } }, "node_modules/zone.js": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz", - "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==", + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.16.2.tgz", + "integrity": "sha512-Eky7p2Z1Ig3NnbfodSPoARCjKBSTFMnE/ACsP1L/XJEfY4SdOFce19BsUCWVwL6K5ABZFy5J3bjcMWffX+YM3Q==", "license": "MIT" } } diff --git a/package.json b/package.json index 4e0a4dfec0..f7646cab11 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "deploy": "run-s -l deploy:build2api", "prepare": "husky install", "test": "ng test", - "test:ci": "ng test --karma-config=src/karma-ci.conf.js --no-progress" + "test:ci": "ng test --no-watch --no-progress" }, "keywords": [], "author": "", @@ -81,7 +81,7 @@ "tslib": "^2.8.1", "typescript-eslint": "^8.12.0", "underscore.string": "2.3.3", - "zone.js": "~0.15.1" + "zone.js": "~0.16.2" }, "devDependencies": { "@angular-eslint/builder": "^21.4.0", @@ -100,8 +100,6 @@ "@types/canvas-confetti": "^1.6.0", "@types/d3": "^3.5.17", "@types/file-saver": "^2.0.1", - "@types/jasmine": "~6.0.0", - "@types/jasminewd2": "~2.0.3", "@types/lodash": "^4.14.115", "@types/node": "^20.9.0", "@typescript-eslint/eslint-plugin": "^8.60.1", @@ -116,23 +114,17 @@ "eslint-plugin-tailwindcss": "^3.18.3", "husky": "~8", "ip": "^2.0.1", - "jasmine-core": "~4.1.0", - "jasmine-spec-reporter": "~5.0.0", - "karma": "^6.3.4", - "karma-chrome-launcher": "~3.1.0", - "karma-coverage-istanbul-reporter": "~3.0.2", - "karma-jasmine": "~4.0.0", - "karma-jasmine-html-reporter": "^1.5.0", + "jsdom": "^29.1.1", "npm-run-all2": "^7.0", "postcss": "^8.5.10", "postcss-scss": "^0.1.7", "prettier": "^3.8.3", - "protractor": "~7.0.0", "sass": "^1.48.0", "tailwindcss": "~3.4.17", "ts-node": "~10.9", "typescript": "~5.9.3", - "underscore": "^1.8.3" + "underscore": "^1.8.3", + "vitest": "^4.1.8" }, "optionalDependencies": { "@nx/nx-darwin-arm64": "^18.0", diff --git a/src/app/account/edit-profile/edit-profile.component.spec.ts b/src/app/account/edit-profile/edit-profile.component.spec.ts index 04b0a4eb05..b15e0bfc85 100644 --- a/src/app/account/edit-profile/edit-profile.component.spec.ts +++ b/src/app/account/edit-profile/edit-profile.component.spec.ts @@ -1,6 +1,12 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {Router} from '@angular/router'; +import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {EditProfileComponent} from './edit-profile.component'; +const emptyProvider = {}; + describe('EditProfileComponent', () => { let component: EditProfileComponent; let fixture: ComponentFixture; @@ -8,11 +14,19 @@ describe('EditProfileComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [EditProfileComponent], - }).compileComponents(); + providers: [ + {provide: AuthenticationService, useValue: emptyProvider}, + {provide: Router, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(EditProfileComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(EditProfileComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.spec.ts b/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.spec.ts index 22e88fc195..6b38a84b69 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.spec.ts +++ b/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.spec.ts @@ -1,6 +1,13 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatDialog} from '@angular/material/dialog'; +import {TeachingPeriodService} from 'src/app/api/services/teaching-period.service'; +import {TeachingPeriodUnitImportService} from '../teaching-period-unit-import/teaching-period-unit-import.dialog'; import {TeachingPeriodListComponent} from './teaching-period-list.component'; +const emptyProvider = {}; + describe('TeachingPeriodListComponent', () => { let component: TeachingPeriodListComponent; let fixture: ComponentFixture; @@ -8,11 +15,20 @@ describe('TeachingPeriodListComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [TeachingPeriodListComponent], - }).compileComponents(); + providers: [ + {provide: TeachingPeriodService, useValue: emptyProvider}, + {provide: MatDialog, useValue: emptyProvider}, + {provide: TeachingPeriodUnitImportService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(TeachingPeriodListComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(TeachingPeriodListComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/admin/states/units/units.component.spec.ts b/src/app/admin/states/units/units.component.spec.ts index e69de29bb2..b5ca421a3a 100644 --- a/src/app/admin/states/units/units.component.spec.ts +++ b/src/app/admin/states/units/units.component.spec.ts @@ -0,0 +1,39 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {ActivatedRoute} from '@angular/router'; +import {UnitService} from 'src/app/api/services/unit.service'; +import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; +import {CreateNewUnitModal} from '../../modals/create-new-unit-modal/create-new-unit-modal.component'; +import {FUnitsComponent} from './units.component'; + +const emptyProvider = {}; + +describe('FUnitsComponent', () => { + let component: FUnitsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [FUnitsComponent], + providers: [ + {provide: CreateNewUnitModal, useValue: emptyProvider}, + {provide: GlobalStateService, useValue: emptyProvider}, + {provide: UnitService, useValue: emptyProvider}, + {provide: ActivatedRoute, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(FUnitsComponent, {set: {template: ''}}) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FUnitsComponent); + component = fixture.componentInstance; + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/tii-action-log/tii-action-log.component.spec.ts b/src/app/admin/tii-action-log/tii-action-log.component.spec.ts index 38e5d9ec65..d9cd6e6310 100644 --- a/src/app/admin/tii-action-log/tii-action-log.component.spec.ts +++ b/src/app/admin/tii-action-log/tii-action-log.component.spec.ts @@ -1,17 +1,32 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {TiiActionService} from 'src/app/api/services/tii-action.service'; +import {AlertService} from 'src/app/common/services/alert.service'; import {TiiActionLogComponent} from './tii-action-log.component'; +const emptyProvider = {}; + describe('TiiActionLogComponent', () => { let component: TiiActionLogComponent; let fixture: ComponentFixture; - beforeEach(() => { - TestBed.configureTestingModule({ + beforeEach(async () => { + await TestBed.configureTestingModule({ declarations: [TiiActionLogComponent], - }); + providers: [ + {provide: TiiActionService, useValue: emptyProvider}, + {provide: AlertService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(TiiActionLogComponent, {set: {template: ''}}) + .compileComponents(); + }); + + beforeEach(() => { fixture = TestBed.createComponent(TiiActionLogComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/api/services/spec/campus.service.spec.ts b/src/app/api/services/spec/campus.service.spec.ts index e89adef628..d96c869e4c 100644 --- a/src/app/api/services/spec/campus.service.spec.ts +++ b/src/app/api/services/spec/campus.service.spec.ts @@ -1,6 +1,7 @@ +import {afterEach, beforeEach, describe, expect, it} from 'vitest'; import {HttpRequest, provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; -import {TestBed, fakeAsync, tick} from '@angular/core/testing'; +import {TestBed} from '@angular/core/testing'; import {Campus} from 'src/app/api/models/doubtfire-model'; import {CampusService} from '../campus.service'; @@ -26,18 +27,22 @@ describe('CampusService', () => { httpMock.verify(); }); - it('should return expected campuses (HttpClient called once)', fakeAsync(() => { + it('should return expected campuses (HttpClient called once)', () => { const c = new Campus(); c.name = 'Melbourne'; c.mode = 'automatic'; c.abbreviation = 'melb'; - const expectedCampuses: Campus[] = [c]; - - campusService - .query() - .subscribe((campuses) => expect(campuses).toEqual(expectedCampuses, 'expected campuses')); + campusService.query().subscribe((campuses) => { + expect(campuses).toHaveLength(1); + expect(campuses[0]).toMatchObject({ + id: 1, + name: 'Melbourne', + mode: 'automatic', + abbreviation: 'melb', + }); + }); const req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/campuses/'); @@ -47,7 +52,5 @@ describe('CampusService', () => { c.id = 1; req.flush(c); - - tick(); - })); + }); }); diff --git a/src/app/api/services/spec/user.service.spec.ts b/src/app/api/services/spec/user.service.spec.ts index 9c5a2439fd..6f39dc81eb 100644 --- a/src/app/api/services/spec/user.service.spec.ts +++ b/src/app/api/services/spec/user.service.spec.ts @@ -1,6 +1,7 @@ +import {afterEach, beforeEach, describe, expect, it} from 'vitest'; import {HttpRequest, provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; -import {TestBed, fakeAsync, tick} from '@angular/core/testing'; +import {TestBed} from '@angular/core/testing'; import {User, UserService} from 'src/app/api/models/doubtfire-model'; describe('UserService', () => { @@ -25,7 +26,7 @@ describe('UserService', () => { httpMock.verify(); }); - it('should return expected users (HttpClient called once)', fakeAsync(() => { + it('should return expected users (HttpClient called once)', () => { const u = new User(); u.id = 1; u.lastName = 'renzella'; @@ -40,24 +41,39 @@ describe('UserService', () => { u.receiveFeedbackNotifications = false; u.receiveTaskNotifications = false; - const expectedUsers: User[] = [u]; - - userService - .query() - .subscribe((users) => expect(users).toEqual(expectedUsers, 'expected users')); + userService.query().subscribe((users) => { + expect(users).toHaveLength(1); + expect(users[0]).toMatchObject({ + id: 1, + firstName: 'Jake', + lastName: 'renzella', + email: 'jake@jake.jake', + }); + }); const req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/users/'); expect(request.method).toBe('GET'); return true; }); - req.flush(u); - tick(); - })); + req.flush({ + id: 1, + last_name: 'renzella', + first_name: 'Jake', + nickname: 'jake', + has_run_first_time_setup: false, + email: 'jake@jake.jake', + student_id: '1', + username: 'test', + opt_in_to_research: true, + receive_portfolio_notifications: false, + receive_feedback_notifications: false, + receive_task_notifications: false, + }); + }); - it('should create a new user', fakeAsync(() => { + it('should create a new user', () => { const user = new User(); - user.id = 1; user.lastName = 'renzella'; user.firstName = 'Jake'; user.nickname = 'jake'; @@ -71,43 +87,57 @@ describe('UserService', () => { user.receiveTaskNotifications = false; userService.create(user).subscribe((result) => { - expect(result).toEqual(user, 'expected users'); + expect(result).toMatchObject({ + id: 1, + firstName: 'Jake', + lastName: 'renzella', + email: 'jake@jake.jake', + }); }); - const expectedUser = user; - expectedUser.id = 1; - const req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/users/'); expect(request.method).toBe('POST'); return true; }); - req.flush(expectedUser); - tick(); - })); - - xit('should delete a user', fakeAsync(() => { - // let user = new User(); - // user.updateFromJson({ - // name: 'jake', lastName: 'renzella', firstName: 'Jake', nickname: 'jake', - // systemRole: 'admin', hasRunFirstTimeSetup: false, email: 'jake@jake.jake', - // student_id: '1', username: 'test', optInToResearch: true, receivePortfolioNotifications: false, - // receiveFeedbackNotifications: false, receiveTaskNotifications: false - // }); - // userService.delete(1).subscribe( - // result => expect(result).toEqual(user, 'expected users') - // ); - // const req = httpMock.expectOne((request: HttpRequest): boolean => { - // expect(request.url).toEqual('http://localhost:3000/api/users/1'); - // expect(request.method).toBe('DELETE'); - // return true; - // }); - // req.flush(user); - // tick(); - })); - - it('should update a User', fakeAsync(() => { + req.flush({ + id: 1, + last_name: 'renzella', + first_name: 'Jake', + nickname: 'jake', + has_run_first_time_setup: false, + email: 'jake@jake.jake', + student_id: '1', + username: 'test', + opt_in_to_research: true, + receive_portfolio_notifications: false, + receive_feedback_notifications: false, + receive_task_notifications: false, + }); + }); + + // it.skip('should delete a user', () => { + // let user = new User(); + // user.updateFromJson({ + // name: 'jake', lastName: 'renzella', firstName: 'Jake', nickname: 'jake', + // systemRole: 'admin', hasRunFirstTimeSetup: false, email: 'jake@jake.jake', + // student_id: '1', username: 'test', optInToResearch: true, receivePortfolioNotifications: false, + // receiveFeedbackNotifications: false, receiveTaskNotifications: false + // }); + // userService.delete(1).subscribe( + // result => expect(result).toEqual(user, 'expected users') + // ); + // const req = httpMock.expectOne((request: HttpRequest): boolean => { + // expect(request.url).toEqual('http://localhost:3000/api/users/1'); + // expect(request.method).toBe('DELETE'); + // return true; + // }); + // req.flush(user); + // tick(); + // }); + + it('should update a User', () => { const u = new User(); u.id = 1; u.lastName = 'renzella'; @@ -122,9 +152,14 @@ describe('UserService', () => { u.receiveFeedbackNotifications = false; u.receiveTaskNotifications = false; - userService.update(u).subscribe((result) => { - expect(result.firstName).toBe(u.firstName); - }, fail); + userService.update(u).subscribe( + (result) => { + expect(result.firstName).toBe(u.firstName); + }, + (error) => { + throw error; + }, + ); let req = httpMock.expectOne((request: HttpRequest): boolean => { expect(request.url).toEqual('http://localhost:3000/api/users/1'); @@ -132,14 +167,15 @@ describe('UserService', () => { return true; }); req.flush(u); - tick(); u.firstName = 'andrew'; userService.update(u).subscribe({ next: (result) => { expect(result.firstName).toBe('andrew'); }, - error: fail, + error: (error) => { + throw error; + }, }); req = httpMock.expectOne((request: HttpRequest): boolean => { @@ -149,10 +185,9 @@ describe('UserService', () => { }); req.flush(u); - tick(); - })); + }); - it('should cache the result of a get request', fakeAsync(() => { + it('should cache the result of a get request', () => { const user = new User(); user.id = 1; user.lastName = 'renzella'; @@ -177,17 +212,15 @@ describe('UserService', () => { const user2 = user; user2.id = 1; req.flush(user2); - tick(); userService.get(1).subscribe(); httpMock.expectNone((_request: HttpRequest): boolean => { return true; }); - tick(); - })); + }); - it('should cache fetch/get', fakeAsync(() => { + it('should cache fetch/get', () => { let user = new User(); user.id = 1; user.lastName = 'renzella'; @@ -217,9 +250,8 @@ describe('UserService', () => { Object.keys(user).forEach((key) => (user2[key] = user[key])); user2.id = 1; req.flush(user2); - tick(); - let _user3; + let user3: User; // 1 request here userService.fetch(1).subscribe((data) => { @@ -237,10 +269,10 @@ describe('UserService', () => { Object.keys(user2).forEach((key) => (user4[key] = user2[key])); user4.firstName = 'fred'; req.flush(user4); + expect(user3).toBe(user); httpMock.expectNone((_request: HttpRequest): boolean => { return true; }); - tick(); - })); + }); }); diff --git a/src/app/api/services/tii.service.spec.ts b/src/app/api/services/tii.service.spec.ts index 5aefcb548c..4cf7e6de2d 100644 --- a/src/app/api/services/tii.service.spec.ts +++ b/src/app/api/services/tii.service.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {TestBed} from '@angular/core/testing'; import {TiiService} from './tii.service'; diff --git a/src/app/common/directives/drag-drop.directive.spec.ts b/src/app/common/directives/drag-drop.directive.spec.ts index 101b686e5a..50b65a31a7 100644 --- a/src/app/common/directives/drag-drop.directive.spec.ts +++ b/src/app/common/directives/drag-drop.directive.spec.ts @@ -1,3 +1,4 @@ +import {describe, expect, it} from 'vitest'; import {DragDropDirective} from './drag-drop.directive'; describe('DragDropDirective', () => { diff --git a/src/app/common/edit-profile-form/edit-profile-form.component.spec.ts b/src/app/common/edit-profile-form/edit-profile-form.component.spec.ts index 18f1c2815b..a3bfc9285a 100644 --- a/src/app/common/edit-profile-form/edit-profile-form.component.spec.ts +++ b/src/app/common/edit-profile-form/edit-profile-form.component.spec.ts @@ -1,20 +1,40 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MAT_DIALOG_DATA} from '@angular/material/dialog'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {Router} from '@angular/router'; +import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {EditProfileFormComponent} from './edit-profile-form.component'; -describe('EditProfileComponent', () => { +const emptyProvider = {}; + +describe('EditProfileFormComponent', () => { let component: EditProfileFormComponent; let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [EditProfileFormComponent], - }).compileComponents(); + providers: [ + {provide: DoubtfireConstants, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: Router, useValue: emptyProvider}, + {provide: AuthenticationService, useValue: emptyProvider}, + {provide: MAT_DIALOG_DATA, useValue: emptyProvider}, + {provide: MatSnackBar, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(EditProfileFormComponent, {set: {template: ''}}) + .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(EditProfileFormComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/common/f-chip/chip.component.spec.ts b/src/app/common/f-chip/chip.component.spec.ts index 2360020249..23dfb6fbc5 100644 --- a/src/app/common/f-chip/chip.component.spec.ts +++ b/src/app/common/f-chip/chip.component.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {FChipComponent} from './chip.component'; diff --git a/src/app/common/file-viewer/file-viewer.component.spec.ts b/src/app/common/file-viewer/file-viewer.component.spec.ts index d3e256c208..21eeaf7660 100644 --- a/src/app/common/file-viewer/file-viewer.component.spec.ts +++ b/src/app/common/file-viewer/file-viewer.component.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {FileViewerComponent} from './file-viewer.component'; diff --git a/src/app/common/footer/footer.component.spec.ts b/src/app/common/footer/footer.component.spec.ts index a948a43d62..dfe700e594 100644 --- a/src/app/common/footer/footer.component.spec.ts +++ b/src/app/common/footer/footer.component.spec.ts @@ -1,6 +1,19 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {TaskService} from 'src/app/api/services/task.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {SelectedTaskService} from 'src/app/projects/states/dashboard/selected-task.service'; +import {FileDownloaderService} from '../file-downloader/file-downloader.service'; +import {ConfirmationModalService} from '../modals/confirmation-modal/confirmation-modal.service'; +import {DiscussedInClassReasonModalService} from '../modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.service'; +import {TaskAssessmentModalService} from '../modals/task-assessment-modal/task-assessment-modal.service'; +import {AlertService} from '../services/alert.service'; import {FooterComponent} from './footer.component'; +const emptyProvider = {}; + describe('FooterComponent', () => { let component: FooterComponent; let fixture: ComponentFixture; @@ -8,11 +21,26 @@ describe('FooterComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [FooterComponent], - }).compileComponents(); + providers: [ + {provide: SelectedTaskService, useValue: emptyProvider}, + {provide: TaskService, useValue: emptyProvider}, + {provide: FileDownloaderService, useValue: emptyProvider}, + {provide: TaskAssessmentModalService, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: ProjectService, useValue: emptyProvider}, + {provide: ConfirmationModalService, useValue: emptyProvider}, + {provide: DiscussedInClassReasonModalService, useValue: emptyProvider}, + {provide: AlertService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(FooterComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(FooterComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/common/grade-icon/grade-icon.component.spec.ts b/src/app/common/grade-icon/grade-icon.component.spec.ts index fff4eaa353..886ce73c90 100644 --- a/src/app/common/grade-icon/grade-icon.component.spec.ts +++ b/src/app/common/grade-icon/grade-icon.component.spec.ts @@ -1,36 +1,23 @@ -import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {GradeService} from 'src/app/common/services/grade.service'; import {GradeIconComponent} from './grade-icon.component'; describe('GradeIconComponent', () => { let component: GradeIconComponent; let fixture: ComponentFixture; - let gradeServiceStub: Pick; + let gradeService: GradeService; - beforeEach(waitForAsync(() => { - gradeServiceStub = { - grades: ['Pass', 'Credit', 'Distinction', 'High Distinction'], - gradeAcronyms: { - Fail: 'F', - Pass: 'P', - Credit: 'C', - Distinction: 'D', - 'High Distinction': 'HD', - 0: 'P', - 1: 'C', - 2: 'D', - 3: 'HD', - }, - }; + beforeEach(async () => { + gradeService = new GradeService(); - gradeServiceStub.grades[-1] = 'Fail'; - gradeServiceStub.gradeAcronyms[-1] = 'F'; - - TestBed.configureTestingModule({ + await TestBed.configureTestingModule({ declarations: [GradeIconComponent], - providers: [{provide: GradeService, useValue: gradeServiceStub}], + providers: [{provide: GradeService, useValue: gradeService}], + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); - })); + }); beforeEach(() => { fixture = TestBed.createComponent(GradeIconComponent); @@ -42,43 +29,39 @@ describe('GradeIconComponent', () => { expect(component).toBeTruthy(); }); - it('should set the index value when undefined', () => { - component.index = undefined; + it('should show the default icon when the grade is undefined', () => { + component.grade = undefined; component.ngOnInit(); - expect(component.index).toEqual(-1); + expect(component.gradeText).toEqual('Grade'); + expect(component.gradeLetter).toEqual('G'); }); - it('should set the grade to Fail when given invalid input', () => { - component.index = undefined; + it('should show the default icon when given invalid input', () => { component.grade = 'Tomato'; component.ngOnInit(); - expect(component.index).toEqual(-1); - expect(component.gradeText).toEqual('Fail'); - expect(component.gradeLetter).toEqual('F'); + expect(component.gradeText).toEqual('Grade'); + expect(component.gradeLetter).toEqual('G'); }); - it('should appropriate set the grade when passed a grade value', () => { - gradeServiceStub.grades.forEach((grade: string) => { + it('should set the grade when passed a grade name', () => { + Object.entries(gradeService.gradeIndex).forEach(([grade, value]) => { component.grade = grade; - component.index = undefined; component.ngOnInit(); - expect(component.index).toEqual(gradeServiceStub.grades.indexOf(grade)); expect(component.gradeText).toEqual(grade); - expect(component.gradeLetter).toEqual(gradeServiceStub.gradeAcronyms[grade]); + expect(component.gradeLetter).toEqual(gradeService.gradeAcronyms[value]); }); }); - it('should appropriate set the grade when passed a grade index', () => { - gradeServiceStub.grades.forEach((_, index: number) => { - component.index = index - 1; + it('should set the grade when passed a numeric grade', () => { + gradeService.allGradeValues.forEach((grade) => { + component.grade = grade; component.ngOnInit(); - expect(component.index).toEqual(index - 1); - expect(component.gradeText).toEqual(gradeServiceStub.grades[component.index]); - expect(component.gradeLetter).toEqual(gradeServiceStub.gradeAcronyms[component.gradeText]); + expect(component.gradeText).toEqual(gradeService.grades[grade]); + expect(component.gradeLetter).toEqual(gradeService.gradeAcronyms[grade]); }); }); }); diff --git a/src/app/common/header/header.component.spec.ts b/src/app/common/header/header.component.spec.ts index 185d36fae4..b0ee436584 100644 --- a/src/app/common/header/header.component.spec.ts +++ b/src/app/common/header/header.component.spec.ts @@ -1,60 +1,56 @@ -import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; -import {MatMenuModule} from '@angular/material/menu'; -import {BehaviorSubject, Subject} from 'rxjs'; -import {Project, Unit, UnitRole} from 'src/app/api/models/doubtfire-model'; -import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; +import {MediaObserver} from 'ng-flex-layout'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {Router} from '@angular/router'; +import {AuthenticationService} from 'src/app/api/models/doubtfire-model'; +import {SidekiqJobService} from 'src/app/api/services/sidekiq-job.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; import {CheckForUpdateService} from 'src/app/sessions/service-worker-updater/check-for-update.service'; +import {AboutDoubtfireModal} from '../modals/about-doubtfire-modal/about-doubtfire-modal.component'; +import {CalendarModalService} from '../modals/calendar-modal/calendar-modal.service'; +import {QrModalService} from '../modals/qr-modal/qr-modal.service'; +import {SidekiqJobsModalService} from '../modals/sidekiq-jobs-modal/sidekiq-jobs-modal.service'; +import {TutorNotesModalService} from '../modals/tutor-notes-modal/tutor-notes-modal.service'; import {IsActiveUnitRole} from '../pipes/is-active-unit-role.pipe'; import {HeaderComponent} from './header.component'; +const emptyProvider = {}; + describe('HeaderComponent', () => { let component: HeaderComponent; let fixture: ComponentFixture; - // let currentUserStub: jasmine.SpyObj; - // let calendarModalStub: jasmine.SpyObj; - // let aboutDoubtfireModalStub: jasmine.SpyObj; - const isActiveUnitRoleStub: Partial = {}; - const checkForUpdateServiceStub: Partial = {}; - let globalStateServiceStub: Partial; - - beforeEach(waitForAsync(() => { - const showHideHeader: Subject = new Subject(); - const unitRolesSubject: BehaviorSubject = new BehaviorSubject(null); - const projectsSubject: BehaviorSubject = new BehaviorSubject(null); - const currentViewAndEntitySubject$: BehaviorSubject<{ - viewType: ViewType; - entity: Unit | Project | UnitRole; - }> = new BehaviorSubject(null); - - // currentUserStub = { - // role: 'tutor', - // }; - globalStateServiceStub = { - showHideHeader: showHideHeader, - unitRolesSubject: unitRolesSubject, - projectsSubject: projectsSubject, - currentViewAndEntitySubject$: currentViewAndEntitySubject$, - }; - - TestBed.configureTestingModule({ + beforeEach(async () => { + await TestBed.configureTestingModule({ declarations: [HeaderComponent], - imports: [MatMenuModule], providers: [ - // { provide: currentUser, useValue: currentUserStub }, - // { provide: calendarModal, useValue: calendarModalStub }, - // { provide: aboutDoubtfireModal, useValue: aboutDoubtfireModalStub }, - {provide: IsActiveUnitRole, useValue: isActiveUnitRoleStub}, - {provide: CheckForUpdateService, useValue: checkForUpdateServiceStub}, - {provide: GlobalStateService, useValue: globalStateServiceStub}, + {provide: CalendarModalService, useValue: emptyProvider}, + {provide: AboutDoubtfireModal, useValue: emptyProvider}, + {provide: IsActiveUnitRole, useValue: emptyProvider}, + {provide: CheckForUpdateService, useValue: emptyProvider}, + {provide: GlobalStateService, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: AuthenticationService, useValue: emptyProvider}, + {provide: MediaObserver, useValue: emptyProvider}, + {provide: DoubtfireConstants, useValue: emptyProvider}, + {provide: SidekiqJobService, useValue: emptyProvider}, + {provide: SidekiqJobsModalService, useValue: emptyProvider}, + {provide: QrModalService, useValue: emptyProvider}, + {provide: Router, useValue: emptyProvider}, + {provide: TutorNotesModalService, useValue: emptyProvider}, ], - }).compileComponents(); - })); + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(HeaderComponent, {set: {template: ''}}) + .compileComponents(); + }); beforeEach(() => { fixture = TestBed.createComponent(HeaderComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/common/header/task-dropdown/task-dropdown.component.spec.ts b/src/app/common/header/task-dropdown/task-dropdown.component.spec.ts index 298ab4f769..bc4976e202 100644 --- a/src/app/common/header/task-dropdown/task-dropdown.component.spec.ts +++ b/src/app/common/header/task-dropdown/task-dropdown.component.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {RouterTestingModule} from '@angular/router/testing'; import {TaskDropdownComponent} from './task-dropdown.component'; diff --git a/src/app/common/header/unit-dropdown/unit-dropdown.component.spec.ts b/src/app/common/header/unit-dropdown/unit-dropdown.component.spec.ts index b8dbc45dc5..bcf7ff444d 100644 --- a/src/app/common/header/unit-dropdown/unit-dropdown.component.spec.ts +++ b/src/app/common/header/unit-dropdown/unit-dropdown.component.spec.ts @@ -1,22 +1,21 @@ -import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; +import {MediaObserver} from 'ng-flex-layout'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {MatMenuModule} from '@angular/material/menu'; -import {DateService} from 'src/app/common/services/date.service'; import {UnitDropdownComponent} from './unit-dropdown.component'; describe('UnitDropdownComponent', () => { let component: UnitDropdownComponent; let fixture: ComponentFixture; - let dateServiceStub: Pick; - - beforeEach(waitForAsync(() => { - dateServiceStub = {showDate: true}; - - TestBed.configureTestingModule({ + beforeEach(async () => { + await TestBed.configureTestingModule({ declarations: [UnitDropdownComponent], imports: [MatMenuModule], - providers: [{provide: DateService, useValue: dateServiceStub}], + providers: [{provide: MediaObserver, useValue: {isActive: () => false}}], + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); - })); + }); beforeEach(() => { fixture = TestBed.createComponent(UnitDropdownComponent); diff --git a/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts b/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts index aeefe2f6cd..19ed7c2b1a 100644 --- a/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts +++ b/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {HeroSidebarComponent} from './hero-sidebar.component'; diff --git a/src/app/common/modals/edit-profile-dialog/edit-profile-dialog.service.spec.ts b/src/app/common/modals/edit-profile-dialog/edit-profile-dialog.service.spec.ts index 3e7432e180..664fe42413 100644 --- a/src/app/common/modals/edit-profile-dialog/edit-profile-dialog.service.spec.ts +++ b/src/app/common/modals/edit-profile-dialog/edit-profile-dialog.service.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {TestBed} from '@angular/core/testing'; import {EditProfileDialogService} from './edit-profile-dialog.service'; diff --git a/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.spec.ts b/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.spec.ts index 73dcf27fd6..6bedbb62b2 100644 --- a/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.spec.ts +++ b/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.spec.ts @@ -1,5 +1,14 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {SidekiqJobService} from 'src/app/api/services/sidekiq-job.service'; +import {AlertService} from '../../services/alert.service'; import {SidekiqProgressModalComponent} from './sidekiq-progress-modal.component'; +import {SidekiqProgressModalService} from './sidekiq-progress-modal.service'; + +const emptyProvider = {}; describe('SidekiqProgressModalComponent', () => { let component: SidekiqProgressModalComponent; @@ -7,12 +16,24 @@ describe('SidekiqProgressModalComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [SidekiqProgressModalComponent], - }).compileComponents(); + declarations: [SidekiqProgressModalComponent], + providers: [ + {provide: AlertService, useValue: emptyProvider}, + {provide: MAT_DIALOG_DATA, useValue: emptyProvider}, + {provide: MatDialogRef, useValue: emptyProvider}, + {provide: SidekiqJobService, useValue: emptyProvider}, + {provide: SidekiqProgressModalService, useValue: emptyProvider}, + {provide: MatSnackBar, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(SidekiqProgressModalComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(SidekiqProgressModalComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.spec.ts b/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.spec.ts index 80de1d50c9..ff24c419cf 100644 --- a/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.spec.ts +++ b/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.spec.ts @@ -1,28 +1,28 @@ -import {provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; -import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {FileDownloaderService} from '../file-downloader/file-downloader.service'; import {PdfViewerPanelComponent} from './pdf-viewer-panel.component'; +const emptyProvider = {}; + describe('PdfViewerPanelComponent', () => { let component: PdfViewerPanelComponent; let fixture: ComponentFixture; - const fileDownloaderServiceStub: Partial = {}; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ + beforeEach(async () => { + await TestBed.configureTestingModule({ declarations: [PdfViewerPanelComponent], - imports: [], - providers: [ - {provide: FileDownloaderService, useValue: fileDownloaderServiceStub}, - provideHttpClient(withInterceptorsFromDi()), - ], - }).compileComponents(); - })); + providers: [{provide: FileDownloaderService, useValue: emptyProvider}], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(PdfViewerPanelComponent, {set: {template: ''}}) + .compileComponents(); + }); beforeEach(() => { fixture = TestBed.createComponent(PdfViewerPanelComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/common/pipes/humanized-date.pipe.spec.ts b/src/app/common/pipes/humanized-date.pipe.spec.ts index eff49c7a3c..62839a0c26 100644 --- a/src/app/common/pipes/humanized-date.pipe.spec.ts +++ b/src/app/common/pipes/humanized-date.pipe.spec.ts @@ -1,3 +1,4 @@ +import {describe, expect, it} from 'vitest'; import {HumanizedDatePipe} from './humanized-date.pipe'; describe('HumanizedDatePipe', () => { diff --git a/src/app/common/pipes/marked.pipe.spec.ts b/src/app/common/pipes/marked.pipe.spec.ts index 4f50279ce7..5ac4060da5 100644 --- a/src/app/common/pipes/marked.pipe.spec.ts +++ b/src/app/common/pipes/marked.pipe.spec.ts @@ -1,3 +1,4 @@ +import {describe, expect, it} from 'vitest'; import {MarkedPipe} from './marked.pipe'; describe('MarkedPipe', () => { diff --git a/src/app/common/pipes/safe.pipe.spec.ts b/src/app/common/pipes/safe.pipe.spec.ts index 76a111c558..1a1332fcd4 100644 --- a/src/app/common/pipes/safe.pipe.spec.ts +++ b/src/app/common/pipes/safe.pipe.spec.ts @@ -1,3 +1,5 @@ +import {describe, it} from 'vitest'; + describe('SafePipe', () => { it('create an instance', () => { /* empty */ diff --git a/src/app/common/project-progress-bar/project-progress-bar.component.spec.ts b/src/app/common/project-progress-bar/project-progress-bar.component.spec.ts index 2281d48791..0bd437cb91 100644 --- a/src/app/common/project-progress-bar/project-progress-bar.component.spec.ts +++ b/src/app/common/project-progress-bar/project-progress-bar.component.spec.ts @@ -1,3 +1,5 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {ProjectProgressBarComponent} from './project-progress-bar.component'; @@ -8,11 +10,15 @@ describe('ProjectProgressBarComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ProjectProgressBarComponent], - }).compileComponents(); + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(ProjectProgressBarComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(ProjectProgressBarComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/common/scorm-player/scorm-player.component.spec.ts b/src/app/common/scorm-player/scorm-player.component.spec.ts index 88a15d8e31..677d27327f 100644 --- a/src/app/common/scorm-player/scorm-player.component.spec.ts +++ b/src/app/common/scorm-player/scorm-player.component.spec.ts @@ -1,6 +1,15 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {DomSanitizer} from '@angular/platform-browser'; +import {ActivatedRoute} from '@angular/router'; +import {AuthenticationService, UserService} from 'src/app/api/models/doubtfire-model'; +import {ScormAdapterService} from 'src/app/api/services/scorm-adapter.service'; +import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; import {ScormPlayerComponent} from './scorm-player.component'; +const emptyProvider = {}; + describe('ScormPlayerComponent', () => { let component: ScormPlayerComponent; let fixture: ComponentFixture; @@ -8,11 +17,23 @@ describe('ScormPlayerComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ScormPlayerComponent], - }).compileComponents(); + providers: [ + {provide: GlobalStateService, useValue: emptyProvider}, + {provide: ScormAdapterService, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: AuthenticationService, useValue: emptyProvider}, + {provide: DomSanitizer, useValue: emptyProvider}, + {provide: ActivatedRoute, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(ScormPlayerComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(ScormPlayerComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/common/services/alert-service.service.spec.ts b/src/app/common/services/alert-service.service.spec.ts index a2906dab0f..72cf8816c6 100644 --- a/src/app/common/services/alert-service.service.spec.ts +++ b/src/app/common/services/alert-service.service.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {TestBed} from '@angular/core/testing'; import {AlertService} from './alert.service'; diff --git a/src/app/common/services/confetti.service.spec.ts b/src/app/common/services/confetti.service.spec.ts index 52427bb60f..5adbef2d05 100644 --- a/src/app/common/services/confetti.service.spec.ts +++ b/src/app/common/services/confetti.service.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {TestBed} from '@angular/core/testing'; import {ConfettiService} from './confetti.service'; diff --git a/src/app/common/services/date.service.spec.ts b/src/app/common/services/date.service.spec.ts index 8a419a94a4..9f4df416bb 100644 --- a/src/app/common/services/date.service.spec.ts +++ b/src/app/common/services/date.service.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {TestBed} from '@angular/core/testing'; import {DateService} from './date.service'; diff --git a/src/app/common/services/grade.service.spec.ts b/src/app/common/services/grade.service.spec.ts index 60794470b9..0e0122b8f9 100644 --- a/src/app/common/services/grade.service.spec.ts +++ b/src/app/common/services/grade.service.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {TestBed} from '@angular/core/testing'; import {GradeService} from './grade.service'; diff --git a/src/app/common/status-icon/status-icon.component.spec.ts b/src/app/common/status-icon/status-icon.component.spec.ts index 5c61910e3a..15cba56103 100644 --- a/src/app/common/status-icon/status-icon.component.spec.ts +++ b/src/app/common/status-icon/status-icon.component.spec.ts @@ -1,21 +1,24 @@ -import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {StatusIconComponent} from './status-icon.component'; describe('StatusIconComponent', () => { let component: StatusIconComponent; let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ + beforeEach(async () => { + await TestBed.configureTestingModule({ declarations: [StatusIconComponent], - providers: [], - }).compileComponents(); - })); + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(StatusIconComponent, {set: {template: ''}}) + .compileComponents(); + }); beforeEach(() => { fixture = TestBed.createComponent(StatusIconComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/common/user-badge/user-badge.component.spec.ts b/src/app/common/user-badge/user-badge.component.spec.ts index 9ecc96953c..87b04a194d 100644 --- a/src/app/common/user-badge/user-badge.component.spec.ts +++ b/src/app/common/user-badge/user-badge.component.spec.ts @@ -1,3 +1,5 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {UserBadgeComponent} from './user-badge.component'; @@ -8,11 +10,15 @@ describe('UserBadgeComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [UserBadgeComponent], - }).compileComponents(); + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(UserBadgeComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(UserBadgeComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/config/privacy-policy/privacy-policy.spec.ts b/src/app/config/privacy-policy/privacy-policy.spec.ts index bde9c19cd3..4371a4c972 100644 --- a/src/app/config/privacy-policy/privacy-policy.spec.ts +++ b/src/app/config/privacy-policy/privacy-policy.spec.ts @@ -1,15 +1,33 @@ +import {afterEach, beforeEach, describe, expect, it} from 'vitest'; +import {provideHttpClient} from '@angular/common/http'; +import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; import {TestBed} from '@angular/core/testing'; import {PrivacyPolicy} from './privacy-policy'; describe('PrivacyPolicy', () => { let service: PrivacyPolicy; + let httpMock: HttpTestingController; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [provideHttpClient(), provideHttpClientTesting()], + }); service = TestBed.inject(PrivacyPolicy); + httpMock = TestBed.inject(HttpTestingController); }); - it('should be created', () => { + afterEach(() => { + httpMock.verify(); + }); + + it('should load the privacy and plagiarism policies', () => { + httpMock + .expectOne('http://localhost:3000/api/settings/privacy') + .flush({privacy: 'Privacy policy', plagiarism: 'Plagiarism policy'}); + expect(service).toBeTruthy(); + expect(service.privacy).toBe('Privacy policy'); + expect(service.plagiarism).toBe('Plagiarism policy'); + expect(service.loaded).toBe(true); }); }); diff --git a/src/app/errors/states/unauthorised/unauthorised.component.spec.ts b/src/app/errors/states/unauthorised/unauthorised.component.spec.ts index 83c64c3549..b0902a02aa 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.spec.ts +++ b/src/app/errors/states/unauthorised/unauthorised.component.spec.ts @@ -1,6 +1,11 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {Location} from '@angular/common'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {UnauthorisedComponent} from './unauthorised.component'; +const emptyProvider = {}; + describe('UnauthorisedComponent', () => { let component: UnauthorisedComponent; let fixture: ComponentFixture; @@ -8,13 +13,16 @@ describe('UnauthorisedComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [UnauthorisedComponent], - }).compileComponents(); + providers: [{provide: Location, useValue: emptyProvider}], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(UnauthorisedComponent, {set: {template: ''}}) + .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(UnauthorisedComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/eula/accept-eula/accept-eula.component.spec.ts b/src/app/eula/accept-eula/accept-eula.component.spec.ts index 8a896ee187..9912d785e5 100644 --- a/src/app/eula/accept-eula/accept-eula.component.spec.ts +++ b/src/app/eula/accept-eula/accept-eula.component.spec.ts @@ -1,6 +1,20 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {Router} from '@angular/router'; +import {EMPTY} from 'rxjs'; +import {UserService} from 'src/app/api/models/doubtfire-model'; +import {TiiService} from 'src/app/api/services/tii.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {AcceptEulaComponent} from './accept-eula.component'; +const constantsStub = { + ExternalName: EMPTY, + IsTiiEnabled: EMPTY, +}; +const emptyProvider = {}; + describe('AcceptEulaComponent', () => { let component: AcceptEulaComponent; let fixture: ComponentFixture; @@ -8,11 +22,22 @@ describe('AcceptEulaComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [AcceptEulaComponent], - }).compileComponents(); + providers: [ + {provide: DoubtfireConstants, useValue: constantsStub}, + {provide: TiiService, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: AlertService, useValue: emptyProvider}, + {provide: Router, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(AcceptEulaComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(AcceptEulaComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/home/splash-screen/splash-screen.component.spec.ts b/src/app/home/splash-screen/splash-screen.component.spec.ts index a1337fe240..6f13f45e5f 100644 --- a/src/app/home/splash-screen/splash-screen.component.spec.ts +++ b/src/app/home/splash-screen/splash-screen.component.spec.ts @@ -1,32 +1,32 @@ -import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; -import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; -import {BehaviorSubject} from 'rxjs'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; +import {LoadingService} from './LoadingService.service'; import {SplashScreenComponent} from './splash-screen.component'; +const emptyProvider = {}; + describe('SplashScreenComponent', () => { let component: SplashScreenComponent; let fixture: ComponentFixture; - let globalStateServiceStub: Partial; - - beforeEach(waitForAsync(() => { - const isLoadingSubject: BehaviorSubject = new BehaviorSubject(true); - globalStateServiceStub = { - isLoadingSubject: isLoadingSubject, - }; - - TestBed.configureTestingModule({ + beforeEach(async () => { + await TestBed.configureTestingModule({ declarations: [SplashScreenComponent], - imports: [BrowserAnimationsModule], - providers: [{provide: GlobalStateService, useValue: globalStateServiceStub}], - }).compileComponents(); - })); + providers: [ + {provide: GlobalStateService, useValue: emptyProvider}, + {provide: LoadingService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(SplashScreenComponent, {set: {template: ''}}) + .compileComponents(); + }); beforeEach(() => { fixture = TestBed.createComponent(SplashScreenComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.spec.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.spec.ts index d1b100354a..ced1674ccc 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.spec.ts @@ -1,6 +1,12 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {TaskService} from 'src/app/api/services/task.service'; +import {GradeService} from 'src/app/common/services/grade.service'; import {TaskAssessmentCardComponent} from './task-assessment-card.component'; +const emptyProvider = {}; + describe('TaskAssessmentCardComponent', () => { let component: TaskAssessmentCardComponent; let fixture: ComponentFixture; @@ -8,11 +14,19 @@ describe('TaskAssessmentCardComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [TaskAssessmentCardComponent], - }).compileComponents(); + providers: [ + {provide: TaskService, useValue: emptyProvider}, + {provide: GradeService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(TaskAssessmentCardComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(TaskAssessmentCardComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.spec.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.spec.ts index 1b973c53f4..ea4330e5de 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.spec.ts @@ -1,3 +1,5 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {TaskDueCardComponent} from './task-due-card.component'; @@ -8,11 +10,15 @@ describe('TaskDueCardComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [TaskDueCardComponent], - }).compileComponents(); + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(TaskDueCardComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(TaskDueCardComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.spec.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.spec.ts index c1f5ef4abf..d377730a00 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.spec.ts @@ -1,6 +1,22 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {ActivatedRoute} from '@angular/router'; +import {EMPTY} from 'rxjs'; +import {TaskService} from 'src/app/api/services/task.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {ExtensionModalService} from 'src/app/common/modals/extension-modal/extension-modal.service'; +import {QrModalService} from 'src/app/common/modals/qr-modal/qr-modal.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {FeedbackAppealModalService} from 'src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.service'; +import {SubmissionTypeModalService} from 'src/app/tasks/modals/submission-type-modal/submission-type-modal.service'; import {TaskStatusCardComponent} from './task-status-card.component'; +const taskServiceStub = { + taskStatusUpdated$: EMPTY, +}; +const emptyProvider = {}; + describe('TaskStatusCardComponent', () => { let component: TaskStatusCardComponent; let fixture: ComponentFixture; @@ -8,11 +24,25 @@ describe('TaskStatusCardComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [TaskStatusCardComponent], - }).compileComponents(); + providers: [ + {provide: ExtensionModalService, useValue: emptyProvider}, + {provide: TaskService, useValue: taskServiceStub}, + {provide: ActivatedRoute, useValue: emptyProvider}, + {provide: QrModalService, useValue: emptyProvider}, + {provide: DoubtfireConstants, useValue: emptyProvider}, + {provide: SubmissionTypeModalService, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: FeedbackAppealModalService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(TaskStatusCardComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(TaskStatusCardComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.spec.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.spec.ts index bdfd4708ab..21b537a0ca 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.spec.ts @@ -1,6 +1,13 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {TaskService} from 'src/app/api/services/task.service'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {AlertService} from 'src/app/common/services/alert.service'; import {TaskSubmissionCardComponent} from './task-submission-card.component'; +const emptyProvider = {}; + describe('TaskSubmissionCardComponent', () => { let component: TaskSubmissionCardComponent; let fixture: ComponentFixture; @@ -8,11 +15,20 @@ describe('TaskSubmissionCardComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [TaskSubmissionCardComponent], - }).compileComponents(); + providers: [ + {provide: TaskService, useValue: emptyProvider}, + {provide: AlertService, useValue: emptyProvider}, + {provide: FileDownloaderService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(TaskSubmissionCardComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(TaskSubmissionCardComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.spec.ts index 4695f366d0..195716d110 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.spec.ts @@ -1,6 +1,15 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {ActivatedRoute} from '@angular/router'; +import {TaskService} from 'src/app/api/services/task.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {SelectedTaskService} from '../../selected-task.service'; import {TaskDashboardComponent} from './task-dashboard.component'; +const emptyProvider = {}; + describe('TaskDashboardComponent', () => { let component: TaskDashboardComponent; let fixture: ComponentFixture; @@ -8,11 +17,22 @@ describe('TaskDashboardComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [TaskDashboardComponent], - }).compileComponents(); + providers: [ + {provide: TaskService, useValue: emptyProvider}, + {provide: FileDownloaderService, useValue: emptyProvider}, + {provide: ActivatedRoute, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: SelectedTaskService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(TaskDashboardComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(TaskDashboardComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/projects/states/dashboard/selected-task.service.spec.ts b/src/app/projects/states/dashboard/selected-task.service.spec.ts index c1ce156e72..cecaef3b82 100644 --- a/src/app/projects/states/dashboard/selected-task.service.spec.ts +++ b/src/app/projects/states/dashboard/selected-task.service.spec.ts @@ -1,11 +1,22 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {TestBed} from '@angular/core/testing'; +import {TaskService} from 'src/app/api/services/task.service'; +import {GlobalStateService} from '../index/global-state.service'; import {SelectedTaskService} from './selected-task.service'; +const emptyProvider = {}; + describe('SelectedTaskService', () => { let service: SelectedTaskService; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [ + SelectedTaskService, + {provide: TaskService, useValue: emptyProvider}, + {provide: GlobalStateService, useValue: emptyProvider}, + ], + }); service = TestBed.inject(SelectedTaskService); }); diff --git a/src/app/projects/states/staff-notes/staff-notes.component.spec.ts b/src/app/projects/states/staff-notes/staff-notes.component.spec.ts index 150a9e5afd..270c10d536 100644 --- a/src/app/projects/states/staff-notes/staff-notes.component.spec.ts +++ b/src/app/projects/states/staff-notes/staff-notes.component.spec.ts @@ -1,18 +1,36 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {UserService} from 'src/app/api/models/doubtfire-model'; +import {StaffNoteService} from 'src/app/api/services/staff-note.service'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; import {StaffNotesComponent} from './staff-notes.component'; +const emptyProvider = {}; + describe('StaffNotesComponent', () => { let component: StaffNotesComponent; let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [StaffNotesComponent], - }).compileComponents(); + declarations: [StaffNotesComponent], + providers: [ + {provide: UserService, useValue: emptyProvider}, + {provide: StaffNoteService, useValue: emptyProvider}, + {provide: AlertService, useValue: emptyProvider}, + {provide: ConfirmationModalService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(StaffNotesComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(StaffNotesComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.spec.ts b/src/app/projects/states/tutor-discussion/tutor-discussion.component.spec.ts index 9f471f8d55..75306dc282 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.spec.ts +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.spec.ts @@ -1,18 +1,55 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatDialog} from '@angular/material/dialog'; +import {ActivatedRoute, Router} from '@angular/router'; +import { + AuthenticationService, + ProjectService, + TaskCommentService, + TaskService, + UnitService, + UserService, +} from 'src/app/api/models/doubtfire-model'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {DiscussedInClassReasonModalService} from 'src/app/common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GradeService} from 'src/app/common/services/grade.service'; import {TutorDiscussionComponent} from './tutor-discussion.component'; +const emptyProvider = {}; + describe('TutorDiscussionComponent', () => { let component: TutorDiscussionComponent; let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [TutorDiscussionComponent], - }).compileComponents(); + declarations: [TutorDiscussionComponent], + providers: [ + {provide: UnitService, useValue: emptyProvider}, + {provide: AuthenticationService, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: ProjectService, useValue: emptyProvider}, + {provide: GradeService, useValue: emptyProvider}, + {provide: Router, useValue: emptyProvider}, + {provide: ActivatedRoute, useValue: emptyProvider}, + {provide: AlertService, useValue: emptyProvider}, + {provide: ConfirmationModalService, useValue: emptyProvider}, + {provide: DiscussedInClassReasonModalService, useValue: emptyProvider}, + {provide: TaskCommentService, useValue: emptyProvider}, + {provide: TaskService, useValue: emptyProvider}, + {provide: MatDialog, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(TutorDiscussionComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(TutorDiscussionComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/sessions/states/sign-in/sign-in.component.spec.ts b/src/app/sessions/states/sign-in/sign-in.component.spec.ts index ccc7662322..f80e7c1961 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.spec.ts +++ b/src/app/sessions/states/sign-in/sign-in.component.spec.ts @@ -1,6 +1,17 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {HttpClient} from '@angular/common/http'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {ActivatedRoute, Router} from '@angular/router'; +import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; import {SignInComponent} from './sign-in.component'; +const emptyProvider = {}; + describe('SignInComponent', () => { let component: SignInComponent; let fixture: ComponentFixture; @@ -8,13 +19,25 @@ describe('SignInComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [SignInComponent], - }).compileComponents(); + providers: [ + {provide: AuthenticationService, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: Router, useValue: emptyProvider}, + {provide: ActivatedRoute, useValue: emptyProvider}, + {provide: DoubtfireConstants, useValue: emptyProvider}, + {provide: HttpClient, useValue: emptyProvider}, + {provide: GlobalStateService, useValue: emptyProvider}, + {provide: AlertService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(SignInComponent, {set: {template: ''}}) + .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(SignInComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/sessions/transition-hooks.service.spec.ts b/src/app/sessions/transition-hooks.service.spec.ts deleted file mode 100644 index 3addee99f2..0000000000 --- a/src/app/sessions/transition-hooks.service.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {TestBed} from '@angular/core/testing'; -import {TransitionHooksService} from './transition-hooks.service'; - -describe('TransitionHooksService', () => { - let service: TransitionHooksService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(TransitionHooksService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.spec.ts b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.spec.ts index ff7c7d796a..5ee4e03498 100644 --- a/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.spec.ts +++ b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.spec.ts @@ -1,4 +1,6 @@ -import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {GradeService} from 'src/app/common/services/grade.service'; import {GradeTaskModalComponent} from './grade-task-modal.component'; @@ -6,41 +8,25 @@ import {GradeTaskModalComponent} from './grade-task-modal.component'; describe('GradeTaskModalComponent', () => { let component: GradeTaskModalComponent; let fixture: ComponentFixture; - let gradeServiceStub: Pick; + let gradeServiceStub: GradeService; let dialogRefMock: {close: () => void}; let dialogDataStub: { task: { grade?: number; - quality_pts?: number; - definition: {max_quality_pts?: number}; + qualityPts?: number; + definition: {maxQualityPts?: number}; }; }; - beforeEach(waitForAsync(() => { - gradeServiceStub = { - grades: ['Pass', 'Credit', 'Distinction', 'High Distinction'], - gradeAcronyms: { - Fail: 'F', - Pass: 'P', - Credit: 'C', - Distinction: 'D', - 'High Distinction': 'HD', - 0: 'P', - 1: 'C', - 2: 'D', - 3: 'HD', - }, - allGradeValues: [-1, 0, 1, 2, 3], - }; - gradeServiceStub.grades[-1] = 'Fail'; - gradeServiceStub.gradeAcronyms[-1] = 'F'; + beforeEach(async () => { + gradeServiceStub = new GradeService(); dialogDataStub = { task: { grade: undefined, - quality_pts: undefined, + qualityPts: undefined, definition: { - max_quality_pts: undefined, + maxQualityPts: undefined, }, }, }; @@ -51,15 +37,16 @@ describe('GradeTaskModalComponent', () => { }, }; - TestBed.configureTestingModule({ + await TestBed.configureTestingModule({ declarations: [GradeTaskModalComponent], providers: [ {provide: GradeService, useValue: gradeServiceStub}, {provide: MatDialogRef, useValue: dialogRefMock}, {provide: MAT_DIALOG_DATA, useValue: dialogDataStub}, ], + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); - })); + }); beforeEach(() => { fixture = TestBed.createComponent(GradeTaskModalComponent); @@ -72,7 +59,7 @@ describe('GradeTaskModalComponent', () => { }); it('should return rating & grade when closed', () => { - spyOn(component.dialogRef, 'close'); + vi.spyOn(component.dialogRef, 'close'); component.rating = 5; component.selectedGrade = 2; @@ -85,7 +72,7 @@ describe('GradeTaskModalComponent', () => { }); it('should dismiss', () => { - spyOn(component.dialogRef, 'close'); + vi.spyOn(component.dialogRef, 'close'); component.dismiss(); expect(component.dialogRef.close).toHaveBeenCalled(); }); @@ -96,18 +83,18 @@ describe('GradeTaskModalComponent', () => { it('should accept a new task object', () => { const newRatingTask = { grade: undefined, - quality_pts: 5, + qualityPts: 5, definition: { - max_quality_pts: 10, + maxQualityPts: 10, }, }; dialogDataStub.task = newRatingTask; component.ngOnInit(); expect(component.task).toEqual(newRatingTask); - expect(component.rating).toEqual(newRatingTask.quality_pts); - expect(component.selectedGrade).toEqual(newRatingTask.grade); - expect(component.totalRating).toEqual(newRatingTask.definition.max_quality_pts); + expect(component.rating).toEqual(newRatingTask.qualityPts); + expect(component.selectedGrade).toEqual(0); + expect(component.totalRating).toEqual(newRatingTask.definition.maxQualityPts); }); it('should not allow a rating higher than the max rating', () => { @@ -167,9 +154,9 @@ describe('GradeTaskModalComponent', () => { it('should not accept a new invalid grade', () => { component.ngOnInit(); component.updateGrade(10); - expect(component.selectedGrade).toEqual(undefined); + expect(component.selectedGrade).toEqual(0); component.updateGrade(-10); - expect(component.selectedGrade).toEqual(undefined); + expect(component.selectedGrade).toEqual(0); }); }); diff --git a/src/app/tasks/task-comments-viewer/comment-bubble-action/comment-bubble-action.component.spec.ts b/src/app/tasks/task-comments-viewer/comment-bubble-action/comment-bubble-action.component.spec.ts index 5bb9a879fa..7e7508a7d2 100644 --- a/src/app/tasks/task-comments-viewer/comment-bubble-action/comment-bubble-action.component.spec.ts +++ b/src/app/tasks/task-comments-viewer/comment-bubble-action/comment-bubble-action.component.spec.ts @@ -1,33 +1,31 @@ -// import { async, ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -// import { TaskComment } from 'src/app/api/models/doubtfire-model'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {CommentBubbleActionComponent} from './comment-bubble-action.component'; -// import { CommentBubbleActionComponent } from './comment-bubble-action.component'; +const emptyProvider = {}; -// describe('CommentBubbleActionComponent', () => { -// let component: CommentBubbleActionComponent; -// let fixture: ComponentFixture; -// let taskComment: TaskComment; +describe('CommentBubbleActionComponent', () => { + let component: CommentBubbleActionComponent; + let fixture: ComponentFixture; -// beforeEach( -// waitForAsync(() => { -// TestBed.configureTestingModule({ -// declarations: [CommentBubbleActionComponent], -// }).compileComponents(); -// }) -// ); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [CommentBubbleActionComponent], + providers: [{provide: ConfirmationModalService, useValue: emptyProvider}], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(CommentBubbleActionComponent, {set: {template: ''}}) + .compileComponents(); + }); -// beforeEach(() => { -// fixture = TestBed.createComponent(CommentBubbleActionComponent); -// component = fixture.componentInstance; + beforeEach(() => { + fixture = TestBed.createComponent(CommentBubbleActionComponent); + component = fixture.componentInstance; + }); -// taskComment = jasmine.createSpyObj('TaskComment', ['currentUserCanEdit']); -// taskComment.currentUserCanEdit.and.returnValue(false); -// component.comment = taskComment; - -// fixture.detectChanges(); -// }); - -// it('should create', () => { -// expect(component).toBeTruthy(); -// }); -// }); + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.spec.ts b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.spec.ts index d28e56ff6b..908c92e587 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.spec.ts +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.spec.ts @@ -1,47 +1,50 @@ -// import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -// import { EventEmitter } from '@angular/core'; -// import { alertService, commentsModal } from 'src/app/ajs-upgraded-providers'; -// import { TaskComment, TaskCommentService } from 'src/app/api/models/doubtfire-model'; -// import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {EMPTY} from 'rxjs'; +import {TaskCommentService, TaskService, UserService} from 'src/app/api/models/doubtfire-model'; +import {FeedbackTemplateService} from 'src/app/api/services/feedback-template.service'; +import {CommentsModalService} from 'src/app/common/modals/comments-modal/comments-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {TaskCommentsViewerComponent} from './task-comments-viewer.component'; -// import { TaskCommentsViewerComponent } from './task-comments-viewer.component'; +const taskCommentServiceStub = { + commentAdded$: EMPTY, +}; +const taskServiceStub = { + taskStatusUpdated$: EMPTY, +}; +const emptyProvider = {}; -// describe('TaskCommentsViewerComponent', () => { -// let component: TaskCommentsViewerComponent; -// let fixture: ComponentFixture; -// let taskCommentServiceStub: Partial; -// let doubtfireConstantsStub: Partial; -// let commentsModalStub: jasmine.SpyObj; -// let taskStub: jasmine.SpyObj; -// let alertServiceStub: jasmine.SpyObj; +describe('TaskCommentsViewerComponent', () => { + let component: TaskCommentsViewerComponent; + let fixture: ComponentFixture; -// beforeEach( -// waitForAsync(() => { -// const commentAdded: EventEmitter = new EventEmitter(); -// taskCommentServiceStub = { -// commentAdded$: commentAdded, -// }; + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [TaskCommentsViewerComponent], + providers: [ + {provide: TaskCommentService, useValue: taskCommentServiceStub}, + {provide: FeedbackTemplateService, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: TaskService, useValue: taskServiceStub}, + {provide: DoubtfireConstants, useValue: emptyProvider}, + {provide: CommentsModalService, useValue: emptyProvider}, + {provide: AlertService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(TaskCommentsViewerComponent, {set: {template: ''}}) + .compileComponents(); + }); -// TestBed.configureTestingModule({ -// declarations: [TaskCommentsViewerComponent], -// providers: [ -// { provide: TaskCommentService, useValue: taskCommentServiceStub }, -// { provide: DoubtfireConstants, useValue: doubtfireConstantsStub }, -// { provide: commentsModal, useValue: commentsModalStub }, -// { provide: Task, useValue: taskStub }, -// { provide: alertService, useValue: alertServiceStub }, -// ], -// }).compileComponents(); -// }) -// ); + beforeEach(() => { + fixture = TestBed.createComponent(TaskCommentsViewerComponent); + component = fixture.componentInstance; + }); -// beforeEach(() => { -// fixture = TestBed.createComponent(TaskCommentsViewerComponent); -// component = fixture.componentInstance; -// fixture.detectChanges(); -// }); - -// it('should create', () => { -// expect(component).toBeTruthy(); -// }); -// }); + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/test.service.spec.ts b/src/app/test.service.spec.ts index c8a75e8168..6c5f5a280c 100644 --- a/src/app/test.service.spec.ts +++ b/src/app/test.service.spec.ts @@ -1,3 +1,4 @@ +import {beforeEach, describe, expect, it} from 'vitest'; import {TestBed} from '@angular/core/testing'; import {TestService} from './test.service'; diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts index 0563c6366a..c6869756c4 100644 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.spec.ts @@ -1,22 +1,35 @@ -import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {CampusService} from 'src/app/api/services/campus.service'; +import {AlertService} from 'src/app/common/services/alert.service'; import {UnitStudentEnrolmentModalComponent} from './unit-student-enrolment-modal.component'; -describe('RolloverTeachingPeriodModalComponent', () => { +const emptyProvider = {}; + +describe('UnitStudentEnrolmentModalComponent', () => { let component: UnitStudentEnrolmentModalComponent; let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ + beforeEach(async () => { + await TestBed.configureTestingModule({ declarations: [UnitStudentEnrolmentModalComponent], - providers: [{provide: DoubtfireConstants}], - }).compileComponents(); - })); + providers: [ + {provide: MatDialogRef, useValue: emptyProvider}, + {provide: MAT_DIALOG_DATA, useValue: emptyProvider}, + {provide: AlertService, useValue: emptyProvider}, + {provide: CampusService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(UnitStudentEnrolmentModalComponent, {set: {template: ''}}) + .compileComponents(); + }); beforeEach(() => { fixture = TestBed.createComponent(UnitStudentEnrolmentModalComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.spec.ts b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.spec.ts index fbf1d43a79..e80775b77a 100644 --- a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.spec.ts +++ b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.spec.ts @@ -1,63 +1,57 @@ -// import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -// import { MatDialogModule } from '@angular/material/dialog'; -// import { MatMenuModule } from '@angular/material/menu'; -// import { alertService, currentUser, groupService, taskDefinition, Unit } from 'src/app/ajs-upgraded-providers'; - -// import { StaffTaskListComponent } from './staff-task-list.component'; - -// describe('StaffTaskListComponent', () => { -// let component: StaffTaskListComponent; -// let fixture: ComponentFixture; -// let taskDefinitionStub: jasmine.SpyObj; -// let unitStub: jasmine.SpyObj; -// let currentUserStub: jasmine.SpyObj; -// let groupServiceStub: jasmine.SpyObj; -// let alertServiceStub: jasmine.SpyObj; - -// beforeEach( -// waitForAsync(() => { -// unitStub = { -// tasksForDefinition: [], -// }; -// currentUserStub = { -// profile: { name: 'Bob Marley' }, -// }; - -// TestBed.configureTestingModule({ -// declarations: [StaffTaskListComponent], -// imports: [ -// MatDialogModule, -// MatMenuModule -// ], -// providers: [ -// { provide: taskDefinition, useValue: taskDefinitionStub }, -// { provide: currentUser, useValue: currentUserStub }, -// { provide: groupService, useValue: groupServiceStub }, -// { provide: alertService, useValue: alertServiceStub }, -// ], -// }).compileComponents(); -// }) -// ); - -// beforeEach(() => { -// fixture = TestBed.createComponent(StaffTaskListComponent); -// component = fixture.componentInstance; - -// component.taskData = { -// selectedTask: null, -// }; -// component.unit = { -// tutorialsForUserName: () => [], -// tutorials: [], -// }; -// component.unitRole = { -// role: 'Convenor', -// }; - -// fixture.detectChanges(); -// }); - -// it('should create', () => { -// expect(component).toBeTruthy(); -// }); -// }); +import {HotkeysService} from '@ngneat/hotkeys'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatDialog} from '@angular/material/dialog'; +import {ActivatedRoute, Router} from '@angular/router'; +import {UserService} from 'src/app/api/models/doubtfire-model'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {CsvResultModalService} from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; +import {CsvUploadModalService} from 'src/app/common/modals/csv-upload-modal/csv-upload-modal.service'; +import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {SelectedTaskService} from 'src/app/projects/states/dashboard/selected-task.service'; +import {StaffTaskListComponent} from './staff-task-list.component'; + +const hotkeysServiceStub = { + removeShortcuts: () => {}, +}; +const emptyProvider = {}; + +describe('StaffTaskListComponent', () => { + let component: StaffTaskListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [StaffTaskListComponent], + providers: [ + {provide: SelectedTaskService, useValue: emptyProvider}, + {provide: AlertService, useValue: emptyProvider}, + {provide: FileDownloaderService, useValue: emptyProvider}, + {provide: MatDialog, useValue: emptyProvider}, + {provide: CsvUploadModalService, useValue: emptyProvider}, + {provide: CsvResultModalService, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: HotkeysService, useValue: hotkeysServiceStub}, + {provide: Router, useValue: emptyProvider}, + {provide: ActivatedRoute, useValue: emptyProvider}, + {provide: TaskDefinitionService, useValue: emptyProvider}, + {provide: SidekiqProgressModalService, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(StaffTaskListComponent, {set: {template: ''}}) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(StaffTaskListComponent); + component = fixture.componentInstance; + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/units/states/tasks/inbox/inbox.component.spec.ts b/src/app/units/states/tasks/inbox/inbox.component.spec.ts index 9112a31a49..408a72a359 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.spec.ts +++ b/src/app/units/states/tasks/inbox/inbox.component.spec.ts @@ -1,6 +1,26 @@ +import {HotkeysService} from '@ngneat/hotkeys'; +import {MediaObserver} from 'ng-flex-layout'; +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatDialog} from '@angular/material/dialog'; +import {Router} from '@angular/router'; +import {EMPTY} from 'rxjs'; +import {UserService} from 'src/app/api/services/user.service'; +import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {SelectedTaskService} from 'src/app/projects/states/dashboard/selected-task.service'; import {InboxComponent} from './inbox.component'; +const selectedTaskServiceStub = { + currentPdfUrl$: EMPTY, + selectedTask$: EMPTY, +}; +const hotkeysServiceStub = { + removeShortcuts: () => {}, +}; +const emptyProvider = {}; + describe('InboxComponent', () => { let component: InboxComponent; let fixture: ComponentFixture; @@ -8,11 +28,25 @@ describe('InboxComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [InboxComponent], - }).compileComponents(); + providers: [ + {provide: HotkeysService, useValue: hotkeysServiceStub}, + {provide: SelectedTaskService, useValue: selectedTaskServiceStub}, + {provide: MediaObserver, useValue: emptyProvider}, + {provide: FileDownloaderService, useValue: emptyProvider}, + {provide: Router, useValue: emptyProvider}, + {provide: MatDialog, useValue: emptyProvider}, + {provide: UserService, useValue: emptyProvider}, + {provide: DoubtfireConstants, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(InboxComponent, {set: {template: ''}}) + .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(InboxComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.spec.ts b/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.spec.ts index e69de29bb2..2767eb6e97 100644 --- a/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.spec.ts +++ b/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.spec.ts @@ -0,0 +1,27 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {FTaskSheetViewComponent} from './task-sheet-view.component'; + +describe('FTaskSheetViewComponent', () => { + let component: FTaskSheetViewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [FTaskSheetViewComponent], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(FTaskSheetViewComponent, {set: {template: ''}}) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FTaskSheetViewComponent); + component = fixture.componentInstance; + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts index 09f4be518b..70a5cbc79d 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts @@ -1,17 +1,31 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {ActivatedRoute, Router} from '@angular/router'; import {FUnitTaskListComponent} from './unit-task-list.component'; +const emptyProvider = {}; + describe('FUnitTaskListComponent', () => { let component: FUnitTaskListComponent; let fixture: ComponentFixture; - beforeEach(() => { - TestBed.configureTestingModule({ + beforeEach(async () => { + await TestBed.configureTestingModule({ declarations: [FUnitTaskListComponent], - }); + providers: [ + {provide: Router, useValue: emptyProvider}, + {provide: ActivatedRoute, useValue: emptyProvider}, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(FUnitTaskListComponent, {set: {template: ''}}) + .compileComponents(); + }); + + beforeEach(() => { fixture = TestBed.createComponent(FUnitTaskListComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { diff --git a/src/app/welcome/welcome.component.spec.ts b/src/app/welcome/welcome.component.spec.ts index 8c834e5b2b..4725c4d866 100644 --- a/src/app/welcome/welcome.component.spec.ts +++ b/src/app/welcome/welcome.component.spec.ts @@ -1,13 +1,58 @@ +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {Router} from '@angular/router'; +import {BehaviorSubject} from 'rxjs'; +import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; import {WelcomeComponent} from './welcome.component'; describe('WelcomeComponent', () => { let component: WelcomeComponent; let fixture: ComponentFixture; + let afterAuthCallback: ((result: boolean) => void) | undefined; + let routerStub: {navigateByUrl: ReturnType}; + let globalStateStub: {hideHeader: ReturnType}; + let userServiceStub: {currentUser: {hasRunFirstTimeSetup: boolean}}; beforeEach(async () => { + afterAuthCallback = undefined; + routerStub = { + navigateByUrl: vi.fn(), + }; + globalStateStub = { + hideHeader: vi.fn(), + }; + userServiceStub = { + currentUser: { + hasRunFirstTimeSetup: false, + }, + }; + await TestBed.configureTestingModule({ declarations: [WelcomeComponent], + providers: [ + { + provide: DoubtfireConstants, + useValue: { + ExternalName: new BehaviorSubject('OnTrack'), + }, + }, + {provide: GlobalStateService, useValue: globalStateStub}, + { + provide: AuthenticationService, + useValue: { + afterAuthCall: vi.fn((callback: (result: boolean) => void) => { + afterAuthCallback = callback; + }), + }, + }, + {provide: Router, useValue: routerStub}, + {provide: UserService, useValue: userServiceStub}, + ], + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -20,4 +65,22 @@ describe('WelcomeComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should hide the header while the welcome page is active', () => { + expect(globalStateStub.hideHeader).toHaveBeenCalled(); + }); + + it('should redirect unauthenticated users to sign in', () => { + expect(afterAuthCallback).toBeDefined(); + + afterAuthCallback?.(false); + + expect(routerStub.navigateByUrl).toHaveBeenCalledWith('/sign_in'); + }); + + it('should show the expected welcome heading', () => { + const element: HTMLElement = fixture.nativeElement; + + expect(element.textContent).toContain('Welcome to OnTrack'); + }); }); diff --git a/src/karma-ci.conf.js b/src/karma-ci.conf.js deleted file mode 100644 index 4393b51ebf..0000000000 --- a/src/karma-ci.conf.js +++ /dev/null @@ -1,32 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/0.13/config/configuration-file.html - -module.exports = function (config) { - config.set({ - logLevel: config.LOG_DEBUG, - basePath: '', - frameworks: ['jasmine', '@angular-devkit/build-angular'], - plugins: [ - require('karma-jasmine'), - require('karma-chrome-launcher'), - require('karma-jasmine-html-reporter'), - require('karma-coverage-istanbul-reporter'), - require('@angular-devkit/build-angular/plugins/karma'), - ], - client: { - clearContext: false, // leave Jasmine Spec Runner output visible in browser - }, - coverageIstanbulReporter: { - dir: require('path').join(__dirname, 'coverage'), - reports: ['html', 'lcovonly'], - fixWebpackSourcePaths: true, - }, - angularCli: { - environment: 'dev', - }, - reporters: ['progress', 'kjhtml'], - port: 9876, - singleRun: true, - browsers: ['ChromeHeadless'], - }); -}; diff --git a/src/karma.conf.js b/src/karma.conf.js deleted file mode 100644 index d5edcff1cb..0000000000 --- a/src/karma.conf.js +++ /dev/null @@ -1,40 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/0.13/config/configuration-file.html - -module.exports = function (config) { - config.set({ - logLevel: config.LOG_DEBUG, - basePath: '', - frameworks: ['jasmine', '@angular-devkit/build-angular'], - plugins: [ - require('karma-jasmine'), - require('karma-chrome-launcher'), - require('karma-jasmine-html-reporter'), - require('karma-coverage-istanbul-reporter'), - - ], - client: { - clearContext: false, // leave Jasmine Spec Runner output visible in browser - }, - coverageIstanbulReporter: { - dir: require('path').join(__dirname, 'coverage'), - reports: ['html', 'lcovonly'], - fixWebpackSourcePaths: true, - }, - angularCli: { - environment: 'dev', - }, - reporters: ['progress', 'kjhtml'], - port: 9876, - colors: true, - autoWatch: true, - browsers: ['Chrome'], - singleRun: false, - customLaunchers: { - ChromeDebug: { - base: 'Chrome', - flags: ['--remote-debugging-port=9333'], - }, - }, - }); -}; diff --git a/src/test.ts b/src/test.ts deleted file mode 100644 index 5f03b6f001..0000000000 --- a/src/test.ts +++ /dev/null @@ -1,27 +0,0 @@ -// This file is required by karma.conf.js and loads recursively all the .spec and framework files - -import 'zone.js/dist/long-stack-trace-zone'; -import 'zone.js/dist/proxy.js'; -import 'zone.js/dist/sync-test'; -import 'zone.js/dist/jasmine-patch'; -import 'zone.js/dist/async-test'; -import 'zone.js/dist/fake-async-test'; -import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; - -declare const __karma__: { - loaded: () => void; - start: () => void; -}; - -// Prevent Karma from running prematurely. -__karma__.loaded = () => { - /* empty */ -}; - -// First, initialize the Angular testing environment. -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { - teardown: { destroyAfterEach: false } -}); -// Finally, start Karma to run the tests. -__karma__.start(); diff --git a/src/tsconfig.spec.json b/src/tsconfig.spec.json index 70add2d529..5fa6abff5f 100644 --- a/src/tsconfig.spec.json +++ b/src/tsconfig.spec.json @@ -2,8 +2,8 @@ "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/spec", - "types": ["jasmine", "node"] + "typeRoots": ["../node_modules/@types", "../node_modules"], + "types": ["vitest/globals", "node"] }, - "files": ["test.ts", "polyfills.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts"] + "include": ["**/*.spec.ts", "**/*.d.ts", "vitest-setup.ts"] } diff --git a/src/vitest-setup.ts b/src/vitest-setup.ts new file mode 100644 index 0000000000..9ee7140bc8 --- /dev/null +++ b/src/vitest-setup.ts @@ -0,0 +1 @@ +import 'zone.js/plugins/vitest-patch'; From b5d57a5698f4477f8e5c5eff89c4961bfccf8d74 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:39:04 +1000 Subject: [PATCH 1144/1531] chore: upgrade to angular 22 --- package-lock.json | 2702 +++++++++++------ package.json | 30 +- .../edit-profile/edit-profile.component.ts | 3 +- .../activity-type-list.component.ts | 3 +- .../campus-list/campus-list.component.ts | 3 +- .../institution-settings.component.ts | 3 +- .../overseer-image-list.component.ts | 9 +- ...create-new-unit-modal-content.component.ts | 3 +- .../create-new-unit-modal.component.ts | 3 +- .../teaching-period-list.component.ts | 4 +- .../teaching-period-unit-import.dialog.ts | 10 +- src/app/admin/states/units/units.component.ts | 10 +- src/app/admin/states/users/users.component.ts | 10 +- .../tii-action-log.component.ts | 3 +- .../api/services/spec/campus.service.spec.ts | 9 +- .../api/services/spec/user.service.spec.ts | 9 +- src/app/app.component.ts | 3 +- .../archive-viewer.component.ts | 2 + .../audio-player/audio-player.component.ts | 11 +- .../audio-comment-recorder.ts | 3 +- .../microphone-tester.component.ts | 3 +- .../chart-base-component.component.ts | 3 +- .../edit-profile-form.component.ts | 3 +- src/app/common/f-chip/chip.component.ts | 3 +- .../feedback-template-editor.component.ts | 11 +- .../common/file-drop/file-drop.component.html | 4 +- .../common/file-drop/file-drop.component.ts | 3 +- .../file-uploader.component.html | 5 +- .../file-uploader/file-uploader.component.ts | 2 + .../file-viewer/file-viewer.component.ts | 10 +- src/app/common/footer/footer.component.ts | 11 +- .../common/grade-icon/grade-icon.component.ts | 10 +- src/app/common/header/header.component.ts | 3 +- .../task-dropdown/task-dropdown.component.ts | 3 +- .../unit-dropdown.component.html | 2 +- .../unit-dropdown/unit-dropdown.component.ts | 3 +- .../hero-sidebar/hero-sidebar.component.ts | 3 +- .../learning-outcome-editor.component.ts | 2 + .../nested-csv-download-modal.component.ts | 3 +- .../about-doubtfire-modal.component.ts | 3 +- .../calendar-modal.component.ts | 10 +- .../comments-modal.component.ts | 3 +- .../confirmation-modal.component.ts | 3 +- .../csv-result-modal.component.ts | 3 +- .../csv-upload-modal.component.ts | 3 +- .../task-date-slider.component.ts | 3 +- ...scussed-in-class-reason-modal.component.ts | 3 +- .../extension-modal.component.ts | 3 +- .../modals/qr-modal/qr-modal.component.ts | 3 +- .../scorm-extension-modal.component.ts | 3 +- .../sidekiq-jobs-modal.component.ts | 3 +- .../sidekiq-progress-modal.component.ts | 3 +- .../spec-con-modal.component.ts | 3 +- .../task-assessment-modal.component.ts | 3 +- .../tutor-notes-modal.component.ts | 3 +- .../obect-select/object-select.component.ts | 3 +- .../pdf-viewer-panel.component.ts | 3 +- .../common/pdf-viewer/pdf-viewer.component.ts | 2 + .../project-progress-bar.component.ts | 3 +- .../project-progress-gauge.component.ts | 10 +- .../scorm-player/scorm-player.component.ts | 3 +- src/app/common/services/alert.service.ts | 3 +- .../status-icon/status-icon.component.ts | 3 +- .../submission-files-download.component.ts | 3 +- .../success-close/success-close.component.ts | 3 +- .../common/task-badge/task-badge.component.ts | 3 +- .../common/unit-code/unit-code.component.ts | 3 +- .../user-badge/user-badge.component.html | 2 +- .../common/user-badge/user-badge.component.ts | 3 +- .../common/user-icon/user-icon.component.ts | 2 + .../privacy-policy/privacy-policy.spec.ts | 4 +- .../states/timeout/timeout.component.ts | 3 +- .../unauthorised/unauthorised.component.ts | 3 +- .../unavailable-card.component.ts | 3 +- .../eula/accept-eula/accept-eula.component.ts | 3 +- ...-member-contribution-assigner.component.ts | 2 + .../group-member-list.component.ts | 10 +- .../group-selector.component.ts | 2 + .../group-set-manager.component.ts | 3 +- .../group-set-selector.component.ts | 10 +- .../splash-screen/splash-screen.component.ts | 3 +- src/app/home/states/home/home.component.html | 12 +- src/app/home/states/home/home.component.ts | 3 +- .../lti-dashboard/lti-dashboard.component.ts | 3 +- .../lti-unit-link/lti-unit-link.component.ts | 3 +- src/app/legacy-route-placeholder.component.ts | 3 +- .../project-progress-dashboard.component.ts | 3 +- .../add-engagement-dialog.component.ts | 3 +- .../engagement-detail-dialog.component.ts | 11 +- .../engagement-passport-card.component.ts | 3 +- .../progress-dashboard.component.ts | 10 +- .../task-planner-card.component.ts | 3 +- ...eate-portfolio-task-list-item.component.ts | 3 +- .../task-list-item.component.ts | 3 +- .../discussion-prompts-view.component.ts | 3 +- .../staff-notes-view.component.ts | 3 +- .../task-assessment-card.component.ts | 3 +- .../task-description-card.component.html | 5 +- .../task-description-card.component.ts | 10 +- .../task-due-card.component.html | 14 +- .../task-due-card/task-due-card.component.ts | 3 +- .../task-ilos-card.component.ts | 10 +- .../submission-files-modal.component.html | 6 +- .../submission-files-modal.component.ts | 3 +- .../task-overseer-report.component.ts | 3 +- .../task-prerequisites-card.component.ts | 3 +- .../task-scorm-card.component.ts | 3 +- .../task-similarity-view.component.html | 5 +- .../task-similarity-view.component.ts | 10 +- .../task-status-card.component.html | 12 +- .../task-status-card.component.ts | 11 +- .../task-submission-card.component.ts | 10 +- .../tutor-notes-view.component.ts | 3 +- .../task-dashboard.component.ts | 10 +- .../project-dashboard.component.ts | 3 +- .../discussion-prompts.component.ts | 10 +- .../groups/project-groups-state.component.ts | 3 +- .../project-groups.component.ts | 3 +- .../jplag/jplag-report-viewer.component.ts | 3 +- .../states/plan/project-plan.component.ts | 10 +- ...k-planner-prerequisites-modal.component.ts | 3 +- .../task-planner/task-planner.component.ts | 2 + ...ortfolio-add-extra-files-step.component.ts | 3 +- .../portfolio-grade-select-step.component.ts | 3 +- ...-learning-summary-report-step.component.ts | 3 +- .../portfolio-included-tasks.component.ts | 11 +- .../portfolio-review-step.component.ts | 3 +- .../portfolio-welcome-step.component.ts | 3 +- .../portfolio/portfolio-state.component.ts | 3 +- .../states/project-root-state.component.ts | 3 +- .../staff-notes/staff-notes.component.ts | 10 +- .../tutor-discussion.component.html | 16 +- .../tutor-discussion.component.ts | 2 + .../tutor-notes/tutor-notes.component.ts | 10 +- .../states/tutorials/tutorials.component.ts | 3 +- .../states/sign-in/sign-in.component.ts | 3 +- .../feedback-appeal-modal.component.ts | 3 +- .../grade-task-modal.component.ts | 3 +- .../submission-type-modal.component.ts | 3 +- .../upload-submission-modal.component.ts | 3 +- .../project-tasks-list.component.ts | 10 +- ...ttachment-confirmation-dialog.component.ts | 3 +- .../discussion-prompt-composer.component.ts | 11 +- .../task-comment-composer.component.ts | 3 + .../task-feedback-templates.component.ts | 2 + .../comment-bubble-action.component.ts | 3 +- .../extension-comment.component.ts | 3 +- ...intelligent-discussion-player.component.ts | 11 +- ...telligent-discussion-recorder.component.ts | 3 +- .../pdf-image-comment.component.ts | 3 +- .../scorm-comment/scorm-comment.component.ts | 3 +- .../scorm-extension-comment.component.ts | 3 +- .../task-assessment-comment.component.ts | 3 +- .../task-comments-viewer.component.ts | 2 + .../unit-student-enrolment-modal.component.ts | 3 +- .../analytics-tutor-times.component.ts | 3 +- .../unit-analytics-route.component.ts | 3 +- .../change-target-grade-action.component.ts | 3 +- .../communication-actions.component.ts | 3 +- .../email-staff-action.component.ts | 3 +- .../email-student-action.component.ts | 3 +- .../task-comment-action.component.ts | 3 +- .../communication-schedule-modal.component.ts | 3 +- .../communication-schedules.component.ts | 3 +- .../communication-conditions.component.ts | 3 +- .../unit-communications-editor.component.ts | 11 +- .../d2l-unit-details-form.component.ts | 3 +- .../unit-details-editor.component.html | 14 +- .../unit-details-editor.component.ts | 3 +- .../unit-group-set-editor.component.ts | 3 +- .../bulk-import-staff-modal.component.ts | 3 +- .../unit-staff-editor.component.ts | 3 +- .../student-campus-select.component.ts | 3 +- .../student-tutorial-select.component.ts | 3 +- .../unit-students-editor.component.ts | 11 +- .../task-definition-dates.component.ts | 3 +- ...definition-discussion-prompts.component.ts | 10 +- .../task-definition-editor.component.ts | 2 + .../task-definition-general.component.ts | 3 +- .../task-definition-options.component.ts | 3 +- .../overseer-script-editor-modal.component.ts | 3 +- .../task-definition-overseer.component.ts | 11 +- ...sk-definition-prerequisites.component.html | 9 +- ...task-definition-prerequisites.component.ts | 10 +- .../task-definition-resources.component.ts | 3 +- .../task-definition-scorm.component.ts | 3 +- .../task-definition-upload.component.ts | 3 +- .../task-definition-who.component.html | 2 +- .../task-definition-who.component.ts | 3 +- .../unit-task-editor.component.ts | 3 +- .../unit-tutorials-list.component.ts | 3 +- .../unit-tutorials-manager.component.ts | 3 +- .../states/edit/unit-admin-state.component.ts | 3 +- .../unit-groups/unit-groups.component.ts | 3 +- .../d2l-transfer.component.ts | 3 +- .../portfolios-assessment.component.ts | 3 +- .../portfolios-list.component.ts | 2 + .../portfolios-portfolio-view.component.ts | 3 +- .../portfolios-project-progress.component.ts | 10 +- .../download-staff-notes.component.ts | 3 +- .../states/portfolios/portfolios.component.ts | 3 +- .../upload-grades/upload-grades.component.ts | 3 +- .../states/rollover/rollover.component.html | 14 +- .../states/rollover/rollover.component.ts | 3 +- .../students-list/students-list.component.ts | 11 +- .../inbox-dashboard.component.html | 4 +- .../inbox-dashboard.component.ts | 11 +- .../confirm-moderation-modal.component.ts | 3 +- .../moderation/moderation.component.ts | 3 +- ...atch-feedback-workflow-dialog.component.ts | 3 +- .../staff-task-list.component.ts | 2 + .../task-claim/task-claim.component.ts | 3 +- .../states/tasks/inbox/inbox.component.html | 4 +- .../states/tasks/inbox/inbox.component.ts | 11 +- .../inbox/unit-task-inbox-state.component.ts | 3 +- .../task-details-view.component.ts | 3 +- .../task-sheet-view.component.ts | 3 +- .../unit-task-list.component.ts | 11 +- .../task-viewer-state.component.ts | 3 +- src/app/units/unit-root-state.component.ts | 3 +- .../progress-burndown-chart.component.ts | 2 + .../task-status-pie-chart.component.ts | 10 +- .../task-visualisation.component.ts | 10 +- src/app/welcome/welcome.component.ts | 3 +- src/tsconfig.app.json | 11 +- src/tsconfig.spec.json | 10 +- tsconfig.json | 2 + 227 files changed, 2624 insertions(+), 1176 deletions(-) diff --git a/package-lock.json b/package-lock.json index e8e4016114..cf8a3ab19e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,19 +9,19 @@ "version": "11.0.0-25", "license": "AGPL-3.0", "dependencies": { - "@angular/animations": "^21.2.17", + "@angular/animations": "^22.0.2", "@angular/cdk": "^21.2.9", - "@angular/common": "^21.2.17", - "@angular/compiler": "^21.2.17", - "@angular/core": "^21.2.17", - "@angular/forms": "^21.2.17", + "@angular/common": "^22.0.2", + "@angular/compiler": "^22.0.2", + "@angular/core": "^22.0.2", + "@angular/forms": "^22.0.2", "@angular/material": "^21.2.9", "@angular/material-date-fns-adapter": "^21.2.9", - "@angular/platform-browser": "^21.2.17", - "@angular/platform-browser-dynamic": "^21.2.17", - "@angular/router": "^21.2.17", - "@angular/service-worker": "^21.2.17", - "@angular/upgrade": "^21.2.17", + "@angular/platform-browser": "^22.0.2", + "@angular/platform-browser-dynamic": "^22.0.2", + "@angular/router": "^22.0.2", + "@angular/service-worker": "^22.0.2", + "@angular/upgrade": "^22.0.2", "@ctrl/ngx-emoji-mart": "^9.3.0", "@eslint/js": "^10.0.1", "@ngneat/hotkeys": "^4.0.0", @@ -73,10 +73,10 @@ "@angular-eslint/eslint-plugin-template": "^21.4.0", "@angular-eslint/schematics": "^21.4.0", "@angular-eslint/template-parser": "^21.4.0", - "@angular/build": "^21.2.15", - "@angular/cli": "^21.2.15", - "@angular/compiler-cli": "^21.2.17", - "@angular/language-service": "^21.2.17", + "@angular/build": "^22.0.3", + "@angular/cli": "^22.0.3", + "@angular/compiler-cli": "^22.0.2", + "@angular/language-service": "^22.0.2", "@commitlint/cli": "^20.5.0", "@commitlint/config-conventional": "^21", "@trivago/prettier-plugin-sort-imports": "^6.0.2", @@ -106,7 +106,7 @@ "sass": "^1.48.0", "tailwindcss": "~3.4.17", "ts-node": "~10.9", - "typescript": "~5.9.3", + "typescript": "~6.0.3", "underscore": "^1.8.3", "vitest": "^4.1.8" }, @@ -124,57 +124,57 @@ } }, "node_modules/@algolia/abtesting": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.14.1.tgz", - "integrity": "sha512-Dkj0BgPiLAaim9sbQ97UKDFHJE/880wgStAM18U++NaJ/2Cws34J5731ovJifr6E3Pv4T2CqvMXf8qLCC417Ew==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.18.0.tgz", + "integrity": "sha512-8siuLG+FIns1AjZ/g2SDVwHz9S+ObacDQISEJvS8XsNei1zl3FXqfqQrBpmrG7ACWCyesXHbicMJtvRbg00FEw==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-abtesting": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.48.1.tgz", - "integrity": "sha512-LV5qCJdj+/m9I+Aj91o+glYszrzd7CX6NgKaYdTOj4+tUYfbS62pwYgUfZprYNayhkQpVFcrW8x8ZlIHpS23Vw==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.52.0.tgz", + "integrity": "sha512-wtwPgyPmO7b7sQPVgoK29c1VpfS08DnnJCmxX/oU1pV2DlMRJCzQcLN7JSloYpodyKHwM8+9wOzlAM0co3TDmA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.48.1.tgz", - "integrity": "sha512-/AVoMqHhPm14CcHq7mwB+bUJbfCv+jrxlNvRjXAuO+TQa+V37N8k1b0ijaRBPdmSjULMd8KtJbQyUyabXOu6Kg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.52.0.tgz", + "integrity": "sha512-9KY36bRl4AH7RjqSeDDOKnjsz4IxQFBEOB8/fWmEbdQe+Isbs5jGzVJu9NEPQ1Tgwxlf8Uf07Swj3jZyMNUZ2g==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.48.1.tgz", - "integrity": "sha512-VXO+qu2Ep6ota28ktvBm3sG53wUHS2n7bgLWmce5jTskdlCD0/JrV4tnBm1l7qpla1CeoQb8D7ShFhad+UoSOw==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.52.0.tgz", + "integrity": "sha512-3a/qM3dzJqqfTx7Yrw7uGQ98I3Q0rDfb4Vkv0wEzko96l7YQMxfBVz/VbLq2N+c59GweYv6Vhp8mPeqnWJSITw==", "dev": true, "license": "MIT", "engines": { @@ -182,151 +182,151 @@ } }, "node_modules/@algolia/client-insights": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.48.1.tgz", - "integrity": "sha512-zl+Qyb0nLg+Y5YvKp1Ij+u9OaPaKg2/EPzTwKNiVyOHnQJlFxmXyUZL1EInczAZsEY8hVpPCLtNfhMhfxluXKQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.52.0.tgz", + "integrity": "sha512-Rki7ACbMcvbQW0BuM84x9dkGHY47ABmv4jU6tYssat2k02p3mIUms2YOLUAMeknhmnFsj6lb6ZzOXdMWMyc1sA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.48.1.tgz", - "integrity": "sha512-r89Qf9Oo9mKWQXumRu/1LtvVJAmEDpn8mHZMc485pRfQUMAwSSrsnaw1tQ3sszqzEgAr1c7rw6fjBI+zrAXTOw==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.52.0.tgz", + "integrity": "sha512-96s4Uzc3kk+/f4jJXIVVGWP5XlngOGNQ1x6hW9AT59pOixHlOs5tqJg+ZUS/GQ6h/iYP0ceQcmxDQeLyCLTaDQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.48.1.tgz", - "integrity": "sha512-TPKNPKfghKG/bMSc7mQYD9HxHRUkBZA4q1PEmHgICaSeHQscGqL4wBrKkhfPlDV1uYBKW02pbFMUhsOt7p4ZpA==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.52.0.tgz", + "integrity": "sha512-lqeycNpSPe5Qa0OUWpejVvYQjQWV5nQuLT0a4aq7XzRAvCxprV/6Lf841EygdD2nrFnuS58ok7Au1uOtXzpnkg==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.48.1.tgz", - "integrity": "sha512-4Fu7dnzQyQmMFknYwTiN/HxPbH4DyxvQ1m+IxpPp5oslOgz8m6PG5qhiGbqJzH4HiT1I58ecDiCAC716UyVA8Q==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.52.0.tgz", + "integrity": "sha512-ly1wETVGRo30cx61O7fetESN+ElL9c9K+bD/AVgnT1ar4c6v+/Yqjrhdtu6Fm4D0s4NZP081Isf6tunH1wUXHg==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/ingestion": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.48.1.tgz", - "integrity": "sha512-/RFq3TqtXDUUawwic/A9xylA2P3LDMO8dNhphHAUOU51b1ZLHrmZ6YYJm3df1APz7xLY1aht6okCQf+/vmrV9w==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.52.0.tgz", + "integrity": "sha512-U4EeTvgmluRjj39ykZSAd5X+a6LD5m7/mcOWDmB7hqm1R6QY0yT8jLxpNVEjYhzgEN5hcDGW6X67EWQY8KiYGQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.48.1.tgz", - "integrity": "sha512-Of0jTeAZRyRhC7XzDSjJef0aBkgRcvRAaw0ooYRlOw57APii7lZdq+layuNdeL72BRq1snaJhoMMwkmLIpJScw==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.52.0.tgz", + "integrity": "sha512-FCPnDcILfpTE94u7BVlV4DmnSV5wE3+j25EEF+3dYPrVzkVCSoAHs318oWDGxnxsAgiL4HpL12Jc4XHmw9shpA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.48.1.tgz", - "integrity": "sha512-bE7JcpFXzxF5zHwj/vkl2eiCBvyR1zQ7aoUdO+GDXxGp0DGw7nI0p8Xj6u8VmRQ+RDuPcICFQcCwRIJT5tDJFw==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.52.0.tgz", + "integrity": "sha512-br3DO7n4N8CXwTRbZS0MnB4WQ9YHfNjCwkCEzVR/wek/qNTDQKDb0nROmkFaNZ8ucUqUVKZi074dbwMwRDlK8Q==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.48.1.tgz", - "integrity": "sha512-MK3wZ2koLDnvH/AmqIF1EKbJlhRS5j74OZGkLpxI4rYvNi9Jn/C7vb5DytBnQ4KUWts7QsmbdwHkxY5txQHXVw==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.52.0.tgz", + "integrity": "sha512-b0T/Ca2c9KyEslKsVrGZvbe1UrrKKSdfXhBZ2pbpKahFUzJfziRZ0urbOm7V65O0tO/jwU+Lo/+bIiiyhzGt8w==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1" + "@algolia/client-common": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.48.1.tgz", - "integrity": "sha512-2oDT43Y5HWRSIQMPQI4tA/W+TN/N2tjggZCUsqQV440kxzzoPGsvv9QP1GhQ4CoDa+yn6ygUsGp6Dr+a9sPPSg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.52.0.tgz", + "integrity": "sha512-ozBT8J/mtD4H4IAojw8QPirlcL2gHrI1BGuZ4/ZXXO/rTE1yQ4VIPJj4mTTbwo4FbkS1MoJsD/DsrqLzhnc4/g==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1" + "@algolia/client-common": "5.52.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.48.1.tgz", - "integrity": "sha512-xcaCqbhupVWhuBP1nwbk1XNvwrGljozutEiLx06mvqDf3o8cHyEgQSHS4fKJM+UAggaWVnnFW+Nne5aQ8SUJXg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.52.0.tgz", + "integrity": "sha512-gyyWcLD22tnabmoit4iukCXuoRc5HYJuUjPSEa8a0D/f/NlRafpWi52AlAaa4Uu/rsl7saHsJFTNjTptWbu2+A==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1" + "@algolia/client-common": "5.52.0" }, "engines": { "node": ">= 14.0.0" @@ -535,80 +535,79 @@ } }, "node_modules/@angular/animations": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.2.17.tgz", - "integrity": "sha512-zOW8FFa9qfbVkZ5TulxDkl1C3+gEjWfAAD5Z2MycA6pjVJQlLYPiTAGq+flOQ3yZfTT0z6kd5rejQMXWI81Dvg==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-22.0.2.tgz", + "integrity": "sha512-l9lVG9k+baFMWXNsFUxwmxQaUZMkpkTn3vRpa1hs/vABzT/KnaDeweDtvvkS0NS1RYJenoxhONlMNEWuJ4VR1A==", "deprecated": "@angular/animations is deprecated. Use `animate.enter` and `animate.leave` instead. For more information see: https://v22.angular.dev/guide/animations.", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/core": "21.2.17" + "@angular/core": "22.0.2" } }, "node_modules/@angular/build": { - "version": "21.2.15", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-21.2.15.tgz", - "integrity": "sha512-APJ5v0/hL38CKSqSQDos5Y8/O2LSiSSqP9FagdcMT5j9JAlENXdhVaA3IxPMXDWcxtzD5T1IlN8Z9aFxDXxHyg==", + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-22.0.3.tgz", + "integrity": "sha512-pwFDRCp+r8JK+fCtScPldizcS75wSpn3u/4goDf2FRa4Y9wzTvq6T0XpFHqdpgq6HcIlIZWwAqqW6XqEM9/pKQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2102.15", + "@angular-devkit/architect": "0.2200.3", "@babel/core": "7.29.0", "@babel/helper-annotate-as-pure": "7.27.3", "@babel/helper-split-export-declaration": "7.24.7", - "@inquirer/confirm": "5.1.21", - "@vitejs/plugin-basic-ssl": "2.1.4", - "beasties": "0.4.1", + "@inquirer/confirm": "6.0.12", + "@vitejs/plugin-basic-ssl": "2.3.0", + "beasties": "0.4.2", "browserslist": "^4.26.0", - "esbuild": "0.27.3", - "https-proxy-agent": "7.0.6", - "istanbul-lib-instrument": "6.0.3", + "esbuild": "0.28.1", + "https-proxy-agent": "9.0.0", "jsonc-parser": "3.3.1", - "listr2": "9.0.5", + "listr2": "10.2.1", "magic-string": "0.30.21", "mrmime": "2.0.1", - "parse5-html-rewriting-stream": "8.0.0", + "parse5-html-rewriting-stream": "8.0.1", "picomatch": "4.0.4", "piscina": "5.1.4", - "rolldown": "1.0.0-rc.4", - "sass": "1.97.3", + "rollup": "4.60.2", + "sass": "1.99.0", "semver": "7.7.4", "source-map-support": "0.5.21", - "tinyglobby": "0.2.15", - "undici": "7.24.4", - "vite": "7.3.2", + "tinyglobby": "0.2.16", + "vite": "7.3.5", "watchpack": "2.5.1" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, "optionalDependencies": { - "lmdb": "3.5.1" + "lmdb": "3.5.4" }, "peerDependencies": { - "@angular/compiler": "^21.0.0", - "@angular/compiler-cli": "^21.0.0", - "@angular/core": "^21.0.0", - "@angular/localize": "^21.0.0", - "@angular/platform-browser": "^21.0.0", - "@angular/platform-server": "^21.0.0", - "@angular/service-worker": "^21.0.0", - "@angular/ssr": "^21.2.15", + "@angular/compiler": "^22.0.0", + "@angular/compiler-cli": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/localize": "^22.0.0", + "@angular/platform-browser": "^22.0.0", + "@angular/platform-server": "^22.0.0", + "@angular/service-worker": "^22.0.0", + "@angular/ssr": "^22.0.3", + "istanbul-lib-instrument": "^6.0.0", "karma": "^6.4.0", "less": "^4.2.0", - "ng-packagr": "^21.0.0", + "ng-packagr": "^22.0.0", "postcss": "^8.4.0", "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", "tslib": "^2.3.0", - "typescript": ">=5.9 <6.0", + "typescript": ">=6.0 <6.1", "vitest": "^4.0.8" }, "peerDependenciesMeta": { @@ -630,6 +629,9 @@ "@angular/ssr": { "optional": true }, + "istanbul-lib-instrument": { + "optional": true + }, "karma": { "optional": true }, @@ -650,20 +652,909 @@ } } }, - "node_modules/@angular/build/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "node_modules/@angular/build/node_modules/@angular-devkit/architect": { + "version": "0.2200.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2200.3.tgz", + "integrity": "sha512-Ru+ucNkTZr98gmeaBYjq3zZwh32yGofAeB8+GJL/ZNy0x+7NzK6b+OatdzwT4l7mCWFC5vL8iYu0B4++M66Jpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "22.0.3", + "rxjs": "7.8.2" + }, + "bin": { + "architect": "bin/cli.js" + }, + "engines": { + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/build/node_modules/@angular-devkit/core": { + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.0.3.tgz", + "integrity": "sha512-pBjo1JKwI8GbNdTo/Z0g+ZekqlTBCJWmzIC5fgGW9q5eRjl1y+5N5jlX8UAyyMCeUTTwsfpQdkAM2jyi/jcvjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.20.0", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.4", + "rxjs": "7.8.2", + "source-map": "0.7.6" + }, + "engines": { + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^5.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular/build/node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", + "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", + "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", + "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", + "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", + "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", + "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", + "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", + "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", + "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", + "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", + "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", + "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", + "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", + "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", + "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", + "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", + "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", + "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", + "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", + "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", + "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", + "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", + "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", + "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", + "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular/build/node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@angular/build/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular/build/node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">= 14.16.0" + "node": ">=18" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" } }, "node_modules/@angular/build/node_modules/readdirp": { @@ -680,15 +1571,60 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@angular/build/node_modules/rollup": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", + "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.2", + "@rollup/rollup-android-arm64": "4.60.2", + "@rollup/rollup-darwin-arm64": "4.60.2", + "@rollup/rollup-darwin-x64": "4.60.2", + "@rollup/rollup-freebsd-arm64": "4.60.2", + "@rollup/rollup-freebsd-x64": "4.60.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", + "@rollup/rollup-linux-arm-musleabihf": "4.60.2", + "@rollup/rollup-linux-arm64-gnu": "4.60.2", + "@rollup/rollup-linux-arm64-musl": "4.60.2", + "@rollup/rollup-linux-loong64-gnu": "4.60.2", + "@rollup/rollup-linux-loong64-musl": "4.60.2", + "@rollup/rollup-linux-ppc64-gnu": "4.60.2", + "@rollup/rollup-linux-ppc64-musl": "4.60.2", + "@rollup/rollup-linux-riscv64-gnu": "4.60.2", + "@rollup/rollup-linux-riscv64-musl": "4.60.2", + "@rollup/rollup-linux-s390x-gnu": "4.60.2", + "@rollup/rollup-linux-x64-gnu": "4.60.2", + "@rollup/rollup-linux-x64-musl": "4.60.2", + "@rollup/rollup-openbsd-x64": "4.60.2", + "@rollup/rollup-openharmony-arm64": "4.60.2", + "@rollup/rollup-win32-arm64-msvc": "4.60.2", + "@rollup/rollup-win32-ia32-msvc": "4.60.2", + "@rollup/rollup-win32-x64-gnu": "4.60.2", + "@rollup/rollup-win32-x64-msvc": "4.60.2", + "fsevents": "~2.3.2" + } + }, "node_modules/@angular/build/node_modules/sass": { - "version": "1.97.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz", - "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", + "version": "1.99.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz", + "integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==", "dev": true, "license": "MIT", "dependencies": { "chokidar": "^4.0.0", - "immutable": "^5.0.2", + "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -701,6 +1637,22 @@ "@parcel/watcher": "^2.4.1" } }, + "node_modules/@angular/build/node_modules/sass/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@angular/cdk": { "version": "21.2.14", "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-21.2.14.tgz", @@ -718,72 +1670,191 @@ } }, "node_modules/@angular/cli": { - "version": "21.2.15", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-21.2.15.tgz", - "integrity": "sha512-8CT1iST5CwdxHEzC0NVFUsMenAY7aE30ayTAw5PpA6MPs6bdHlL6QxTmkqThW7hoCj6PJ56YfQMzSQU+aYRLQA==", + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-22.0.3.tgz", + "integrity": "sha512-YgFzfQu3Il6Aka8IdH4pk7faieICaca5Wklke0jMTKBUxzLGWw82X7+J/Lox7FERb6LHtxiHpa6ttXqerCZvgg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.2102.15", - "@angular-devkit/core": "21.2.15", - "@angular-devkit/schematics": "21.2.15", - "@inquirer/prompts": "7.10.1", - "@listr2/prompt-adapter-inquirer": "3.0.5", - "@modelcontextprotocol/sdk": "1.26.0", - "@schematics/angular": "21.2.15", + "@angular-devkit/architect": "0.2200.3", + "@angular-devkit/core": "22.0.3", + "@angular-devkit/schematics": "22.0.3", + "@inquirer/prompts": "8.4.2", + "@listr2/prompt-adapter-inquirer": "4.2.3", + "@modelcontextprotocol/sdk": "1.29.0", + "@schematics/angular": "22.0.3", "@yarnpkg/lockfile": "1.1.0", - "algoliasearch": "5.48.1", + "algoliasearch": "5.52.0", "ini": "6.0.0", "jsonc-parser": "3.3.1", - "listr2": "9.0.5", + "listr2": "10.2.1", "npm-package-arg": "13.0.2", - "pacote": "21.3.1", - "parse5-html-rewriting-stream": "8.0.0", + "pacote": "21.5.1", + "parse5-html-rewriting-stream": "8.0.1", "semver": "7.7.4", "yargs": "18.0.0", - "zod": "4.3.6" + "zod": "4.4.2" }, "bin": { "ng": "bin/ng.js" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { + "version": "0.2200.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2200.3.tgz", + "integrity": "sha512-Ru+ucNkTZr98gmeaBYjq3zZwh32yGofAeB8+GJL/ZNy0x+7NzK6b+OatdzwT4l7mCWFC5vL8iYu0B4++M66Jpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "22.0.3", + "rxjs": "7.8.2" + }, + "bin": { + "architect": "bin/cli.js" + }, + "engines": { + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/core": { + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.0.3.tgz", + "integrity": "sha512-pBjo1JKwI8GbNdTo/Z0g+ZekqlTBCJWmzIC5fgGW9q5eRjl1y+5N5jlX8UAyyMCeUTTwsfpQdkAM2jyi/jcvjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.20.0", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.4", + "rxjs": "7.8.2", + "source-map": "0.7.6" + }, + "engines": { + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^5.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/schematics": { + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-22.0.3.tgz", + "integrity": "sha512-aIp5sQDHdhyLbeVJF/k3w079XhW91mNAo2OliZllBCjoYhkIXNnWECOx5y2nXtCChyFJA2+ZgNST7NIDvtz1/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "22.0.3", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.21", + "ora": "9.4.0", + "rxjs": "7.8.2" + }, + "engines": { + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } }, + "node_modules/@angular/cli/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular/cli/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@angular/cli/node_modules/ora": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-9.4.0.tgz", + "integrity": "sha512-84cglkRILFxdtA8hAvLNdMrtBpPNBTrQ9/ulg0FA7xLMnD6mifv+enAIeRmvtv+WgdCE+LPGOfQmtJRrVaIVhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.6.2", + "cli-cursor": "^5.0.0", + "cli-spinners": "^3.2.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.1.0", + "log-symbols": "^7.0.1", + "stdin-discarder": "^0.3.2", + "string-width": "^8.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@angular/common": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-21.2.17.tgz", - "integrity": "sha512-hqAQxRfi5ldFE42suAXRcY+JCANrUh7fuSQ/DtZ7L896id5BT/exuv6dWNBC1PyAfQmRbpD5Pt6/pd+tNLyhDQ==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-22.0.2.tgz", + "integrity": "sha512-XSkHYRwrM54v4GZ+fg9KU1KbSIE/iQF33VXKo5zqVNKO11MnAbJ59qzyqX/5EzSeogHyBoHApprFKACsCAKm/Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/core": "21.2.17", + "@angular/core": "22.0.2", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-21.2.17.tgz", - "integrity": "sha512-p+NdjYiwAz9Zmu2yul0LlMXaFjMISVVa24+/MVMoKFeQeI82QE8jDywPlnOSHQHvdCcQVpS7saeEriZzX3JuBQ==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-22.0.2.tgz", + "integrity": "sha512-5G+h/4/iCfqdTBsSgjB46Oe4oC6jXutCpFc5JYWRpnJWsbp3UfwRhwGVWIV1DBPnR8H/3QZzteRP1jINiH5+hg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" } }, "node_modules/@angular/compiler-cli": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-21.2.17.tgz", - "integrity": "sha512-KithZ3b0HBFH0NbUcswBcjpN9y09vLbarMD7qmGWTnGUBk4W8cn4sbT8zJyv9CRKg9ZcuUBeJYKUfUPn/u/5OQ==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-22.0.2.tgz", + "integrity": "sha512-jBGGWdbrPQhIHWUz523CLQqEh/iYWxzZt7U9y0Ocdbas4/OlHcqaERO/K4ULkxclWX8MWYQoxal/MZbYOBfXgw==", "dev": true, "license": "MIT", "dependencies": { @@ -801,11 +1872,11 @@ "ngc": "bundles/src/bin/ngc.js" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/compiler": "21.2.17", - "typescript": ">=5.9 <6.1" + "@angular/compiler": "22.0.2", + "typescript": ">=6.0 <6.1" }, "peerDependenciesMeta": { "typescript": { @@ -814,18 +1885,18 @@ } }, "node_modules/@angular/core": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-21.2.17.tgz", - "integrity": "sha512-wYHpwIdnUnjQFOJJNqRcGx7LS3u64jT+R9L0TnMR/ViBM9dQgGYImlSikkftg2yrFCNo5aKRxhG2LLskQurVdg==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-22.0.2.tgz", + "integrity": "sha512-YMs6OZNeXh4tg67ePwSRN426WYvjqGdjxEwLrdOONKAruOmJAzW/Tqe328k/4SHfdbJTR87GPpRi5FzVP43DRA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/compiler": "21.2.17", + "@angular/compiler": "22.0.2", "rxjs": "^6.5.3 || ^7.4.0", "zone.js": "~0.15.0 || ~0.16.0" }, @@ -839,32 +1910,33 @@ } }, "node_modules/@angular/forms": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-21.2.17.tgz", - "integrity": "sha512-WKu8XeRSNZo+a+aDDZ3M5OtReF7KYqR/PmZ2l1lSf6N5EEAmc+Ky4aqbRhTL/mTSfHrO4+TDJ4C5A2tFmuwIeA==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-22.0.2.tgz", + "integrity": "sha512-k2WhkE8Of8/JRYEojSgfygiXbP6I7f/yZ/jgJzFGRC1FlF5w5erQMFx8KPg1J5CRE8kYPzW8rM4tSVCq7AaDUg==", "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", - "tslib": "^2.3.0" + "tslib": "^2.3.0", + "zod": "^4.0.10" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/common": "21.2.17", - "@angular/core": "21.2.17", - "@angular/platform-browser": "21.2.17", + "@angular/common": "22.0.2", + "@angular/core": "22.0.2", + "@angular/platform-browser": "22.0.2", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-21.2.17.tgz", - "integrity": "sha512-Pq0V7VBkShQThA6QME2FjZgHLuxFpsioEoppx1i8rHFTGoJuXtBJK8iaArF7XuYaMzMRInUGfMQzsXc2WE+rmg==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-22.0.2.tgz", + "integrity": "sha512-J7QXjv9R/wFVwK4CZBjzE6B1owFQTKsb0KWVhuuPcglD3jtVAJ5xipUI9gco93GmCT3EU9oANmN8jQcAn67h4A==", "dev": true, "license": "MIT", "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" } }, "node_modules/@angular/material": { @@ -899,20 +1971,20 @@ } }, "node_modules/@angular/platform-browser": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.2.17.tgz", - "integrity": "sha512-ROdSliejY37g1EphYmweYdm5cHM8HY3X4tbWt4ubxmhTyYgfN3nxrxfGQ/n7Mz5tDY9VXVLIGDgjLOGYOo4uTQ==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-22.0.2.tgz", + "integrity": "sha512-xUkpJo/Jwa7rgpoSnZs5TeuOD3SDQL+CPJrMGjHivsqWMcAqzSNnIOcbNDJRSxAYkZ9zlJ1+h39JWSUk99rRBw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/animations": "21.2.17", - "@angular/common": "21.2.17", - "@angular/core": "21.2.17" + "@angular/animations": "22.0.2", + "@angular/common": "22.0.2", + "@angular/core": "22.0.2" }, "peerDependenciesMeta": { "@angular/animations": { @@ -921,45 +1993,46 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-21.2.17.tgz", - "integrity": "sha512-r/BU/T8bOTghP3fIXhzYf5wcMcAmhWnAFv3p4asCCPXomaktoas70wYcMaDH+pK1LAFBxLwzBWHm36MpFlTMFg==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-22.0.2.tgz", + "integrity": "sha512-5jDZzbesBBPCt41oq166B23TCW4ue9ZJyX4KlSRpGP/x8fjPGF22+AKASU6OPRnCNmmUsNk8DpenaBj+eFg/Sw==", + "deprecated": "@angular/platform-browser-dynamic is deprecated. Use `@angular/platform-browser` instead.", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/common": "21.2.17", - "@angular/compiler": "21.2.17", - "@angular/core": "21.2.17", - "@angular/platform-browser": "21.2.17" + "@angular/common": "22.0.2", + "@angular/compiler": "22.0.2", + "@angular/core": "22.0.2", + "@angular/platform-browser": "22.0.2" } }, "node_modules/@angular/router": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-21.2.17.tgz", - "integrity": "sha512-RSCtK5ppAV6y6wfRLHSK2a9Wc/vm8j0wsC+/j9PH9yQmppWFVXDWsg5E39MKOIpnoYVx2+hI6eak6+wYtZTe1A==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-22.0.2.tgz", + "integrity": "sha512-uiYlcbOyBliFq1v7O3nMyZtM8scDBurjk4AU2wEPWxSVAXuEjyfnAvowyPzVzGYAEKrsYtcg2TWSsQraqHUbnA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/common": "21.2.17", - "@angular/core": "21.2.17", - "@angular/platform-browser": "21.2.17", + "@angular/common": "22.0.2", + "@angular/core": "22.0.2", + "@angular/platform-browser": "22.0.2", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/service-worker": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-21.2.17.tgz", - "integrity": "sha512-6/uKwxBA3udngVHuIVqD8kdMV1whfym9ESB1UyjoNINx+2zj7A749X89tiV0TW2CvWpUYUE7VxpoapEiv5lvfw==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-22.0.2.tgz", + "integrity": "sha512-mUGA3PwTltRI2i3/fbJrlprqdtzD/qRZeoGc70Z9fL/4kVYUfz9lC2PNkKf5vgsl3Z4om5BXKM11uZGWtI9urQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -968,29 +2041,29 @@ "ngsw-config": "ngsw-config.js" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/core": "21.2.17", + "@angular/core": "22.0.2", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/upgrade": { - "version": "21.2.17", - "resolved": "https://registry.npmjs.org/@angular/upgrade/-/upgrade-21.2.17.tgz", - "integrity": "sha512-dy1ZgG7QveN8q3cBD3Sfce8KY3sX8I/LPhlhHetdQU0bDZHF/+LLSQlnciV/UFDBvck7vJZ5pifOnk6JdQ+RpA==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/upgrade/-/upgrade-22.0.2.tgz", + "integrity": "sha512-FrETq4hwyDZ3v/6p6HZDSxSCDe7eQPopGJCdA8GdL/RjxHzKsoz7XHgM/lFKHx6JJK5yzof1mqK4BQz64G6YLQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/compiler": "21.2.17", - "@angular/core": "21.2.17", - "@angular/platform-browser": "21.2.17", - "@angular/platform-browser-dynamic": "21.2.17" + "@angular/compiler": "22.0.2", + "@angular/core": "22.0.2", + "@angular/platform-browser": "22.0.2", + "@angular/platform-browser-dynamic": "22.0.2" } }, "node_modules/@asamuzakjp/css-color": { @@ -1984,43 +3057,6 @@ "license": "MIT", "peer": true }, - "node_modules/@emnapi/core": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.0.tgz", - "integrity": "sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.0.tgz", - "integrity": "sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", - "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", @@ -2717,30 +3753,29 @@ } }, "node_modules/@inquirer/ansi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", - "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.7.tgz", + "integrity": "sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" } }, "node_modules/@inquirer/checkbox": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", - "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.2.1.tgz", + "integrity": "sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@inquirer/ansi": "^2.0.7", + "@inquirer/core": "^11.2.1", + "@inquirer/figures": "^2.0.7", + "@inquirer/type": "^4.0.7" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -2752,17 +3787,17 @@ } }, "node_modules/@inquirer/confirm": { - "version": "5.1.21", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", - "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.0.12.tgz", + "integrity": "sha512-h9FgGun3QwVYNj5TWIZZ+slii73bMoBFjPfVIGtnFuL4t8gBiNDV9PcSfIzkuxvgquJKt9nr1QzszpBzTbH8Og==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@inquirer/core": "^11.1.9", + "@inquirer/type": "^4.0.5" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -2774,23 +3809,22 @@ } }, "node_modules/@inquirer/core": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", - "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.2.1.tgz", + "integrity": "sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", + "@inquirer/ansi": "^2.0.7", + "@inquirer/figures": "^2.0.7", + "@inquirer/type": "^4.0.7", "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.3" + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -2802,18 +3836,18 @@ } }, "node_modules/@inquirer/editor": { - "version": "4.2.23", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", - "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.2.2.tgz", + "integrity": "sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/external-editor": "^1.0.3", - "@inquirer/type": "^3.0.10" + "@inquirer/core": "^11.2.1", + "@inquirer/external-editor": "^3.0.3", + "@inquirer/type": "^4.0.7" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -2825,18 +3859,17 @@ } }, "node_modules/@inquirer/expand": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", - "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.1.1.tgz", + "integrity": "sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@inquirer/core": "^11.2.1", + "@inquirer/type": "^4.0.7" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -2848,17 +3881,17 @@ } }, "node_modules/@inquirer/external-editor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", - "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA==", "dev": true, "license": "MIT", "dependencies": { "chardet": "^2.1.1", - "iconv-lite": "^0.7.0" + "iconv-lite": "^0.7.2" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -2870,27 +3903,27 @@ } }, "node_modules/@inquirer/figures": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", - "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.7.tgz", + "integrity": "sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" } }, "node_modules/@inquirer/input": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", - "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.1.2.tgz", + "integrity": "sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@inquirer/core": "^11.2.1", + "@inquirer/type": "^4.0.7" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -2902,17 +3935,17 @@ } }, "node_modules/@inquirer/number": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", - "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.1.1.tgz", + "integrity": "sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@inquirer/core": "^11.2.1", + "@inquirer/type": "^4.0.7" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -2924,18 +3957,18 @@ } }, "node_modules/@inquirer/password": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", - "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.1.1.tgz", + "integrity": "sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@inquirer/ansi": "^2.0.7", + "@inquirer/core": "^11.2.1", + "@inquirer/type": "^4.0.7" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -2947,25 +3980,25 @@ } }, "node_modules/@inquirer/prompts": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", - "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.4.2.tgz", + "integrity": "sha512-XJmn/wY4AX56l1BRU+ZjDrFtg9+2uBEi4JvJQj82kwJDQKiPgSn4CEsbfGGygS4Gw6rkL4W18oATjfVfaqub2Q==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^4.3.2", - "@inquirer/confirm": "^5.1.21", - "@inquirer/editor": "^4.2.23", - "@inquirer/expand": "^4.0.23", - "@inquirer/input": "^4.3.1", - "@inquirer/number": "^3.0.23", - "@inquirer/password": "^4.0.23", - "@inquirer/rawlist": "^4.1.11", - "@inquirer/search": "^3.2.2", - "@inquirer/select": "^4.4.2" + "@inquirer/checkbox": "^5.1.4", + "@inquirer/confirm": "^6.0.12", + "@inquirer/editor": "^5.1.1", + "@inquirer/expand": "^5.0.13", + "@inquirer/input": "^5.0.12", + "@inquirer/number": "^4.0.12", + "@inquirer/password": "^5.0.12", + "@inquirer/rawlist": "^5.2.8", + "@inquirer/search": "^4.1.8", + "@inquirer/select": "^5.1.4" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -2977,18 +4010,17 @@ } }, "node_modules/@inquirer/rawlist": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", - "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.3.1.tgz", + "integrity": "sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@inquirer/core": "^11.2.1", + "@inquirer/type": "^4.0.7" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -3000,19 +4032,18 @@ } }, "node_modules/@inquirer/search": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", - "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.2.1.tgz", + "integrity": "sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@inquirer/core": "^11.2.1", + "@inquirer/figures": "^2.0.7", + "@inquirer/type": "^4.0.7" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -3024,20 +4055,19 @@ } }, "node_modules/@inquirer/select": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", - "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.2.1.tgz", + "integrity": "sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@inquirer/ansi": "^2.0.7", + "@inquirer/core": "^11.2.1", + "@inquirer/figures": "^2.0.7", + "@inquirer/type": "^4.0.7" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -3049,13 +4079,13 @@ } }, "node_modules/@inquirer/type": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", - "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.0.7.tgz", + "integrity": "sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -3085,6 +4115,8 @@ "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -3140,26 +4172,26 @@ } }, "node_modules/@listr2/prompt-adapter-inquirer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-3.0.5.tgz", - "integrity": "sha512-WELs+hj6xcilkloBXYf9XXK8tYEnKsgLj01Xl5ONUJpKjmT5hGVUzNUS5tooUxs7pGMrw+jFD/41WpqW4V3LDA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-4.2.3.tgz", + "integrity": "sha512-Co9U3AJ3LW0J8XBHjVoNKA79dMAyFt8EZH3OaKTMcDTj8r+6kG3vSUPq/eGLHT7P0iK3uLaFfhdFYd3033P24g==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/type": "^3.0.8" + "@inquirer/type": "^4.0.5" }, "engines": { - "node": ">=20.0.0" + "node": ">=22.13.0" }, "peerDependencies": { - "@inquirer/prompts": ">= 3 < 8", - "listr2": "9.0.5" + "@inquirer/prompts": ">= 3 < 9", + "listr2": "10.2.1" } }, "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.1.tgz", - "integrity": "sha512-tpfN4kKrrMpQ+If1l8bhmoNkECJi0iOu6AEdrTJvWVC+32sLxTARX5Rsu579mPImRP9YFWfWgeRQ5oav7zApQQ==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.4.tgz", + "integrity": "sha512-Kk4Kz3iyu1QiLsLZBS9Af1eSKUC8VR2T+/jyE2iAyuGw2VwK08pp5iTbZnXn6sWu0LogO/RFktMxOjiDA2sS3w==", "cpu": [ "arm64" ], @@ -3171,9 +4203,9 @@ ] }, "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.1.tgz", - "integrity": "sha512-+a2tTfc3rmWhLAolFUWRgJtpSuu+Fw/yjn4rF406NMxhfjbMuiOUTDRvRlMFV+DzyjkwnokisskHbCWkS3Ly5w==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.4.tgz", + "integrity": "sha512-BEe5Rp3trn26oxoXOVL5HVDoiYmjUDwr8NRPkBOdUdCSBEorKI+7JrZLRKAdxO+G6cGQLgseXk0gR7qIQa7aGw==", "cpu": [ "x64" ], @@ -3185,9 +4217,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.1.tgz", - "integrity": "sha512-0EgcE6reYr8InjD7V37EgXcYrloqpxVPINy3ig1MwDSbl6LF/vXTYRH9OE1Ti1D8YZnB35ZH9aTcdfSb5lql2A==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.4.tgz", + "integrity": "sha512-SGbFR7816uBcTHc2ZY4S6WyOkl9bICnzqTQd2Mv4V/j24cfds88xx2nC6cm/y8zGQL7Ds31YF/5NGxjgcdM5Hw==", "cpu": [ "arm" ], @@ -3199,9 +4231,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.1.tgz", - "integrity": "sha512-aoERa5B6ywXdyFeYGQ1gbQpkMkDbEo45qVoXE5QpIRavqjnyPwjOulMkmkypkmsbJ5z4Wi0TBztON8agCTG0Vg==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.4.tgz", + "integrity": "sha512-cUXEengO8o60v1SWerJTH4/RH4U3+9jC0/4njp2Z9NdmvaGzhKsbRM2wpXuRYrN8tytsoJCg0SvWEWwHAwLbCA==", "cpu": [ "arm64" ], @@ -3213,9 +4245,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.1.tgz", - "integrity": "sha512-SqNDY1+vpji7bh0sFH5wlWyFTOzjbDOl0/kB5RLLYDAFyd/uw3n7wyrmas3rYPpAW7z18lMOi1yKlTPv967E3g==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.4.tgz", + "integrity": "sha512-Gxq8jpgOWXwd0PUR+c9R2Ik1/uBnGd5GMIIzRRDqABCkvmjtC3KWcyhesV9jSPCz759isl0NlbsstZ2oyvk8lA==", "cpu": [ "x64" ], @@ -3227,9 +4259,9 @@ ] }, "node_modules/@lmdb/lmdb-win32-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.1.tgz", - "integrity": "sha512-50v0O1Lt37cwrmR9vWZK5hRW0Aw+KEmxJJ75fge/zIYdvNKB/0bSMSVR5Uc2OV9JhosIUyklOmrEvavwNJ8D6w==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.4.tgz", + "integrity": "sha512-pKv1DJ1bPZAaHkdFsSz5IDfUG8x9vntgquXF9/Dm2xuupcIe/EkLzylpoBxppFVK5vzbV561Dq26jNY2fIMA7g==", "cpu": [ "arm64" ], @@ -3241,9 +4273,9 @@ ] }, "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.1.tgz", - "integrity": "sha512-qwosvPyl+zpUlp3gRb7UcJ3H8S28XHCzkv0Y0EgQToXjQP91ZD67EHSCDmaLjtKhe+GVIW5om1KUpzVLA0l6pg==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.4.tgz", + "integrity": "sha512-JF1BmLCm9kGEVZgYmJq43zeQVdHVgAJnTi/NURWEsy6L1ZrrlSmdltS+D17QN4LODwf+1LMXAA9auIZVXtWwzw==", "cpu": [ "x64" ], @@ -3470,9 +4502,9 @@ "license": "MIT" }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz", - "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", + "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3914,26 +4946,7 @@ "win32" ], "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" + "node": ">= 10" } }, "node_modules/@ngneat/hotkeys": { @@ -4013,6 +5026,30 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/@npmcli/agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@npmcli/agent/node_modules/lru-cache": { "version": "11.5.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", @@ -4341,16 +5378,6 @@ "node": ">= 10" } }, - "node_modules/@oxc-project/types": { - "version": "0.113.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.113.0.tgz", - "integrity": "sha512-Tp3XmgxwNQ9pEN9vxgJBAqdRamHibi76iowQ38O2I4PMpcvNRQNVsU2n1x1nv9yh0XoTrGFzf7cZSGxmixxrhA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, "node_modules/@parcel/watcher": { "version": "2.5.6", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", @@ -4682,234 +5709,6 @@ "url": "https://opencollective.com/pkgr" } }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.4.tgz", - "integrity": "sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.4.tgz", - "integrity": "sha512-kFgEvkWLqt3YCgKB5re9RlIrx9bRsvyVUnaTakEpOPuLGzLpLapYxE9BufJNvPg8GjT6mB1alN4yN1NjzoeM8Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.4.tgz", - "integrity": "sha512-JXmaOJGsL/+rsmMfutcDjxWM2fTaVgCHGoXS7nE8Z3c9NAYjGqHvXrAhMUZvMpHS/k7Mg+X7n/MVKb7NYWKKww==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.4.tgz", - "integrity": "sha512-ep3Catd6sPnHTM0P4hNEvIv5arnDvk01PfyJIJ+J3wVCG1eEaPo09tvFqdtcaTrkwQy0VWR24uz+cb4IsK53Qw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.4.tgz", - "integrity": "sha512-LwA5ayKIpnsgXJEwWc3h8wPiS33NMIHd9BhsV92T8VetVAbGe2qXlJwNVDGHN5cOQ22R9uYvbrQir2AB+ntT2w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.4.tgz", - "integrity": "sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.4.tgz", - "integrity": "sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.4.tgz", - "integrity": "sha512-DZaN1f0PGp/bSvKhtw50pPsnln4T13ycDq1FrDWRiHmWt1JeW+UtYg9touPFf8yt993p8tS2QjybpzKNTxYEwg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.4.tgz", - "integrity": "sha512-RnGxwZLN7fhMMAItnD6dZ7lvy+TI7ba+2V54UF4dhaWa/p8I/ys1E73KO6HmPmgz92ZkfD8TXS1IMV8+uhbR9g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.4.tgz", - "integrity": "sha512-6lcI79+X8klGiGd8yHuTgQRjuuJYNggmEml+RsyN596P23l/zf9FVmJ7K0KVKkFAeYEdg0iMUKyIxiV5vebDNQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.4.tgz", - "integrity": "sha512-wz7ohsKCAIWy91blZ/1FlpPdqrsm1xpcEOQVveWoL6+aSPKL4VUcoYmmzuLTssyZxRpEwzuIxL/GDsvpjaBtOw==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^1.1.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.4.tgz", - "integrity": "sha512-cfiMrfuWCIgsFmcVG0IPuO6qTRHvF7NuG3wngX1RZzc6dU8FuBFb+J3MIR5WrdTNozlumfgL4cvz+R4ozBCvsQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.4.tgz", - "integrity": "sha512-p6UeR9y7ht82AH57qwGuFYn69S6CZ7LLKdCKy/8T3zS9VTrJei2/CGsTUV45Da4Z9Rbhc7G4gyWQ/Ioamqn09g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.4.tgz", - "integrity": "sha512-1BrrmTu0TWfOP1riA8uakjFc9bpIUGzVKETsOtzY39pPga8zELGDl8eu1Dx7/gjM5CAz14UknsUMpBO8L+YntQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.61.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.1.tgz", @@ -5239,47 +6038,148 @@ ], "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.1.tgz", + "integrity": "sha512-X+zaP2x+j4RXGfbp/seSoRHWnPxzApilDszisZxbYH5C/jTxFhCtDNdPGZb9lJyYPs24wGxruPF7Y+sIXt9Gzw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@schematics/angular": { + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-22.0.3.tgz", + "integrity": "sha512-iAUqIoRcK1CCHDm5E4Q1SI7rpVtsHJ+0qv5ll72wV3C1eCNdeDuGV0lX7PXEEkwd4y//s6yqI9o7f6VZZd6Fbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "22.0.3", + "@angular-devkit/schematics": "22.0.3", + "jsonc-parser": "3.3.1", + "typescript": "6.0.3" + }, + "engines": { + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.0.3.tgz", + "integrity": "sha512-pBjo1JKwI8GbNdTo/Z0g+ZekqlTBCJWmzIC5fgGW9q5eRjl1y+5N5jlX8UAyyMCeUTTwsfpQdkAM2jyi/jcvjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.20.0", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.4", + "rxjs": "7.8.2", + "source-map": "0.7.6" + }, + "engines": { + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^5.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@schematics/angular/node_modules/@angular-devkit/schematics": { + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-22.0.3.tgz", + "integrity": "sha512-aIp5sQDHdhyLbeVJF/k3w079XhW91mNAo2OliZllBCjoYhkIXNnWECOx5y2nXtCChyFJA2+ZgNST7NIDvtz1/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "22.0.3", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.21", + "ora": "9.4.0", + "rxjs": "7.8.2" + }, + "engines": { + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.1.tgz", - "integrity": "sha512-X+zaP2x+j4RXGfbp/seSoRHWnPxzApilDszisZxbYH5C/jTxFhCtDNdPGZb9lJyYPs24wGxruPF7Y+sIXt9Gzw==", - "cpu": [ - "x64" - ], + "node_modules/@schematics/angular/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } }, - "node_modules/@scarf/scarf": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", - "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", - "hasInstallScript": true, - "license": "Apache-2.0" + "node_modules/@schematics/angular/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } }, - "node_modules/@schematics/angular": { - "version": "21.2.15", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-21.2.15.tgz", - "integrity": "sha512-xdTirIUUegMXtyEDsYabCRcAnlVatVYb6S8v77fgK2eqUhGalI2e/3+L51N3XF1+6K2vEhyDpmmhFZLsdhLYbw==", + "node_modules/@schematics/angular/node_modules/ora": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-9.4.0.tgz", + "integrity": "sha512-84cglkRILFxdtA8hAvLNdMrtBpPNBTrQ9/ulg0FA7xLMnD6mifv+enAIeRmvtv+WgdCE+LPGOfQmtJRrVaIVhQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "21.2.15", - "@angular-devkit/schematics": "21.2.15", - "jsonc-parser": "3.3.1" + "chalk": "^5.6.2", + "cli-cursor": "^5.0.0", + "cli-spinners": "^3.2.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.1.0", + "log-symbols": "^7.0.1", + "stdin-discarder": "^0.3.2", + "string-width": "^8.1.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@sigstore/bundle": { @@ -5571,17 +6471,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", - "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/angular": { "version": "1.5.11", "resolved": "https://registry.npmjs.org/@types/angular/-/angular-1.5.11.tgz", @@ -5963,16 +6852,16 @@ } }, "node_modules/@vitejs/plugin-basic-ssl": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.4.tgz", - "integrity": "sha512-HXciTXN/sDBYWgeAD4V4s0DN0g72x5mlxQhHxtYu3Tt8BLa6MzcJZUyDVFCdtjNs3bfENVHVzOsmooTVuNgAAw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.3.0.tgz", + "integrity": "sha512-bdyo8rB3NnQbikdMpHaML9Z1OZPBu6fFOBo+OtxsBlvMJtysWskmBcnbIDhUqgC8tcxNv/a+BcV5U+2nQMm1OQ==", "dev": true, "license": "MIT", "engines": { "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "peerDependencies": { - "vite": "^6.0.0 || ^7.0.0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/@vitest/expect": { @@ -6178,13 +7067,13 @@ } }, "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz", + "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 14" + "node": ">= 20" } }, "node_modules/ajv": { @@ -6223,26 +7112,26 @@ } }, "node_modules/algoliasearch": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.48.1.tgz", - "integrity": "sha512-Rf7xmeuIo7nb6S4mp4abW2faW8DauZyE2faBIKFaUfP3wnpOvNSbiI5AwVhqBNj0jPgBWEvhyCu0sLjN2q77Rg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.52.0.tgz", + "integrity": "sha512-0ZzY9mjqV7gop/AH8pIBiAS8giXP7WcSiUfoFYIzYAK9QC5c37E4SIVtJVBMwlURc0/uNt2o4RcNRvdHa4CJ5w==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/abtesting": "1.14.1", - "@algolia/client-abtesting": "5.48.1", - "@algolia/client-analytics": "5.48.1", - "@algolia/client-common": "5.48.1", - "@algolia/client-insights": "5.48.1", - "@algolia/client-personalization": "5.48.1", - "@algolia/client-query-suggestions": "5.48.1", - "@algolia/client-search": "5.48.1", - "@algolia/ingestion": "1.48.1", - "@algolia/monitoring": "1.48.1", - "@algolia/recommend": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/abtesting": "1.18.0", + "@algolia/client-abtesting": "5.52.0", + "@algolia/client-analytics": "5.52.0", + "@algolia/client-common": "5.52.0", + "@algolia/client-insights": "5.52.0", + "@algolia/client-personalization": "5.52.0", + "@algolia/client-query-suggestions": "5.52.0", + "@algolia/client-search": "5.52.0", + "@algolia/ingestion": "1.52.0", + "@algolia/monitoring": "1.52.0", + "@algolia/recommend": "5.52.0", + "@algolia/requester-browser-xhr": "5.52.0", + "@algolia/requester-fetch": "5.52.0", + "@algolia/requester-node-http": "5.52.0" }, "engines": { "node": ">= 14.0.0" @@ -6705,9 +7594,9 @@ } }, "node_modules/beasties": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.4.1.tgz", - "integrity": "sha512-2Imdcw3LznDuxAbJM26RHniOLAzE6WgrK8OuvVXCQtNBS8rsnD9zsSEa3fHl4hHpUY7BYTlrpvtPVbvu9G6neg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.4.2.tgz", + "integrity": "sha512-NvcGjG/7AVUAfRbvrJmHunDQS9uHnE6Q/7AkaPr8oKE8HjOlpjRG5075z/th2Tmlezk3VlaaS8+X9I1RwHJMQw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -6780,22 +7669,36 @@ } }, "node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", "dev": true, "license": "MIT", "dependencies": { "bytes": "^3.1.2", - "content-type": "^1.0.5", + "content-type": "^2.0.0", "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" + }, + "engines": { + "node": ">=18" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -7371,13 +8274,6 @@ "color-support": "bin.js" } }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" - }, "node_modules/commander": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", @@ -8580,13 +9476,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -9257,6 +10146,23 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "license": "MIT" }, + "node_modules/fast-string-truncated-width": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-string-truncated-width": "^3.0.2" + } + }, "node_modules/fast-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", @@ -9274,6 +10180,16 @@ ], "license": "BSD-3-Clause" }, + "node_modules/fast-wrap-ansi": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz", + "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-string-width": "^3.0.2" + } + }, "node_modules/fastq": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", @@ -9872,9 +10788,9 @@ } }, "node_modules/hono": { - "version": "4.12.25", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.25.tgz", - "integrity": "sha512-2NFaIyNVgJmBs/ecmtGzlmluTFs5cHEWGTdu0t1HBwYzoGXOL5nUQBRMXsXWla5i4KkG//QMzVP88m1+I3fdAQ==", + "version": "4.12.26", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.26.tgz", + "integrity": "sha512-uyZtpnYxM9CmQ7QsQknM4zN8EftNqhON1qYeIKM0Se67CCEe2c44xyGURwB0axX2fBDu1dqHrHAc1hmNT8ITkw==", "dev": true, "license": "MIT", "engines": { @@ -10027,18 +10943,28 @@ "node": ">= 14" } }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.0.0.tgz", + "integrity": "sha512-/MVmHp58WkOypgFhCLk4fzpPcFQvTJ/e6LBI7irpIO2HfxUbpmYoHF+KzipzJpxxzJu7aJNWQ0xojJ/dzV2G5g==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" + "agent-base": "9.0.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 14" + "node": ">= 20" } }, "node_modules/husky": { @@ -10482,6 +11408,8 @@ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "license": "BSD-3-Clause", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -10492,6 +11420,8 @@ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "license": "BSD-3-Clause", + "optional": true, + "peer": true, "dependencies": { "@babel/core": "^7.23.9", "@babel/parser": "^7.23.9", @@ -11263,21 +12193,20 @@ "license": "MIT" }, "node_modules/listr2": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", - "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-10.2.1.tgz", + "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", "dev": true, "license": "MIT", "dependencies": { - "cli-truncate": "^5.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", + "cli-truncate": "^5.2.0", + "eventemitter3": "^5.0.4", "log-update": "^6.1.0", "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" + "wrap-ansi": "^10.0.0" }, "engines": { - "node": ">=20.0.0" + "node": ">=22.13.0" } }, "node_modules/listr2/node_modules/ansi-styles": { @@ -11293,13 +12222,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, "node_modules/listr2/node_modules/eventemitter3": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", @@ -11307,46 +12229,28 @@ "dev": true, "license": "MIT" }, - "node_modules/listr2/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/listr2/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.0.tgz", + "integrity": "sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "ansi-styles": "^6.2.3", + "string-width": "^8.2.0", + "strip-ansi": "^7.1.2" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/lmdb": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.5.1.tgz", - "integrity": "sha512-NYHA0MRPjvNX+vSw8Xxg6FLKxzAG+e7Pt8RqAQA/EehzHVXq9SxDqJIN3JL1hK0dweb884y8kIh6rkWvPyg9Wg==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.5.4.tgz", + "integrity": "sha512-9FKQA6G1MMtqNxfxvSBNXD/axeG2QRjYbNh0/ykRL5xYcRbCm2vXq7B9bhc7nSuKdHzr8/BHIwfPuYYH1UsXXw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -11363,13 +12267,13 @@ "download-lmdb-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "3.5.1", - "@lmdb/lmdb-darwin-x64": "3.5.1", - "@lmdb/lmdb-linux-arm": "3.5.1", - "@lmdb/lmdb-linux-arm64": "3.5.1", - "@lmdb/lmdb-linux-x64": "3.5.1", - "@lmdb/lmdb-win32-arm64": "3.5.1", - "@lmdb/lmdb-win32-x64": "3.5.1" + "@lmdb/lmdb-darwin-arm64": "3.5.4", + "@lmdb/lmdb-darwin-x64": "3.5.4", + "@lmdb/lmdb-linux-arm": "3.5.4", + "@lmdb/lmdb-linux-arm64": "3.5.4", + "@lmdb/lmdb-linux-x64": "3.5.4", + "@lmdb/lmdb-win32-arm64": "3.5.4", + "@lmdb/lmdb-win32-x64": "3.5.4" } }, "node_modules/load-json-file": { @@ -12112,13 +13016,13 @@ } }, "node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-3.0.0.tgz", + "integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==", "dev": true, "license": "ISC", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/mz": { @@ -12397,16 +13301,6 @@ "node": ">=20" } }, - "node_modules/node-gyp/node_modules/undici": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.26.0.tgz", - "integrity": "sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, "node_modules/node-gyp/node_modules/which": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", @@ -12910,12 +13804,13 @@ } }, "node_modules/pacote": { - "version": "21.3.1", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.3.1.tgz", - "integrity": "sha512-O0EDXi85LF4AzdjG74GUwEArhdvawi/YOHcsW6IijKNj7wm8IvEWNF5GnfuxNpQ/ZpO3L37+v8hqdVh8GgWYhg==", + "version": "21.5.1", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.5.1.tgz", + "integrity": "sha512-KvcJ9iy3crysCsgqc4+PknH/w6jkrp8JN36mpZBPwNaDRwTfMZD37YzRazNstiZUOhuF5pno9f78n9mEJBavwg==", "dev": true, "license": "ISC", "dependencies": { + "@gar/promise-retry": "^1.0.0", "@npmcli/git": "^7.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/package-json": "^7.0.0", @@ -12929,7 +13824,6 @@ "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", "sigstore": "^4.0.0", "ssri": "^13.0.0", "tar": "^7.4.3" @@ -13016,13 +13910,13 @@ } }, "node_modules/parse5-html-rewriting-stream": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-8.0.0.tgz", - "integrity": "sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-8.0.1.tgz", + "integrity": "sha512-NaRku2aMpUN1Sh1Gyk1KWUh2A7EJx2c6qYzvwsPtqhoHoaURshdrceYK3LunVCm3WHhm6FS7Vcczbvdh3/UIVw==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^6.0.0", + "entities": "^8.0.0", "parse5": "^8.0.0", "parse5-sax-parser": "^8.0.0" }, @@ -13031,13 +13925,13 @@ } }, "node_modules/parse5-html-rewriting-stream/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=0.12" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" @@ -13734,20 +14628,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -14268,16 +15148,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -14312,38 +15182,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rolldown": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.4.tgz", - "integrity": "sha512-V2tPDUrY3WSevrvU2E41ijZlpF+5PbZu4giH+VpNraaadsJGHa4fR6IFwsocVwEXDoAdIv5qgPPxgrvKAOIPtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@oxc-project/types": "=0.113.0", - "@rolldown/pluginutils": "1.0.0-rc.4" - }, - "bin": { - "rolldown": "bin/cli.mjs" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.4", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.4", - "@rolldown/binding-darwin-x64": "1.0.0-rc.4", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.4", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.4", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.4", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.4", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.4", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.4", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.4", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.4", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.4", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.4" - } - }, "node_modules/rollup": { "version": "4.61.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.1.tgz", @@ -15146,6 +15984,16 @@ "node": ">= 14" } }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/source-map": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", @@ -15726,13 +16574,13 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -16000,9 +16848,9 @@ } }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -16087,13 +16935,13 @@ } }, "node_modules/undici": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.4.tgz", - "integrity": "sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==", + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz", + "integrity": "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==", "dev": true, "license": "MIT", "engines": { - "node": ">=20.18.1" + "node": ">=18.17" } }, "node_modules/undici-types": { @@ -16242,9 +17090,9 @@ } }, "node_modules/vite": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", - "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.5.tgz", + "integrity": "sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==", "dev": true, "license": "MIT", "dependencies": { @@ -16837,24 +17685,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yoctocolors-cjs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", - "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/zod": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", - "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", - "dev": true, + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.2.tgz", + "integrity": "sha512-IynmDyxsEsb9RKzO3J9+4SxXnl2FTFSzNBaKKaMV6tsSk0rw9gYw9gs+JFCq/qk2LCZ78KDwyj+Z289TijSkUw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index f7646cab11..3d849a4a55 100644 --- a/package.json +++ b/package.json @@ -25,19 +25,19 @@ "keywords": [], "author": "", "dependencies": { - "@angular/animations": "^21.2.17", + "@angular/animations": "^22.0.2", "@angular/cdk": "^21.2.9", - "@angular/common": "^21.2.17", - "@angular/compiler": "^21.2.17", - "@angular/core": "^21.2.17", - "@angular/forms": "^21.2.17", + "@angular/common": "^22.0.2", + "@angular/compiler": "^22.0.2", + "@angular/core": "^22.0.2", + "@angular/forms": "^22.0.2", "@angular/material": "^21.2.9", "@angular/material-date-fns-adapter": "^21.2.9", - "@angular/platform-browser": "^21.2.17", - "@angular/platform-browser-dynamic": "^21.2.17", - "@angular/router": "^21.2.17", - "@angular/service-worker": "^21.2.17", - "@angular/upgrade": "^21.2.17", + "@angular/platform-browser": "^22.0.2", + "@angular/platform-browser-dynamic": "^22.0.2", + "@angular/router": "^22.0.2", + "@angular/service-worker": "^22.0.2", + "@angular/upgrade": "^22.0.2", "@ctrl/ngx-emoji-mart": "^9.3.0", "@eslint/js": "^10.0.1", "@ngneat/hotkeys": "^4.0.0", @@ -89,10 +89,10 @@ "@angular-eslint/eslint-plugin-template": "^21.4.0", "@angular-eslint/schematics": "^21.4.0", "@angular-eslint/template-parser": "^21.4.0", - "@angular/build": "^21.2.15", - "@angular/cli": "^21.2.15", - "@angular/compiler-cli": "^21.2.17", - "@angular/language-service": "^21.2.17", + "@angular/build": "^22.0.3", + "@angular/cli": "^22.0.3", + "@angular/compiler-cli": "^22.0.2", + "@angular/language-service": "^22.0.2", "@commitlint/cli": "^20.5.0", "@commitlint/config-conventional": "^21", "@trivago/prettier-plugin-sort-imports": "^6.0.2", @@ -122,7 +122,7 @@ "sass": "^1.48.0", "tailwindcss": "~3.4.17", "ts-node": "~10.9", - "typescript": "~5.9.3", + "typescript": "~6.0.3", "underscore": "^1.8.3", "vitest": "^4.1.8" }, diff --git a/src/app/account/edit-profile/edit-profile.component.ts b/src/app/account/edit-profile/edit-profile.component.ts index 3dc37b0c12..91e2c95b78 100644 --- a/src/app/account/edit-profile/edit-profile.component.ts +++ b/src/app/account/edit-profile/edit-profile.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core'; import {Router} from '@angular/router'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; @@ -6,6 +6,7 @@ import {AuthenticationService} from 'src/app/api/services/authentication.service selector: 'f-edit-profile', templateUrl: './edit-profile.component.html', styleUrls: ['./edit-profile.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class EditProfileComponent implements OnInit { diff --git a/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.ts b/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.ts index 47fb5c6210..b9899b934d 100644 --- a/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.ts +++ b/src/app/admin/institution-settings/activity-type-list/activity-type-list.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ViewChild} from '@angular/core'; +import {AfterViewInit, ChangeDetectionStrategy, Component, ViewChild} from '@angular/core'; import {UntypedFormControl, Validators} from '@angular/forms'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTable, MatTableDataSource} from '@angular/material/table'; @@ -10,6 +10,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'activity-type-list', templateUrl: 'activity-type-list.component.html', styleUrls: ['activity-type-list.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ActivityTypeListComponent diff --git a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts index a83d640a5f..0ba7c27ad8 100644 --- a/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts +++ b/src/app/admin/institution-settings/campuses/campus-list/campus-list.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ViewChild} from '@angular/core'; +import {AfterViewInit, ChangeDetectionStrategy, Component, ViewChild} from '@angular/core'; import {UntypedFormControl, Validators} from '@angular/forms'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTable, MatTableDataSource} from '@angular/material/table'; @@ -10,6 +10,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'campus-list', templateUrl: 'campus-list.component.html', styleUrls: ['campus-list.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class CampusListComponent extends EntityFormComponent implements AfterViewInit { diff --git a/src/app/admin/institution-settings/institution-settings.component.ts b/src/app/admin/institution-settings/institution-settings.component.ts index 5d859282f8..2914c7606c 100644 --- a/src/app/admin/institution-settings/institution-settings.component.ts +++ b/src/app/admin/institution-settings/institution-settings.component.ts @@ -1,10 +1,11 @@ -import {Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component} from '@angular/core'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; @Component({ selector: 'institution-settings', templateUrl: 'institution-settings.component.html', styleUrls: ['institution-settings.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class InstitutionSettingsComponent { diff --git a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts index 14f3a20f0c..fc427c320a 100644 --- a/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts +++ b/src/app/admin/institution-settings/overseer-images/overseer-image-list.component.ts @@ -1,5 +1,11 @@ import {HttpClient} from '@angular/common/http'; -import {AfterViewInit, Component, TemplateRef, ViewChild} from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + TemplateRef, + ViewChild, +} from '@angular/core'; import {UntypedFormControl, Validators} from '@angular/forms'; import {MatDialog} from '@angular/material/dialog'; import {MatSort, Sort} from '@angular/material/sort'; @@ -13,6 +19,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'overseer-image-list', templateUrl: 'overseer-image-list.component.html', styleUrls: ['overseer-image-list.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class OverseerImageListComponent diff --git a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.ts b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.ts index b9e6da9451..e844877f73 100644 --- a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.ts +++ b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal-content.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core'; import {MatDialogRef} from '@angular/material/dialog'; import {TeachingPeriod} from 'src/app/api/models/teaching-period'; import {TeachingPeriodService} from 'src/app/api/services/teaching-period.service'; @@ -8,6 +8,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; @Component({ selector: 'create-new-unit-modal-content', templateUrl: 'create-new-unit-modal-content.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class CreateNewUnitModalContentComponent implements OnInit { diff --git a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component.ts b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component.ts index 6096f86bcc..d3e7dde8f5 100644 --- a/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component.ts +++ b/src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component.ts @@ -1,10 +1,11 @@ -import {Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {CreateNewUnitModalContentComponent} from './create-new-unit-modal-content.component'; @Component({ selector: 'create-new-unit-modal', templateUrl: './create-new-unit-modal.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class CreateNewUnitModal { diff --git a/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.ts b/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.ts index 12415b42da..b61aeeb53c 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.ts +++ b/src/app/admin/states/teaching-periods/teaching-period-list/teaching-period-list.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnInit, ViewChild} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit, ViewChild} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog'; import {MatPaginator} from '@angular/material/paginator'; import {MatSort, Sort} from '@angular/material/sort'; @@ -14,6 +14,7 @@ import {TeachingPeriodUnitImportService} from '../teaching-period-unit-import/te selector: 'f-teaching-period-list', templateUrl: './teaching-period-list.component.html', styleUrls: ['./teaching-period-list.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TeachingPeriodListComponent implements OnInit { @@ -95,6 +96,7 @@ export class TeachingPeriodListComponent implements OnInit { @Component({ selector: 'f-new-teaching-period-dialog', templateUrl: 'new-teaching-period-dialog.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class NewTeachingPeriodDialogComponent { diff --git a/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts b/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts index 8b01596437..8dfefa5cb5 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts +++ b/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.ts @@ -1,4 +1,11 @@ -import {Component, Inject, Injectable, OnInit, ViewChild} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Inject, + Injectable, + OnInit, + ViewChild, +} from '@angular/core'; import {FormControl} from '@angular/forms'; import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog'; import {MatTable, MatTableDataSource} from '@angular/material/table'; @@ -50,6 +57,7 @@ export class TeachingPeriodUnitImportService { selector: 'f-teaching-period-unit-import', templateUrl: 'teaching-period-unit-import.dialog.html', styleUrls: ['teaching-period-unit-import.dialog.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TeachingPeriodUnitImportDialogComponent implements OnInit { diff --git a/src/app/admin/states/units/units.component.ts b/src/app/admin/states/units/units.component.ts index 7b224e13fe..86f03ab90d 100644 --- a/src/app/admin/states/units/units.component.ts +++ b/src/app/admin/states/units/units.component.ts @@ -1,4 +1,11 @@ -import {AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + Input, + OnInit, + ViewChild, +} from '@angular/core'; import {MatPaginator} from '@angular/material/paginator'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTable, MatTableDataSource} from '@angular/material/table'; @@ -33,6 +40,7 @@ interface IUnitOrProject { selector: 'f-units', templateUrl: './units.component.html', styleUrls: ['./units.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FUnitsComponent implements OnInit, AfterViewInit { diff --git a/src/app/admin/states/users/users.component.ts b/src/app/admin/states/users/users.component.ts index 6e3461172b..b75d603d61 100644 --- a/src/app/admin/states/users/users.component.ts +++ b/src/app/admin/states/users/users.component.ts @@ -1,4 +1,11 @@ -import {AfterViewInit, Component, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + OnDestroy, + OnInit, + ViewChild, +} from '@angular/core'; import {MatPaginator} from '@angular/material/paginator'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTable, MatTableDataSource} from '@angular/material/table'; @@ -14,6 +21,7 @@ import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; selector: 'f-users', templateUrl: './users.component.html', styleUrls: ['./users.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FUsersComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/src/app/admin/tii-action-log/tii-action-log.component.ts b/src/app/admin/tii-action-log/tii-action-log.component.ts index 545bbd177d..ae492f6773 100644 --- a/src/app/admin/tii-action-log/tii-action-log.component.ts +++ b/src/app/admin/tii-action-log/tii-action-log.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ViewChild} from '@angular/core'; +import {AfterViewInit, ChangeDetectionStrategy, Component, ViewChild} from '@angular/core'; import {MatPaginator} from '@angular/material/paginator'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTable, MatTableDataSource} from '@angular/material/table'; @@ -10,6 +10,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-tii-action-log', templateUrl: './tii-action-log.component.html', styleUrls: ['./tii-action-log.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TiiActionLogComponent implements AfterViewInit { diff --git a/src/app/api/services/spec/campus.service.spec.ts b/src/app/api/services/spec/campus.service.spec.ts index d96c869e4c..3373d5b15d 100644 --- a/src/app/api/services/spec/campus.service.spec.ts +++ b/src/app/api/services/spec/campus.service.spec.ts @@ -1,5 +1,10 @@ import {afterEach, beforeEach, describe, expect, it} from 'vitest'; -import {HttpRequest, provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; +import { + HttpRequest, + provideHttpClient, + withInterceptorsFromDi, + withXhr, +} from '@angular/common/http'; import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; import {TestBed} from '@angular/core/testing'; import {Campus} from 'src/app/api/models/doubtfire-model'; @@ -14,7 +19,7 @@ describe('CampusService', () => { imports: [], providers: [ CampusService, - provideHttpClient(withInterceptorsFromDi()), + provideHttpClient(withXhr(), withInterceptorsFromDi()), provideHttpClientTesting(), ], }); diff --git a/src/app/api/services/spec/user.service.spec.ts b/src/app/api/services/spec/user.service.spec.ts index 6f39dc81eb..2e03e7e9c4 100644 --- a/src/app/api/services/spec/user.service.spec.ts +++ b/src/app/api/services/spec/user.service.spec.ts @@ -1,5 +1,10 @@ import {afterEach, beforeEach, describe, expect, it} from 'vitest'; -import {HttpRequest, provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; +import { + HttpRequest, + provideHttpClient, + withInterceptorsFromDi, + withXhr, +} from '@angular/common/http'; import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; import {TestBed} from '@angular/core/testing'; import {User, UserService} from 'src/app/api/models/doubtfire-model'; @@ -13,7 +18,7 @@ describe('UserService', () => { imports: [], providers: [ UserService, - provideHttpClient(withInterceptorsFromDi()), + provideHttpClient(withXhr(), withInterceptorsFromDi()), provideHttpClientTesting(), ], }); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index adc62064a8..b5d35f7f32 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,10 +1,11 @@ -import {Component, OnDestroy, OnInit, Renderer2} from '@angular/core'; +import {ChangeDetectionStrategy, Component, OnDestroy, OnInit, Renderer2} from '@angular/core'; import {NavigationEnd, Router} from '@angular/router'; import {Subscription, filter} from 'rxjs'; @Component({ selector: 'app-root', templateUrl: './app.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class AppComponent implements OnInit, OnDestroy { diff --git a/src/app/common/archive-viewer/archive-viewer.component.ts b/src/app/common/archive-viewer/archive-viewer.component.ts index 6ea01d9949..ef08675259 100644 --- a/src/app/common/archive-viewer/archive-viewer.component.ts +++ b/src/app/common/archive-viewer/archive-viewer.component.ts @@ -1,6 +1,7 @@ import JSZip from 'jszip'; import {HttpClient, HttpResponse} from '@angular/common/http'; import { + ChangeDetectionStrategy, Component, EventEmitter, Input, @@ -39,6 +40,7 @@ interface ArchiveFileTreeNode { selector: 'f-archive-viewer', templateUrl: './archive-viewer.component.html', styleUrls: ['./archive-viewer.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ArchiveViewerComponent implements OnChanges, OnDestroy { diff --git a/src/app/common/audio-player/audio-player.component.ts b/src/app/common/audio-player/audio-player.component.ts index d72d61ae11..e1f14e8b4f 100644 --- a/src/app/common/audio-player/audio-player.component.ts +++ b/src/app/common/audio-player/audio-player.component.ts @@ -1,5 +1,13 @@ import {HttpResponse} from '@angular/common/http'; -import {Component, ElementRef, Inject, Input, OnDestroy, ViewChild} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + Inject, + Input, + OnDestroy, + ViewChild, +} from '@angular/core'; import {Project, Task, TaskComment} from 'src/app/api/models/doubtfire-model'; import {FileDownloaderService} from '../file-downloader/file-downloader.service'; import {AlertService} from '../services/alert.service'; @@ -8,6 +16,7 @@ import {AlertService} from '../services/alert.service'; selector: 'audio-player', templateUrl: './audio-player.component.html', styleUrls: ['./audio-player.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class AudioPlayerComponent implements OnDestroy { diff --git a/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.ts b/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.ts index b326da25f9..cf6fbf25aa 100644 --- a/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.ts +++ b/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {Task, TaskComment, TaskCommentService} from 'src/app/api/models/doubtfire-model'; import {AlertService} from 'src/app/common/services/alert.service'; import {MediaRecorderService} from 'src/app/common/services/recorder-service'; @@ -8,6 +8,7 @@ import {BaseAudioRecorderComponent} from '../base-audio-recorder'; selector: 'audio-comment-recorder', templateUrl: './audio-comment-recorder.html', providers: [MediaRecorderService], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class AudioCommentRecorderComponent extends BaseAudioRecorderComponent implements OnInit { diff --git a/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester.component.ts b/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester.component.ts index 07a5559d16..ddbdba7851 100644 --- a/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester.component.ts +++ b/src/app/common/audio-recorder/audio/microphone-tester/microphone-tester.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, Input} from '@angular/core'; +import {AfterViewInit, ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Task} from 'src/app/api/models/doubtfire-model'; import {MediaRecorderService} from 'src/app/common/services/recorder-service'; import {BaseAudioRecorderComponent} from '../base-audio-recorder'; @@ -7,6 +7,7 @@ import {BaseAudioRecorderComponent} from '../base-audio-recorder'; selector: 'microphone-tester', templateUrl: './microphone-tester-component.html', providers: [MediaRecorderService], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class MicrophoneTesterComponent extends BaseAudioRecorderComponent implements AfterViewInit { diff --git a/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts b/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts index 58e2cc25c6..e54f546dcc 100644 --- a/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts +++ b/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts @@ -1,5 +1,5 @@ import {TooltipService} from '@swimlane/ngx-charts'; -import {Component, ViewContainerRef} from '@angular/core'; +import {ChangeDetectionStrategy, Component, ViewContainerRef} from '@angular/core'; import {AppInjector} from 'src/app/app-injector'; /** @@ -10,6 +10,7 @@ import {AppInjector} from 'src/app/app-injector'; */ @Component({ templateUrl: './chart-base-component.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ChartBaseComponent { diff --git a/src/app/common/edit-profile-form/edit-profile-form.component.ts b/src/app/common/edit-profile-form/edit-profile-form.component.ts index 0e9605f118..fbc51a92d6 100644 --- a/src/app/common/edit-profile-form/edit-profile-form.component.ts +++ b/src/app/common/edit-profile-form/edit-profile-form.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, Input, OnInit, Optional} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Input, OnInit, Optional} from '@angular/core'; import {MAT_DIALOG_DATA} from '@angular/material/dialog'; import {MatSnackBar} from '@angular/material/snack-bar'; import {Router} from '@angular/router'; @@ -11,6 +11,7 @@ import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; selector: 'f-edit-profile-form', templateUrl: './edit-profile-form.component.html', styleUrls: ['./edit-profile-form.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class EditProfileFormComponent implements OnInit { diff --git a/src/app/common/f-chip/chip.component.ts b/src/app/common/f-chip/chip.component.ts index ff926f0556..6aa6222a72 100644 --- a/src/app/common/f-chip/chip.component.ts +++ b/src/app/common/f-chip/chip.component.ts @@ -1,9 +1,10 @@ -import {Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component} from '@angular/core'; @Component({ selector: 'f-chip', templateUrl: './chip.component.html', styleUrls: ['./chip.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FChipComponent {} diff --git a/src/app/common/feedback-template-editor/feedback-template-editor.component.ts b/src/app/common/feedback-template-editor/feedback-template-editor.component.ts index 69b1f24ed1..82e3dcb16c 100644 --- a/src/app/common/feedback-template-editor/feedback-template-editor.component.ts +++ b/src/app/common/feedback-template-editor/feedback-template-editor.component.ts @@ -1,4 +1,12 @@ -import {AfterViewInit, Component, Input, OnChanges, SimpleChanges, ViewChild} from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + SimpleChanges, + ViewChild, +} from '@angular/core'; import {MatPaginator} from '@angular/material/paginator'; import {MatSelectChange} from '@angular/material/select'; import {MatSort, Sort} from '@angular/material/sort'; @@ -23,6 +31,7 @@ import {CsvUploadModalService} from '../modals/csv-upload-modal/csv-upload-modal @Component({ selector: 'f-feedback-template-editor', templateUrl: 'feedback-template-editor.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FeedbackTemplateEditorComponent implements OnChanges, AfterViewInit { diff --git a/src/app/common/file-drop/file-drop.component.html b/src/app/common/file-drop/file-drop.component.html index d4615a73f4..fe4f73c8a9 100644 --- a/src/app/common/file-drop/file-drop.component.html +++ b/src/app/common/file-drop/file-drop.component.html @@ -37,7 +37,9 @@ (click)="uploadProgress ? cancelUpload() : upload()" > @if (!uploadProgress) { - upload + upload } @if (uploadProgress) { cancel diff --git a/src/app/common/file-drop/file-drop.component.ts b/src/app/common/file-drop/file-drop.component.ts index ea4e8ec7cd..610dc4cbe3 100644 --- a/src/app/common/file-drop/file-drop.component.ts +++ b/src/app/common/file-drop/file-drop.component.ts @@ -1,5 +1,5 @@ import {HttpClient, HttpErrorResponse, HttpEventType, HttpResponse} from '@angular/common/http'; -import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core'; import {Subscription, throwError} from 'rxjs'; import {AlertService} from '../services/alert.service'; @@ -10,6 +10,7 @@ import {AlertService} from '../services/alert.service'; selector: 'f-file-drop', templateUrl: 'file-drop.component.html', styleUrls: ['file-drop.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FileDropComponent { diff --git a/src/app/common/file-uploader/file-uploader.component.html b/src/app/common/file-uploader/file-uploader.component.html index 900c616b27..72443ddca0 100644 --- a/src/app/common/file-uploader/file-uploader.component.html +++ b/src/app/common/file-uploader/file-uploader.component.html @@ -128,7 +128,10 @@
      Upload Summary
      - + } diff --git a/src/app/common/file-uploader/file-uploader.component.ts b/src/app/common/file-uploader/file-uploader.component.ts index c4a6653f49..a3b47f8830 100644 --- a/src/app/common/file-uploader/file-uploader.component.ts +++ b/src/app/common/file-uploader/file-uploader.component.ts @@ -1,4 +1,5 @@ import { + ChangeDetectionStrategy, Component, EventEmitter, Input, @@ -79,6 +80,7 @@ export const ACCEPTED_TYPES = { selector: 'f-file-uploader', templateUrl: './file-uploader.component.html', styleUrls: ['./file-uploader.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FileUploaderComponent implements OnInit, OnChanges { diff --git a/src/app/common/file-viewer/file-viewer.component.ts b/src/app/common/file-viewer/file-viewer.component.ts index ae6ae795d1..c034f471d3 100644 --- a/src/app/common/file-viewer/file-viewer.component.ts +++ b/src/app/common/file-viewer/file-viewer.component.ts @@ -1,6 +1,13 @@ import {PDFProgressData} from 'ng2-pdf-viewer'; import {HttpResponse} from '@angular/common/http'; -import {Component, Input, OnChanges, OnDestroy, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnDestroy, + SimpleChanges, +} from '@angular/core'; import {FileDownloaderService} from '../file-downloader/file-downloader.service'; import {AlertService} from '../services/alert.service'; @@ -11,6 +18,7 @@ import {AlertService} from '../services/alert.service'; selector: 'f-file-viewer', templateUrl: './file-viewer.component.html', styleUrls: ['./file-viewer.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FileViewerComponent implements OnDestroy, OnChanges { diff --git a/src/app/common/footer/footer.component.ts b/src/app/common/footer/footer.component.ts index d0a0836ad1..9278ba3da7 100644 --- a/src/app/common/footer/footer.component.ts +++ b/src/app/common/footer/footer.component.ts @@ -1,4 +1,12 @@ -import {Component, ElementRef, HostListener, Input, OnInit, ViewChild} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + HostListener, + Input, + OnInit, + ViewChild, +} from '@angular/core'; import {Observable} from 'rxjs'; import {Task} from 'src/app/api/models/task'; import {UnitRole} from 'src/app/api/models/unit-role'; @@ -16,6 +24,7 @@ import {AlertService} from '../services/alert.service'; selector: 'f-footer', templateUrl: './footer.component.html', styleUrls: ['./footer.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FooterComponent implements OnInit { diff --git a/src/app/common/grade-icon/grade-icon.component.ts b/src/app/common/grade-icon/grade-icon.component.ts index a07bf1c238..f99a8ee817 100644 --- a/src/app/common/grade-icon/grade-icon.component.ts +++ b/src/app/common/grade-icon/grade-icon.component.ts @@ -1,11 +1,19 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import {GradeService} from '../services/grade.service'; @Component({ selector: 'f-grade-icon', templateUrl: './grade-icon.component.html', styleUrls: ['./grade-icon.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class GradeIconComponent implements OnInit, OnChanges { diff --git a/src/app/common/header/header.component.ts b/src/app/common/header/header.component.ts index 68ebc4dd99..a5859dc65f 100644 --- a/src/app/common/header/header.component.ts +++ b/src/app/common/header/header.component.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import {MediaObserver} from 'ng-flex-layout'; -import {Component, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, OnDestroy, OnInit} from '@angular/core'; import {Router} from '@angular/router'; import {Subscription, asapScheduler, observeOn} from 'rxjs'; import { @@ -27,6 +27,7 @@ import {IsActiveUnitRole} from '../pipes/is-active-unit-role.pipe'; selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class HeaderComponent implements OnInit, OnDestroy { diff --git a/src/app/common/header/task-dropdown/task-dropdown.component.ts b/src/app/common/header/task-dropdown/task-dropdown.component.ts index 6230c70764..08d3b0e861 100644 --- a/src/app/common/header/task-dropdown/task-dropdown.component.ts +++ b/src/app/common/header/task-dropdown/task-dropdown.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {ActivatedRoute, NavigationEnd, Router} from '@angular/router'; import {filter} from 'rxjs'; import {Project, Unit, UnitRole} from 'src/app/api/models/doubtfire-model'; @@ -9,6 +9,7 @@ import {TutorNotesModalService} from '../../modals/tutor-notes-modal/tutor-notes selector: 'task-dropdown', templateUrl: './task-dropdown.component.html', styleUrls: ['./task-dropdown.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDropdownComponent { diff --git a/src/app/common/header/unit-dropdown/unit-dropdown.component.html b/src/app/common/header/unit-dropdown/unit-dropdown.component.html index 3bf5b0c19f..8a3927d771 100644 --- a/src/app/common/header/unit-dropdown/unit-dropdown.component.html +++ b/src/app/common/header/unit-dropdown/unit-dropdown.component.html @@ -6,7 +6,7 @@ [isDropdown]="true" [matMenuTriggerFor]="menu" [shiftBetweenBadges]="false" - [unit_code]="unit?.code" + [unit_code]="$safeNavigationMigration(unit?.code)" [width]="80" > {{ menuState.menuOpen ? 'arrow_drop_up' : 'arrow_drop_down' }} diff --git a/src/app/common/header/unit-dropdown/unit-dropdown.component.ts b/src/app/common/header/unit-dropdown/unit-dropdown.component.ts index f32bb06acc..4190257424 100644 --- a/src/app/common/header/unit-dropdown/unit-dropdown.component.ts +++ b/src/app/common/header/unit-dropdown/unit-dropdown.component.ts @@ -1,11 +1,12 @@ import {MediaObserver} from 'ng-flex-layout'; -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Project, Unit, UnitRole} from 'src/app/api/models/doubtfire-model'; @Component({ selector: 'unit-dropdown', templateUrl: './unit-dropdown.component.html', styleUrls: ['./unit-dropdown.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitDropdownComponent { diff --git a/src/app/common/hero-sidebar/hero-sidebar.component.ts b/src/app/common/hero-sidebar/hero-sidebar.component.ts index 7c47c46a5e..7c54a7bd8c 100644 --- a/src/app/common/hero-sidebar/hero-sidebar.component.ts +++ b/src/app/common/hero-sidebar/hero-sidebar.component.ts @@ -1,10 +1,11 @@ -import {Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component} from '@angular/core'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; @Component({ selector: 'f-hero-sidebar', templateUrl: './hero-sidebar.component.html', styleUrls: ['./hero-sidebar.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class HeroSidebarComponent { diff --git a/src/app/common/learning-outcome-editor/learning-outcome-editor.component.ts b/src/app/common/learning-outcome-editor/learning-outcome-editor.component.ts index d5801ed011..7b141d5cbb 100644 --- a/src/app/common/learning-outcome-editor/learning-outcome-editor.component.ts +++ b/src/app/common/learning-outcome-editor/learning-outcome-editor.component.ts @@ -3,6 +3,7 @@ import {LiveAnnouncer} from '@angular/cdk/a11y'; import {COMMA, ENTER} from '@angular/cdk/keycodes'; import { AfterViewInit, + ChangeDetectionStrategy, Component, Input, OnChanges, @@ -44,6 +45,7 @@ import {NestedCsvDownloadModalService} from './nested-csv-download-modal/nested- @Component({ selector: 'f-learning-outcome-editor', templateUrl: 'learning-outcome-editor.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class LearningOutcomeEditorComponent implements OnChanges, OnInit, AfterViewInit, OnDestroy { diff --git a/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.ts b/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.ts index 1c072924cf..d17b8fd895 100644 --- a/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.ts +++ b/src/app/common/learning-outcome-editor/nested-csv-download-modal/nested-csv-download-modal.component.ts @@ -1,10 +1,11 @@ -import {Component, Inject} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {FileDownloaderService} from '../../file-downloader/file-downloader.service'; @Component({ selector: 'f-nested-csv-download-modal', templateUrl: './nested-csv-download-modal.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class NestedCsvDownloadModalComponent { diff --git a/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.component.ts b/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.component.ts index df9295c025..e0cdf53f73 100644 --- a/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.component.ts +++ b/src/app/common/modals/about-doubtfire-modal/about-doubtfire-modal.component.ts @@ -1,7 +1,7 @@ // // Modal to show Doubtfire version info // -import {Component, Inject, Injectable} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Injectable} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialog} from '@angular/material/dialog'; import {Sort} from '@angular/material/sort'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; @@ -12,6 +12,7 @@ import {GithubProfile} from './github-profile'; @Component({ selector: 'about-doubtfire-dialog', templateUrl: 'about-doubtfire-modal-content.tpl.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class AboutDoubtfireModalContent { diff --git a/src/app/common/modals/calendar-modal/calendar-modal.component.ts b/src/app/common/modals/calendar-modal/calendar-modal.component.ts index 40e5856c6e..9d464eca36 100644 --- a/src/app/common/modals/calendar-modal/calendar-modal.component.ts +++ b/src/app/common/modals/calendar-modal/calendar-modal.component.ts @@ -1,4 +1,11 @@ -import {AfterViewInit, Component, Inject, OnInit, ViewChild} from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + Inject, + OnInit, + ViewChild, +} from '@angular/core'; import {MAT_DIALOG_DATA} from '@angular/material/dialog'; import {MatSlideToggle} from '@angular/material/slide-toggle'; import {Project, ProjectService, Webcal, WebcalService} from 'src/app/api/models/doubtfire-model'; @@ -10,6 +17,7 @@ import {ConfirmationModalService} from '../confirmation-modal/confirmation-modal selector: 'calendar-modal', templateUrl: './calendar-modal.component.html', styleUrls: ['./calendar-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class CalendarModalComponent implements OnInit, AfterViewInit { diff --git a/src/app/common/modals/comments-modal/comments-modal.component.ts b/src/app/common/modals/comments-modal/comments-modal.component.ts index 197162b588..7cb5d80dc3 100644 --- a/src/app/common/modals/comments-modal/comments-modal.component.ts +++ b/src/app/common/modals/comments-modal/comments-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Input, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA} from '@angular/material/dialog'; import {TaskComment} from 'src/app/api/models/doubtfire-model'; @@ -11,6 +11,7 @@ export interface CommentsModalData { selector: 'comments-modal', templateUrl: './comments-modal.component.html', styleUrls: ['./comments-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class CommentsModalComponent implements OnInit { diff --git a/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts b/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts index dea3e5fad4..5427fc020c 100644 --- a/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts +++ b/src/app/common/modals/confirmation-modal/confirmation-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Input, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {AlertService} from '../../services/alert.service'; @@ -15,6 +15,7 @@ export interface ConfirmationModalData { selector: 'confirmation-modal', templateUrl: './confirmation-modal.component.html', styleUrls: ['./confirmation-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ConfirmationModalComponent implements OnInit { diff --git a/src/app/common/modals/csv-result-modal/csv-result-modal.component.ts b/src/app/common/modals/csv-result-modal/csv-result-modal.component.ts index b5f3bea79a..8d1f1a6d70 100644 --- a/src/app/common/modals/csv-result-modal/csv-result-modal.component.ts +++ b/src/app/common/modals/csv-result-modal/csv-result-modal.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, Inject, ViewChild} from '@angular/core'; +import {AfterViewInit, ChangeDetectionStrategy, Component, Inject, ViewChild} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {MatPaginator} from '@angular/material/paginator'; import {MatTableDataSource} from '@angular/material/table'; @@ -16,6 +16,7 @@ interface CsvDisplayRow { selector: 'f-csv-result-modal', templateUrl: './csv-result-modal.component.html', styleUrls: ['./csv-result-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class CsvResultModalComponent implements AfterViewInit { diff --git a/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.ts b/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.ts index 76d58e1ac6..809dd0abae 100644 --- a/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.ts +++ b/src/app/common/modals/csv-upload-modal/csv-upload-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; export interface CsvUploadFileSpec { @@ -20,6 +20,7 @@ export interface CsvUploadModalData { selector: 'f-csv-upload-modal', templateUrl: './csv-upload-modal.component.html', styleUrls: ['./csv-upload-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class CsvUploadModalComponent { diff --git a/src/app/common/modals/date-change-modal/task-date-slider.component.ts b/src/app/common/modals/date-change-modal/task-date-slider.component.ts index 6ffa383a0a..5947ff626a 100644 --- a/src/app/common/modals/date-change-modal/task-date-slider.component.ts +++ b/src/app/common/modals/date-change-modal/task-date-slider.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnChanges, SimpleChanges} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges} from '@angular/core'; import {Task} from 'src/app/api/models/doubtfire-model'; import {MappingFunctions} from 'src/app/api/services/mapping-fn'; import {AlertService} from '../../services/alert.service'; @@ -8,6 +8,7 @@ import {ConfirmationModalService} from '../confirmation-modal/confirmation-modal selector: 'f-task-date-slider', styleUrl: './task-date-slider.component.scss', templateUrl: './task-date-slider.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDateSliderComponent implements OnChanges { diff --git a/src/app/common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.component.ts b/src/app/common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.component.ts index 84206f6236..0166f2fc3d 100644 --- a/src/app/common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.component.ts +++ b/src/app/common/modals/discussed-in-class-reason-modal/discussed-in-class-reason-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; export interface DiscussedInClassReasonModalData { @@ -11,6 +11,7 @@ export interface DiscussedInClassReasonModalData { selector: 'f-discussed-in-class-reason-modal', templateUrl: './discussed-in-class-reason-modal.component.html', styleUrl: './discussed-in-class-reason-modal.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class DiscussedInClassReasonModalComponent { diff --git a/src/app/common/modals/extension-modal/extension-modal.component.ts b/src/app/common/modals/extension-modal/extension-modal.component.ts index 9ae3da2c81..70ff977b6b 100644 --- a/src/app/common/modals/extension-modal/extension-modal.component.ts +++ b/src/app/common/modals/extension-modal/extension-modal.component.ts @@ -1,5 +1,5 @@ import {addDays, differenceInDays, differenceInWeeks, isAfter} from 'date-fns'; -import {Component, Inject, LOCALE_ID} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, LOCALE_ID} from '@angular/core'; import {FormControl, FormGroup, FormGroupDirective, NgForm, Validators} from '@angular/forms'; import {ErrorStateMatcher} from '@angular/material/core'; import {MatDatepickerInputEvent} from '@angular/material/datepicker'; @@ -19,6 +19,7 @@ export class ReasonErrorStateMatcher implements ErrorStateMatcher { @Component({ selector: 'extension-modal', templateUrl: './extension-modal.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ExtensionModalComponent { diff --git a/src/app/common/modals/qr-modal/qr-modal.component.ts b/src/app/common/modals/qr-modal/qr-modal.component.ts index 072f319ba2..92f1784ee7 100644 --- a/src/app/common/modals/qr-modal/qr-modal.component.ts +++ b/src/app/common/modals/qr-modal/qr-modal.component.ts @@ -1,5 +1,5 @@ import QRCode from 'qrcode'; -import {Component, Inject, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA} from '@angular/material/dialog'; import {QrModalData} from './qr-modal.service'; @@ -7,6 +7,7 @@ import {QrModalData} from './qr-modal.service'; selector: 'f-qr-modal', templateUrl: './qr-modal.component.html', styleUrls: ['./qr-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class QrModalComponent implements OnInit { diff --git a/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.ts b/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.ts index 9ebb0f1ac5..8322724d1b 100644 --- a/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.ts +++ b/src/app/common/modals/scorm-extension-modal/scorm-extension-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, LOCALE_ID} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, LOCALE_ID} from '@angular/core'; import {FormControl, FormGroup, FormGroupDirective, NgForm, Validators} from '@angular/forms'; import {ErrorStateMatcher} from '@angular/material/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; @@ -17,6 +17,7 @@ export class ReasonErrorStateMatcher implements ErrorStateMatcher { @Component({ selector: 'f-scorm-extension-modal', templateUrl: './scorm-extension-modal.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ScormExtensionModalComponent { diff --git a/src/app/common/modals/sidekiq-jobs-modal/sidekiq-jobs-modal.component.ts b/src/app/common/modals/sidekiq-jobs-modal/sidekiq-jobs-modal.component.ts index 3cc938e9b3..dceebc3455 100644 --- a/src/app/common/modals/sidekiq-jobs-modal/sidekiq-jobs-modal.component.ts +++ b/src/app/common/modals/sidekiq-jobs-modal/sidekiq-jobs-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit} from '@angular/core'; import {MatDialogRef} from '@angular/material/dialog'; import {SidekiqJobEntry, SidekiqJobService} from 'src/app/api/services/sidekiq-job.service'; import {SidekiqProgressModalService} from 'src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.service'; @@ -8,6 +8,7 @@ import {AlertService} from '../../services/alert.service'; selector: 'f-sidekiq-jobs-modal', templateUrl: './sidekiq-jobs-modal.component.html', styleUrl: './sidekiq-jobs-modal.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class SidekiqJobsModalComponent implements OnInit { diff --git a/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.ts b/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.ts index e5fd5e5cf1..440d1ebf5d 100644 --- a/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.ts +++ b/src/app/common/modals/sidekiq-progress-modal/sidekiq-progress-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {MatSnackBar} from '@angular/material/snack-bar'; import {Subject} from 'rxjs'; @@ -18,6 +18,7 @@ export interface SidekiqProgressModalData { selector: 'f-sidekiq-progress-modal', templateUrl: './sidekiq-progress-modal.component.html', styleUrl: './sidekiq-progress-modal.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class SidekiqProgressModalComponent implements OnInit, OnDestroy { diff --git a/src/app/common/modals/spec-con-modal/spec-con-modal.component.ts b/src/app/common/modals/spec-con-modal/spec-con-modal.component.ts index 64eba3bf2a..ee96ac0396 100644 --- a/src/app/common/modals/spec-con-modal/spec-con-modal.component.ts +++ b/src/app/common/modals/spec-con-modal/spec-con-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {Project} from 'src/app/api/models/doubtfire-model'; import {AlertService} from '../../services/alert.service'; @@ -6,6 +6,7 @@ import {AlertService} from '../../services/alert.service'; @Component({ selector: 'f-spec-con-modal', templateUrl: './spec-con-modal.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class SpecConModalComponent { diff --git a/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.ts b/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.ts index c560b4b20c..c37611915f 100644 --- a/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.ts +++ b/src/app/common/modals/task-assessment-modal/task-assessment-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Input, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {Subject} from 'rxjs'; import {Task} from 'src/app/api/models/doubtfire-model'; @@ -8,6 +8,7 @@ import {TaskAssessmentModalData} from './task-assessment-modal.service'; selector: 'task-assessment-modal', templateUrl: './task-assessment-modal.component.html', styleUrls: ['./task-assessment-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskAssessmentModalComponent implements OnInit { diff --git a/src/app/common/modals/tutor-notes-modal/tutor-notes-modal.component.ts b/src/app/common/modals/tutor-notes-modal/tutor-notes-modal.component.ts index 097684ace0..bb34f4495f 100644 --- a/src/app/common/modals/tutor-notes-modal/tutor-notes-modal.component.ts +++ b/src/app/common/modals/tutor-notes-modal/tutor-notes-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA} from '@angular/material/dialog'; import {Task} from 'src/app/api/models/task'; import {UnitRole} from 'src/app/api/models/unit-role'; @@ -8,6 +8,7 @@ import {TutorNotesModalData} from './tutor-notes-modal.service'; selector: 'f-tutor-notes-modal', templateUrl: './tutor-notes-modal.component.html', styleUrl: './tutor-notes-modal.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TutorNotesModalComponent implements OnInit { diff --git a/src/app/common/obect-select/object-select.component.ts b/src/app/common/obect-select/object-select.component.ts index 3be3019985..386429f338 100644 --- a/src/app/common/obect-select/object-select.component.ts +++ b/src/app/common/obect-select/object-select.component.ts @@ -1,4 +1,4 @@ -import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core'; import {MatSelectChange} from '@angular/material/select'; /** @@ -9,6 +9,7 @@ import {MatSelectChange} from '@angular/material/select'; @Component({ selector: 'object-select', templateUrl: 'object-select.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ObjectSelectComponent { diff --git a/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.ts b/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.ts index c1e38cf8f5..5fa911c55a 100644 --- a/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.ts +++ b/src/app/common/pdf-viewer-panel/pdf-viewer-panel.component.ts @@ -1,10 +1,11 @@ -import {Component, Inject, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Input} from '@angular/core'; import {FileDownloaderService} from '../file-downloader/file-downloader.service'; @Component({ selector: 'pdf-viewer-panel', templateUrl: './pdf-viewer-panel.component.html', styleUrls: ['./pdf-viewer-panel.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PdfViewerPanelComponent { diff --git a/src/app/common/pdf-viewer/pdf-viewer.component.ts b/src/app/common/pdf-viewer/pdf-viewer.component.ts index a6b1ca914c..a8a2de519f 100644 --- a/src/app/common/pdf-viewer/pdf-viewer.component.ts +++ b/src/app/common/pdf-viewer/pdf-viewer.component.ts @@ -2,6 +2,7 @@ import {PDFDocumentProxy, PdfViewerComponent} from 'ng2-pdf-viewer'; import {HttpResponse} from '@angular/common/http'; import { AfterViewInit, + ChangeDetectionStrategy, Component, Inject, Input, @@ -17,6 +18,7 @@ import {AlertService} from '../services/alert.service'; selector: 'f-pdf-viewer', templateUrl: './pdf-viewer.component.html', styleUrls: ['./pdf-viewer.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class fPdfViewerComponent implements OnDestroy, OnChanges, AfterViewInit { diff --git a/src/app/common/project-progress-bar/project-progress-bar.component.ts b/src/app/common/project-progress-bar/project-progress-bar.component.ts index 9a1db3bd5c..d1935aa561 100644 --- a/src/app/common/project-progress-bar/project-progress-bar.component.ts +++ b/src/app/common/project-progress-bar/project-progress-bar.component.ts @@ -1,9 +1,10 @@ -import {Component, Input, OnChanges, SimpleChanges} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges} from '@angular/core'; @Component({ selector: 'f-project-progress-bar', templateUrl: './project-progress-bar.component.html', styleUrls: ['./project-progress-bar.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProjectProgressBarComponent implements OnChanges { diff --git a/src/app/common/project-progress/project-progress-gauge.component.ts b/src/app/common/project-progress/project-progress-gauge.component.ts index 8ed44e122c..75a4249481 100644 --- a/src/app/common/project-progress/project-progress-gauge.component.ts +++ b/src/app/common/project-progress/project-progress-gauge.component.ts @@ -1,11 +1,19 @@ import {TooltipService} from '@swimlane/ngx-charts'; -import {Component, Injector, Input, OnInit, ViewContainerRef} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Injector, + Input, + OnInit, + ViewContainerRef, +} from '@angular/core'; import {Project} from 'src/app/api/models/project'; @Component({ selector: 'f-project-progress-gauge', templateUrl: './project-progress-gauge.component.html', styleUrl: './project-progress-gauge.component.css', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProjectProgressGaugeComponent implements OnInit { diff --git a/src/app/common/scorm-player/scorm-player.component.ts b/src/app/common/scorm-player/scorm-player.component.ts index c4897d905a..7c33c459e9 100644 --- a/src/app/common/scorm-player/scorm-player.component.ts +++ b/src/app/common/scorm-player/scorm-player.component.ts @@ -1,4 +1,4 @@ -import {Component, HostListener, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, HostListener, Input, OnInit} from '@angular/core'; import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser'; import {ActivatedRoute} from '@angular/router'; import { @@ -30,6 +30,7 @@ declare global { selector: 'f-scorm-player', templateUrl: './scorm-player.component.html', styleUrls: ['./scorm-player.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ScormPlayerComponent implements OnInit { diff --git a/src/app/common/services/alert.service.ts b/src/app/common/services/alert.service.ts index 4b26a8ae23..bf27c6f386 100644 --- a/src/app/common/services/alert.service.ts +++ b/src/app/common/services/alert.service.ts @@ -1,4 +1,4 @@ -import {Component, Inject, Injectable, inject} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Injectable, inject} from '@angular/core'; import {MAT_SNACK_BAR_DATA, MatSnackBar, MatSnackBarRef} from '@angular/material/snack-bar'; import {ConfettiService} from './confetti.service'; @@ -49,6 +49,7 @@ export class AlertService { @Component({ selector: 'f-alert', templateUrl: './alert.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class AlertComponent { diff --git a/src/app/common/status-icon/status-icon.component.ts b/src/app/common/status-icon/status-icon.component.ts index 56e2cf060a..7a9667694a 100644 --- a/src/app/common/status-icon/status-icon.component.ts +++ b/src/app/common/status-icon/status-icon.component.ts @@ -1,10 +1,11 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {TaskStatus, TaskStatusEnum} from 'src/app/api/models/task-status'; @Component({ selector: 'status-icon', templateUrl: './status-icon.component.html', styleUrls: ['./status-icon.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class StatusIconComponent implements OnInit { diff --git a/src/app/common/submission-files-download/submission-files-download.component.ts b/src/app/common/submission-files-download/submission-files-download.component.ts index 386000446b..5d0e75f629 100644 --- a/src/app/common/submission-files-download/submission-files-download.component.ts +++ b/src/app/common/submission-files-download/submission-files-download.component.ts @@ -1,5 +1,5 @@ import {HttpResponse} from '@angular/common/http'; -import {Component, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {FileDownloaderService} from '../file-downloader/file-downloader.service'; @@ -9,6 +9,7 @@ type DownloadState = 'downloading' | 'downloaded' | 'failed'; @Component({ selector: 'f-submission-files-download', templateUrl: './submission-files-download.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class SubmissionFilesDownloadComponent implements OnInit { diff --git a/src/app/common/success-close/success-close.component.ts b/src/app/common/success-close/success-close.component.ts index b635087ff9..558e7b7ecc 100644 --- a/src/app/common/success-close/success-close.component.ts +++ b/src/app/common/success-close/success-close.component.ts @@ -1,9 +1,10 @@ -import {Component, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core'; @Component({ selector: 'f-success-close', templateUrl: 'success-close.component.html', styleUrls: ['success-close.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class SuccessCloseComponent implements OnInit { diff --git a/src/app/common/task-badge/task-badge.component.ts b/src/app/common/task-badge/task-badge.component.ts index 6fd3950704..9868e4fb80 100644 --- a/src/app/common/task-badge/task-badge.component.ts +++ b/src/app/common/task-badge/task-badge.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; @Component({ selector: 'f-task-badge', templateUrl: './task-badge.component.html', styleUrl: './task-badge.component.css', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FTaskBadgeComponent { diff --git a/src/app/common/unit-code/unit-code.component.ts b/src/app/common/unit-code/unit-code.component.ts index fb28c4eba0..a01278f7dc 100644 --- a/src/app/common/unit-code/unit-code.component.ts +++ b/src/app/common/unit-code/unit-code.component.ts @@ -1,5 +1,5 @@ import {animate, state, style, transition, trigger} from '@angular/animations'; -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {Subscription} from 'rxjs'; import {UnitCodeService} from './unit-code.service'; @@ -20,6 +20,7 @@ import {UnitCodeService} from './unit-code.service'; ]), ]), ], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitCodeComponent implements OnInit, OnDestroy { diff --git a/src/app/common/user-badge/user-badge.component.html b/src/app/common/user-badge/user-badge.component.html index 4baab5ced6..8b407dcf87 100644 --- a/src/app/common/user-badge/user-badge.component.html +++ b/src/app/common/user-badge/user-badge.component.html @@ -8,7 +8,7 @@ size="40" style="margin-right: 8px" [unselected]="unselected" - [user]="selectedTask?.project.student" + [user]="$safeNavigationMigration(selectedTask?.project.student)" >
      diff --git a/src/app/common/user-badge/user-badge.component.ts b/src/app/common/user-badge/user-badge.component.ts index cd57a75e36..52f1a7b93d 100644 --- a/src/app/common/user-badge/user-badge.component.ts +++ b/src/app/common/user-badge/user-badge.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Task} from 'src/app/api/models/doubtfire-model'; @Component({ selector: 'f-user-badge', templateUrl: './user-badge.component.html', styleUrls: ['./user-badge.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UserBadgeComponent { diff --git a/src/app/common/user-icon/user-icon.component.ts b/src/app/common/user-icon/user-icon.component.ts index 7073ba6999..dd2f25058a 100644 --- a/src/app/common/user-icon/user-icon.component.ts +++ b/src/app/common/user-icon/user-icon.component.ts @@ -1,6 +1,7 @@ import {Md5} from 'ts-md5/dist/md5'; import { AfterViewInit, + ChangeDetectionStrategy, Component, ElementRef, Input, @@ -42,6 +43,7 @@ declare const d3: { selector: 'user-icon', templateUrl: './user-icon.component.html', styleUrls: ['./user-icon.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UserIconComponent implements AfterViewInit, OnChanges { diff --git a/src/app/config/privacy-policy/privacy-policy.spec.ts b/src/app/config/privacy-policy/privacy-policy.spec.ts index 4371a4c972..634447dd0a 100644 --- a/src/app/config/privacy-policy/privacy-policy.spec.ts +++ b/src/app/config/privacy-policy/privacy-policy.spec.ts @@ -1,5 +1,5 @@ import {afterEach, beforeEach, describe, expect, it} from 'vitest'; -import {provideHttpClient} from '@angular/common/http'; +import {provideHttpClient, withXhr} from '@angular/common/http'; import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; import {TestBed} from '@angular/core/testing'; import {PrivacyPolicy} from './privacy-policy'; @@ -10,7 +10,7 @@ describe('PrivacyPolicy', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [provideHttpClient(), provideHttpClientTesting()], + providers: [provideHttpClient(withXhr()), provideHttpClientTesting()], }); service = TestBed.inject(PrivacyPolicy); httpMock = TestBed.inject(HttpTestingController); diff --git a/src/app/errors/states/timeout/timeout.component.ts b/src/app/errors/states/timeout/timeout.component.ts index 94730d3043..b9b4094231 100644 --- a/src/app/errors/states/timeout/timeout.component.ts +++ b/src/app/errors/states/timeout/timeout.component.ts @@ -1,9 +1,10 @@ -import {Component, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, OnDestroy, OnInit} from '@angular/core'; import {AuthenticationService} from '../../../api/services/authentication.service'; @Component({ selector: 'f-timeout', templateUrl: 'timeout.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TimeoutComponent implements OnInit, OnDestroy { diff --git a/src/app/errors/states/unauthorised/unauthorised.component.ts b/src/app/errors/states/unauthorised/unauthorised.component.ts index 289a4ad067..da3f9dddb8 100644 --- a/src/app/errors/states/unauthorised/unauthorised.component.ts +++ b/src/app/errors/states/unauthorised/unauthorised.component.ts @@ -1,10 +1,11 @@ import {Location} from '@angular/common'; -import {Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component} from '@angular/core'; @Component({ selector: 'unauthorised', templateUrl: 'unauthorised.component.html', styleUrls: ['unauthorised.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnauthorisedComponent { diff --git a/src/app/errors/unavailable-card/unavailable-card.component.ts b/src/app/errors/unavailable-card/unavailable-card.component.ts index 51709816b8..f949856e31 100644 --- a/src/app/errors/unavailable-card/unavailable-card.component.ts +++ b/src/app/errors/unavailable-card/unavailable-card.component.ts @@ -1,9 +1,10 @@ -import {Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component} from '@angular/core'; @Component({ selector: 'f-unavailable-card', templateUrl: './unavailable-card.component.html', styleUrls: ['./unavailable-card.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnavailableCardComponent {} diff --git a/src/app/eula/accept-eula/accept-eula.component.ts b/src/app/eula/accept-eula/accept-eula.component.ts index 17d24aeec5..a8c0ede0e0 100644 --- a/src/app/eula/accept-eula/accept-eula.component.ts +++ b/src/app/eula/accept-eula/accept-eula.component.ts @@ -1,4 +1,4 @@ -import {Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component} from '@angular/core'; import {Router} from '@angular/router'; import {Observable, ReplaySubject, take} from 'rxjs'; import {UserService} from 'src/app/api/models/doubtfire-model'; @@ -10,6 +10,7 @@ import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; selector: 'f-accept-eula', templateUrl: './accept-eula.component.html', styleUrls: ['./accept-eula.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class AcceptEulaComponent { diff --git a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.ts b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.ts index f96cfc1266..6f75ea24ea 100644 --- a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.ts +++ b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.component.ts @@ -1,4 +1,5 @@ import { + ChangeDetectionStrategy, Component, EventEmitter, Input, @@ -18,6 +19,7 @@ import {Task} from 'src/app/api/models/task'; selector: 'f-group-member-contribution-assigner', templateUrl: './group-member-contribution-assigner.component.html', styleUrls: ['./group-member-contribution-assigner.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class GroupMemberContributionAssignerComponent implements OnInit, OnChanges { diff --git a/src/app/groups/group-member-list/group-member-list.component.ts b/src/app/groups/group-member-list/group-member-list.component.ts index 6d752d67d8..162c552139 100644 --- a/src/app/groups/group-member-list/group-member-list.component.ts +++ b/src/app/groups/group-member-list/group-member-list.component.ts @@ -1,4 +1,11 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import {MatTableDataSource} from '@angular/material/table'; import {Subscription} from 'rxjs'; import {Group, UnitRole} from 'src/app/api/models/doubtfire-model'; @@ -10,6 +17,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-group-member-list', templateUrl: './group-member-list.component.html', styleUrls: ['./group-member-list.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class GroupMemberListComponent implements OnInit, OnChanges { diff --git a/src/app/groups/group-selector/group-selector.component.ts b/src/app/groups/group-selector/group-selector.component.ts index 4dd8ed7de3..0a9b475738 100644 --- a/src/app/groups/group-selector/group-selector.component.ts +++ b/src/app/groups/group-selector/group-selector.component.ts @@ -1,5 +1,6 @@ import { AfterViewInit, + ChangeDetectionStrategy, Component, Input, OnChanges, @@ -23,6 +24,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-group-selector', templateUrl: './group-selector.component.html', styleUrls: ['./group-selector.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class GroupSelectorComponent diff --git a/src/app/groups/group-set-manager/group-set-manager.component.ts b/src/app/groups/group-set-manager/group-set-manager.component.ts index 6a214c6ee8..5d986592e6 100644 --- a/src/app/groups/group-set-manager/group-set-manager.component.ts +++ b/src/app/groups/group-set-manager/group-set-manager.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {FormControl} from '@angular/forms'; import {Observable, map, startWith} from 'rxjs'; import {Group, GroupSet, Project, Unit, UnitRole} from 'src/app/api/models/doubtfire-model'; @@ -9,6 +9,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-group-set-manager', templateUrl: './group-set-manager.component.html', styleUrls: ['./group-set-manager.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class GroupSetManagerComponent implements OnInit { diff --git a/src/app/groups/group-set-selector/group-set-selector.component.ts b/src/app/groups/group-set-selector/group-set-selector.component.ts index 10430346cd..b6b7103d67 100644 --- a/src/app/groups/group-set-selector/group-set-selector.component.ts +++ b/src/app/groups/group-set-selector/group-set-selector.component.ts @@ -1,10 +1,18 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + OnInit, + Output, +} from '@angular/core'; import {GroupSet, Unit} from 'src/app/api/models/doubtfire-model'; @Component({ selector: 'group-set-selector', templateUrl: './group-set-selector.component.html', styleUrls: ['./group-set-selector.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class GroupSetSelectorComponent implements OnInit { diff --git a/src/app/home/splash-screen/splash-screen.component.ts b/src/app/home/splash-screen/splash-screen.component.ts index 18b1ca48b8..f53ae1d1ad 100644 --- a/src/app/home/splash-screen/splash-screen.component.ts +++ b/src/app/home/splash-screen/splash-screen.component.ts @@ -1,5 +1,5 @@ import {AnimationOptions} from 'ngx-lottie'; -import {Component, ContentChild, OnInit, TemplateRef} from '@angular/core'; +import {ChangeDetectionStrategy, Component, ContentChild, OnInit, TemplateRef} from '@angular/core'; import {Observable} from 'rxjs'; import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; import {LoadingService} from './LoadingService.service'; @@ -8,6 +8,7 @@ import {LoadingService} from './LoadingService.service'; selector: 'splash-screen', templateUrl: './splash-screen.component.html', styleUrls: ['./splash-screen.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class SplashScreenComponent implements OnInit { diff --git a/src/app/home/states/home/home.component.html b/src/app/home/states/home/home.component.html index cdeeb9af4e..2ae5a92d86 100644 --- a/src/app/home/states/home/home.component.html +++ b/src/app/home/states/home/home.component.html @@ -19,7 +19,15 @@

      Units you teach

      @for (unitRole of unitRoles | isActiveUnitRole; track unitRole) {
      @if (!unitRole.unit.teachingPeriod || unitRole.unit.teachingPeriod?.active) { -
      +
      {{ unitRole.unit?.name }} @@ -55,7 +63,7 @@

      Units you teach

      You do not teach any active units

      diff --git a/src/app/home/states/home/home.component.ts b/src/app/home/states/home/home.component.ts index fe4f807fc9..a384d1ff64 100644 --- a/src/app/home/states/home/home.component.ts +++ b/src/app/home/states/home/home.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit} from '@angular/core'; import {Router} from '@angular/router'; import {Subscription} from 'rxjs'; import {Project, UnitRole, User, UserService} from 'src/app/api/models/doubtfire-model'; @@ -10,6 +10,7 @@ import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global selector: 'home', templateUrl: 'home.component.html', styleUrls: ['home.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class HomeComponent implements OnInit, OnDestroy { diff --git a/src/app/home/states/lti-dashboard/lti-dashboard.component.ts b/src/app/home/states/lti-dashboard/lti-dashboard.component.ts index 8b821f3612..dd775f824d 100644 --- a/src/app/home/states/lti-dashboard/lti-dashboard.component.ts +++ b/src/app/home/states/lti-dashboard/lti-dashboard.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, Input} from '@angular/core'; +import {AfterViewInit, ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {ProjectService, User} from 'src/app/api/models/doubtfire-model'; import {Unit} from 'src/app/api/models/unit'; @@ -15,6 +15,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-lti-dashboard', templateUrl: 'lti-dashboard.component.html', styleUrls: ['lti-dashboard.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class LtiDashboardComponent implements AfterViewInit { diff --git a/src/app/home/states/lti-unit-link/lti-unit-link.component.ts b/src/app/home/states/lti-unit-link/lti-unit-link.component.ts index 9319ce2067..74f4c8bbb3 100644 --- a/src/app/home/states/lti-unit-link/lti-unit-link.component.ts +++ b/src/app/home/states/lti-unit-link/lti-unit-link.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, Input} from '@angular/core'; +import {AfterViewInit, ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {CreateNewUnitModal} from 'src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component'; import {Unit} from 'src/app/api/models/unit'; @@ -13,6 +13,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-lti-unit-link', templateUrl: 'lti-unit-link.component.html', styleUrls: ['lti-unit-link.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class LtiUnitLinkComponent implements AfterViewInit { diff --git a/src/app/legacy-route-placeholder.component.ts b/src/app/legacy-route-placeholder.component.ts index a08dfc603c..dc364e55dc 100644 --- a/src/app/legacy-route-placeholder.component.ts +++ b/src/app/legacy-route-placeholder.component.ts @@ -1,9 +1,10 @@ -import {Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component} from '@angular/core'; @Component({ selector: 'legacy-route-placeholder', templateUrl: './legacy-route-placeholder.component.html', styleUrl: './legacy-route-placeholder.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class LegacyRoutePlaceholderComponent {} diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.ts b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.ts index bc26d55292..c08e4f6934 100644 --- a/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.ts +++ b/src/app/projects/project-progress-dashboard/project-progress-dashboard.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, type OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, type OnInit} from '@angular/core'; import {Observable} from 'rxjs'; import {Project} from 'src/app/api/models/project'; import {ProjectService} from 'src/app/api/services/project.service'; @@ -9,6 +9,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; selector: 'f-project-progress-dashboard', templateUrl: './project-progress-dashboard.component.html', styleUrl: './project-progress-dashboard.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProjectProgressDashboardComponent implements OnInit { diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.ts index f3e3019c7a..3ceeff6ff8 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/add-engagement-dialog/add-engagement-dialog.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject} from '@angular/core'; import {FormControl, FormGroup, Validators} from '@angular/forms'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {Engagement, EngagementService, Project} from 'src/app/api/models/doubtfire-model'; @@ -19,6 +19,7 @@ interface AddEngagementForm { selector: 'f-add-engagement-dialog', templateUrl: './add-engagement-dialog.component.html', styleUrl: './add-engagement-dialog.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class AddEngagementDialogComponent { diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.ts index d86b756544..e64a8007d5 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-detail-dialog/engagement-detail-dialog.component.ts @@ -1,4 +1,12 @@ -import {Component, ElementRef, Inject, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + Inject, + OnDestroy, + OnInit, + ViewChild, +} from '@angular/core'; import {MAT_DIALOG_DATA} from '@angular/material/dialog'; import { Engagement, @@ -14,6 +22,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-engagement-detail-dialog', templateUrl: './engagement-detail-dialog.component.html', styleUrl: './engagement-detail-dialog.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class EngagementDetailDialogComponent implements OnInit, OnDestroy { diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.ts index 8ef0cc2706..560e609555 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/engagement-passport-card/engagement-passport-card.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnChanges} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnChanges} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import { Engagement, @@ -36,6 +36,7 @@ interface EngagementLegendItem extends EngagementPresentation { selector: 'f-engagement-passport-card', templateUrl: './engagement-passport-card.component.html', styleUrl: './engagement-passport-card.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class EngagementPassportCardComponent implements OnChanges { diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts index 621544ee18..f840db6819 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts @@ -1,4 +1,11 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + OnInit, + Output, +} from '@angular/core'; import {Project} from 'src/app/api/models/project'; import {ProjectService} from 'src/app/api/services/project.service'; import {UserService} from 'src/app/api/services/user.service'; @@ -9,6 +16,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; selector: 'f-progress-dashboard', templateUrl: './progress-dashboard.component.html', styleUrls: ['./progress-dashboard.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProgressDashboardComponent implements OnInit { diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts index 8f10cc0c38..c3d77da113 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/task-planner-card/task-planner-card.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Project} from 'src/app/api/models/project'; @Component({ selector: 'f-task-planner-card', templateUrl: './task-planner-card.component.html', styleUrl: './task-planner-card.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskPlannerCardComponent { diff --git a/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.ts b/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.ts index 47792337ab..3c8b138d06 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.ts +++ b/src/app/projects/states/dashboard/directives/student-task-list/create-portfolio-task-list-item/create-portfolio-task-list-item.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Project, Task} from 'src/app/api/models/doubtfire-model'; @Component({ selector: 'create-portfolio-task-list-item', templateUrl: 'create-portfolio-task-list-item.component.html', styleUrls: ['create-portfolio-task-list-item.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class CreatePortfolioTaskListItemComponent { diff --git a/src/app/projects/states/dashboard/directives/student-task-list/task-list-item/task-list-item.component.ts b/src/app/projects/states/dashboard/directives/student-task-list/task-list-item/task-list-item.component.ts index a8612c44ba..2f2351cc40 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/task-list-item/task-list-item.component.ts +++ b/src/app/projects/states/dashboard/directives/student-task-list/task-list-item/task-list-item.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {Task} from 'src/app/api/models/doubtfire-model'; import {GradeService} from 'src/app/common/services/grade.service'; @@ -6,6 +6,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; selector: 'task-list-item', templateUrl: 'task-list-item.component.html', styleUrls: ['task-list-item.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskListItemComponent implements OnInit { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts index 43ae248427..864f64226f 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/discussion-prompts-view/discussion-prompts-view.component.ts @@ -1,9 +1,10 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; @Component({ selector: 'f-discussion-prompts-view', templateUrl: './discussion-prompts-view.component.html', styleUrls: ['./discussion-prompts-view.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class DiscussionPromptsViewComponent { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.ts index 7f7d38039d..e61a9d1a43 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/staff-notes-view/staff-notes-view.component.ts @@ -1,9 +1,10 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; @Component({ selector: 'f-staff-notes-view', templateUrl: './staff-notes-view.component.html', styleUrls: ['./staff-notes-view.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class StaffNotesViewComponent { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.ts index 8047e45479..0b04db98a9 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-assessment-card/task-assessment-card.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Task} from 'src/app/api/models/task'; import {TaskService} from 'src/app/api/services/task.service'; import {GradeService} from 'src/app/common/services/grade.service'; @@ -7,6 +7,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; selector: 'f-task-assessment-card', templateUrl: './task-assessment-card.component.html', styleUrls: ['./task-assessment-card.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskAssessmentCardComponent { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html index 4269449855..b13dee8ab3 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html @@ -6,7 +6,10 @@
      -
      +
      @if (task) { } diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.ts index bb41a679a3..eaf85a0273 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.ts @@ -1,4 +1,11 @@ -import {Component, EventEmitter, Inject, Input, Output} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Inject, + Input, + Output, +} from '@angular/core'; import {Task, TaskDefinition, Unit} from 'src/app/api/models/doubtfire-model'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {GradeService} from 'src/app/common/services/grade.service'; @@ -7,6 +14,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; selector: 'f-task-description-card', templateUrl: 'task-description-card.component.html', styleUrls: ['task-description-card.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDescriptionCardComponent { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html index 1bd23719a9..0e308f0ffa 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.html @@ -15,13 +15,13 @@ @if (flexibleDatesEnabled) { -

      +

      Your target due date for this task is {{ task?.localDueDateString() }}. You should aim to complete this task before then to keep your progress on track.

      } @else { -

      +

      This task's due date is {{ task?.localDueDateString() }}. You should aim to complete this task before then to keep your progress on track.

      @@ -68,7 +68,10 @@ - + @if (flexibleDatesEnabled) {

      @@ -125,7 +128,10 @@ > - +

      @if (task?.definition?.unit.markLateSubmissionsAsAssessInPortfolio) { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.ts index 1e100f72b8..4cba264c1b 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-due-card/task-due-card.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Task} from 'src/app/api/models/task'; @Component({ selector: 'f-task-due-card', templateUrl: './task-due-card.component.html', styleUrls: ['./task-due-card.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDueCardComponent { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.ts index 5033a187b2..033e5d5b6a 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-ilos-card/task-ilos-card.component.ts @@ -1,4 +1,11 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import {LearningOutcome} from 'src/app/api/models/learning-outcome'; import {Project} from 'src/app/api/models/project'; import {TaskDefinition} from 'src/app/api/models/task-definition'; @@ -8,6 +15,7 @@ import {Unit} from 'src/app/api/models/unit'; selector: 'f-task-ilos-card', templateUrl: './task-ilos-card.component.html', styleUrls: ['./task-ilos-card.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskIlosCardComponent implements OnInit, OnChanges { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html index a5cf691e16..92a1481c32 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.html @@ -56,7 +56,7 @@

      [ngTemplateOutletContext]="{ number: data.comparedWithNumber, isMostRecent: data.comparedWithIsMostRecent, - timestamp: data.comparedWith?.timestamp, + timestamp: $safeNavigationMigration(data.comparedWith?.timestamp), }" > @if (primaryArchiveParsed) { @@ -193,8 +193,8 @@

      } @else { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts index 47d19f2a7e..5a1cce8f98 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/submission-files-modal/submission-files-modal.component.ts @@ -1,6 +1,6 @@ import * as monaco from 'monaco-editor'; import {HttpResponse} from '@angular/common/http'; -import {Component, Inject, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {SubmissionArchive} from 'src/app/api/models/submission-history'; import { @@ -25,6 +25,7 @@ export interface SubmissionFilesModalData { selector: 'f-submission-files-modal', templateUrl: './submission-files-modal.component.html', styleUrls: ['./submission-files-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class SubmissionFilesModalComponent implements OnInit, OnDestroy { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts index d9868ab3ef..8906c1de07 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-overseer-report/task-overseer-report.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {MatMenuTrigger} from '@angular/material/menu'; import {forkJoin} from 'rxjs'; @@ -15,6 +15,7 @@ import {SubmissionFilesModalComponent} from './submission-files-modal/submission selector: 'f-task-overseer-report', templateUrl: './task-overseer-report.component.html', styleUrl: './task-overseer-report.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskOverseerReportComponent implements OnInit { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-prerequisites-card/task-prerequisites-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-prerequisites-card/task-prerequisites-card.component.ts index 490847af90..659232c1c8 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-prerequisites-card/task-prerequisites-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-prerequisites-card/task-prerequisites-card.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Task} from 'src/app/api/models/task'; import {TaskDefinition} from 'src/app/api/models/task-definition'; @@ -6,6 +6,7 @@ import {TaskDefinition} from 'src/app/api/models/task-definition'; selector: 'f-task-prerequisites-card', templateUrl: './task-prerequisites-card.component.html', styleUrls: ['./task-prerequisites-card.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskPrerequisitesCardComponent { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts index bbf0af2fb4..9839c23679 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-scorm-card/task-scorm-card.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnChanges, SimpleChanges} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges} from '@angular/core'; import {Task, User, UserService} from 'src/app/api/models/doubtfire-model'; import {ScormExtensionModalService} from 'src/app/common/modals/scorm-extension-modal/scorm-extension-modal.service'; @@ -6,6 +6,7 @@ import {ScormExtensionModalService} from 'src/app/common/modals/scorm-extension- selector: 'f-task-scorm-card', templateUrl: './task-scorm-card.component.html', styleUrls: ['./task-scorm-card.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskScormCardComponent implements OnChanges { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html index 4893c99cb4..c96b1d69bc 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html @@ -17,7 +17,10 @@

      Similarities

      @if (!jplagOpenState) { - @for (similarity of task?.similarityCache.values | async; track similarity) { + @for ( + similarity of $safeNavigationMigration(task?.similarityCache.values) | async; + track similarity + ) {
      @for (part of similarity.parts; track part; let i = $index) { - +

      {{ task?.statusLabel() }}

      @@ -26,7 +29,10 @@
      {{ trigger.label }}
      @if (triggers?.length < 0) { - +
      {{ task?.statusLabel() }}
      diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts index 75e00023fb..a66b5f81fe 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts @@ -1,5 +1,13 @@ import * as _ from 'lodash'; -import {AfterViewInit, Component, Input, OnChanges, OnDestroy, SimpleChanges} from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnDestroy, + SimpleChanges, +} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {Subscription} from 'rxjs'; import {Project} from 'src/app/api/models/project'; @@ -18,6 +26,7 @@ import {SubmissionTypeModalService} from 'src/app/tasks/modals/submission-type-m selector: 'f-task-status-card', templateUrl: './task-status-card.component.html', styleUrls: ['./task-status-card.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskStatusCardComponent implements OnChanges, AfterViewInit, OnDestroy { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.ts index 1b9c53bd75..1af683d9ad 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-submission-card/task-submission-card.component.ts @@ -1,4 +1,11 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import {Task} from 'src/app/api/models/task'; import {TaskService} from 'src/app/api/services/task.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; @@ -8,6 +15,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-task-submission-card', templateUrl: './task-submission-card.component.html', styleUrls: ['./task-submission-card.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskSubmissionCardComponent implements OnChanges, OnInit { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.ts index 3e58ce563c..6b44ee689b 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/tutor-notes-view/tutor-notes-view.component.ts @@ -1,10 +1,11 @@ -import {Component, Input, OnChanges, SimpleChanges} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges} from '@angular/core'; import {UnitRole} from 'src/app/api/models/unit-role'; @Component({ selector: 'f-tutor-notes-view', templateUrl: './tutor-notes-view.component.html', styleUrls: ['./tutor-notes-view.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TutorNotesViewComponent implements OnChanges { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts index 7aecf1173d..cc98b75399 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/task-dashboard.component.ts @@ -1,4 +1,11 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import {MatTabChangeEvent} from '@angular/material/tabs'; import {ActivatedRoute} from '@angular/router'; import {UnitRole} from 'src/app/api/models/doubtfire-model'; @@ -13,6 +20,7 @@ import {DashboardViews} from '../../selected-task.service'; selector: 'f-task-dashboard', templateUrl: './task-dashboard.component.html', styleUrls: ['./task-dashboard.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDashboardComponent implements OnInit, OnChanges { diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts index 189b177e34..fc38e38e41 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import {CdkDragEnd, CdkDragMove, CdkDragStart} from '@angular/cdk/drag-drop'; -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import { BehaviorSubject, @@ -23,6 +23,7 @@ import {GlobalStateService, ViewType} from '../../index/global-state.service'; selector: 'f-project-dashboard', templateUrl: './project-dashboard.component.html', styleUrl: './project-dashboard.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProjectDashboardComponent implements OnInit { diff --git a/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts b/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts index be33473189..cc81e95a94 100644 --- a/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts +++ b/src/app/projects/states/discussion-prompts/discussion-prompts.component.ts @@ -1,4 +1,11 @@ -import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + Input, + OnInit, + ViewChild, +} from '@angular/core'; import {DiscussionPrompt} from 'src/app/api/models/discussion-prompt'; import {Project, TaskDefinition, UserService} from 'src/app/api/models/doubtfire-model'; import {StaffNote} from 'src/app/api/models/staff-note'; @@ -10,6 +17,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-discussion-prompts', templateUrl: './discussion-prompts.component.html', styleUrl: './discussion-prompts.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class DiscussionPromptsComponent implements OnInit { diff --git a/src/app/projects/states/groups/project-groups-state.component.ts b/src/app/projects/states/groups/project-groups-state.component.ts index afe151bbf1..5d46a7c7c4 100644 --- a/src/app/projects/states/groups/project-groups-state.component.ts +++ b/src/app/projects/states/groups/project-groups-state.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {Observable, Subscription, of} from 'rxjs'; import {GroupSet, Project} from 'src/app/api/models/doubtfire-model'; @@ -8,6 +8,7 @@ import {GlobalStateService} from '../index/global-state.service'; selector: 'f-project-groups-state', templateUrl: './project-groups-state.component.html', styleUrls: ['./project-groups-state.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProjectGroupsStateComponent implements OnInit, OnDestroy { diff --git a/src/app/projects/states/groups/project-groups/project-groups.component.ts b/src/app/projects/states/groups/project-groups/project-groups.component.ts index 21f88722ec..6e64ae5f43 100644 --- a/src/app/projects/states/groups/project-groups/project-groups.component.ts +++ b/src/app/projects/states/groups/project-groups/project-groups.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {GroupSet, Project} from 'src/app/api/models/doubtfire-model'; import {Unit} from 'src/app/api/models/unit'; @@ -7,6 +7,7 @@ import {Unit} from 'src/app/api/models/unit'; selector: 'f-project-groups', templateUrl: './project-groups.component.html', styleUrl: './project-groups.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProjectGroupsComponent { diff --git a/src/app/projects/states/jplag/jplag-report-viewer.component.ts b/src/app/projects/states/jplag/jplag-report-viewer.component.ts index 28da488d6b..09f9bff4db 100644 --- a/src/app/projects/states/jplag/jplag-report-viewer.component.ts +++ b/src/app/projects/states/jplag/jplag-report-viewer.component.ts @@ -1,9 +1,10 @@ -import {Component, ElementRef, Input, ViewChild} from '@angular/core'; +import {ChangeDetectionStrategy, Component, ElementRef, Input, ViewChild} from '@angular/core'; import {AlertService} from 'src/app/common/services/alert.service'; @Component({ selector: 'f-jplag-report-viewer', templateUrl: './jplag-report-viewer.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class JplagReportViewerComponent { diff --git a/src/app/projects/states/plan/project-plan.component.ts b/src/app/projects/states/plan/project-plan.component.ts index 8a2a591ea9..42ae46547f 100644 --- a/src/app/projects/states/plan/project-plan.component.ts +++ b/src/app/projects/states/plan/project-plan.component.ts @@ -1,4 +1,11 @@ -import {Component, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnDestroy, + OnInit, + ViewChild, +} from '@angular/core'; import {MatSelectChange} from '@angular/material/select'; import {ActivatedRoute} from '@angular/router'; import {Observable, Subscription, of} from 'rxjs'; @@ -12,6 +19,7 @@ import {TaskPlannerComponent} from './task-planner/task-planner.component'; selector: 'f-project-plan', templateUrl: 'project-plan.component.html', styleUrls: ['project-plan.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProjectPlanComponent implements OnInit, OnDestroy { diff --git a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts index 0a6cf37de1..7af70513b0 100644 --- a/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts +++ b/src/app/projects/states/plan/task-planner/task-planner-prerequisites-modal/task-planner-prerequisites-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Input, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA} from '@angular/material/dialog'; import {MatTableDataSource} from '@angular/material/table'; import {Project} from 'src/app/api/models/project'; @@ -15,6 +15,7 @@ export interface TaskPlannerPrerequisitesModalData { selector: 'f-task-planner-prerequisites-modal', templateUrl: './task-planner-prerequisites-modal.component.html', styleUrl: './task-planner-prerequisites-modal.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskPlannerPrerequisitesModalComponent implements OnInit { diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.ts b/src/app/projects/states/plan/task-planner/task-planner.component.ts index fa36cd35c6..fc78bb6dcb 100644 --- a/src/app/projects/states/plan/task-planner/task-planner.component.ts +++ b/src/app/projects/states/plan/task-planner/task-planner.component.ts @@ -11,6 +11,7 @@ import { } from '@worktile/gantt'; import { AfterViewInit, + ChangeDetectionStrategy, Component, ElementRef, Input, @@ -43,6 +44,7 @@ interface TaskGanttItem extends GanttItem { templateUrl: './task-planner.component.html', styleUrl: './task-planner.component.scss', providers: [GanttPrintService], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskPlannerComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts index efc4bd9432..2d2316b633 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts +++ b/src/app/projects/states/portfolio/directives/portfolio-add-extra-files-step/portfolio-add-extra-files-step.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {MatSelectChange} from '@angular/material/select'; import {Project} from 'src/app/api/models/project'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -7,6 +7,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-portfolio-add-extra-files-step', templateUrl: 'portfolio-add-extra-files-step.component.html', styleUrls: ['portfolio-add-extra-files-step.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfolioAddExtraFilesStepComponent implements OnInit { diff --git a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts index 910e02daa8..747a9f5fd4 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts +++ b/src/app/projects/states/portfolio/directives/portfolio-grade-select-step/portfolio-grade-select-step.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Project, Unit} from 'src/app/api/models/doubtfire-model'; import {ProjectService} from 'src/app/api/services/project.service'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -8,6 +8,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; selector: 'f-portfolio-grade-select-step', templateUrl: 'portfolio-grade-select-step.component.html', styleUrls: ['portfolio-grade-select-step.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfolioGradeSelectStepComponent { diff --git a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.ts index 2d162c1f7f..66843a5bae 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.ts +++ b/src/app/projects/states/portfolio/directives/portfolio-learning-summary-report-step/portfolio-learning-summary-report-step.component.ts @@ -1,4 +1,4 @@ -import {Component, Injector, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Injector, Input} from '@angular/core'; import {Project} from 'src/app/api/models/project'; import {Unit} from 'src/app/api/models/unit'; import {GradeService} from 'src/app/common/services/grade.service'; @@ -7,6 +7,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; selector: 'f-portfolio-learning-summary-report-step', templateUrl: 'portfolio-learning-summary-report-step.component.html', styleUrls: ['portfolio-learning-summary-report-step.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfolioLearningSummaryReportStepComponent { diff --git a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.ts b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.ts index 1bd988ead0..3be9d74844 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.ts +++ b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-included-tasks/portfolio-included-tasks.component.ts @@ -1,4 +1,12 @@ -import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + OnDestroy, + OnInit, + Output, +} from '@angular/core'; import {Subscription, interval} from 'rxjs'; import {Project} from 'src/app/api/models/project'; import {Task} from 'src/app/api/models/task'; @@ -8,6 +16,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-portfolio-included-tasks', templateUrl: 'portfolio-included-tasks.component.html', styleUrls: ['portfolio-included-tasks.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfolioIncludedTasksComponent implements OnInit, OnDestroy { diff --git a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.component.ts index 3af5d2a896..865e9449c0 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.component.ts +++ b/src/app/projects/states/portfolio/directives/portfolio-review-step/portfolio-review-step.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {Project} from 'src/app/api/models/project'; import {Task} from 'src/app/api/models/task'; import {Unit} from 'src/app/api/models/unit'; @@ -13,6 +13,7 @@ import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; selector: 'f-portfolio-review-step', templateUrl: 'portfolio-review-step.component.html', styleUrls: ['portfolio-review-step.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfolioReviewStepComponent implements OnInit { diff --git a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.ts b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.ts index c20eb3f23b..e2c9bda66c 100644 --- a/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.ts +++ b/src/app/projects/states/portfolio/directives/portfolio-welcome-step/portfolio-welcome-step.component.ts @@ -1,10 +1,11 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; @Component({ selector: 'f-portfolio-welcome-step', templateUrl: 'portfolio-welcome-step.component.html', styleUrls: ['portfolio-welcome-step.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfolioWelcomeStepComponent implements OnInit { diff --git a/src/app/projects/states/portfolio/portfolio-state.component.ts b/src/app/projects/states/portfolio/portfolio-state.component.ts index fc270d92d0..e96f5d2eec 100644 --- a/src/app/projects/states/portfolio/portfolio-state.component.ts +++ b/src/app/projects/states/portfolio/portfolio-state.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {Observable, Subscription, of} from 'rxjs'; import {Project} from 'src/app/api/models/project'; @@ -14,6 +14,7 @@ interface PortfolioStepTab { selector: 'f-portfolio-state', templateUrl: './portfolio-state.component.html', styleUrls: ['./portfolio-state.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfolioStateComponent implements OnInit, OnDestroy { diff --git a/src/app/projects/states/project-root-state.component.ts b/src/app/projects/states/project-root-state.component.ts index bfdaee850c..355f9f641f 100644 --- a/src/app/projects/states/project-root-state.component.ts +++ b/src/app/projects/states/project-root-state.component.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {Observable, of} from 'rxjs'; import {Project} from 'src/app/api/models/doubtfire-model'; @@ -8,6 +8,7 @@ import {Project} from 'src/app/api/models/doubtfire-model'; selector: 'f-project-root-state', templateUrl: './project-root-state.component.html', styleUrl: './project-root-state.component.css', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProjectRootStateComponent { diff --git a/src/app/projects/states/staff-notes/staff-notes.component.ts b/src/app/projects/states/staff-notes/staff-notes.component.ts index 1d943bcb56..6ca071e75e 100644 --- a/src/app/projects/states/staff-notes/staff-notes.component.ts +++ b/src/app/projects/states/staff-notes/staff-notes.component.ts @@ -1,4 +1,11 @@ -import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + Input, + OnInit, + ViewChild, +} from '@angular/core'; import {Project, UserService} from 'src/app/api/models/doubtfire-model'; import {StaffNote} from 'src/app/api/models/staff-note'; import {StaffNoteService} from 'src/app/api/services/staff-note.service'; @@ -9,6 +16,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-staff-notes', templateUrl: './staff-notes.component.html', styleUrl: './staff-notes.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class StaffNotesComponent implements OnInit { diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html index d41f5095af..02fe4fac65 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html @@ -36,7 +36,10 @@ [disabled]="selectedTaskDefinition" [(ngModel)]="selectedTaskDefinition" > - @for (td of unit?.taskDefinitionCache.values | async; track td) { + @for ( + td of $safeNavigationMigration(unit?.taskDefinitionCache.values) | async; + track td + ) { {{ td.abbreviation }} - {{ td.name }} }
      @@ -67,7 +70,7 @@ }
      - Target Grade: {{ getTargetTradeString(project?.targetGrade) }} + Target Grade: {{ getTargetTradeString($safeNavigationMigration(project?.targetGrade)) }}
      } @else { @@ -110,7 +113,12 @@ similarities: task.similaritiesDetected, }" > - + +

      {{ task.definition.name }}

      @@ -225,7 +233,7 @@

      {{ task.definition.name }}

      diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts index bc6819ee40..56384bd286 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.ts @@ -2,6 +2,7 @@ import {Html5QrcodeScanner, Html5QrcodeScannerState} from 'html5-qrcode'; import {DOCUMENT} from '@angular/common'; import { AfterViewInit, + ChangeDetectionStrategy, Component, Inject, Input, @@ -43,6 +44,7 @@ enum TutorDiscussionTabView { templateUrl: './tutor-discussion.component.html', styleUrl: './tutor-discussion.component.scss', encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TutorDiscussionComponent implements AfterViewInit, OnDestroy { diff --git a/src/app/projects/states/tutor-notes/tutor-notes.component.ts b/src/app/projects/states/tutor-notes/tutor-notes.component.ts index 81f3b0da7c..e595818ab0 100644 --- a/src/app/projects/states/tutor-notes/tutor-notes.component.ts +++ b/src/app/projects/states/tutor-notes/tutor-notes.component.ts @@ -1,4 +1,11 @@ -import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + Input, + OnInit, + ViewChild, +} from '@angular/core'; import {Task, UnitRole, UserService} from 'src/app/api/models/doubtfire-model'; import {TutorNote} from 'src/app/api/models/tutor-note'; import {TutorNoteService} from 'src/app/api/services/tutor-note.service'; @@ -9,6 +16,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-tutor-notes', templateUrl: './tutor-notes.component.html', styleUrl: './tutor-notes.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TutorNotesComponent implements OnInit { diff --git a/src/app/projects/states/tutorials/tutorials.component.ts b/src/app/projects/states/tutorials/tutorials.component.ts index 47963b0d05..07f4879f06 100644 --- a/src/app/projects/states/tutorials/tutorials.component.ts +++ b/src/app/projects/states/tutorials/tutorials.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {Sort} from '@angular/material/sort'; import {MatTableDataSource} from '@angular/material/table'; import {ActivatedRoute} from '@angular/router'; @@ -9,6 +9,7 @@ import {Project, Tutorial, Unit} from 'src/app/api/models/doubtfire-model'; selector: 'f-tutorials', templateUrl: './tutorials.component.html', styleUrls: ['./tutorials.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TutorialsComponent implements OnInit, OnDestroy { diff --git a/src/app/sessions/states/sign-in/sign-in.component.ts b/src/app/sessions/states/sign-in/sign-in.component.ts index 59fab3a6cd..02cd5a197f 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.ts +++ b/src/app/sessions/states/sign-in/sign-in.component.ts @@ -1,5 +1,5 @@ import {HttpClient} from '@angular/common/http'; -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {BehaviorSubject} from 'rxjs'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; @@ -39,6 +39,7 @@ type signInData = selector: 'f-sign-in', templateUrl: './sign-in.component.html', styleUrls: ['./sign-in.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class SignInComponent implements OnInit { diff --git a/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.ts b/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.ts index feffeefeb8..271630413a 100644 --- a/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.ts +++ b/src/app/tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {Task} from 'src/app/api/models/task'; import {TaskService} from 'src/app/api/services/task.service'; @@ -9,6 +9,7 @@ import {FeedbackAppealModalData} from './feedback-appeal-modal.service'; selector: 'f-feedback-appeal-modal', templateUrl: './feedback-appeal-modal.component.html', styleUrl: './feedback-appeal-modal.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FeedbackAppealModalComponent implements OnInit { diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.ts b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.ts index 10a77aea68..5a21b0c6e3 100644 --- a/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.ts +++ b/src/app/tasks/modals/grade-task-modal/grade-task-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {GradeService, Task} from 'src/app/api/models/doubtfire-model'; @@ -6,6 +6,7 @@ import {GradeService, Task} from 'src/app/api/models/doubtfire-model'; selector: 'grade-task-modal', templateUrl: './grade-task-modal.component.html', styleUrls: ['./grade-task-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class GradeTaskModalComponent implements OnInit { diff --git a/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.ts b/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.ts index 93ac4ca259..ef90da6a05 100644 --- a/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.ts +++ b/src/app/tasks/modals/submission-type-modal/submission-type-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {Task} from 'src/app/api/models/task'; import {TaskStatusEnum} from 'src/app/api/models/task-status'; @@ -11,6 +11,7 @@ export interface SubmissionTypeModalData { selector: 'f-submission-type-modal', templateUrl: './submission-type-modal.component.html', styleUrls: ['./submission-type-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class SubmissionTypeModalComponent { diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.component.ts b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.component.ts index d9709369de..5107f3f584 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.component.ts +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnInit, ViewChild} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit, ViewChild} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {MemberContribution} from 'src/app/api/models/groups/group'; import {Task} from 'src/app/api/models/task'; @@ -57,6 +57,7 @@ export type UploadSubmissionModalResult = @Component({ selector: 'f-upload-submission-modal', templateUrl: './upload-submission-modal.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UploadSubmissionModalComponent implements OnInit { diff --git a/src/app/tasks/project-tasks-list/project-tasks-list.component.ts b/src/app/tasks/project-tasks-list/project-tasks-list.component.ts index a5fa15a6a5..b1ea1f3f72 100644 --- a/src/app/tasks/project-tasks-list/project-tasks-list.component.ts +++ b/src/app/tasks/project-tasks-list/project-tasks-list.component.ts @@ -1,4 +1,11 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + OnInit, + Output, +} from '@angular/core'; import { GradeService, Project, @@ -12,6 +19,7 @@ import { selector: 'f-project-tasks-list', templateUrl: './project-tasks-list.component.html', styleUrls: ['./project-tasks-list.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProjectTasksListComponent implements OnInit { diff --git a/src/app/tasks/task-comment-composer/attachment-confirmation-dialog/attachment-confirmation-dialog.component.ts b/src/app/tasks/task-comment-composer/attachment-confirmation-dialog/attachment-confirmation-dialog.component.ts index 60d4644fed..644281e04e 100644 --- a/src/app/tasks/task-comment-composer/attachment-confirmation-dialog/attachment-confirmation-dialog.component.ts +++ b/src/app/tasks/task-comment-composer/attachment-confirmation-dialog/attachment-confirmation-dialog.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; export interface AttachmentConfirmationDialogData { @@ -8,6 +8,7 @@ export interface AttachmentConfirmationDialogData { @Component({ selector: 'f-attachment-confirmation-dialog', templateUrl: './attachment-confirmation-dialog.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class AttachmentConfirmationDialogComponent implements OnInit, OnDestroy { diff --git a/src/app/tasks/task-comment-composer/discussion-prompt-composer/discussion-prompt-composer.component.ts b/src/app/tasks/task-comment-composer/discussion-prompt-composer/discussion-prompt-composer.component.ts index df50dd71d5..8beb8baaa8 100644 --- a/src/app/tasks/task-comment-composer/discussion-prompt-composer/discussion-prompt-composer.component.ts +++ b/src/app/tasks/task-comment-composer/discussion-prompt-composer/discussion-prompt-composer.component.ts @@ -1,4 +1,12 @@ -import {AfterViewInit, Component, ElementRef, Inject, Input, ViewChild} from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + ElementRef, + Inject, + Input, + ViewChild, +} from '@angular/core'; import {Task, TaskComment, TaskCommentService} from 'src/app/api/models/doubtfire-model'; import {BaseAudioRecorderComponent} from 'src/app/common/audio-recorder/audio/base-audio-recorder'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -9,6 +17,7 @@ import {MediaRecorderService} from 'src/app/common/services/recorder-service'; templateUrl: './discussion-prompt-composer.component.html', styleUrls: ['./discussion-prompt-composer.component.scss'], providers: [MediaRecorderService], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class DiscussionPromptComposerComponent diff --git a/src/app/tasks/task-comment-composer/task-comment-composer.component.ts b/src/app/tasks/task-comment-composer/task-comment-composer.component.ts index 2c1850cbbf..ab994a0d57 100644 --- a/src/app/tasks/task-comment-composer/task-comment-composer.component.ts +++ b/src/app/tasks/task-comment-composer/task-comment-composer.component.ts @@ -3,6 +3,7 @@ import {EmojiData} from '@ctrl/ngx-emoji-mart/ngx-emoji'; import {animate, style, transition, trigger} from '@angular/animations'; import { AfterViewInit, + ChangeDetectionStrategy, ChangeDetectorRef, Component, DoCheck, @@ -76,6 +77,7 @@ const ACCEPTED_FILE_TYPES = [ transition('false => true', [style({width: 80}), animate('150ms 0ms ease-in-out')]), ]), ], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskCommentComposerComponent implements AfterViewInit, DoCheck, OnChanges { @@ -791,6 +793,7 @@ export class TaskCommentComposerComponent implements AfterViewInit, DoCheck, OnC selector: 'discussion-prompt-composer-dialog.html', templateUrl: 'discussion-prompt-composer-dialog.html', styleUrls: ['./discussion-prompt-composer/discussion-prompt-composer.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class DiscussionComposerDialog { diff --git a/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts b/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts index 6f6b2bf886..c873efd7a1 100644 --- a/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts +++ b/src/app/tasks/task-comment-composer/task-feedback-templates/task-feedback-templates.component.ts @@ -1,4 +1,5 @@ import { + ChangeDetectionStrategy, Component, ElementRef, EventEmitter, @@ -26,6 +27,7 @@ import { styleUrl: './task-feedback-templates.component.scss', templateUrl: './task-feedback-templates.component.html', encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskFeedbackTemplatesComponent implements OnInit, OnChanges { diff --git a/src/app/tasks/task-comments-viewer/comment-bubble-action/comment-bubble-action.component.ts b/src/app/tasks/task-comments-viewer/comment-bubble-action/comment-bubble-action.component.ts index 9177e395e2..dc68053e56 100644 --- a/src/app/tasks/task-comments-viewer/comment-bubble-action/comment-bubble-action.component.ts +++ b/src/app/tasks/task-comments-viewer/comment-bubble-action/comment-bubble-action.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {TaskComment} from 'src/app/api/models/doubtfire-model'; import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; import {TaskCommentComposerData} from '../../task-comment-composer/task-comment-composer.component'; @@ -7,6 +7,7 @@ import {TaskCommentComposerData} from '../../task-comment-composer/task-comment- selector: 'comment-bubble-action', templateUrl: './comment-bubble-action.component.html', styleUrls: ['./comment-bubble-action.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class CommentBubbleActionComponent { diff --git a/src/app/tasks/task-comments-viewer/extension-comment/extension-comment.component.ts b/src/app/tasks/task-comments-viewer/extension-comment/extension-comment.component.ts index b3784c20f3..4db00f9864 100644 --- a/src/app/tasks/task-comments-viewer/extension-comment/extension-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/extension-comment/extension-comment.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Task, TaskComment} from 'src/app/api/models/doubtfire-model'; import {ExtensionComment} from 'src/app/api/models/task-comment/extension-comment'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -7,6 +7,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'extension-comment', templateUrl: './extension-comment.component.html', styleUrls: ['./extension-comment.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ExtensionCommentComponent { diff --git a/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-player.component.ts b/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-player.component.ts index ec03752589..5947922893 100644 --- a/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-player.component.ts +++ b/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-player.component.ts @@ -1,5 +1,12 @@ import moment from 'moment'; -import {AfterViewInit, Component, Inject, Input, ViewChild} from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + Inject, + Input, + ViewChild, +} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog'; import {Subscription, timer} from 'rxjs'; import {DiscussionComment, Task} from 'src/app/api/models/doubtfire-model'; @@ -13,6 +20,7 @@ import {IntelligentDiscussionRecorderComponent} from './intelligent-discussion-r templateUrl: './intelligent-discussion-player.component.html', styleUrls: ['./intelligent-discussion-player.component.scss'], providers: [IntelligentDiscussionPlayerService], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class IntelligentDiscussionPlayerComponent implements AfterViewInit { @@ -77,6 +85,7 @@ export class IntelligentDiscussionPlayerComponent implements AfterViewInit { templateUrl: 'intelligent-discussion-dialog.html', styleUrls: ['./intelligent-discussion-player.component.scss'], providers: [IntelligentDiscussionPlayerService], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class IntelligentDiscussionDialog { diff --git a/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-recorder/intelligent-discussion-recorder.component.ts b/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-recorder/intelligent-discussion-recorder.component.ts index a87039ef51..bc988c98a5 100644 --- a/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-recorder/intelligent-discussion-recorder.component.ts +++ b/src/app/tasks/task-comments-viewer/intelligent-discussion-player/intelligent-discussion-recorder/intelligent-discussion-recorder.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, Inject, Input} from '@angular/core'; +import {AfterViewInit, ChangeDetectionStrategy, Component, Inject, Input} from '@angular/core'; import {DiscussionComment, Task} from 'src/app/api/models/doubtfire-model'; import { BaseAudioRecorderComponent, @@ -22,6 +22,7 @@ interface DiscussionReplyService { templateUrl: './intelligent-discussion-recorder.component.html', styleUrls: ['./intelligent-discussion-recorder.component.css'], providers: [MediaRecorderService], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class IntelligentDiscussionRecorderComponent diff --git a/src/app/tasks/task-comments-viewer/pdf-image-comment/pdf-image-comment.component.ts b/src/app/tasks/task-comments-viewer/pdf-image-comment/pdf-image-comment.component.ts index 7bc04435e1..32fee56dff 100644 --- a/src/app/tasks/task-comments-viewer/pdf-image-comment/pdf-image-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/pdf-image-comment/pdf-image-comment.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {Project, Task, TaskComment} from 'src/app/api/models/doubtfire-model'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; import {CommentsModalService} from 'src/app/common/modals/comments-modal/comments-modal.service'; @@ -8,6 +8,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'pdf-image-comment', templateUrl: './pdf-image-comment.component.html', styleUrls: [], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PdfImageCommentComponent implements OnInit, OnDestroy { diff --git a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts index 485c951a51..5cf6e6845c 100644 --- a/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/scorm-comment/scorm-comment.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import { ScormComment, Task, @@ -12,6 +12,7 @@ import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal selector: 'f-scorm-comment', templateUrl: './scorm-comment.component.html', styleUrls: ['./scorm-comment.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ScormCommentComponent { diff --git a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts index b1f93de747..ea963d9b00 100644 --- a/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/scorm-extension-comment/scorm-extension-comment.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {ScormExtensionComment, Task, TaskComment} from 'src/app/api/models/doubtfire-model'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -6,6 +6,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-scorm-extension-comment', templateUrl: './scorm-extension-comment.component.html', styleUrls: ['./scorm-extension-comment.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ScormExtensionCommentComponent { diff --git a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts index 39eac04240..2c4e842f98 100644 --- a/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts +++ b/src/app/tasks/task-comments-viewer/task-assessment-comment/task-assessment-comment.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Input} from '@angular/core'; import {Task} from 'src/app/api/models/doubtfire-model'; import {TaskAssessmentModalService} from 'src/app/common/modals/task-assessment-modal/task-assessment-modal.service'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -37,6 +37,7 @@ export interface TaskAssessmentComment { selector: 'app-task-assessment-comment', templateUrl: './task-assessment-comment.component.html', styleUrls: ['./task-assessment-comment.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskAssessmentCommentComponent { diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts index 7f5e1d4af4..3233a9850b 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.ts @@ -1,4 +1,5 @@ import { + ChangeDetectionStrategy, Component, ElementRef, Input, @@ -26,6 +27,7 @@ import {TaskCommentComposerData} from '../task-comment-composer/task-comment-com selector: 'task-comments-viewer', templateUrl: './task-comments-viewer.component.html', styleUrls: ['./task-comments-viewer.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskCommentsViewerComponent implements OnChanges, OnDestroy { diff --git a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts index 4772d837fd..21460b7484 100644 --- a/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts +++ b/src/app/units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {Campus, Project, Unit} from 'src/app/api/models/doubtfire-model'; import {CampusService} from 'src/app/api/services/campus.service'; @@ -8,6 +8,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-unit-student-enrolment-modal', templateUrl: 'unit-student-enrolment-modal.component.html', styleUrls: ['unit-student-enrolment-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitStudentEnrolmentModalComponent implements OnInit { diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts index e8e655690d..99712feab4 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit, ViewEncapsulation} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation} from '@angular/core'; import {MatDatepickerInputEvent} from '@angular/material/datepicker'; import {Observable} from 'rxjs'; import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; @@ -32,6 +32,7 @@ interface SessionEvent { templateUrl: 'analytics-tutor-times.component.html', styleUrls: ['analytics-tutor-times.component.scss'], encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class AnalyticsTutorTimesComponent implements OnInit { diff --git a/src/app/units/states/analytics/unit-analytics-route.component.ts b/src/app/units/states/analytics/unit-analytics-route.component.ts index f7a63585d9..b05fa7187b 100644 --- a/src/app/units/states/analytics/unit-analytics-route.component.ts +++ b/src/app/units/states/analytics/unit-analytics-route.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {Observable, first, of} from 'rxjs'; import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; @@ -12,6 +12,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-unit-analytics', templateUrl: 'unit-analytics-route.component.html', styleUrls: ['unit-analytics-route.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitAnalyticsComponent implements OnInit { diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.ts index fd47ca76af..5be3b69259 100644 --- a/src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.ts +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/change-target-grade-action/change-target-grade-action.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; import type {UnitCommunicationsEditorComponent} from '../../unit-communications-editor.component'; @@ -6,6 +6,7 @@ import type {UnitCommunicationsEditorComponent} from '../../unit-communications- selector: 'f-change-target-grade-action', standalone: false, templateUrl: './change-target-grade-action.component.html', + changeDetection: ChangeDetectionStrategy.Eager, host: {class: 'flex w-full flex-col items-center'}, }) export class ChangeTargetGradeActionComponent { diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.ts index 5a3b083c9d..254e5ccf50 100644 --- a/src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.ts +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/communication-actions.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; import type {UnitCommunicationsEditorComponent} from '../unit-communications-editor.component'; @Component({ selector: 'f-communication-actions', standalone: false, + changeDetection: ChangeDetectionStrategy.Eager, templateUrl: './communication-actions.component.html', }) export class CommunicationActionsComponent { diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.ts index f795a326a1..91f2a22c79 100644 --- a/src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.ts +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-staff-action/email-staff-action.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; import type {UnitCommunicationsEditorComponent} from '../../unit-communications-editor.component'; @@ -6,6 +6,7 @@ import type {UnitCommunicationsEditorComponent} from '../../unit-communications- selector: 'f-email-staff-action', standalone: false, templateUrl: './email-staff-action.component.html', + changeDetection: ChangeDetectionStrategy.Eager, host: {class: 'block w-full'}, }) export class EmailStaffActionComponent { diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.ts index 09cd6fc64a..100e890c66 100644 --- a/src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.ts +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/email-student-action/email-student-action.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; import type {UnitCommunicationsEditorComponent} from '../../unit-communications-editor.component'; @@ -6,6 +6,7 @@ import type {UnitCommunicationsEditorComponent} from '../../unit-communications- selector: 'f-email-student-action', standalone: false, templateUrl: './email-student-action.component.html', + changeDetection: ChangeDetectionStrategy.Eager, host: {class: 'block w-full'}, }) export class EmailStudentActionComponent { diff --git a/src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.ts index f7f2fb5b4b..6c459e3d26 100644 --- a/src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.ts +++ b/src/app/units/states/edit/directives/unit-communications-editor/actions/task-comment-action/task-comment-action.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; import type {UnitCommunicationsEditorComponent} from '../../unit-communications-editor.component'; @@ -6,6 +6,7 @@ import type {UnitCommunicationsEditorComponent} from '../../unit-communications- selector: 'f-task-comment-action', standalone: false, templateUrl: './task-comment-action.component.html', + changeDetection: ChangeDetectionStrategy.Eager, host: {class: 'block w-full'}, }) export class TaskCommentActionComponent { diff --git a/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.ts index eb241004d0..674e156d72 100644 --- a/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.ts +++ b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedule-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import { Campus, @@ -25,6 +25,7 @@ export const SCHEDULE_WEEKDAYS = [ @Component({ selector: 'f-communication-schedule-modal', standalone: false, + changeDetection: ChangeDetectionStrategy.Eager, templateUrl: './communication-schedule-modal.component.html', }) export class CommunicationScheduleModalComponent implements OnInit { diff --git a/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.ts index e902eca099..aa1156619e 100644 --- a/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.ts +++ b/src/app/units/states/edit/directives/unit-communications-editor/communication-schedule-modal/communication-schedules.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {CommunicationSet} from 'src/app/api/models/doubtfire-model'; import type {UnitCommunicationsEditorComponent} from '../unit-communications-editor.component'; @Component({ selector: 'f-communication-schedules', standalone: false, + changeDetection: ChangeDetectionStrategy.Eager, templateUrl: './communication-schedules.component.html', }) export class CommunicationSchedulesComponent { diff --git a/src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.ts index abab204e98..a4167c217a 100644 --- a/src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.ts +++ b/src/app/units/states/edit/directives/unit-communications-editor/conditions/communication-conditions.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {CommunicationRule} from 'src/app/api/models/doubtfire-model'; import type {UnitCommunicationsEditorComponent} from '../unit-communications-editor.component'; @Component({ selector: 'f-communication-conditions', standalone: false, + changeDetection: ChangeDetectionStrategy.Eager, templateUrl: './communication-conditions.component.html', }) export class CommunicationConditionsComponent { diff --git a/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.ts b/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.ts index 5b83236047..cfe6bf4191 100644 --- a/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-communications-editor/unit-communications-editor.component.ts @@ -1,5 +1,13 @@ import {NestedTreeControl} from '@angular/cdk/tree'; -import {Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnDestroy, + OnInit, + SimpleChanges, +} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {MatTreeNestedDataSource} from '@angular/material/tree'; import {Subscription} from 'rxjs'; @@ -47,6 +55,7 @@ interface CommunicationTreeNode { selector: 'f-unit-communications-editor', standalone: false, templateUrl: './unit-communications-editor.component.html', + changeDetection: ChangeDetectionStrategy.Eager, styleUrl: './unit-communications-editor.component.scss', }) export class UnitCommunicationsEditorComponent implements OnInit, OnChanges, OnDestroy { diff --git a/src/app/units/states/edit/directives/unit-details-editor/d2l-details-form/d2l-unit-details-form.component.ts b/src/app/units/states/edit/directives/unit-details-editor/d2l-details-form/d2l-unit-details-form.component.ts index 4b66e6c644..cd19b0b701 100644 --- a/src/app/units/states/edit/directives/unit-details-editor/d2l-details-form/d2l-unit-details-form.component.ts +++ b/src/app/units/states/edit/directives/unit-details-editor/d2l-details-form/d2l-unit-details-form.component.ts @@ -1,7 +1,7 @@ // // Modal to show Doubtfire version info // -import {Component, Inject, Injectable, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Injectable, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog'; import {Observable} from 'rxjs'; import {D2lAssessmentMapping} from 'src/app/api/models/d2l/d2l_assessment_mapping'; @@ -13,6 +13,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-d2l-unit-details-form', templateUrl: 'd2l-unit-details-form.component.html', styleUrl: 'd2l-unit-details-form.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class D2lUnitDetailsFormComponent implements OnInit { diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html index 93e858b13f..ce5030841c 100644 --- a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html +++ b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.html @@ -48,11 +48,21 @@

      Unit Details

      } @else { {{ unit.teachingPeriod.name }} Start Date - + {{ unit.teachingPeriod.name }} End Date - + }
      diff --git a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts index 8b6448915b..961ea8def8 100644 --- a/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-details-editor/unit-details-editor.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {MatSlideToggleChange} from '@angular/material/slide-toggle'; import {OverseerImage, UnitService} from 'src/app/api/models/doubtfire-model'; import {TaskDefinition} from 'src/app/api/models/task-definition'; @@ -16,6 +16,7 @@ import {D2lUnitDetailsModal} from './d2l-details-form/d2l-unit-details-form.comp selector: 'f-unit-details-editor', templateUrl: 'unit-details-editor.component.html', styleUrls: ['unit-details-editor.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitDetailsEditorComponent implements OnInit { diff --git a/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.component.ts b/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.component.ts index dc95919d08..f35f861698 100644 --- a/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-group-set-editor/unit-group-set-editor.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {GroupSet, Unit, UnitRole} from 'src/app/api/models/doubtfire-model'; import {GroupSetService} from 'src/app/api/services/group-set.service'; import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service'; @@ -20,6 +20,7 @@ interface GroupSetEditModel { selector: 'f-unit-group-set-editor', templateUrl: './unit-group-set-editor.component.html', styleUrls: ['./unit-group-set-editor.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitGroupSetEditorComponent implements OnInit { diff --git a/src/app/units/states/edit/directives/unit-staff-editor/bulk-import-staff-modal/bulk-import-staff-modal.component.ts b/src/app/units/states/edit/directives/unit-staff-editor/bulk-import-staff-modal/bulk-import-staff-modal.component.ts index e3d7a8a295..0456d484ed 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/bulk-import-staff-modal/bulk-import-staff-modal.component.ts +++ b/src/app/units/states/edit/directives/unit-staff-editor/bulk-import-staff-modal/bulk-import-staff-modal.component.ts @@ -1,9 +1,10 @@ -import {Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component} from '@angular/core'; import {MatDialogRef} from '@angular/material/dialog'; @Component({ selector: 'bulk-import-staff-modal', templateUrl: './bulk-import-staff-modal.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class BulkImportStaffModalComponent { diff --git a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts index f549cd09b8..af051c8f14 100644 --- a/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-staff-editor/unit-staff-editor.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {MatButtonToggleChange} from '@angular/material/button-toggle'; import {MatSelectChange} from '@angular/material/select'; import {MatTableDataSource} from '@angular/material/table'; @@ -20,6 +20,7 @@ import {BulkImportStaffModalService} from './bulk-import-staff-modal/bulk-import @Component({ selector: 'unit-staff-editor', templateUrl: 'unit-staff-editor.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitStaffEditorComponent implements OnInit { diff --git a/src/app/units/states/edit/directives/unit-students-editor/student-campus-select/student-campus-select.component.ts b/src/app/units/states/edit/directives/unit-students-editor/student-campus-select/student-campus-select.component.ts index 001758c768..bb80001e70 100644 --- a/src/app/units/states/edit/directives/unit-students-editor/student-campus-select/student-campus-select.component.ts +++ b/src/app/units/states/edit/directives/unit-students-editor/student-campus-select/student-campus-select.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnChanges, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnChanges, OnInit} from '@angular/core'; import {MatSelectChange} from '@angular/material/select'; import {Campus, CampusService, Project, Unit} from 'src/app/api/models/doubtfire-model'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -7,6 +7,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'student-campus-select', templateUrl: 'student-campus-select.component.html', styleUrls: ['student-campus-select.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class StudentCampusSelectComponent implements OnChanges, OnInit { diff --git a/src/app/units/states/edit/directives/unit-students-editor/student-tutorial-select/student-tutorial-select.component.ts b/src/app/units/states/edit/directives/unit-students-editor/student-tutorial-select/student-tutorial-select.component.ts index 1ca41cdb12..ce5b9b1e58 100644 --- a/src/app/units/states/edit/directives/unit-students-editor/student-tutorial-select/student-tutorial-select.component.ts +++ b/src/app/units/states/edit/directives/unit-students-editor/student-tutorial-select/student-tutorial-select.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Project, Tutorial, TutorialStream, Unit} from 'src/app/api/models/doubtfire-model'; @Component({ selector: 'student-tutorial-select', templateUrl: 'student-tutorial-select.component.html', styleUrls: ['student-tutorial-select.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class StudentTutorialSelectComponent { diff --git a/src/app/units/states/edit/directives/unit-students-editor/unit-students-editor.component.ts b/src/app/units/states/edit/directives/unit-students-editor/unit-students-editor.component.ts index 9033952a22..fd20d9cdf8 100644 --- a/src/app/units/states/edit/directives/unit-students-editor/unit-students-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-students-editor/unit-students-editor.component.ts @@ -1,5 +1,13 @@ import {HttpClient} from '@angular/common/http'; -import {AfterViewInit, Component, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + Input, + OnDestroy, + OnInit, + ViewChild, +} from '@angular/core'; import {MatPaginator} from '@angular/material/paginator'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTable, MatTableDataSource} from '@angular/material/table'; @@ -22,6 +30,7 @@ import {UnitStudentEnrolmentModalService} from 'src/app/units/modals/unit-studen selector: 'unit-students-editor', templateUrl: 'unit-students-editor.component.html', styleUrls: ['unit-students-editor.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitStudentsEditorComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.ts index 2846c38f2c..40d0f325c5 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-dates/task-definition-dates.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; @@ -6,6 +6,7 @@ import {Unit} from 'src/app/api/models/unit'; selector: 'f-task-definition-dates', templateUrl: 'task-definition-dates.component.html', styleUrls: ['task-definition-dates.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionDatesComponent { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts index 1de5e5f142..7f9de46ef7 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-discussion-prompts/task-definition-discussion-prompts.component.ts @@ -1,4 +1,11 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import {UntypedFormControl, Validators} from '@angular/forms'; import {MatTableDataSource} from '@angular/material/table'; import {Observable, Subscription} from 'rxjs'; @@ -17,6 +24,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-task-definition-discussion-prompts', templateUrl: 'task-definition-discussion-prompts.component.html', styleUrls: ['task-definition-discussion-prompts.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionDiscussionPromptsComponent diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.ts index 1e24f9cc96..6c48f141f8 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-editor.component.ts @@ -1,5 +1,6 @@ import { AfterViewInit, + ChangeDetectionStrategy, Component, ElementRef, HostListener, @@ -41,6 +42,7 @@ interface TaskDefinitionSection { selector: 'f-task-definition-editor', templateUrl: 'task-definition-editor.component.html', styleUrls: ['task-definition-editor.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionEditorComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.ts index 5683af008a..3203ea0eaa 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-general/task-definition-general.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; import {GradeService} from 'src/app/common/services/grade.service'; @@ -7,6 +7,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; selector: 'f-task-definition-general', templateUrl: 'task-definition-general.component.html', styleUrls: ['task-definition-general.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionGeneralComponent { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts index f41aac39bb..29037633b7 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-options/task-definition-options.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; @@ -7,6 +7,7 @@ import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal selector: 'f-task-definition-options', templateUrl: 'task-definition-options.component.html', styleUrls: ['task-definition-options.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionOptionsComponent { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts index ab124ad2da..c2bc724c2e 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/overseer-script-editor-modal/overseer-script-editor-modal.component.ts @@ -1,6 +1,6 @@ import {CodeModel} from '@ngstack/code-editor'; import {HttpClient} from '@angular/common/http'; -import {Component, Inject, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {AlertService} from 'src/app/common/services/alert.service'; import {OverseerScriptEditorModalData} from './overseer-script-editor-modal.service'; @@ -9,6 +9,7 @@ import {OverseerScriptEditorModalData} from './overseer-script-editor-modal.serv selector: 'f-overseer-script-editor-modal', templateUrl: './overseer-script-editor-modal.component.html', styleUrls: ['./overseer-script-editor-modal.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class OverseerScriptEditorModalComponent implements OnInit { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts index feb75b8fbc..17df2de59c 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-overseer/task-definition-overseer.component.ts @@ -1,7 +1,15 @@ import * as monaco from 'monaco-editor'; import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop'; import {HttpClient, HttpResponse} from '@angular/common/http'; -import {Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, + ViewChild, +} from '@angular/core'; import {MatSelectChange} from '@angular/material/select'; import {Observable} from 'rxjs'; import { @@ -28,6 +36,7 @@ import {OverseerScriptEditorModalService} from './overseer-script-editor-modal/o selector: 'f-task-definition-overseer', templateUrl: 'task-definition-overseer.component.html', styleUrls: ['task-definition-overseer.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionOverseerComponent implements OnChanges, OnInit { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html index 530d31da43..5f9bb9acd6 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.html @@ -6,7 +6,7 @@
      @@ -23,12 +23,15 @@
      + Username + Username {{ project.student.username || 'N/A' }} Name + Name {{ project.student.name }} Stats + Stats
      @for (bar of project.taskStats; track bar.key) {
      @if (bar.key === 'not_started') { {{ bar.value }}% @@ -132,15 +132,15 @@

      Students

      -
      Target Grade + Target Grade Portfolio + Portfolio @if (project.hasPortfolio) { menu_book } @@ -148,8 +148,8 @@

      Students

      -
      Similarity + Similarity @if (project.similarityFlag) { visibility } @@ -157,12 +157,12 @@

      Students

      -
      Campus + Campus
      @@ -170,23 +170,23 @@

      Students

      -
      Tutorial + Tutorial
      - +
      No students were found using the filters specified. {{ link.prerequisite?.abbreviation }} {{ link.prerequisite?.name }} @if (!staffView) { } @else { @if (link.taskStatus) { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts index bc19d15057..7870470c2c 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-prerequisites/task-definition-prerequisites.component.ts @@ -1,4 +1,11 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import {FormControl} from '@angular/forms'; import {MatTableDataSource} from '@angular/material/table'; import {Observable, Subscription} from 'rxjs'; @@ -15,6 +22,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-task-definition-prerequisites', templateUrl: 'task-definition-prerequisites.component.html', styleUrls: ['task-definition-prerequisites.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionPrerequisitesComponent implements OnInit, OnChanges { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.ts index 0973e21805..991202f359 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-resources/task-definition-resources.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; @@ -9,6 +9,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-task-definition-resources', templateUrl: 'task-definition-resources.component.html', styleUrls: ['task-definition-resources.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionResourcesComponent { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts index ec01b60b09..93ceb71852 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-scorm/task-definition-scorm.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; @@ -9,6 +9,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-task-definition-scorm', templateUrl: 'task-definition-scorm.component.html', styleUrls: ['task-definition-scorm.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionScormComponent { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts index 3cbb9a03ed..0cb7e0b0d7 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-upload/task-definition-upload.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, ViewChild} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, ViewChild} from '@angular/core'; import {MatTable} from '@angular/material/table'; import {TaskDefinition, UploadRequirement} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; @@ -8,6 +8,7 @@ import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; selector: 'f-task-definition-upload', templateUrl: 'task-definition-upload.component.html', styleUrls: ['task-definition-upload.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionUploadComponent { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html index 65dee44436..e857fed00c 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.html @@ -28,7 +28,7 @@ Related tutorials
        @for ( - tutorial of taskDefinition.tutorialStream?.tutorialsIn(unit) + tutorial of $safeNavigationMigration(taskDefinition.tutorialStream?.tutorialsIn(unit)) | slice: 0 : (showAllTutorials ? undefined : 3); track tutorial ) { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts index 4ca19148ce..7ef4f65c5a 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/task-definition-editor/task-definition-who/task-definition-who.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; @@ -6,6 +6,7 @@ import {Unit} from 'src/app/api/models/unit'; selector: 'f-task-definition-who', templateUrl: 'task-definition-who.component.html', styleUrls: ['task-definition-who.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskDefinitionWhoComponent { diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts index ddb32c6635..f12139cd37 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts @@ -1,5 +1,5 @@ import {addWeeks} from 'date-fns'; -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {MatTableDataSource} from '@angular/material/table'; import {Subscription} from 'rxjs'; import {Grade} from 'src/app/api/models/grade'; @@ -21,6 +21,7 @@ type GradeCol = 'p' | 'c' | 'd' | 'hd'; selector: 'f-unit-task-editor', templateUrl: 'unit-task-editor.component.html', styleUrls: ['unit-task-editor.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitTaskEditorComponent implements OnInit, OnDestroy { diff --git a/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts b/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts index e2a351c8da..4db0b6c297 100644 --- a/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts +++ b/src/app/units/states/edit/directives/unit-tutorials-list/unit-tutorials-list.component.ts @@ -1,6 +1,6 @@ import {RequestOptions} from 'ngx-entity-service'; import {HttpErrorResponse} from '@angular/common/http'; -import {AfterViewInit, Component, Input, ViewChild} from '@angular/core'; +import {AfterViewInit, ChangeDetectionStrategy, Component, Input, ViewChild} from '@angular/core'; import {UntypedFormControl, Validators} from '@angular/forms'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTable, MatTableDataSource} from '@angular/material/table'; @@ -22,6 +22,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'df-unit-tutorials-list', templateUrl: 'unit-tutorials-list.component.html', styleUrls: ['unit-tutorials-list.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitTutorialsListComponent diff --git a/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.ts b/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.ts index cdc7bacc90..2a71c1c6c7 100644 --- a/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.ts +++ b/src/app/units/states/edit/directives/unit-tutorials-manager/unit-tutorials-manager.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import { ActivityType, ActivityTypeService, @@ -11,6 +11,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'unit-tutorials-manager', templateUrl: 'unit-tutorials-manager.component.html', styleUrls: ['unit-tutorials-manager.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitTutorialsManagerComponent implements OnInit { diff --git a/src/app/units/states/edit/unit-admin-state.component.ts b/src/app/units/states/edit/unit-admin-state.component.ts index a9e02c4753..9550f29044 100644 --- a/src/app/units/states/edit/unit-admin-state.component.ts +++ b/src/app/units/states/edit/unit-admin-state.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {MatTabChangeEvent} from '@angular/material/tabs'; import {ActivatedRoute, Router} from '@angular/router'; import {Observable, Subscription, first, of} from 'rxjs'; @@ -23,6 +23,7 @@ interface UnitAdminTab { @Component({ selector: 'f-unit-admin-state', templateUrl: './unit-admin-state.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitAdminStateComponent implements OnInit, OnDestroy { diff --git a/src/app/units/states/groups/unit-groups/unit-groups.component.ts b/src/app/units/states/groups/unit-groups/unit-groups.component.ts index ee40e83f08..16d8612a5c 100644 --- a/src/app/units/states/groups/unit-groups/unit-groups.component.ts +++ b/src/app/units/states/groups/unit-groups/unit-groups.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {Observable, Subscription, of} from 'rxjs'; import {GroupSet, Unit, UnitRole, UserService} from 'src/app/api/models/doubtfire-model'; @@ -10,6 +10,7 @@ import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global selector: 'f-unit-groups', templateUrl: './unit-groups.component.html', styleUrl: './unit-groups.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitGroupsComponent implements OnInit, OnDestroy { diff --git a/src/app/units/states/portfolios/d2l-transfer-modal/d2l-transfer.component.ts b/src/app/units/states/portfolios/d2l-transfer-modal/d2l-transfer.component.ts index d262360101..c965168641 100644 --- a/src/app/units/states/portfolios/d2l-transfer-modal/d2l-transfer.component.ts +++ b/src/app/units/states/portfolios/d2l-transfer-modal/d2l-transfer.component.ts @@ -2,7 +2,7 @@ // Modal to show Doubtfire version info // import {HttpClient} from '@angular/common/http'; -import {Component, Inject, Injectable, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, Injectable, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog'; import {D2lAssessmentMapping} from 'src/app/api/models/d2l/d2l_assessment_mapping'; import {D2lAssessmentMappingService} from 'src/app/api/models/doubtfire-model'; @@ -15,6 +15,7 @@ import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; selector: 'f-d2l-transfer', templateUrl: 'd2l-transfer.component.html', styleUrl: 'd2l-transfer.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class D2lTransferComponent implements OnInit { diff --git a/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.ts b/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.ts index 48a9bed310..54f33d479e 100644 --- a/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-assessment/portfolios-assessment.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Project} from 'src/app/api/models/project'; import {Unit} from 'src/app/api/models/unit'; @@ -6,6 +6,7 @@ import {Unit} from 'src/app/api/models/unit'; selector: 'f-portfolios-assessment', templateUrl: './portfolios-assessment.component.html', styleUrl: './portfolios-assessment.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfoliosAssessmentComponent { diff --git a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts index 36b7a1dc0b..a07840e7ba 100644 --- a/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-list/portfolios-list.component.ts @@ -1,5 +1,6 @@ import { AfterViewInit, + ChangeDetectionStrategy, Component, EventEmitter, Input, @@ -28,6 +29,7 @@ import {D2lTransferModal} from '../../d2l-transfer-modal/d2l-transfer.component' selector: 'f-portfolios-list', templateUrl: './portfolios-list.component.html', styleUrl: './portfolios-list.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfoliosListComponent implements OnChanges, AfterViewInit { diff --git a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts index c7d0f4d066..53efce9faa 100644 --- a/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-portfolio-view/portfolios-portfolio-view.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Project} from 'src/app/api/models/project'; @Component({ selector: 'f-portfolios-portfolio-view', templateUrl: './portfolios-portfolio-view.component.html', styleUrl: './portfolios-portfolio-view.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfoliosPortfolioViewComponent { diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts index 044245349b..b608d8937a 100644 --- a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts @@ -1,4 +1,11 @@ -import {Component, ElementRef, HostListener, Input, OnChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + HostListener, + Input, + OnChanges, +} from '@angular/core'; import {BehaviorSubject} from 'rxjs'; import {Project} from 'src/app/api/models/project'; import {Unit} from 'src/app/api/models/unit'; @@ -11,6 +18,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; selector: 'f-portfolios-project-progress', templateUrl: './portfolios-project-progress.component.html', styleUrl: './portfolios-project-progress.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfoliosProjectProgressComponent implements OnChanges { diff --git a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts index 93b802e44b..6c102ef91c 100644 --- a/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts +++ b/src/app/units/states/portfolios/download-staff-notes/download-staff-notes.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {Unit} from 'src/app/api/models/unit'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -6,6 +6,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-download-staff-notes', templateUrl: 'download-staff-notes.component.html', styleUrl: 'download-staff-notes.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class DownloadStaffNotesComponent implements OnInit { diff --git a/src/app/units/states/portfolios/portfolios.component.ts b/src/app/units/states/portfolios/portfolios.component.ts index 7144b754d5..2f8ad67b63 100644 --- a/src/app/units/states/portfolios/portfolios.component.ts +++ b/src/app/units/states/portfolios/portfolios.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {MatTabChangeEvent} from '@angular/material/tabs'; import {ActivatedRoute, Router} from '@angular/router'; import {BehaviorSubject, Observable, Subscription, first, of} from 'rxjs'; @@ -19,6 +19,7 @@ interface PortfolioTab { selector: 'f-portfolios', templateUrl: './portfolios.component.html', styleUrl: './portfolios.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class PortfoliosComponent implements OnInit, OnDestroy { diff --git a/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts b/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts index d8d246cbb9..fe302d5415 100644 --- a/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts +++ b/src/app/units/states/portfolios/upload-grades/upload-grades.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; import {Unit} from 'src/app/api/models/unit'; import {CsvResultModalService} from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; @@ -10,6 +10,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-upload-grades', templateUrl: 'upload-grades.component.html', styleUrl: 'upload-grades.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UploadGradesComponent implements OnInit { diff --git a/src/app/units/states/rollover/rollover.component.html b/src/app/units/states/rollover/rollover.component.html index a6f4ed56f2..1ad9d9c595 100644 --- a/src/app/units/states/rollover/rollover.component.html +++ b/src/app/units/states/rollover/rollover.component.html @@ -40,11 +40,21 @@ } @else { {{ teachingPeriod.name }} Start Date - + {{ teachingPeriod.name }} End Date - + } diff --git a/src/app/units/states/rollover/rollover.component.ts b/src/app/units/states/rollover/rollover.component.ts index 80d2a6e69e..a9c255c5bd 100644 --- a/src/app/units/states/rollover/rollover.component.ts +++ b/src/app/units/states/rollover/rollover.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {TeachingPeriod} from 'src/app/api/models/teaching-period'; import {Unit} from 'src/app/api/models/unit'; @@ -11,6 +11,7 @@ import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global selector: 'f-rollover', templateUrl: './rollover.component.html', styleUrl: './rollover.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class RolloverComponent implements OnInit { diff --git a/src/app/units/states/students-list/students-list.component.ts b/src/app/units/states/students-list/students-list.component.ts index 21a2345e2c..46b36bcde5 100644 --- a/src/app/units/states/students-list/students-list.component.ts +++ b/src/app/units/states/students-list/students-list.component.ts @@ -1,4 +1,12 @@ -import {AfterViewInit, Component, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + Input, + OnDestroy, + OnInit, + ViewChild, +} from '@angular/core'; import {MatPaginator} from '@angular/material/paginator'; import {MatSort, Sort} from '@angular/material/sort'; import {MatTableDataSource} from '@angular/material/table'; @@ -18,6 +26,7 @@ import {UnitStudentEnrolmentModalService} from '../../modals/unit-student-enrolm @Component({ selector: 'f-students-list', templateUrl: './students-list.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class StudentsListComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html index f7c4f017c9..756361487e 100644 --- a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html +++ b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.html @@ -92,7 +92,9 @@ } @case (InboxDashboardTab.staffNotes) {
        - +
        } @case (InboxDashboardTab.tutorNotes) { diff --git a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts index 6f81bf8311..701396d9f3 100644 --- a/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts +++ b/src/app/units/states/tasks/inbox/directives/inbox-dashboard/inbox-dashboard.component.ts @@ -1,4 +1,12 @@ -import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + OnChanges, + Output, + SimpleChanges, +} from '@angular/core'; import {MatTabChangeEvent} from '@angular/material/tabs'; import {UnitRole} from 'src/app/api/models/doubtfire-model'; import {Task} from 'src/app/api/models/task'; @@ -18,6 +26,7 @@ enum InboxDashboardTab { selector: 'f-inbox-dashboard', templateUrl: './inbox-dashboard.component.html', host: {'class': 'block h-full'}, + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class InboxDashboardComponent implements OnChanges { diff --git a/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.ts b/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.ts index f1d562d4cd..abfd42c886 100644 --- a/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.ts +++ b/src/app/units/states/tasks/inbox/directives/moderation/confirm-moderation-modal/confirm-moderation-modal.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {FeedbackModerationActionType} from 'src/app/api/models/task'; import {Task} from 'src/app/api/models/task'; @@ -10,6 +10,7 @@ import {ConfirmModerationModalData} from './confirm-moderation-modal.service'; selector: 'f-confirm-moderation-modal', templateUrl: './confirm-moderation-modal.component.html', styleUrl: './confirm-moderation-modal.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ConfirmModerationModalComponent implements OnInit { diff --git a/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.ts b/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.ts index 761c0e4010..c1ae2b0225 100644 --- a/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.ts +++ b/src/app/units/states/tasks/inbox/directives/moderation/moderation.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Router} from '@angular/router'; import {FeedbackModerationActionType, Task} from 'src/app/api/models/task'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -8,6 +8,7 @@ import {ConfirmModerationModalService} from './confirm-moderation-modal/confirm- selector: 'f-moderation', templateUrl: './moderation.component.html', styleUrl: './moderation.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ModerationComponent { diff --git a/src/app/units/states/tasks/inbox/directives/staff-task-list/batch-feedback-workflow-dialog/batch-feedback-workflow-dialog.component.ts b/src/app/units/states/tasks/inbox/directives/staff-task-list/batch-feedback-workflow-dialog/batch-feedback-workflow-dialog.component.ts index ae95e7e203..3ff4d4f302 100644 --- a/src/app/units/states/tasks/inbox/directives/staff-task-list/batch-feedback-workflow-dialog/batch-feedback-workflow-dialog.component.ts +++ b/src/app/units/states/tasks/inbox/directives/staff-task-list/batch-feedback-workflow-dialog/batch-feedback-workflow-dialog.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {TaskDefinition, Unit} from 'src/app/api/models/doubtfire-model'; @@ -11,6 +11,7 @@ export interface BatchFeedbackWorkflowDialogData { @Component({ selector: 'f-batch-feedback-workflow-dialog', templateUrl: './batch-feedback-workflow-dialog.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class BatchFeedbackWorkflowDialogComponent { diff --git a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts index d5fc369806..d27857003b 100644 --- a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts +++ b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts @@ -1,6 +1,7 @@ /* eslint-disable no-shadow, @typescript-eslint/no-shadow */ import {HotkeysService} from '@ngneat/hotkeys'; import { + ChangeDetectionStrategy, Component, Input, OnChanges, @@ -42,6 +43,7 @@ import {BatchFeedbackWorkflowDialogComponent} from './batch-feedback-workflow-di selector: 'df-staff-task-list', templateUrl: './staff-task-list.component.html', styleUrls: ['./staff-task-list.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { diff --git a/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.ts b/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.ts index 2ef59dd69b..e79654c560 100644 --- a/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.ts +++ b/src/app/units/states/tasks/inbox/directives/task-claim/task-claim.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {MatSnackBar} from '@angular/material/snack-bar'; import {Task} from 'src/app/api/models/task'; import {UnitRole} from 'src/app/api/models/unit-role'; @@ -10,6 +10,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; selector: 'f-task-claim', templateUrl: './task-claim.component.html', styleUrl: './task-claim.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskClaimComponent { diff --git a/src/app/units/states/tasks/inbox/inbox.component.html b/src/app/units/states/tasks/inbox/inbox.component.html index 7dfe9338b0..1ad317db4e 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.html +++ b/src/app/units/states/tasks/inbox/inbox.component.html @@ -73,7 +73,7 @@ } @else { } @@ -156,7 +156,7 @@

        {{ taskData?.selectedTask?.project.student.nickname }}

        } @else { } diff --git a/src/app/units/states/tasks/inbox/inbox.component.ts b/src/app/units/states/tasks/inbox/inbox.component.ts index 0964f06543..71924db971 100644 --- a/src/app/units/states/tasks/inbox/inbox.component.ts +++ b/src/app/units/states/tasks/inbox/inbox.component.ts @@ -1,7 +1,15 @@ import {HotkeysHelpComponent, HotkeysService} from '@ngneat/hotkeys'; import {MediaObserver} from 'ng-flex-layout'; import {CdkDragEnd, CdkDragMove, CdkDragStart} from '@angular/cdk/drag-drop'; -import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + Input, + OnDestroy, + OnInit, + ViewChild, +} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {Router} from '@angular/router'; import {Observable, Subject, auditTime, merge, of, tap, withLatestFrom} from 'rxjs'; @@ -19,6 +27,7 @@ import {SelectedTaskService} from 'src/app/projects/states/dashboard/selected-ta selector: 'f-inbox', templateUrl: './inbox.component.html', styleUrls: ['./inbox.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class InboxComponent implements OnInit, OnDestroy { diff --git a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts index 032fdcf4fc..05f22ae741 100644 --- a/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts +++ b/src/app/units/states/tasks/inbox/unit-task-inbox-state.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {Observable, first, of, tap} from 'rxjs'; import { @@ -42,6 +42,7 @@ type TaskSource = ( @Component({ selector: 'f-unit-task-inbox-state', templateUrl: './unit-task-inbox-state.component.html', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitTaskInboxStateComponent implements OnInit, OnDestroy { diff --git a/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.ts b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.ts index d593c2ad68..5360b13f58 100644 --- a/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.ts +++ b/src/app/units/task-viewer/directives/task-details-view/task-details-view.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, signal} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, signal} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; import {Unit} from 'src/app/api/models/unit'; @@ -6,6 +6,7 @@ import {Unit} from 'src/app/api/models/unit'; selector: 'f-task-details-view', templateUrl: './task-details-view.component.html', styleUrls: ['./task-details-view.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FTaskDetailsViewComponent { diff --git a/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.ts b/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.ts index 256db4968e..7f027aab91 100644 --- a/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.ts +++ b/src/app/units/task-viewer/directives/task-sheet-view/task-sheet-view.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {TaskDefinition} from 'src/app/api/models/task-definition'; @Component({ selector: 'f-task-sheet-view', templateUrl: './task-sheet-view.component.html', styleUrls: ['./task-sheet-view.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FTaskSheetViewComponent { diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index 19b0e9c736..0cb2ba0562 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -1,4 +1,12 @@ -import {Component, HostBinding, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + HostBinding, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {BehaviorSubject} from 'rxjs'; import {Project, Task, TaskDefinition} from 'src/app/api/models/doubtfire-model'; @@ -9,6 +17,7 @@ import {TaskDefinitionNamePipe} from 'src/app/common/filters/task-definition-nam selector: 'f-unit-task-list', templateUrl: './unit-task-list.component.html', styleUrls: ['./unit-task-list.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class FUnitTaskListComponent implements OnChanges, OnInit { diff --git a/src/app/units/task-viewer/task-viewer-state.component.ts b/src/app/units/task-viewer/task-viewer-state.component.ts index edc089dfbc..36c6635f83 100644 --- a/src/app/units/task-viewer/task-viewer-state.component.ts +++ b/src/app/units/task-viewer/task-viewer-state.component.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import {Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {BehaviorSubject, Observable} from 'rxjs'; import {of} from 'rxjs'; @@ -9,6 +9,7 @@ import {TaskDefinition, Unit} from 'src/app/api/models/doubtfire-model'; selector: 'f-task-viewer-state', templateUrl: './task-viewer-state.component.html', styleUrl: './task-viewer-state.component.scss', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskViewerStateComponent { diff --git a/src/app/units/unit-root-state.component.ts b/src/app/units/unit-root-state.component.ts index f66a6d3bee..55feeecb27 100644 --- a/src/app/units/unit-root-state.component.ts +++ b/src/app/units/unit-root-state.component.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import {Component, Input, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {Observable} from 'rxjs'; import {Unit} from 'src/app/api/models/doubtfire-model'; @@ -8,6 +8,7 @@ import {Unit} from 'src/app/api/models/doubtfire-model'; selector: 'f-unit-root-state', templateUrl: './unit-root-state.component.html', styleUrl: './unit-root-state.component.css', + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class UnitRootStateComponent implements OnInit { diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts index b6e4835462..fd874e7c19 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts @@ -1,5 +1,6 @@ import {formatDate} from '@angular/common'; import { + ChangeDetectionStrategy, Component, Input, LOCALE_ID, @@ -26,6 +27,7 @@ interface BurndownSeries { selector: 'f-progress-burndown-chart', templateUrl: './progress-burndown-chart.component.html', styleUrls: ['./progress-burndown-chart.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class ProgressBurndownChartComponent diff --git a/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts index c7fc6c6a1b..f2028a452b 100644 --- a/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts +++ b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.ts @@ -1,4 +1,11 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import {Project, TaskStatus} from 'src/app/api/models/doubtfire-model'; import {ChartBaseComponent} from 'src/app/common/chart-base/chart-base-component/chart-base-component.component'; @@ -6,6 +13,7 @@ import {ChartBaseComponent} from 'src/app/common/chart-base/chart-base-component selector: 'f-task-status-pie-chart', templateUrl: './task-status-pie-chart.component.html', styleUrls: ['./task-status-pie-chart.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskStatusPieChartComponent extends ChartBaseComponent implements OnChanges, OnInit { diff --git a/src/app/visualisations/task-visualisation/task-visualisation.component.ts b/src/app/visualisations/task-visualisation/task-visualisation.component.ts index 74a6d92898..ba1dc1a54e 100644 --- a/src/app/visualisations/task-visualisation/task-visualisation.component.ts +++ b/src/app/visualisations/task-visualisation/task-visualisation.component.ts @@ -1,10 +1,18 @@ -import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import {Project, TaskStatus} from 'src/app/api/models/doubtfire-model'; @Component({ selector: 'f-task-visualisation', templateUrl: './task-visualisation.component.html', styleUrls: ['./task-visualisation.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class TaskVisualisationComponent implements OnChanges, OnInit { diff --git a/src/app/welcome/welcome.component.ts b/src/app/welcome/welcome.component.ts index 5abc2b4439..afa619b690 100644 --- a/src/app/welcome/welcome.component.ts +++ b/src/app/welcome/welcome.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit} from '@angular/core'; +import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core'; import {Router} from '@angular/router'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; @@ -9,6 +9,7 @@ import {GlobalStateService} from '../projects/states/index/global-state.service' selector: 'f-welcome', templateUrl: './welcome.component.html', styleUrls: ['./welcome.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) export class WelcomeComponent implements OnInit { diff --git a/src/tsconfig.app.json b/src/tsconfig.app.json index 4e165072c4..c15174ae8c 100644 --- a/src/tsconfig.app.json +++ b/src/tsconfig.app.json @@ -5,5 +5,14 @@ "types": [] }, "files": ["main.ts", "polyfills.ts"], - "include": ["src/**/*.d.ts", "src/**/*.ts"] + "include": ["src/**/*.d.ts", "src/**/*.ts"], + "angularCompilerOptions": { + // TODO: Re-enable extendedDiagnostics after strictTempaltes is enabled + // "extendedDiagnostics": { + // "checks": { + // "nullishCoalescingNotNullable": "suppress", + // "optionalChainNotNullable": "suppress" + // } + // } + } } diff --git a/src/tsconfig.spec.json b/src/tsconfig.spec.json index 5fa6abff5f..8d291fc904 100644 --- a/src/tsconfig.spec.json +++ b/src/tsconfig.spec.json @@ -5,5 +5,13 @@ "typeRoots": ["../node_modules/@types", "../node_modules"], "types": ["vitest/globals", "node"] }, - "include": ["**/*.spec.ts", "**/*.d.ts", "vitest-setup.ts"] + "include": ["**/*.spec.ts", "**/*.d.ts", "vitest-setup.ts"], + "angularCompilerOptions": { + "extendedDiagnostics": { + "checks": { + "nullishCoalescingNotNullable": "suppress", + "optionalChainNotNullable": "suppress" + } + } + } } diff --git a/tsconfig.json b/tsconfig.json index 84230f0709..5a5fc3099e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,11 @@ { "compileOnSave": false, "compilerOptions": { + "ignoreDeprecations": "6.0", "baseUrl": "./", "importHelpers": true, "module": "es2020", + "rootDir": ".", "outDir": "./build", "sourceMap": true, "esModuleInterop": true, From e300ac043f199442e361235e5ba2affafe90decc Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:40:39 +1000 Subject: [PATCH 1145/1531] chore: upgrade material ui to 22 --- package-lock.json | 44 ++++++++++++++++++++++---------------------- package.json | 6 +++--- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index cf8a3ab19e..fc17ee8128 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,13 +10,13 @@ "license": "AGPL-3.0", "dependencies": { "@angular/animations": "^22.0.2", - "@angular/cdk": "^21.2.9", + "@angular/cdk": "^22.0.2", "@angular/common": "^22.0.2", "@angular/compiler": "^22.0.2", "@angular/core": "^22.0.2", "@angular/forms": "^22.0.2", - "@angular/material": "^21.2.9", - "@angular/material-date-fns-adapter": "^21.2.9", + "@angular/material": "^22.0.2", + "@angular/material-date-fns-adapter": "^22.0.2", "@angular/platform-browser": "^22.0.2", "@angular/platform-browser-dynamic": "^22.0.2", "@angular/router": "^22.0.2", @@ -1654,18 +1654,18 @@ } }, "node_modules/@angular/cdk": { - "version": "21.2.14", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-21.2.14.tgz", - "integrity": "sha512-806REq/CLf37nEhmmd8Q+ILN8z/RVG2vk2n8YZ/4TdHpcBCi5ux4AxLbpMmduLwGPOzPagJ6ggRzE5fnX0rmcQ==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-22.0.2.tgz", + "integrity": "sha512-3AOyLNIpvXkxbiCeUc4R5ubwCBpY83ZPe2I6Q/cTUW53SnFapEBNYZ2spSY+jPVY4IVPnQN1Tvjlzq6R9K4M3w==", "license": "MIT", "dependencies": { "parse5": "^8.0.0", "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^21.0.0 || ^22.0.0", - "@angular/core": "^21.0.0 || ^22.0.0", - "@angular/platform-browser": "^21.0.0 || ^22.0.0", + "@angular/common": "^22.0.0 || ^23.0.0", + "@angular/core": "^22.0.0 || ^23.0.0", + "@angular/platform-browser": "^22.0.0 || ^23.0.0", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -1940,33 +1940,33 @@ } }, "node_modules/@angular/material": { - "version": "21.2.14", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-21.2.14.tgz", - "integrity": "sha512-fMQca8VRtei93JRRG9qQ+u08DCb0nga59Esoakq5yx3+A1NfdpFeUS1tBns56U04o8KAaIAwZK3NBqXz8ZKNqg==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-22.0.2.tgz", + "integrity": "sha512-a2sp9ipozR4THqu5A3ff3VXBpbQHpfTmH+Oqb0+RD47fJ+/kvyBUZQ5JK2Yh6eUXVceAOW4s+sL0ev8tS1EfuQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/cdk": "21.2.14", - "@angular/common": "^21.0.0 || ^22.0.0", - "@angular/core": "^21.0.0 || ^22.0.0", - "@angular/forms": "^21.0.0 || ^22.0.0", - "@angular/platform-browser": "^21.0.0 || ^22.0.0", + "@angular/cdk": "22.0.2", + "@angular/common": "^22.0.0 || ^23.0.0", + "@angular/core": "^22.0.0 || ^23.0.0", + "@angular/forms": "^22.0.0 || ^23.0.0", + "@angular/platform-browser": "^22.0.0 || ^23.0.0", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/material-date-fns-adapter": { - "version": "21.2.14", - "resolved": "https://registry.npmjs.org/@angular/material-date-fns-adapter/-/material-date-fns-adapter-21.2.14.tgz", - "integrity": "sha512-PvfX/Y+6ml8G+Zacgmp52nerI4fQmPtCKPDweUVA5Drm8Ygoo3zdVS9UnB+74KuH56I+AS5IZ8usJSwdV+z1UQ==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@angular/material-date-fns-adapter/-/material-date-fns-adapter-22.0.2.tgz", + "integrity": "sha512-xoxECE2NowCIT3GlKIfxFh8tvuaS4g7wV9wN9rbMH284SRITC1TavvhtFdLcCDrMafUvSxY/du441SBcBmOoKg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/core": "^21.0.0 || ^22.0.0", - "@angular/material": "21.2.14", + "@angular/core": "^22.0.0 || ^23.0.0", + "@angular/material": "22.0.2", "date-fns": ">2.20.0 <5.0" } }, diff --git a/package.json b/package.json index 3d849a4a55..452ebf402e 100644 --- a/package.json +++ b/package.json @@ -26,13 +26,13 @@ "author": "", "dependencies": { "@angular/animations": "^22.0.2", - "@angular/cdk": "^21.2.9", + "@angular/cdk": "^22.0.2", "@angular/common": "^22.0.2", "@angular/compiler": "^22.0.2", "@angular/core": "^22.0.2", "@angular/forms": "^22.0.2", - "@angular/material": "^21.2.9", - "@angular/material-date-fns-adapter": "^21.2.9", + "@angular/material": "^22.0.2", + "@angular/material-date-fns-adapter": "^22.0.2", "@angular/platform-browser": "^22.0.2", "@angular/platform-browser-dynamic": "^22.0.2", "@angular/router": "^22.0.2", From 886d9b7be89707c10e62f63b1f534b48dc832b8a Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:41:26 +1000 Subject: [PATCH 1146/1531] chore: upgrade angular eslint to 22 --- package-lock.json | 470 ++++++++++------------------------------------ package.json | 12 +- 2 files changed, 106 insertions(+), 376 deletions(-) diff --git a/package-lock.json b/package-lock.json index fc17ee8128..ec43a6471f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -68,11 +68,11 @@ "zone.js": "~0.16.2" }, "devDependencies": { - "@angular-eslint/builder": "^21.4.0", - "@angular-eslint/eslint-plugin": "^21.4.0", - "@angular-eslint/eslint-plugin-template": "^21.4.0", - "@angular-eslint/schematics": "^21.4.0", - "@angular-eslint/template-parser": "^21.4.0", + "@angular-eslint/builder": "^22.0.0", + "@angular-eslint/eslint-plugin": "^22.0.0", + "@angular-eslint/eslint-plugin-template": "^22.0.0", + "@angular-eslint/schematics": "^22.0.0", + "@angular-eslint/template-parser": "^22.0.0", "@angular/build": "^22.0.3", "@angular/cli": "^22.0.3", "@angular/compiler-cli": "^22.0.2", @@ -88,7 +88,7 @@ "@types/node": "^20.9.0", "@typescript-eslint/eslint-plugin": "^8.60.1", "@typescript-eslint/parser": "^8.60.1", - "angular-eslint": "^21.4.0", + "angular-eslint": "^22.0.0", "autoprefixer": "~6", "canonical-path": "0.0.2", "concurrently": "^3.2.0", @@ -360,32 +360,32 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.2102.15", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2102.15.tgz", - "integrity": "sha512-EZQXu6j7J7OUxmpxIO2mxd58NTlCb7HOAOfLLGdk7lRcwZeCxnjGRzb72tXlJgIEi3IoOYwcW0ft2cg7r/d6qA==", + "version": "0.2200.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2200.3.tgz", + "integrity": "sha512-Ru+ucNkTZr98gmeaBYjq3zZwh32yGofAeB8+GJL/ZNy0x+7NzK6b+OatdzwT4l7mCWFC5vL8iYu0B4++M66Jpg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "21.2.15", + "@angular-devkit/core": "22.0.3", "rxjs": "7.8.2" }, "bin": { "architect": "bin/cli.js" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } }, "node_modules/@angular-devkit/core": { - "version": "21.2.15", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.2.15.tgz", - "integrity": "sha512-x7EwuQtMGHANVznHpwyEi/3lMo/kRoaxV2w7lXbRGjTezwv4SPaOBwhrIGCbAVFs5B1ziff4jZzors4owlCTgg==", + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.0.3.tgz", + "integrity": "sha512-pBjo1JKwI8GbNdTo/Z0g+ZekqlTBCJWmzIC5fgGW9q5eRjl1y+5N5jlX8UAyyMCeUTTwsfpQdkAM2jyi/jcvjA==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "8.18.0", + "ajv": "8.20.0", "ajv-formats": "3.0.1", "jsonc-parser": "3.3.1", "picomatch": "4.0.4", @@ -393,7 +393,7 @@ "source-map": "0.7.6" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, @@ -407,130 +407,143 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "21.2.15", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-21.2.15.tgz", - "integrity": "sha512-kHHV694KUPuXlItjvnxUspn+KYjlTKu8KINX/kT1qlogzLYojpnRwcUtZyRPUz1f/M1d3TUHVFeBKx+h5HoNcA==", + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-22.0.3.tgz", + "integrity": "sha512-aIp5sQDHdhyLbeVJF/k3w079XhW91mNAo2OliZllBCjoYhkIXNnWECOx5y2nXtCChyFJA2+ZgNST7NIDvtz1/w==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "21.2.15", + "@angular-devkit/core": "22.0.3", "jsonc-parser": "3.3.1", "magic-string": "0.30.21", - "ora": "9.3.0", + "ora": "9.4.0", "rxjs": "7.8.2" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "node": "^22.22.3 || ^24.15.0 || >=26.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } }, "node_modules/@angular-eslint/builder": { - "version": "21.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-21.4.0.tgz", - "integrity": "sha512-3kgGmrVaCYbLtDjC8g4BmMBbdz4thsOB8/NYly8JtXM8EuDZEk5Pz6VTRpJR02ARprwayraTTmhyvq6OGBlQ9w==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-22.0.0.tgz", + "integrity": "sha512-T2vWQYUhJs6iUlgocHV12OgoxbmN63f17a+tgW+3sYrKN0KAB3xuHsPOoYpRYoWqkVVC44HD441Ju4IDvo8vKg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": ">= 0.2100.0 < 0.2200.0", - "@angular-devkit/core": ">= 21.0.0 < 22.0.0" + "@angular-devkit/architect": ">= 0.2200.0 < 0.2300.0", + "@angular-devkit/core": ">= 22.0.0 < 23.0.0" }, "peerDependencies": { - "@angular/cli": ">= 21.0.0 < 22.0.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "@angular/cli": ">= 22.0.0 < 23.0.0", + "eslint": "^9.0.0 || ^10.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "21.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-21.4.0.tgz", - "integrity": "sha512-/3H4BPbQ1BHJkkrUsfusZtmHc+qiFWBBZ9UDPWah4xZMjflexOK9U4GYeH7nMjcuyqFnIlMMeJJNwNLGt/hmdg==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-22.0.0.tgz", + "integrity": "sha512-rv15vGDpGW8zZFaLdhQ+iIO1f0bZds/xvuxoX277hFisXp5Kt6FumJNNIb4g/qxq3xsY46a7fD6R7KvGY3smHg==", "dev": true, "license": "MIT" }, "node_modules/@angular-eslint/eslint-plugin": { - "version": "21.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-21.4.0.tgz", - "integrity": "sha512-mow2DMj+xBvGl5t7jzC34R8YfbHbaGNyCNFzpovtl9qc0JbuqLyg6htmt8xb05f8ZjATOr4nz0ESt6HV4c51hw==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-22.0.0.tgz", + "integrity": "sha512-mKLScPZhqG64ic0KIQoxqSqCdkPwtEZuTOuunvc9lYTw05MJSHRUM2yVFODlCGq97c6BN1F6KBk2I+a+KFnr1g==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "21.4.0", - "@angular-eslint/utils": "21.4.0", + "@angular-eslint/bundled-angular-compiler": "22.0.0", + "@angular-eslint/utils": "22.0.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "@typescript-eslint/utils": "^8.0.0", + "eslint": "^9.0.0 || ^10.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "21.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-21.4.0.tgz", - "integrity": "sha512-sJEHx2WYnvOgPpzP1eHnUdRS06zgKmRxbiIR0JiCcaSen5iv1HlsMieXy//FS9TtNW+abHOy4UtDuGuSPflPFA==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-22.0.0.tgz", + "integrity": "sha512-y6XL5HJ8C31NpBvkVHpU3bWc+Rk9g1zRtHrs39omhuT29eEUcS3zu47HMFV6tf8rHOI97B2Mstg6qYS5XL9ATg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "21.4.0", - "@angular-eslint/utils": "21.4.0", + "@angular-eslint/bundled-angular-compiler": "22.0.0", + "@angular-eslint/utils": "22.0.0", "aria-query": "5.3.2", "axobject-query": "4.1.0" }, "peerDependencies": { - "@angular-eslint/template-parser": "21.4.0", - "@typescript-eslint/types": "^7.11.0 || ^8.0.0", - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "@angular-eslint/template-parser": "22.0.0", + "@typescript-eslint/types": "^8.0.0", + "@typescript-eslint/utils": "^8.0.0", + "eslint": "^9.0.0 || ^10.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/schematics": { - "version": "21.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-21.4.0.tgz", - "integrity": "sha512-crD6Hfxs7x5bN9FCqTZI7uVSiGvprfCS3MCPOpyIQl87bRr/9aNhnicJ3ROUHv+2A713BgPHIgiCII/bxzrfPw==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-22.0.0.tgz", + "integrity": "sha512-gsJQx6c+WIWC5d+NAqn4rRdUzwhinUCTNmCM9x4wygV9DrbAfVG+6OFPEbaDMryNvf0HYDcnGclbIbXjukGCaw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": ">= 21.0.0 < 22.0.0", - "@angular-devkit/schematics": ">= 21.0.0 < 22.0.0", - "@angular-eslint/eslint-plugin": "21.4.0", - "@angular-eslint/eslint-plugin-template": "21.4.0", + "@angular-devkit/core": ">= 22.0.0 < 23.0.0", + "@angular-devkit/schematics": ">= 22.0.0 < 23.0.0", + "@angular-eslint/eslint-plugin": "22.0.0", + "@angular-eslint/eslint-plugin-template": "22.0.0", "ignore": "7.0.5", - "semver": "7.7.4", + "semver": "7.8.0", "strip-json-comments": "3.1.1" }, "peerDependencies": { - "@angular/cli": ">= 21.0.0 < 22.0.0" + "@angular/cli": ">= 22.0.0 < 23.0.0" + } + }, + "node_modules/@angular-eslint/schematics/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/@angular-eslint/template-parser": { - "version": "21.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-21.4.0.tgz", - "integrity": "sha512-BaUSLSyS+43fzDoJkTMkGqNdCXq3fGnUZsfXTmrlZPJf5AYFbgAlAPGZXDJyoNWw43fux+DafdlrlKcYUSgSIw==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-22.0.0.tgz", + "integrity": "sha512-jU5MKQ24bBB4J99gSSexmUrLm2LvTJZCuCHhNTQ1LavWX4e1lrIxhm+6pJILOm6Cixf8jyNXnHMty6nljX8J+Q==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "21.4.0", + "@angular-eslint/bundled-angular-compiler": "22.0.0", "eslint-scope": "9.1.2" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "eslint": "^9.0.0 || ^10.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/utils": { - "version": "21.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-21.4.0.tgz", - "integrity": "sha512-7pi+Ga7QmdH5Ig/diau6fR5L4yubgKr9TOjdCg7OeuE/zo0O3osTCNT6JOodzS/iQM1kSCJFDoIBKFeUOttiNw==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-22.0.0.tgz", + "integrity": "sha512-VFodMojghnPYm+B3U+HRYrqebPMj8NyobNjVzDdY8V5XIBW+4ivOSEINIz81G48rmm/NZKwj56+bJ88bVX4KIw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "21.4.0" + "@angular-eslint/bundled-angular-compiler": "22.0.0" }, "peerDependencies": { - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "@typescript-eslint/utils": "^8.0.0", + "eslint": "^9.0.0 || ^10.0.0", "typescript": "*" } }, @@ -652,53 +665,6 @@ } } }, - "node_modules/@angular/build/node_modules/@angular-devkit/architect": { - "version": "0.2200.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2200.3.tgz", - "integrity": "sha512-Ru+ucNkTZr98gmeaBYjq3zZwh32yGofAeB8+GJL/ZNy0x+7NzK6b+OatdzwT4l7mCWFC5vL8iYu0B4++M66Jpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "22.0.3", - "rxjs": "7.8.2" - }, - "bin": { - "architect": "bin/cli.js" - }, - "engines": { - "node": "^22.22.3 || ^24.15.0 || >=26.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/build/node_modules/@angular-devkit/core": { - "version": "22.0.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.0.3.tgz", - "integrity": "sha512-pBjo1JKwI8GbNdTo/Z0g+ZekqlTBCJWmzIC5fgGW9q5eRjl1y+5N5jlX8UAyyMCeUTTwsfpQdkAM2jyi/jcvjA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.20.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^22.22.3 || ^24.15.0 || >=26.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, "node_modules/@angular/build/node_modules/@esbuild/aix-ppc64": { "version": "0.28.1", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", @@ -1498,23 +1464,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@angular/build/node_modules/ajv": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@angular/build/node_modules/esbuild": { "version": "0.28.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", @@ -1704,125 +1653,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { - "version": "0.2200.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2200.3.tgz", - "integrity": "sha512-Ru+ucNkTZr98gmeaBYjq3zZwh32yGofAeB8+GJL/ZNy0x+7NzK6b+OatdzwT4l7mCWFC5vL8iYu0B4++M66Jpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "22.0.3", - "rxjs": "7.8.2" - }, - "bin": { - "architect": "bin/cli.js" - }, - "engines": { - "node": "^22.22.3 || ^24.15.0 || >=26.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/cli/node_modules/@angular-devkit/core": { - "version": "22.0.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.0.3.tgz", - "integrity": "sha512-pBjo1JKwI8GbNdTo/Z0g+ZekqlTBCJWmzIC5fgGW9q5eRjl1y+5N5jlX8UAyyMCeUTTwsfpQdkAM2jyi/jcvjA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.20.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^22.22.3 || ^24.15.0 || >=26.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular/cli/node_modules/@angular-devkit/schematics": { - "version": "22.0.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-22.0.3.tgz", - "integrity": "sha512-aIp5sQDHdhyLbeVJF/k3w079XhW91mNAo2OliZllBCjoYhkIXNnWECOx5y2nXtCChyFJA2+ZgNST7NIDvtz1/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "22.0.3", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.21", - "ora": "9.4.0", - "rxjs": "7.8.2" - }, - "engines": { - "node": "^22.22.3 || ^24.15.0 || >=26.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/cli/node_modules/ajv": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@angular/cli/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@angular/cli/node_modules/ora": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-9.4.0.tgz", - "integrity": "sha512-84cglkRILFxdtA8hAvLNdMrtBpPNBTrQ9/ulg0FA7xLMnD6mifv+enAIeRmvtv+WgdCE+LPGOfQmtJRrVaIVhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.6.2", - "cli-cursor": "^5.0.0", - "cli-spinners": "^3.2.0", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.1.0", - "log-symbols": "^7.0.1", - "stdin-discarder": "^0.3.2", - "string-width": "^8.1.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@angular/common": { "version": "22.0.2", "resolved": "https://registry.npmjs.org/@angular/common/-/common-22.0.2.tgz", @@ -6082,106 +5912,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { - "version": "22.0.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.0.3.tgz", - "integrity": "sha512-pBjo1JKwI8GbNdTo/Z0g+ZekqlTBCJWmzIC5fgGW9q5eRjl1y+5N5jlX8UAyyMCeUTTwsfpQdkAM2jyi/jcvjA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.20.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^22.22.3 || ^24.15.0 || >=26.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@schematics/angular/node_modules/@angular-devkit/schematics": { - "version": "22.0.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-22.0.3.tgz", - "integrity": "sha512-aIp5sQDHdhyLbeVJF/k3w079XhW91mNAo2OliZllBCjoYhkIXNnWECOx5y2nXtCChyFJA2+ZgNST7NIDvtz1/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "22.0.3", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.21", - "ora": "9.4.0", - "rxjs": "7.8.2" - }, - "engines": { - "node": "^22.22.3 || ^24.15.0 || >=26.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@schematics/angular/node_modules/ajv": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@schematics/angular/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@schematics/angular/node_modules/ora": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-9.4.0.tgz", - "integrity": "sha512-84cglkRILFxdtA8hAvLNdMrtBpPNBTrQ9/ulg0FA7xLMnD6mifv+enAIeRmvtv+WgdCE+LPGOfQmtJRrVaIVhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.6.2", - "cli-cursor": "^5.0.0", - "cli-spinners": "^3.2.0", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.1.0", - "log-symbols": "^7.0.1", - "stdin-discarder": "^0.3.2", - "string-width": "^8.1.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@sigstore/bundle": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-4.0.0.tgz", @@ -7077,9 +6807,9 @@ } }, "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { @@ -7185,25 +6915,25 @@ } }, "node_modules/angular-eslint": { - "version": "21.4.0", - "resolved": "https://registry.npmjs.org/angular-eslint/-/angular-eslint-21.4.0.tgz", - "integrity": "sha512-LH7bWmtJvsubzwPoztnl1pWgI5X0VrfGTUITGSYcwn2J+SXuN/avzrKrxJmhUiIrNvLtfV+18GG6xZS1IGZdKg==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/angular-eslint/-/angular-eslint-22.0.0.tgz", + "integrity": "sha512-6tHLndzM6rU+2iuICakJS/hD1scK5sWLkcD7828zStT1ViA9zX8z9g/V1IlBiKEdZeMsl+m7K2DlNc34AkYyoQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": ">= 21.0.0 < 22.0.0", - "@angular-devkit/schematics": ">= 21.0.0 < 22.0.0", - "@angular-eslint/builder": "21.4.0", - "@angular-eslint/eslint-plugin": "21.4.0", - "@angular-eslint/eslint-plugin-template": "21.4.0", - "@angular-eslint/schematics": "21.4.0", - "@angular-eslint/template-parser": "21.4.0", + "@angular-devkit/core": ">= 22.0.0 < 23.0.0", + "@angular-devkit/schematics": ">= 22.0.0 < 23.0.0", + "@angular-eslint/builder": "22.0.0", + "@angular-eslint/eslint-plugin": "22.0.0", + "@angular-eslint/eslint-plugin-template": "22.0.0", + "@angular-eslint/schematics": "22.0.0", + "@angular-eslint/template-parser": "22.0.0", "@typescript-eslint/types": "^8.0.0", "@typescript-eslint/utils": "^8.0.0" }, "peerDependencies": { - "@angular/cli": ">= 21.0.0 < 22.0.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "@angular/cli": ">= 22.0.0 < 23.0.0", + "eslint": "^9.0.0 || ^10.0.0", "typescript": "*", "typescript-eslint": "^8.0.0" } @@ -13708,9 +13438,9 @@ } }, "node_modules/ora": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-9.3.0.tgz", - "integrity": "sha512-lBX72MWFduWEf7v7uWf5DHp9Jn5BI8bNPGuFgtXMmr2uDz2Gz2749y3am3agSDdkhHPHYmmxEGSKH85ZLGzgXw==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-9.4.0.tgz", + "integrity": "sha512-84cglkRILFxdtA8hAvLNdMrtBpPNBTrQ9/ulg0FA7xLMnD6mifv+enAIeRmvtv+WgdCE+LPGOfQmtJRrVaIVhQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13720,7 +13450,7 @@ "is-interactive": "^2.0.0", "is-unicode-supported": "^2.1.0", "log-symbols": "^7.0.1", - "stdin-discarder": "^0.3.1", + "stdin-discarder": "^0.3.2", "string-width": "^8.1.0" }, "engines": { diff --git a/package.json b/package.json index 452ebf402e..5add687337 100644 --- a/package.json +++ b/package.json @@ -84,11 +84,11 @@ "zone.js": "~0.16.2" }, "devDependencies": { - "@angular-eslint/builder": "^21.4.0", - "@angular-eslint/eslint-plugin": "^21.4.0", - "@angular-eslint/eslint-plugin-template": "^21.4.0", - "@angular-eslint/schematics": "^21.4.0", - "@angular-eslint/template-parser": "^21.4.0", + "@angular-eslint/builder": "^22.0.0", + "@angular-eslint/eslint-plugin": "^22.0.0", + "@angular-eslint/eslint-plugin-template": "^22.0.0", + "@angular-eslint/schematics": "^22.0.0", + "@angular-eslint/template-parser": "^22.0.0", "@angular/build": "^22.0.3", "@angular/cli": "^22.0.3", "@angular/compiler-cli": "^22.0.2", @@ -104,7 +104,7 @@ "@types/node": "^20.9.0", "@typescript-eslint/eslint-plugin": "^8.60.1", "@typescript-eslint/parser": "^8.60.1", - "angular-eslint": "^21.4.0", + "angular-eslint": "^22.0.0", "autoprefixer": "~6", "canonical-path": "0.0.2", "concurrently": "^3.2.0", From e2b718c1aed4f8ea3746a6f0f0622ebc7af6f8b4 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:54:51 +1000 Subject: [PATCH 1147/1531] chore: suppress change detection eager warnings --- eslint.config.js | 1 + .../directives/student-task-list/student-task-list.component.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index f724f8a890..c30806bfe0 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -61,6 +61,7 @@ module.exports = tseslint.config( '@angular-eslint/prefer-standalone': 'off', '@typescript-eslint/consistent-generic-constructors': ['error', 'type-annotation'], '@typescript-eslint/no-inferrable-types': 'off', + '@angular-eslint/prefer-on-push-component-change-detection': 'off', '@typescript-eslint/no-unused-vars': [ 'error', { diff --git a/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.ts b/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.ts index fae6805595..a4bd5296cd 100644 --- a/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.ts +++ b/src/app/projects/states/dashboard/directives/student-task-list/student-task-list.component.ts @@ -6,6 +6,6 @@ import {ChangeDetectionStrategy, Component} from '@angular/core'; imports: [], templateUrl: './student-task-list.component.html', styleUrl: './student-task-list.component.css', - changeDetection: ChangeDetectionStrategy.OnPush, + changeDetection: ChangeDetectionStrategy.Eager, }) export class StudentTaskListComponent {} From ec4bab9719e12e5ceffb74f4b2f9f44713c70ff0 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:19:03 +1000 Subject: [PATCH 1148/1531] chore: update packages --- package-lock.json | 28 ++++++++++++++-------------- package.json | 4 ++-- src/app/doubtfire-angular.module.ts | 3 ++- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index ec43a6471f..c4272051da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,9 +54,9 @@ "ng-file-upload": "~5.0.9", "ng-flex-layout": "^17.3.7-beta.1", "ng2-pdf-viewer": "10.2.2", - "ngx-entity-service": "^0.0.43", + "ngx-entity-service": "^0.0.44", "ngx-lottie": "^21.2.0", - "ngx-monaco-editor-v2": "^21", + "ngx-monaco-editor-v2-alternative": "^22.0.0", "ngx-skeleton-loader": "^12.0.0", "nvd3": "1.8.6", "qrcode": "^1.5.4", @@ -12859,15 +12859,15 @@ } }, "node_modules/ngx-entity-service": { - "version": "0.0.43", - "resolved": "https://registry.npmjs.org/ngx-entity-service/-/ngx-entity-service-0.0.43.tgz", - "integrity": "sha512-O77ZIu3822bKsiL8nBpj+4DW5q6V53URO5iiAojYVwITdd2zFmsiOZjgrYUEjEAIT7B+o5sDKvpzROZ1CS33OQ==", + "version": "0.0.44", + "resolved": "https://registry.npmjs.org/ngx-entity-service/-/ngx-entity-service-0.0.44.tgz", + "integrity": "sha512-FmSYKulHJxILKzLkBhXjNJsMdd55Slu11/TLg89GJZq3guBBD8RDsxHtbN1mKku5+Dp8i8H6vNSqJ3bwsyYwVw==", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17 || ^18 || ^19 || ^20 || ^21", - "@angular/core": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17 || ^18 || ^19 || ^20 || ^21" + "@angular/common": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17 || ^18 || ^19 || ^20 || ^21 || ^22", + "@angular/core": "^13.0 || ^14.0 || ^15.0 || ^16.0 || ^17 || ^18 || ^19 || ^20 || ^21 || ^22" } }, "node_modules/ngx-lottie": { @@ -12884,17 +12884,17 @@ "lottie-web": ">=5.9.2" } }, - "node_modules/ngx-monaco-editor-v2": { - "version": "21.1.4", - "resolved": "https://registry.npmjs.org/ngx-monaco-editor-v2/-/ngx-monaco-editor-v2-21.1.4.tgz", - "integrity": "sha512-dZu3dY3D1YXPTIDRn9zOERdtDtGy1SOztpWG6gJlaj6NMSV59kNR/hfzaP+L3BukP6Ve07f3bIyvsx6Pz7uOaA==", + "node_modules/ngx-monaco-editor-v2-alternative": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/ngx-monaco-editor-v2-alternative/-/ngx-monaco-editor-v2-alternative-22.0.0.tgz", + "integrity": "sha512-JB5eSWdtDhJF5hhuDUQQyABfx+1JHHWFwvhdn/R74twxE2NcCODWqgPFNKYLZhWKiPIG/w6TlpsyfS68wRNw0g==", "license": "MIT", "dependencies": { - "tslib": "^2.8.1" + "tslib": "^2.4.0" }, "peerDependencies": { - "@angular/common": "^21.1.4", - "@angular/core": "^21.1.4", + "@angular/common": "^22.0.0", + "@angular/core": "^22.0.0", "monaco-editor": "^0.55.1" } }, diff --git a/package.json b/package.json index 5add687337..21049bd0a4 100644 --- a/package.json +++ b/package.json @@ -70,9 +70,9 @@ "ng-file-upload": "~5.0.9", "ng-flex-layout": "^17.3.7-beta.1", "ng2-pdf-viewer": "10.2.2", - "ngx-entity-service": "^0.0.43", + "ngx-entity-service": "^0.0.44", "ngx-lottie": "^21.2.0", - "ngx-monaco-editor-v2": "^21", + "ngx-monaco-editor-v2-alternative": "^22.0.0", "ngx-skeleton-loader": "^12.0.0", "nvd3": "1.8.6", "qrcode": "^1.5.4", diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index f64afd172d..27c6b54932 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -19,7 +19,8 @@ import player from 'lottie-web'; import {PdfViewerModule} from 'ng2-pdf-viewer'; import {FlexLayoutModule} from 'ng-flex-layout'; import {LottieComponent, provideLottieOptions} from 'ngx-lottie'; -import {MonacoEditorModule} from 'ngx-monaco-editor-v2'; +// TODO: replace back to original ngx-monaco-editor-v2 once it supports angular 22 +import {MonacoEditorModule} from 'ngx-monaco-editor-v2-alternative'; import {NgxSkeletonLoaderModule} from 'ngx-skeleton-loader'; import {environment} from 'src/environments/environment'; // import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; From 1d228d5f01ec712761dafbafb6d6bbfa2aa5be75 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:20:19 +1000 Subject: [PATCH 1149/1531] ci: use node 22 --- .github/workflows/lint.yml | 2 +- .github/workflows/nodejs-ci.yml | 2 +- .github/workflows/test.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 42e81cb2d1..953c8b8fa9 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: - node-version: [20] + node-version: [22] steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/nodejs-ci.yml b/.github/workflows/nodejs-ci.yml index ea2b1cd81c..c2f9f1a4ef 100644 --- a/.github/workflows/nodejs-ci.yml +++ b/.github/workflows/nodejs-ci.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - node-version: [20] + node-version: [22] steps: - uses: actions/checkout@v4 - uses: browser-actions/setup-chrome@latest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5a5dc93556..a8da82c7e4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,10 +10,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Use Node.js 20 + - name: Use Node.js 22 uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: npm - run: npm ci - run: npm run test:ci From f9357bbb5646f4ce57007dd1b4d139775badb02f Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:20:50 +1000 Subject: [PATCH 1150/1531] build: use node 22 --- Dockerfile | 2 +- deploy.Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 18590c09e9..0a0b3f0c7c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20 +FROM node:22 ENV DEBIAN_FRONTEND noninteractive ENV USER=node diff --git a/deploy.Dockerfile b/deploy.Dockerfile index 9aa69355e3..f39e326af0 100644 --- a/deploy.Dockerfile +++ b/deploy.Dockerfile @@ -1,5 +1,5 @@ ### STAGE 1: Build ### -FROM node:20 AS build +FROM node:22 AS build USER node From 6790339fcbef96f4bc9664998fa2f2b9b8fcdb61 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:23:29 +1000 Subject: [PATCH 1151/1531] chore: update deps --- .tool-versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tool-versions b/.tool-versions index c2ca3d3d25..42bb250e67 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -nodejs 20.9.0 +nodejs 22.22.3 From 4d02701447bf68b78d3c05631bf92a94ec0d2c92 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:25:51 +1000 Subject: [PATCH 1152/1531] ci: update packages to support node 22 --- .github/workflows/deployment.yml | 10 +++++----- .github/workflows/lint.yml | 4 ++-- .github/workflows/nodejs-ci.yml | 6 +++--- .github/workflows/test.yml | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 40d35b9eee..6c986fcff7 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -50,20 +50,20 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: recursive - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to DockerHub - uses: docker/login-action@v3 + uses: docker/login-action@v4 if: github.event_name != 'pull_request' with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Setup meta for web server id: docker_meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: lmsdoubtfire/doubtfire-web tags: | @@ -74,7 +74,7 @@ jobs: type=semver,pattern=prod-{{major}} - name: Build and push web server id: docker_build - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v7 with: file: deploy.Dockerfile context: . diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 953c8b8fa9..a6e94362b6 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,9 +13,9 @@ jobs: node-version: [22] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: ${{ matrix.node-version }} - run: npm ci diff --git a/.github/workflows/nodejs-ci.yml b/.github/workflows/nodejs-ci.yml index c2f9f1a4ef..df3f516514 100644 --- a/.github/workflows/nodejs-ci.yml +++ b/.github/workflows/nodejs-ci.yml @@ -15,10 +15,10 @@ jobs: matrix: node-version: [22] steps: - - uses: actions/checkout@v4 - - uses: browser-actions/setup-chrome@latest + - uses: actions/checkout@v6 + - uses: browser-actions/setup-chrome@v2 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: ${{ matrix.node-version }} - run: npm ci diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a8da82c7e4..0254469205 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,9 +9,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Use Node.js 22 - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: 22 cache: npm From 20d610e16c2cf106abc713ade05cb69432cfbc50 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:43:10 +1000 Subject: [PATCH 1153/1531] chore: hotfix tooltip errors --- .../chart-base-component.component.ts | 7 +---- .../project-progress-gauge.component.html | 1 + .../project-progress-gauge.component.ts | 25 ++-------------- .../analytics-tutor-times.component.html | 30 +++++++++++++++---- .../analytics-tutor-times.component.scss | 15 ++++++++++ .../analytics-tutor-times.component.ts | 11 +++++++ .../progress-burndown-chart.component.html | 1 + .../task-status-pie-chart.component.html | 1 + 8 files changed, 56 insertions(+), 35 deletions(-) diff --git a/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts b/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts index e54f546dcc..326b8cd75c 100644 --- a/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts +++ b/src/app/common/chart-base/chart-base-component/chart-base-component.component.ts @@ -1,6 +1,4 @@ -import {TooltipService} from '@swimlane/ngx-charts'; import {ChangeDetectionStrategy, Component, ViewContainerRef} from '@angular/core'; -import {AppInjector} from 'src/app/app-injector'; /** * @title chart-base-component @@ -14,8 +12,5 @@ import {AppInjector} from 'src/app/app-injector'; standalone: false, }) export class ChartBaseComponent { - constructor(public viewContainerRef: ViewContainerRef) { - const chartToolTipService = AppInjector.get(TooltipService); - chartToolTipService.injectionService.setRootViewContainer(this.viewContainerRef); - } + constructor(public viewContainerRef: ViewContainerRef) {} } diff --git a/src/app/common/project-progress/project-progress-gauge.component.html b/src/app/common/project-progress/project-progress-gauge.component.html index c1a7ba8dca..c3fada1231 100644 --- a/src/app/common/project-progress/project-progress-gauge.component.html +++ b/src/app/common/project-progress/project-progress-gauge.component.html @@ -12,6 +12,7 @@ [showAxis]="false" [showText]="true" [textValue]="gaugeData[0].value" + [tooltipDisabled]="true" [view]="view" > diff --git a/src/app/common/project-progress/project-progress-gauge.component.ts b/src/app/common/project-progress/project-progress-gauge.component.ts index 75a4249481..07b5f0d265 100644 --- a/src/app/common/project-progress/project-progress-gauge.component.ts +++ b/src/app/common/project-progress/project-progress-gauge.component.ts @@ -1,12 +1,4 @@ -import {TooltipService} from '@swimlane/ngx-charts'; -import { - ChangeDetectionStrategy, - Component, - Injector, - Input, - OnInit, - ViewContainerRef, -} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {Project} from 'src/app/api/models/project'; @Component({ @@ -16,7 +8,7 @@ import {Project} from 'src/app/api/models/project'; changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) -export class ProjectProgressGaugeComponent implements OnInit { +export class ProjectProgressGaugeComponent { @Input() project: Project; protected gaugeData = [ @@ -38,19 +30,6 @@ export class ProjectProgressGaugeComponent implements OnInit { }, ]; - ngOnInit(): void { - this.chartToolTipService.injectionService.setRootViewContainer(this.viewContainerRef); - - console.log(this.project.taskStats); - } - - constructor(private injectorObj: Injector) { - this.chartToolTipService = this.injectorObj.get(TooltipService); - this.viewContainerRef = this.injectorObj.get(ViewContainerRef); - } - private chartToolTipService: TooltipService; - readonly viewContainerRef: ViewContainerRef; - smallView = [90, 90]; view = [500, 500]; legend: boolean = true; diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html index 6298d27683..449c726ca2 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.html +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.html @@ -90,25 +90,43 @@

        Tutor Times Session Summary

        @if (isLoading) { - - +
        } + + +
        + {{ weekEvent.event.title }} +
        +
        diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.scss b/src/app/units/states/analytics/directives/analytics-tutor-times.component.scss index 2ce45fc98d..298a078abc 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.scss +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.scss @@ -14,3 +14,18 @@ width: 100%; min-height: 35px; } + +.analytics-loading-spinner { + width: 48px; + height: 48px; + border: 4px solid rgb(0 0 0 / 12%); + border-top-color: var(--mat-sys-primary, #3f51b5); + border-radius: 50%; + animation: analytics-spinner-rotate 800ms linear infinite; +} + +@keyframes analytics-spinner-rotate { + to { + transform: rotate(360deg); + } +} diff --git a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts index 99712feab4..8d6db18fde 100644 --- a/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts +++ b/src/app/units/states/analytics/directives/analytics-tutor-times.component.ts @@ -269,6 +269,17 @@ export class AnalyticsTutorTimesComponent implements OnInit { } } + sessionEventTitle(event: SessionEvent): string { + return [ + `${event.tutorName} (${event.duration} minutes)${event.duringTutorial ? ' T' : ''}`, + `${event.startHour} - ${event.endHour}`, + `Assessments: ${event.assessments || 0}`, + `Comments: ${event.commentsAdded || 0}`, + `Submissions opened: ${event.submissionsOpened || 0}`, + `During Tutorial?: ${event.duringTutorial ? 'yes' : 'no'}`, + ].join('\n'); + } + private stringToHexColor( name: string, opts?: {hue?: [number, number]; sat?: [number, number]; lit?: [number, number]}, diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index d4406f7937..e2b819eaed 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -8,6 +8,7 @@ [scheme]="colorScheme" [showXAxisLabel]="showXAxisLabel" [showYAxisLabel]="showYAxisLabel" + [tooltipDisabled]="true" [view]="" [xAxis]="xAxis" [xAxisLabel]="xAxisLabel" diff --git a/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.html b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.html index b4c56c857b..0f477cb78d 100644 --- a/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.html +++ b/src/app/visualisations/task-status-pie-chart/task-status-pie-chart.component.html @@ -6,6 +6,7 @@ [legend]="true" [legendTitle]="''" [results]="data" + [tooltipDisabled]="true" [view]="" > From e1f9baa6b3a87247694a81ae45355212cb071e32 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:45:39 +1000 Subject: [PATCH 1154/1531] test: fix ci --- .../common/hero-sidebar/hero-sidebar.component.spec.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts b/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts index 19ed7c2b1a..96247b980e 100644 --- a/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts +++ b/src/app/common/hero-sidebar/hero-sidebar.component.spec.ts @@ -1,5 +1,7 @@ import {beforeEach, describe, expect, it} from 'vitest'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {BehaviorSubject} from 'rxjs'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {HeroSidebarComponent} from './hero-sidebar.component'; describe('HeroSidebarComponent', () => { @@ -9,6 +11,12 @@ describe('HeroSidebarComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [HeroSidebarComponent], + providers: [ + { + provide: DoubtfireConstants, + useValue: {ExternalName: new BehaviorSubject('Doubtfire')}, + }, + ], }).compileComponents(); }); From 7bcc4460c22226af58d0a41e6eb21bd027168365 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:51:04 +1000 Subject: [PATCH 1155/1531] chore: bump node requirement --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index c4272051da..f9018de1ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -111,7 +111,7 @@ "vitest": "^4.1.8" }, "engines": { - "node": ">=20.9.0" + "node": ">=22.22.3" }, "optionalDependencies": { "@nx/nx-darwin-arm64": "^18.0", diff --git a/package.json b/package.json index 21049bd0a4..284eb2f421 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "license": "AGPL-3.0", "repository": {}, "engines": { - "node": ">=20.9.0" + "node": ">=22.22.3" }, "scripts": { "build": "ng build", From 4583569390e686f7aca3ee4bebcda4be630274a5 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 15:00:58 +1000 Subject: [PATCH 1156/1531] Merge pull request #1201 from b0ink/feat/overflow-task-claim-analytics feat: download overflow task claim analytics --- src/app/api/models/unit.ts | 6 ++++++ .../analytics/unit-analytics-route.component.html | 3 +++ .../analytics/unit-analytics-route.component.ts | 14 +++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/app/api/models/unit.ts b/src/app/api/models/unit.ts index 37f11595cc..9a00a22d11 100644 --- a/src/app/api/models/unit.ts +++ b/src/app/api/models/unit.ts @@ -673,6 +673,12 @@ export class Unit extends Entity { ); } + public downloadOverflowTaskClaimsCsv(): Observable { + return AppInjector.get(HttpClient).get( + `${AppInjector.get(DoubtfireConstants).API_URL}/csv/units/${this.id}/overflow_task_claims`, + ); + } + public downloadTutorAssessmentCsv(): Observable { return AppInjector.get(HttpClient).get( `${AppInjector.get(DoubtfireConstants).API_URL}/csv/units/${this.id}/tutor_assessments`, diff --git a/src/app/units/states/analytics/unit-analytics-route.component.html b/src/app/units/states/analytics/unit-analytics-route.component.html index 39b3461d24..9a554016c3 100644 --- a/src/app/units/states/analytics/unit-analytics-route.component.html +++ b/src/app/units/states/analytics/unit-analytics-route.component.html @@ -16,6 +16,9 @@

        Unit Statistics

        + diff --git a/src/app/units/states/analytics/unit-analytics-route.component.ts b/src/app/units/states/analytics/unit-analytics-route.component.ts index b05fa7187b..c8f2cabaf9 100644 --- a/src/app/units/states/analytics/unit-analytics-route.component.ts +++ b/src/app/units/states/analytics/unit-analytics-route.component.ts @@ -1,4 +1,5 @@ -import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; +import {formatDate} from '@angular/common'; +import {ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {Observable, first, of} from 'rxjs'; import {SidekiqJob} from 'src/app/api/models/sidekiq-job'; @@ -27,6 +28,7 @@ export class UnitAnalyticsComponent implements OnInit { private userService: UserService, private alertService: AlertService, private route: ActivatedRoute, + @Inject(LOCALE_ID) private locale: string, ) {} ngOnInit(): void { @@ -72,6 +74,16 @@ export class UnitAnalyticsComponent implements OnInit { ); } + public getOverflowTaskClaimsCsv() { + const timestamp = formatDate(new Date(), 'd-MMMM-y-HHmm', this.locale).toLowerCase(); + + this.downloadCsv( + this.unit.downloadOverflowTaskClaimsCsv(), + 'Overflow Task Claims CSV', + `${this.unit.code}-overflow-task-claims-${timestamp}.csv`, + ); + } + public downloadCsv(newJob: Observable, title: string, filename: string) { newJob.subscribe({ next: (job) => { From fc75fcb2f61eacaee6620bd2362bff50d386d801 Mon Sep 17 00:00:00 2001 From: Boink <40929320+b0ink@users.noreply.github.com> Date: Fri, 19 Jun 2026 16:43:36 +1000 Subject: [PATCH 1157/1531] chore: upgrade to tailwindcss 4 (#1292) * chore: upgrade to tailwindcss 4 * fix: restore intellisense * chore: format --- .postcssrc.json | 6 + package-lock.json | 1126 +++++++++-------- package.json | 9 +- .../teaching-period-unit-import.dialog.html | 2 +- .../admin/states/units/units.component.html | 2 +- .../archive-viewer.component.html | 8 +- .../audio-comment-recorder.html | 2 +- .../file-uploader.component.html | 2 +- .../nested-csv-download-modal.component.html | 2 +- .../about-doubtfire-modal-content.tpl.html | 8 +- .../csv-result-modal.component.html | 18 +- .../sidekiq-progress-modal.component.html | 2 +- .../status-icon/status-icon.component.html | 2 +- .../unavailable-card.component.html | 2 +- .../group-member-list.component.html | 2 +- .../group-set-manager.component.html | 2 +- .../lti-dashboard.component.html | 4 +- .../project-progress-dashboard.component.html | 2 +- .../engagement-detail-dialog.component.html | 12 +- .../student-task-list.tpl.html | 2 +- .../task-ilos-card.component.html | 2 +- .../submission-files-modal.component.html | 6 +- .../task-overseer-report.component.html | 6 +- .../task-scorm-card.component.html | 2 +- .../task-dashboard.component.html | 2 +- .../task-dashboard/task-dashboard.tpl.html | 4 +- .../staff-notes/staff-notes.component.html | 12 +- .../tutor-discussion.component.html | 14 +- .../tutor-discussion.component.scss | 27 +- .../tutor-notes/tutor-notes.component.html | 14 +- .../submission-type-modal.component.html | 2 +- .../upload-submission-modal.component.html | 2 +- ...achment-confirmation-dialog.component.html | 2 +- .../task-feedback-templates.component.html | 2 +- .../task-assessment-comment.component.html | 2 +- .../analytics-tutor-times.component.html | 2 +- .../communication-schedules.component.html | 8 +- .../task-definition-editor.component.html | 8 +- ...sk-definition-prerequisites.component.html | 2 +- .../task-definition-scorm.component.html | 2 +- .../unit-task-editor.component.html | 2 +- .../unit-tutorials-list.component.html | 2 +- .../inbox-dashboard.component.html | 2 +- .../staff-task-list.component.html | 2 +- .../unit-task-list.component.html | 12 +- src/styles.scss | 6 +- src/tailwind-intellisense.css | 2 + 47 files changed, 715 insertions(+), 649 deletions(-) create mode 100644 .postcssrc.json create mode 100644 src/tailwind-intellisense.css diff --git a/.postcssrc.json b/.postcssrc.json new file mode 100644 index 0000000000..865e00b364 --- /dev/null +++ b/.postcssrc.json @@ -0,0 +1,6 @@ +{ + "syntax": "postcss-scss", + "plugins": { + "@tailwindcss/postcss": {} + } +} diff --git a/package-lock.json b/package-lock.json index f9018de1ba..c53b176b2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "@ngneat/hotkeys": "^4.0.0", "@ngstack/code-editor": "^9.0.0", "@swimlane/ngx-charts": "^20.5.0", + "@tailwindcss/postcss": "^4.3.1", "@worktile/gantt": "^21.0.0", "angular-calendar": "^0.31.1", "angular-cookies": "1.5.11", @@ -100,11 +101,11 @@ "ip": "^2.0.1", "jsdom": "^29.1.1", "npm-run-all2": "^7.0", - "postcss": "^8.5.10", - "postcss-scss": "^0.1.7", + "postcss": "^8.5.15", + "postcss-scss": "^4.0.9", "prettier": "^3.8.3", - "sass": "^1.48.0", - "tailwindcss": "~3.4.17", + "sass": "^1.101.0", + "tailwindcss": "^4.3.1", "ts-node": "~10.9", "typescript": "~6.0.3", "underscore": "^1.8.3", @@ -336,7 +337,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -3955,7 +3955,6 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -3966,7 +3965,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -3977,7 +3975,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -3987,14 +3984,12 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -6069,6 +6064,284 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, + "node_modules/@tailwindcss/node": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.1.tgz", + "integrity": "sha512-6NDaqRoAMSXD1mr/RXu0HBvNE9a2n5tHPsxu9XHLws8o4Twes5rBM2205SUUiJ9goAtadrN6xTGX0UDEwp/N4A==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "5.21.6", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.1" + } + }, + "node_modules/@tailwindcss/node/node_modules/enhanced-resolve": { + "version": "5.21.6", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz", + "integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tailwindcss/node/node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.1.tgz", + "integrity": "sha512-yVPyo8RNkabVr3O2EhHEE0Rewu7YKzc1DhIqfL46LKveFrmu9XbDazNOJY7/GRuvw1h6u3utWnR29H/p5JPlgA==", + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.1", + "@tailwindcss/oxide-darwin-arm64": "4.3.1", + "@tailwindcss/oxide-darwin-x64": "4.3.1", + "@tailwindcss/oxide-freebsd-x64": "4.3.1", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.1", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.1", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.1", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.1", + "@tailwindcss/oxide-linux-x64-musl": "4.3.1", + "@tailwindcss/oxide-wasm32-wasi": "4.3.1", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.1", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.1" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.1.tgz", + "integrity": "sha512-SVlyf61g374l5cHyg8x9kf5xmLcOaxvOTsbsqDnSsDJaKOEFZ7GCvi84VAVGpxojYOs1+3K6M0UjXfqPU8vmOQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.1.tgz", + "integrity": "sha512-hVnWLwv+e/l7c4WKyVtHVrIPvYdqWHjRB3MDIqARynzFtnQg85kmQEFCbV9Ja0VVx4xXTIiDWY60Y7iz/iNoDA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.1.tgz", + "integrity": "sha512-Cf7abu0WVgbhU7ANgPUnSAvm7nCvMweusHb8FnaHlLfv/Caq4GYaEZg7ZImzzmjx4lIAfuS8q+eLIS7A7IzxIg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.1.tgz", + "integrity": "sha512-ZZqzX2Y+GXtXXfqSfpJhDm60OoZfvLHLCgm+J7NVqgHHJjG/m9ugZI77RwTsVd4fnBJuCFP6Ae6kTJb71UdS8g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.1.tgz", + "integrity": "sha512-/Ah/xik0LaMYfv9DZ0S/t4pBlBNYOcqtRwusjgovHkvT8ixueWCLyJjsaF5kQIckjb4IT8Q6K6p/iPmZMixYgg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.1.tgz", + "integrity": "sha512-gqdFoVJlw444GvpnheZLHmvTzSxI/cOUUh2KSNejQjTcYkW062SVD+En0rUgD+QV91bz1XGIGtt1HJd48xUGbQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.1.tgz", + "integrity": "sha512-Bwv9KwOvE0VKa86xPFif9b9c3Y1NxOV1P0gLti/IYaWEsQYZXDlxfGEtA8mdDZ7SG3wyNXAWYT5SIn3giL57oA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.1.tgz", + "integrity": "sha512-Ymi8O8T15HYQdOUWUtTI6ldN0neHP85FC+Qz32xTcZ7iJXtem/x8ITev0o1e9e5rkqj4lONZfTRLvkmin1+tKg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.1.tgz", + "integrity": "sha512-M+P/91qJ6uILLw4k2G93GMDRAXj61SMvFQYt39AqvUqYgExXpLL5aepfns7sj4HiAQeolirQF9E0lzRvdf4zPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.1.tgz", + "integrity": "sha512-zsM8uOeqvVGHsAXsJxsT28ttosFahLJKCLOTUBqRAtKnVgGSRitds9T432QiT8b77Yga7JIBkulIRRlJPtYhRA==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.10.0", + "@emnapi/runtime": "^1.10.0", + "@emnapi/wasi-threads": "^1.2.1", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.1.tgz", + "integrity": "sha512-aiNvSq9BsVk8V513lDKlrCFAgf8qBMPZTpgEhInL+NwQqs97mYmupVMrPrgBBSL8Pv/0zXu9MrMF9rMun1ZeNg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.1.tgz", + "integrity": "sha512-xDEyu1rg290472FEGaKHnzyDyh5QH+AlWvsU5hMoMtPpzmKlRI0jaYKCgSHDYtaQWZOYbMaduSyCwFwY4n1HmA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.1.tgz", + "integrity": "sha512-dNJuNbdEJT/SWRuXTYP1WSamelsz3ztkUsdtWQPjrexysrTpaEPM40P/71knXiXLYEojqPOEGitVLLpPMS5T6A==", + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.1", + "@tailwindcss/oxide": "4.3.1", + "postcss": "8.5.15", + "tailwindcss": "4.3.1" + } + }, "node_modules/@trivago/prettier-plugin-sort-imports": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-6.0.2.tgz", @@ -7022,19 +7295,14 @@ "node": ">=4" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, - "license": "MIT" - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -7049,6 +7317,8 @@ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8.6" }, @@ -7093,13 +7363,6 @@ "node": ">= 6" } }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, - "license": "MIT" - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -7360,6 +7623,8 @@ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8" }, @@ -7690,16 +7955,6 @@ "node": ">=6" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/caniuse-db": { "version": "1.0.30001797", "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001797.tgz", @@ -8425,19 +8680,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/custom-event": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", @@ -8850,7 +9092,6 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=8" } @@ -8864,13 +9105,6 @@ "optional": true, "peer": true }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/diff": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", @@ -8887,13 +9121,6 @@ "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", "license": "MIT" }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, - "license": "MIT" - }, "node_modules/dom-serialize": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", @@ -10430,7 +10657,6 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/has-ansi": { @@ -10951,6 +11177,8 @@ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -11902,30 +12130,266 @@ "immediate": "~3.0.5" } }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, - "license": "MIT", + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, "engines": { - "node": ">=14" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/listr2": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-10.2.1.tgz", - "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-10.2.1.tgz", + "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -12231,7 +12695,6 @@ "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -12755,18 +13218,6 @@ "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "node_modules/nan": { "version": "2.27.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.27.0.tgz", @@ -12778,7 +13229,6 @@ "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true, "funding": [ { "type": "github", @@ -13109,6 +13559,8 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -13344,16 +13796,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -13876,7 +14318,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -13914,16 +14355,6 @@ "node": ">=4" } }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/piscina": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.1.4.tgz", @@ -13978,7 +14409,6 @@ "version": "8.5.15", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -14003,268 +14433,65 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-import/node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", "dev": true, "license": "MIT" }, - "node_modules/postcss-js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", - "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "node_modules/postcss-safe-parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", + "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" + }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", - "dependencies": { - "camelcase-css": "^2.0.1" - }, "engines": { - "node": "^12 || ^14 || >= 16" + "node": ">=18.0" }, "peerDependencies": { - "postcss": "^8.4.21" + "postcss": "^8.4.31" } }, - "node_modules/postcss-load-config": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", - "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", - "dependencies": { - "lilconfig": "^3.1.1" - }, "engines": { - "node": ">= 18" + "node": ">=12.0" }, "peerDependencies": { - "jiti": ">=1.21.0", - "postcss": ">=8.0.9", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true, - "license": "MIT" - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-safe-parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", - "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-scss": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-0.1.9.tgz", - "integrity": "sha512-FkLd8Pxci394edesXqewjAd6eMnYGUPK5bgkYbYHX7YPeJDcuaKMuHnXsd0i3tnXJOLTuX+L+m3edda1IKMrbQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss": "^5.1.0" - } - }, - "node_modules/postcss-scss/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-scss/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-scss/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-scss/node_modules/chalk/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/postcss-scss/node_modules/postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/postcss-scss/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-scss/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" + "postcss": "^8.4.29" } }, "node_modules/postcss-value-parser": { @@ -14690,26 +14917,6 @@ "node": ">=0.10.0" } }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/read-cache/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/read-package-json-fast": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", @@ -15047,9 +15254,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.100.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz", - "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", + "version": "1.101.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.101.0.tgz", + "integrity": "sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==", "dev": true, "license": "MIT", "dependencies": { @@ -15738,7 +15945,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -15950,39 +16156,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sucrase": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", - "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "tinyglobby": "^0.2.11", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/sucrase/node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", @@ -16051,122 +16224,15 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", - "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.6.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.7", - "lilconfig": "^3.1.3", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.47", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", - "postcss-nested": "^6.2.0", - "postcss-selector-parser": "^6.1.2", - "resolve": "^1.22.8", - "sucrase": "^3.35.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tailwindcss/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/tailwindcss/node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/tailwindcss/node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/tailwindcss/node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/tailwindcss/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.1.tgz", + "integrity": "sha512-hk+TB1m+K8CYNrP6rjQaq/Y+4Zylwpa87mLYBKCunwnnQ9p+fHb7kmSfGqyEJoxF/O6CDyABWVFEafNSYKll+Q==", + "license": "MIT" }, "node_modules/tapable": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -16263,29 +16329,6 @@ "node": ">=18" } }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -16429,13 +16472,6 @@ "typescript": ">=4.8.4" } }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/ts-md5": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/ts-md5/-/ts-md5-1.3.1.tgz", diff --git a/package.json b/package.json index 284eb2f421..e6356cdb59 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "@ngneat/hotkeys": "^4.0.0", "@ngstack/code-editor": "^9.0.0", "@swimlane/ngx-charts": "^20.5.0", + "@tailwindcss/postcss": "^4.3.1", "@worktile/gantt": "^21.0.0", "angular-calendar": "^0.31.1", "angular-cookies": "1.5.11", @@ -116,11 +117,11 @@ "ip": "^2.0.1", "jsdom": "^29.1.1", "npm-run-all2": "^7.0", - "postcss": "^8.5.10", - "postcss-scss": "^0.1.7", + "postcss": "^8.5.15", + "postcss-scss": "^4.0.9", "prettier": "^3.8.3", - "sass": "^1.48.0", - "tailwindcss": "~3.4.17", + "sass": "^1.101.0", + "tailwindcss": "^4.3.1", "ts-node": "~10.9", "typescript": "~6.0.3", "underscore": "^1.8.3", diff --git a/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.html b/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.html index 275098a43d..28ea364d2e 100644 --- a/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.html +++ b/src/app/admin/states/teaching-periods/teaching-period-unit-import/teaching-period-unit-import.dialog.html @@ -78,7 +78,7 @@

        Import Units Into {{ data.teachingPeriod.name }}

      -
      +
      Unit Code(s) diff --git a/src/app/admin/states/units/units.component.html b/src/app/admin/states/units/units.component.html index d334c47c1c..b7ef11e74c 100644 --- a/src/app/admin/states/units/units.component.html +++ b/src/app/admin/states/units/units.component.html @@ -5,7 +5,7 @@

      {{ title }}

      - + Search search diff --git a/src/app/common/archive-viewer/archive-viewer.component.html b/src/app/common/archive-viewer/archive-viewer.component.html index 2b081b24ec..51331b3e4f 100644 --- a/src/app/common/archive-viewer/archive-viewer.component.html +++ b/src/app/common/archive-viewer/archive-viewer.component.html @@ -1,4 +1,4 @@ -
      +
      @if (isLoading) {
      @@ -43,7 +43,7 @@ @if (navigationMode === 'tree') {
    diff --git a/src/app/common/notification-settings/notification-settings.component.spec.ts b/src/app/common/notification-settings/notification-settings.component.spec.ts index 13bbf25837..b0f26cb8a5 100644 --- a/src/app/common/notification-settings/notification-settings.component.spec.ts +++ b/src/app/common/notification-settings/notification-settings.component.spec.ts @@ -84,4 +84,23 @@ describe('NotificationSettingsComponent', () => { expect(text).toContain('Receive notifications for feedback-related events.'); expect(text).toContain('Receive notifications for portfolio-related events.'); }); + + it('associates each checkbox with its help text', () => { + const inputs = fixture.nativeElement.querySelectorAll('input[type="checkbox"]'); + const descriptions = fixture.nativeElement.querySelectorAll('.notification-setting small'); + const descriptionIds = [ + 'task-notification-description', + 'feedback-notification-description', + 'portfolio-notification-description', + ]; + + expect(inputs.length).toBe(3); + expect(descriptions.length).toBe(3); + + descriptionIds.forEach((id, index) => { + expect(descriptions[index].id).toBe(id); + expect(inputs[index].getAttribute('aria-describedby')).toBe(id); + expect(inputs[index].hasAttribute('name')).toBe(false); + }); + }); }); From 60c1d3e13ac7f1fbce613ed1629339966327f444 Mon Sep 17 00:00:00 2001 From: The Herald Sun Date: Mon, 17 Aug 2026 05:03:51 +0000 Subject: [PATCH 1336/1531] feat: add new maskable icon and alter manifest entry to use it --- .../icons/android-chrome-maskable-512x512.png | Bin 0 -> 7529 bytes src/manifest.webmanifest | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/assets/icons/android-chrome-maskable-512x512.png diff --git a/src/assets/icons/android-chrome-maskable-512x512.png b/src/assets/icons/android-chrome-maskable-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..ca17d722a5ddaa7a2e0977fd75ec5d4e4cf0a01d GIT binary patch literal 7529 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 literal 0 HcmV?d00001 diff --git a/src/manifest.webmanifest b/src/manifest.webmanifest index d04bdbeee4..6aa76a0c12 100644 --- a/src/manifest.webmanifest +++ b/src/manifest.webmanifest @@ -13,7 +13,7 @@ "type": "image/png" }, { - "src": "/assets/icons/android-chrome-512x512.png", + "src": "/assets/icons/android-chrome-maskable-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" From ea5c1fd90c471206b99eb98b6ff41e01aa9089e6 Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Mon, 17 Aug 2026 15:05:14 +1000 Subject: [PATCH 1337/1531] fix(notifications): cancel requests on sign out and order count responses reset() now cancels every request the service has handed out before it clears, so a response in flight at sign out cannot write the previous user's rows back into a cache the whole app shares. Unread count requests carry a sequence number and only a newer one can move the subject, so an older response can no longer overwrite a newer count. A local write retires the requests already in the air for the same reason. --- src/app/api/services/notification.service.ts | 75 ++++++++++++- .../spec/notification.service.spec.ts | 106 +++++++++++++++++- 2 files changed, 175 insertions(+), 6 deletions(-) diff --git a/src/app/api/services/notification.service.ts b/src/app/api/services/notification.service.ts index 6b9ac7ada4..b8e02cadc5 100644 --- a/src/app/api/services/notification.service.ts +++ b/src/app/api/services/notification.service.ts @@ -1,7 +1,7 @@ import {CachedEntityService, RequestOptions} from 'ngx-entity-service'; import {HttpClient} from '@angular/common/http'; import {Injectable} from '@angular/core'; -import {BehaviorSubject, Observable, map, tap} from 'rxjs'; +import {BehaviorSubject, Observable, Subject, map, takeUntil, tap} from 'rxjs'; import API_URL from 'src/app/config/constants/apiUrl'; import {Notification} from '../models/notification'; import {MappingFunctions} from './mapping-fn'; @@ -28,6 +28,31 @@ export class NotificationService extends CachedEntityService { private readonly unreadCountSubject: BehaviorSubject = new BehaviorSubject(0); + /** + * Fires once per sign out, from reset(). + * + * Every request this service returns ends with takeUntil on it, so this + * unsubscribes the lot. Unsubscribing aborts the underlying request, which is + * the part that matters: nothing in ngx-entity-service subscribes internally, + * so the cache writes all live in taps on the chain and an aborted request + * never reaches them. Without this, one still in flight at sign out would + * land afterwards and put the previous user's rows back into a cache that is + * shared by the whole app. + */ + private readonly sessionEnded: Subject = new Subject(); + + /** + * Which unread count request is which. + * + * Every mutation asks for the count again, so several are often in the air at + * once, and nothing makes them answer in the order they were sent. The older + * answer is the wrong one, it was computed before the newer mutation applied. + * Each request takes the next number on the way out and only a number higher + * than the last one applied is allowed to move the subject. + */ + private issuedUnreadCountRequests = 0; + private appliedUnreadCountRequest = 0; + constructor(private apiHttpClient: HttpClient) { super(apiHttpClient, API_URL); @@ -99,6 +124,7 @@ export class NotificationService extends CachedEntityService { this.evictMissing(notifications); } }), + takeUntil(this.sessionEnded), ); } @@ -107,11 +133,25 @@ export class NotificationService extends CachedEntityService { * * Direct HttpClient. unread_count answers `{count: n}`, which is not a * Notification. + * + * Only the newest request in flight is allowed to move the subject, see + * appliedUnreadCountRequest. The returned observable still emits whatever the + * server said either way, because the caller asked a question and that is the + * answer to it. unreadCount$ is the one the bell reads and the one that has to + * stay right. */ public refreshUnreadCount(): Observable { + const request = ++this.issuedUnreadCountRequests; + return this.apiHttpClient.get<{count: number}>(`${API_URL}/notifications/unread_count`).pipe( map((response) => response.count), - tap((count) => this.unreadCountSubject.next(count)), + tap((count) => { + if (request > this.appliedUnreadCountRequest) { + this.appliedUnreadCountRequest = request; + this.unreadCountSubject.next(count); + } + }), + takeUntil(this.sessionEnded), ); } @@ -140,6 +180,7 @@ export class NotificationService extends CachedEntityService { this.resyncUnreadCount(); }), + takeUntil(this.sessionEnded), ); } @@ -172,9 +213,10 @@ export class NotificationService extends CachedEntityService { this.cache.set(notification.key, notification); }); - this.unreadCountSubject.next(0); + this.setUnreadCount(0); this.resyncUnreadCount(); }), + takeUntil(this.sessionEnded), ); } @@ -197,6 +239,7 @@ export class NotificationService extends CachedEntityService { this.resyncUnreadCount(); }), + takeUntil(this.sessionEnded), ); } @@ -208,10 +251,19 @@ export class NotificationService extends CachedEntityService { * person's notification messages and the bell keeps their unread count. On a * shared machine the next person to sign in sees both. AuthenticationService * already drops the push registration for the same reason. + * + * Clearing is not enough on its own. Anything still in flight would answer + * after the clear and write the previous user's rows straight back, so the + * requests are cancelled first. */ public reset(): void { + // Before the clear, not after. This unsubscribes every request the service + // has handed out, which aborts each one, so none of them reach the taps + // that write to the cache or the count. + this.sessionEnded.next(); + this.cache.clear(); - this.unreadCountSubject.next(0); + this.setUnreadCount(0); } /** @@ -242,7 +294,20 @@ export class NotificationService extends CachedEntityService { * Floored at zero. A negative badge is a worse thing to show than a stale one. */ private adjustUnreadCount(delta: number): void { - this.unreadCountSubject.next(Math.max(0, this.unreadCountSubject.value + delta)); + this.setUnreadCount(Math.max(0, this.unreadCountSubject.value + delta)); + } + + /** + * Put a locally worked out number on the bell. + * + * A local write counts as newer than every count request already in the air, + * so this retires all of them. Without that, one sent before this line could + * answer after it and undo it. That is the same stale write the sequence + * guard exists to stop, just arriving from the other direction. + */ + private setUnreadCount(count: number): void { + this.appliedUnreadCountRequest = this.issuedUnreadCountRequests; + this.unreadCountSubject.next(count); } /** diff --git a/src/app/api/services/spec/notification.service.spec.ts b/src/app/api/services/spec/notification.service.spec.ts index 8549274fa5..e34d0f3912 100644 --- a/src/app/api/services/spec/notification.service.spec.ts +++ b/src/app/api/services/spec/notification.service.spec.ts @@ -53,7 +53,12 @@ describe('NotificationService', () => { }); afterEach(() => { - httpMock.verify(); + // A cancelled request is still open as far as the backend is concerned, and + // reset() cancels on purpose. The tests that call it assert the + // cancellation themselves. Nothing is lost by ignoring them here: a request + // cancelled by accident still fails, because the flush that was expecting + // it throws rather than being skipped. + httpMock.verify({ignoreCancelled: true}); }); /** @@ -185,6 +190,51 @@ describe('NotificationService', () => { expect(emitted).toBe(7); expect(currentUnreadCount()).toBe(7); }); + + it('ignores an older count response that lands after a newer one', () => { + service.refreshUnreadCount().subscribe(); + service.refreshUnreadCount().subscribe(); + + const requests = httpMock.match(COUNT_URL); + expect(requests).toHaveLength(2); + + // The second request answers first. + requests[1].flush({count: 4}); + expect(currentUnreadCount()).toBe(4); + + // Then the first one answers, carrying the number from before whatever + // triggered the second. Nothing orders http responses, so without the + // sequence guard this overwrites a correct count with a stale one and the + // bell stays wrong until the next mutation. + requests[0].flush({count: 9}); + + expect(currentUnreadCount()).toBe(4); + }); + + it('ignores a count response older than a local change to the count', () => { + seedUnreadCount(5); + + // In flight before the mutation, so its answer was computed without it. + service.refreshUnreadCount().subscribe(); + const stale = httpMock.expectOne(COUNT_URL); + + const notification = new Notification(); + notification.id = 4; + notification.readAt = null; + service.markRead(notification).subscribe(); + httpMock.expectOne(`${API_URL}/notifications/4/read`).flush(readJson(4)); + + expect(currentUnreadCount()).toBe(4); + + // The local decrement is newer than that request, so it has to retire it. + // Guarding only response against response leaves this hole open, and it + // is the common one: every mutation starts a count request. + stale.flush({count: 5}); + + expect(currentUnreadCount()).toBe(4); + + flushResync(4); + }); }); describe('markRead', () => { @@ -375,5 +425,59 @@ describe('NotificationService', () => { expect(service.cache.size).toBe(0); expect(currentUnreadCount()).toBe(0); }); + + it('cancels a list still in flight so it cannot refill the cache', () => { + let emitted = false; + + service.list().subscribe(() => (emitted = true)); + const pending = httpMock.expectOne(LIST_URL); + + service.reset(); + + // Aborted, not merely ignored, and that distinction is the whole fix. + // The cache write lives in a tap inside the base class, upstream of + // anything this service could put a guard in, so the only way to stop it + // is to make sure the response never arrives. + expect(pending.cancelled).toBe(true); + expect(emitted).toBe(false); + expect(service.cache.size).toBe(0); + }); + + it('cancels a count re-sync still in flight so it cannot restore the count', () => { + seedUnreadCount(5); + + const notification = new Notification(); + notification.id = 4; + notification.readAt = null; + + service.markRead(notification).subscribe(); + httpMock.expectOne(`${API_URL}/notifications/4/read`).flush(readJson(4)); + expect(currentUnreadCount()).toBe(4); + + // Nobody holds this one. It is fired and forgotten by every mutation, so + // it is the request most likely to be open when someone signs out. + const resync = httpMock.expectOne(COUNT_URL); + + service.reset(); + + expect(resync.cancelled).toBe(true); + expect(currentUnreadCount()).toBe(0); + }); + + it('cancels a mark read still in flight so it cannot re-add the entity', () => { + primeCache(unreadJson(1)); + + const notification = service.cache.currentValues[0]; + service.markRead(notification).subscribe(); + const pending = httpMock.expectOne(`${API_URL}/notifications/1/read`); + + service.reset(); + + // update() writes the response entity into the cache in a base class tap. + // A sign out between the request and the response would otherwise leave + // one of the previous user's notifications sitting in an empty cache. + expect(pending.cancelled).toBe(true); + expect(service.cache.size).toBe(0); + }); }); }); From 805e4790d88dc2eb6a612f67bb00de4a204fc250 Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Mon, 17 Aug 2026 15:47:34 +1000 Subject: [PATCH 1338/1531] fix(notifications): teach the sign out spec about NotificationService signOut resolves NotificationService through AppInjector and calls reset() on it, which merged with #14. The injector stub in this spec only answers PushNotificationService and GlobalStateService, so it throws "unexpected AppInjector token" and takes three tests down with it. The file is red on feature/notifications as it stands. Adds the NotificationService branch, returning a mock with reset, and asserts it was called once so the branch is load bearing rather than a way to stop a throw. The throw at the end of the stub is left alone and documented: a token it does not know about means signOut grew a dependency nobody told these tests about, and a stub that quietly answered undefined would turn that into a confusing failure somewhere else. Tests: 3 in authentication.service.spec.ts, 135 across the suite. --- .../spec/authentication.service.spec.ts | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/app/api/services/spec/authentication.service.spec.ts b/src/app/api/services/spec/authentication.service.spec.ts index 9a78d157c2..ae718e722b 100644 --- a/src/app/api/services/spec/authentication.service.spec.ts +++ b/src/app/api/services/spec/authentication.service.spec.ts @@ -11,6 +11,7 @@ import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; import {AuthenticationService} from '../authentication.service'; +import {NotificationService} from '../notification.service'; import {PushNotificationService} from '../push-notification.service'; const API_URL = 'http://localhost:3000/api'; @@ -33,6 +34,7 @@ describe('AuthenticationService sign out', () => { let httpMock: HttpTestingController; let pushService: {unsubscribeQuietly: ReturnType}; + let notificationService: {reset: ReturnType}; let globalState: { clearUnitsAndProjects: ReturnType; hideHeader: ReturnType; @@ -46,12 +48,18 @@ describe('AuthenticationService sign out', () => { }; let router: {navigateByUrl: ReturnType}; - // signOut resolves PushNotificationService and GlobalStateService through - // AppInjector rather than the constructor (its comment explains this avoids a - // circular dependency). This stub injector hands back the mocks above. It is - // set once, and reads them through its closure so each test's fresh mocks flow - // through. setAppInjector is only ever called by the app module otherwise, so - // in a unit test AppInjector starts unset and this is the only writer. + // signOut resolves PushNotificationService, GlobalStateService and + // NotificationService through AppInjector rather than the constructor (its + // comment explains this avoids a circular dependency). This stub injector + // hands back the mocks above. It is set once, and reads them through its + // closure so each test's fresh mocks flow through. setAppInjector is only ever + // called by the app module otherwise, so in a unit test AppInjector starts + // unset and this is the only writer. + // + // The throw at the end is deliberate. A token this stub does not know about + // means signOut grew a dependency nobody told these tests about, and a stub + // that quietly answered undefined would turn that into a confusing failure + // somewhere else. const injectorStub = { get: (token: unknown) => { if (token === PushNotificationService) { @@ -60,12 +68,16 @@ describe('AuthenticationService sign out', () => { if (token === GlobalStateService) { return globalState; } + if (token === NotificationService) { + return notificationService; + } throw new Error(`unexpected AppInjector token: ${String(token)}`); }, } as unknown as Injector; beforeEach(() => { pushService = {unsubscribeQuietly: vi.fn().mockReturnValue(of(void 0))}; + notificationService = {reset: vi.fn()}; globalState = { clearUnitsAndProjects: vi.fn(), hideHeader: vi.fn(), @@ -130,6 +142,11 @@ describe('AuthenticationService sign out', () => { // The browser is signed out now, so the next person starts unsubscribed. expect(userService.currentUser).toBe(userService.anonymousUser); + + // Same shared machine problem, other half of it. The push registration is + // gone but NotificationService is a root singleton, so its cache and unread + // count would otherwise survive into the next person's session. + expect(notificationService.reset).toHaveBeenCalledTimes(1); }); // unsubscribeQuietly is the "never throw" variant, and sign out is also wired From d1c971eaaa6bd357e71acf29f12a3504f76258c9 Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Mon, 17 Aug 2026 15:47:48 +1000 Subject: [PATCH 1339/1531] feat(notifications): add notification bell to header A bell in the header carrying the unread count from NotificationService. The count comes from unreadCount$ rather than a request this component makes, so marking one read anywhere in the app moves the badge without the bell knowing who did it. The badge is hidden entirely at zero rather than showing a 0, and its aria-label carries the count, because Material renders the badge into a span marked aria-hidden and the count is the one thing the control exists to say. Material anchors a badge outside the host, at bottom:100% left:100%, and pulls it back with a negative margin. At the theme's -11px it sits beside the bell rather than on it, so both offset tokens are overridden. The white ring is a box-shadow and not a border: Material sets box-sizing: border-box with a fixed 22px box and a 22px line-height, so a border shrinks the content box and shoves the digit off centre. The count is re-read on every NavigationEnd and once on init, since unreadCount$ seeds at zero whether or not that is true. Refreshes are guarded on AuthenticationService.isAuthenticated(): sign out hides the header and routes in the same tick, so this component can still be alive for the navigation event, and anonymous the request comes back 403. HttpErrorInterceptor reads a 403 on an anonymous user as an expired session and redirects to /timeout, so without the guard signing out looks like being thrown out. Not rendered below xs. That toolbar is a flex row that does not wrap and neither dropdown in it shrinks, so one more icon pushes the account button off screen. An @if rather than display:none, so the component is never created and does not sit there asking for a count nobody can see. The account menu carries a Notifications item at that size instead, with the unread count on it, so a phone still has a way in. That is why HeaderComponent now takes NotificationService: the bell is the component that does not exist at that size, so it cannot be the one to read the count. The bell itself is its own component rather than more markup in HeaderComponent, whose spec replaces the template with an empty string. Tests: 7 new, 142 across the suite. --- src/app/common/header/header.component.html | 26 +++ src/app/common/header/header.component.scss | 15 ++ .../common/header/header.component.spec.ts | 3 + src/app/common/header/header.component.ts | 20 ++ .../notification-bell.component.html | 10 + .../notification-bell.component.scss | 30 +++ .../notification-bell.component.spec.ts | 199 ++++++++++++++++++ .../notification-bell.component.ts | 96 +++++++++ src/app/doubtfire-angular.module.ts | 2 + 9 files changed, 401 insertions(+) create mode 100644 src/app/common/header/notification-bell/notification-bell.component.html create mode 100644 src/app/common/header/notification-bell/notification-bell.component.scss create mode 100644 src/app/common/header/notification-bell/notification-bell.component.spec.ts create mode 100644 src/app/common/header/notification-bell/notification-bell.component.ts diff --git a/src/app/common/header/header.component.html b/src/app/common/header/header.component.html index 47bef3cb70..1c90ce4018 100644 --- a/src/app/common/header/header.component.html +++ b/src/app/common/header/header.component.html @@ -38,6 +38,16 @@ > + + @if (!media.isActive('xs')) { + + } @if (sidekiqJobs.length) { + + @if (media.isActive('xs')) { + + } diff --git a/src/app/common/header/notification-bell/notification-bell.component.scss b/src/app/common/header/notification-bell/notification-bell.component.scss new file mode 100644 index 0000000000..35c9da673f --- /dev/null +++ b/src/app/common/header/notification-bell/notification-bell.component.scss @@ -0,0 +1,30 @@ +// Put the count on the bell. +// +// Material anchors the badge at the host's outside top right corner, with +// `bottom: 100%` and `left: 100%`, and then pulls it back with a negative +// margin from one of these two tokens. Which token depends on whether the badge +// overlaps, so both are set: left at the theme's -11px the number sits beside +// the bell rather than on it. +:host { + --mat-badge-container-offset: -20px -20px; + --mat-badge-container-overlap-offset: -20px; + + // The toolbar is a plain flex row with no wrapping, so anything in it that + // can grow pushes the rest towards the edge. This one never does. + // + // The header drops this component entirely below xs, where there is no room + // for it at all. See the comment beside it in header.component.html. + flex: 0 0 auto; +} + +// A ring in the toolbar's own colour, so the badge cuts itself out from the +// glyph it sits on top of. +// +// A box-shadow and not a border. Material sets box-sizing: border-box on the +// badge and gives it a fixed 22px box with a 22px line-height, so a 2px border +// takes the content box down to 18px while the line box stays 22 and the digit +// is shoved off centre. A shadow draws the same ring and costs no layout. +:host ::ng-deep .mat-badge-content { + box-shadow: 0 0 0 2px #fff; + font-weight: 700; +} diff --git a/src/app/common/header/notification-bell/notification-bell.component.spec.ts b/src/app/common/header/notification-bell/notification-bell.component.spec.ts new file mode 100644 index 0000000000..2e2df5540f --- /dev/null +++ b/src/app/common/header/notification-bell/notification-bell.component.spec.ts @@ -0,0 +1,199 @@ +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatBadge, MatBadgeModule} from '@angular/material/badge'; +import {MatButtonModule} from '@angular/material/button'; +import {MatIconModule} from '@angular/material/icon'; +import {MatTooltipModule} from '@angular/material/tooltip'; +import {By} from '@angular/platform-browser'; +import {NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {NavigationEnd, Router} from '@angular/router'; +import {BehaviorSubject, Observable, Subject, config, defer, of, throwError} from 'rxjs'; +import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {NotificationService} from 'src/app/api/services/notification.service'; +import {NotificationBellComponent} from './notification-bell.component'; + +/** + * The bell has three jobs and each one is a way for it to be wrong: show the + * number the service holds, show nothing at all when that number is zero, and + * ask again as the user moves around the app. The two after those cover the + * ones that are easy to leave out, a count request going out after sign out and + * one still going out after the component is gone. + */ +describe('NotificationBellComponent', () => { + let component: NotificationBellComponent; + let fixture: ComponentFixture; + + let unreadCount: BehaviorSubject; + let routerEvents: Subject; + let subscribedTo: Set; + let notificationService: { + unreadCount$: BehaviorSubject; + refreshUnreadCount: ReturnType; + }; + let authenticationService: {isAuthenticated: ReturnType}; + let router: {events: unknown; navigateByUrl: ReturnType}; + + /** + * A stand-in that records whether anybody actually subscribed. + * + * A spy that only counts calls is happy either way, and refreshUnreadCount + * returns a cold observable, so dropping the .subscribe() in the component + * sends no request at all while the call count stays the same. + */ + const answers = (name: string, value: T): Observable => + defer(() => { + subscribedTo.add(name); + return of(value); + }); + + const bell = (): HTMLElement => fixture.nativeElement.querySelector('button'); + + // What is drawn, not what was bound. Material always renders the content + // span and hides the whole badge with a class on the host, so the number on + // screen and whether anyone can see it are two separate questions. + const badgeText = (): string => + fixture.nativeElement.querySelector('.mat-badge-content').textContent.trim(); + + const badgeIsHidden = (): boolean => + fixture.debugElement + .query(By.directive(MatBadge)) + .nativeElement.classList.contains('mat-badge-hidden'); + + beforeEach(async () => { + unreadCount = new BehaviorSubject(0); + routerEvents = new Subject(); + subscribedTo = new Set(); + + notificationService = { + unreadCount$: unreadCount, + refreshUnreadCount: vi.fn(() => answers('refreshUnreadCount', 0)), + }; + authenticationService = {isAuthenticated: vi.fn().mockReturnValue(true)}; + router = {events: routerEvents.asObservable(), navigateByUrl: vi.fn()}; + + await TestBed.configureTestingModule({ + declarations: [NotificationBellComponent], + imports: [ + MatBadgeModule, + MatButtonModule, + MatIconModule, + MatTooltipModule, + NoopAnimationsModule, + ], + providers: [ + {provide: NotificationService, useValue: notificationService}, + {provide: AuthenticationService, useValue: authenticationService}, + {provide: Router, useValue: router}, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(NotificationBellComponent); + component = fixture.componentInstance; + }); + + it('shows how many are unread', () => { + unreadCount.next(3); + fixture.detectChanges(); + + expect(badgeText()).toBe('3'); + expect(badgeIsHidden()).toBe(false); + + // The service is the only source of the number, so a change made anywhere + // in the app has to reach the bell without it asking. + unreadCount.next(4); + fixture.detectChanges(); + + expect(badgeText()).toBe('4'); + }); + + it('shows no badge at all when nothing is unread', () => { + fixture.detectChanges(); + + // Not a badge reading zero. A zero sitting on the bell is a permanent + // little alarm that never means anything. + expect(badgeIsHidden()).toBe(true); + + unreadCount.next(1); + fixture.detectChanges(); + + expect(badgeIsHidden()).toBe(false); + }); + + it('says how many are unread to a screen reader too', () => { + fixture.detectChanges(); + + expect(bell().getAttribute('aria-label')).toBe('Notifications'); + + unreadCount.next(4); + fixture.detectChanges(); + + // Material renders the badge into a span marked aria-hidden, so without + // this the count is the one thing the control exists to say and the only + // thing it does not say. + expect(bell().getAttribute('aria-label')).toBe('Notifications, 4 unread'); + }); + + it('asks for the count again after every navigation', () => { + fixture.detectChanges(); + + // Once on init, because unreadCount$ starts at zero whether or not that is + // true. + expect(notificationService.refreshUnreadCount).toHaveBeenCalledTimes(1); + expect(subscribedTo.has('refreshUnreadCount')).toBe(true); + + routerEvents.next(new NavigationEnd(1, '/home', '/home')); + expect(notificationService.refreshUnreadCount).toHaveBeenCalledTimes(2); + + routerEvents.next(new NavigationEnd(2, '/units/1/tasks/inbox', '/units/1/tasks/inbox')); + expect(notificationService.refreshUnreadCount).toHaveBeenCalledTimes(3); + }); + + it('does not ask for the count when nobody is signed in', () => { + authenticationService.isAuthenticated.mockReturnValue(false); + + fixture.detectChanges(); + routerEvents.next(new NavigationEnd(1, '/sign_in', '/sign_in')); + + // Sign out hides the header and routes, and the hiding takes a change + // detection pass while the routing event does not, so this component can + // still be alive for it. Anonymous, the request comes back 403, and + // HttpErrorInterceptor treats a 403 on an anonymous user as an expired + // session: an "Authentication timed out" alert and a redirect to /timeout. + expect(notificationService.refreshUnreadCount).not.toHaveBeenCalled(); + }); + + it('stops asking once it is destroyed', () => { + fixture.detectChanges(); + expect(notificationService.refreshUnreadCount).toHaveBeenCalledTimes(1); + + fixture.destroy(); + routerEvents.next(new NavigationEnd(1, '/home', '/home')); + + expect(notificationService.refreshUnreadCount).toHaveBeenCalledTimes(1); + }); + + it('handles a count request that fails instead of leaving it unhandled', async () => { + // rxjs does not throw an unhandled subscriber error where the subscribe + // call was, it hands it to config.onUnhandledError a macrotask later, and + // the default for that is to rethrow globally. Swapping it for a spy is the + // only way to see the difference from inside a test, and without it this + // passes whether or not the error is handled at all. + const unhandled = vi.fn(); + const previous = config.onUnhandledError; + config.onUnhandledError = unhandled; + + try { + notificationService.refreshUnreadCount.mockReturnValue( + throwError(() => new Error('unread_count failed')), + ); + + fixture.detectChanges(); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(unhandled).not.toHaveBeenCalled(); + expect(component.unreadCount).toBe(0); + } finally { + config.onUnhandledError = previous; + } + }); +}); diff --git a/src/app/common/header/notification-bell/notification-bell.component.ts b/src/app/common/header/notification-bell/notification-bell.component.ts new file mode 100644 index 0000000000..c22989602f --- /dev/null +++ b/src/app/common/header/notification-bell/notification-bell.component.ts @@ -0,0 +1,96 @@ +import {ChangeDetectionStrategy, Component, OnDestroy, OnInit} from '@angular/core'; +import {NavigationEnd, Router} from '@angular/router'; +import {Subscription, filter} from 'rxjs'; +import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {NotificationService} from 'src/app/api/services/notification.service'; + +/** + * The bell in the header, and the unread count on it. + * + * Its own component rather than more markup in HeaderComponent. The header is + * already eleven injected services long and its spec replaces the template with + * an empty string, so anything added there is untested by construction. This + * also keeps the change to the header itself to one element. + * + * The count comes from NotificationService.unreadCount$ and not from a request + * this component makes, so marking one read anywhere in the app moves the badge + * without the bell knowing who did it. + */ +@Component({ + selector: 'notification-bell', + templateUrl: './notification-bell.component.html', + styleUrls: ['./notification-bell.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, + standalone: false, +}) +export class NotificationBellComponent implements OnInit, OnDestroy { + unreadCount = 0; + + private subscriptions: Subscription[] = []; + + constructor( + private notificationService: NotificationService, + private authenticationService: AuthenticationService, + private router: Router, + ) {} + + ngOnInit(): void { + this.subscriptions.push( + this.notificationService.unreadCount$.subscribe((count) => { + this.unreadCount = count; + }), + ); + + // The count goes stale on its own. Notifications are created by the api, + // and push only reaches a browser that granted permission and kept the + // service worker alive, so most sessions never hear about a new one. A + // navigation is the cheapest honest excuse to ask again, and it is roughly + // when someone would look at the bell anyway. + this.subscriptions.push( + this.router.events + .pipe(filter((event) => event instanceof NavigationEnd)) + .subscribe(() => this.refresh()), + ); + + // unreadCount$ seeds at zero and stays there until something asks, so the + // first navigation is too late to be the only trigger. + this.refresh(); + } + + ngOnDestroy(): void { + this.subscriptions.forEach((subscription) => subscription.unsubscribe()); + } + + /** + * What a screen reader should call the bell. + * + * The badge is not part of it. Material renders the number into a span marked + * aria-hidden, so a bell with four unread notifications announces itself as + * "Notifications, button" and the count is the one thing the control exists + * to say. + */ + get bellLabel(): string { + return this.unreadCount ? `Notifications, ${this.unreadCount} unread` : 'Notifications'; + } + + /** + * Ask the api for the count, but only while somebody is signed in. + * + * The guard is not tidiness. Sign out hides the header and routes to + * /sign_in, and hiding is a change detection away while the navigation event + * fires straight away, so this component can still be alive for it. The + * request would then go out anonymous, come back 403, and + * HttpErrorInterceptor reads a 403 on an anonymous user as an expired session: + * it shows "Authentication timed out" and redirects to /timeout. Signing out + * would look like being kicked out. + * + * Errors are dropped. Nothing the user asked for depends on this. + */ + private refresh(): void { + if (!this.authenticationService.isAuthenticated()) { + return; + } + + this.notificationService.refreshUnreadCount().subscribe({error: () => undefined}); + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index dcc8a3f9ef..428db146d1 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -186,6 +186,7 @@ import {TasksOfTaskDefinitionPipe} from './common/filters/tasks-of-task-definiti import {FooterComponent} from './common/footer/footer.component'; import {GradeIconComponent} from './common/grade-icon/grade-icon.component'; import {HeaderComponent} from './common/header/header.component'; +import {NotificationBellComponent} from './common/header/notification-bell/notification-bell.component'; import {TaskDropdownComponent} from './common/header/task-dropdown/task-dropdown.component'; import {UnitDropdownComponent} from './common/header/unit-dropdown/unit-dropdown.component'; import {HeroSidebarComponent} from './common/hero-sidebar/hero-sidebar.component'; @@ -540,6 +541,7 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { HeaderComponent, UnitDropdownComponent, TaskDropdownComponent, + NotificationBellComponent, SplashScreenComponent, SubmissionFilesDownloadComponent, ProjectDashboardComponent, From 29c331a8398d5fe50d0afe2f769c9b58585a6f59 Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Mon, 17 Aug 2026 15:47:56 +1000 Subject: [PATCH 1340/1531] feat(notifications): add notification dropdown Clicking the bell opens the five most recent notifications. Each row shows the message and how long ago it arrived, and clicking one marks it read and follows its link. A row with no link is still marked read, otherwise the badge carries a number the user has no way to clear. The dropdown lives in the bell component rather than one of its own, the same shape as unit-dropdown and task-dropdown next door. MatMenu collects its items with a content query and a content query does not reach into another component's template, so rows in a child component would click and close the menu but the key manager would never see them and the arrow keys would walk over an empty menu. Rows are real buttons for a related reason: the key manager moves focus and never synthesises a click, so on a div Enter does nothing. The list is read on (menuOpened), not in ngOnInit. Content inside a mat-menu is built with the surrounding component whether the menu is opened or not, so an ngOnInit fetch would read the list once at sign in and show it all session. Each row carries a category icon and colour. notificationType is all NotificationEntity exposes, so this is five categories rather than one icon per event, and a new task, a due date change and a due soon reminder share the task icon. Rows lay themselves out with .notification-line rather than letting mat-menu-item do it, because its .mat-mdc-menu-item-text wrapper clips and refuses to wrap, which pushed the glyph off centre. Three states rather than two. An empty list says so, and a failed read says it failed, because an empty box after a failed request tells the user they have no notifications and that is a different and wrong thing to say. Rows stay on screen during a refresh, with a line above them if that refresh failed. Opening a row cancels any list read still in flight. Those responses are written into the shared entity cache, so one landing after the mark read would put readAt back to null and draw the row unread again. Tests: 17 new, 159 across the suite. --- .../notification-bell.component.html | 98 ++++- .../notification-bell.component.scss | 169 ++++++++- .../notification-bell.component.spec.ts | 351 +++++++++++++++++- .../notification-bell.component.ts | 186 +++++++++- 4 files changed, 795 insertions(+), 9 deletions(-) diff --git a/src/app/common/header/notification-bell/notification-bell.component.html b/src/app/common/header/notification-bell/notification-bell.component.html index 0cb80a9b31..2a571898e5 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.html +++ b/src/app/common/header/notification-bell/notification-bell.component.html @@ -5,6 +5,102 @@ [attr.aria-label]="bellLabel" [matBadge]="unreadCount" [matBadgeHidden]="unreadCount === 0" + [matMenuTriggerFor]="notificationMenu" + (menuOpened)="onMenuOpened()" > - notifications + notifications + + +

    Notifications

    + + + @if (notifications.length) { + @if (loadFailed) { +

    + These may be out of date, the last refresh did not work. +

    + } + + @for (notification of notifications; track notification.id) { +
    + + +
    + } + } @else if (loading) { +
    + + Loading your notifications +
    + } @else if (loadFailed) { + +
    +

    We could not load your notifications.

    +

    Close this and open it again to try once more.

    +
    + } @else { +
    +

    You are all caught up.

    +

    Anything new will show up here.

    +
    + } +
    diff --git a/src/app/common/header/notification-bell/notification-bell.component.scss b/src/app/common/header/notification-bell/notification-bell.component.scss index 35c9da673f..32e04eb20d 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.scss +++ b/src/app/common/header/notification-bell/notification-bell.component.scss @@ -1,10 +1,36 @@ +// The menu panel is rendered into the cdk overlay container, outside this +// component's element, so component scoped styles never reach it. ::ng-deep on +// the panel class is how unit-dropdown next door sizes its own menu. Everything +// below that line is inside the component's own template, overlay or not, so it +// keeps its encapsulation attribute and needs no ::ng-deep. +// +// The width is a preference and not a floor. Material's own panel sets +// max-width: 280px, which is what this is here to override, but a fixed +// min-width would make the panel wider than a 320px phone and push the page +// sideways. +::ng-deep .notification-dropdown-menu.mat-mdc-menu-panel { + border-radius: 16px; + max-width: min(380px, calc(100vw - 32px)); + min-width: 0; + // Material's own container shape is 4px. Without clipping, the first and last + // rows square the corners back off again on hover. + overflow: hidden; + width: 380px; +} + // Put the count on the bell. // // Material anchors the badge at the host's outside top right corner, with // `bottom: 100%` and `left: 100%`, and then pulls it back with a negative // margin from one of these two tokens. Which token depends on whether the badge -// overlaps, so both are set: left at the theme's -11px the number sits beside -// the bell rather than on it. +// overlaps, so both are set: leaving either at the theme's -11px leaves the +// number sitting beside the bell rather than on it, which is what the default +// looks like on a 40px icon button. +// +// matBadgeSize="small" is also gone from the template. It is a 16px container, +// fine for a one digit job count and cramped for a two digit unread count; the +// default 22px is the readable one, and a bigger badge needs pulling in further +// to sit on the glyph. :host { --mat-badge-container-offset: -20px -20px; --mat-badge-container-overlap-offset: -20px; @@ -28,3 +54,142 @@ box-shadow: 0 0 0 2px #fff; font-weight: 700; } + +// mat-menu-item is built for one line of text. It pins itself to 48px, and it +// wraps whatever you put in it in a .mat-mdc-menu-item-text span that clips and +// refuses to wrap. That span is Material's own, so it carries no encapsulation +// attribute and ::ng-deep is the only way to reach it. Without this the row lays +// itself out inside a box that is not the width it looks, which is what pushes +// the glyph off centre. +.notification-row.mat-mdc-menu-item { + height: auto; + line-height: 1.35; + min-height: 0; + padding: 12px 10px 12px 16px; + white-space: normal; + + ::ng-deep .mat-mdc-menu-item-text { + display: block; + overflow: visible; + white-space: normal; + width: 100%; + } +} + +// --------------------------------------------------------------------------- +// Shared row shape. The full notifications page carries a copy of this block, +// deliberately: the two components are on sibling branches so neither can +// import from the other yet, and a row has to look the same in both places. +// Both copies belong in one stylesheet once they have merged. +// --------------------------------------------------------------------------- +.notification-line { + align-items: center; + display: flex; + gap: 12px; + width: 100%; +} + +.notification-body { + display: flex; + flex: 1 1 auto; + flex-direction: column; + gap: 2px; + min-width: 0; + text-align: left; +} + +.notification-glyph { + align-items: center; + border-radius: 50%; + display: inline-flex; + flex: 0 0 36px; + height: 36px; + justify-content: center; + width: 36px; + + // mat-icon ships as a 24px inline-block with a 24px line box, and picks up + // margins from Material's list and menu classes. Left alone the glyph is + // nearly as wide as the circle and sits low and left in it, because an inline + // box aligns on its baseline and the margins push it. Making it a block with + // a line-height equal to its own height and no margin takes both out, and the + // flex centring above then does what it looks like it does. + .mat-icon { + // Explicitly, not by inheritance. Material colours icons inside a menu item + // with .mat-mdc-menu-item .mat-icon { color: ... }, so a tone set on the + // circle around it is simply overridden and the glyph comes out black in + // the dropdown while the same glyph is coloured on the page. + color: inherit; + display: block; + font-size: 20px; + height: 20px; + line-height: 20px; + margin: 0; + overflow: visible; + width: 20px; + } + + // One pair per category in Notification::TYPES. The tints are the same hue as + // the glyph at low alpha, so the circle reads as a wash rather than a second + // colour to remember. + &.tone-feedback { + background: rgba(57, 57, 255, 0.12); + color: #2a2ad6; + } + + &.tone-task { + background: rgba(199, 119, 0, 0.12); + color: #b26a00; + } + + &.tone-portfolio { + background: rgba(123, 63, 242, 0.12); + color: #7b3ff2; + } + + &.tone-extension { + background: rgba(31, 138, 76, 0.12); + color: #1f8a4c; + } + + &.tone-general { + background: rgba(95, 99, 104, 0.12); + color: #5f6368; + } +} + +.notification-message { + color: rgba(0, 0, 0, 0.87); + font-size: 14px; + line-height: 1.35; + white-space: normal; + + // Unread is carried by weight and by the dot, not by colour on its own, and + // the row's aria-label says it in words for anyone who can see neither. + &.unread { + font-weight: 600; + } +} + +.notification-unread-dot { + background: #3939ff; + border-radius: 50%; + flex: 0 0 7px; + height: 7px; + width: 7px; + + &.is-read { + visibility: hidden; + } +} + +.notification-time, +.notification-stale { + color: rgba(0, 0, 0, 0.6); + font-size: 12px; + line-height: 1.3; +} + +.notification-empty { + color: rgba(0, 0, 0, 0.6); + font-size: 14px; +} diff --git a/src/app/common/header/notification-bell/notification-bell.component.spec.ts b/src/app/common/header/notification-bell/notification-bell.component.spec.ts index 2e2df5540f..d80ad34fad 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.spec.ts +++ b/src/app/common/header/notification-bell/notification-bell.component.spec.ts @@ -1,15 +1,21 @@ -import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'; +import {OverlayContainer} from '@angular/cdk/overlay'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {MatBadge, MatBadgeModule} from '@angular/material/badge'; import {MatButtonModule} from '@angular/material/button'; import {MatIconModule} from '@angular/material/icon'; +import {MatListModule} from '@angular/material/list'; +import {MatMenuModule} from '@angular/material/menu'; +import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; import {MatTooltipModule} from '@angular/material/tooltip'; import {By} from '@angular/platform-browser'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {NavigationEnd, Router} from '@angular/router'; import {BehaviorSubject, Observable, Subject, config, defer, of, throwError} from 'rxjs'; +import {Notification} from 'src/app/api/models/notification'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {NotificationService} from 'src/app/api/services/notification.service'; +import {AlertService} from 'src/app/common/services/alert.service'; import {NotificationBellComponent} from './notification-bell.component'; /** @@ -18,27 +24,38 @@ import {NotificationBellComponent} from './notification-bell.component'; * ask again as the user moves around the app. The two after those cover the * ones that are easy to leave out, a count request going out after sign out and * one still going out after the component is gone. + * + * The dropdown tests open the real menu and read the real overlay rather than + * poking at the component's fields, because "handle the empty state" is a + * question about what is on the screen. The one that matters most is the pair + * about failure: a list that came back empty and a list that failed to come + * back look identical from the outside and mean opposite things. */ describe('NotificationBellComponent', () => { let component: NotificationBellComponent; let fixture: ComponentFixture; + let overlayContainer: OverlayContainer; let unreadCount: BehaviorSubject; let routerEvents: Subject; + let list: Subject; let subscribedTo: Set; let notificationService: { unreadCount$: BehaviorSubject; refreshUnreadCount: ReturnType; + list: ReturnType; + markRead: ReturnType; }; let authenticationService: {isAuthenticated: ReturnType}; + let alerts: {success: ReturnType; error: ReturnType}; let router: {events: unknown; navigateByUrl: ReturnType}; /** * A stand-in that records whether anybody actually subscribed. * - * A spy that only counts calls is happy either way, and refreshUnreadCount - * returns a cold observable, so dropping the .subscribe() in the component - * sends no request at all while the call count stays the same. + * A spy that only counts calls is happy either way, and every one of these + * methods returns a cold observable, so dropping the .subscribe() in the + * component sends no request at all while every call count stays the same. */ const answers = (name: string, value: T): Observable => defer(() => { @@ -46,6 +63,17 @@ describe('NotificationBellComponent', () => { return of(value); }); + const notification = (id: number, over: Partial = {}): Notification => { + const built = new Notification(); + built.id = id; + built.message = `notification ${id}`; + built.link = `/projects/${id}/dashboard`; + built.notificationType = 'feedback'; + built.readAt = null; + built.createdAt = new Date(2026, 7, 17, 9, 0, 0); + return Object.assign(built, over); + }; + const bell = (): HTMLElement => fixture.nativeElement.querySelector('button'); // What is drawn, not what was bound. Material always renders the content @@ -59,16 +87,61 @@ describe('NotificationBellComponent', () => { .query(By.directive(MatBadge)) .nativeElement.classList.contains('mat-badge-hidden'); + const openMenu = (): void => { + bell().click(); + fixture.detectChanges(); + }; + + // Reads the list a second time without going through the trigger, which is + // what reopening the menu does. + const reopenWith = (): Subject => { + const refresh: Subject = new Subject(); + notificationService.list.mockReturnValue(refresh); + component.onMenuOpened(); + fixture.detectChanges(); + return refresh; + }; + + // The menu panel is not inside the component, it is in the cdk overlay + // container, so nothing in the dropdown can be found through the fixture. + const panel = (): HTMLElement => overlayContainer.getContainerElement(); + + const rows = (): HTMLElement[] => Array.from(panel().querySelectorAll('.notification-row')); + + const rowText = (): string[] => + rows().map((row) => row.querySelector('.notification-message').textContent.trim()); + + const glyphIcons = (): string[] => + Array.from(panel().querySelectorAll('.notification-glyph mat-icon')).map((icon) => + icon.textContent.trim(), + ); + + // The tone class, not the computed colour. jsdom applies no stylesheet, and + // the class is the contract between the template and the scss anyway. + const glyphTones = (): string[] => + Array.from(panel().querySelectorAll('.notification-glyph')).map((glyph) => + Array.from(glyph.classList).find((name) => name.startsWith('tone-')), + ); + + const placeholderText = (): string => + Array.from(panel().querySelectorAll('.notification-empty')) + .map((element) => element.textContent.trim()) + .join(' '); + beforeEach(async () => { unreadCount = new BehaviorSubject(0); routerEvents = new Subject(); + list = new Subject(); subscribedTo = new Set(); notificationService = { unreadCount$: unreadCount, refreshUnreadCount: vi.fn(() => answers('refreshUnreadCount', 0)), + list: vi.fn().mockReturnValue(list), + markRead: vi.fn(() => answers('markRead', undefined)), }; authenticationService = {isAuthenticated: vi.fn().mockReturnValue(true)}; + alerts = {success: vi.fn(), error: vi.fn()}; router = {events: routerEvents.asObservable(), navigateByUrl: vi.fn()}; await TestBed.configureTestingModule({ @@ -77,20 +150,29 @@ describe('NotificationBellComponent', () => { MatBadgeModule, MatButtonModule, MatIconModule, + MatListModule, + MatMenuModule, + MatProgressSpinnerModule, MatTooltipModule, NoopAnimationsModule, ], providers: [ {provide: NotificationService, useValue: notificationService}, {provide: AuthenticationService, useValue: authenticationService}, + {provide: AlertService, useValue: alerts}, {provide: Router, useValue: router}, ], }).compileComponents(); + overlayContainer = TestBed.inject(OverlayContainer); fixture = TestBed.createComponent(NotificationBellComponent); component = fixture.componentInstance; }); + afterEach(() => { + fixture.destroy(); + }); + it('shows how many are unread', () => { unreadCount.next(3); fixture.detectChanges(); @@ -196,4 +278,265 @@ describe('NotificationBellComponent', () => { config.onUnhandledError = previous; } }); + + describe('the dropdown', () => { + beforeEach(() => { + fixture.detectChanges(); + }); + + it('reads the list every time it is opened', () => { + expect(notificationService.list).not.toHaveBeenCalled(); + + openMenu(); + expect(notificationService.list).toHaveBeenCalledTimes(1); + + list.next([notification(1)]); + fixture.detectChanges(); + + // Closing and opening again has to go back to the api. A list fetched + // once at sign in would be wrong for the rest of the session. + component.onMenuOpened(); + expect(notificationService.list).toHaveBeenCalledTimes(2); + }); + + it('shows the newest few, newest first', () => { + openMenu(); + + const at = (hour: number) => new Date(2026, 7, 17, hour, 0, 0); + list.next([ + notification(1, {createdAt: at(9)}), + notification(2, {createdAt: at(14)}), + notification(3, {createdAt: at(11)}), + notification(4, {createdAt: at(15)}), + notification(5, {createdAt: at(10)}), + notification(6, {createdAt: at(13)}), + notification(7, {createdAt: at(12)}), + ]); + fixture.detectChanges(); + + expect(rowText()).toEqual([ + 'notification 4', + 'notification 2', + 'notification 6', + 'notification 7', + 'notification 3', + ]); + }); + + it('makes each row a real button so a keyboard can open it', () => { + openMenu(); + list.next([notification(1)]); + fixture.detectChanges(); + + // Structural, and it has to be. MatMenu's key manager only moves focus, + // it never synthesises a click, so Enter on a row works only because the + // element is natively a button. The test environment does not simulate + // that browser behaviour either, so the element type is the assertion. + expect(rows()[0].tagName).toBe('BUTTON'); + }); + + it('gives each category its own icon and colour', () => { + openMenu(); + list.next([ + notification(1, {notificationType: 'feedback'}), + notification(2, {notificationType: 'task'}), + notification(3, {notificationType: 'portfolio'}), + notification(4, {notificationType: 'extension'}), + notification(5, {notificationType: 'general'}), + ]); + fixture.detectChanges(); + + expect(glyphIcons()).toEqual([ + 'chat_bubble', + 'assignment', + 'collections_bookmark', + 'more_time', + 'campaign', + ]); + + // The tone is what the stylesheet colours on, so a row with the right + // icon and the wrong tone still looks wrong. + expect(glyphTones()).toEqual([ + 'tone-feedback', + 'tone-task', + 'tone-portfolio', + 'tone-extension', + 'tone-general', + ]); + }); + + it('still draws something for a category it has never heard of', () => { + openMenu(); + // Notification::TYPES is validated on the api, so this is a sixth + // category added there reaching a browser running older web code. A row + // with no icon at all is worse than a generic one. + list.next([notification(1, {notificationType: 'announcement'})]); + fixture.detectChanges(); + + expect(glyphIcons()).toEqual(['notifications']); + expect(glyphTones()).toEqual(['tone-general']); + }); + + it('marks the unread rows with a dot and leaves the read ones a gap', () => { + openMenu(); + list.next([notification(1), notification(2, {readAt: new Date(2026, 7, 17, 9, 30, 0)})]); + fixture.detectChanges(); + + const dots = Array.from(panel().querySelectorAll('.notification-unread-dot')); + + // Both rows keep the element. Removing it on read would shuffle the + // delete button sideways from row to row. + expect(dots).toHaveLength(2); + expect(dots[0].classList.contains('is-read')).toBe(false); + expect(dots[1].classList.contains('is-read')).toBe(true); + }); + + it('says unread in words, not only in bold and colour', () => { + openMenu(); + list.next([ + notification(1, {message: 'Andrew Cain commented on 1.1P.'}), + notification(2, { + message: 'Your extension was granted.', + readAt: new Date(2026, 7, 17, 9, 30, 0), + }), + ]); + fixture.detectChanges(); + + // Weight and a dot are both things you have to be able to see. + expect(rows()[0].getAttribute('aria-label')).toContain('Unread.'); + expect(rows()[0].getAttribute('aria-label')).toContain('Andrew Cain commented on 1.1P.'); + expect(rows()[1].getAttribute('aria-label')).toContain('Read.'); + }); + + it('says how long ago each one arrived', () => { + openMenu(); + + const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000); + list.next([notification(1, {createdAt: twoHoursAgo})]); + fixture.detectChanges(); + + expect(rows()[0].querySelector('.notification-time').textContent.trim()).toBe('2 hours ago'); + }); + + it('says something friendly when there is nothing to show', () => { + openMenu(); + + list.next([]); + fixture.detectChanges(); + + expect(rows()).toHaveLength(0); + expect(placeholderText()).toContain('You are all caught up'); + }); + + it('says it could not load rather than claiming there is nothing', () => { + openMenu(); + + list.error(new Error('GET /notifications failed')); + fixture.detectChanges(); + + // The whole point of this one. An empty box after a failed request tells + // the user they have no notifications, which is a different and wrong + // thing to say. + expect(placeholderText()).toContain('could not load'); + expect(placeholderText()).not.toContain('caught up'); + }); + + it('shows the list it already has while it reads a fresh one', () => { + openMenu(); + list.next([notification(1)]); + fixture.detectChanges(); + + // Reopening starts a second read. Blanking the panel for it would make + // every open flash, when what is on screen is still nearly right. + reopenWith(); + + expect(rowText()).toEqual(['notification 1']); + }); + + it('warns that the rows are stale when a refresh fails behind them', () => { + openMenu(); + list.next([notification(1)]); + fixture.detectChanges(); + + reopenWith().error(new Error('GET /notifications failed')); + fixture.detectChanges(); + + // Keeping the rows is right, keeping them silently is not. A list nobody + // could refresh looks exactly like a list nothing has happened to. + expect(rowText()).toEqual(['notification 1']); + expect(panel().textContent).toContain('may be out of date'); + }); + + it('marks a row read and follows its link when it is clicked', () => { + openMenu(); + list.next([notification(1, {link: '/projects/9/dashboard'})]); + fixture.detectChanges(); + + rows()[0].click(); + + expect(notificationService.markRead).toHaveBeenCalledTimes(1); + expect(notificationService.markRead.mock.calls[0][0].id).toBe(1); + expect(subscribedTo.has('markRead')).toBe(true); + expect(router.navigateByUrl).toHaveBeenCalledWith('/projects/9/dashboard'); + }); + + it('does not mark a row read twice', () => { + openMenu(); + list.next([notification(1, {readAt: new Date(2026, 7, 17, 9, 30, 0)})]); + fixture.detectChanges(); + + rows()[0].click(); + + // read_all and mark_read are both no-ops on the api for one already read, + // so a second call would do nothing except tell the service to take one + // off a count that never included it. + expect(notificationService.markRead).not.toHaveBeenCalled(); + expect(router.navigateByUrl).toHaveBeenCalledTimes(1); + }); + + it('marks a row read even when it has nowhere to go', () => { + openMenu(); + list.next([notification(1, {link: null})]); + fixture.detectChanges(); + + rows()[0].click(); + + // link is nullable on the api. Refusing to mark it read would leave a + // number on the bell that the user has no way to clear. + expect(notificationService.markRead).toHaveBeenCalledTimes(1); + expect(router.navigateByUrl).not.toHaveBeenCalled(); + }); + + it('says so when a notification could not be marked as read', () => { + notificationService.markRead.mockReturnValue(throwError(() => new Error('PUT read failed'))); + + openMenu(); + list.next([notification(1, {link: null})]); + fixture.detectChanges(); + + rows()[0].click(); + + // Nothing else on screen changes when this fails. Swallowing it leaves + // the row unread and the badge where it was with no explanation. + expect(alerts.error).toHaveBeenCalledTimes(1); + }); + + it('drops a list read still in flight when a row is opened', () => { + openMenu(); + list.next([notification(1)]); + fixture.detectChanges(); + + // The rows on screen during a refresh are the previous list's, so this is + // the ordinary way to reach this: reopen, click before the read lands. + const refresh = reopenWith(); + expect(refresh.observed).toBe(true); + + rows()[0].click(); + + // That response was worked out before the click and NotificationService + // writes list responses into the shared entity cache, so letting it land + // would put readAt back to null and draw the row unread again. + expect(refresh.observed).toBe(false); + }); + }); }); diff --git a/src/app/common/header/notification-bell/notification-bell.component.ts b/src/app/common/header/notification-bell/notification-bell.component.ts index c22989602f..a94693dacd 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.ts +++ b/src/app/common/header/notification-bell/notification-bell.component.ts @@ -1,16 +1,28 @@ +import moment from 'moment'; import {ChangeDetectionStrategy, Component, OnDestroy, OnInit} from '@angular/core'; import {NavigationEnd, Router} from '@angular/router'; import {Subscription, filter} from 'rxjs'; +import {Notification} from 'src/app/api/models/notification'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {NotificationService} from 'src/app/api/services/notification.service'; +import {AlertService} from 'src/app/common/services/alert.service'; /** - * The bell in the header, and the unread count on it. + * The bell in the header, the unread count on it, and the list behind it. * * Its own component rather than more markup in HeaderComponent. The header is * already eleven injected services long and its spec replaces the template with * an empty string, so anything added there is untested by construction. This - * also keeps the change to the header itself to one element. + * also keeps the change to the header itself to one line. + * + * The dropdown lives here rather than in a component of its own, which is the + * same shape as unit-dropdown and task-dropdown next door. Both of those own + * their trigger and their mat-menu in one template, and the reason is not + * tidiness: MatMenu collects its items with a content query, and a content + * query does not reach into another component's template. Rows in a child + * component would still click and still close the menu, but the menu's key + * manager would never see them, so the arrow keys would walk over an empty + * menu. * * The count comes from NotificationService.unreadCount$ and not from a request * this component makes, so marking one read anywhere in the app moves the badge @@ -24,13 +36,59 @@ import {NotificationService} from 'src/app/api/services/notification.service'; standalone: false, }) export class NotificationBellComponent implements OnInit, OnDestroy { + /** + * How many rows the dropdown shows. + * + * The api has no paging, GET /notifications answers with the lot, so this is + * a display limit and not a request size. Somebody with four hundred of them + * still downloads four hundred, and the full page is where they go to read + * them. + */ + public static readonly RECENT_COUNT = 5; + + /** + * The icon and colour for a notification's category. + * + * Keyed on notificationType and nothing finer, because that is all the api + * sends. NotificationEntity exposes id, notification_type, message, link, + * read_at and created_at, and the event naming the specific thing that + * happened is deliberately not among them. So a new task, a due date change + * and a due soon reminder all share the one task icon. Icons per event would + * need `expose :event` on the api first, and then this stops being a closed + * list of five and becomes something every event ticket has to edit, which is + * the coupling the mailer templates were shaped to avoid. + */ + private static readonly CATEGORIES: Record = { + feedback: {icon: 'chat_bubble', tone: 'feedback'}, + task: {icon: 'assignment', tone: 'task'}, + portfolio: {icon: 'collections_bookmark', tone: 'portfolio'}, + extension: {icon: 'more_time', tone: 'extension'}, + general: {icon: 'campaign', tone: 'general'}, + }; + + /** + * For a category this build has not heard of. + * + * Notification::TYPES is validated on the api, so the five above are the five + * that exist today. A sixth added there would reach a browser running older + * web code, and a row with no icon at all is worse than a generic one. + */ + private static readonly UNKNOWN_CATEGORY = {icon: 'notifications', tone: 'general'}; + unreadCount = 0; + notifications: Notification[] = []; + + loading = false; + loadFailed = false; + private subscriptions: Subscription[] = []; + private listSubscription: Subscription | null = null; constructor( private notificationService: NotificationService, private authenticationService: AuthenticationService, + private alerts: AlertService, private router: Router, ) {} @@ -58,6 +116,7 @@ export class NotificationBellComponent implements OnInit, OnDestroy { } ngOnDestroy(): void { + this.listSubscription?.unsubscribe(); this.subscriptions.forEach((subscription) => subscription.unsubscribe()); } @@ -73,6 +132,129 @@ export class NotificationBellComponent implements OnInit, OnDestroy { return this.unreadCount ? `Notifications, ${this.unreadCount} unread` : 'Notifications'; } + /** + * Read the list again every time the menu is opened. + * + * On the open event and not in ngOnInit. Content written inside a mat-menu is + * built with the surrounding component whether the menu is ever opened or + * not, so an ngOnInit here would fetch once at sign in and then show that + * same list for the rest of the session. + */ + onMenuOpened(): void { + this.loading = true; + this.loadFailed = false; + + // Opening twice quickly is easy to do. Without this the first response can + // land after the second and put the older list back. + this.listSubscription?.unsubscribe(); + + this.listSubscription = this.notificationService.list().subscribe({ + next: (notifications) => { + this.notifications = this.mostRecent(notifications); + this.loading = false; + }, + error: () => { + this.loading = false; + this.loadFailed = true; + }, + }); + } + + /** + * Open one notification: mark it read, then go where it points. + * + * Marking read is not conditional on the link. A notification with nowhere to + * go has still been seen once it is clicked, and leaving it unread would keep + * a number on the bell that the user cannot clear. + */ + open(notification: Notification): void { + if (!notification.isRead) { + // The rows on screen during a refresh are the previous list's, so this is + // a real sequence and not a theoretical one. That response was worked out + // before this click and it is written straight into the shared entity + // cache, so letting it land would put readAt back to null and draw the + // row unread again. + this.cancelPendingList(); + + // Not waited on. The row is already gone from view by the time this + // answers, the badge follows from unreadCount$, and holding the + // navigation for it would make every click feel slow. + this.notificationService.markRead(notification).subscribe({ + error: () => this.alerts.error('That notification could not be marked as read'), + }); + } + + if (notification.link) { + this.router.navigateByUrl(notification.link); + } + } + + iconFor(notification: Notification): string { + return this.categoryFor(notification).icon; + } + + toneFor(notification: Notification): string { + return this.categoryFor(notification).tone; + } + + /** + * What a screen reader should read for a row. + * + * Unread is drawn as bold text and a coloured dot, and both of those are + * things you have to be able to see. The message and the time are already in + * the button, so this only exists to put the state into words. + */ + rowLabel(notification: Notification): string { + const state = notification.isRead ? 'Read' : 'Unread'; + + return `${state}. ${notification.message}. ${this.timeAgo(notification)}`; + } + + /** + * How long ago this arrived, in words. + * + * Worked out on each change detection pass rather than stored, so a menu left + * open does not sit there insisting something happened "a few seconds ago" + * ten minutes later. + */ + timeAgo(notification: Notification): string { + return moment(notification.createdAt).fromNow(); + } + + /** + * Retire a list request that is still in the air. + * + * Anything this component changes locally is newer than a read that went out + * before it. NotificationService writes list responses into the shared cache, + * so one arriving late does not merely show stale rows, it undoes the change. + */ + protected cancelPendingList(): void { + this.listSubscription?.unsubscribe(); + this.listSubscription = null; + this.loading = false; + } + + /** + * The newest few. + * + * The api already answers newest first, and this sorts anyway. Recency is the + * entire meaning of this list, and the copies handed back here come out of a + * cache that other calls also write to, so the order of the array is not + * something worth trusting. + */ + private mostRecent(notifications: Notification[]): Notification[] { + return [...notifications] + .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()) + .slice(0, NotificationBellComponent.RECENT_COUNT); + } + + private categoryFor(notification: Notification): {icon: string; tone: string} { + return ( + NotificationBellComponent.CATEGORIES[notification.notificationType] ?? + NotificationBellComponent.UNKNOWN_CATEGORY + ); + } + /** * Ask the api for the count, but only while somebody is signed in. * From 59bb64a846e39ce15dfcd22ff60db137396dc899 Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Mon, 17 Aug 2026 15:48:53 +1000 Subject: [PATCH 1341/1531] feat(notifications): add mark all read and delete Wires up the last two endpoints. Mark all read asks nothing first, because nothing is lost by it and every notification is still readable afterwards. Delete goes through the existing ConfirmationModalService, because it is the only one of the five endpoints that destroys anything and there is no undo anywhere in this feature. An explicit empty cancel function is passed to that service. Given none it pops a green success snackbar reading "Delete notification action cancelled", and telling somebody they successfully did not delete something is noise. Both actions stop the click reaching the menu panel, which MatMenu closes from, and the delete button has to anyway or the row underneath would treat it as opening the notification. Both also cancel any list read still in flight, since those responses are written into the shared cache and one landing late would undo the change. Neither touches the unread count. NotificationService sets it to zero inside markAllRead and decrements inside remove, and the badge reads unreadCount$, so a second copy of that arithmetic here could only disagree with it. The component now holds the whole list and slices five for display, so deleting one of the five promotes the sixth rather than leaving four and a gap. Also adds a "See all notifications" item, without which the sixth notification is unreachable except by typing a url. Tests: 11 new, 170 across the suite. --- .../notification-bell.component.html | 30 ++- .../notification-bell.component.scss | 17 ++ .../notification-bell.component.spec.ts | 185 ++++++++++++++++++ .../notification-bell.component.ts | 129 +++++++++++- 4 files changed, 349 insertions(+), 12 deletions(-) diff --git a/src/app/common/header/notification-bell/notification-bell.component.html b/src/app/common/header/notification-bell/notification-bell.component.html index 2a571898e5..093d94a8b3 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.html +++ b/src/app/common/header/notification-bell/notification-bell.component.html @@ -12,7 +12,14 @@ -

    Notifications

    +
    +

    Notifications

    + @if (unreadCount) { + + } +
    - @if (notifications.length) { + @if (recent.length) { @if (loadFailed) {

    These may be out of date, the last refresh did not work.

    } - @for (notification of notifications; track notification.id) { + @for (notification of recent; track notification.id) {
    + } @else if (loading) {
    diff --git a/src/app/common/header/notification-bell/notification-bell.component.scss b/src/app/common/header/notification-bell/notification-bell.component.scss index 32e04eb20d..0bd320b0f6 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.scss +++ b/src/app/common/header/notification-bell/notification-bell.component.scss @@ -193,3 +193,20 @@ color: rgba(0, 0, 0, 0.6); font-size: 14px; } + +.notification-mark-all, +.notification-see-all { + font-size: 12px; +} + +// The delete button sits in a menu row, so at its natural size it competes with +// the message for attention on a list nobody opened to delete things from. +.notification-delete { + flex: none; + + .mat-icon { + font-size: 18px; + height: 18px; + width: 18px; + } +} diff --git a/src/app/common/header/notification-bell/notification-bell.component.spec.ts b/src/app/common/header/notification-bell/notification-bell.component.spec.ts index d80ad34fad..fd1449ae8a 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.spec.ts +++ b/src/app/common/header/notification-bell/notification-bell.component.spec.ts @@ -16,6 +16,7 @@ import {Notification} from 'src/app/api/models/notification'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {NotificationService} from 'src/app/api/services/notification.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {ConfirmationModalService} from '../../modals/confirmation-modal/confirmation-modal.service'; import {NotificationBellComponent} from './notification-bell.component'; /** @@ -45,8 +46,11 @@ describe('NotificationBellComponent', () => { refreshUnreadCount: ReturnType; list: ReturnType; markRead: ReturnType; + markAllRead: ReturnType; + remove: ReturnType; }; let authenticationService: {isAuthenticated: ReturnType}; + let confirmationModal: {show: ReturnType}; let alerts: {success: ReturnType; error: ReturnType}; let router: {events: unknown; navigateByUrl: ReturnType}; @@ -139,8 +143,11 @@ describe('NotificationBellComponent', () => { refreshUnreadCount: vi.fn(() => answers('refreshUnreadCount', 0)), list: vi.fn().mockReturnValue(list), markRead: vi.fn(() => answers('markRead', undefined)), + markAllRead: vi.fn(() => answers('markAllRead', undefined)), + remove: vi.fn(() => answers('remove', undefined)), }; authenticationService = {isAuthenticated: vi.fn().mockReturnValue(true)}; + confirmationModal = {show: vi.fn()}; alerts = {success: vi.fn(), error: vi.fn()}; router = {events: routerEvents.asObservable(), navigateByUrl: vi.fn()}; @@ -159,6 +166,7 @@ describe('NotificationBellComponent', () => { providers: [ {provide: NotificationService, useValue: notificationService}, {provide: AuthenticationService, useValue: authenticationService}, + {provide: ConfirmationModalService, useValue: confirmationModal}, {provide: AlertService, useValue: alerts}, {provide: Router, useValue: router}, ], @@ -539,4 +547,181 @@ describe('NotificationBellComponent', () => { expect(refresh.observed).toBe(false); }); }); + + /** + * The split that matters here is which action asks first. Marking read + * destroys nothing and a dialog on it is a step to click through; delete has + * no undo anywhere in this feature and gets one. + */ + describe('the bulk actions', () => { + // The dialog is a callback, not a promise. show() is handed the function to + // run on confirm and the one to run on cancel, so a test drives it by + // reaching for whichever of those it wants. + const confirmed = (): void => confirmationModal.show.mock.calls[0][2](); + const cancelled = (): void => confirmationModal.show.mock.calls[0][3](); + + const deleteButtons = (): HTMLElement[] => + Array.from(panel().querySelectorAll('.notification-delete')); + + const markAllButton = (): HTMLElement => panel().querySelector('.notification-mark-all'); + + const seeAllButton = (): HTMLElement => panel().querySelector('.notification-see-all'); + + beforeEach(() => { + fixture.detectChanges(); + openMenu(); + list.next([notification(1), notification(2, {readAt: new Date(2026, 7, 17, 9, 30, 0)})]); + fixture.detectChanges(); + }); + + it('marks everything read without asking first', () => { + unreadCount.next(1); + fixture.detectChanges(); + + // MatMenu closes the panel from a click handler on the panel itself, so + // anything that reaches it shuts the menu. The whole reward for this + // button is watching the rows stop being bold, and that is gone if the + // menu closes underneath it. Watching the click arrive is steadier than + // watching the overlay leave, which is animation timing. + const reachedThePanel = vi.fn(); + panel().addEventListener('click', reachedThePanel); + + markAllButton().click(); + fixture.detectChanges(); + + expect(notificationService.markAllRead).toHaveBeenCalledTimes(1); + expect(subscribedTo.has('markAllRead')).toBe(true); + expect(confirmationModal.show).not.toHaveBeenCalled(); + expect(reachedThePanel).not.toHaveBeenCalled(); + }); + + it('does not offer to mark all read when nothing is unread', () => { + unreadCount.next(0); + fixture.detectChanges(); + + // Same reason the badge disappears at zero rather than showing one. An + // action that cannot do anything should not be sitting there. + expect(markAllButton()).toBeNull(); + + unreadCount.next(2); + fixture.detectChanges(); + + expect(markAllButton()).not.toBeNull(); + }); + + it('says so when marking everything read fails', () => { + unreadCount.next(1); + fixture.detectChanges(); + notificationService.markAllRead.mockReturnValue( + throwError(() => new Error('PUT read_all failed')), + ); + + markAllButton().click(); + + expect(alerts.error).toHaveBeenCalledTimes(1); + }); + + it('asks before it deletes anything', () => { + deleteButtons()[0].click(); + + expect(confirmationModal.show).toHaveBeenCalledTimes(1); + expect(notificationService.remove).not.toHaveBeenCalled(); + }); + + it('deletes only once the dialog is agreed to', () => { + deleteButtons()[0].click(); + confirmed(); + + expect(notificationService.remove).toHaveBeenCalledTimes(1); + expect(notificationService.remove.mock.calls[0][0].id).toBe(1); + expect(subscribedTo.has('remove')).toBe(true); + + fixture.detectChanges(); + expect(rowText()).toEqual(['notification 2']); + }); + + it('leaves the notification alone when the dialog is cancelled', () => { + deleteButtons()[0].click(); + cancelled(); + fixture.detectChanges(); + + expect(notificationService.remove).not.toHaveBeenCalled(); + expect(rowText()).toEqual(['notification 1', 'notification 2']); + }); + + it('keeps the row when the delete fails', () => { + notificationService.remove.mockReturnValue(throwError(() => new Error('DELETE failed'))); + + deleteButtons()[0].click(); + confirmed(); + fixture.detectChanges(); + + // Taking the row out first and putting it back on failure would be worse + // than leaving it. The user reads the row vanishing as the delete having + // worked. + expect(rowText()).toEqual(['notification 1', 'notification 2']); + expect(alerts.error).toHaveBeenCalledTimes(1); + }); + + it('does not open the notification when its delete button is clicked', () => { + deleteButtons()[0].click(); + + // The delete button sits in the row, and the row opens the notification. + // Without stopping the click there, asking to delete one would mark it + // read and navigate away from the menu it was asked in. + expect(notificationService.markRead).not.toHaveBeenCalled(); + expect(router.navigateByUrl).not.toHaveBeenCalled(); + }); + + it('promotes the next notification when a shown one is deleted', () => { + const at = (hour: number) => new Date(2026, 7, 17, hour, 0, 0); + const refresh = reopenWith(); + refresh.next([ + notification(1, {createdAt: at(15)}), + notification(2, {createdAt: at(14)}), + notification(3, {createdAt: at(13)}), + notification(4, {createdAt: at(12)}), + notification(5, {createdAt: at(11)}), + notification(6, {createdAt: at(10)}), + ]); + fixture.detectChanges(); + + expect(rowText()).toHaveLength(5); + expect(rowText()).not.toContain('notification 6'); + + deleteButtons()[0].click(); + confirmed(); + fixture.detectChanges(); + + // Filtering only the five on screen would leave four and a gap, when the + // sixth is already in hand and nothing needs to be asked for. + expect(rowText()).toEqual([ + 'notification 2', + 'notification 3', + 'notification 4', + 'notification 5', + 'notification 6', + ]); + }); + + it('drops a list read still in flight when everything is marked read', () => { + unreadCount.next(1); + fixture.detectChanges(); + + const refresh = reopenWith(); + expect(refresh.observed).toBe(true); + + markAllButton().click(); + + expect(refresh.observed).toBe(false); + }); + + it('offers a way to the rest of them', () => { + // The dropdown shows five and the api sends every one, so without this a + // sixth notification can only be reached by typing a url. + seeAllButton().click(); + + expect(router.navigateByUrl).toHaveBeenCalledWith('/notifications'); + }); + }); }); diff --git a/src/app/common/header/notification-bell/notification-bell.component.ts b/src/app/common/header/notification-bell/notification-bell.component.ts index a94693dacd..f2507a3b55 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.ts +++ b/src/app/common/header/notification-bell/notification-bell.component.ts @@ -6,6 +6,7 @@ import {Notification} from 'src/app/api/models/notification'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {NotificationService} from 'src/app/api/services/notification.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {ConfirmationModalService} from '../../modals/confirmation-modal/confirmation-modal.service'; /** * The bell in the header, the unread count on it, and the list behind it. @@ -77,8 +78,20 @@ export class NotificationBellComponent implements OnInit, OnDestroy { unreadCount = 0; + /** + * Everything the last read came back with, newest first. + * + * All of it and not just the five on screen. Deleting one of the five has to + * promote the sixth, and re-reading the list to find out what the sixth was + * would be a request for something already in hand. + */ notifications: Notification[] = []; + /** + * The slice actually drawn. + */ + recent: Notification[] = []; + loading = false; loadFailed = false; @@ -88,6 +101,7 @@ export class NotificationBellComponent implements OnInit, OnDestroy { constructor( private notificationService: NotificationService, private authenticationService: AuthenticationService, + private confirmationModal: ConfirmationModalService, private alerts: AlertService, private router: Router, ) {} @@ -150,7 +164,8 @@ export class NotificationBellComponent implements OnInit, OnDestroy { this.listSubscription = this.notificationService.list().subscribe({ next: (notifications) => { - this.notifications = this.mostRecent(notifications); + this.notifications = this.newestFirst(notifications); + this.updateRecent(); this.loading = false; }, error: () => { @@ -189,6 +204,74 @@ export class NotificationBellComponent implements OnInit, OnDestroy { } } + /** + * Mark the lot as read. + * + * No confirmation. Nothing is lost by it and the user can still read every + * one of them afterwards, so a dialog here would only be a step to click + * through. Delete is the one that asks. + * + * The count on the bell is not touched here. NotificationService drops it to + * zero inside markAllRead and pushes that down unreadCount$, which is where + * the badge reads it from, so a second copy of the arithmetic here could only + * ever disagree with it. + */ + markAllRead(event: MouseEvent): void { + // MatMenu closes on any click that reaches the panel, and closing here + // would hide the thing the user just asked to see happen. It also has to + // stop before the row underneath, which would treat this as opening the + // notification. + event.stopPropagation(); + + // A read that went out before this is now out of date, and its response is + // written into the shared cache, so landing late would draw every row + // unread again. + this.cancelPendingList(); + + this.notificationService.markAllRead().subscribe({ + error: () => this.alerts.error('Your notifications could not be marked as read'), + }); + } + + /** + * Ask first, then delete. + * + * Delete is the only one of the five endpoints that destroys anything, and + * there is no undo anywhere in this feature, so it gets the dialog the house + * already has rather than a new one. + * + * The empty cancel function is deliberate. ConfirmationModalService pops a + * green success snackbar reading " action cancelled" when none is + * given, and telling somebody they successfully did not delete something is + * noise. + */ + confirmDelete(notification: Notification, event: MouseEvent): void { + event.stopPropagation(); + + this.confirmationModal.show( + 'Delete notification', + 'This removes the notification. You will not be able to get it back.', + () => this.remove(notification), + () => undefined, + 'Delete', + ); + } + + /** + * Go to the full list. + * + * The dropdown shows five and the api sends every one, so without a way out + * of it a sixth notification is unreachable except by typing a url. + * + * The /notifications route arrives with IN-04, which is a sibling branch, so + * on this branch alone there is nothing at that path yet and app.routes.ts + * sends an unmatched path to /home. Both branches merge into + * feature/notifications before any of this ships. + */ + seeAll(): void { + this.router.navigateByUrl('/notifications'); + } + iconFor(notification: Notification): string { return this.categoryFor(notification).icon; } @@ -235,17 +318,45 @@ export class NotificationBellComponent implements OnInit, OnDestroy { } /** - * The newest few. + * Delete it for real, once the dialog has been agreed to. + * + * The row is dropped from the held list on success rather than by reading the + * list again. A second GET for something we already know the answer to would + * make the row sit there for a round trip after the user asked for it to go. + * The unread count corrects itself from unreadCount$, the same as everywhere + * else here. + */ + private remove(notification: Notification): void { + this.cancelPendingList(); + + this.notificationService.remove(notification).subscribe({ + next: () => { + this.notifications = this.notifications.filter((row) => row !== notification); + + // Recomputed and not filtered in place. Filtering the five on screen + // leaves four and a gap, when the sixth newest is sitting right here + // waiting to move up. + this.updateRecent(); + this.alerts.success('Notification deleted'); + }, + error: () => this.alerts.error('That notification could not be deleted'), + }); + } + + /** + * Newest first. * - * The api already answers newest first, and this sorts anyway. Recency is the - * entire meaning of this list, and the copies handed back here come out of a - * cache that other calls also write to, so the order of the array is not + * The api already answers in this order, and this sorts anyway. Recency is + * the entire meaning of this list, and the copies handed back here come out + * of a cache that other calls also write to, so the order of the array is not * something worth trusting. */ - private mostRecent(notifications: Notification[]): Notification[] { - return [...notifications] - .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()) - .slice(0, NotificationBellComponent.RECENT_COUNT); + private newestFirst(notifications: Notification[]): Notification[] { + return [...notifications].sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()); + } + + private updateRecent(): void { + this.recent = this.notifications.slice(0, NotificationBellComponent.RECENT_COUNT); } private categoryFor(notification: Notification): {icon: string; tone: string} { From f2aae94b409d8357c99da0cf60de8e48270b5fca Mon Sep 17 00:00:00 2001 From: Clupai8o0 <clupaio4@gmail.com> Date: Mon, 17 Aug 2026 15:49:01 +1000 Subject: [PATCH 1342/1531] feat(notifications): add notifications page A /notifications route and a page listing every notification, paged client side at twenty a page with 10/20/50 offered. Paged here because GET /notifications takes unread_only and nothing else and answers with the lot, so there is nothing to page with on the api. If real paging is wanted that is an api ticket. Under common/ next to the other routed components that belong to neither a unit nor a project, scorm-player and submission-files-download. Loading, empty and failed-to-load are three separate states. The failed one has a Try again button, because it is the only state on the page with nothing useful on it, and it is kept apart from the empty one because "you have none" and "we could not find out" look the same and mean opposite things. afterAuthCall before the first request, the same as EditProfileComponent. The route has no guard, matching edit_profile, so without it opening the url signed out sends an anonymous request, gets a 403, and HttpErrorInterceptor reads that as an expired session and redirects to /timeout. A reload that comes back shorter clamps the page index, so a run of deletes cannot strand the reader on page three of one. Rows are plain buttons carrying the same .notification-line markup and the same category icons and colours as the header dropdown. Material lays out neither: a mat-list-item wraps its content differently from a mat-menu-item, and the two would never line up. The shared stylesheet block is duplicated in both components with a comment in each, because they are sibling branches and neither can import from the other yet. Tests: 18 new, 153 across the suite. --- src/app/app.routes.ts | 2 + .../notifications-page.component.html | 80 ++++ .../notifications-page.component.scss | 135 ++++++ .../notifications-page.component.spec.ts | 395 ++++++++++++++++++ .../notifications-page.component.ts | 211 ++++++++++ src/app/doubtfire-angular.module.ts | 2 + 6 files changed, 825 insertions(+) create mode 100644 src/app/common/notifications-page/notifications-page.component.html create mode 100644 src/app/common/notifications-page/notifications-page.component.scss create mode 100644 src/app/common/notifications-page/notifications-page.component.spec.ts create mode 100644 src/app/common/notifications-page/notifications-page.component.ts diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index c9160fca0e..5f5b23066f 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -4,6 +4,7 @@ import {InstitutionSettingsComponent} from './admin/institution-settings/institu import {FUnitsComponent} from './admin/states/units/units.component'; import {FUsersComponent} from './admin/states/users/users.component'; import {roleWhitelistGuard} from './common/guards/role-whitelist.guard'; +import {NotificationsPageComponent} from './common/notifications-page/notifications-page.component'; import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component'; import {SubmissionFilesDownloadComponent} from './common/submission-files-download/submission-files-download.component'; import {SuccessCloseComponent} from './common/success-close/success-close.component'; @@ -44,6 +45,7 @@ export const routes: Routes = [ {path: 'timeout', component: TimeoutComponent}, {path: 'success-close', component: SuccessCloseComponent}, {path: 'edit_profile', component: EditProfileComponent}, + {path: 'notifications', component: NotificationsPageComponent}, {path: 'eula', component: AcceptEulaComponent}, {path: 'lti', component: LtiDashboardComponent}, {path: 'lti/link', component: LtiUnitLinkComponent}, diff --git a/src/app/common/notifications-page/notifications-page.component.html b/src/app/common/notifications-page/notifications-page.component.html new file mode 100644 index 0000000000..488aea0e0c --- /dev/null +++ b/src/app/common/notifications-page/notifications-page.component.html @@ -0,0 +1,80 @@ +<div class="notifications-page mx-auto my-6 max-w-3xl px-4"> + <h1 class="mb-4 text-2xl">Notifications</h1> + + @if (loading) { + <div class="flex items-center gap-3 py-6"> + <mat-spinner [diameter]="24"></mat-spinner> + <span>Loading your notifications</span> + </div> + } @else if (loadFailed) { + <!-- + Kept apart from the empty state on purpose. "You have none" and "we could + not find out" look the same and mean opposite things, and only one of them + has a way out. + --> + <div class="notifications-placeholder py-6"> + <p>We could not load your notifications.</p> + <button class="notifications-retry" mat-stroked-button (click)="load()">Try again</button> + </div> + } @else if (!notifications.length) { + <div class="notifications-placeholder py-6"> + <p>You have no notifications yet.</p> + <p class="notification-time"> + Comments on your tasks, feedback and reminders will show up here. + </p> + </div> + } @else { + <!-- + Plain buttons rather than mat-list-item. Material lays a list row out with + its own leading-icon and content wrappers, and the dropdown in the header + is a mat-menu-item with a different set of wrappers again, so the two + never lined up. Both now use the same .notification-line markup and the + same stylesheet block, and Material lays out neither. + + Still a <button>: a div with a click handler is a row only a mouse can + open. + --> + <div class="notification-list"> + @for (notification of visible; track notification.id) { + <button + class="notification-row" + type="button" + [attr.aria-label]="rowLabel(notification)" + (click)="open(notification)" + > + <span class="notification-line"> + <!-- + Same five categories and the same colours as the dropdown in the + header, so a notification looks like itself wherever it is read. + --> + <span class="notification-glyph" [class]="'tone-' + toneFor(notification)"> + <mat-icon>{{ iconFor(notification) }}</mat-icon> + </span> + + <span class="notification-body"> + <span class="notification-message" [class.unread]="!notification.isRead">{{ + notification.message + }}</span> + <span class="notification-time">{{ timeAgo(notification) }}</span> + </span> + + <span + aria-hidden="true" + class="notification-unread-dot" + [class.is-read]="notification.isRead" + ></span> + </span> + </button> + } + </div> + + <mat-paginator + class="mat-elevation-z0" + [length]="notifications.length" + [pageIndex]="pageIndex" + [pageSize]="pageSize" + [pageSizeOptions]="pageSizeOptions" + (page)="onPage($event)" + ></mat-paginator> + } +</div> diff --git a/src/app/common/notifications-page/notifications-page.component.scss b/src/app/common/notifications-page/notifications-page.component.scss new file mode 100644 index 0000000000..fee98e829a --- /dev/null +++ b/src/app/common/notifications-page/notifications-page.component.scss @@ -0,0 +1,135 @@ +.notification-list { + border-top: 1px solid rgba(0, 0, 0, 0.08); +} + +// A plain button carrying the shared row shape. Material lays out neither this +// nor the header dropdown's rows, which is the only way the two match. +.notification-row { + background: none; + border: 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.08); + cursor: pointer; + display: block; + font: inherit; + padding: 14px 12px; + width: 100%; + + &:hover { + background: rgba(0, 0, 0, 0.04); + } + + &:focus-visible { + outline: 2px solid #3939ff; + outline-offset: -2px; + } +} + +// --------------------------------------------------------------------------- +// Shared row shape. The header's notification-bell carries a copy of this +// block, deliberately: the two components are on sibling branches so neither +// can import from the other yet, and a row has to look the same in both places. +// Both copies belong in one stylesheet once they have merged. Keep them equal. +// --------------------------------------------------------------------------- +.notification-line { + align-items: center; + display: flex; + gap: 12px; + width: 100%; +} + +.notification-body { + display: flex; + flex: 1 1 auto; + flex-direction: column; + gap: 2px; + min-width: 0; + text-align: left; +} + +.notification-glyph { + align-items: center; + border-radius: 50%; + display: inline-flex; + flex: 0 0 36px; + height: 36px; + justify-content: center; + width: 36px; + + // mat-icon ships as a 24px inline-block with a 24px line box. Left alone the + // glyph is nearly as wide as the circle and sits low in it, because an inline + // box aligns on its baseline. A block with a line-height equal to its own + // height and no margin takes that out, and the flex centring above then does + // what it looks like it does. + .mat-icon { + // Explicitly, not by inheritance. Material colours icons inside a menu item + // with .mat-mdc-menu-item .mat-icon { color: ... }, so a tone set on the + // circle around it is simply overridden and the glyph comes out black in + // the dropdown while the same glyph is coloured on the page. + color: inherit; + display: block; + font-size: 20px; + height: 20px; + line-height: 20px; + margin: 0; + overflow: visible; + width: 20px; + } + + &.tone-feedback { + background: rgba(57, 57, 255, 0.12); + color: #2a2ad6; + } + + &.tone-task { + background: rgba(199, 119, 0, 0.12); + color: #b26a00; + } + + &.tone-portfolio { + background: rgba(123, 63, 242, 0.12); + color: #7b3ff2; + } + + &.tone-extension { + background: rgba(31, 138, 76, 0.12); + color: #1f8a4c; + } + + &.tone-general { + background: rgba(95, 99, 104, 0.12); + color: #5f6368; + } +} + +.notification-message { + color: rgba(0, 0, 0, 0.87); + font-size: 14px; + line-height: 1.35; + white-space: normal; + + &.unread { + font-weight: 600; + } +} + +.notification-unread-dot { + background: #3939ff; + border-radius: 50%; + flex: 0 0 7px; + height: 7px; + width: 7px; + + &.is-read { + visibility: hidden; + } +} + +.notification-time { + color: rgba(0, 0, 0, 0.6); + font-size: 12px; + line-height: 1.3; +} + +.notifications-placeholder { + color: rgba(0, 0, 0, 0.6); +} diff --git a/src/app/common/notifications-page/notifications-page.component.spec.ts b/src/app/common/notifications-page/notifications-page.component.spec.ts new file mode 100644 index 0000000000..bd2fcb0dac --- /dev/null +++ b/src/app/common/notifications-page/notifications-page.component.spec.ts @@ -0,0 +1,395 @@ +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatButtonModule} from '@angular/material/button'; +import {MatIconModule} from '@angular/material/icon'; +import {MatListModule} from '@angular/material/list'; +import {MatPaginator, MatPaginatorModule} from '@angular/material/paginator'; +import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; +import {By} from '@angular/platform-browser'; +import {NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {Router} from '@angular/router'; +import {Observable, Subject, defer, of, throwError} from 'rxjs'; +import {Notification} from 'src/app/api/models/notification'; +import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {NotificationService} from 'src/app/api/services/notification.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {NotificationsPageComponent} from './notifications-page.component'; + +/** + * Three of these are the states the ticket names, loading, empty and the list + * itself, and they are tested through the rendered page because that is where + * the difference between them lives. The fourth is the one the ticket does not + * name and is the same trap as in the dropdown: a request that failed must not + * be drawn as a user with no notifications. + * + * The paging tests drive the real paginator rather than calling onPage, so the + * binding between them counts. They hold the api at arm's length deliberately: + * there is one fetch and one only, and every page after the first has to come + * out of what is already here. + */ +describe('NotificationsPageComponent', () => { + let component: NotificationsPageComponent; + let fixture: ComponentFixture<NotificationsPageComponent>; + + let list: Subject<Notification[]>; + let subscribedTo: Set<string>; + let notificationService: { + list: ReturnType<typeof vi.fn>; + markRead: ReturnType<typeof vi.fn>; + }; + let authenticationService: {afterAuthCall: ReturnType<typeof vi.fn>}; + let alerts: {success: ReturnType<typeof vi.fn>; error: ReturnType<typeof vi.fn>}; + let router: {navigateByUrl: ReturnType<typeof vi.fn>}; + + /** + * A stand-in that records whether anybody actually subscribed. + * + * A spy that only counts calls is happy either way, and markRead returns a + * cold observable, so dropping the .subscribe() sends no request at all while + * the call count stays exactly the same. + */ + const answers = <T>(name: string, value: T): Observable<T> => + defer(() => { + subscribedTo.add(name); + return of(value); + }); + + const notification = (id: number, over: Partial<Notification> = {}): Notification => { + const built = new Notification(); + built.id = id; + built.message = `notification ${id}`; + built.link = `/projects/${id}/dashboard`; + built.notificationType = 'feedback'; + built.readAt = null; + // Newest id first, so a page of them reads in a checkable order. + built.createdAt = new Date(2026, 0, 1, 0, 0, id); + return Object.assign(built, over); + }; + + const many = (count: number): Notification[] => + Array.from({length: count}, (_unused, index) => notification(count - index)); + + const rows = (): HTMLElement[] => + Array.from(fixture.nativeElement.querySelectorAll('.notification-row')); + + const rowText = (): string[] => + rows().map((row) => row.querySelector('.notification-message').textContent.trim()); + + const pageText = (): string => fixture.nativeElement.textContent; + + const paginator = (): MatPaginator => + fixture.debugElement.query(By.directive(MatPaginator)).componentInstance; + + beforeEach(async () => { + list = new Subject<Notification[]>(); + subscribedTo = new Set<string>(); + + notificationService = { + list: vi.fn().mockReturnValue(list), + markRead: vi.fn(() => answers('markRead', undefined)), + }; + // Signed in and settled, unless a test says otherwise. + authenticationService = {afterAuthCall: vi.fn((callback) => callback(true))}; + alerts = {success: vi.fn(), error: vi.fn()}; + router = {navigateByUrl: vi.fn()}; + + await TestBed.configureTestingModule({ + declarations: [NotificationsPageComponent], + imports: [ + MatButtonModule, + MatIconModule, + MatListModule, + MatPaginatorModule, + MatProgressSpinnerModule, + NoopAnimationsModule, + ], + providers: [ + {provide: NotificationService, useValue: notificationService}, + {provide: AuthenticationService, useValue: authenticationService}, + {provide: AlertService, useValue: alerts}, + {provide: Router, useValue: router}, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(NotificationsPageComponent); + component = fixture.componentInstance; + }); + + it('says it is loading before the list arrives', () => { + fixture.detectChanges(); + + expect(pageText()).toContain('Loading your notifications'); + expect(rows()).toHaveLength(0); + + list.next([notification(1)]); + fixture.detectChanges(); + + expect(pageText()).not.toContain('Loading your notifications'); + expect(rows()).toHaveLength(1); + }); + + it('says something friendly when there is nothing to show', () => { + fixture.detectChanges(); + + list.next([]); + fixture.detectChanges(); + + expect(pageText()).toContain('You have no notifications yet'); + expect(rows()).toHaveLength(0); + }); + + it('says it could not load rather than claiming there is nothing', () => { + fixture.detectChanges(); + + list.error(new Error('GET /notifications failed')); + fixture.detectChanges(); + + expect(pageText()).toContain('could not load'); + expect(pageText()).not.toContain('You have no notifications yet'); + }); + + it('reads the list again when the retry is clicked', () => { + fixture.detectChanges(); + list.error(new Error('GET /notifications failed')); + fixture.detectChanges(); + + list = new Subject<Notification[]>(); + notificationService.list.mockReturnValue(list); + + fixture.nativeElement.querySelector('.notifications-retry').click(); + fixture.detectChanges(); + + expect(notificationService.list).toHaveBeenCalledTimes(2); + expect(pageText()).toContain('Loading your notifications'); + + list.next([notification(1)]); + fixture.detectChanges(); + + expect(rowText()).toEqual(['notification 1']); + }); + + it('shows the newest first', () => { + fixture.detectChanges(); + + list.next([notification(1), notification(3), notification(2)]); + fixture.detectChanges(); + + expect(rowText()).toEqual(['notification 3', 'notification 2', 'notification 1']); + }); + + it('makes each row a real button so a keyboard can open it', () => { + fixture.detectChanges(); + list.next([notification(1)]); + fixture.detectChanges(); + + // Structural, and it has to be. A mat-list-item on its own is static list + // content: no focus, no Enter, no Space. Only the element type gives the + // row those, and the test environment does not simulate the browser + // behaviour that would let this be asserted any other way. + expect(rows()[0].tagName).toBe('BUTTON'); + }); + + it('gives each category the same icon and colour the dropdown gives it', () => { + fixture.detectChanges(); + list.next([ + notification(5, {notificationType: 'feedback'}), + notification(4, {notificationType: 'task'}), + notification(3, {notificationType: 'portfolio'}), + notification(2, {notificationType: 'extension'}), + notification(1, {notificationType: 'general'}), + ]); + fixture.detectChanges(); + + const glyphs: HTMLElement[] = Array.from( + fixture.nativeElement.querySelectorAll('.notification-glyph'), + ); + + expect(glyphs.map((g) => g.querySelector('mat-icon').textContent.trim())).toEqual([ + 'chat_bubble', + 'assignment', + 'collections_bookmark', + 'more_time', + 'campaign', + ]); + expect(glyphs.map((g) => Array.from(g.classList).find((n) => n.startsWith('tone-')))).toEqual([ + 'tone-feedback', + 'tone-task', + 'tone-portfolio', + 'tone-extension', + 'tone-general', + ]); + }); + + it('still draws something for a category it has never heard of', () => { + fixture.detectChanges(); + list.next([notification(1, {notificationType: 'announcement'})]); + fixture.detectChanges(); + + const glyph = fixture.nativeElement.querySelector('.notification-glyph'); + + expect(glyph.querySelector('mat-icon').textContent.trim()).toBe('notifications'); + expect(Array.from(glyph.classList)).toContain('tone-general'); + }); + + it('says unread in words, not only in bold', () => { + fixture.detectChanges(); + list.next([ + notification(2, {message: 'Andrew Cain commented on 1.1P.'}), + notification(1, {message: 'Your extension was granted.', readAt: new Date(2026, 0, 2)}), + ]); + fixture.detectChanges(); + + expect(rows()[0].getAttribute('aria-label')).toContain('Unread.'); + expect(rows()[1].getAttribute('aria-label')).toContain('Read.'); + }); + + it('shows one page at a time out of a single fetch', () => { + fixture.detectChanges(); + + list.next(many(45)); + fixture.detectChanges(); + + expect(rows()).toHaveLength(20); + expect(rowText()[0]).toBe('notification 45'); + expect(paginator().length).toBe(45); + + // Through the paginator and not through onPage. Calling the handler + // directly passes just as well with the (page) binding deleted, and then + // the real Next button does nothing. + paginator().nextPage(); + fixture.detectChanges(); + + expect(rowText()[0]).toBe('notification 25'); + expect(rows()).toHaveLength(20); + + // The last page is the short one, and it is where an off by one shows up. + paginator().nextPage(); + fixture.detectChanges(); + + expect(rows()).toHaveLength(5); + expect(rowText()).toEqual([ + 'notification 5', + 'notification 4', + 'notification 3', + 'notification 2', + 'notification 1', + ]); + + // One request for the whole thing. Paging is over what is already here, + // because the api has no page parameters to send. + expect(notificationService.list).toHaveBeenCalledTimes(1); + }); + + it('follows a change of page size', () => { + fixture.detectChanges(); + list.next(many(45)); + fixture.detectChanges(); + + paginator()._changePageSize(50); + fixture.detectChanges(); + + expect(rows()).toHaveLength(45); + }); + + it('does not strand the reader past the end when a reload is shorter', () => { + fixture.detectChanges(); + list.next(many(45)); + fixture.detectChanges(); + + paginator().nextPage(); + paginator().nextPage(); + fixture.detectChanges(); + expect(rows()).toHaveLength(5); + + // Same page number, far fewer notifications behind it. Left alone this + // renders an empty page with a paginator insisting it is page three of one. + list = new Subject<Notification[]>(); + notificationService.list.mockReturnValue(list); + component.load(); + list.next(many(4)); + fixture.detectChanges(); + + expect(component.pageIndex).toBe(0); + expect(rows()).toHaveLength(4); + }); + + it('marks a row read and follows its link when it is clicked', () => { + fixture.detectChanges(); + list.next([notification(1, {link: '/projects/9/dashboard'})]); + fixture.detectChanges(); + + rows()[0].click(); + + expect(notificationService.markRead).toHaveBeenCalledTimes(1); + expect(notificationService.markRead.mock.calls[0][0].id).toBe(1); + expect(subscribedTo.has('markRead')).toBe(true); + expect(router.navigateByUrl).toHaveBeenCalledWith('/projects/9/dashboard'); + }); + + it('does not mark a row read twice', () => { + fixture.detectChanges(); + list.next([notification(1, {readAt: new Date(2026, 0, 2)})]); + fixture.detectChanges(); + + rows()[0].click(); + + expect(notificationService.markRead).not.toHaveBeenCalled(); + expect(router.navigateByUrl).toHaveBeenCalledTimes(1); + }); + + it('marks a row read even when it has nowhere to go', () => { + fixture.detectChanges(); + list.next([notification(1, {link: null})]); + fixture.detectChanges(); + + rows()[0].click(); + + // link is nullable on the api. Refusing to mark it read would leave a + // number on the bell that the user has no way to clear. + expect(notificationService.markRead).toHaveBeenCalledTimes(1); + expect(router.navigateByUrl).not.toHaveBeenCalled(); + }); + + it('says so when a notification could not be marked as read', () => { + notificationService.markRead.mockReturnValue(throwError(() => new Error('PUT read failed'))); + + fixture.detectChanges(); + list.next([notification(1, {link: null})]); + fixture.detectChanges(); + + rows()[0].click(); + + expect(alerts.error).toHaveBeenCalledTimes(1); + }); + + describe('before anyone is signed in', () => { + it('asks nothing of the api until authentication has settled', () => { + let resume: (signedIn: boolean) => void; + authenticationService.afterAuthCall.mockImplementation((callback) => { + resume = callback; + }); + + fixture.detectChanges(); + + // An anonymous GET /notifications comes back 403, and HttpErrorInterceptor + // reads a 403 on an anonymous user as an expired session: it alerts + // "Authentication timed out" and redirects to /timeout. Opening a + // bookmark while signed out would look like being thrown out. + expect(notificationService.list).not.toHaveBeenCalled(); + + resume(true); + fixture.detectChanges(); + + expect(notificationService.list).toHaveBeenCalledTimes(1); + }); + + it('sends the visitor to sign in instead of asking the api', () => { + authenticationService.afterAuthCall.mockImplementation((callback) => callback(false)); + + fixture.detectChanges(); + + expect(notificationService.list).not.toHaveBeenCalled(); + expect(router.navigateByUrl).toHaveBeenCalledWith('/sign_in'); + }); + }); +}); diff --git a/src/app/common/notifications-page/notifications-page.component.ts b/src/app/common/notifications-page/notifications-page.component.ts new file mode 100644 index 0000000000..24fce244b1 --- /dev/null +++ b/src/app/common/notifications-page/notifications-page.component.ts @@ -0,0 +1,211 @@ +import moment from 'moment'; +import {ChangeDetectionStrategy, Component, OnDestroy, OnInit} from '@angular/core'; +import {PageEvent} from '@angular/material/paginator'; +import {Router} from '@angular/router'; +import {Subscription} from 'rxjs'; +import {Notification} from 'src/app/api/models/notification'; +import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {NotificationService} from 'src/app/api/services/notification.service'; +import {AlertService} from 'src/app/common/services/alert.service'; + +/** + * The whole notification list, on a page of its own. + * + * Lives under common/ next to the other routed components that are not part of + * a unit or a project, scorm-player and submission-files-download. + * + * Paged here and not by the api. GET /notifications takes unread_only and + * nothing else and answers with every row the user has, so this holds the lot + * and shows a page of it. That is fine at the sizes this feature produces and + * it is wrong at some size, which is an api ticket and not this one. + */ +@Component({ + selector: 'f-notifications-page', + templateUrl: './notifications-page.component.html', + styleUrls: ['./notifications-page.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, + standalone: false, +}) +export class NotificationsPageComponent implements OnInit, OnDestroy { + public readonly pageSizeOptions: number[] = [10, 20, 50]; + + /** + * The icon and colour for a notification's category. + * + * The same five as the header dropdown, deliberately, so a notification looks + * like itself wherever it is read. Duplicated rather than shared because the + * dropdown is on a sibling branch and neither can import from the other yet; + * this belongs in one place once both have merged, along with open(). + * + * Keyed on notificationType because that is all NotificationEntity exposes. + * The event naming the specific thing that happened is not in the payload, so + * a new task, a due date change and a due soon reminder share the task icon. + */ + private static readonly CATEGORIES: Record<string, {icon: string; tone: string}> = { + feedback: {icon: 'chat_bubble', tone: 'feedback'}, + task: {icon: 'assignment', tone: 'task'}, + portfolio: {icon: 'collections_bookmark', tone: 'portfolio'}, + extension: {icon: 'more_time', tone: 'extension'}, + general: {icon: 'campaign', tone: 'general'}, + }; + + private static readonly UNKNOWN_CATEGORY = {icon: 'notifications', tone: 'general'}; + + notifications: Notification[] = []; + + /** + * The rows actually on screen. + * + * Held rather than worked out in the template. A getter that slices would + * build a new array on every change detection pass, and with a click handler + * on every row there are a lot of those. + */ + visible: Notification[] = []; + + loading = true; + loadFailed = false; + + pageIndex = 0; + pageSize = 20; + + private listSubscription: Subscription | null = null; + + constructor( + private notificationService: NotificationService, + private authenticationService: AuthenticationService, + private alerts: AlertService, + private router: Router, + ) {} + + /** + * Wait for authentication before asking the api for anything. + * + * The route has no guard, so this component is built for whoever opens the + * url, signed in or not. An anonymous GET /notifications comes back 403, and + * HttpErrorInterceptor reads a 403 on an anonymous user as an expired + * session: it shows "Authentication timed out" and redirects to /timeout, + * instead of the sign in page somebody following a stale bookmark should get. + * + * afterAuthCall is what EditProfileComponent does for the same reason, and it + * waits rather than guessing, so a page opened while the session is still + * being restored still loads. + */ + ngOnInit(): void { + this.authenticationService.afterAuthCall((signedIn) => { + if (!signedIn) { + this.router.navigateByUrl('/sign_in'); + return; + } + + this.load(); + }); + } + + ngOnDestroy(): void { + this.listSubscription?.unsubscribe(); + } + + /** + * Read every notification, once. + * + * Also the retry. A failed load is the one state on this page with nothing + * useful on it, so the way out has to be on the page rather than a refresh of + * the browser. + */ + load(): void { + this.loading = true; + this.loadFailed = false; + + this.listSubscription?.unsubscribe(); + + this.listSubscription = this.notificationService.list().subscribe({ + next: (notifications) => { + this.notifications = [...notifications].sort( + (a, b) => b.createdAt.getTime() - a.createdAt.getTime(), + ); + + // A retry after a run of deletes can leave the reader stranded on a + // page that no longer exists, staring at nothing. + this.pageIndex = Math.min(this.pageIndex, this.lastPageIndex()); + this.loading = false; + this.updateVisible(); + }, + error: () => { + this.loading = false; + this.loadFailed = true; + }, + }); + } + + onPage(event: PageEvent): void { + this.pageIndex = event.pageIndex; + this.pageSize = event.pageSize; + this.updateVisible(); + } + + /** + * Open one notification: mark it read, then go where it points. + * + * The same shape as the dropdown in the header. They are on separate branches + * so neither can call the other today, and once both have merged this belongs + * in one place. + */ + open(notification: Notification): void { + if (!notification.isRead) { + // A read that went out before this click is out of date now, and + // NotificationService writes list responses into the shared entity cache, + // so one landing late would put readAt back to null. + this.listSubscription?.unsubscribe(); + this.listSubscription = null; + + this.notificationService.markRead(notification).subscribe({ + error: () => this.alerts.error('That notification could not be marked as read'), + }); + } + + if (notification.link) { + this.router.navigateByUrl(notification.link); + } + } + + iconFor(notification: Notification): string { + return this.categoryFor(notification).icon; + } + + toneFor(notification: Notification): string { + return this.categoryFor(notification).tone; + } + + /** + * What a screen reader should read for a row. + * + * Unread is drawn as bold text, and that is a thing you have to be able to + * see. The message and the time are already in the button, so this only + * exists to put the state into words. + */ + rowLabel(notification: Notification): string { + const state = notification.isRead ? 'Read' : 'Unread'; + + return `${state}. ${notification.message}. ${this.timeAgo(notification)}`; + } + + timeAgo(notification: Notification): string { + return moment(notification.createdAt).fromNow(); + } + + private categoryFor(notification: Notification): {icon: string; tone: string} { + return ( + NotificationsPageComponent.CATEGORIES[notification.notificationType] ?? + NotificationsPageComponent.UNKNOWN_CATEGORY + ); + } + + private updateVisible(): void { + const start = this.pageIndex * this.pageSize; + this.visible = this.notifications.slice(start, start + this.pageSize); + } + + private lastPageIndex(): number { + return Math.max(0, Math.ceil(this.notifications.length / this.pageSize) - 1); + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index dcc8a3f9ef..b0cc11af8b 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -211,6 +211,7 @@ import {SpecConModalService} from './common/modals/spec-con-modal/spec-con-modal import {TaskAssessmentModalComponent} from './common/modals/task-assessment-modal/task-assessment-modal.component'; import {TutorNotesModalComponent} from './common/modals/tutor-notes-modal/tutor-notes-modal.component'; import {NotificationSettingsComponent} from './common/notification-settings/notification-settings.component'; +import {NotificationsPageComponent} from './common/notifications-page/notifications-page.component'; import {ObjectSelectComponent} from './common/obect-select/object-select.component'; import {PdfViewerPanelComponent} from './common/pdf-viewer-panel/pdf-viewer-panel.component'; import {fPdfViewerComponent} from './common/pdf-viewer/pdf-viewer.component'; @@ -589,6 +590,7 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { ProgressBurndownChartComponent, TaskVisualisationComponent, ScormPlayerComponent, + NotificationsPageComponent, ScormCommentComponent, TaskScormCardComponent, ScormExtensionCommentComponent, From 650c865548a4666554cad0bd279f47ca94ca84dd Mon Sep 17 00:00:00 2001 From: Clupai8o0 <clupaio4@gmail.com> Date: Mon, 17 Aug 2026 15:49:11 +1000 Subject: [PATCH 1343/1531] fix(tasks): follow the task in the url instead of reading it once FUnitTaskListComponent read route.snapshot.paramMap in ngOnInit and never subscribed. Angular reuses a component when only a route parameter changes, so going from /projects/2/dashboard/1.1P to /projects/2/dashboard/2.3P never runs ngOnInit again: the url changed, the first task stayed selected and the second was never opened. Opening the same link in a fresh tab worked, which is what made it look intermittent. Any in-app link to another task on a dashboard the reader is already looking at hits this. Notification links are the first feature to produce those routinely, which is how it surfaced. Also adds an ngOnDestroy. The component had none, and the existing selectedTaskDefinition$ subscription leaked on every teardown. Both subscriptions now end with the component. Tests: none added. The behaviour needs a routed component that Angular reuses across a parameter change, which this component's spec has no harness for. Tests: 135 across the suite, unchanged. --- .../unit-task-list.component.ts | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index bfce70d27d..7a3fe9c76a 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -4,11 +4,12 @@ import { HostBinding, Input, OnChanges, + OnDestroy, OnInit, SimpleChanges, } from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; -import {BehaviorSubject} from 'rxjs'; +import {BehaviorSubject, Subject, takeUntil} from 'rxjs'; import {Project, Task, TaskDefinition} from 'src/app/api/models/doubtfire-model'; import {TaskDefinitionNamePipe} from 'src/app/common/filters/task-definition-name.pipe'; @@ -45,7 +46,9 @@ const START_APPROACHING_DAYS = 7; changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) -export class FUnitTaskListComponent implements OnChanges, OnInit { +export class FUnitTaskListComponent implements OnChanges, OnInit, OnDestroy { + private readonly destroy$: Subject<void> = new Subject(); + @Input() mode: 'project' | 'all-tasks'; @Input() project: Project; @Input() taskDefinitions: readonly TaskDefinition[]; @@ -249,7 +252,7 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { this.applyFilters(); // Watch for changes in the selected task definition... including from us - this.selectedTaskDefinition$.subscribe((taskDef) => { + this.selectedTaskDefinition$.pipe(takeUntil(this.destroy$)).subscribe((taskDef) => { this.selectedTaskDef = taskDef; }); @@ -267,23 +270,41 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { // this.setSelectedTaskDefinition(this.taskDefinitions[0]); // } - // Load selected task from URL - const current = this.selectedTaskDefinition$.value; - const param = this.route.snapshot.paramMap.get('taskAbbreviation'); - - queueMicrotask(() => { - if (param) { - const taskDef = this.taskDefinitions.find((t) => t.abbreviation === param); - - if (taskDef !== current) { - this.selectedTaskDefinition$.next(taskDef); + // Follow the selected task in the url, rather than reading it once. + // + // Angular reuses this component when only a route parameter changes, so + // going from .../dashboard/1.1P to .../dashboard/2.3P never runs ngOnInit + // again. Reading route.snapshot here left the first task selected and the + // second one never opened, which is what any in-app link to another task on + // a dashboard the user is already looking at runs into. A notification + // linking to a task is exactly that. + this.route.paramMap.pipe(takeUntil(this.destroy$)).subscribe((params) => { + const param = params.get('taskAbbreviation'); + + queueMicrotask(() => { + // Read inside the microtask, not outside. taskDefinitions arrives as an + // input and the value here has to be whatever is current when the + // comparison actually happens. + const current = this.selectedTaskDefinition$.value; + + if (param) { + const taskDef = this.taskDefinitions?.find((t) => t.abbreviation === param); + + if (taskDef && taskDef !== current) { + this.selectedTaskDefinition$.next(taskDef); + } + } else if (current !== null) { + this.selectedTaskDefinition$.next(null); } - } else if (current !== null) { - this.selectedTaskDefinition$.next(null); - } + }); }); } + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + setSelectedTaskDefinition(taskDef: TaskDefinition) { if (this.isSelectedTaskDefinition(taskDef)) { this.selectedTaskDefinition$.next(null); From 2af3c1c0e6a845d1492829ff2911d0089d4e805b Mon Sep 17 00:00:00 2001 From: officialid130-13e13 <officialid130@gmail.com> Date: Mon, 17 Aug 2026 16:32:42 +1000 Subject: [PATCH 1344/1531] test(PPI-T02): fix malformed and impossible-state regression tests --- ...-progress-indicator.adapter-compat.spec.ts | 96 ----------------- .../peer-progress-indicator.fixtures.spec.ts | 42 ++++---- ...ress-indicator.unit-summary-compat.spec.ts | 101 ------------------ 3 files changed, 23 insertions(+), 216 deletions(-) delete mode 100644 src/app/api/fixtures/peer-progress-indicator.adapter-compat.spec.ts delete mode 100644 src/app/api/fixtures/peer-progress-indicator.unit-summary-compat.spec.ts diff --git a/src/app/api/fixtures/peer-progress-indicator.adapter-compat.spec.ts b/src/app/api/fixtures/peer-progress-indicator.adapter-compat.spec.ts deleted file mode 100644 index ea116a469f..0000000000 --- a/src/app/api/fixtures/peer-progress-indicator.adapter-compat.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import {describe, expect, it} from 'vitest'; -import {PeerProgressIndicator} from '../models/peer-progress-indicator'; -import { - FIXTURE_DISABLED, - FIXTURE_MALFORMED, - FIXTURE_NORMAL, - FIXTURE_STALE, - FIXTURE_SUPPRESSED, - FIXTURE_UNAVAILABLE, - FIXTURE_ZERO_PERCENT, -} from './peer-progress-indicator.fixtures'; - -// A mock adapter boundary check -const adapterBoundaryCheck = (input: PeerProgressIndicator) => { - // The adapter must never throw on valid fixtures - if (input.submittedPercentage !== null && typeof input.submittedPercentage !== 'number') { - throw new Error('Invalid percentage type'); - } - - if (typeof input.isSuppressed !== 'boolean') { - throw new Error('Invalid suppression flag'); - } - - if (typeof input.isFeatureEnabled !== 'boolean') { - throw new Error('Invalid feature flag'); - } - - if (typeof input.lastUpdatedAt !== 'string') { - throw new Error('Invalid timestamp'); - } - - return true; -}; - -describe('PPI Adapter Compatibility Expectations', () => { - it('accepts all valid safe-state fixtures', () => { - const validFixtures = [ - FIXTURE_NORMAL, - FIXTURE_ZERO_PERCENT, - FIXTURE_SUPPRESSED, - FIXTURE_UNAVAILABLE, - FIXTURE_DISABLED, - FIXTURE_STALE, - ]; - - validFixtures.forEach((f) => { - expect(() => adapterBoundaryCheck(f)).not.toThrow(); - }); - }); - - it('rejects malformed fixture fields', () => { - expect(() => - adapterBoundaryCheck( - FIXTURE_MALFORMED as Partial<PeerProgressIndicator> as PeerProgressIndicator, - ), - ).toThrow(); - }); - - it('suppressed fixture must hide percentage', () => { - expect(FIXTURE_SUPPRESSED.submittedPercentage).toBeNull(); - expect(FIXTURE_SUPPRESSED.isSuppressed).toBe(true); - }); - - it('unavailable fixture must hide percentage but not be suppressed', () => { - expect(FIXTURE_UNAVAILABLE.submittedPercentage).toBeNull(); - expect(FIXTURE_UNAVAILABLE.isSuppressed).toBe(false); - }); - - it('disabled fixture must hide percentage and disable feature', () => { - expect(FIXTURE_DISABLED.submittedPercentage).toBeNull(); - expect(FIXTURE_DISABLED.isFeatureEnabled).toBe(false); - }); - - it('adapter must treat stale data as a safe state', () => { - expect(FIXTURE_STALE.isStale).toBe(true); - }); - - it('adapter must not leak peer identities or raw cohort counts', () => { - const fixtures = [ - FIXTURE_NORMAL, - FIXTURE_ZERO_PERCENT, - FIXTURE_SUPPRESSED, - FIXTURE_UNAVAILABLE, - FIXTURE_DISABLED, - FIXTURE_STALE, - ]; - - fixtures.forEach((f) => { - expect(f).not.toHaveProperty('peerName'); - expect(f).not.toHaveProperty('studentId'); - expect(f).not.toHaveProperty('cohortCount'); - expect(f).not.toHaveProperty('marks'); - expect(f).not.toHaveProperty('feedback'); - }); - }); -}); diff --git a/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts b/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts index 73905a8342..d302c9bdd7 100644 --- a/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts +++ b/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts @@ -111,31 +111,35 @@ describe('PeerProgressIndicator Fixture Regression Tests', () => { it('MALFORMED fixture contains invalid values for safe-failure testing', () => { const malformed = FIXTURE_MALFORMED as Partial<PeerProgressIndicator>; - expect(malformed.taskDefinitionId).not.toBe(12); + // invalid numeric values expect(malformed.submittedPercentage).toBeNaN(); - expect(typeof malformed.lastUpdatedAt).toBe('string'); // but invalid - }); + expect(Number.isFinite(malformed.submittedPercentage as number)).toBe(false); - // Adapter Compatibility Expectations - it('Adapter should accept all valid fixtures without throwing', () => { - const validFixtures = [ - FIXTURE_NORMAL, - FIXTURE_ZERO_PERCENT, - FIXTURE_SUPPRESSED, - FIXTURE_UNAVAILABLE, - FIXTURE_DISABLED, - FIXTURE_STALE, - ]; + // invalid ranges + // expect((malformed.submittedPercentage as number) < 0).toBe(true); + // expect((malformed.submittedPercentage as number) > 100).toBe(true); - validFixtures.forEach((f) => { - expect(() => assertContractShape(f)).not.toThrow(); - }); + // invalid timestamp + expect(isNaN(Date.parse(malformed.lastUpdatedAt as string))).toBe(true); + + // invalid IDs + expect(typeof malformed.taskDefinitionId).not.toBe('number'); + expect(typeof malformed.unitId).not.toBe('number'); + + // invalid target grade + expect(typeof malformed.targetGrade).not.toBe('number'); }); - it('Adapter should reject or normalise malformed fixture fields', () => { + it('MALFORMED fixture must not allow impossible state combinations', () => { const malformed = FIXTURE_MALFORMED as Partial<PeerProgressIndicator>; - expect(malformed.submittedPercentage).toBeNaN(); - expect(typeof malformed.targetGrade).toBe('string'); + // suppressed must be boolean + expect(typeof malformed.isSuppressed).not.toBe('boolean'); + + // stale must be boolean + expect(typeof malformed.isStale).not.toBe('boolean'); + + // featureEnabled must be boolean + expect(typeof malformed.isFeatureEnabled).not.toBe('boolean'); }); }); diff --git a/src/app/api/fixtures/peer-progress-indicator.unit-summary-compat.spec.ts b/src/app/api/fixtures/peer-progress-indicator.unit-summary-compat.spec.ts deleted file mode 100644 index c356813847..0000000000 --- a/src/app/api/fixtures/peer-progress-indicator.unit-summary-compat.spec.ts +++ /dev/null @@ -1,101 +0,0 @@ -import {describe, expect, it} from 'vitest'; -import { - FIXTURE_DISABLED, - FIXTURE_MALFORMED, - FIXTURE_NORMAL, - FIXTURE_STALE, - FIXTURE_SUPPRESSED, - FIXTURE_UNAVAILABLE, - FIXTURE_ZERO_PERCENT, -} from './peer-progress-indicator.fixtures'; - -describe('PPI Unit Summary Compatibility Expectations', () => { - // Basic Input Expectations - it('component must accept all valid safe-state fixtures', () => { - const validFixtures = [ - FIXTURE_NORMAL, - FIXTURE_ZERO_PERCENT, - FIXTURE_SUPPRESSED, - FIXTURE_UNAVAILABLE, - FIXTURE_DISABLED, - FIXTURE_STALE, - ]; - - validFixtures.forEach((f) => { - expect(f).toHaveProperty('submittedPercentage'); - expect(f).toHaveProperty('isSuppressed'); - expect(f).toHaveProperty('isFeatureEnabled'); - expect(f).toHaveProperty('unavailableMessage'); - }); - }); - - // Comparison Expectations - it('normal fixture must show student and cohort progress separately', () => { - expect(FIXTURE_NORMAL.submittedPercentage).toBeGreaterThan(0); - expect(FIXTURE_NORMAL.isSuppressed).toBe(false); - }); - - it('0% fixture must be distinguishable from suppressed/unavailable', () => { - expect(FIXTURE_ZERO_PERCENT.submittedPercentage).toBe(0); - expect(FIXTURE_ZERO_PERCENT.isSuppressed).toBe(false); - expect(FIXTURE_ZERO_PERCENT.unavailableMessage).toBe(''); - }); - - it('suppressed fixture must hide cohort progress and show safe wording', () => { - expect(FIXTURE_SUPPRESSED.submittedPercentage).toBeNull(); - expect(FIXTURE_SUPPRESSED.unavailableMessage).toContain('Not enough students'); - }); - - it('unavailable fixture must hide cohort progress but not be suppressed', () => { - expect(FIXTURE_UNAVAILABLE.submittedPercentage).toBeNull(); - expect(FIXTURE_UNAVAILABLE.isSuppressed).toBe(false); - expect(FIXTURE_UNAVAILABLE.unavailableMessage).toContain('Progress unavailable'); - }); - - it('disabled fixture must hide progress and mark feature disabled', () => { - expect(FIXTURE_DISABLED.submittedPercentage).toBeNull(); - expect(FIXTURE_DISABLED.isFeatureEnabled).toBe(false); - }); - - it('stale fixture must be treated as a safe state', () => { - expect(FIXTURE_STALE.isStale).toBe(true); - }); - - // Privacy Expectations - it('component must not expose peer identities or raw cohort counts', () => { - const fixtures = [ - FIXTURE_NORMAL, - FIXTURE_ZERO_PERCENT, - FIXTURE_SUPPRESSED, - FIXTURE_UNAVAILABLE, - FIXTURE_DISABLED, - FIXTURE_STALE, - ]; - - fixtures.forEach((f) => { - expect(f).not.toHaveProperty('peerName'); - expect(f).not.toHaveProperty('studentId'); - expect(f).not.toHaveProperty('cohortCount'); - expect(f).not.toHaveProperty('marks'); - expect(f).not.toHaveProperty('feedback'); - }); - }); - - // Malformed Expectations - it('component must reject or safely handle malformed fixture', () => { - const malformed = FIXTURE_MALFORMED as Partial<Record<string, unknown>>; - - expect(malformed.submittedPercentage).toBeNaN(); - expect(typeof malformed.targetGrade).toBe('string'); - }); - - // Layout (logic only) Expectations - it('component must remain understandable without relying on colour alone', () => { - // This is a logic placeholder — real UI tests will be added in PPI-F02 - expect(true).toBe(true); - }); - - it('component must support narrow and desktop layouts (logic placeholder)', () => { - expect(true).toBe(true); - }); -}); From a91026d2486032191dc6a0cd8a65a68b5b348a88 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Mon, 17 Aug 2026 17:45:26 +1000 Subject: [PATCH 1345/1531] fix(dashboard): address task search review feedback --- .../f-cross-dashboard.component.spec.ts | 90 +++++++++++++++++-- .../dashboard/f-cross-dashboard.component.ts | 87 ++++++++++++++---- 2 files changed, 149 insertions(+), 28 deletions(-) diff --git a/src/app/dashboard/f-cross-dashboard.component.spec.ts b/src/app/dashboard/f-cross-dashboard.component.spec.ts index 19c0a907a9..709d79af1f 100644 --- a/src/app/dashboard/f-cross-dashboard.component.spec.ts +++ b/src/app/dashboard/f-cross-dashboard.component.spec.ts @@ -233,6 +233,70 @@ describe('CrossDashboardComponent', () => { } }); + it('does not confuse Australian dates that contain the same numbers in another order', () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('December Task', 'DEC', 'not_started', new Date(2026, 11, 8)), + ]), + ]); + + component.setSearch(1, '12/08/2026'); + expect(component.displayedUnits[0].tasks).toEqual([]); + + component.setSearch(1, '08/12/2026'); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['DEC']); + }); + + it('matches subtitle and description text shown on the task card', () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Individual Retrospective', '5.1P', 'not_started', new Date(2026, 7, 12)), + ]), + ]); + + component.setSearch(1, 'Pass'); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['5.1P']); + + component.setSearch(1, 'description'); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['5.1P']); + + component.setSearch(1, 'not shown anywhere'); + expect(component.displayedUnits[0].tasks).toEqual([]); + }); + + it('keeps punctuation-only input visible without filtering tasks', async () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Individual Retrospective', '5.1P', 'not_started', new Date(2026, 7, 12)), + makeTask('Leadership Report', '5.3D', 'not_started', new Date(2026, 7, 18)), + ]), + ]); + + await syncView(); + + const searchInput = fixture.nativeElement.querySelector( + 'input[type="search"]', + ) as HTMLInputElement; + + searchInput.value = 'retro'; + searchInput.dispatchEvent(new Event('input', {bubbles: true})); + await syncView(); + + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['5.1P']); + + searchInput.value = '-'; + searchInput.dispatchEvent(new Event('input', {bubbles: true})); + await syncView(); + + expect(component.getSearchTerm(1)).toBe('-'); + expect(component.hasSearchTerm(1)).toBe(false); + expect(searchInput.value).toBe('-'); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + '5.1P', + '5.3D', + ]); + }); + it('clears the search and restores the original task list', () => { projectsSubject.next([ makeProject(1, 'SIT764', true, [ @@ -256,26 +320,34 @@ describe('CrossDashboardComponent', () => { it('combines search with the Hide Completed filter', () => { projectsSubject.next([ makeProject(1, 'SIT764', true, [ - makeTask('Completed Task', '1.1P', 'complete', new Date(2026, 7, 10)), - makeTask('Open Task', '1.2P', 'not_started', new Date(2026, 7, 12)), + makeTask('Completed Security Review', '1.1P', 'complete', new Date(2026, 7, 10)), + makeTask('Open Security Review', '1.2P', 'not_started', new Date(2026, 7, 12)), + makeTask('Open Calendar Review', '1.3P', 'not_started', new Date(2026, 7, 14)), ]), ]); - component.setSearch(1, 'task'); - component.toggleFilter(1, component.filterOptions[0]); + component.setSearch(1, 'security'); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + '1.1P', + '1.2P', + ]); + component.toggleFilter(1, component.filterOptions[0]); expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['1.2P']); component.setSearch(1, ''); - - expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['1.2P']); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + '1.2P', + '1.3P', + ]); }); it('preserves Due Date sorting after search is applied', () => { projectsSubject.next([ makeProject(1, 'SIT764', true, [ - makeTask('Later Task', 'LATE', 'not_started', new Date(2026, 7, 20)), - makeTask('Earlier Task', 'EARLY', 'not_started', new Date(2026, 7, 10)), + makeTask('Later Security Review', 'LATE', 'not_started', new Date(2026, 7, 20)), + makeTask('Calendar Setup', 'OTHER', 'not_started', new Date(2026, 7, 5)), + makeTask('Earlier Security Review', 'EARLY', 'not_started', new Date(2026, 7, 10)), ]), ]); @@ -286,7 +358,7 @@ describe('CrossDashboardComponent', () => { } component.setSort(1, dueDateSort); - component.setSearch(1, 'task'); + component.setSearch(1, 'security'); expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ 'EARLY', diff --git a/src/app/dashboard/f-cross-dashboard.component.ts b/src/app/dashboard/f-cross-dashboard.component.ts index 961ee708cc..45bd487bf2 100644 --- a/src/app/dashboard/f-cross-dashboard.component.ts +++ b/src/app/dashboard/f-cross-dashboard.component.ts @@ -112,14 +112,7 @@ export class CrossDashboardComponent implements OnInit { } setSearch(project: number, value: string): void { - const searchTerm = value ?? ''; - - if (this.normaliseSearchText(searchTerm).length === 0) { - this.searchTerms.delete(project); - } else { - this.searchTerms.set(project, searchTerm); - } - + this.searchTerms.set(project, value ?? ''); this.processTasks(); } @@ -201,18 +194,36 @@ export class CrossDashboardComponent implements OnInit { return 0; }), })); + + this.changeDetectorRef.markForCheck(); } private taskMatchesSearch(task: DashboardTask, projectId: number): boolean { - const searchTerm = this.normaliseSearchText(this.getSearchTerm(projectId)); + const rawSearchTerm = this.getSearchTerm(projectId); + const searchTerm = this.normaliseSearchText(rawSearchTerm); if (!searchTerm) { return true; } + const {numericDates, remainingText} = this.extractNumericDateSearches(rawSearchTerm); + const taskDate = this.formatDateAsIso(task.dueDate); + + if (numericDates.some((date) => date !== taskDate)) { + return false; + } + + const remainingSearchTerm = this.normaliseSearchText(remainingText); + + if (!remainingSearchTerm) { + return numericDates.length > 0; + } + const searchableText = this.normaliseSearchText( [ task.title, + task.subtitle, + task.description, task.abbreviation, task.statusLabel, task.unitCode, @@ -220,7 +231,37 @@ export class CrossDashboardComponent implements OnInit { ].join(' '), ); - return searchTerm.split(' ').every((term) => searchableText.includes(term)); + return remainingSearchTerm.split(' ').every((term) => searchableText.includes(term)); + } + + private extractNumericDateSearches(value: string): { + numericDates: string[]; + remainingText: string; + } { + const numericDates: string[] = []; + let remainingText = value; + + remainingText = remainingText.replace( + /\b(\d{4})-(\d{1,2})-(\d{1,2})\b/g, + (_match: string, year: string, month: string, day: string) => { + numericDates.push(this.normaliseNumericDate(year, month, day)); + return ' '; + }, + ); + + remainingText = remainingText.replace( + /\b(\d{1,2})\/(\d{1,2})\/(\d{4})\b/g, + (_match: string, day: string, month: string, year: string) => { + numericDates.push(this.normaliseNumericDate(year, month, day)); + return ' '; + }, + ); + + return {numericDates, remainingText}; + } + + private normaliseNumericDate(year: string, month: string, day: string): string { + return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`; } private normaliseSearchText(value: string): string { @@ -230,20 +271,28 @@ export class CrossDashboardComponent implements OnInit { .trim(); } - private formatDateForSearch(date: Date): string { + private formatDateAsIso(date: Date): string { if (!(date instanceof Date) || Number.isNaN(date.getTime())) { return ''; } - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); + return this.normaliseNumericDate( + String(date.getFullYear()), + String(date.getMonth() + 1), + String(date.getDate()), + ); + } + + private formatDateForSearch(date: Date): string { + const isoDate = this.formatDateAsIso(date); + + if (!isoDate) { + return ''; + } + + const [year, month, day] = isoDate.split('-'); - return [ - displayedDueDateFormatter.format(date), - `${day}/${month}/${year}`, - `${year}-${month}-${day}`, - ].join(' '); + return [displayedDueDateFormatter.format(date), `${day}/${month}/${year}`, isoDate].join(' '); } private getUnitsForCurrentScope(): DashboardUnit[] { From e6d37b6bce8acaabb90cd8f41bf79a82f468e820 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Tue, 18 Aug 2026 12:47:53 +1000 Subject: [PATCH 1346/1531] fix(ppi): safely extend burndown with peer median --- src/app/api/models/peer-progress.ts | 26 +- src/app/api/services/peer-progress.service.ts | 38 ++- .../spec/peer-progress.service.spec.ts | 35 +++ .../ppi-progress-calculation.service.ts | 7 +- .../progress-burndown-chart.component.html | 28 +- .../progress-burndown-chart.component.spec.ts | 273 ++++++++++++++++++ .../progress-burndown-chart.component.ts | 230 +++++++++++---- 7 files changed, 539 insertions(+), 98 deletions(-) create mode 100644 src/app/api/services/spec/peer-progress.service.spec.ts create mode 100644 src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts diff --git a/src/app/api/models/peer-progress.ts b/src/app/api/models/peer-progress.ts index e4b137437e..8e70cdd25b 100644 --- a/src/app/api/models/peer-progress.ts +++ b/src/app/api/models/peer-progress.ts @@ -1,19 +1,33 @@ export interface PeerMedianPoint { date: string; + /** * Median proportion of target task weight still remaining across the cohort, - * 0..1. This is the same scale the burndown's own series use before they are - * converted to a percentage for display. + * from 0 to 1. This matches the scale used by the existing burndown series + * before those values are converted into percentages for display. */ remaining: number; } +/** + * A safe display state returned by the authorised backend or frontend adapter. + * + * The browser must not receive a raw cohort size and decide whether a cohort is + * large enough. That privacy decision belongs at the trusted data boundary. + */ +export type PeerProgressState = 'ready' | 'suppressed' | 'unavailable' | 'disabled'; + export interface PeerProgressResponse { project_id: number; - /** The median covers students in this unit targeting this same grade. */ + + /** The comparison applies to this selected target grade. */ target_grade: number; - /** How many students the median was taken across. */ - cohort_size: number; - /** One point per week, on the same weekly grid the burndown plots. */ + + /** Privacy-safe state; no raw cohort size is returned to the component. */ + state: PeerProgressState; + + /** + * Anonymous median points. This must be empty unless state is ready. + */ median_burndown: PeerMedianPoint[]; } diff --git a/src/app/api/services/peer-progress.service.ts b/src/app/api/services/peer-progress.service.ts index 85a3b1d244..9183204be9 100644 --- a/src/app/api/services/peer-progress.service.ts +++ b/src/app/api/services/peer-progress.service.ts @@ -1,6 +1,6 @@ import {Injectable} from '@angular/core'; import {Observable, of} from 'rxjs'; -import {PeerMedianPoint, PeerProgressResponse} from '../models/peer-progress'; +import {PeerMedianPoint, PeerProgressResponse, PeerProgressState} from '../models/peer-progress'; import {Project} from '../models/project'; import {MappingFunctions} from './mapping-fn'; @@ -14,33 +14,31 @@ export class PeerProgressService { ]; /** - * The chart's insufficient-cohort state is - * displayed by dropping this below 'MINIMUM_COHORT_SIZE' + * Temporary proof-of-concept state. + * + * The future authorised backend must decide whether the result is ready, + * suppressed, unavailable or disabled. It must not send the raw cohort size + * to the browser. */ - private static readonly MOCK_COHORT_SIZE = 24; + private static readonly MOCK_STATE: PeerProgressState = 'ready'; - private static readonly MOCK_MY_PROGRESS = [ - 1.0, 1.0, 0.97, 0.97, 0.88, 0.88, 0.74, 0.7, 0.62, 0.55, 0.48, 0.4, 0.28, 0.18, 0.08, 0.02, 0.0, - ]; + public getCohortMedian( + project: Project, + targetGrade: number = project.targetGrade, + ): Observable<PeerProgressResponse> { + const state = PeerProgressService.MOCK_STATE; - public getCohortMedian(project: Project): Observable<PeerProgressResponse> { return of({ project_id: project.id, - target_grade: project.targetGrade, - cohort_size: PeerProgressService.MOCK_COHORT_SIZE, - median_burndown: this.sampleProfile(project, PeerProgressService.MOCK_WEEKLY_REMAINING), + target_grade: targetGrade, + state, + median_burndown: + state === 'ready' + ? this.sampleProfile(project, PeerProgressService.MOCK_WEEKLY_REMAINING) + : [], }); } - /** - * This line has a real source already -- `Project.refreshBurndownChartData()` computes it from - * the student's own tasks. Delete this method and `MOCK_MY_PROGRESS` once the - * chart no longer needs demo data; nothing needs to replace them. - */ - public getMyProgressMock(project: Project): Observable<PeerMedianPoint[]> { - return of(this.sampleProfile(project, PeerProgressService.MOCK_MY_PROGRESS)); - } - private sampleProfile(project: Project, profile: number[]): PeerMedianPoint[] { const weeks = MappingFunctions.step( project.unit.startDate.getTime(), diff --git a/src/app/api/services/spec/peer-progress.service.spec.ts b/src/app/api/services/spec/peer-progress.service.spec.ts new file mode 100644 index 0000000000..64fccf0687 --- /dev/null +++ b/src/app/api/services/spec/peer-progress.service.spec.ts @@ -0,0 +1,35 @@ +import {describe, expect, it} from 'vitest'; +import {firstValueFrom} from 'rxjs'; +import {Project} from '../../models/project'; +import {PeerProgressService} from '../peer-progress.service'; + +describe('PeerProgressService', () => { + it('returns a safe demo state without exposing raw cohort size', async () => { + const project = { + id: 42, + targetGrade: 2, + unit: { + startDate: new Date(2026, 6, 1), + endDate: new Date(2026, 7, 31), + }, + } as unknown as Project; + + const service = new PeerProgressService(); + + const response = await firstValueFrom(service.getCohortMedian(project, 3)); + + expect(response).toMatchObject({ + project_id: 42, + target_grade: 3, + state: 'ready', + }); + + expect(Object.keys(response)).not.toContain('cohort_size'); + + expect(response.median_burndown.length).toBeGreaterThan(0); + + expect( + response.median_burndown.every((point) => point.remaining >= 0 && point.remaining <= 1), + ).toBe(true); + }); +}); diff --git a/src/app/common/services/ppi-progress-calculation.service.ts b/src/app/common/services/ppi-progress-calculation.service.ts index d159015dd1..ff0bb0ec80 100644 --- a/src/app/common/services/ppi-progress-calculation.service.ts +++ b/src/app/common/services/ppi-progress-calculation.service.ts @@ -1,7 +1,4 @@ -export function calculateCompletionPercentage( - completed: number, - available: number -): number | null { +export function calculateCompletionPercentage(completed: number, available: number): number | null { if ( !Number.isFinite(completed) || !Number.isFinite(available) || @@ -17,7 +14,7 @@ export function calculateCompletionPercentage( export function calculateProgressComparison( studentPercentage: number, - cohortPercentage: number | null + cohortPercentage: number | null, ): number | null { if ( cohortPercentage === null || diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index adf8a80080..424746b707 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -23,22 +23,42 @@ </ngx-charts-line-chart> </div> - <!-- Check for peerMedianState --> - @if (peerMedianState !== 'ready') { + @if (peerMedianState === 'ready') { + <div class="flex items-center justify-center gap-2 pt-2 text-sm opacity-70" role="note"> + <mat-icon inline>science</mat-icon> + <span> + Peer median (demo) uses anonymous aggregate sample data for this proof of concept. + </span> + </div> + } @else { <div class="flex items-center justify-center gap-2 pt-2 text-sm opacity-70" role="status"> @switch (peerMedianState) { @case ('loading') { <mat-spinner color="accent" diameter="16"></mat-spinner> <span>Loading peer comparison…</span> } - @case ('insufficient') { + + @case ('suppressed') { <mat-icon inline>group_off</mat-icon> - <span>Too few students are targeting this grade to show an anonymous peer median.</span> + <span> + Peer comparison is hidden because the anonymous cohort threshold was not met. + </span> } + @case ('unavailable') { <mat-icon inline>cloud_off</mat-icon> <span>Peer median is unavailable right now.</span> } + + @case ('disabled') { + <mat-icon inline>visibility_off</mat-icon> + <span>Peer comparison is disabled for this unit.</span> + } + + @case ('error') { + <mat-icon inline>error_outline</mat-icon> + <span>Peer median could not be loaded. Please try again later.</span> + } } </div> } diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts new file mode 100644 index 0000000000..82db93df15 --- /dev/null +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts @@ -0,0 +1,273 @@ +import {beforeAll, describe, expect, it, vi} from 'vitest'; +import {Injector, LOCALE_ID, SimpleChange, ViewContainerRef} from '@angular/core'; +import {Subject, of, throwError} from 'rxjs'; +import { + PeerProgressResponse, + PeerProgressService, + PeerProgressState, + Project, +} from 'src/app/api/models/doubtfire-model'; +import {AppInjector, setAppInjector} from 'src/app/app-injector'; +import {ProgressBurndownChartComponent} from './progress-burndown-chart.component'; + +describe('ProgressBurndownChartComponent peer comparison', () => { + const EXISTING_SERIES = ['Target', 'Projected', 'To Submit', 'To Complete']; + + beforeAll(() => { + if (!AppInjector) { + setAppInjector( + Injector.create({ + providers: [ + { + provide: LOCALE_ID, + useValue: 'en-US', + }, + ], + }), + ); + } + }); + + function makeProject(): Project { + const startDate = new Date(2026, 6, 1); + const endDate = new Date(2026, 7, 31); + + return { + id: 123, + targetGrade: 2, + unit: { + startDate, + endDate, + }, + burndownChartData: [ + { + key: 'Target', + values: [ + [startDate.getTime(), 1], + [endDate.getTime(), 0], + ], + }, + { + key: 'Projected', + values: [ + [startDate.getTime(), 0.9], + [endDate.getTime(), 0.1], + ], + }, + { + key: 'To Submit', + values: [ + [startDate.getTime(), 0.8], + [endDate.getTime(), 0.2], + ], + }, + { + key: 'To Complete', + values: [ + [startDate.getTime(), 0.7], + [endDate.getTime(), 0.3], + ], + }, + ], + refreshBurndownChartData: vi.fn(), + } as unknown as Project; + } + + function makeResponse( + project: Project, + state: PeerProgressState, + targetGrade: number = project.targetGrade, + ): PeerProgressResponse { + return { + project_id: project.id, + target_grade: targetGrade, + state, + median_burndown: + state === 'ready' + ? [ + { + date: project.unit.startDate.toISOString(), + remaining: 0.75, + }, + { + date: project.unit.endDate.toISOString(), + remaining: 0.25, + }, + ] + : [], + }; + } + + function makeHarness(getCohortMedian: ReturnType<typeof vi.fn>): { + component: ProgressBurndownChartComponent; + project: Project; + } { + const project = makeProject(); + + const component = new ProgressBurndownChartComponent( + {} as ViewContainerRef, + { + getCohortMedian, + } as unknown as PeerProgressService, + ); + + component.project = project; + component.unit = project.unit; + component.grade = project.targetGrade; + + return { + component, + project, + }; + } + + function initialise(component: ProgressBurndownChartComponent): void { + // Angular calls ngOnChanges before ngOnInit for initial inputs. + component.ngOnChanges({ + grade: new SimpleChange(undefined, component.grade, true), + }); + + component.ngOnInit(); + } + + function seriesNames(component: ProgressBurndownChartComponent): string[] { + return component.data.map((series) => series.name); + } + + function expectOnlyExistingSeries(component: ProgressBurndownChartComponent): void { + expect(seriesNames(component)).toEqual(EXISTING_SERIES); + } + + it('makes one initial request and keeps the real lines while loading', () => { + const request: Subject<PeerProgressResponse> = new Subject(); + const getCohortMedian = vi.fn().mockReturnValue(request.asObservable()); + + const {component, project} = makeHarness(getCohortMedian); + + initialise(component); + + expect(getCohortMedian).toHaveBeenCalledTimes(1); + expect(getCohortMedian).toHaveBeenCalledWith(project, 2); + expect(project.refreshBurndownChartData).toHaveBeenCalledTimes(1); + expect(component.peerMedianState).toBe('loading'); + expectOnlyExistingSeries(component); + + component.ngOnDestroy(); + }); + + it('appends the demo median without replacing existing lines', () => { + const getCohortMedian = vi.fn(); + const {component, project} = makeHarness(getCohortMedian); + + getCohortMedian.mockReturnValue(of(makeResponse(project, 'ready'))); + + initialise(component); + + expect(component.peerMedianState).toBe('ready'); + expect(seriesNames(component)).toEqual([...EXISTING_SERIES, 'Peer median (demo)']); + + const peerSeries = component.data.find((series) => series.name === 'Peer median (demo)'); + + expect(peerSeries?.series.map((point) => point.value)).toEqual([75, 25]); + }); + + it('withholds the median when the response is suppressed', () => { + const getCohortMedian = vi.fn(); + const {component, project} = makeHarness(getCohortMedian); + + getCohortMedian.mockReturnValue(of(makeResponse(project, 'suppressed'))); + + initialise(component); + + expect(component.peerMedianState).toBe('suppressed'); + expectOnlyExistingSeries(component); + }); + + it('keeps the existing lines when peer data is unavailable', () => { + const getCohortMedian = vi.fn(); + const {component, project} = makeHarness(getCohortMedian); + + getCohortMedian.mockReturnValue(of(makeResponse(project, 'unavailable'))); + + initialise(component); + + expect(component.peerMedianState).toBe('unavailable'); + expectOnlyExistingSeries(component); + }); + + it('keeps the existing lines when peer comparison is disabled', () => { + const getCohortMedian = vi.fn(); + const {component, project} = makeHarness(getCohortMedian); + + getCohortMedian.mockReturnValue(of(makeResponse(project, 'disabled'))); + + initialise(component); + + expect(component.peerMedianState).toBe('disabled'); + expectOnlyExistingSeries(component); + }); + + it('shows an error state without removing the existing lines', () => { + const getCohortMedian = vi.fn().mockReturnValue(throwError(() => new Error('network down'))); + + const {component} = makeHarness(getCohortMedian); + + initialise(component); + + expect(component.peerMedianState).toBe('error'); + expectOnlyExistingSeries(component); + }); + + it('does not mutate the source burndown data while redrawing', () => { + const getCohortMedian = vi.fn(); + const {component, project} = makeHarness(getCohortMedian); + + getCohortMedian.mockReturnValue(of(makeResponse(project, 'ready'))); + + const sourceBefore = JSON.stringify(project.burndownChartData); + + initialise(component); + component.updateData(); + + expect(JSON.stringify(project.burndownChartData)).toBe(sourceBefore); + }); + + it('cancels the old grade request and only applies the current result', () => { + const firstRequest: Subject<PeerProgressResponse> = new Subject(); + const secondRequest: Subject<PeerProgressResponse> = new Subject(); + + const getCohortMedian = vi + .fn() + .mockReturnValueOnce(firstRequest.asObservable()) + .mockReturnValueOnce(secondRequest.asObservable()); + + const {component, project} = makeHarness(getCohortMedian); + + initialise(component); + + project.targetGrade = 3; + component.grade = 3; + + component.ngOnChanges({ + grade: new SimpleChange(2, 3, false), + }); + + expect(getCohortMedian).toHaveBeenCalledTimes(2); + expect(getCohortMedian).toHaveBeenNthCalledWith(2, project, 3); + expect(component.peerMedianState).toBe('loading'); + expectOnlyExistingSeries(component); + + // This must have no effect because its subscription was cancelled. + firstRequest.next(makeResponse(project, 'ready', 2)); + + expect(component.peerMedianState).toBe('loading'); + expectOnlyExistingSeries(component); + + secondRequest.next(makeResponse(project, 'ready', 3)); + + expect(component.peerMedianState).toBe('ready'); + expect(seriesNames(component)).toEqual([...EXISTING_SERIES, 'Peer median (demo)']); + + component.ngOnDestroy(); + }); +}); diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts index 100dcdf9ad..9355f21208 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts @@ -6,13 +6,17 @@ import { Input, LOCALE_ID, OnChanges, + OnDestroy, OnInit, SimpleChanges, ViewContainerRef, } from '@angular/core'; +import {Subscription} from 'rxjs'; import { PeerMedianPoint, + PeerProgressResponse, PeerProgressService, + PeerProgressState, Project, Unit, } from 'src/app/api/models/doubtfire-model'; @@ -29,14 +33,7 @@ interface BurndownSeries { series: BurndownPoint[]; } -type PeerMedianState = 'loading' | 'ready' | 'unavailable' | 'insufficient'; - -/** - * Fewest students the median may be drawn from. Below this a "middle student" is - * identifiable enough that the comparison stops being anonymous. The endpoint has - * to enforce this too; the check here only decides what to render. - */ -const MINIMUM_COHORT_SIZE = 5; +type PeerMedianState = 'loading' | 'error' | PeerProgressState; @Component({ selector: 'f-progress-burndown-chart', @@ -47,7 +44,7 @@ const MINIMUM_COHORT_SIZE = 5; }) export class ProgressBurndownChartComponent extends ChartBaseComponent - implements OnChanges, OnInit + implements OnChanges, OnDestroy, OnInit { @Input() project: Project; @Input() unit: Unit; @@ -56,7 +53,7 @@ export class ProgressBurndownChartComponent data: BurndownSeries[] = []; temp: BurndownSeries[] = []; - // options + // Chart options legend: boolean = true; showLabels: boolean = true; animations: boolean = true; @@ -67,22 +64,26 @@ export class ProgressBurndownChartComponent xAxisLabel: string = 'Time'; yAxisLabel: string = 'Tasks Remaining'; legendPosition: LegendPosition = LegendPosition.Below; + colorScheme: Color = { name: 'Burndown', selectable: true, group: ScaleType.Ordinal, - // My progress, Peer median. - domain: ['#E01B5D', '#0079d8'], + // Target, Projected, To Submit, To Complete, Peer median (demo). + domain: ['#AAAAAA', '#777777', '#0079d8', '#E01B5D', '#7C3AED', 'transparent'], }; + yScaleMin: number = 0; yScaleMax: number = 100; - /** Drives the status note under the chart. Read by the template. */ + /** Drives the privacy-safe status message below the chart. */ peerMedianState: PeerMedianState = 'loading'; private seriesVisibility: Record<string, boolean> = {}; private peerMedian: PeerMedianPoint[] = []; - private myProgress: PeerMedianPoint[] = []; + private activePeerMedianRequest?: Subscription; + private peerMedianRequestVersion: number = 0; + private initialised: boolean = false; constructor( public viewContainerRef: ViewContainerRef, @@ -94,52 +95,114 @@ export class ProgressBurndownChartComponent } ngOnInit(): void { + this.initialised = true; + this.project.refreshBurndownChartData(); this.updateData(); + this.data.forEach((item) => { this.seriesVisibility[item.name] = true; }); + this.loadPeerMedian(); } ngOnChanges(changes: SimpleChanges): void { - if ('grade' in changes && changes.grade.currentValue !== undefined) { - this.project.refreshBurndownChartData(); - this.updateData(); - // The cohort is the students on this target grade, so it moves with it. - this.loadPeerMedian(); + const gradeChange = changes.grade; + + // Angular calls ngOnChanges before ngOnInit. Ignore that first call so the + // initial peer request is made exactly once from ngOnInit. + if ( + !this.initialised || + !gradeChange || + gradeChange.firstChange || + gradeChange.currentValue === undefined || + gradeChange.currentValue === gradeChange.previousValue + ) { + return; } + + this.project.refreshBurndownChartData(); + this.updateData(); + + // The comparison cohort changes when the selected target grade changes. + this.loadPeerMedian(); + } + + ngOnDestroy(): void { + this.peerMedianRequestVersion++; + this.activePeerMedianRequest?.unsubscribe(); } private loadPeerMedian(): void { + const requestVersion = ++this.peerMedianRequestVersion; + const requestedProjectId = this.project.id; + const requestedGrade = this.grade ?? this.project.targetGrade; + + // Remove the old peer line immediately and cancel the previous request. + // This prevents an old grade result from overwriting the current grade. + this.activePeerMedianRequest?.unsubscribe(); + this.peerMedianState = 'loading'; this.peerMedian = []; + this.updateData(); + + this.activePeerMedianRequest = this.peerProgressService + .getCohortMedian(this.project, requestedGrade) + .subscribe({ + next: (response) => { + if (requestVersion !== this.peerMedianRequestVersion) { + return; + } + + // Fail safely if an adapter returns data for a different project or + // grade than the one currently displayed. + if ( + response.project_id !== requestedProjectId || + response.target_grade !== requestedGrade + ) { + this.peerMedian = []; + this.peerMedianState = 'unavailable'; + this.updateData(); + return; + } + + this.applyPeerMedianResponse(response); + this.updateData(); + }, + + error: () => { + if (requestVersion !== this.peerMedianRequestVersion) { + return; + } - this.peerProgressService.getCohortMedian(this.project).subscribe({ - next: (response) => { - if (response.cohort_size < MINIMUM_COHORT_SIZE) { - // Withhold the line rather than identify the few students behind it. - this.peerMedianState = 'insufficient'; - } else if (response.median_burndown.length === 0) { + this.peerMedian = []; + this.peerMedianState = 'error'; + this.updateData(); + }, + }); + } + + private applyPeerMedianResponse(response: PeerProgressResponse): void { + this.peerMedian = []; + + switch (response.state) { + case 'ready': + if (response.median_burndown.length === 0) { this.peerMedianState = 'unavailable'; - } else { - this.peerMedian = response.median_burndown; - this.peerMedianState = 'ready'; + return; } - this.updateData(); - }, - error: () => { - this.peerMedianState = 'unavailable'; - this.updateData(); - }, - }); - // Demo data. See PeerProgressService.getMyProgressMock -- the real source for - // this line is the 'To Complete' series in this.project.burndownChartData. - this.peerProgressService.getMyProgressMock(this.project).subscribe((points) => { - this.myProgress = points; - this.updateData(); - }); + this.peerMedian = [...response.median_burndown]; + this.peerMedianState = 'ready'; + return; + + case 'suppressed': + case 'unavailable': + case 'disabled': + this.peerMedianState = response.state; + return; + } } updateData(): void { @@ -149,18 +212,49 @@ export class ProgressBurndownChartComponent const endDate: Date = this.project.unit.endDate; if (!chartData) { + this.temp = []; this.data = []; return; } - const formattedData: BurndownSeries[] = []; + // Preserve the existing OnTrack burndown series. New chart values are + // created instead of changing project.burndownChartData in place. + const formattedData: BurndownSeries[] = chartData.map((series) => ({ + name: series.key, + series: series.values + .filter((value) => value[0] >= startDate.getTime() && value[0] <= endDate.getTime()) + .map((value) => ({ + name: formatDate(new Date(value[0]), 'd MMM', locale), + value: Math.round(Math.max(0, value[1]) * 100), + })), + })); + + // Keep the existing workaround for the chart's y-axis bounds. + const target = formattedData.find((series) => series.name === 'Target'); + + if (target) { + const start = target.series.find( + (point) => point.name === formatDate(new Date(startDate), 'd MMM', locale), + ); + + const end = target.series.find( + (point) => point.name === formatDate(new Date(endDate), 'd MMM', locale), + ); - if (this.myProgress.length > 0) { - formattedData.push(this.toSeries('My progress', this.myProgress, startDate, endDate, locale)); + if (start) { + start.value = 100; + } + + if (end) { + end.value = 0; + } } - if (this.peerMedian.length > 0) { - formattedData.push(this.toSeries('Peer median', this.peerMedian, startDate, endDate, locale)); + // This label is intentionally explicit while the adapter uses mock data. + if (this.peerMedianState === 'ready' && this.peerMedian.length > 0) { + formattedData.push( + this.toSeries('Peer median (demo)', this.peerMedian, startDate, endDate, locale), + ); } this.temp = JSON.parse(JSON.stringify(formattedData)); @@ -179,6 +273,7 @@ export class ProgressBurndownChartComponent series: points .filter((point) => { const time = new Date(point.date).getTime(); + return time >= startDate.getTime() && time <= endDate.getTime(); }) .map((point) => ({ @@ -189,23 +284,31 @@ export class ProgressBurndownChartComponent } onSelect(event: string | BurndownPoint): void { - if (this.isLegend(event)) { - const tempData = JSON.parse(JSON.stringify(this.data)); - if (this.isDataShown(event)) { - tempData.forEach((series) => { - if (series.name === event) { - series.series.forEach((point) => (point.value = 0)); - } - }); - } else { - const originalSeries = this.temp.find((series) => series.name === event); - const seriesIndex = tempData.findIndex((series) => series.name === event); - if (seriesIndex >= 0) { - tempData[seriesIndex] = JSON.parse(JSON.stringify(originalSeries)); + if (!this.isLegend(event)) { + return; + } + + const tempData: BurndownSeries[] = JSON.parse(JSON.stringify(this.data)); + + if (this.isDataShown(event)) { + tempData.forEach((series) => { + if (series.name === event) { + series.series.forEach((point) => { + point.value = 0; + }); } + }); + } else { + const originalSeries = this.temp.find((series) => series.name === event); + + const seriesIndex = tempData.findIndex((series) => series.name === event); + + if (originalSeries && seriesIndex >= 0) { + tempData[seriesIndex] = JSON.parse(JSON.stringify(originalSeries)); } - this.data = tempData; } + + this.data = tempData; } isLegend(event: string | BurndownPoint): event is string { @@ -213,11 +316,12 @@ export class ProgressBurndownChartComponent } isDataShown(name: string): boolean { - const series = this.data.find((series) => series.name === name); - return series && series.series.some((point) => point.value !== 0); + return Boolean( + this.data.find((series) => series.name === name)?.series.some((point) => point.value !== 0), + ); } - public formatPerc(input: number) { + public formatPerc(input: number): string { return `${input}%`; } } From 8e574addb775103424f8923df65e19ae66ed701e Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Tue, 18 Aug 2026 16:00:25 +1000 Subject: [PATCH 1347/1531] fix(ppi): improve burndown responsive layout --- .../progress-burndown-chart.component.html | 58 +++++-- .../progress-burndown-chart.component.scss | 148 ++++++++++++++++++ .../progress-burndown-chart.component.spec.ts | 31 ++++ .../progress-burndown-chart.component.ts | 26 ++- 4 files changed, 242 insertions(+), 21 deletions(-) diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index 424746b707..f19cd9753b 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -1,10 +1,8 @@ -<div class="flex h-full min-h-[320px] flex-col pb-6"> - <div class="chart-container flex min-h-0 flex-1"> +<div class="progress-burndown"> + <div class="progress-burndown__chart"> <ngx-charts-line-chart - class="progress-burndown-chart h-full flex-1" + class="progress-burndown-chart" [legend]="legend" - [legendPosition]="legendPosition" - [legendTitle]="''" [results]="data" [scheme]="colorScheme" [showXAxisLabel]="showXAxisLabel" @@ -23,15 +21,43 @@ </ngx-charts-line-chart> </div> + @if (data.length > 0) { + <div + aria-label="Burndown chart series visibility" + class="progress-burndown__legend" + role="group" + > + @for (series of data; track series.name; let index = $index) { + <button + class="progress-burndown__legend-item" + type="button" + [attr.aria-pressed]="isDataShown(series.name)" + [attr.title]="'Show or hide ' + series.name" + [class.progress-burndown__legend-item--hidden]="!isDataShown(series.name)" + (click)="onSelect(series.name)" + > + <span + aria-hidden="true" + class="progress-burndown__legend-swatch" + [style.background-color]="seriesColors[index] || '#777777'" + ></span> + + <span class="progress-burndown__legend-label"> + {{ series.name }} + </span> + </button> + } + </div> + } + @if (peerMedianState === 'ready') { - <div class="flex items-center justify-center gap-2 pt-2 text-sm opacity-70" role="note"> - <mat-icon inline>science</mat-icon> - <span> - Peer median (demo) uses anonymous aggregate sample data for this proof of concept. - </span> + <div class="progress-burndown__message" role="note"> + <mat-icon aria-hidden="true">science</mat-icon> + + <span> Demo peer median: anonymous aggregate sample data, not live cohort data. </span> </div> } @else { - <div class="flex items-center justify-center gap-2 pt-2 text-sm opacity-70" role="status"> + <div aria-live="polite" class="progress-burndown__message" role="status"> @switch (peerMedianState) { @case ('loading') { <mat-spinner color="accent" diameter="16"></mat-spinner> @@ -39,25 +65,25 @@ } @case ('suppressed') { - <mat-icon inline>group_off</mat-icon> + <mat-icon aria-hidden="true">group_off</mat-icon> <span> Peer comparison is hidden because the anonymous cohort threshold was not met. </span> } @case ('unavailable') { - <mat-icon inline>cloud_off</mat-icon> + <mat-icon aria-hidden="true">cloud_off</mat-icon> <span>Peer median is unavailable right now.</span> } @case ('disabled') { - <mat-icon inline>visibility_off</mat-icon> + <mat-icon aria-hidden="true">visibility_off</mat-icon> <span>Peer comparison is disabled for this unit.</span> } @case ('error') { - <mat-icon inline>error_outline</mat-icon> - <span>Peer median could not be loaded. Please try again later.</span> + <mat-icon aria-hidden="true">error_outline</mat-icon> + <span> Peer median could not be loaded. Please try again later. </span> } } </div> diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.scss b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.scss index e69de29bb2..fa286533dd 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.scss +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.scss @@ -0,0 +1,148 @@ +:host { + display: block; + width: 100%; + min-width: 0; +} + +.progress-burndown { + display: grid; + width: 100%; + min-width: 0; + gap: 0.75rem; + padding-bottom: 1rem; +} + +.progress-burndown__chart { + width: 100%; + min-width: 0; + height: clamp(20rem, 30vw, 26rem); +} + +.progress-burndown-chart { + display: block; + width: 100%; + height: 100%; + min-width: 0; +} + +.progress-burndown__legend { + display: flex; + flex-wrap: wrap; + align-items: stretch; + gap: 0.5rem; + width: 100%; + min-width: 0; +} + +.progress-burndown__legend-item { + display: inline-flex; + align-items: center; + gap: 0.45rem; + min-width: 0; + max-width: 100%; + padding: 0.4rem 0.6rem; + border: 1px solid rgba(127, 127, 127, 0.35); + border-radius: 0.4rem; + background: rgba(127, 127, 127, 0.08); + color: inherit; + font: inherit; + line-height: 1.25; + cursor: pointer; + + &:hover { + background: rgba(127, 127, 127, 0.16); + } + + &:focus-visible { + outline: 2px solid currentColor; + outline-offset: 2px; + } +} + +.progress-burndown__legend-item--hidden { + opacity: 0.55; + + .progress-burndown__legend-label { + text-decoration: line-through; + } +} + +.progress-burndown__legend-swatch { + width: 0.8rem; + height: 0.8rem; + flex: 0 0 0.8rem; + border-radius: 0.2rem; +} + +.progress-burndown__legend-label { + min-width: 0; + overflow-wrap: anywhere; + text-align: left; +} + +.progress-burndown__message { + display: flex; + align-items: flex-start; + gap: 0.5rem; + width: 100%; + min-width: 0; + box-sizing: border-box; + padding: 0.65rem 0.75rem; + border-radius: 0.45rem; + background: rgba(127, 127, 127, 0.1); + font-size: 0.875rem; + line-height: 1.4; + overflow-wrap: anywhere; + + > span { + flex: 1 1 auto; + min-width: 0; + } + + mat-icon, + mat-spinner { + flex: 0 0 auto; + margin-top: 0.05rem; + } + + mat-icon { + width: 1.25rem; + height: 1.25rem; + font-size: 1.25rem; + line-height: 1.25rem; + } +} + +@media (max-width: 639px) { + .progress-burndown { + gap: 0.65rem; + } + + .progress-burndown__chart { + height: 20rem; + } + + .progress-burndown__legend { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0.4rem; + } + + .progress-burndown__legend-item { + width: 100%; + + &:last-child:nth-child(odd) { + grid-column: 1 / -1; + } + } +} + +@media (max-width: 379px) { + .progress-burndown__legend { + grid-template-columns: minmax(0, 1fr); + } + + .progress-burndown__legend-item:last-child:nth-child(odd) { + grid-column: auto; + } +} diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts index 82db93df15..0917526001 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts @@ -270,4 +270,35 @@ describe('ProgressBurndownChartComponent peer comparison', () => { component.ngOnDestroy(); }); + it('hides axis titles on narrow screens', () => { + const {component} = makeHarness(vi.fn()); + const originalWidth = window.innerWidth; + + try { + Object.defineProperty(window, 'innerWidth', { + configurable: true, + value: 639, + }); + + component.onViewportResize(); + + expect(component.showXAxisLabel).toBe(false); + expect(component.showYAxisLabel).toBe(false); + + Object.defineProperty(window, 'innerWidth', { + configurable: true, + value: 640, + }); + + component.onViewportResize(); + + expect(component.showXAxisLabel).toBe(true); + expect(component.showYAxisLabel).toBe(true); + } finally { + Object.defineProperty(window, 'innerWidth', { + configurable: true, + value: originalWidth, + }); + } + }); }); diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts index 9355f21208..5bf186ecde 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts @@ -1,8 +1,9 @@ -import {Color, LegendPosition, ScaleType} from '@swimlane/ngx-charts'; +import {Color, ScaleType} from '@swimlane/ngx-charts'; import {formatDate} from '@angular/common'; import { ChangeDetectionStrategy, Component, + HostListener, Input, LOCALE_ID, OnChanges, @@ -54,7 +55,7 @@ export class ProgressBurndownChartComponent temp: BurndownSeries[] = []; // Chart options - legend: boolean = true; + legend: boolean = false; showLabels: boolean = true; animations: boolean = true; xAxis: boolean = true; @@ -63,14 +64,14 @@ export class ProgressBurndownChartComponent showXAxisLabel: boolean = true; xAxisLabel: string = 'Time'; yAxisLabel: string = 'Tasks Remaining'; - legendPosition: LegendPosition = LegendPosition.Below; + + readonly seriesColors: string[] = ['#AAAAAA', '#777777', '#0079d8', '#E01B5D', '#7C3AED']; colorScheme: Color = { name: 'Burndown', selectable: true, group: ScaleType.Ordinal, - // Target, Projected, To Submit, To Complete, Peer median (demo). - domain: ['#AAAAAA', '#777777', '#0079d8', '#E01B5D', '#7C3AED', 'transparent'], + domain: this.seriesColors, }; yScaleMin: number = 0; @@ -96,6 +97,7 @@ export class ProgressBurndownChartComponent ngOnInit(): void { this.initialised = true; + this.updateResponsiveAxisLabels(); this.project.refreshBurndownChartData(); this.updateData(); @@ -129,11 +131,25 @@ export class ProgressBurndownChartComponent this.loadPeerMedian(); } + @HostListener('window:resize') + onViewportResize(): void { + this.updateResponsiveAxisLabels(); + } + ngOnDestroy(): void { this.peerMedianRequestVersion++; this.activePeerMedianRequest?.unsubscribe(); } + private updateResponsiveAxisLabels(): void { + const viewportWidth = typeof window === 'undefined' ? 1024 : window.innerWidth; + + const showAxisTitles = viewportWidth >= 640; + + this.showYAxisLabel = showAxisTitles; + this.showXAxisLabel = showAxisTitles; + } + private loadPeerMedian(): void { const requestVersion = ++this.peerMedianRequestVersion; const requestedProjectId = this.project.id; From 65465664462195e85b05aba38aa9cc68df221e6b Mon Sep 17 00:00:00 2001 From: David Tenni <davidctenni@gmail.com> Date: Tue, 18 Aug 2026 18:35:41 +1000 Subject: [PATCH 1348/1531] feat: add unit-level PPI adapter and view model for PPI-F01 --- .../peer-progress-unit-summary-state.spec.ts | 118 ++++++++++++++++++ .../peer-progress-unit-summary-state.ts | 49 ++++++++ .../api/models/peer-progress-unit-summary.ts | 16 +++ .../peer-progress-indicator.service.ts | 25 ++++ .../peer-progress-indicator.service.spec.ts | 41 ++++++ 5 files changed, 249 insertions(+) create mode 100644 src/app/api/models/peer-progress-unit-summary-state.spec.ts create mode 100644 src/app/api/models/peer-progress-unit-summary-state.ts create mode 100644 src/app/api/models/peer-progress-unit-summary.ts diff --git a/src/app/api/models/peer-progress-unit-summary-state.spec.ts b/src/app/api/models/peer-progress-unit-summary-state.spec.ts new file mode 100644 index 0000000000..ae1feda5e0 --- /dev/null +++ b/src/app/api/models/peer-progress-unit-summary-state.spec.ts @@ -0,0 +1,118 @@ +import {describe, expect, it} from 'vitest'; +import { + DISABLED_STATE, + NORMAL_STATE, + STALE_STATE, + SUPPRESSED_STATE, + UNAVAILABLE_STATE, + ZERO_PERCENT_STATE, +} from '../services/mock'; +import {PeerProgressUnitSummary} from './peer-progress-unit-summary'; +import {resolvePeerProgressUnitSummaryState} from './peer-progress-unit-summary-state'; + +// Builds a PeerProgressUnitSummary from one of the six shared cohort mock states, +// the same way PeerProgressIndicatorService.getUnitSummary() does. +function toUnitSummary( + cohort: + | typeof NORMAL_STATE + | typeof ZERO_PERCENT_STATE + | typeof SUPPRESSED_STATE + | typeof UNAVAILABLE_STATE + | typeof STALE_STATE + | typeof DISABLED_STATE, + studentPercentage: number | null, +): PeerProgressUnitSummary { + return { + unitId: cohort.unitId, + targetGrade: cohort.targetGrade, + studentPercentage, + submittedPercentage: cohort.submittedPercentage, + isSuppressed: cohort.isSuppressed, + isStale: cohort.isStale, + isFeatureEnabled: cohort.isFeatureEnabled, + lastUpdatedAt: cohort.lastUpdatedAt, + unavailableMessage: cohort.unavailableMessage, + }; +} + +describe('resolvePeerProgressUnitSummaryState', () => { + it('returns loading while the request is in flight, ignoring any data passed in', () => { + const result = resolvePeerProgressUnitSummaryState(true, null, toUnitSummary(NORMAL_STATE, 30)); + expect(result.state).toBe('loading'); + expect(result.data).toBeNull(); + }); + + it('returns error when the request fails, and does not leak the previous data', () => { + const result = resolvePeerProgressUnitSummaryState( + false, + new Error('network down'), + toUnitSummary(NORMAL_STATE, 30), + ); + expect(result.state).toBe('error'); + expect(result.data).toBeNull(); + }); + + it('returns success with the student and cohort percentages kept separate', () => { + const summary = toUnitSummary(NORMAL_STATE, 30); + const result = resolvePeerProgressUnitSummaryState(false, null, summary); + + expect(result.state).toBe('success'); + expect(result.data?.studentPercentage).toBe(30); + expect(result.data?.submittedPercentage).toBe(NORMAL_STATE.submittedPercentage); + }); + + it('returns no-data when the cohort genuinely has not submitted yet', () => { + const result = resolvePeerProgressUnitSummaryState( + false, + null, + toUnitSummary(ZERO_PERCENT_STATE, 0), + ); + expect(result.state).toBe('no-data'); + }); + + it('returns hidden with the safe message for a small, suppressed cohort', () => { + const result = resolvePeerProgressUnitSummaryState( + false, + null, + toUnitSummary(SUPPRESSED_STATE, 30), + ); + expect(result.state).toBe('hidden'); + expect(result.message).toBe(SUPPRESSED_STATE.unavailableMessage); + }); + + it('returns unavailable for a generically unavailable cohort response', () => { + const result = resolvePeerProgressUnitSummaryState( + false, + null, + toUnitSummary(UNAVAILABLE_STATE, 30), + ); + expect(result.state).toBe('unavailable'); + }); + + it('returns disabled when the unit has turned the feature off', () => { + const result = resolvePeerProgressUnitSummaryState( + false, + null, + toUnitSummary(DISABLED_STATE, 30), + ); + expect(result.state).toBe('disabled'); + expect(result.message).toBe(DISABLED_STATE.unavailableMessage); + }); + + it('returns stale without exposing a cohort percentage when data is outdated', () => { + const result = resolvePeerProgressUnitSummaryState(false, null, toUnitSummary(STALE_STATE, 30)); + + expect(result.state).toBe('stale'); + expect(result.data?.submittedPercentage).toBeNull(); + expect(result.message).toBe(STALE_STATE.unavailableMessage); + }); + + it('transitions from loading to success without carrying over a stale value', () => { + const loadingResult = resolvePeerProgressUnitSummaryState(true, null, null); + expect(loadingResult.data).toBeNull(); + + const summary = toUnitSummary(NORMAL_STATE, 30); + const successResult = resolvePeerProgressUnitSummaryState(false, null, summary); + expect(successResult.data).toEqual(summary); + }); +}); diff --git a/src/app/api/models/peer-progress-unit-summary-state.ts b/src/app/api/models/peer-progress-unit-summary-state.ts new file mode 100644 index 0000000000..53ae747d89 --- /dev/null +++ b/src/app/api/models/peer-progress-unit-summary-state.ts @@ -0,0 +1,49 @@ +import {PeerProgressUiState} from './peer-progress-indicator-state'; +import {PeerProgressUnitSummary} from './peer-progress-unit-summary'; + +export interface PeerProgressUnitSummaryViewModel { + state: PeerProgressUiState; + data: PeerProgressUnitSummary | null; + message: string | null; +} + +const GENERIC_ERROR_MESSAGE = 'Could not load peer progress. Please try again.'; + +// Same priority order as resolvePeerProgressState (peer-progress-indicator-state.ts) -- +// unit-level summaries resolve to the same UI states as the task-level widget, just +// over PeerProgressUnitSummary data instead of PeerProgressIndicator. +export function resolvePeerProgressUnitSummaryState( + loading: boolean, + error: unknown | null, + data: PeerProgressUnitSummary | null, +): PeerProgressUnitSummaryViewModel { + if (loading) { + return {state: 'loading', data: null, message: null}; + } + + if (error || !data) { + return {state: 'error', data: null, message: GENERIC_ERROR_MESSAGE}; + } + + if (!data.isFeatureEnabled) { + return {state: 'disabled', data, message: data.unavailableMessage}; + } + + if (data.isSuppressed) { + return {state: 'hidden', data, message: data.unavailableMessage}; + } + + if (data.isStale) { + return {state: 'stale', data, message: data.unavailableMessage}; + } + + if (data.submittedPercentage === null) { + return {state: 'unavailable', data, message: data.unavailableMessage}; + } + + if (data.submittedPercentage === 0) { + return {state: 'no-data', data, message: null}; + } + + return {state: 'success', data, message: null}; +} diff --git a/src/app/api/models/peer-progress-unit-summary.ts b/src/app/api/models/peer-progress-unit-summary.ts new file mode 100644 index 0000000000..d99a46e1a5 --- /dev/null +++ b/src/app/api/models/peer-progress-unit-summary.ts @@ -0,0 +1,16 @@ +import {PeerProgressIndicator} from './peer-progress-indicator'; + +/** + * Unit-level aggregate PPI summary: the requesting student's own progress next to + * the anonymous cohort aggregate for a unit's target grade. + * + * Reuses PeerProgressIndicator's fields as-is -- suppression, staleness, the feature + * flag, and safe messaging all mean the same thing at unit scope as they do at task + * scope. `studentPercentage` is the one genuinely missing field: the requesting + * student's own aggregate progress across the unit, needed so a unit-level summary + * can show "your progress" and "cohort progress" as separate, plainly labelled values. + * `taskDefinitionId` is dropped since a unit summary isn't scoped to a single task. + */ +export interface PeerProgressUnitSummary extends Omit<PeerProgressIndicator, 'taskDefinitionId'> { + studentPercentage: number | null; // null under the same conditions submittedPercentage is +} diff --git a/src/app/api/services/peer-progress-indicator.service.ts b/src/app/api/services/peer-progress-indicator.service.ts index 404a62e093..682a0185f6 100644 --- a/src/app/api/services/peer-progress-indicator.service.ts +++ b/src/app/api/services/peer-progress-indicator.service.ts @@ -1,6 +1,7 @@ import {Injectable} from '@angular/core'; import {Observable, of} from 'rxjs'; import {PeerProgressIndicator} from '../models/peer-progress-indicator'; +import {PeerProgressUnitSummary} from '../models/peer-progress-unit-summary'; import { DISABLED_STATE, NORMAL_STATE, @@ -34,6 +35,30 @@ export class PeerProgressIndicatorService { }); } + // Unit-level counterpart to getIndicator(): same six cohort states, scoped to a + // unit's target grade rather than one task, plus the student's own percentage -- + // the one field the cohort-only PeerProgressIndicator contract doesn't carry. + getUnitSummary( + unitId: number, + targetGrade: number, + studentPercentage: number | null, + state: 'normal' | 'zero' | 'suppressed' | 'unavailable' | 'stale' | 'disabled', + ): Observable<PeerProgressUnitSummary> { + const cohort = this.resolveState(state); + + return of({ + unitId, + targetGrade, + studentPercentage, + submittedPercentage: cohort.submittedPercentage, + isSuppressed: cohort.isSuppressed, + isStale: cohort.isStale, + isFeatureEnabled: cohort.isFeatureEnabled, + lastUpdatedAt: cohort.lastUpdatedAt, + unavailableMessage: cohort.unavailableMessage, + }); + } + private resolveState(state: string): PeerProgressIndicator { switch (state) { case 'normal': diff --git a/src/app/api/services/spec/peer-progress-indicator.service.spec.ts b/src/app/api/services/spec/peer-progress-indicator.service.spec.ts index 7e874ac5b6..9d91e63e29 100644 --- a/src/app/api/services/spec/peer-progress-indicator.service.spec.ts +++ b/src/app/api/services/spec/peer-progress-indicator.service.spec.ts @@ -102,4 +102,45 @@ describe('PeerProgressIndicatorService', () => { expect(result.targetGrade).toBe(0); }); }); + + describe('getUnitSummary', () => { + it('should keep the student and cohort percentages separate for a normal response', () => { + service.getUnitSummary(10, 2, 30, 'normal').subscribe((result) => { + expect(result.studentPercentage).toBe(30); + expect(result.submittedPercentage).toBe(NORMAL_STATE.submittedPercentage); + expect(result.isSuppressed).toBe(NORMAL_STATE.isSuppressed); + + expect(result.unitId).toBe(10); + expect(result.targetGrade).toBe(2); + }); + }); + + it('should not expose a task definition id -- a unit summary is not task-scoped', () => { + service.getUnitSummary(10, 2, 30, 'normal').subscribe((result) => { + expect((result as unknown as {taskDefinitionId?: number}).taskDefinitionId).toBeUndefined(); + }); + }); + + it('should return suppressed state with the safe message and no cohort percentage', () => { + service.getUnitSummary(30, 0, 30, 'suppressed').subscribe((result) => { + expect(result.submittedPercentage).toBe(SUPPRESSED_STATE.submittedPercentage); + expect(result.isSuppressed).toBe(true); + expect(result.unavailableMessage).toBe(SUPPRESSED_STATE.unavailableMessage); + expect(result.studentPercentage).toBe(30); + }); + }); + + it('should return disabled state when the unit has PPI turned off', () => { + service.getUnitSummary(60, 1, 30, 'disabled').subscribe((result) => { + expect(result.isFeatureEnabled).toBe(false); + expect(result.unavailableMessage).toBe(DISABLED_STATE.unavailableMessage); + }); + }); + + it('should preserve a null studentPercentage rather than substituting a default', () => { + service.getUnitSummary(10, 2, null, 'normal').subscribe((result) => { + expect(result.studentPercentage).toBeNull(); + }); + }); + }); }); From 000f9642e90bcf77f41aa9cee1c4abe1d8934dd0 Mon Sep 17 00:00:00 2001 From: dylancleal <dylancleal@gmail.com> Date: Thu, 6 Aug 2026 19:45:37 +1000 Subject: [PATCH 1349/1531] test(dashboard): add route/navigation tests for /dashboard (CPD-F01) --- .../dashboard/f-cross-dashboard.route.spec.ts | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/app/dashboard/f-cross-dashboard.route.spec.ts diff --git a/src/app/dashboard/f-cross-dashboard.route.spec.ts b/src/app/dashboard/f-cross-dashboard.route.spec.ts new file mode 100644 index 0000000000..b203a61a57 --- /dev/null +++ b/src/app/dashboard/f-cross-dashboard.route.spec.ts @@ -0,0 +1,93 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {provideRouter, Router} from '@angular/router'; +import {RouterTestingHarness} from '@angular/router/testing'; +import {TestBed} from '@angular/core/testing'; +import {BehaviorSubject, of} from 'rxjs'; +import {routes} from '../app.routes'; +import {AuthenticationService} from '../api/services/authentication.service'; +import {UserService} from '../api/services/user.service'; +import {GlobalStateService} from '../projects/states/index/global-state.service'; + +/** + * CPD-F01: route/navigation tests for the Cross-Project Dashboard (/dashboard). + * + * These tests exercise the actual route config (app.routes.ts) and the real + * roleWhitelistGuard, rather than testing CrossDashboardComponent in isolation, + * since the ticket is specifically about navigation behaviour at the route level. + */ + +describe('Cross-Project Dashboard route (/dashboard)', () => { + let authorised: boolean; + + const globalStateMock = { + isLoadingSubject: new BehaviorSubject<boolean>(false), + loadedUnitRoles: {currentValues: []}, + currentUserProjects: {values: of([])}, + onLoad: (run: () => void) => run(), + }; + + const userServiceMock = { + currentUser: {role: 'Student'}, + }; + + beforeEach(() => { + authorised = true; + + TestBed.configureTestingModule({ + providers: [ + provideRouter(routes), + { + provide: AuthenticationService, + useValue: {isAuthorised: () => authorised}, + }, + {provide: UserService, useValue: userServiceMock}, + {provide: GlobalStateService, useValue: globalStateMock}, + ], + }); + }); + + it('AC1: navigates directly to /dashboard for an authorised student', async () => { + const harness = await RouterTestingHarness.create('/dashboard'); + const router = TestBed.inject(Router); + + expect(router.url).toBe('/dashboard'); + expect(harness.routeNativeElement).toBeTruthy(); + }); + + it('AC2: re-navigating to /dashboard (simulated refresh) does not lose the route or throw', async () => { + const harness = await RouterTestingHarness.create('/dashboard'); + const router = TestBed.inject(Router); + expect(router.url).toBe('/dashboard'); + + // Re-navigating to the same URL stands in for a refresh, since a true + // full page reload can't be simulated inside RouterTestingHarness. + await harness.navigateByUrl('/dashboard'); + + expect(router.url).toBe('/dashboard'); + expect(harness.routeNativeElement).toBeTruthy(); + }); + + it('AC3: redirects to /unauthorised instead of crashing when the role check fails', async () => { + authorised = false; + + const harness = await RouterTestingHarness.create('/dashboard'); + const router = TestBed.inject(Router); + + expect(router.url).toBe('/unauthorised'); + expect(harness.routeNativeElement).toBeTruthy(); + }); + + it('AC4: current implementation does not persist Active/Previous/All scope in the URL (documented gap, not a fix)', async () => { + // f-cross-dashboard.component.ts has no ActivatedRoute / queryParams handling + // as of this branch, so there is nothing to restore on navigation. Asserting + // the route has no query params here to make that gap explicit and catch it + // if a later "Show previous units" implementation starts using the URL. + const harness = await RouterTestingHarness.create('/dashboard?scope=previous'); + const router = TestBed.inject(Router); + + expect(router.url).toBe('/dashboard?scope=previous'); + // Scope is preserved in the URL by the router itself, but nothing in the + // component currently reads it back out - see test note for detail. + expect(harness.routeNativeElement).toBeTruthy(); + }); +}); From 24f8736f34757d59f168f1d79ef107e2be7d75f3 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Tue, 18 Aug 2026 20:10:33 +1000 Subject: [PATCH 1350/1531] test(dashboard): address route review feedback --- .../dashboard/f-cross-dashboard.route.spec.ts | 88 +++++++++---------- 1 file changed, 41 insertions(+), 47 deletions(-) diff --git a/src/app/dashboard/f-cross-dashboard.route.spec.ts b/src/app/dashboard/f-cross-dashboard.route.spec.ts index b203a61a57..eda2482605 100644 --- a/src/app/dashboard/f-cross-dashboard.route.spec.ts +++ b/src/app/dashboard/f-cross-dashboard.route.spec.ts @@ -1,23 +1,22 @@ -import {beforeEach, describe, expect, it} from 'vitest'; -import {provideRouter, Router} from '@angular/router'; -import {RouterTestingHarness} from '@angular/router/testing'; +import {beforeEach, describe, expect, it, vi} from 'vitest'; import {TestBed} from '@angular/core/testing'; +import {Router, provideRouter} from '@angular/router'; +import {RouterTestingHarness} from '@angular/router/testing'; import {BehaviorSubject, of} from 'rxjs'; -import {routes} from '../app.routes'; import {AuthenticationService} from '../api/services/authentication.service'; +import {ProjectService} from '../api/services/project.service'; import {UserService} from '../api/services/user.service'; +import {routes} from '../app.routes'; import {GlobalStateService} from '../projects/states/index/global-state.service'; -/** - * CPD-F01: route/navigation tests for the Cross-Project Dashboard (/dashboard). - * - * These tests exercise the actual route config (app.routes.ts) and the real - * roleWhitelistGuard, rather than testing CrossDashboardComponent in isolation, - * since the ticket is specifically about navigation behaviour at the route level. - */ - describe('Cross-Project Dashboard route (/dashboard)', () => { - let authorised: boolean; + const userServiceMock = { + currentUser: {role: 'Student'}, + }; + + const isAuthorisedMock = vi.fn((roleWhitelist: string[], role?: string) => { + return role !== undefined && roleWhitelist.includes(role); + }); const globalStateMock = { isLoadingSubject: new BehaviorSubject<boolean>(false), @@ -26,68 +25,63 @@ describe('Cross-Project Dashboard route (/dashboard)', () => { onLoad: (run: () => void) => run(), }; - const userServiceMock = { - currentUser: {role: 'Student'}, + const projectServiceMock = { + query: vi.fn().mockReturnValue(of([])), }; beforeEach(() => { - authorised = true; + userServiceMock.currentUser.role = 'Student'; + isAuthorisedMock.mockClear(); + projectServiceMock.query.mockClear(); TestBed.configureTestingModule({ providers: [ provideRouter(routes), { provide: AuthenticationService, - useValue: {isAuthorised: () => authorised}, + useValue: {isAuthorised: isAuthorisedMock}, + }, + { + provide: UserService, + useValue: userServiceMock, + }, + { + provide: GlobalStateService, + useValue: globalStateMock, + }, + { + provide: ProjectService, + useValue: projectServiceMock, }, - {provide: UserService, useValue: userServiceMock}, - {provide: GlobalStateService, useValue: globalStateMock}, ], }); }); - it('AC1: navigates directly to /dashboard for an authorised student', async () => { + it('AC1: allows a Student to navigate directly to /dashboard', async () => { const harness = await RouterTestingHarness.create('/dashboard'); const router = TestBed.inject(Router); expect(router.url).toBe('/dashboard'); expect(harness.routeNativeElement).toBeTruthy(); + expect(isAuthorisedMock).toHaveBeenCalledTimes(1); + expect(isAuthorisedMock).toHaveBeenCalledWith(['Student'], 'Student'); }); - it('AC2: re-navigating to /dashboard (simulated refresh) does not lose the route or throw', async () => { - const harness = await RouterTestingHarness.create('/dashboard'); - const router = TestBed.inject(Router); - expect(router.url).toBe('/dashboard'); - - // Re-navigating to the same URL stands in for a refresh, since a true - // full page reload can't be simulated inside RouterTestingHarness. - await harness.navigateByUrl('/dashboard'); - - expect(router.url).toBe('/dashboard'); - expect(harness.routeNativeElement).toBeTruthy(); - }); - - it('AC3: redirects to /unauthorised instead of crashing when the role check fails', async () => { - authorised = false; + it('AC3: redirects a non-whitelisted Tutor to /unauthorised', async () => { + userServiceMock.currentUser.role = 'Tutor'; const harness = await RouterTestingHarness.create('/dashboard'); const router = TestBed.inject(Router); expect(router.url).toBe('/unauthorised'); expect(harness.routeNativeElement).toBeTruthy(); + expect(isAuthorisedMock).toHaveBeenCalledTimes(1); + expect(isAuthorisedMock).toHaveBeenCalledWith(['Student'], 'Tutor'); }); - it('AC4: current implementation does not persist Active/Previous/All scope in the URL (documented gap, not a fix)', async () => { - // f-cross-dashboard.component.ts has no ActivatedRoute / queryParams handling - // as of this branch, so there is nothing to restore on navigation. Asserting - // the route has no query params here to make that gap explicit and catch it - // if a later "Show previous units" implementation starts using the URL. - const harness = await RouterTestingHarness.create('/dashboard?scope=previous'); - const router = TestBed.inject(Router); + // RouterTestingHarness performs client-side navigation. It does not restart + // the browser or Angular application, so real refresh coverage belongs in + // a future browser-level end-to-end test. - expect(router.url).toBe('/dashboard?scope=previous'); - // Scope is preserved in the URL by the router itself, but nothing in the - // component currently reads it back out - see test note for detail. - expect(harness.routeNativeElement).toBeTruthy(); - }); + it.todo('AC4: restores component.unitScope from the URL once URL-backed scope is implemented'); }); From c5b379d801d88c2114bbee148a818b717ff20ccf Mon Sep 17 00:00:00 2001 From: David Tenni <davidctenni@gmail.com> Date: Tue, 18 Aug 2026 21:28:22 +1000 Subject: [PATCH 1351/1531] docs: apply review feedback to PPI help-text pack --- docs/ppi-help-text-pack.md | 68 ++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/docs/ppi-help-text-pack.md b/docs/ppi-help-text-pack.md index d8493998b7..6dd7f4738b 100644 --- a/docs/ppi-help-text-pack.md +++ b/docs/ppi-help-text-pack.md @@ -1,14 +1,26 @@ -# PPI Help-Text & Privacy Copy Pack (Draft) +# PPI-D01: Task-Level Help Text and Privacy Copy -**Status:** first-pass draft for human review — wording is not final, expect it to be rewritten. -**Ticket:** PPI help-text & privacy copy (branch `docs/ppi-help-privacy`, based on `feature/peer-progress-indicator`) +**Ticket:** PPI-D01 — Write the peer-comparison explanation, privacy limits and help text +**Branch:** `docs/ppi-help-privacy`, based on `feature/peer-progress-indicator` *(recommended base branch, not independently confirmed with the team — confirm before merge)* **Scope:** content/copy only. No widget logic, states, or data flow were changed to produce this doc. --- -## 0. Answer to the open question this ticket depends on +## Acceptance criteria coverage -**Does a unit-level PPI view exist? No.** +| # | Criterion | Status | +|---|---|---| +| 1 | Label, tooltip, and expanded explanation for task-level and unit-level views | Task-level: met (§3). Unit-level: not applicable — confirmed no unit-level view exists in the codebase (§0) | +| 2 | Explain the value is an anonymous aggregate, not an individual ranking | Met — shared framing in §1, echoed in state-specific copy | +| 3 | Wording for small-cohort suppression, unavailable data, and delayed/stale data | Met (§3.3, §3.4, §3.5) | +| 4 | Plain language, no wording that could shame or pressure students | Met — reassurance framing present across label/tooltip/explanation for every state where a null, zero, or hidden result could otherwise read as evaluative | +| 5 | Map each text block to an exact UI location, plus one annotated screenshot | Location map: met (§2). Annotated screenshot: pending — manual step, not part of this document | + +--- + +## 0. Scope: Task-Level Only — No Unit-Level PPI View Exists + +**Confirmed by repo search, not assumed.** Searched `src/app` for `PeerProgressIndicator`, `peer-progress`, `PpiWidget`, and `ppi-widget` (case-sensitive, to avoid false hits like "mapping" or "shipping" matching a naive case-insensitive `ppi` search). 12 files matched, all of them belonging to the single task-level widget and its supporting service/model/mock: @@ -33,12 +45,14 @@ A separate search of `src/app/units` (where a unit-level dashboard surface would --- -## 0.1 A second gap worth flagging before you read the drafts below +## 0.1 Implementation Note: Tooltip and Expanded-Explanation Text Have No UI Home Yet The ticket asks for a **label, tooltip, and expanded explanation** per state (three tiers of copy). The widget as it exists today (`ppi-widget.component.html`) only has **one visible text slot per state** — a single `<span>{{ view.message }}</span>` next to an icon. There is no `matTooltip` (or any tooltip mechanism) anywhere in this widget or its parent card, and no expandable/"learn more" panel. So the drafts below give you all three tiers of copy as requested, but only the "label" tier maps to something that renders today. The tooltip and expanded-explanation tiers are **content ready for a future implementation ticket** to wire up (e.g. `matTooltip` on the icon, and something like a `mat-expansion-panel` or info popover for the long-form text) — not something this documentation-only ticket should build. Flagging this now so it isn't a surprise later. +**Recommendation, applied throughout this doc:** treat Label as new UI — a small heading or icon label — added alongside the existing `{{ view.message }}` text, not a replacement for it. The message text is the data payload (the percentage, or the reason it's hidden); the Label names what the widget is, a separate concern. If a reviewer wants it to replace the current text instead, that's a one-line change at implementation time, not a reason to redo this doc. + --- ## 1. Shared framing (applies across every state) @@ -62,6 +76,8 @@ This sentence (or a close variant) is repeated in the states where a percentage | 5 | Stale (`stale`) | `@case ('stale')` | `ppi-widget.component.html:39-45` | `isStale === true` | | 6 | Disabled (`disabled`) | `@case ('disabled')` | `ppi-widget.component.html:21-25` | `isFeatureEnabled === false` | +*Line numbers reflect the file's state at time of writing and will drift if the widget is edited again — treat the `@case` name as the durable reference, line numbers as a point-in-time aid only.* + Widget mount point: `f-ppi-widget` is rendered inside `f-task-description-card`, immediately after `f-task-date-slider`, gated by `showPeerProgress` — `task-description-card.component.html:16-18`. @@ -71,7 +87,7 @@ Not covered by the six acceptance-criterion states, but present in the actual st --- -## 3. Draft copy, state by state +## 3. Copy, state by state ### 3.1 Normal — peers have submitted @@ -90,10 +106,10 @@ Not covered by the six acceptance-criterion states, but present in the actual st **Current copy source:** hardcoded client-side string, `"No peer submissions yet"` (`ZERO_PERCENT_STATE.unavailableMessage` is actually an empty string — the component ignores it and shows its own fallback text instead; flagged as an open design question during PPI-F03, still unresolved) - **Label:** Peer progress -- **Tooltip:** No peers aiming for your target grade have submitted this task yet. +- **Tooltip:** No peers have submitted yet — not a reflection of your own progress. - **Expanded explanation:** No one aiming for the same grade as you has submitted this task yet. This isn't feedback on your own progress — it just means the group total is currently zero, and it may change as others submit. -*Rationale:* explicitly disclaims that a zero reads as evaluative. Avoids "yet" doing too much implicit-pressure work by pairing it with the explicit non-evaluative framing. +*Rationale:* explicitly disclaims that a zero reads as evaluative, now in both the tooltip and the expanded explanation rather than the expanded explanation alone. **Flag:** worth deciding, separately from this ticket, whether this state should read `unavailableMessage` from the API like every other state does (currently it's the only one of the six with copy hardcoded in the template rather than data-driven). @@ -116,10 +132,10 @@ Not covered by the six acceptance-criterion states, but present in the actual st **Current copy source:** `unavailableMessage` = `"Progress unavailable."` - **Label:** Peer progress unavailable -- **Tooltip:** Peer progress data isn't available right now. +- **Tooltip:** Peer progress data isn't available right now — not a reflection of your own progress. - **Expanded explanation:** Peer progress information isn't available for this task right now. This is a data issue, not a reflection of your own progress — check back later. -*Rationale:* explicit "data issue, not a progress issue" framing per the starting principles, so a blank state doesn't read as an implicit signal about the student's own standing. +*Rationale:* explicit "data issue, not a progress issue" framing per the starting principles, now present in both tiers rather than the expanded explanation alone. --- @@ -128,7 +144,7 @@ Not covered by the six acceptance-criterion states, but present in the actual st **Current copy source:** `unavailableMessage` = `"Peer progress is currently unavailable."` (reused generic wording) plus a separate hardcoded badge, `"Data may be outdated"` - **Label:** Peer progress — data outdated -- **Tooltip:** Peer progress data hasn't refreshed recently and isn't shown right now. +- **Tooltip:** Peer progress data hasn't refreshed recently — not a reflection of your own progress. - **Expanded explanation:** Peer progress data hasn't updated recently, so it isn't being shown right now rather than risk showing an out-of-date figure. This is a data timing issue, not a reflection of your own progress — check back later for a current number. *Rationale:* Note the current implementation (`ppi-widget.component.html:39-45`, `peer-progress-indicator-state.ts:43-44`) never actually renders a percentage in this state, even if one exists in the underlying data — the stale check happens before the percentage check, so only the message + badge show. Copy above is written to match what actually renders (no number implied). **Flag:** worth asking the team whether that's intentional; if a stale percentage should ever be shown (e.g. "42% (as of 3 days ago)"), the copy would need to change along with the logic — out of scope for this ticket either way. @@ -162,18 +178,22 @@ Six widget-state screenshots exist from PPI-F03's verification pass (saved local | Stale state | §3.5 | | Disabled state | §3.6 | -Annotation itself (drawing labels onto the image) is manual/outside this session per the ticket's step 8 — this table just maps which shot goes with which copy block. +Annotation itself (drawing labels onto the image) is manual/outside this session — this table just maps which shot goes with which copy block. --- -## 5. Things I wasn't confident about / left for review - -1. **Zero state's data source** (§3.2 flag) — hardcoded vs. API-driven, pre-existing open question from PPI-F03, not resolved here. -2. **Stale state's actual rendered content** (§3.5 flag) — confirmed by reading the code that no percentage renders in this state today; flagging in case that's not the intended long-term behavior. -3. **Tooltip/expanded-explanation UI hooks don't exist yet** (§0.1) — this doc's tooltip and expanded-explanation tiers are copy-in-waiting, not copy for something you can click on today. -4. **Base branch** — used `feature/peer-progress-indicator` per the handover doc's recommendation; not independently confirmed with the team. -5. **Deliverable format** — produced this as a standalone markdown spec doc only (option (a) from the handover's open question #3). No widget `.html`/`.ts` template strings or `unavailableMessage` values were changed. If the ticket actually wants the real strings updated too (option (b) or (c)), that's a separate, larger change this session did not make — confirm before that work starts. -6. **Pre-existing data-contract defect in already-merged PPI-F03 code — separate from this ticket, not fixed here.** `STALE_STATE` in `peer-progress-indicator.mock.ts:51-61` sets `submittedPercentage: null`. The interface comment on `PeerProgressIndicator.submittedPercentage` (`peer-progress-indicator.ts`) documents null as valid only "when suppressed/unavailable/disabled" — not stale. The mock violates its own type's documented contract. - - As it stands today this is **latent, not actively broken**: the `stale` template branch (`ppi-widget.component.html:39-45`) never interpolates `submittedPercentage` — it only renders `view.message` and the static "Data may be outdated" badge — so no "null%" currently reaches the screen. - - It becomes a live bug the moment either (a) the stale branch is changed to also show the percentage (something §3.5 above already flags as a plausible future UX improvement), or (b) any other code path reads `submittedPercentage` off a stale record assuming the interface comment's contract holds. - - Recommend a separate ticket/fix in the PPI-F03 codebase: either update the interface comment to include `isStale` among the valid-null cases, or update `STALE_STATE`'s mock (and whatever the real backend does) to carry a real percentage alongside `isStale: true`, consistent with "stale" meaning *old but present* data rather than *absent* data. +## 5. Recommendations for follow-up + +These are findings from reading the code while writing this doc, not uncertainty about the copy itself — the copy is complete. Each one is a decision or fix that belongs to someone other than this ticket. + +**For Maple / code review:** + +1. **Data-contract defect in already-merged PPI-F03 code.** `STALE_STATE` in `peer-progress-indicator.mock.ts` sets `submittedPercentage: null`, but the interface comment on `PeerProgressIndicator.submittedPercentage` documents null as valid only for suppressed/unavailable/disabled — not stale. Currently latent: the stale template branch never interpolates the percentage, so no "null%" reaches the screen today. Becomes a live bug the moment either the stale UI is enhanced to also show a number, or any other code reads `submittedPercentage` trusting that contract. **Recommend:** fix the mock to carry a real percentage alongside `isStale: true`, or update the interface comment to include `isStale` among the valid-null cases. + +2. **Zero state's message is hardcoded, not API-driven** — the only one of the six states where this is true. `ZERO_PERCENT_STATE.unavailableMessage` is an empty string; the component shows its own fallback instead. Pre-existing open question from PPI-F03, still unresolved. **Recommend:** decide whether the mock/backend should supply a real message here, matching how the other five states work. + +3. **Stale state's percentage is currently unreachable in the UI** — the `isStale` check fires before the percentage check in the resolver, so `view.data?.submittedPercentage` never renders even when present in the underlying data. Copy in §3.5 is written to match current behavior (no number implied). **Recommend:** if a stale-but-real number should ever display (e.g. "42% (as of 3 days ago)"), that's a template change; the copy would need a matching update at that time. + +**For whoever implements this doc's copy into the UI:** + +4. Tooltip and expanded-explanation UI don't exist yet (§0.1) — this is copy ready for a future implementation ticket, not something wired up today. \ No newline at end of file From 2995c55ab0f10b96d939ee7ada263d35dfa0d61f Mon Sep 17 00:00:00 2001 From: Thirus224849242 <s224849242@deakin.edu.au> Date: Wed, 19 Aug 2026 00:38:43 +1000 Subject: [PATCH 1352/1531] refactor: replace flex-layout with tailwind in extension-comment (#1187) --- .../extension-comment/extension-comment.component.html | 8 ++++---- tailwind.config.js | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/app/tasks/task-comments-viewer/extension-comment/extension-comment.component.html b/src/app/tasks/task-comments-viewer/extension-comment/extension-comment.component.html index 00af98e249..e5d5e305b7 100644 --- a/src/app/tasks/task-comments-viewer/extension-comment/extension-comment.component.html +++ b/src/app/tasks/task-comments-viewer/extension-comment/extension-comment.component.html @@ -1,20 +1,20 @@ -<div fxLayout="row" fxLayoutAlign="space-evenly center"> +<div class="flex flex-row items-center justify-evenly"> @if (comment.assessed) { - <div fxLayout="column" fxLayoutAlign="space-around center"> + <div class="flex flex-col items-center justify-around"> <hr class="hr-text" [attr.data-content]="message" /> <p class="fade-text"><strong> reason:</strong> {{ comment.text }}</p> </div> } @if (!comment.assessed) { - <div fxLayout="column" fxLayoutAlign="space-around center"> + <div class="flex flex-col items-center justify-around"> <hr class="hr-fade" /> <p> {{ message }} <br /> <strong> reason:</strong> {{ comment.text }} </p> @if (isNotStudent) { - <div fxLayout="row" fxLayoutAlign="space-evenly center"> + <div class="flex flex-row items-center justify-evenly"> <button color="primary" mat-flat-button diff --git a/tailwind.config.js b/tailwind.config.js index ca0e02b4f0..6b9f2e6f72 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -4,6 +4,12 @@ module.exports = { important: true, theme: { extend: { + screens: { + 'fl-sm': '600px', + 'fl-md': '960px', + 'fl-lg': '1280px', + 'fl-xl': '1920px', + }, colors: { 'formatif-blue': '#3939ff', 'formatif-blue-lighter': '#e7e7ff', From 854f9ce9ba5f100b0425996c3f5d7e248faa6b32 Mon Sep 17 00:00:00 2001 From: SandilBandara <sandilbandara@gmail.com> Date: Wed, 19 Aug 2026 01:00:08 +1000 Subject: [PATCH 1353/1531] fix(dashboard): apply responsive dashboard sizing fixes --- src/app/dashboard/f-cross-dashboard.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/dashboard/f-cross-dashboard.component.html b/src/app/dashboard/f-cross-dashboard.component.html index 22b4b9ded7..b76efd350e 100644 --- a/src/app/dashboard/f-cross-dashboard.component.html +++ b/src/app/dashboard/f-cross-dashboard.component.html @@ -1,6 +1,6 @@ <div class="panel-full-screen flex h-full flex-col"> <div class="shrink-0 px-16 pt-4"> - <mat-form-field appearance="outline" class="w-64"> + <mat-form-field appearance="outline" class="w-full max-w-64"> <mat-label>Unit scope</mat-label> <mat-select [value]="unitScope" (selectionChange)="setUnitScope($event.value)"> <mat-option value="active">Active units</mat-option> @@ -12,7 +12,7 @@ <div class="flex min-h-0 flex-1 flex-row gap-8 overflow-x-auto px-16 pb-4"> @for (unit of displayedUnits; track unit.projectId) { - <div class="flex h-full w-136 shrink-0 flex-col shadow"> + <div class="flex h-full w-128 shrink-0 flex-col shadow"> <div class="flex w-full shrink-0 flex-row items-center gap-4 rounded-t-lg p-4" [class.bg-formatif-blue]="!unit.isPrevious" @@ -32,7 +32,7 @@ <input autocomplete="off" - class="text-md h-full w-64 rounded-md p-2 px-4" + class="text-md h-full w-56 rounded-md p-2 px-4" placeholder="Search tasks..." type="search" [attr.aria-label]="'Search tasks in ' + unit.code" From 27805012ae4a69319b0f2ec37eba391fce426a58 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Wed, 19 Aug 2026 01:53:24 +1000 Subject: [PATCH 1354/1531] docs(ppi): complete PPI-D01 copy and wireframe --- .../ppi/ppi-d01-copy-location-wireframe.svg | 350 ++++++++++++++++ docs/ppi-help-text-pack.md | 388 +++++++++++------- 2 files changed, 594 insertions(+), 144 deletions(-) create mode 100644 docs/assets/ppi/ppi-d01-copy-location-wireframe.svg diff --git a/docs/assets/ppi/ppi-d01-copy-location-wireframe.svg b/docs/assets/ppi/ppi-d01-copy-location-wireframe.svg new file mode 100644 index 0000000000..c5593b8ee8 --- /dev/null +++ b/docs/assets/ppi/ppi-d01-copy-location-wireframe.svg @@ -0,0 +1,350 @@ +<svg + xmlns="http://www.w3.org/2000/svg" + width="1400" + height="900" + viewBox="0 0 1400 900" + role="img" + aria-labelledby="ppi-wireframe-title ppi-wireframe-description" +> + <title id="ppi-wireframe-title"> + Annotated copy-location wireframe for task-level and unit-level peer progress + + + Two privacy-safe mock Peer Progress Indicator cards. Number one marks the visible label, number + two marks an accessible help control, and number three marks the expanded explanation. The + task-level card is current and the unit-level card is a planned proof of concept. + + + + + + PPI-D01 copy-location wireframe + + + + Sanitised mock values only. Task-level is current; unit-level is planned. + + + + + A. Current task-level widget + + + + + + Peer task progress + + + + + 1 + + + + + ? + + + + + 2 + + + + 42% of peers at your target grade have submitted + + + + + + 42% + + + + + + This is one combined group percentage. It does not show names, individual results, + + + raw group size or rankings, and it does not assess your own work. + + + + + 3 + + + + + B. Planned PPI-F02 unit-level proof of concept + + + + + + Unit progress overview + + + + + 1 + + + + + ? + + + + + 2 + + + + My progress + + + + + 63% + + + + Anonymous group progress + + + + + 42% + + + + + + My progress and Anonymous group progress are separate values. The group value does + + + not show names, individual results, raw group size, marks, feedback or rankings. + + + + + 3 + + + + + Callouts + + + + + 1 + + + Visible label + + + + + 2 + + + Keyboard, touch and screen-reader accessible help control + + + + + 3 + + + Expanded explanation + + + + Based on the earlier unit-level PPI visual baseline by Umeda Ranuluge. Sanitised and updated for + PPI-D01 copy placement. No real student data is shown. + + diff --git a/docs/ppi-help-text-pack.md b/docs/ppi-help-text-pack.md index 6dd7f4738b..58c2482d18 100644 --- a/docs/ppi-help-text-pack.md +++ b/docs/ppi-help-text-pack.md @@ -1,199 +1,299 @@ -# PPI-D01: Task-Level Help Text and Privacy Copy +# PPI-D01: Peer Progress Help Text and Privacy Copy -**Ticket:** PPI-D01 — Write the peer-comparison explanation, privacy limits and help text -**Branch:** `docs/ppi-help-privacy`, based on `feature/peer-progress-indicator` *(recommended base branch, not independently confirmed with the team — confirm before merge)* -**Scope:** content/copy only. No widget logic, states, or data flow were changed to produce this doc. +**Ticket:** PPI-D01 - Write the peer-comparison explanation, privacy limits and help text +**Branch:** `docs/ppi-help-privacy` +**Scope:** Documentation and copy specification only. No production widget logic, API +behaviour or data flow is changed by this document. ---- +**Implementation status:** -## Acceptance criteria coverage - -| # | Criterion | Status | -|---|---|---| -| 1 | Label, tooltip, and expanded explanation for task-level and unit-level views | Task-level: met (§3). Unit-level: not applicable — confirmed no unit-level view exists in the codebase (§0) | -| 2 | Explain the value is an anonymous aggregate, not an individual ranking | Met — shared framing in §1, echoed in state-specific copy | -| 3 | Wording for small-cohort suppression, unavailable data, and delayed/stale data | Met (§3.3, §3.4, §3.5) | -| 4 | Plain language, no wording that could shame or pressure students | Met — reassurance framing present across label/tooltip/explanation for every state where a null, zero, or hidden result could otherwise read as evaluative | -| 5 | Map each text block to an exact UI location, plus one annotated screenshot | Location map: met (§2). Annotated screenshot: pending — manual step, not part of this document | - ---- - -## 0. Scope: Task-Level Only — No Unit-Level PPI View Exists - -**Confirmed by repo search, not assumed.** - -Searched `src/app` for `PeerProgressIndicator`, `peer-progress`, `PpiWidget`, and `ppi-widget` (case-sensitive, to avoid false hits like "mapping" or "shipping" matching a naive case-insensitive `ppi` search). 12 files matched, all of them belonging to the single task-level widget and its supporting service/model/mock: - -``` -src/app/projects/.../task-description-card/ppi-widget/ppi-widget.component.ts -src/app/projects/.../task-description-card/ppi-widget/ppi-widget.component.html -src/app/projects/.../task-description-card/ppi-widget/ppi-widget.component.spec.ts -src/app/projects/.../task-description-card/task-description-card.component.html -src/app/api/services/peer-progress-indicator.service.ts -src/app/api/services/spec/peer-progress-indicator.service.spec.ts -src/app/api/services/mock/peer-progress-indicator.mock.ts -src/app/api/services/mock/index.ts -src/app/api/models/peer-progress-indicator.ts -src/app/api/models/peer-progress-indicator-state.ts -src/app/api/models/peer-progress-indicator-state.spec.ts -src/app/doubtfire-angular.module.ts -``` - -A separate search of `src/app/units` (where a unit-level dashboard surface would live) for "peer" returned nothing. - -**Conclusion:** there is no unit-level PPI screen in this codebase yet. Acceptance criterion 1 asks for copy covering "both task-level and unit-level views" — the unit-level half is not achievable right now. This doc covers task-level only. **Recommend flagging back to whoever assigned the ticket** rather than inventing copy for a screen that doesn't exist — that would run against the ticket's own "do not redesign the PPI" instruction in spirit. - ---- - -## 0.1 Implementation Note: Tooltip and Expanded-Explanation Text Have No UI Home Yet +- The task-level location map is based on the current PPI widget. +- The unit-level copy is planned for the mock-backed PPI-F02 proof of concept. +- The unit-level section does not claim that a live unit-level component or API already + exists. +- Labels, help controls and expanded explanations still require a separate frontend + implementation. -The ticket asks for a **label, tooltip, and expanded explanation** per state (three tiers of copy). The widget as it exists today (`ppi-widget.component.html`) only has **one visible text slot per state** — a single `{{ view.message }}` next to an icon. There is no `matTooltip` (or any tooltip mechanism) anywhere in this widget or its parent card, and no expandable/"learn more" panel. - -So the drafts below give you all three tiers of copy as requested, but only the "label" tier maps to something that renders today. The tooltip and expanded-explanation tiers are **content ready for a future implementation ticket** to wire up (e.g. `matTooltip` on the icon, and something like a `mat-expansion-panel` or info popover for the long-form text) — not something this documentation-only ticket should build. Flagging this now so it isn't a surprise later. - -**Recommendation, applied throughout this doc:** treat Label as new UI — a small heading or icon label — added alongside the existing `{{ view.message }}` text, not a replacement for it. The message text is the data payload (the percentage, or the reason it's hidden); the Label names what the widget is, a separate concern. If a reviewer wants it to replace the current text instead, that's a one-line change at implementation time, not a reason to redo this doc. - ---- - -## 1. Shared framing (applies across every state) - -Per acceptance criterion 2 — every state's expanded explanation should reinforce, directly or by implication, that: - -> This number is a combined total across a group of students aiming for the same grade. It is never a list of names, never an individual comparison, and never a ranking. - -This sentence (or a close variant) is repeated in the states where a percentage is actually shown (Normal, Zero), since that's where a misreading-as-ranking risk is highest. - ---- - -## 2. Location map +## Acceptance criteria coverage -| # | State (mock key) | Widget template case | File : line | Trigger condition | -|---|---|---|---|---| -| 1 | Normal (`normal`) | `@case ('success')` | `ppi-widget.component.html:46-52` | `submittedPercentage` is a number > 0 | -| 2 | Zero (`zero`) | `@case ('no-data')` | `ppi-widget.component.html:33-38` | `submittedPercentage === 0` | -| 3 | Suppressed (`suppressed`) | `@case ('hidden')` | `ppi-widget.component.html:27-32` | `isSuppressed === true` | -| 4 | Unavailable (`unavailable`) | `@case ('unavailable')` | `ppi-widget.component.html:15-19` | `submittedPercentage === null` (and not suppressed/stale) | -| 5 | Stale (`stale`) | `@case ('stale')` | `ppi-widget.component.html:39-45` | `isStale === true` | -| 6 | Disabled (`disabled`) | `@case ('disabled')` | `ppi-widget.component.html:21-25` | `isFeatureEnabled === false` | +| Requirement | Result | Evidence | +| ----------------------------------------------------------------------- | ------ | -------------------------------------------------------------------- | +| Label, tooltip and expanded explanation for the task-level view | Met | Section 3 | +| Label, tooltip and expanded explanation for the planned unit-level view | Met | Section 4 | +| Explain that the result is an anonymous aggregate and not a ranking | Met | Section 1 and all visible-value states | +| Cover suppression, unavailable and stale data | Met | Sections 3 and 4 | +| Use plain language without shame or pressure | Met | All copy avoids ahead, behind, winning, losing and judgement wording | +| Map copy to exact current or planned UI locations | Met | Section 2 | +| Include one annotated screenshot or wireframe | Met | `assets/ppi/ppi-d01-copy-location-wireframe.svg` | -*Line numbers reflect the file's state at time of writing and will drift if the widget is edited again — treat the `@case` name as the durable reference, line numbers as a point-in-time aid only.* +## 1. Shared privacy and wellbeing rules -Widget mount point: `f-ppi-widget` is rendered inside `f-task-description-card`, immediately after `f-task-date-slider`, gated by `showPeerProgress` — -`task-description-card.component.html:16-18`. +These rules apply to both views: -Not covered by the six acceptance-criterion states, but present in the actual state machine (`peer-progress-indicator-state.ts`) — flagging for completeness, no copy drafted since they're outside the ticket's named scope: -- `loading` — `ppi-widget.component.html:2-7`, static text "Loading peer progress…" -- `error` — `ppi-widget.component.html:8-14`, generic text "Could not load peer progress. Please try again." plus a Retry button +1. A group result is shown as one combined percentage. +2. It must not display names, student IDs, project IDs, individual results, individual + task statuses, marks, feedback, raw group size or rankings. +3. A genuine `0%` is a real value. It must not be presented as missing, suppressed or + unavailable data. +4. A suppressed result explains that the group value is hidden for privacy without + revealing the exact group size. +5. Unavailable and stale states describe a data or timing condition. They must not sound + like feedback about the student's own work. +6. The wording must not describe the student as ahead, behind, better or worse than + anyone else. +7. The percentage is not a predicted grade or a judgement about the student's chance of + receiving a grade. +8. Student-facing text must not expose technical errors, internal identifiers or backend + details. ---- +This wording describes the intended display boundary. Backend authorisation, aggregation +and small-group suppression must still enforce that boundary. -## 3. Copy, state by state +## 2. Copy placement and accessibility -### 3.1 Normal — peers have submitted +### 2.1 Current task-level location -**Current copy source:** built from `submittedPercentage` — `"{X}% of peers at your target grade have submitted"` +- **Widget template:** `src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.html` +- **Parent mount location:** `src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/task-description-card.component.html` +- **State resolver:** `src/app/api/models/peer-progress-indicator-state.ts` +- **Current screen location:** inside the task description card, after the task date + controls. +- **State locations:** use the durable template cases rather than relying only on line + numbers: + - `@case ('success')` + - `@case ('no-data')` + - `@case ('hidden')` + - `@case ('unavailable')` + - `@case ('stale')` + - `@case ('disabled')` -- **Label:** Peer progress -- **Tooltip:** How many peers aiming for your target grade have submitted this task so far. -- **Expanded explanation:** This shows the combined share of students aiming for the same grade as you who have submitted this task. It's a single group number, not a list of names or a ranking — you can't see who specifically has or hasn't submitted. +The task-level copy should use the three numbered locations in the wireframe: -*Rationale:* states the number as a fact ("X% have submitted"), not a comparison ("you're behind X%"). No ahead/behind language. +1. A visible label naming the information. +2. A short tooltip or help summary opened from an accessible help control. +3. An expanded explanation in a popover, panel or other accessible disclosure. ---- +### 2.2 Planned unit-level location -### 3.2 Zero — no peers have submitted yet +The unit-level copy is planned for the PPI-F02 mock-backed proof of concept. It should use +the same three locations: -**Current copy source:** hardcoded client-side string, `"No peer submissions yet"` (`ZERO_PERCENT_STATE.unavailableMessage` is actually an empty string — the component ignores it and shows its own fallback text instead; flagged as an open design question during PPI-F03, still unresolved) +1. **Label:** at the top of the unit progress summary card. +2. **Tooltip or short help text:** opened from the card's help control. +3. **Expanded explanation:** below the two progress values or inside an accessible + disclosure panel. -- **Label:** Peer progress -- **Tooltip:** No peers have submitted yet — not a reflection of your own progress. -- **Expanded explanation:** No one aiming for the same grade as you has submitted this task yet. This isn't feedback on your own progress — it just means the group total is currently zero, and it may change as others submit. +The planned card should keep these values separate: -*Rationale:* explicitly disclaims that a zero reads as evaluative, now in both the tooltip and the expanded explanation rather than the expanded explanation alone. +- **My progress** +- **Anonymous group progress** -**Flag:** worth deciding, separately from this ticket, whether this state should read `unavailableMessage` from the API like every other state does (currently it's the only one of the six with copy hardcoded in the template rather than data-driven). +The earlier unit-level wireframe used one anonymous Ready-for-Feedback value. The current +PPI-F02 scope requires the student's own progress and the anonymous group value to be +separately labelled. The annotated wireframe below keeps the earlier simple card style +while showing the current two-value boundary. ---- +![Annotated PPI copy-location wireframe](assets/ppi/ppi-d01-copy-location-wireframe.svg) -### 3.3 Suppressed — cohort too small +### 2.3 Accessibility requirement for implementation -**Current copy source:** `unavailableMessage` = `"Not enough students to show progress."` +The future help control must: -- **Label:** Peer progress hidden -- **Tooltip:** Hidden to protect student privacy — too few students in this group. -- **Expanded explanation:** This is hidden because too few students are aiming for this grade to show a group percentage without potentially identifying individuals. This is a privacy safeguard, not an error or a sign that something's missing. +- be a real button with a useful accessible name; +- work with keyboard, touch, and screen-reader use; +- not depend on mouse hover alone; +- expose expanded text in a predictable reading and focus order; +- close without trapping keyboard focus; +- remain understandable without colour; +- avoid using an icon as the only explanation. -*Rationale:* directly implements the "suppression as protection, not absence" principle — names the actual mechanism (small-cohort re-identification risk) rather than leaving it vague. +Suggested accessible name: ---- +> About peer progress -### 3.4 Unavailable — data missing +## 3. Task-level copy -**Current copy source:** `unavailableMessage` = `"Progress unavailable."` +### 3.1 Normal result -- **Label:** Peer progress unavailable -- **Tooltip:** Peer progress data isn't available right now — not a reflection of your own progress. -- **Expanded explanation:** Peer progress information isn't available for this task right now. This is a data issue, not a reflection of your own progress — check back later. +**Template state:** `@case ('success')` -*Rationale:* explicit "data issue, not a progress issue" framing per the starting principles, now present in both tiers rather than the expanded explanation alone. +- **Label:** Peer task progress +- **Tooltip or short help text:** Shows the percentage of students in your + privacy-protected target-grade group who have submitted this task. +- **Expanded explanation:** This is one combined percentage for students aiming for the + same target grade. It does not show names, individual results, raw group size or + rankings. It does not assess your own work or predict your grade. ---- +### 3.2 Genuine zero result -### 3.5 Stale — data outdated +**Template state:** `@case ('no-data')` -**Current copy source:** `unavailableMessage` = `"Peer progress is currently unavailable."` (reused generic wording) plus a separate hardcoded badge, `"Data may be outdated"` +- **Label:** Peer task progress +- **Tooltip or short help text:** The group percentage is currently 0%. This is a real + result, not missing data. +- **Expanded explanation:** No students in the privacy-protected group have submitted + this task yet. This is not feedback about your own progress. The percentage may change + as submissions are made. -- **Label:** Peer progress — data outdated -- **Tooltip:** Peer progress data hasn't refreshed recently — not a reflection of your own progress. -- **Expanded explanation:** Peer progress data hasn't updated recently, so it isn't being shown right now rather than risk showing an out-of-date figure. This is a data timing issue, not a reflection of your own progress — check back later for a current number. +### 3.3 Small-group suppression -*Rationale:* Note the current implementation (`ppi-widget.component.html:39-45`, `peer-progress-indicator-state.ts:43-44`) never actually renders a percentage in this state, even if one exists in the underlying data — the stale check happens before the percentage check, so only the message + badge show. Copy above is written to match what actually renders (no number implied). **Flag:** worth asking the team whether that's intentional; if a stale percentage should ever be shown (e.g. "42% (as of 3 days ago)"), the copy would need to change along with the logic — out of scope for this ticket either way. +**Template state:** `@case ('hidden')` -**Also flag:** the current `unavailableMessage` for this state ("Peer progress is currently unavailable") is nearly identical to the plain Unavailable state's message, even though they're different situations (no data vs. old data) and already get a distinguishing badge. Recommend the API-side message text be differentiated too, not just the badge — draft expanded explanation above already treats them distinctly, but the actual `message` span will keep showing the old generic string until that's changed. +- **Label:** Peer task progress hidden +- **Tooltip or short help text:** The group percentage is hidden because the group is too + small to show safely. +- **Expanded explanation:** OnTrack hides the group percentage to protect student + privacy. It does not show the hidden value, exact group size, names or individual + results. This is a privacy safeguard, not an error or a judgement about your work. ---- +### 3.4 Unavailable data -### 3.6 Disabled — feature off for this unit +**Template state:** `@case ('unavailable')` -**Current copy source:** `unavailableMessage` = `"Peer Progress Indicator is disabled for this unit."` +- **Label:** Peer task progress unavailable +- **Tooltip or short help text:** Current group progress is not available. This does not + describe your own progress. +- **Expanded explanation:** OnTrack cannot show a current group percentage for this task + right now. This is a data-availability state, not feedback about your work. Check again + later. -- **Label:** Peer progress off -- **Tooltip:** Your unit coordinator has turned this feature off for this unit. -- **Expanded explanation:** This unit doesn't use the Peer Progress Indicator. Your own progress, submissions, and grading are completely unaffected — this setting only controls whether peer comparison information is shown to students in this unit. +### 3.5 Stale data -*Rationale:* reassures that a coordinator-level toggle isn't a signal about the student personally, and doesn't imply the feature being off is a loss. +**Template state:** `@case ('stale')` ---- +- **Label:** Peer task progress not current +- **Tooltip or short help text:** The group value has not refreshed recently, so it is not + shown as current. +- **Expanded explanation:** The latest group percentage may be out of date. OnTrack does + not present it as current because that could be misleading. This is a timing issue, not + feedback about your own progress. -## 4. Suggested screenshot pairing +### 3.6 Feature disabled -Six widget-state screenshots exist from PPI-F03's verification pass (saved locally at capture time, not in this repo — need to be located and re-attached, not recaptured). Suggested pairing for the annotated screenshot required by acceptance criterion 5: +**Template state:** `@case ('disabled')` -| Screenshot | Pair with | -|---|---| -| Normal / 42% state | §3.1 | -| Zero/no-data state | §3.2 | -| Suppressed state | §3.3 | -| Unavailable state | §3.4 | -| Stale state | §3.5 | -| Disabled state | §3.6 | +- **Label:** Peer task progress off +- **Tooltip or short help text:** Peer progress is turned off for this unit. +- **Expanded explanation:** Peer comparison is not shown for this unit. This message only + describes whether the feature is available. It is not a judgement about your work, + submission or progress. -Annotation itself (drawing labels onto the image) is manual/outside this session — this table just maps which shot goes with which copy block. +### 3.7 Supporting loading and error copy ---- +These states already exist in the task-level widget and should use the same accessible +help pattern when the copy is implemented. -## 5. Recommendations for follow-up +- **Loading:** Loading peer progress. +- **Error:** Could not load peer progress. Please try again. -These are findings from reading the code while writing this doc, not uncertainty about the copy itself — the copy is complete. Each one is a decision or fix that belongs to someone other than this ticket. +The error message must remain generic and must not reveal peer details, internal IDs, +authorisation rules or backend errors. -**For Maple / code review:** +## 4. Planned unit-level copy -1. **Data-contract defect in already-merged PPI-F03 code.** `STALE_STATE` in `peer-progress-indicator.mock.ts` sets `submittedPercentage: null`, but the interface comment on `PeerProgressIndicator.submittedPercentage` documents null as valid only for suppressed/unavailable/disabled — not stale. Currently latent: the stale template branch never interpolates the percentage, so no "null%" reaches the screen today. Becomes a live bug the moment either the stale UI is enhanced to also show a number, or any other code reads `submittedPercentage` trusting that contract. **Recommend:** fix the mock to carry a real percentage alongside `isStale: true`, or update the interface comment to include `isStale` among the valid-null cases. +This section is design-ready copy for the mock-backed PPI-F02 proof of concept. It is not a +claim that live unit-level data has been delivered. -2. **Zero state's message is hardcoded, not API-driven** — the only one of the six states where this is true. `ZERO_PERCENT_STATE.unavailableMessage` is an empty string; the component shows its own fallback instead. Pre-existing open question from PPI-F03, still unresolved. **Recommend:** decide whether the mock/backend should supply a real message here, matching how the other five states work. +### 4.1 Normal result -3. **Stale state's percentage is currently unreachable in the UI** — the `isStale` check fires before the percentage check in the resolver, so `view.data?.submittedPercentage` never renders even when present in the underlying data. Copy in §3.5 is written to match current behavior (no number implied). **Recommend:** if a stale-but-real number should ever display (e.g. "42% (as of 3 days ago)"), that's a template change; the copy would need a matching update at that time. +- **Label:** Unit progress overview +- **Tooltip or short help text:** Shows your own unit progress beside one + privacy-protected group percentage. +- **Expanded explanation:** My progress and Anonymous group progress are separate values. + They use the agreed unit-progress measure. The group value is one combined percentage + and does not show names, individual results, raw group size, marks, feedback or + rankings. -**For whoever implements this doc's copy into the UI:** +### 4.2 Genuine zero group result -4. Tooltip and expanded-explanation UI don't exist yet (§0.1) — this is copy ready for a future implementation ticket, not something wired up today. \ No newline at end of file +- **Label:** Unit progress overview +- **Tooltip or short help text:** Anonymous group progress is currently 0%. This is a real + value, not missing data. +- **Expanded explanation:** Your own progress remains separate from the group result. A + group value of 0% only describes the current aggregate. It is not feedback about your + work and does not predict your grade. + +### 4.3 Small-group suppression + +- **Label:** Anonymous group progress hidden +- **Tooltip or short help text:** The group percentage is hidden because the group is too + small to show safely. +- **Expanded explanation:** Your own progress may still be shown when it is available, but + the anonymous group percentage is hidden for privacy. OnTrack does not show the hidden + percentage, exact group size, names or individual results. + +### 4.4 Unavailable group data + +- **Label:** Anonymous group progress unavailable +- **Tooltip or short help text:** Your own progress may remain visible, but current group + progress is unavailable. +- **Expanded explanation:** OnTrack cannot show a current anonymous group percentage + right now. This does not change or assess your own progress. Check again later. + +### 4.5 Stale group data + +- **Label:** Anonymous group progress not current +- **Tooltip or short help text:** The group value has not refreshed recently and is not + shown as current. +- **Expanded explanation:** The latest anonymous group percentage may be out of date. + OnTrack does not present it as current because that could be misleading. Your own + progress remains a separate value. + +### 4.6 Feature disabled + +- **Label:** Unit peer progress off +- **Tooltip or short help text:** Peer progress is turned off for this unit. +- **Expanded explanation:** The unit-level peer comparison is not shown. This message only + describes feature availability. It is not feedback about your work, submission or + progress. + +### 4.7 Supporting loading and error copy + +- **Loading:** Loading unit progress. +- **Error:** Could not load unit progress. Please try again. + +A failed request or unit change must not leave the previous unit's anonymous group value +visible as though it were current. + +## 5. Implementation status and handover + +| Item | Status after PPI-D01 | +| ------------------------------------------------- | ---------------------------------------------------- | +| Task-level state copy | Complete in this document | +| Task-level label, help control and expanded panel | Planned frontend implementation | +| Unit-level state copy | Complete as planned PPI-F02 copy | +| Unit-level component | Separate PPI-F02 work | +| Live unit-level API | Future work and not claimed here | +| Annotated copy-location evidence | Complete in the sanitised SVG wireframe | +| Privacy and authorisation enforcement | Separate backend and security testing responsibility | + +### Known implementation follow-ups + +1. The current task-level template contains a visible message but no dedicated accessible + help control or expanded explanation location. +2. The genuine zero message is currently handled differently from several other states. + A frontend follow-up should decide whether all state messages use one consistent + source. +3. Stale and unavailable states need clearly different visible messages when this copy is + implemented. +4. The disabled state must remain neutral. The frontend must not claim that a particular + role or person disabled the feature unless the trusted response explicitly supplies + that information. +5. The exact unit-progress metric must be confirmed by the implementation and calculation + tickets before the planned unit-level wording is wired into production. + +## 6. Evidence and attribution + +- Original PPI-D01 task-level research and copy: + - David Tenni + - commits `c98e044` and `c5b379d` +- Earlier unit-level visual baseline and usability work: + - Umeda Ranuluge + - used as a design reference without copying personal identifying details +- Acceptance-criteria completion, privacy wording correction, sanitised annotated + wireframe and handover: + - Maple Fox +- Documentation: + - `docs/ppi-help-text-pack.md` +- Annotated wireframe: + - `docs/assets/ppi/ppi-d01-copy-location-wireframe.svg` From a7864efcae2e2778bb2abc4048b4dc288b5c2248 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Wed, 19 Aug 2026 02:00:33 +1000 Subject: [PATCH 1355/1531] fix(ppi): clarify unit summary scope and safe states --- .../peer-progress-unit-summary-state.spec.ts | 96 +++++++++++++------ .../peer-progress-unit-summary-state.ts | 73 +++++++++++--- .../api/models/peer-progress-unit-summary.ts | 21 ++-- .../peer-progress-indicator.service.ts | 12 ++- .../peer-progress-indicator.service.spec.ts | 12 +-- 5 files changed, 155 insertions(+), 59 deletions(-) diff --git a/src/app/api/models/peer-progress-unit-summary-state.spec.ts b/src/app/api/models/peer-progress-unit-summary-state.spec.ts index ae1feda5e0..f1b23c12e4 100644 --- a/src/app/api/models/peer-progress-unit-summary-state.spec.ts +++ b/src/app/api/models/peer-progress-unit-summary-state.spec.ts @@ -10,16 +10,16 @@ import { import {PeerProgressUnitSummary} from './peer-progress-unit-summary'; import {resolvePeerProgressUnitSummaryState} from './peer-progress-unit-summary-state'; -// Builds a PeerProgressUnitSummary from one of the six shared cohort mock states, -// the same way PeerProgressIndicatorService.getUnitSummary() does. +type SharedCohortState = + | typeof NORMAL_STATE + | typeof ZERO_PERCENT_STATE + | typeof SUPPRESSED_STATE + | typeof UNAVAILABLE_STATE + | typeof STALE_STATE + | typeof DISABLED_STATE; + function toUnitSummary( - cohort: - | typeof NORMAL_STATE - | typeof ZERO_PERCENT_STATE - | typeof SUPPRESSED_STATE - | typeof UNAVAILABLE_STATE - | typeof STALE_STATE - | typeof DISABLED_STATE, + cohort: SharedCohortState, studentPercentage: number | null, ): PeerProgressUnitSummary { return { @@ -36,23 +36,26 @@ function toUnitSummary( } describe('resolvePeerProgressUnitSummaryState', () => { - it('returns loading while the request is in flight, ignoring any data passed in', () => { + it('clears data while loading', () => { const result = resolvePeerProgressUnitSummaryState(true, null, toUnitSummary(NORMAL_STATE, 30)); + expect(result.state).toBe('loading'); expect(result.data).toBeNull(); }); - it('returns error when the request fails, and does not leak the previous data', () => { + it('clears previous data when a request fails', () => { const result = resolvePeerProgressUnitSummaryState( false, new Error('network down'), toUnitSummary(NORMAL_STATE, 30), ); + expect(result.state).toBe('error'); expect(result.data).toBeNull(); + expect(result.message).toBe('Could not load peer progress. Please try again.'); }); - it('returns success with the student and cohort percentages kept separate', () => { + it('returns success with student and cohort percentages kept separate', () => { const summary = toUnitSummary(NORMAL_STATE, 30); const result = resolvePeerProgressUnitSummaryState(false, null, summary); @@ -61,58 +64,93 @@ describe('resolvePeerProgressUnitSummaryState', () => { expect(result.data?.submittedPercentage).toBe(NORMAL_STATE.submittedPercentage); }); - it('returns no-data when the cohort genuinely has not submitted yet', () => { + it('keeps a genuine cohort 0% different from unavailable data', () => { const result = resolvePeerProgressUnitSummaryState( false, null, toUnitSummary(ZERO_PERCENT_STATE, 0), ); + expect(result.state).toBe('no-data'); + expect(result.data?.studentPercentage).toBe(0); + expect(result.data?.submittedPercentage).toBe(0); }); - it('returns hidden with the safe message for a small, suppressed cohort', () => { - const result = resolvePeerProgressUnitSummaryState( - false, - null, - toUnitSummary(SUPPRESSED_STATE, 30), - ); + it('removes a cohort percentage from a malformed suppressed response', () => { + const unsafeSummary: PeerProgressUnitSummary = { + ...toUnitSummary(SUPPRESSED_STATE, 30), + submittedPercentage: 65, + }; + + const result = resolvePeerProgressUnitSummaryState(false, null, unsafeSummary); + expect(result.state).toBe('hidden'); + expect(result.data?.studentPercentage).toBe(30); + expect(result.data?.submittedPercentage).toBeNull(); expect(result.message).toBe(SUPPRESSED_STATE.unavailableMessage); }); - it('returns unavailable for a generically unavailable cohort response', () => { + it('keeps own progress but hides unavailable cohort progress', () => { const result = resolvePeerProgressUnitSummaryState( false, null, toUnitSummary(UNAVAILABLE_STATE, 30), ); + expect(result.state).toBe('unavailable'); + expect(result.data?.studentPercentage).toBe(30); + expect(result.data?.submittedPercentage).toBeNull(); }); - it('returns disabled when the unit has turned the feature off', () => { - const result = resolvePeerProgressUnitSummaryState( - false, - null, - toUnitSummary(DISABLED_STATE, 30), - ); + it('clears both percentages when the feature is disabled', () => { + const unsafeSummary: PeerProgressUnitSummary = { + ...toUnitSummary(DISABLED_STATE, 30), + submittedPercentage: 65, + }; + + const result = resolvePeerProgressUnitSummaryState(false, null, unsafeSummary); + expect(result.state).toBe('disabled'); + expect(result.data?.studentPercentage).toBeNull(); + expect(result.data?.submittedPercentage).toBeNull(); expect(result.message).toBe(DISABLED_STATE.unavailableMessage); }); - it('returns stale without exposing a cohort percentage when data is outdated', () => { - const result = resolvePeerProgressUnitSummaryState(false, null, toUnitSummary(STALE_STATE, 30)); + it('keeps own progress but removes a malformed stale cohort percentage', () => { + const unsafeSummary: PeerProgressUnitSummary = { + ...toUnitSummary(STALE_STATE, 30), + submittedPercentage: 65, + }; + + const result = resolvePeerProgressUnitSummaryState(false, null, unsafeSummary); expect(result.state).toBe('stale'); + expect(result.data?.studentPercentage).toBe(30); expect(result.data?.submittedPercentage).toBeNull(); expect(result.message).toBe(STALE_STATE.unavailableMessage); }); - it('transitions from loading to success without carrying over a stale value', () => { + it('does not return success when the student percentage is missing', () => { + const result = resolvePeerProgressUnitSummaryState( + false, + null, + toUnitSummary(NORMAL_STATE, null), + ); + + expect(result.state).toBe('unavailable'); + expect(result.data?.studentPercentage).toBeNull(); + expect(result.data?.submittedPercentage).toBeNull(); + }); + + it('transitions from loading to success without carrying old data', () => { const loadingResult = resolvePeerProgressUnitSummaryState(true, null, null); + expect(loadingResult.data).toBeNull(); const summary = toUnitSummary(NORMAL_STATE, 30); const successResult = resolvePeerProgressUnitSummaryState(false, null, summary); + + expect(successResult.state).toBe('success'); expect(successResult.data).toEqual(summary); }); }); diff --git a/src/app/api/models/peer-progress-unit-summary-state.ts b/src/app/api/models/peer-progress-unit-summary-state.ts index 53ae747d89..ad4aab81fd 100644 --- a/src/app/api/models/peer-progress-unit-summary-state.ts +++ b/src/app/api/models/peer-progress-unit-summary-state.ts @@ -9,9 +9,32 @@ export interface PeerProgressUnitSummaryViewModel { const GENERIC_ERROR_MESSAGE = 'Could not load peer progress. Please try again.'; -// Same priority order as resolvePeerProgressState (peer-progress-indicator-state.ts) -- -// unit-level summaries resolve to the same UI states as the task-level widget, just -// over PeerProgressUnitSummary data instead of PeerProgressIndicator. +function withoutCohortPercentage(data: PeerProgressUnitSummary): PeerProgressUnitSummary { + return { + ...data, + submittedPercentage: null, + }; +} + +function withoutAnyPercentage(data: PeerProgressUnitSummary): PeerProgressUnitSummary { + return { + ...data, + studentPercentage: null, + submittedPercentage: null, + }; +} + +/** + * Converts unit-summary data into the shared PPI UI states. + * + * Privacy rule: + * Hidden, unavailable and stale states must never retain an anonymous cohort + * percentage, even when a malformed response contains one. + * + * Accuracy rule: + * Disabled, loading and error states must not retain percentages that could be + * mistaken for current information. + */ export function resolvePeerProgressUnitSummaryState( loading: boolean, error: unknown | null, @@ -22,28 +45,56 @@ export function resolvePeerProgressUnitSummaryState( } if (error || !data) { - return {state: 'error', data: null, message: GENERIC_ERROR_MESSAGE}; + return { + state: 'error', + data: null, + message: GENERIC_ERROR_MESSAGE, + }; } if (!data.isFeatureEnabled) { - return {state: 'disabled', data, message: data.unavailableMessage}; + return { + state: 'disabled', + data: withoutAnyPercentage(data), + message: data.unavailableMessage, + }; } if (data.isSuppressed) { - return {state: 'hidden', data, message: data.unavailableMessage}; + return { + state: 'hidden', + data: withoutCohortPercentage(data), + message: data.unavailableMessage, + }; } if (data.isStale) { - return {state: 'stale', data, message: data.unavailableMessage}; + return { + state: 'stale', + data: withoutCohortPercentage(data), + message: data.unavailableMessage, + }; } - if (data.submittedPercentage === null) { - return {state: 'unavailable', data, message: data.unavailableMessage}; + if (data.studentPercentage === null || data.submittedPercentage === null) { + return { + state: 'unavailable', + data: withoutCohortPercentage(data), + message: data.unavailableMessage, + }; } if (data.submittedPercentage === 0) { - return {state: 'no-data', data, message: null}; + return { + state: 'no-data', + data, + message: null, + }; } - return {state: 'success', data, message: null}; + return { + state: 'success', + data, + message: null, + }; } diff --git a/src/app/api/models/peer-progress-unit-summary.ts b/src/app/api/models/peer-progress-unit-summary.ts index d99a46e1a5..d7abdd3242 100644 --- a/src/app/api/models/peer-progress-unit-summary.ts +++ b/src/app/api/models/peer-progress-unit-summary.ts @@ -1,16 +1,19 @@ import {PeerProgressIndicator} from './peer-progress-indicator'; /** - * Unit-level aggregate PPI summary: the requesting student's own progress next to - * the anonymous cohort aggregate for a unit's target grade. + * Unit-level PPI proof-of-concept model for PPI-F02. * - * Reuses PeerProgressIndicator's fields as-is -- suppression, staleness, the feature - * flag, and safe messaging all mean the same thing at unit scope as they do at task - * scope. `studentPercentage` is the one genuinely missing field: the requesting - * student's own aggregate progress across the unit, needed so a unit-level summary - * can show "your progress" and "cohort progress" as separate, plainly labelled values. - * `taskDefinitionId` is dropped since a unit summary isn't scoped to a single task. + * This model places the authenticated student's own unit progress beside an + * anonymous cohort aggregate. It is a mock-backed frontend model and does not + * represent a live unit-level API response. + * + * `studentPercentage` is the authenticated student's own unit progress. It may + * remain available when the anonymous cohort percentage is suppressed, + * unavailable, or stale. It is null when the student's own progress is + * unavailable or when the feature is disabled. + * + * `taskDefinitionId` is omitted because this summary is not scoped to one task. */ export interface PeerProgressUnitSummary extends Omit { - studentPercentage: number | null; // null under the same conditions submittedPercentage is + studentPercentage: number | null; } diff --git a/src/app/api/services/peer-progress-indicator.service.ts b/src/app/api/services/peer-progress-indicator.service.ts index 682a0185f6..7bbf160a46 100644 --- a/src/app/api/services/peer-progress-indicator.service.ts +++ b/src/app/api/services/peer-progress-indicator.service.ts @@ -35,10 +35,14 @@ export class PeerProgressIndicatorService { }); } - // Unit-level counterpart to getIndicator(): same six cohort states, scoped to a - // unit's target grade rather than one task, plus the student's own percentage -- - // the one field the cohort-only PeerProgressIndicator contract doesn't carry. - getUnitSummary( + /** + * Builds a privacy-safe unit-summary fixture for PPI-F02 tests and demos. + * + * This is mock-only. It must not be treated as the live PPI-F01 production + * adapter, and the caller-supplied target grade must never become the design + * of a future live endpoint. + */ + getMockUnitSummary( unitId: number, targetGrade: number, studentPercentage: number | null, diff --git a/src/app/api/services/spec/peer-progress-indicator.service.spec.ts b/src/app/api/services/spec/peer-progress-indicator.service.spec.ts index 9d91e63e29..9a8863738e 100644 --- a/src/app/api/services/spec/peer-progress-indicator.service.spec.ts +++ b/src/app/api/services/spec/peer-progress-indicator.service.spec.ts @@ -103,9 +103,9 @@ describe('PeerProgressIndicatorService', () => { }); }); - describe('getUnitSummary', () => { + describe('getMockUnitSummary', () => { it('should keep the student and cohort percentages separate for a normal response', () => { - service.getUnitSummary(10, 2, 30, 'normal').subscribe((result) => { + service.getMockUnitSummary(10, 2, 30, 'normal').subscribe((result) => { expect(result.studentPercentage).toBe(30); expect(result.submittedPercentage).toBe(NORMAL_STATE.submittedPercentage); expect(result.isSuppressed).toBe(NORMAL_STATE.isSuppressed); @@ -116,13 +116,13 @@ describe('PeerProgressIndicatorService', () => { }); it('should not expose a task definition id -- a unit summary is not task-scoped', () => { - service.getUnitSummary(10, 2, 30, 'normal').subscribe((result) => { + service.getMockUnitSummary(10, 2, 30, 'normal').subscribe((result) => { expect((result as unknown as {taskDefinitionId?: number}).taskDefinitionId).toBeUndefined(); }); }); it('should return suppressed state with the safe message and no cohort percentage', () => { - service.getUnitSummary(30, 0, 30, 'suppressed').subscribe((result) => { + service.getMockUnitSummary(30, 0, 30, 'suppressed').subscribe((result) => { expect(result.submittedPercentage).toBe(SUPPRESSED_STATE.submittedPercentage); expect(result.isSuppressed).toBe(true); expect(result.unavailableMessage).toBe(SUPPRESSED_STATE.unavailableMessage); @@ -131,14 +131,14 @@ describe('PeerProgressIndicatorService', () => { }); it('should return disabled state when the unit has PPI turned off', () => { - service.getUnitSummary(60, 1, 30, 'disabled').subscribe((result) => { + service.getMockUnitSummary(60, 1, 30, 'disabled').subscribe((result) => { expect(result.isFeatureEnabled).toBe(false); expect(result.unavailableMessage).toBe(DISABLED_STATE.unavailableMessage); }); }); it('should preserve a null studentPercentage rather than substituting a default', () => { - service.getUnitSummary(10, 2, null, 'normal').subscribe((result) => { + service.getMockUnitSummary(10, 2, null, 'normal').subscribe((result) => { expect(result.studentPercentage).toBeNull(); }); }); From 55d7b3050ab20ee81dfaa859fdc263c2f3879258 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Wed, 19 Aug 2026 07:40:04 +1000 Subject: [PATCH 1356/1531] fix(settings): preserve bootstrap with protected feature flags --- .../api/services/authentication.service.ts | 17 +++- .../constants/doubtfire-constants.spec.ts | 95 +++++++++++++++++++ .../config/constants/doubtfire-constants.ts | 80 +++++++++++----- 3 files changed, 165 insertions(+), 27 deletions(-) create mode 100644 src/app/config/constants/doubtfire-constants.spec.ts diff --git a/src/app/api/services/authentication.service.ts b/src/app/api/services/authentication.service.ts index 1f4ed2b7ff..46c6f89aa0 100644 --- a/src/app/api/services/authentication.service.ts +++ b/src/app/api/services/authentication.service.ts @@ -5,7 +5,10 @@ import {AsyncSubject, Observable, catchError, map, throwError} from 'rxjs'; import {User, UserService} from 'src/app/api/models/doubtfire-model'; import {AppInjector} from 'src/app/app-injector'; import {AlertService} from 'src/app/common/services/alert.service'; -import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import { + type AuthenticatedSettingsResponseFormat, + DoubtfireConstants, +} from 'src/app/config/constants/doubtfire-constants'; import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; /** @@ -160,6 +163,15 @@ export class AuthenticationService { ); } + private loadAuthenticatedSettings(): void { + const url: string = `${this.doubtfireConstants.API_URL}/settings`; + + this.httpClient.get(url).subscribe({ + next: (settings) => this.doubtfireConstants.applyAuthenticatedSettings(settings), + error: (error) => console.error('Unable to load authenticated settings', error), + }); + } + /** * Use the user service to get or create a user object, and update it * from the response. Ensure that the authentication token is set. @@ -181,6 +193,9 @@ export class AuthenticationService { // Record the current user this.userService.currentUser = user; + // Load feature flags using the newly issued authentication token. + this.loadAuthenticatedSettings(); + if (firstTime) { // Load everything! AppInjector.get(GlobalStateService).loadGlobals(); diff --git a/src/app/config/constants/doubtfire-constants.spec.ts b/src/app/config/constants/doubtfire-constants.spec.ts new file mode 100644 index 0000000000..b55790798a --- /dev/null +++ b/src/app/config/constants/doubtfire-constants.spec.ts @@ -0,0 +1,95 @@ +import {provideHttpClient} from '@angular/common/http'; +import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; +import {TestBed} from '@angular/core/testing'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; + +describe('DoubtfireConstants', () => { + let httpMock: HttpTestingController; + + const publicSettings = { + externalName: 'OnTrack', + hasLogo: true, + logoUrl: '/logo.svg', + logoLinkUrl: '/', + }; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [provideHttpClient(), provideHttpClientTesting()], + }); + + httpMock = TestBed.inject(HttpTestingController); + }); + + afterEach(() => { + httpMock.verify(); + }); + + function flushSignoutUrl(): void { + const request = httpMock.expectOne(`${API_URL}/auth/signout_url`); + request.flush({auth_signout_url: '/sign_out'}); + } + + it('loads public branding without authentication headers', () => { + const service = TestBed.inject(DoubtfireConstants); + + const request = httpMock.expectOne(`${API_URL}/settings/public`); + + expect(request.request.headers.has('Auth-Token')).toBe(false); + expect(request.request.headers.has('Username')).toBe(false); + + request.flush(publicSettings); + flushSignoutUrl(); + + expect(service.ExternalName.value).toBe('OnTrack'); + expect(service.LogoSettings.value).toEqual({ + hasLogo: true, + logoUrl: '/logo.svg', + logoLinkUrl: '/', + }); + }); + + it('falls back to the legacy settings route during a staged deployment', () => { + const service = TestBed.inject(DoubtfireConstants); + + const publicRequest = httpMock.expectOne(`${API_URL}/settings/public`); + publicRequest.flush( + {error: 'Not found'}, + { + status: 404, + statusText: 'Not Found', + }, + ); + + const legacyRequest = httpMock.expectOne(`${API_URL}/settings`); + legacyRequest.flush({ + ...publicSettings, + overseerEnabled: true, + tiiEnabled: true, + d2lEnabled: true, + }); + + flushSignoutUrl(); + + expect(service.ExternalName.value).toBe('OnTrack'); + }); + + it('applies feature flags received after authentication', () => { + const service = TestBed.inject(DoubtfireConstants); + + const publicRequest = httpMock.expectOne(`${API_URL}/settings/public`); + publicRequest.flush(publicSettings); + flushSignoutUrl(); + + service.applyAuthenticatedSettings({ + overseerEnabled: true, + tiiEnabled: true, + d2lEnabled: false, + }); + + expect(service.IsOverseerEnabled.value).toBe(true); + expect(service.IsTiiEnabled.value).toBe(true); + expect(service.IsD2LEnabled.value).toBe(false); + }); +}); diff --git a/src/app/config/constants/doubtfire-constants.ts b/src/app/config/constants/doubtfire-constants.ts index 16207391e7..64981f7133 100644 --- a/src/app/config/constants/doubtfire-constants.ts +++ b/src/app/config/constants/doubtfire-constants.ts @@ -1,14 +1,17 @@ -import {HttpBackend, HttpClient} from '@angular/common/http'; +import {HttpBackend, HttpClient, HttpErrorResponse} from '@angular/common/http'; import {Injectable} from '@angular/core'; -import {BehaviorSubject} from 'rxjs'; +import {BehaviorSubject, catchError, throwError} from 'rxjs'; import API_URL from 'src/app/config/constants/apiUrl'; import HOST_URL from 'src/app/config/constants/hostUrl'; -interface SettingsResponseFormat { +interface PublicSettingsResponseFormat { externalName: string; hasLogo: boolean; logoUrl: string; logoLinkUrl: string; +} + +export interface AuthenticatedSettingsResponseFormat { overseerEnabled: boolean; tiiEnabled: boolean; d2lEnabled: boolean; @@ -40,7 +43,7 @@ export class DoubtfireConstants { // Where should we redirect users on signout? public SignoutURL: string; - // initialise exernal name to loading. + // Initialise external name to loading. public ExternalName: BehaviorSubject = new BehaviorSubject('Loading...'); /** @@ -54,7 +57,7 @@ export class DoubtfireConstants { public IsD2LEnabled: BehaviorSubject = new BehaviorSubject(false); /** - * Details on the logo + * Details on the logo. */ public LogoSettings: BehaviorSubject = new BehaviorSubject({ hasLogo: false, @@ -67,37 +70,62 @@ export class DoubtfireConstants { */ public IsTiiEnabled: BehaviorSubject = new BehaviorSubject(false); - private readonly settingsUrl: string = `${this.API_URL}/settings`; + private readonly publicSettingsUrl: string = `${this.API_URL}/settings/public`; + private readonly legacySettingsUrl: string = `${this.API_URL}/settings`; constructor(handler: HttpBackend) { - // Don't use interceptors for Doubtfire Constants + // Do not use interceptors for pre-authentication Doubtfire constants. this.http = new HttpClient(handler); - this.loadSettings(); + this.loadPublicSettings(); this.loadSignoutUrl(); } - private loadSignoutUrl() { + private loadSignoutUrl(): void { const url: string = `${this.API_URL}/auth/signout_url`; - this.http.get(url).subscribe( - (result) => (this.SignoutURL = result.auth_signout_url), - (error) => console.error(error), - ); + this.http.get(url).subscribe({ + next: (result) => (this.SignoutURL = result.auth_signout_url), + error: (error) => console.error(error), + }); } - // publish update to ExternalName when get request finishes. - private loadSettings() { - this.http.get(this.settingsUrl).subscribe((result) => { - this.ExternalName.next(result.externalName); - this.IsOverseerEnabled.next(result.overseerEnabled); - this.IsTiiEnabled.next(result.tiiEnabled); - this.IsD2LEnabled.next(result.d2lEnabled); - - this.LogoSettings.next({ - hasLogo: result.hasLogo, - logoUrl: result.logoUrl, - logoLinkUrl: result.logoLinkUrl, + /** + * Load branding needed before the user signs in. + * + * The fallback allows this web change to be deployed before the API change. + * The current API returns the same branding fields from /settings. + */ + private loadPublicSettings(): void { + this.http + .get(this.publicSettingsUrl) + .pipe( + catchError((error: HttpErrorResponse) => { + if (error.status === 404) { + return this.http.get(this.legacySettingsUrl); + } + + return throwError(() => error); + }), + ) + .subscribe({ + next: (result) => { + this.ExternalName.next(result.externalName); + this.LogoSettings.next({ + hasLogo: result.hasLogo, + logoUrl: result.logoUrl, + logoLinkUrl: result.logoLinkUrl, + }); + }, + error: (error) => console.error('Unable to load public settings', error), }); - }); + } + + /** + * Apply settings returned after successful authentication. + */ + public applyAuthenticatedSettings(result: AuthenticatedSettingsResponseFormat): void { + this.IsOverseerEnabled.next(result.overseerEnabled); + this.IsTiiEnabled.next(result.tiiEnabled); + this.IsD2LEnabled.next(result.d2lEnabled); } } From 8351f0166bc7c76f6507e7cf07cb7191a43453e3 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Wed, 19 Aug 2026 08:34:09 +1000 Subject: [PATCH 1357/1531] fix(notifications): refresh unread count after auth and on mobile --- src/app/common/header/header.component.html | 2 +- .../common/header/header.component.spec.ts | 68 +++++++++++++++++-- src/app/common/header/header.component.ts | 10 +++ .../notification-bell.component.spec.ts | 43 +++++++++++- .../notification-bell.component.ts | 17 ++++- 5 files changed, 129 insertions(+), 11 deletions(-) diff --git a/src/app/common/header/header.component.html b/src/app/common/header/header.component.html index 1c90ce4018..29ac6fd43e 100644 --- a/src/app/common/header/header.component.html +++ b/src/app/common/header/header.component.html @@ -98,7 +98,7 @@ } - diff --git a/src/app/common/header/header.component.spec.ts b/src/app/common/header/header.component.spec.ts index 51e7d8cf37..7a307629b3 100644 --- a/src/app/common/header/header.component.spec.ts +++ b/src/app/common/header/header.component.spec.ts @@ -1,9 +1,9 @@ import {MediaObserver} from 'ng-flex-layout'; -import {beforeEach, describe, expect, it} from 'vitest'; +import {beforeEach, describe, expect, it, vi} from 'vitest'; import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {Router} from '@angular/router'; -import {of} from 'rxjs'; +import {Observable, defer, of} from 'rxjs'; import {AuthenticationService} from 'src/app/api/models/doubtfire-model'; import {NotificationService} from 'src/app/api/services/notification.service'; import {SidekiqJobService} from 'src/app/api/services/sidekiq-job.service'; @@ -25,7 +25,42 @@ describe('HeaderComponent', () => { let component: HeaderComponent; let fixture: ComponentFixture; + let refreshSubscribed: boolean; + + let authenticationService: { + isAuthenticated: ReturnType; + }; + + let mediaObserver: { + isActive: ReturnType; + }; + + let notificationService: { + unreadCount$: Observable; + refreshUnreadCount: ReturnType; + }; + beforeEach(async () => { + refreshSubscribed = false; + + authenticationService = { + isAuthenticated: vi.fn().mockReturnValue(true), + }; + + mediaObserver = { + isActive: vi.fn().mockImplementation((alias: string) => alias === 'xs'), + }; + + notificationService = { + unreadCount$: of(0), + refreshUnreadCount: vi.fn(() => + defer(() => { + refreshSubscribed = true; + return of(0); + }), + ), + }; + await TestBed.configureTestingModule({ declarations: [HeaderComponent], providers: [ @@ -35,10 +70,10 @@ describe('HeaderComponent', () => { {provide: CheckForUpdateService, useValue: emptyProvider}, {provide: GlobalStateService, useValue: emptyProvider}, {provide: UserService, useValue: emptyProvider}, - {provide: AuthenticationService, useValue: emptyProvider}, - {provide: MediaObserver, useValue: emptyProvider}, + {provide: AuthenticationService, useValue: authenticationService}, + {provide: MediaObserver, useValue: mediaObserver}, {provide: DoubtfireConstants, useValue: emptyProvider}, - {provide: NotificationService, useValue: {unreadCount$: of(0)}}, + {provide: NotificationService, useValue: notificationService}, {provide: SidekiqJobService, useValue: emptyProvider}, {provide: SidekiqJobsModalService, useValue: emptyProvider}, {provide: QrModalService, useValue: emptyProvider}, @@ -59,4 +94,27 @@ describe('HeaderComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('refreshes the unread count when the mobile account menu opens', () => { + component.refreshMobileUnreadCount(); + + expect(notificationService.refreshUnreadCount).toHaveBeenCalledTimes(1); + expect(refreshSubscribed).toBe(true); + }); + + it('does not refresh the mobile count on larger screens', () => { + mediaObserver.isActive.mockReturnValue(false); + + component.refreshMobileUnreadCount(); + + expect(notificationService.refreshUnreadCount).not.toHaveBeenCalled(); + }); + + it('does not refresh the mobile count after sign out', () => { + authenticationService.isAuthenticated.mockReturnValue(false); + + component.refreshMobileUnreadCount(); + + expect(notificationService.refreshUnreadCount).not.toHaveBeenCalled(); + }); }); diff --git a/src/app/common/header/header.component.ts b/src/app/common/header/header.component.ts index 61fabdcb8a..8fce0f1892 100644 --- a/src/app/common/header/header.component.ts +++ b/src/app/common/header/header.component.ts @@ -260,6 +260,16 @@ export class HeaderComponent implements OnInit, OnDestroy { this.aboutDoubtfireModal.show(); } + public refreshMobileUnreadCount(): void { + if (!this.media.isActive('xs') || !this.authService.isAuthenticated()) { + return; + } + + this.notificationService.refreshUnreadCount().subscribe({ + error: () => undefined, + }); + } + openCalendar(): void { this.calendarModal.show(null); } diff --git a/src/app/common/header/notification-bell/notification-bell.component.spec.ts b/src/app/common/header/notification-bell/notification-bell.component.spec.ts index 2e2df5540f..ae8a3389fd 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.spec.ts +++ b/src/app/common/header/notification-bell/notification-bell.component.spec.ts @@ -30,7 +30,12 @@ describe('NotificationBellComponent', () => { unreadCount$: BehaviorSubject; refreshUnreadCount: ReturnType; }; - let authenticationService: {isAuthenticated: ReturnType}; + let completeAuthentication: (authenticated: boolean) => void; + + let authenticationService: { + isAuthenticated: ReturnType; + afterAuthCall: ReturnType; + }; let router: {events: unknown; navigateByUrl: ReturnType}; /** @@ -68,7 +73,14 @@ describe('NotificationBellComponent', () => { unreadCount$: unreadCount, refreshUnreadCount: vi.fn(() => answers('refreshUnreadCount', 0)), }; - authenticationService = {isAuthenticated: vi.fn().mockReturnValue(true)}; + completeAuthentication = () => undefined; + + authenticationService = { + isAuthenticated: vi.fn().mockReturnValue(true), + afterAuthCall: vi.fn((callback: (authenticated: boolean) => void) => { + completeAuthentication = callback; + }), + }; router = {events: routerEvents.asObservable(), navigateByUrl: vi.fn()}; await TestBed.configureTestingModule({ @@ -172,6 +184,33 @@ describe('NotificationBellComponent', () => { expect(notificationService.refreshUnreadCount).toHaveBeenCalledTimes(1); }); + it('waits for restored authentication before the initial refresh', () => { + authenticationService.isAuthenticated.mockReturnValue(false); + + fixture.detectChanges(); + + expect(authenticationService.afterAuthCall).toHaveBeenCalledTimes(1); + expect(notificationService.refreshUnreadCount).not.toHaveBeenCalled(); + + authenticationService.isAuthenticated.mockReturnValue(true); + completeAuthentication(true); + + expect(notificationService.refreshUnreadCount).toHaveBeenCalledTimes(1); + expect(subscribedTo.has('refreshUnreadCount')).toBe(true); + }); + + it('does not refresh after delayed authentication once destroyed', () => { + authenticationService.isAuthenticated.mockReturnValue(false); + + fixture.detectChanges(); + fixture.destroy(); + + authenticationService.isAuthenticated.mockReturnValue(true); + completeAuthentication(true); + + expect(notificationService.refreshUnreadCount).not.toHaveBeenCalled(); + }); + it('handles a count request that fails instead of leaving it unhandled', async () => { // rxjs does not throw an unhandled subscriber error where the subscribe // call was, it hands it to config.onUnhandledError a macrotask later, and diff --git a/src/app/common/header/notification-bell/notification-bell.component.ts b/src/app/common/header/notification-bell/notification-bell.component.ts index c22989602f..a2f79f3245 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.ts +++ b/src/app/common/header/notification-bell/notification-bell.component.ts @@ -27,6 +27,7 @@ export class NotificationBellComponent implements OnInit, OnDestroy { unreadCount = 0; private subscriptions: Subscription[] = []; + private destroyed = false; constructor( private notificationService: NotificationService, @@ -52,12 +53,22 @@ export class NotificationBellComponent implements OnInit, OnDestroy { .subscribe(() => this.refresh()), ); - // unreadCount$ seeds at zero and stays there until something asks, so the - // first navigation is too late to be the only trigger. - this.refresh(); + // A remembered session is restored after the header is created. If the bell + // asks immediately, the authentication guard can skip the request before the + // restored session is ready, and no later navigation is guaranteed. + if (this.authenticationService.isAuthenticated()) { + this.refresh(); + } else { + this.authenticationService.afterAuthCall((authenticated) => { + if (authenticated && !this.destroyed) { + this.refresh(); + } + }); + } } ngOnDestroy(): void { + this.destroyed = true; this.subscriptions.forEach((subscription) => subscription.unsubscribe()); } From 431a6a7061382f02831004a96c6ef2a93282ce42 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Wed, 19 Aug 2026 08:51:16 +1000 Subject: [PATCH 1358/1531] fix(notifications): make dropdown actions keyboard accessible --- .../notification-bell.component.html | 6 ++-- .../notification-bell.component.scss | 31 ++++++++++++++++--- .../notification-bell.component.spec.ts | 26 ++++++++++++++++ 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/app/common/header/notification-bell/notification-bell.component.html b/src/app/common/header/notification-bell/notification-bell.component.html index 093d94a8b3..852b115e0c 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.html +++ b/src/app/common/header/notification-bell/notification-bell.component.html @@ -15,7 +15,7 @@

    Notifications

    @if (unreadCount) { - } @@ -88,10 +88,10 @@

    Notifications

    From 752993bda65eea7e4f7e2bfeb52fcaf65159d8d2 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Wed, 19 Aug 2026 14:39:12 +1000 Subject: [PATCH 1365/1531] fix: preserve comments empty-state sizing --- .../task-comments-viewer/task-comments-viewer.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html index f7158de740..cb608e93b6 100644 --- a/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html +++ b/src/app/tasks/task-comments-viewer/task-comments-viewer.component.html @@ -13,7 +13,7 @@
    @if (!task || task.comments.length === 0) { -
    +
    forum
    } From a8b8c9c5b08fd93ec109ddc6bf8f7c3f574e5a59 Mon Sep 17 00:00:00 2001 From: Eloise Ridder-Strickland Date: Wed, 19 Aug 2026 15:13:25 +1000 Subject: [PATCH 1366/1531] docs: add PPI task sheet widget feedback document and review images --- docs/images/PPI-task-sheet-widget-v1.png | Bin 0 -> 3958466 bytes docs/images/survey-distribution-chart.png | Bin 0 -> 97855 bytes docs/images/teams-review-doc.png | Bin 0 -> 162018 bytes docs/task-sheet-widget-feedback.md | 160 ++++++++++++++++++++++ 4 files changed, 160 insertions(+) create mode 100644 docs/images/PPI-task-sheet-widget-v1.png create mode 100644 docs/images/survey-distribution-chart.png create mode 100644 docs/images/teams-review-doc.png create mode 100644 docs/task-sheet-widget-feedback.md diff --git a/docs/images/PPI-task-sheet-widget-v1.png b/docs/images/PPI-task-sheet-widget-v1.png new file mode 100644 index 0000000000000000000000000000000000000000..010199c6c60b416cd6158dd6212b05d6cbfc2aa6 GIT binary patch literal 3958466 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

    dmK^& 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

    y@erDd zbFPZCDh!!`g$z64nKYSxSTprXGbxoZ=oG{yi&mz(6{r@l^beV5QF+tyK~XrU%_lR7 zeL8MW(Pa}$G|ozS7@yZq9Oyi{OuV)9-jS#v@G34r%VvXe(r%vyg7h_qBC##;CeM(YMNO|YSc8T3=|J^RdXzIbW8P_S+j@otwnyO=b8x)Oz7i` zcy$DczkfI2PB_FnbSD1h!M@G)L&Q50ru_6y&pfml2h^)D+Bp=yi2xG?3nBpX-`~Nj zT4P-ED`aj}MJ$BM0$F`t>6AoN8^V# z@r)1a|2PTRK#Ze@r>AF+wt+e_G>mLLc5(U2<5r7@nZ27bclS3lD*Sic!1RAq$&8+KR!6|g~I7!)nEj)1U1isX2`2i9*PmH|~ssI|A`61Ow<7c*YLnu=qk34^Vd z(WJ4tif$W3o}=&G&%i%xe>Axr2Tk+~hh9N~CkmkxY4;%g+HSgaxg!Wh5QHKq9g})) z8$fXVjNTM?@Us+=lzi2?f;rim1|m7M{opt2noByy;I5_k_ik_b^zcS0r+v#Z-PqiH zgWZZ*MkZSoH`(@FM*evF(tGx2pBp;$JBtxs+r70bH91jf5-WLCcsQ+NTP6ca_3PR~ zgTf)R{@l1HdSjiV)ECcS9s@3Zu$cBPY8YiKr*Q|fIYb^Kh z_=Ym<582%MCetaVe`*1w+0M?0Z>)5>n`0S;?ks<0CHT3km@|0|jMM@rL7F}RuV0bR~@i`$pe+1lJKOb@%p2&ZmmzP>1$c0&2UDYDSuI386Iu9^k z#fK2l1eaxs5jCikeIdf84|5;Yz40)cpW{naZwQgB%w+4P**)j)Y+O$KoN8l=L9@)c zbrSbeNK#3NiaC#y^A_r0#Gp4!jMfMax?~eaL6&=byQ6&NIM>BvWW3^MZZc~Q3no7o zSej4%SS-se>1K6E-8dprErLDDwuPIcEI}CF#}A~Y0x3VNQ+i2EjMZ^~5OjTLVC9`V zgLAu7S$GvLl5W-zn|pb*VU_5Lc7r$TdsS^o4K8B@6lY`qs<2>f2Nd00VQVK7zJ6V7>?AhdKQ`0l;^AjOfH}S7Ona&>{ zHoj16)jM}Cpbg}mVELcHu6AzFOaeQ38%)e+b|KT2UoFOLwCXIG@o=AEiCHqm^w=(n zk#9v69p1-#gB^wd_yoC=f#m}`NH zf;ujIVQ2B1R&?TF+IFMr-)-?Db5F#;YQu*&zABLh4;ZD*v%5Xpw0Ea+0wNb`o*BND z+Tk>vY41>*ZO@mWcxbIFO(%EQn;ze-Yh0|?Z0h$;y*9&n>zSzP|VRyFs!cTOaH$a@DQ)L9T$f0BzN557jtL2^nc!0VPC)GK;VlXs&XgbYWU)fiZp6! zq>qW!e*UbvE7=gxn6MoG@9oOJw16$MmjP9K=?668EYOItEYRTi9j2y!mPAI3t+6kX z6(zl~Q7XobIa=c^a1wv8*Iu=L`1yNG8P@8dZvY1eLx{*QQ%u{@c0O=SeBlSgf8S>R zm^QH!L0Z6d_G_QfV?*-35!yps80J&d5!r3^86b*Z|27bv$$E;K$k|5N>v!~NldO0} zhxn)JV^=vHoG8e6FJ@zMR(xVpK2ndlx! zjq#ZG44s#=bf&;)_zVK?b<|zQvDL_>s()hQ=&PNB$k`VKeYvvaRL%#2cPgqF(S65- z+t4n2OQ5^iBg~xj6Cc+=hAPlz-47Bey2UQ`*B#8Nf zUTcJ1cbxF+5E!LGmx_D?T}Q3M=4|_5igriVv%sl)z3ql>PYUojyQQoC-dUn% zDv070R5|HS7eP9#BL7Pl8p!DCVrVeo>z{_2Zq*uk^i=7Eb}FKSVW+$pU?&gE6*i`V zkC#K9Rn&n5J>*sE2G)oof&0Isqwafy2T^c~;xlFvJcLhK!Y zzXUL1d^N{fzYp{=&Q>14WkeN&v9;(QDX@Bi))wuwUb3`gYXk#mA9&m0YB)8{5NiEt z8_~n7x*d#XFt%44qoXt7*?oE8454s^?Z~n!h>`>CXjJ)cgelkDrc|ZYuwf6UHYtAi zGG18hL*`I8rcyDK#0j4wU~=?=+(E8yM}xp->2iVDne{{DZ>Zncz)2weeE=uke(BjI z>QsCWdEfP)1=vuL`9gsX7xH`W0`& z?#lF8Up?=K5n7rMyuL2WCeKYpbOpb)j;9G=JnRa@75_D0T)rJ%QN)}Is!HN^yHHqW zIrVbd1wbMs*aoSu{8_1a8zvettQaBP{cq?NBnh* zPMG{uEG;eN!gQQ^p>pkj(gLB4sT7GHv?5wLnJDV16vkn+Z2SD?G1_}j=K<^BzZO&* zZ_m1`U2lho#CPCg`c~-fHwypBwb6IY%?gP6jgtP#9mCOV@_0Dq{{4emvOf%1{gy>Q z*|gyk*RWRMOc4F_Yq)yeoe|WaP^msbq7nLWHA60~)PIf-bR9IdlqOD4K6X$$2?|el za1k0d`7D{MSAcY4ZonVSTcO2^QZ{4qyRFu3YIV)I?T^9B`vf(q9Q^-Y41G=V$v3V+S56sxBaYSFhM)nXvY@k1WMZI2 z_H6(`8p>kV1|q#-AFdjNW^T-NBOB=0#A=Ju&E8vg5lMD-P5%HGxB$NcLG(>9cuRBm zf{bV-;DTS^@Iq~Ety;_jls5Ewq&}(?EFXcbq5x~a$-5V?TlmO@o2*n++ zxVD|Rnk;&*v=)h4f6vJ8pG9TW-N(XD>K1t4@RW_uiSQCzKEDl=;(N=u$CtTERS{W}Qn$PJMQ@ zHdkUs&FXS1TQu>EaK&z?Hr?R(QPNxXl;s{ zP2lE9Pb6=r?b7F7DZjqDdsQYkEwlIM;t$dlL#q|ls4m{?mJx3U85W-Iy{oc&Vdm$l zJ|-Hm*kcvRdd8uqP_fyr)W5H|HS#14wUda^*ItrH-(V2v58oFMGd=oQQqfo`i%Lh3 zejT3+Jkfca`t|FN3IfaxYBgvnKv8lh;H=ul)zmGIUrl7=Zhp_2=h?+B><1QrsL3@( z&n;B_|C;xStVPcRNhplg17oytHmFK1igfHj{XsG^t)6$GL=_G|x(%~Z_ek&@CsQUX z7G@`>xv8X?Vtu)gP85$#GR#rS`ShHw>LtCu&}mX>rJy%%$!=v=vlwQxC2aX!52-n) z$s9dN{ayCtWp`+ax$ZHOk^LgN|6~jBl@U%%x1Ak{Ep-ex5Ih)Ycl$yP#=B6E{gOWU ziU;QUF)mxs9rw#P%qOMg`&ddmz|H7+F55R}eU&l!VDbn)0Z;F*qK&!@jR>Bpes00%}=ne@nQ zAX(jjiMJ}QRep`~T)`LHi_6(V=kgXB_pw-+73DH% z{D}8*6Vc7^ks7I~2)O09mz?%x;pUNXCob=_bB)2@AAkC^WmliHH?V5u)92uK$DmXw zTZnMAC%5U9vGMS0f=SMTZTw`uxTzc~jj&de`2$cx_hQQ74SGa_G{Q z0b05bY*l=EdU}-W)e6E57!T^8GhU;rjy!qEF=Ht)U~>OF=rE^{Kle{?F%-+nEG{iA zooQb}#56SHGRI}VQ^AjVDlDPa!fBPLED>41G$cPQD&fc&}AsyKAEj(KVA zz_n~{L#Pr|K0c&B0v_FMaRpRJk^s4aipf##7_)%)FQ}!h@QdEiOZI=O4P*6vh<5KF zR&9Q!9>P9c;T!VOV{yR$R1PA+5f7$$%Xg51e$n2o0$O6%g|s^xT!9;02#7>43G9=s zA{LVZzxuGcvTVK)y89Fe!avz&f(xHtqheegxLeI{g3q@V{0e+tEAVsNwB$Z)(7b)$ z+Hym^Jje&4coIcIQ8qo???Q<|b^*6Qdf*Rs^!8nGJUdHkkpGKPQ%H^+aer?CZ)Zlp z)-93X|417O&LHsI$`Z%rLNIlvDG$8Dinca@VtoZ5@0C`QKEhDjTzSs)TMP@YW&y* zmtuyd>&m*p@=y1XefvgBE>ljShJLcbx`` z3|V40P7HH6vb_YJq}=~{!Z|(ix!So`?_+52#xpoZ{vjUo3afFBwjBbiM#@mOK#sWH zNb+QFWOw^~NfFj>Dgig9h2@zmH%vdS!0Wgvdp%rI3lkz@9b?5$iA-rczg99GHkHu7 zH7u+aQA#(Yp1fMZ3nG~k^+%t0u5}F^($6)_H`IU^L52C;MsF zZem-u=ySZ-t9P_^@8gvijy6{rWqv`@AYp=|yvnFt$q6FsjRCn&Pk-0^$K3yqv7l7! zaz7_&?a32(&AXtu?u6;!k`EW7KoXb!;xi$2oz#$mA)b3s*Ak>@#^ImkGpgk2w2E=FFAE96>{Vq{L=wcvS% z*DS1x&RlSL7AG*8|MWwKD|_=6v-J(nyn)GD#Ypn~O5!8urA+Co^j~al8;>xhg>1^K z2XHy?(JB*R1$C0C7=z1noIb!Vv>=D%%VgyWEov2Sa&_Dp^LWvQ1sDVt)AVp-*Q~le z2)=%;PDBjrE~*g}Z1z8vzG_YT@ZRDYDUF~|V7k+KoLI}hnvaC-Z>#b}@*79kjiA%J z_5bp&E(;b_B429+AljCc0!4yE)LqvbTA-=hKvxJLh*Nc&??661+sB84^+1%O$>KBn zbX@lM79fD%AoS8Z0tp46?Cn6jg;op)G_qiGVqE7fa`^D!Q`GU?;p+kNmdYTO1}YnQ zJ0bNFI66n5kd5Z%X8!@q_3I}s;r}ZM9JNS$gkPlF6S=^=1M>DoAJrl^_cX@b(>tUE zR$Cegk47{(eEry$KArk;rY<7GqBcu2<5uHj{NDGSEr&O6FQ5D&y1L+X!Fg@##;v|; zHeB~hLRzmHF?MXi>X|cBtZ&HOY#I5o)K0%F5bv!R2ijJ+-WyIqn;9O9daT}42mf~M zae9|^FGCSZw7e??{z6L^pF8$B)D7(iz(oNJ-#id_V=uHifG;rVD(>DKn^tU_cleQ0a)1quks!! z$?E}uAARDJ*9!t%@`h6YYtDdD4{QGJ2d~#=3Xlf5c9;=1ES6ccaJ0-9TxLP9`Zq)) zULBVckpoK@sB|MyyK>Ic>dvXD)BlgK_l~Ff@B6?TDx^YoBzq(zBt%AL#0lA(tYd`; z6;UKxh^%ZfENQb=|-Fe*FHqzSsAgsB=E&{eHck(*Ycz z<$%4!-gsy!A>obo3y`*9{GjWC~K*svJ7t6^+63s07e#QOS4EkclZB0E@%~P!Ws`ps=%C?Digd!Y$4U^@+3oy1B{?%?Gnhd6 z5xYE1edxjQ??84OO&(<*F0|hDpf}?^pM`vgoe+$sXTxc*5yG~LhN4@Mb zc>?|o7Wp5#vXjqj^=fliek`xl8h@=nbZ%couO{THVMWnfEM9Bi_tsa7U)}eF>4G-9 zR}-|hFIr&@Ho4U}&qcW|c3a&Bi zxTi(a4u<)**B9q)C11pnJgk%NpTujHrFMi9dRiuZ@A>2D)@}`QN8rh$Fuyl8u0ri= zYcg>I>jOY$LAq!BI;E;Ap7xrh%ey+Nzw_15Z1?{rp~>addt4`LiV( z>fR+@?n&5v*%*wg!i*!#ArI~3lm=bg$JxqAIMQ2BUH?u<=ld*>xi(O=A>0Q@J zs9!BCR5ic;GVm#IKI-C)nH8@Uapj*fDar4W+vvtbQfQm~oL(34>lZ*lkF%6sjbUS4 ztaS2hjuzBpWN7eoYhLLROINDUO)i6XNVj3jTii&6lpI}ejz!+{!S!hgN_7Oj!e%7u z6gA8;zE#uLEG90M?>}_Gkk}0U=}g?z;Z=B=lx3%*Fu1k9=a2@f-Q8Zt$y)pz3n>JaF`k5*mp_nO^k`*eZ+LudoE@XU*JEO}f+$}An6-9Wi74kh`awjn<4 z&P`|`i$JE=ot-!I$lZo2@C-@wtqec_?-+v1OpKK4;lF52pX1f z_(X$fL^Lm7ZJtI5VR#waHq3xXb5i+ zW6;NB<#`ok5HeCjAPa5&kn3IB8`8`Pa6D=Oym$AeP)wo4ygLlS?NELL64`&AZb6WL z#K(5gAo!L5A+J|lhgL^~6YaD=S}GAodJXs?j(|=Jh=|1EzrW{v4-dHiY3jAir++f} zcHHN8zQuqJ2MZQA@W1#RzTby_as}Ob$F&(0QPmscLv zNKytYh*v*|E&cGc9?)hc;mTm*%emy%u;$4a1sXt~ z>_By1!rPB;+9Gv8Z-EkeCY^6Ap90kc`pbofdZn4|*1|%vju_A#`W}9g0f)N%a>(;; zUbw7l3;6*+1n@%8&pEV!j6MYkV*K(Wof|N1paC8L8Kr}3BCUf^B(U9AR(l(A3(L-e z@$)H2br7epUhETD51vlOF`yeDHUH*R#uT$vNiqpB8uFwwCd6!?!=zr?L}>s4CVvPGzg1Hxlv{Q~Go?+UZ*A zgq><^|Jz|_@4o$fph_(oUE;hk$v0QLgO;CX*2hBAx|JYH180M_a-MpoxeZ$L|L0XTLVDyqysZF%$2=hh}n!4eUg?`8=v}+)dx64}2ehG=HF2)E6BEkPl|S zFHv0gHs{`9*d3n&euj|MBTc5^Fc5@RJeyeGTa-es?GO?Ep(bP0g{^kkY51 zIW2;$I~a0+1A@;P%$5LXw%hX=LG>&=UTBm8bo59e)T2=G>VGlX?=@1iS0iPgeb57< zs%GHn6OuYU^v_o>doP;-2fib8=6}IK&^_VT3Rb57#i~)hU!Qm3=Tt}MMRE;>j!II! z%+5BVArcly0eeYsg`MdP5qn8P*e|%g+o&2Fh32x8uaL+za4I&MOVlpk%X91Lot&_H zV?&*|CS^@+B{=Y>2Z9a*8tHh1DV>`>7q!Z`@LrlqEp6zbdqX^k$&9mo7;miNJ4;9u zC&-$$9+tdWa{5#Ram%}_XZ$Z;kbCrkphuwmO?DS8zJz?}(9zPH?afbDKZ2H%CqCk? z$xRmYeyzM^$ZfNJvy*P`$g$BACyN5lmy|L$a5fv$=J#gz&k4o};p`cb2R@i#rI}V{ z=bV}9;mU^KLv&@+caG@2*XR1>2~CB~PV83qtQMt%5?cZwy7y%N+jou~z3chOH(6;~ zoSw+U+*eZIA1WJi(EW{Zc;vP+WF-h2yL+Pi{rmTSoQ$0O4Epw=!ajIwAyb%7XB%Vg z=y`B3>2VPxT#su)Ft5PQLQ3E%`?Ozo9eprS)jY#>&zpeBqJ^H-j+-!&G*1XM=px>4 ztxglxb!5Q&OeQ~ZJ?H$t-!XnMkqgakh-D4Ex%oY|H4++gGp^SJqU*%DV%X{C=XG&3 znuFl0I_7p~blyj;Tqj`pRzdoPs$BNs+ThW;F&4mrY6xPJ9KaS<+YEzj%;{@z+Mw63{rV5j0K{a~GJiN@Gn439u~Cy?Cu1_5$c*`qA9j*oeqrG)E&&=X{9zsZ*!W1_5}An#5Baybr)Q zBN(Re@L+d(eWMw+@AoBt`x}!a4{vYmZ1Mxu`U3L`{UCivpV>Kx&U@7L{`NbUZbgp~ z>pZknRKQ{I&QIF*^;M|f`CCK-$3zHO$(b`}&{p;Yx>BcFF2MZ)shA^P08TE&E>Hez z$AXA`#o8ouSLoYraU8IS!EU+#1P{v?JQ?ly=$b8q<;T|?)kQ|oe)|Q?%JJ*Mifv{)w5NIpUa;fWzlX1?2v0ff zu#I@w$oMFJ)DsRIny@E|7B`$MzLT>b=t6H{P-AjMm^Pc#R*1^K$s5b}!RGR#-GSpm zbC3FPlEo5(Tn|1ro4#h?%GI(OZJjAmZL<3M^D>mg--?ihN&aJRS}*ZE9lhspiCren z?tfwRLPh)>_vEpgBO||6;^)#lCdmy(cpWr(JOHFmOlqw)(9y3e%oo=d&jWyBW5AxQ@H&9s#QB>&Uq{1Bngi}THmr09RH8ZhXK1|g!EL@ zIK4So*L6ST9uslNABOtuc9;=0^~mFklRtKvb+RddP_v8;jCf+JGFSEC<)l=?VJpx0O` zrE79LJz0YU{G9O48ghfq3I>KHV*gL6`m0=2$M-(T*xruNj=)LecPA%Lr!&ih?u39Tf$( z3=>ZIuQ?oUI-rWv9UQIM_os*ZJ7Dl{g2B$s zodt+B?fhPwtANJ<-Fe|a((}Q^2e(~+?k?ZZbSpC%=Y$92D^D`6wnco9n-WooLNzjG1^;bMP01c2HO?5V27jy zAtK{|9nSKHPIWmD<@+}fH-Px`QLwo5eEy_HT0qmN7^z(!jD$!&=YFpxK>C>*aM>mUZra`5z`yoT1RCD?dmhl1UfV?$Y~ z6+k%j*pb)Y-`j=>p#=tBh0GqI#c!3BqH@7>z2o8^wYj%p1Ofl94OJo5&d&T-ga7Lb z*UxsWKc*;Y3i>z-zYQUykUS%A!BF>dz7i?wfqLou_U$u#`^X9dNF+zaE`YeQ4);bT zL#C3U$0Q|`6~?74_>-34aL(hw*PQ_@`}R+72~W`BUdN$%cbXzp|HiG)qx}sY>kn@) zXO>QZeigL@3hf_Dr+9wy%otL-6{$80l*7;a_HA`@(@g^6ry%OIGFyl&XEK>2^?uO6w)>gz- zinKGdU9!u0#q{*7tgnD3fvbWyI?Vi`>%_y2iTU~L0^3hT_e7#qz7h@ni7vSnpthLq zIuq3IbP$k(?N{8DBP6qkdrwdK{;MFhO}7vo<+c^&$;2ov#dAgqn)mE=p9Sph(UrWy zF?AMskfi4+bXs!E{h=e%`~7@@$L74j`u)`dwtaQVz!^b?wI#>YuxS591wXbTo^bPO zo|Hxs3UHsVc!io~%MM&QPw<4ZEjKD_n{qG+TmD8Mn(a&fEW31?^LQv?6iDf0FY^E5Mk(}P0203&v1k1Jy}@!=tsVQp_SDgK%j!@|J-WAVWID& z1Lml9^adW-q+?7z2aq9R3#Krh+3QP}>05pw>VH_-;Na=>;EOYboK57@QKmKhM z&7;!*@Mv{M!O@e?O%BV2Yv2aG^G+lj+`^1QxX8LD^yxcI%{#pOhv_7GC}>Fj*MIEN zu~=QBkuZFny!fewaPX`nApM=x{7m%**X_r{jJJEe75L9)OUdWA`^JSOldG$pRZ~i( zAmAn@I!WAd&QTfa>7HS#l;If~^C&67VXSOZ^|OCgQrcPj`{F7e&&{oUo1S+vC&uFx z222#xh>0-lO!e+!QN-6ZSR#@c!;@9Ma=wrG(kCm=eOIpKr2pAH&Y8@vEb|&hCLw8A zazUof_e$jVDJOcQN>p@{OG#uNYBTs#zRCNbbXse2(x%~g(UH5FZ*oH2Y6axbhnbIH+ndb(xiT*-q>iD~%ex~~Eym84n4hbXO=v#gh>Eh%>QeV@eFWal*C|3DTHBaw-Iox1BYsiDq5 zMEBi!PY~hBaGHweCq&)MZ2ov-p@RhJFvnwfV3 zJTTLFR=CU1Zyck-wiN#$k<0gH!Ab@p2_ut0_9JHUlA{V1{tvxN_O9IwJz?-bb>r-9 zk^bBQ!ojiIPm{n48rOsy_s@YsL)C-+!#_rhxye@&*FV~ih#I>8I)Nk*(AtWdSanym z*n9ZsSM0xT6tJwKh7mXnfU+ZUC%5R%0uqmXF&D7P15Xtf8z^NbLHd~dtZoi2FKbfzGX5Y&1({g5abBJ%$Jy7t&(ecl)kNGEg$ae+IiV67Y+ z3b^LyaGuj^ONyOTWvc~X_W)Qo;y0t$C`Wu7vfH8@@8SWT{P{Id?-f~fG5-L*$vnxA z6s}{aS2^&n1GfLeKqfpk3j-gKFt_rz%HwNEEJ+0%NqH@9^cdB+*OAQ;RM8eJA4EKRyOKh7 ze+qn+V4&camH5E2ALyvs?aVCrxVeQfr$luE~BcE3!Lnq7zP{!cubb znE7vy+G)%xszkD{2w>cf8WBjm&(wL;KHYCxQz4zzb>qgLEnDL+VN!5Kgtuk1TJ~7w z74j7Fga`a=7$0@gmrcuxd=}+YcQVajXzI0v`>uIOP9*eM^iC$W`vgGYI*?YzKdL>1 z-j`@&9>MO7Ds?ur&nE0j_V(A01o!U&nP|Q=Tp_gf2V^?nzpL11_tZ2v_1F_^7x7b5 zmdFHyK16gP|NQg!sj2i+@@e8JBTNu|@}bWIjhWm#;cFe{Bj3Ja^1W?t~Uk@nuMbr~NTcS^#j=JjLT_Rprd zl+yWGXDTV(gqPDQ(%+a?fU;VSSdkqb8GK|%|2?DrXX9y(b}vgJ<%k1Ic>HEaOEeFa zOLXYM?czy~N%2^wnx)!G`zEW;C>VCBGd6_9hZUvgb5qg=^}CeUWhszTpWrEt=43UN zA7YO(IZZ_*{>QldR#BM~JG1&!1F%z9s(%`f^ANOfJ zYa1#fxZu`|`g$9>Jv+8IqlX+X^Wv_w_D|Dv!UWS?4;ST^sqP79>sw|+$A+SzeEa+h zf<}gr)Nnd3mzF0=WWTGjB_ZxETuPm))S_F6sJ;9vq=Z; z-zu*|_?t^Wt+{|%Gf4=5mAt4<67phxPQ^Qb1Xc)6j^)jLq*;cK@=gl1&Ku0wt_0$A z0Ny-@8n0vUi{Z&O;EKl=BVZ8tfA-pCvmv+c0}5#nS)6kO;|9nFK~rr4Z@7SNuNV77d68H>>w)l*S>Xrx`@Ew6HlzP?tcz1K68Uv;%sbr3t}rcCohuZpI?3 zzm?_MMeo^-GoU8J0KmdVsZ$KH_wJo{sNG@5VL4iKl@#HyK{pyCx3I+Ed%x|%J&{-T z<157Ljix&kmz9*2p$aEwm{4e>h9m~v&XfOraF{-u7r2dB7V=anZxS;o;@-DszjD?f z%?M7T_|DueL^fF>`a?EFsx^zJkx#PI-EdpNejrt2jkAJRMWs!!tfaH=hiXb*K%cRm zFm5pn!qxHSMXAG@!U<{FZmOrB38gHgu;*7@kNI zIJ>b!zp>$Q@+|$WT3%(*Nah4wr|b=JW%;C@A_rX=aW&SGSDReX38(!igzP=je@k2- zntfN(t-Cegwx77Ph29j{vv<5|l^IunP&8@qBO2koMgEFTC@(Ls)w8$1pQHa1+ztyJ z1DClh1SB+GvxW`WMZ1WqkXl@M)a!7_c>>!ZzE0AUc~{=nfTi2nAO;D;n}VqOU)L>4 zK9&E#-!fatnf_(c*<9f5NVJ2|&5q5M1SJ4v)okH_gatJ;89Ljdy zlAlJRa=r(xCm`3qe@%E~aPX@i(fM-7wouvp`kxc!zyDj~(O|L?S`tP+IPHJJX@5#Y zuG4bnbZpqq{0n8JOi~G7226MEYhV1;aV(fM%C^^!AVp>-+K-^oX#1$uiP{3ko57f4 zW%?=FAJp6o+ysSshP&^0UL_$qCZZZw63HHum&zO2;%3*a8h3~LIY={c&kLm+?`PdT zo)GZ;7AsRdzduz_qfNtW#bnjzq>B7%w~4N+XqpP}oUoCxb5cpJq@H?grSz3_peB=4y1K6GLUfci&cB3}(1*e#K<%>R z<7@uY74C_l^U+Sq5W|={R`qMbDP>jD|I&(LI(BaUq2RavYgQ|_);4YwzomHl`n-So zr{ac1D)nOZ`$U7}^$eH%UTvyh%F78$KAEnf;ArGxA9F>o8PauasQ9}f^G0JESY{4z zHssig)%SKR4m*t)+{@=99DF=jH-hbvXCU`F*qMF{$xcv~Bccl50z$P=z|5|JLgD&P zIagZ7fRShWI-Qn7!suK9-i|c}&(;D4nrqhGtl+LcXeIE2E4`Wl9VbA17n_?%puDQ9 z&|O~(&at@U!v9<>f87nS&=H5k8e~Nq+EoQ|9Spt+tK%*G!%53a-UvBDsBv6;yzP@| zkBc#ekGViYFgIR-EUV$fj+p+{?kxJ?1aMJ%>Cai|Vqm6m=a6Dv}%k%MQ*ho{1 zga;G?p7Jg0^IIiUaP6F@!%h&lO4YSY2Dosr6r) z^1NnIaBmU*d9ULPW0MD0)!H`xpo!!R~Jh% zGT0N{$A~UI*)|y*9JGIQ=j(H32R8zCbJ`kJ`7xQGh%5&uW< z#WWILBBKYJWj8=Nu%*;Z733BJ257Vu!2Xu4k)!OfnE#I(hgBqI4eliVCwuO~*uf}5 z-_kxX*djm-Ak*WY(ESTXyRDxsXg5*9Dfn}0GinEL3IA-&Ijkqu{kIlCwG+qD{c)~C zbpLk`1Z&w~9&Nr!Zo^?AhT_XaYotz@y#aNRk;D9hyS}*c4>vo^#y$rkS07Vk>ojXxr*}=Jru@KXr>{=oJIW|AIi3!vXl%VJ{ z$+<$hVytI)SSckhc+)goTJI{iCz0+?g_lv04H3ey@w#vakEbbQ3Ya9R5&KaB^cF?P zMMlnJZF1We7w4U-Bu+i))36XKCr|sqT;4yQ{397rXU^Q~umBOybe0?OS~IugC)2wW zNXh*)h1{eyRr6Tt)5V5uepv>nJ)y!H##;BVVl5bCY0Kus-_C54V=kprh6v6aq1<+V zL+r!YH?GvgwsL$gIl?QHFbrcRMwK0Pg1mc{!qxQ#>{e&acnG|u$c~cXwvey5%wU;q zuBmm$_2ObDp+-b~gcgnPd1m4SYc~%Ei@VwFhD}>8W1Fi!uVLE;R0yPkuC0b1i7o!r zhF_4VB|VfSeFAdTrodjV_~#^G>u2e|pkFkC28ZS1&??CX1!+;Rydm}-wX)dhkrJRL zs5`OzKHz=2INvOvQ1f`Ti5eXglg<^eM)1b$;Oq93QT~UFOyiS#F<0>KD=OZiEG2}F z3z@N^nmPbtJ*a4qK(evcP zuH(XIiJE;r*>GJ@-!72pqZ;vV@(Uv* z6aH*LLH;59o#wu>Ya#Dm5amre{J_}sOcuRMZ^vggDOUylsI2T2PeEPflCVp55n;($ z-tpyk0{tKLj^4*Fm&jQM7ie($s)$6ll0$lL8F?O zvP|~pDT1%ZDWb2CM$4r(gc(c7*XD;D9RH&p(-zjA)fGPj_%Qkg@WP)b?(G@8|5 z)Kj2Rz5(88umVaH4Lut@peKJVwu1Dg5H|=M+oklh{QM9y7CCv^9+xJX#sE{8FiWD<7xO;i@vr8eS7m?b{p^Qc>g)?Wl*u)+!q3z&(c6RpE zquS+%fK?z5#3H5>_jtpGT_x_@?M|)x_gmmbrMcm3UeMA8+3_$fqZ}~E?m3d8jYU8( z1VRA9M(_;zr$L?Y(eg*V=6!=EU^5|4UOT!8>W=Y5CKI7o_wyjF@sBykDI2 z`1K)U#lzbo@J@@G!rIyb@X917DL+?O^u zP@|#Ge(Y5<5qN8??d)W2gU3Zc*e!{NOJM&{tqYklAC^wS!cKqMp(TGs{`9%R235PB)JtiwYEfIG=~ z4pr8qj;%`lF>pNn6C2m`dCMP)S0K6Dd~;zy95D9QgQnfA(kU>RPk~B!9H^j7h$k9o z0XQ!jPB2=4$`=<@JE@XFky-=fbkIOzrlTd&(!EuLt-`7DrF@f3UWP-U|DOGWS8I7{Lg#4qR9g|UC$Hz+Vud6hG<1R zNjgQLNF$?0<9(@G!*Aw?K6N%d}~cQPy|IFEsE8cwx0ucGj` z#S47(oVvJ&2|Kn3HEwaUwWcvRyXySe$Yn`T4R5vlV&0?O&77bL>n-kz6a8r>L7Yln zvWol(!)p;~?@u)@zR}{`Ioia(_x;~U7!8Rx?f=cmvA3+5rQ$O%t4;=t{p;4&)|oXm37eQeX}$1EYTJnoTgTGE zv>N~z6HQ=GXovd_mOcJ=COX<7&q>Lxbrh_bSicL95H%+y1q`@QX!bA+U3q^bk*d=2 z3NKmEpv~Nid~UJ8TkN*)W<^+Otu&Z(&R;U$_9r=kt+e41WO)3`M%vejU(Idez{SOJ zjMS9bH<$bA`+kkOP>N&0%xV%o)9Oxm4Q^haTbcLNr8E`z-R1&w`aiq!QMG$(i=G}F zOFH-4@ilfxd~c=kp9HZO7;WMl%}EK6_2r#YGp$g+1Q#1z0&swSgrWZAxr^_r<+z$) zxJ9`Ye_RwC0kS}>v7nF;TYW3c^&ui-gwcFP?VTwyo+L%y-+Xas__>oH`Ud8Dfwyg7c@_!qXw9}{S4kATpL9AB92)bCT7g?;Ls2n;49z^rWLk}B_etv+cJjIMauWq z@Yc4rFk)S%3PM?%LVzyi=@8(J`RUz12hpg)a0Wr+lr2u3y5|Xw!bA%M&$647*#98% zOdO#6#OPox<{#jpOpCtXZr94z5COuY90U)Kg-q_*s&KyIDu* zrNkll5V?b6UAx3eJ*LCf%IYVau56L5zio!~l@tNh8E*+i!u{4=>pWyq2R_l6*(e_V zA3DY(r_(T8aOBn_QziSuGpL+h=Rtxd%VRO{Q0{<+qehvX3;j;|cu_w)~sZ8&ZTPpb~Of5Ml!M z|JGs7j&&W#9^U%E2-leaE+i|a0T5(V!#it(YsF`A;1m<3k$`De`-5mPBVD2-N-m5qKe4? z_7S~2*MSxMKJMYVI$XOyH-{y_wwhgKXSITv?L}=stKnj0Tc=K^mVvO+Y?i?=Q%A(J z5_6SJ?tk2#Ex)8a$JJQGjgQcde$8shux~cnuTiabakx(_Lt~Yb3SWYwavCAd%fpu7 zO4NDZWS3t&_QhhpfnH5m##=@blPwrB9`<#rkmo{+s>uy13?aRqsq$OGcCRx}j?^AY zZ`dafe;1rn9UAtGt$`$*@S~JybgE`=V0oKHLd`2YcXTG(?gfiZ*==m+=y4^*O4PqVepkOR<6UvqFpS8K;w8_eo(oN;bJ-lr@G0uH@yFl$DM}N@5WLrkI!cA~1FiYZtQQ#tNXoxV@IfkFxz8>D{O831p z%W7V%*e;rKvV=g>SNL@@mT>{PQ^et;gE-X$u}92)=&gU}wbqK1nN7IGI9sFAYRqA&pE zyiD4g;0PS%%g;n0I8159t$H*hPfr5G54Tx8_&7in(Hd(6;4h*{VJaJ5+&}X_&Z>V$ zieA*d`oE#SoBjkcDQ`ohU2|Aizu)dWsmpbY@&!>NzXDBR&~b`irYy;+&)!X+aIbCH zx=D<+P?{uOY!dL7ChOm@a^UOM;>0-J^y-km^d7$ zXPkzlFDVR=56xMPmN9J%lagLO7x#!)(O>5x5)rJ zOmUT0D8x8{s0NEY@oEuUPD$N=Mc#yC#XIy8;TLoIHCG+FKmAwTS8h2EsI^D8rge#u z+)=bP(K$9mr9gyZlm4YkVZ}Pg7qA}5pv>&bNKT>ocRYHU&m@H}hU4d4te`cyL(K-& ztc$45iZdX4=+?WyIy1GcW*1GDM8zuVR&%9Q^RJ3Zc5}P2Ry8j=W9XK7-(w7KpwSFoIIHi z4=+la0R%A{{~6CD^J3)-OXz}gJh~*nbUJdI>Jd0pKbkhZGUUs@pRExq`4q7y=FWVw zTus+&SIJv{C!A}F-1NE*3mnei$gb4z* zVAOoNu%+qO`91n2*@+EJm)@9^cskYlh`Q|Rlgbl1*2QGevpP3u%J{D0RF)&ZZh3Vj zQHrR+#-Gpjgg*0?!)`-Zamb$iy*yf%Vesw8k9NR8P(=aYAZi7J1gkZ5&J}myS{S?u z2&3oZoBOfi9?q<%!df57hhA)Bcr;x9C7fkdydXnmO62U{mQFaogE2M*1lX&qZjcT8 zH;f0;&6v_ZcnmwyqYaCQ<6Ys9n?C(8G<@#O-LEqRb#|0ex@_SIHRw8l(v_s$;pt7Q zu1WVNeISrmK{$@ARVHG2kaZr_7y4exx>1Y6uEVg*4{r&ejo)mg;-eyf6bMy}WM2h} zn0@h19wH*(p&%UHdMjkB<@{76vEK#mM`y?*V_WQ>+wy{NGFTLqinr~CRr7Ll%|J5m zg$mL-gVdKVOAQ%38fk)TpD4c)Khlzt5=RsU1};Jvx7v2dgAPFm*bG9aDm^JcvCxBy znYUw}?obyG*d-+ySrA|umMP7oebIzI6BN79n?FQi5`W8uE@+`vjk;eT3Q`CItj zawQyeiK>x)G*M8}9Z0XDOKuW4GtEhzMj=IWQF)UoI$!fafkrYBv$~#sjUUAq&P>X_ zJhko&Q>pkR!L!^7iI**+9*}os`DlS`&g%Kf!!%Mty-Pf__CcL9pXBE+fuSQ+gBR30 z*4Pn5+@)hU?PQ)=3|Uc<61@8JhiCuKB&}eUWaCRlSs57y*9xBO5@?OuOHR%3ix4hc zRO@~b5aOu0$$jw`;l2CZ*?JAH%uIdfW|EdUZXcxVVtc2{qnzu+whq2|)AYMqW3jgh zr6iI#05aC^&uKXhm);>+Nz)KL!O^z1HqLaAVgg6I5aartaBwqp0pvy1@Nf;o^;Esu zeBoPf@6n%?yfQD(T0q+6sbMD=E^Zo~6L$FV4{UvM_wL;+~6T}B8e8$qgRrbSflqIt{*fWP`jxn5^5AZd> znBo;WsTLy(1Zy)Ro~d(MotE)6DY?T=UVNz&#@o|Ymn)+TLQPxK(@PnEj!Lh1GnJ4> zF{E5R>1a}^pC59EU744dD5J;Pj^nnd-b;%C5mipR$YYoge>S%8-Jn}O)6WZ1!wl)k zNzS=3i^>qnveL8Ie6khfR3X*r6--IvB_aH3o)Vw-0T7^XtI|rX4d+cfxX$>HllqN5 z`WEb1R5kPEGhgr~(_{V18l*1>ghYwWd<)s6U*fjEyBVdS>$;PCkpmqS+Q}n+i1JOJs+PpD0z=)&`MwK0}ANuG1hq!T<1a8Sj#)D5t zISI6+ExVZwXsMErnG@J30L(UL3}23m41>C97*0C_c0+iB(D7pOlA&+%Acpi<$2zi) z4-}cnw=KgM{Mn|4mID|c6l#E4V*{brk9QpaxR9Bl!dres<5CA4X|4Lt zL74;ViY|+l7yxo_C7&KVVYWK1$9=D2m#6nDv&^|tdKT+zUS6{2Gso&)>iQWyn`$H; zl+Ao9xwQXncPT3GK;p3;rT1vRC5K*g6998~1T!k6(`cUSdK z^tvDb9zWJk*Z>t3fW_tr=U2Mn6y%{f4E4 z&#N}~hCZ-Sa2=uKG~^u$DD@hZS89bQ%IzVbwE^JZq8jSIfF%O%su`FF;9!8&C@NA_G<#^v3t(*^r???V{qEqbG@;wV z_j=ghcc7|I{aTXSqm9a{@j|!;L4Q34fpN-HNlo3Ah_pcIZ3c#nNqVsSJb=(nA@Z6f z0_>G5S5VUi@QCmUeI6Bol73L&4yZDP2FkW$n_Uaa*2%8mmCRrCj)CU03W`3FUD;Ff zoae)f-d_8JELK5`L0A7va((-+$n7LPLX$yr#99yZ#$5$G4GZCHEP-!NQgV7p+MCUB zUT2M1coRTifr*$1jXKMQW$SNTPXTIz;#K*ifLOdP3`HFNeaHNziSjhMUnpkwe4CtC zOsD6;GbOY#r3FViE8O7XQI1f&k!E*!;kr^_AE}j(Tr%OfR^U68d8;xZX>yBL^OzJu zN|$d$Ot&?wxG4HAr+4`@ht8?KtBGKqJ07^=QG4tdVToLB2zmeK3Km+TpYIpmu+kcI zabH^T)<{+py_L&fkbdIQ3179aOqXYy$4TQZtz<_jM{&a>n@2&M2Y=8fKbg{RizZ0F z;-~HHRFkiJ@%ZFfyPqIWf1kp1SJ>8M=%;4Go-XE`pPa6--laTlrvxhXP42I_6r%UP zDW%yuA~EvbLGE=YYWWV#2Xf0t+5Nshm{xT)GP&EnIM?6YpYY?ygB<&+<+;+;SjD~S zrDmG3TK#u5kHI2AD`2jmvN?wW2toYNT3S%$JrcQ~xv}}k(r8rv72X&~h<8u`G-6qR zKFr_~)BX6gxBu{Fo8d-DIX=;FH+Og7CPUqiZ{bTb*828$=b!Ry??J?I2bcjW%?kh* z`Uj<3i@DjgO>a!Cd-hNt@;|-%XzQTr@$$L&nmMnt%R$0E*dc_7!w3IYr9EaVK0Y3K zm%hM9ALPVF1@m1?bDclzJ-wd%{yk{G5aX@x@ThFN`^Un)>3NSw1&4+GHSGnXJ;gKn z`BilB%S)o);{}Ed1~xQK?vByVsCbXW|M^%pZR6!VJk-CmSehLNDm#EVbgJC20&Wb4 zi&cQyqok_;A9Y3G|Gi?3Tn}gr(<`q5=>h|BBM(>M*vb53>Bqz+N%l4Qa!iLxnd(Kh zsg%2`Z>e*8YH-Iv39PLxR-rHt_*NXbuC>6dV7ALEJ9e4c6eAk)k{aWzkQZcS;OK?bOr_As~CulNW&r4lM&Px2k@REQM zq?XntTCK-!VTk<#s3!xw9Jz-tj*Li4y=UR1esEgGDPHdK?Vr2h$ya_{3@((Vu>019 z`;&F)7U7EbxibB5 z8R+HJvY#=!*cGq|M#E1|T@0p{e3j$AohqlPIG9B&c}xS|mKbSY@08Rkh=1#$#W_a%{8Rsl{=V?`wa@`0$lf`0vZ601dt{Xd!}>eua6xV$ zPjSWb4Oe$in6bXwfJLkJ{W}2V!7l<f7g zM}dsAsB%m=KF>P!^Fua7Km#0q5tFSUz>z72wiVE9uY+(N1x8*q{T$$!Z;>j!}<<5xIH4vhZ{QRuapJS`j3#X-qP@675G%$DHrOF-!3Jz&R zk+?F(A0$y3>FNH^;4b<{@zMWD{&F z{i>7zaL2wiH9h@PdxqBFkWxwM8#V4v5mXr6?>GRrn~QmP@KS@Su}sbl!Xajg#cu_< zhU#&R(=(ih6fd5?UkU9?CVYq~^(Xgsr6W_zVR2_|oQ8mPg7mR>x~x|Be%-nioAj#q z{xjlRml=o$ecKy7O{OmI@%7A&ri=gKf?~t(##=f+e{7!`-UfZGH@e29lmBOE%ffq++Atdzsy+2;NkHjG;cA+}vm3d%=KJV=O2D|5*j_Gg=Bmp3CH;7O_ zZF%$H-xn2yqaG@l=$DHbD>M5`qob+1X9bZ;0GzmY&3`)`x+4GyKp^;<{t0uiCq;TM zVmG;$;2Nw;>^FLv0G~Lp1cH_TZS_v$&7hJR%`E~t0`eldyM6oOfWYL98Nv>HZmCt{ zT!H3T)EP$Xe@uyszQqI-ysznRL?C$TJFZ54TyA9JTu_rK^v;3U6;uqDB3qCAy4m1! z{FK0>C4Hcq3nzZ0L`5JZ^TcmK)t}J114-9FVhCQp&M_{d#6@@E0xiGskyQCmOYls1 z>OUBJvH}KEow_GCp-+;LD+X_sH#=GQm@`1T3j_e{=-vsefHhPY)a(LpW2$kxG>|(D=C7pgy!aB!KbU# zPkl&D3)YySW))8Tm!Q>VTV^CU3MLa0T7k5w@~tWN&#u|&>1;PfduCmn?KO?ci~y_y z{Z_zyB``H;u0gT&S?Z~e_p0aSJ*sPJm#-OrI^suK^YwhoMt*6jkoAzTprEmiR-4c# z99Fy|wWj8#hpN6r?=rx6%PXT`&s+firBb>y`cqvsB}n@7EfYK{H$#q66Q4l!mGDXg z!B6Y42L8JhRYC%rVmPUsyM;~!^g=L*xv@^_7#ZD_kvX0!7iXrpL)1Hr-K~3}`lp2<_ zm8-tE!LdJB5C00E!SX9T^;rz2lu7DHkeVo{Pl;rFeF})8q)*UYfz8@N z@q!|0a`t=l3qtFZHz_(%QFVt*H&aT|#i>N=r znJy)}CUP`cjr-Q@5lWSX`#yKmF=u7WnuLLu%+k=0!e~dcMk<==9rMYkWx6Zl4U6~O z4Xf{@aDolIri7&1m3=Fs>t`@lJXI{L+L5`hzm|c>s`oP4sR5TaUT1kOi?i=yI;kEF zkF^ihif`pKJxCDqsIuK$2o{4n5p5iy05M@dku#q5!MiRCAJP8- ziJ9CDoMc939u&hJqZq5i)h;qlk`L_h2yZbF!?-ngx-CtufgMB{P%ziHwLSPO@Cw>{ z`GF=(HWPP-vlWs8{2|S@_se-;Kp!UU(!-pR6aMgb$x|4Bk+&J0gRQ&YacwHsM?S~Y z{!X`Vazs8tge$iZbhk!wpk@g$?H6Af0$AbQu(G2;4C==~VEOLvCj&p2kLbmxbxhZ^)^gg9-5%W6%&e+`kLHWc zy<0gj>L6MT>6+Gx+d=RI7u5}*IFN>oR>+0|ql6;l>kdTGtPIwQbTv-EXE~{YpeE@A z0wp}ztUUi4xi%K`TR-VsL615lkrPrxJiHnUX+R*#QmERy zhJtu+Oh(1wY>WOM!rlZL>vnA)HqT@%Q!*u$gv`mTs1)Tk6e1KEq9~PQ9y3-#GF1|V z43QyYC}l`xN{B)TNlK~jxZ3Z#*7v>tZ@qtO?X`FN>A7$B{kyJnIF92yPRp@hLw_|_ zY5oxXrv-oYXC{Ua=+I%OfJdtRH8_j1VGoKqtGx8K5}zq^slCZ{d=}PS4!>S`3Bw-! z2;g$--FFTY*UZ;^M7}-sQmMxiwlo`Pp7?5AI{<06Yhg_@ahAdEOf5OjVeKb)Q7P7} zmVx4}bnaw!0CRztiZ9M9iy;5KxSEq%Ub1=0<&(;5Dmby)JrNS+D&`9IX8ZeQHs>Ls9a_^ah* zW@bU4iCJ5Z7F%3+`@ZW?=s8g{ZleRH8XKdeLTBn#MfIiC59%bV95C9TGR+kJIKSd% zSC_$C?M&V$=FWF=eOY=Ib1O96-TC@i)<0i={re+@C+qZ&%xk=sD-Vg6-qI;}+iA2H zt+IiQ?5=*J5mm@ed0!>=ZWJ0|{&oHpch{qx+$ENV;Su6i*^idimHPlniuj>Mb5!jH z4PUPG!8i9V-4#3h zROOHKUBkbAJeS~|rg!G^DACO_&FbC4L=`h?sTyl+qq#@(3T&W0pR!UAfQTx-?U>=6 z2EQAn>bK8l?J+((c2_3ms_7XS!AZ_8s$Iq#qognJZU1Uw^gZv^O6AG^_iw;4S5Li6 zn|vR8i5yN)GHg9QS2Tj(rV`u{|0&ru83|R+-`@+w?-P>zvTkr2T|#t z7Ej`17f=Yn5M4~|ud3R{M>9K~Tsl6WOxBnaWA>~p>K-3Jh!)HmNiGot$9lmOgLjw2-4l&hYpV?vZINH z^la6-`Ke17vYR8TbkRB9!1mk=7cLZU!C!^U@#{|wa>20w4MHG!o3BhAKxU=uBX9#1bsnq%ToEjIqVWxNTC1?9#utb|7T7c$+JPh zcg_xQ1-u+T5Y+^_8asf}Mn9bt1n`TK1wVWai;X9roY3l_7q ztZco{?u`autgg4AYv}+>Sb-x>^2XT|uZJ?xWM>l0AR&~&&3HJ6mjCTi z8Q1!&MrOXnbHN-~%kDzmOEv-%C#A;lRkNplV}}=!^!~+CKGV}NMKaO&#R={(bD$XU z?1sw8W3b%?L@lc}6f8RYx8&^m5enbWzn3!396le|>8ekyqhH4tv)k01*T(wkS0<+X zDs5-+n|9KHA&CKWoSr^gq*e?EUhrW@F|T zi=J~@ai0?3U1(3~NJ-hg?YM2m(v|(1kw7fElrrJVISlP%c<2%a1Z55!I8f&$ye~sD z2EErZ!~#b5XDc?B0&y~vD-ocwG4B6CKi zb9`IyqrdL*!OA&Dg83zV%V-y<%jifNPL=T^% zW>AetWKWdV;ij(;=IE7t_PgAe#+Rd7I%xcH-8fBMI+xr*TA8}^$p_|*8hd*3#dOju za_A#e1{I6Cy>Br{^2^;BHJo3^8H`ofT^ye>)=saI{JTvhq00JKhnj!GO%r&@h*;7ybRUYu8%a+MrhYtvz)L zpp+++2K6JJuYdMIsx;CR$uswBh3dtxo@@hF$qgG0zlbJ>7d+4?>Mi{1^78V|1CO?( zD!S;#83c%)T8rxM>HC@s_a5^Y{drY>@(4Mre0+SoV^MK&yE@W$Z1g;^MzXi+>`Al+ z>+o+&Z`#xVQOGRFob=}&v3V(cKr5QVFVrCYCqBJ`+4pPLs(Wj@xlJqSxCDs~zq+$W z)q8?d(n#0eUz30cd3l>s)6DSo@7#Ix$J~fBs?1P6Bfo(%*W=VW&w?UzTvX3~5hfQM z>a-7t08jBm0&wXgvYCv#J1c!$6RX~`i>kD)p>QMJ$*+sJQH6ns0ni@y7%+Kmp8|A zsOhjt;e~ZFR(s3*U!9qEvWKa%+gJ+HxEp zJuxw{Gv8vX_vhEl?)|0rN-nKmT7;>E>bb9yHT$1Ed*<9zu$DgAPjg-DI;~h>7sK$D zR4K52OryiunQJQHJ@uBImVr%sy#1z_(JM+y16Sq}0!8V*n`)=SM2=7>u=!zlaHvdo z>C2!OM0TQTYLDO3nct4n@cKX}Yh9sD{gz{`dL{taZ||>Oy*i9ew-=%)j&+)Bt;eI*;P>Se~l@b{kGyFDj5#h^dj@B>3OBa7!pPCf2K82tA64eQ2@8*u_$Zq_-x ze5m+Xi=Lid)&I9DhloZ5uI31~1O(2R_DJ@N5W}TTwea+d(B=sHtPyc zYJ6vU1_tyi7g6eo(7#b`tN*4V{m`nZ*p$NgbBv|Ay*QhVSbNP(E9v&aX|mx|Kq1e97Cx9 zr;b95R;GC}Uh-ajn8TRbG9H#E3`ecr3aXrZe|i0$B$EYJaU9(WF9$LKGtv7{f@&D? zguDyRx!XAo4}Jzmt7fo;cuE=PGZH2$W1&W4Mk~#*qcB_A7h416ot|GUa;-#Bi*kkx z)Nd&nnr*@IK{=0is;Pz^C`b(V@4wqJ_tTFcYM7N-iSFG~7Z}{id_VDTN5lhq#vTu; zoFnE}UURvr91HoK^W;#QL^XBR{3XjFHB0wT1zope3Tv1cEF?l|8>*8XYu{s`3F$6z zQC~@ZRBG83W=}U$n=e9}(DZKXan`_0jzg@gyz^!mnI_x@uOD;v_?w5m8#gyKk=9cW zXSLo-_$x9pjQi5meOR)k4}CxJ+NtvqGPL9IWZQ?)(UCJ%pg44} zR$vW2#OlVPs3;atGV5?5LnMucRXHF==OFuDmW)(y?ju)vueV-X%tcB#d zbwT5KTN^3dNlfJkAI)pFbF9@qe_mbl@9)zHnr$@?``mod=aDV8db|d_e0=s8V)}uB zVcqX1lwW7YT;5+&QZf&iGURe}ut9U0m6a6&@V!M}$Bb4e80H{(4CCj&GLLTJW!IfO zYbr0*%`Qo7-MZ@M&z~l|^m%!@ro8wbK7e{Fk^Hi9kF6h?{@}in2}h(*QVngb`XSxSI^1?=Q!eqi3;Wh9CU#%`T>P0KbLyDdH>%_M zmtU*3GbP8;uSv=GUuAz!kv8vyf{mj`hgXi6^`ffP-NiktD*EPy8Dq!m7ij3x8P~`i z=L!8>Mn}tFMhUzx-Kn@%vv1YY+3;-Xxr!ag)h3QwycGGhue{kS3sN4rXi%kx+tHjJ zrsI&kOUqFelALSU)TCeMQBwc$lrAs5XWFwxrZg&BIjxg)NymJT<~C1#@_JmiKj6Is z_vYC9cR0Jx%T5eY2P@Yx{T{R9|FFOKyKB2kgifi>%Pjw>9nC27%6e?|_U+?9EjnS@ zH@h?nfnyWWUqXC5=cAiKVS(Sid6OwQlB8>w&exD3JYXZ7k4|zMaBbM1-bAX-pdcFc z<2{P(^YinVrr@gdo}__Z38Mdzl;i1vIWFD>lS{wwiUDX0>7g@WZ1E!LHQj&N1*h(< z`YI-sOJ)>4E-o(24oVTuGB@wgh6_G8?ha7)wmy4SpT6UQXjHb-AFgW6Olg+>NAA&Z z^~!c=iS2QGwe!pAW5=W*h1=U^F;HFb>EfxX!HKsIgfP7lo12?^zAyjh!nlOGx*$$} zaL?3(r{9Vzhic*GE00N~A}RME(aihz*>K$Iz6@4z2?@EXpr^LM=;`kdWZb zJ_}PTVp{=#$H{8@eYJHDthV~tgi9Ln19=mHm0rBaC{9(~xVAtg0}_9zP^6h&;lcT>NEw@Fv^@j<=`P!+65P z+S<)!30cGv>uG?peL57kB}zP2WCsR4&4=ek8WkDJo@yn#yz#mDopEJ(k+rSeFfj!1 zpCB9%nlNZH;;AZKa^=R2Xk2(ZbQaLh|FO3cDmb^VSW^wo2)LXTwjTPt2DsB=Dk^J^ z`2W0fCnG<9UxM;d6VHA-q=<;vSdOZl>!ZZq`z;s~{#Q^h>Dsj{PZO-p1__A627?FssRHaw zIu+gW!|HtBD{|_^i(Sv6)OP&dD<@!1%N>#;*COYg8@Os?9<`NumbBnIih_oRmY=Nv zqGfI|L+yR-q?Jw|9?91}S2_>+X!o$q1u+>V+Fg;<->F|G)@N6~9aXnzgob1|-Hn$F zI%9RLQp0!YggfQLZNi?S0>RB}4#!1f=R2R%c1J|7; zIV$E;)gl$;!i%N(VRXThuj+g}%?;z1-vtKS)9w2vLD|8TuPpQ%Nf4)vTuMZmhL5MZ zA|K$C5Y!Zt25YjV!**Pkjv_S;>T}MuYuVGsU5;$SdSx=iVqd>ThtuT1fgolcDZ9Ua zRuo5KvZW1o?{2{SW!Jrf8>qBVmBV-_?8Aqn{aWWVM7(GE`LNAfUssm~LnV0rWa8Gh z#?~-V|1YbiN}#->6$dq&!nSQ)kYcEd=@j-vLvG50Jda*%D`2f~)cX?R;z3gH#8w{k zOc~%t5F={x%Pgi!yeaRE$9=xG*#dE%CP>sWAZGYU`|Q$T(F1WU!I=7EB=t)7;OvRiKe`m%;e??Y6NhG!Khl&+HF`w1jk0ToQ)CZko6 zvsl|00dEH}bd;SLuh$)c{m94Xd}MH&%q=|lOQ)fMgn=qLjF8Fr7Cj$Zm$KCl9i-d& z^`{^HP=Rnh4~w^35T*Gf86Y-|k2}1{qx7QC`t7e}d`v%fzqUBOHiEybRp*u16EIr zH^Y@aeDMVP+WO=N&Bu=)OGSDvYZ-mpsa*>MlnEiDM6x$eU!ieuk~E`YQ`GoYXcwTUMB;m8pl}WYPqbEj~Hf@?_2W#S`dJe1FZ9&qJ+X zs`t#UanpgjipIem<9d#ck_>G80g&`(g9$Ht&tsH02j4B?zmIATTUc)2rb8dv3>Run zKE6;V`jymB{oUJDcXp zhW*WCuu|RlC7n(k5CP&|aP``?uJaa$4n@K8QxJb6ta~yf#|17H>FXm8dwIz#C@2sN zseXK61hKsZ6XPbfwj5Q1`_^b0ts7rFPikE9+@0T7tKpMK8uiv*(z5lNH^A3%*}sFX zTnVQUdD0%$Co#bJ>`pr-vYMCI4%Kciw&$SlV8g44eM@!lc*S^j@)bS20O}#AKB2UX z(CXymxmiFTrM4k^rZ+^1qje015SSpN zif8KGrn65P2R;RI`qgbk_=W{=xF+%Ki&_x>8Jrh z*I@v*a5?3i`&VC$irFW>$goJI?Xv}q-Fx=P!|wsd@^HF5^_!_y$H9HP25suw5{71X z5u_v~#j21wT$Jet{IuiK)AwD8{OPAj8itgVly6ox#$2>fpnMJ|J}m>Nfs5}v^kfG* zd6?Zq;aR^bGr#e2XGYBm_uCm&PtJO_e*Zz1g1>G9BGJs7O z{3dt2`LEaZZJa0Ck691epI9Bq%A?Mmd&K1m3{&w10E5ozm@VKd5bNN+YkVV&XudU1 zyXEQ#*=f>V!jZ(zf>-emdHeqAeAkJ;s2U{NdHij*^s5!cGJ(<+faSaP?Th``C)?Me ztGOrrLHB3Q-l{QA)j1&L*#MYc2e^SYB^P_JjW(ItjzYQPu;a$dWAfiVsK$O_Cj&X> zzfE{io|Q!+0)wfL$CoHLWS6jFt|TV$by}s@uON%T9mOl)PmBjC{Pw@pT9GVVh;xe> zQCcu5p?E&(8I9QDjjq`qmslEJRz83Czg%%c^m~3^n#EeSr{ien&dX!4L!XBopjD#G zY2jTdPwG`tjJwodul38I>JkY-WADhcEYVkf`XkZ9IS*ELzio zOWR(&*jrh6H%HO9!yVO}efyp4zD9=hs z)tkx@iBviYF=L92a$9Xw;8`rExS%BOe(T`*cB*x}+_cpDSQ#>DQ;!Ljx}@qnmOFj_ zY2c`Do1aCG;zW}oUD`R0^i?nRAR{xTkBc%LyU*TE*DzN1$DX1xym0=dSNezWs#ol_ z9cz-umyM;KcV-Ex`%+a)2dpus-EPY(8bu>6e$!KZIwIz>wx2ccGzVkazU}(4!8tcn z2C9dIKYnao8TSns{Z_ZtC%(=z>CM`9$2UP-8qbe}$_6Aa&fS%FmRMjfE z)rebj<=esAckXmOW>4W^2?`*91K=F|Au8L@_y~&J6Y_~0K6${%LdVa~ulHhKhTm6a zs1`0G?)Q5*Sv5lp5P))B3^lc2=?dl-9=+&xvf62FEo|%m(+N@y8u)As*9Y^1w-!`7 z;Z3=iSTI%8=SI#MHnaq)_ieW6>AG*VZB8Q&XA6DU8<$-Dw>*_+W}@!jmyuk*-p1#W z(I*{}7LhykE)Puoas#BV?mZFkCf`CrN-D?vdz7CFX^_{*TGt^bHx#(Mp8mUe^JaPY z>1sgNX+L|~#bqNV`67YZiAqT|H=ILk3*|4x+9EX74ya+JH*RE(l(#BjF31nr!mr^g zN0gsKJ)Mv4NVCA|C;}>}4Q>}7Y<_}z6ED()Cd5Ui#&#LtD} zT_Z9gA|hY8SkmhdX;i9a9>qV|pC~D;?#%?x1{CZeU_e?%b%1rr!I_r`ph_RSE%z`u z3fevz4dL6z?<)W+-@beIR%t2kzPk%~&kgpzAej;UUgO78p-Mab7GA2%LoMHB2|)P+ zy9!&q|EPIn%>nJK+&gH%NpEv2CcD#ghV4E*z(8eX*V}y)DY(T4^E1A7(wkA zM64R@2hJ3EIe?&=`5W0aLVVCxWd5&hMAZMijqr>YZQ(kt(4DxsH}^6tRgj;jt}qSL zXX}9Z4?%m|TLV=2xfSEw;}<*wa;S^*bSR3x8VY{4?EY~}My$Q{3o%{K_ z(~P~6qcw`brn`Qg+OYGBwwa@(urfl#266E;&h=az*Xgbga&)x^ui2|_+@0S|?b2ko zPvr<>uhtcp(Y+<|vAQUD4Xv~XnS$tyR^*4C_ay&zuH?|`-m9I^e2sR)949?BO-CSp zNt%<*+c_OKOHM54e*cx#s*snr*U%(s#e}y{QD>Vsf92|cWmV5?DkI+dd0}5MD&~Io zh)4x7og0JH*W0M&sd~5^)Vi%>SKoMlHnxX$NkLfBIVkSfG)*Y)ixUTCtnVJARf$D7 zQH&Rr=M$f~u6;l&6sZe{e8RPB^i_i%M*INnLcy4lf=z5DZTy^>xj88=drOYT(JL>U zubJq+y9#%h_IexNYLV@p!&KNXajv!4&B(kP!3G*rCLr=SdAnkT>#^qfc$=d|k`vgV ze+LZ5wthhaHavfSPse9wOA{bl{mgU(iWNQ6tB35@#*P9t0g_Lgc}#EZ#5S>fhNK{| zdXmlhVGQ#I!FjGL z8EC*sT)=YF^19u0sn1Xx1Je|X5?7kY%TL14Bt z(h0il{sc@UmY^u%7Zc{#b<>MYGd;&87ic8lanwVRq^~hn$C4B91R=mKN6<&}K6)^F z$VPSzlDrf3rNXzF##p+GkO6@CmiF3vdUW5>rjr*a+-T3;u|UB4gw)jCfzAiCA_E=3 zvz(xhG@}@Jc*ug+VWLo6xXZ$tKvq-?dXUAiq$)w0)_snBN-z)Dj9iliLJ15n>LNsm z1{9B8U*4%<)`0Wr)2HY>>}OeBdO*XGf|WSz>hIds#-uSA=-K= z%Y!+4>&ce&B6naXWE#-2_id_H%U+LeuA4d2BS4Ev9E6FZqhsdT z+4p7NjU?Nv&dw6F-xEPDb#I~A#pI#caC?5T`b-W!SVcQ8A-IG4;N_NVzB87JfTi=& zsBv){!Z$Gt+A=STOaaM!B-C>u`~tfZLjcW4Y}mjE_Mo7QovtO|+Z7a^I(T%hq56R5 zENnn%BPz#xiKmTSQv0PW;|$=l10^8>(|o@2ndLE%=|5M6fBLrpSTUZ>&kr=CAseU zuAw)7$5bU9mbUJ#H$N?0(4YH2>}j4r!;!33RR`Qv0tcE=%IY?-=NVBil-kyu7X$d^ z<>j>~Sh_gTMT=&(FZ*nl0H=x7YJVTH0mg;I-tGtmS!otn)kWJ0oyQ z?Q`eO1ut1A*6hUmObhyJ3xg}>Zy-3catWD+XOxOFl zxpmOiM*;ts9;~|l_Nga>`orJAFFb*u~l=;%>#oG7jX z%EcCEA#ET}yxMk_Qhtt#NG494*hF?zS9XkD7d_S)7O!3}sw0J;oFljRFHn|*3qaWW z6bQM!TFt-hRG8Y+^?Nx2@3L`p8oSB{7g?MaZQp5^MxC6oD)~~1T->uY0#x37CKT-? zC24=!;v=Cg546qADh6%M%zQ=L{LRcOv!qYdy|WC4Vpy|*{bn{dbN6Rqm**gLR zEQ)4&AM=@TIwM}ueo6I}Prj#K%5C@(=JNg+{~O^HtM612d>WzSd;Om~KBAGiW?$F& zG9%5tvX9GQn+>D4%`GYSRC}|nDs!K@&S`pzy!U&#z`&*#Y(HUQMqiw#OHuM&(QGYd zqnHn$v8bP2&`IFSO{EDOuRHxIl$mDLGbx>TNmXkO!!tsXM*7~jS@(srCnU%=J=Jft zUt?c>fMh9+jl?tJ}SQADMLSd$M$>F zw~R3R&Xp;pn39HPQ;Q$K9Ml60(S7koNPSf*j55h|&xua+fyXCo_oJRxiYV;Jj7c8j zYFt`=zRNcmr_=$ICU{DRh`#@0iZP$eCQ?_DU^*8I>{_L zoPsZYbDAH=j-y^^o|K$jo&5$;64or5J03fRVs>?y{V?ig0vB(ww)eaoJh0^_$Afd4 z2#pBGAFy6vbE>lY39E8WI_h6bvt*x=Xq$plhT+9Cs>051^7s&c+cUJ{z{o#u>YX`5 zC;?E%Nfjy~HR3*_0GtUzW5*wMXYc|bK)@NKt$%g2Js~6s}9CMQj?uY7xCNXC6Hbh_XIn9IQ;CZ~>Zx z00rUm@Qb^jUG>mNObnE7MUP;)IUjAdDV$N{@2eetS^UPDht(W?2f0bNb8^Dwb|{e$ zaJQqK&p-#Yu;Imm{H>d|YjXJ$o8a_&2^?n?CLZ zT?1a23-4C?C1JLabX@D#ub1;zkYR8Svrip*1Q6rSojaaYgWnbwuNj!~g68Ky0s+I! z9t+9{Unvx@o6t3J78mSZ9zbhFaw&-{EnPl4Zr3uEw@)to`17Ki>}i-yrsxymj1cPtGJ$3AF@{vRSq~(uvQsr#UMn%5TRMBgf!QJ<-m@|74O% z@o7M|Kzz-n-|^V7Y&AdsU&8}uk2>n^^spJ1R%4;Ez^Hefz;mpxlj=c>NGf%=GdFXvi; zz#kRP5I3m`)A)MkJWDgRu`CGF5o%H4Xr4#UoXyu8)j+3Pj~ zuf${?fsv!KJ7bn^+ib(|4fh#v(9x!Thp$%)8ZFleX?nx`SP%Kcph z7qH}*r9qXEkC&tn8+UFUG}2c4@=vrIL1`2OF)DkOslg1rsi;&J5HI$PioGSnLOqkd@^iJv2k~Vx(liVIY0z`<2hj zrjHW^B)kq@AC=q1-RX4vczBKS*FKa7u!>s?UCK@RxB0ob+J_DaVv0srXWGt?lWOKHvy546Q`CQf>l?yetWN4UhhLT1slUx5Bju)l=Njfl4oL%$!oI6;#6aYLbyM0^`(`cYU2}2D&+Nfs+ z6f^>*Jp6plXWWAm6jrl20LXc*8mv((J~h*%uao3N0xHVc2TT2bZX9KBCzbQxEmk}g zLUJ^P-wv_$`|dfp_RsiMBgZ2qW%Fre?|l3P>Jy*d%=b!mo%8#3CrYDR1EMBkc_plN ziVlHXky_0tN~HR_ZnvUyDhQ!S03{z1c8Syz_-A6mS=~HAl6l?5Z(I=578;TRLf4Bcth_)7|f zLcY-Ak`jABvD>VzlICGi%1(4A0MhRzSbNeq9MGgtKvj1_=cj?4AQM2>TK(6e^Z=hjiJY&oCHN-bz}r1uKfgMmsH3LB zoIE42h(lj!&o?45Tdyu4VTx4WDJei~L zpa7yyrd~<>YrP_{&DkMdl%Pv6zPVhJcY%ZRxozl$2i-=BDdX+<3)}Mp7q0H076M#@@{h2fTLHrFKLe?y93Nu_)a~|M&OL-pxn- z4s_d%9~yw}H5ogFh|;UA1YXYJnirSt(7%dZ3>IY~p3$f@S2tKB_&Y&x$gk*Z^59)7 z#*d^6^)9~xh!_FwZTC+{y}o>CaA0l23N50isxYcC?}Byjj`Yo(d7c%&G7p_-Gjw2` zAW)%(8Fqj;y{V;zNMihJ*8!;UuG#S8No(; zezCB7vh@Bc(9%Snh4J95wEZ^Id}rL^37UkBdFnB^VJ0eQmmyqZeSGFtS8otgybH!}#BI(m%Aq7FeYLhEE#Ud&I;_|4ch(5@m5YZ*Z(yG>-o#5mJ_GI$0MUY89@E3ahw8EM?StWt1fP2l z58%xkPz>F^Eh)1G;XjnbM(DfP+bV0IKWlyYGE}B5sq8FwK5P#~h>gR4)Rzx|au7CM zB(CLXtYP{F4a}!NMV9k%`*7`3+l0kt9O0t?(v#$ap|K*V3hD}+{M7b6cy^&=UFe0S zFSrBrL_2$6t82mhl}Fm?w~$pE8g%!jDl(Hv?P+zNS`__yBs8YulN)uVzVasxdPyu6H@x zAho-w@8tzaBN{gjX5}hp!BQjc^=r??7Um4qF$xdteHXJ$wOe17s+K?;Q9zwz|$tp-N`vO)R`n9BkEt z@`slmdF2$<*H_+rz&x0!&Si53(7AI9?_-p#Vox;IH@nRWfnqDuh7Z}d?8>91B$>3k zsEk!+g*L8cKBzR|^41}ETM%168{J_05h_Wh+&o=s2+94q4NXjW3F$>-=QFg1x;Nov zX@^OBG3_Afs2@GGe?lRm5mi=x`&ES|8wTPUbed=maYBgH@cpH~7jbY7T^=M_FK863 zl_Y(~TDgd8LW7K>_~C7ul15x9bV@(9d!Y$0ac&6gQeyMNz9_2TrvZEp*oH->8+w)xnSJFjyIx87G z(F3!CanCyFML`UA3uiZ@y4BY(4x2=LYNcS3F0Z{9->KH96<$9aj=>4nxe=; zsNo>8a@-BhHEY6gyN4lysooU)2tvHhWo_;qZxmU{-AAo4kJ$^`)33H3cmg&7cx||@ z7Z_5&;8=3O2xf0fSiI7&=Y*(KQo3fFk>i3|1Co1vh=wt^gf0n~2$@@`uGWaQ;&&+_ zxroSp0Pd?WakGV08CI=#*ixsMo!1wac)IN5kcgU^8qgC8)BUFl8l(imLl>64zWKHm zG!+ri(R#rD#F%KvumwJ2nB>=wsvLkmCSKiPMX`AqK&@rJkxhJN!BozSHiczztjY@qDc71anzVThdfgty|2oRg044)XAUO}5zQ(X9 z(m2NrlK3gybYw27yL9B`Wy8S{*mMxGpslS4{b$$ow$XXfEnC>*G`>cBwEhds#+3J8 ztqUyt;kPW5cz~tJm<5noF(YmkR#vayKfI;^y`fcv!eytq`RXqfqp?u9Kxjxx0LE1! zrNXt)LXdX`Tq_{i`af}vZ?}+?p8Wp02lNJE27NTwoyY|`2Bk{?!ejVKm2{NqsWB#^ zQWRG8q{3|zYvygL(@t{26w$4dLr<`v$+tJeRq4)@I^oU9aM(A2OqA1^I>AV|J7d-f za^FDxOSIuQX#qV`W%uXNID&>pe{KhPCqzI$x3*aZ3X}pkmtT3o^4BK&MqeK_)uGl4 zK`KL3Sz&JPwpOIoYq2Z(9^pLuGV3=bYTA|L3^d1{NY@w!%0$zIi`k%p%L93xE|Iq* z-H|0;$d152oPJ*;geH}+ zxdDKdkkF~L_4Vnx~*v5 zB_X%`u@D0Y2c&s|$ziIHoHGJ|WJ?3YBd-U|l^0ZoS;srl!E2Im1O#V4-V!4KXeWPT zOj#e_^`w6ksa>#mO!f39w!!YDe>~cX3ROhUEQkcja1*g0z=#;e+W)MN{15T16ZDT_s@*C7 zJ@1SBY3U20f~RfQ)_?gR#nTixo;UuDT1(+dxj2vA&EN0GiueAJwli<0Z|0|#jvRfl z^tsZdGiQ^!86`YNFy0B+R^zP2$ihYwUUtolp|KJ(KFtg*yM{YD-853i!(3dO=Y!6% zXxcS2pB_HP5hSfMOmCRTo-G=%hAtwT&QsV|C#3F1v%AKIPFL3Sq8pav77y%+lJCrZCeR_=74RniO1x{+aO#&;-S zq05^+tU!kr`?ERMm>eF?upP9J1O5sF_U%L5qyYHKPFMho1P#Ce1$L@>0)P?u1 zf`Kc^Y72<$L@kKCe4vC6Ee&vjqaUAN!^qUV&^L3w8bsiQeZDt~e#b)Oj|UT zl7ZqBupz-5khp&-JuOG~gj+!m3sw|GM1F?r+qnqh0@ZXdMx?VbCxBrQ#V2GI48(?_ zF>S{}F4(yWuhF8DLz)P$w2+_a4n4Wpg>`}Pvm3ah!P64)K-OXyzd828u#w?<_rGI5 zaIG8BMQ#ip1KfAph^HF6Ih+9*FwGh!UnkR&Si_+0=l7fP&;sukf)I~tg?yEVU-U(A z^+A_UeAxa-e-E77jeOh;EbzFzWPV;=1Lmf8Vg1X4w>}U@CuC&Ap#_5eQ37!Z@|AVO z^x*k9hL(&bCqQYK#tVA-?OsI%KU%T+criU0pFCO8niK-Wf=B8GB0R2>V|%081n;3*MwJ@9FQ|{L11)Y8YTj2iR@EABz^9;5_W#c`!T=j`gwARw{ub zu*-;k?H%nmL@Y3iZ`V)TL5>Sa_5zELNIB6-7m<|d5tUWNpgMESa*zkklcH%h7LHj(54 zHN+&$L(lRMiSt-&>4h?vwRRWVFG9%mI>cEuFTpVkLAABLeW$&B*2niKdJ#trDpWkHUPx3_oiIr_=jZQHhy z!x{bf2!JUvvD0r+Y^L^q^6>wk|3?dB-w&28^)J^PU48&b(F((|AL#1ZEnr!`xpD^6 zxmwJ`+r1o99ZRJxS{FwpY54w_?zymb#sGDWodMJmnW8OTI-hLEe556FPcWESg=bGd zDx{gg%zVBE^IKYuR(G^0lw0wcIRc$N3zc-X3dYa%se_<8Y;_e8?+Cswi2(xBL}`=e zg}|4e)2Pzd)Ezvn)EyF&q}+P@MdntfZ-#qcFl{oDqP7-Yt*-cHFH7!Z&WND5whGPS zOQzR)6FHC99uEko9z+);?$^UYH<) zhIf0Q`4YF5t@_zba3OjlUi&M1J55=s(sy=l`NWCEtipF0ZTZK9hVCD1dLirkrIGRP z?^!6Aw6UhZvE=W5uW3M-4j2-CJ;yAka~-fX-23?uTC&`4Qb|CYtw6NW7=LYgwTeFs zEs#6}+`oy0ac>g6P94S+w!s896A*Y;9F>&Hqr4h9;F}F|(+d z5tl^i@d4iQuRM&2xg(nPUx>hfM^((DHq;1c8@T}mpuYr?+9DCB5d`m*EFhgI*|R;( z@qxb24#h$3yT=U%4FfaHcn316aftC;dU#$Q(VA#3Pe`z6a}_xQ#3P!nm~DZ9r2WAX ziHsl6SrX6)Pxh69A}=>x03d0x?b~nAY_DHhz>sG1kNHudv=?QM=r=XW6(Kv3rR6A> zzMVuQA4 zKzu~W0#59UwvW{0yX`B*$v{=ph6KP*w9-tPz$h?2i}=V2mLuDoSQW zK%f?o4GXD;k2*MPoI8)1SvYbK31pIgP-zN|9kH8cRkLu97v*xf4jQk1)_-X`nZXA8 zhH6r$^&I*lQ2r$J;gY%Lt?cANi?vEWB66lJKTv|~gdf@XnN1A)amfe+w$l1aZBRVn63mj&W zWX3jS+Ep3>=x{BYM{aXKkIe}Fshq!n%cKg&natopT(FOQ?N*!0kQgDAqX?i$=k-7I zVAOkTY%CMczO?<13Z{>S;>af@XV6KUAp?nB(aPRa=-Gcs<=~#eOZrx1++J6)(O*QZ zhI+eLJ18_Xlpm(8@at>CEY|=0@h=5GM7j@K+xMAEjD?Zm7of37ymG}wyvkF2%9YIY z0dn-3?v+RC?DlzzG51oBK|z8blG$-+1F4)l4^?9-1d=w~Oolo|ec;5L1P{URW4>|) zDlSqvfBpK^^ZT?_ZXQe3U@U|>rRcOVd6wT3GWu7Sm~})(PL3y;ww+|32wbr`->LcF zbB1u9%CM(>Y~xB$+qoDi_cFf4OMZUz$sIS^oeEce zk2g>`H@vNEURU2?QE2@*==t;A2rBSF0AsW>M$mL&t4)tfkR^q3Z=N^c&=qsmAnn2% zR}(agm3@p_h@Gwu0Fr=_nSvOepa z&A7y3{N<%*Y6UqjMxO64C@e1KM%i+#L=2EOQ3OBac)#Bu{Xvf#ZK9+-La}A7f6e+n zFN6UQQ(h>bUN5`ZBucssJYtVty#+n}-SI>x0aQs%P&+$kFIV;p_WdFxF}{P!jJ>=D z0D${H1uxb8<_1KV7iZ8U`u~N)<`6!z0 zZ^!$T@Li^oU;aKQ_>v+V^zLp0&4-Iw1w|h$Y)miZMtq5y$Sz9T6fPPfsm-)Y4jv_U zrNgBwiwdHmMJtO7)_krE63^W%PLm&GsCvry*z*0Mb%T_Y_7{@EBL%DWr%N{8j{E%i zb3y9zw|q{ft6Gh6S`DiCw(n#QUawSZB%-beH;kL;~D_I3x& zSjrjqNR+H)Oq%>cdnu!lU$`Zxkzb}I$bGwKGSA07a#UYBSk`w+hvwuNvM^-12+{;n zC0+^s@+XHO{_1_5ZZo>zRG~lFoVhHEX-eW@N0YajJ@_24&xz{r$FnNQG2umAp-(wx zn%JF3YkP7o7*yM7tloC1>QVE*1{OnIt>xBV7T{II0!Hro#97nb4=*fvkQHQA;A*{A z`BJr`rwIoFe+vs?vL9q!{Qx9MAEl|FvYT{&oTut#_+$wnNMsNB<$j@fYo#v@0?wI- zAv0;Q#XSo!g$zNi97GJCr}8ak8Y$zp^J<^a%I-wGcF?#@ME983$7ny-r53%5M9W`b zQzg>%Zf-)Z3KTsvXwbM`W!v|J>4f>11Wn_uo^@**%x+%bi_|ABBnWB4*wi^s&%(E6 zjRV>Q6ti3X>UWQL@?#IVJb6WQYf;4-+)F2*rb4}`gOlA<5#T<6**EPtksTkBY`nFW z41az2J-hMFk54yF5_%;&TU`FpaefBkr2!l8Ow`v;6!Oonz5Q?7>JQYh5LK#Y;(K{x zyO~0Higl^-Fi`Z;@YNn5^a7N!2=oz^7HHKmXZ!H+OOO&FXbJ3h9Z$HI||?Xo9J$jB#gLChBBer)lM zIUhdOPLp4DRded*ZdP#Vh!HNpUe54t>h*ji(ERALOu{J<7H_YyT|gGx3dG zI;%05Pn5mDG?AzO>i@)iJW%Cf43mDRr)hS*ablUxfI>kw8^vtI;$sWom=#k6Rm4&A zh|P6FN$yB}@r3`s|57{PsD1cjvFfXu#I$>@0gtw2zPwKDepf{y)A-aT(e?FBuVt8b zGL{G{xQ`ffY7V;`Lz{P9GHv+dVlfpVfn*gI>)_oKI$96I6kW zJQIpaT?{u%w%P6=Ha3mh?d%Q*^;1mV3~r$K=(Sf!8fp(m6sdm-efC&9&ZW-|EY_)| zX!)h%&BFURz3cexw&(mRkEI_dw%^8>zG7znejUeEN^Kl%t0uf_QQPBCWghAHM~KDyD}LBGrT zuhUVhs75okzTT-VG^_6qV-hGSGWL%tu+b9zI`MgdQ1h2$9J)h#X@n#B zhxkIUHFCQ1-+673q(omjSs6?2F5DX`riJqjr1`dFSVS+6CTzt#r=Rak>xSRa7q)69B|PD3X= z$tw4u7NXgiIw8>WOl{t;F7!2-H zID4NQYApF7e*u>NbCmlx}L&L}4RH9edgQXC*SFxjnSQQbC1l0W* z)|TexVE}{$fhDi5PpNh*ck2rRMF6Y`P1sxMgGs@J@5axxT5)^!>@hVl3BbV4 za{qQ)e`1UQCmYFvZ7m16-<2F+MYeilY)hw1Ud_FZ*-VrFdg|6%J*z^Pu>uyMm8WS$F!mPnaOBC18^lA)wQg;EkS zB#LU8hYFD)saA?uiUtW8GgTsm21BN(l&KPB`rmK+ob#RU{J(Qu`#Sq-v#gfi`##Te zKle}=D(I5Bw6@2xR%7jgrlq(k>lQ9OSUdTkPI*b&JE3{`_mt20IZga%D%-?-92>d& ze#8j@q0+Rf(uv4NGEr~N6n-_!k2N_NE2=WoQv2QYYhmm56Sfl*CJ)m3tmlcyB;V*P z^Y8c9c5e7|k{Cac>!G@;sH#Vun8m`sEghqW*W%ZWk{e|OD~LS;KqI`#F7_$7p+x|1 zR}A$3eNS~n#LQ3Yxf+d3XuUg}9exmCH z?Q&mfgkaC!W!4kY8WZJo2^V7rT@TaCed>~&A%}~D+bXLUkwuI^U8vLg?DCM}`pQ%^JU1vd_Ro{dxYCD8xRrVMk69~H#&IURnEP~YoCr4d3zDAD_xDFt@ z(Y5uboYp7X*ovW(eF6&i7#QC3kA?gXk9reJWzzGmztOkX22&~V)4t)IN9=eo>5}faw-7Ynzg9zl zF$~{z-5WfEg%klpR;_B5K-k>gE3i0S9V2JBPr!BUhmKP(;2Hw}cJf<3J|WZ$@hwt* z9|#t6VTnmE+$TidVhFpg!~-!mc7J|UUIX)Eotr=Ig|?p;7jz}L)9|I~w{LIO7MS*F z1>k+d^4fZ@&deo6;mJu!(XthveUzm6_hb1miA&So{kL7I_}gv#shN&gMMDsW%z<=X z!s8)CUYM4d$O;P9XE&AtU?C=bTefU@u_FNlz`(E2I0+3co;VB}q+o*81CVgiC3Gg- zRzz969(Go^4q}P|tq6UE}LBte&>F0V)3oIB_GS`m| z?S@VdtM!lb#aeu2&`20KI?CY}?v#?btSuBzS1*`PW1W5x26FbNfA?d>viY-ycey%h z8eCk(`x|1vxSt4mrCXf(}uXLI|8dbu*XmS7Fv!6mbo`#xWGibyUWiVn`* z_Q^cBc-YV^cz+3GresP49&C3KaBF8}4>IqJ_^vQ7L8v9z zYPFadE}Srf))xE(D?6T#-{s2-S!H>Iru3Jw+IFhh+R~OeQS}E{AZ>M*DsZmSRIx6% zH)~2Xm2MArw=)keaIfrPb&uhz%P~2pbCv#S(Q@-BsprP4QL^Q_In)&tisBu-nTp(; z+bC?QQnDso+j==umswwTTd&{LKJj^ut!J(w{igl^N5P5j@;}sWc$?Xlcbwd|JKo{g zOf>)JY!#)9Ni-Xvh&z01d$`F|ZF(9yo(+qjLB2*U1Q!{!H{Hy}A6>qCOz#RkwKAZu0~QdrwwEBABmQSfRMx zB^8aDmIFBDO}=|fh3$pOF-Gf>vuEPEbk2SS?(g(#2s?Dd9KyI5eZSw?3PgDn%0|1~ z;@lh1br8W=+oPjrw#9eDvYZa43>q{0+q$AWJ%mDoEs?{{HyWpCmhPs(_QChvr67!4 z&H3Hhd<@+U`YDUh(y^7rc(5-dCo5KKsOBNrc0Wue9~U0{S{%d4x6lD$nv)GjPcJ!e zb7QH;c13QY$3Aq$H%U7NeN^vJ;9Q1+`;TdNy~_7RZvsQ7CvYYGm_Rwv3DK#`Ltna$ zvf)aLW~R!SSA8#`i-sK@wHU zW`6A!8m#>~jUILJ)&VAyT%uJVi&*d4H7EkQM@`r4uQl*2-TZBnyjfhtiJ2aOGZnyu z4R`(+T5TbMp|}!P&^O)OP(hSpO^*&q7#$vSh2U{ox~yu{s;*FkB~+m zzt-H5wFGV;*PDioBW7y#GqZuj%UYdx$$;K=QI4)NbL((}V`2YM>aGgLYmiCQ@t{&d z^u0Ru_QrSPQVY({*Mu>4v!eGK6hKV$dcbc_8?t5umj2D^uCu%KTVn|BZx~`EmiU?f z?>NaV%ie}R`?#Yj@Q2fmM6{9(;v=i1XY-HBYB5wkP-MKHOyvKu()z8FXeh69&&nJ) zIZ;jHL5?gE2yC>*y|)$&Q@>fUxppA4WM9+kb7s9I{pAsE&JdGz8$P#G{9`9%bJY0em3XnRDb$vK7vMH5+QDC< zzOq7dft%D_ceXu`O4V11T!>_?FMuuMn+@?3YRRc<~zG} z8;7#*$S2M7@{+u?W~KOq_zR+3@`5dKX`-P_Wv-UiK9QlpgIjzwaC!I&T z!3a6@j^!UL z8yg$9NdCEbcp+h9WB<gzDXDFoNBW_5Y-pQNXyOt9_hkC6Av+t~8AcQzAe#pp7UCD8ukF%daRlUvOv`IA=zSF3>I?fYEUP10 zW{>u=5*4iMv@v(e);9M7Z+eWLRRmwEn#*cifAR4aIKN-bO3>TviFb{aMBK>f3pT`q z&;b{~llC6ae2{j#2m{`|muJZph5u%F!biXhuq1&jj{Y9&SU&uDbm*SD?!kRfHbD}0 z&!Ljd+S32hKImu2h6-Sy_|`di|KXKlFwR|510fB)XCyk3KWuIM(%N+VDd7w}S;B7r z@)$m{-qf9YbZt>+$gi{PUZW{B7|odjG(k^{bgvF4f{>4!`opP-Jzb~qyLV8JBu;DC zk}roC(bLp@Yst_FFxJUCxfWmxjFQ~RKxKPpjsCk6`5zGLqe~pCdt!aB>4dp=raXIF zBVB7BXa1EB7?7T2(=Sp)d?w>%bA+3=|L$Jg9&mO?yc)w|jIFez-1?&SnrHHqh8f*~ zQ|}9w&nu3X4RK~I_Ndf!m(2Xak+0L_+ldMT_~vssM{~Y|QzZU!c7%mqd>AD=dTuGNy@y+$3z71n+9q3hphWzg{`YId?c56B0Dw%SZ^oC|y zQ`i==r9yjmfO=S;66~RLnQ24Kpx|nti{EV09Q<=7ri(*#{k{%~8>*wD)wHY6I62cR zPJy3#NXGbW4pYFt4bshR%mI@DHzYd9RT?pH1oninUiD9Db^ z-WoN4;Ggf{Z){*T>Y|+#?*Oja$??H3%n7x3j;3bzknJUkblfv8xw|Xoqbm?6`1q0B zqJb=GCAt$w1Q3%OY6^fDRE15rPdZ?S+B+9h^YB&yRljU#tl-`tjVD7Ck#UCb9RLV* zN|Hn#BFH52T?tOb@vbYAsll|06;3K3RTWua3xR^g<8YLWuLmdD_O6CbebbpL~ zNXA|P(I{lQn0c63d_V(WNK-g^d9B~@Ik;FxGIY(C5#a<(J$`fc0jR=&k82R{ab2kU zB_@-|Q3&vXy{i~hgifab(U8?946b+Hpk{qtOArF!x{7WS2G<2q$cgC9TJiV2zgRpX zak@?^Wrz|L8)+`OPTlI${RaB28%x3wk9T#$ptuk6MQiawHzRM2)vZRNaZ6A1Td(&(@S(MM9P%TJ#Ia?uNc zhS=XPb!PhHDZr#lHf&got?>Hccn8p5 zh-oQ^PiK#xdt_m^$5#v#geIo#atd3J>u_sM`7Gk_C@=MXoU;_>4KpD8A>6*F#*P1f z*Mc?>Yy4r%y3Lda_p&0j)*p?wZ8x_&tuwlAs9mBdGi`L;?LdF+IhodJRf6wa`%EtY z`Fd&~8h0j4W%`Jb5o%sQSDJLKB$=O}oD{tVx#DIA8cqvAXHk%PA{T!<#T=JqslUAS z_LbBCSq1&Sw-SXQG3Nq|dVhxO^ksFQzEgcFLZS>bG->-4jxV{`RjX94WI+ zT6ObJJy*{(6YF5ERV+0tFGRz zVzP8FNh<$fJHKRytX5q?rL_M|!%Y0WWB_ml=q0Kh>*=)>{Z$t!M?@v78O3$hP9qugX-c~eX$1LL<2!9~N z$u_X)q|LZ}&fp%SGjF$C8WXcG6Vk{dzxCLA&3uWw4*hv5d0IWb7L9HbWjBj_ceH1@H^wzh=5OC+p>nt`^1MR3^G z!(-T*BOgT>n;&Qb9N;b4J0rd4?R8`ltT`G(7HcN4iwJm~(zj2_!^s^h5M4_qiTc#$N( z3uk90)cNAmQeX!FXpEqN8pSFnxm8Jqwj#;7T?_QnSm1AMc8ch9a8Y6LhhfkF83my}+aI1M z=m;U!nNoX~had?|99}>AU{?11IYfBjpw`^O0>q2IX1>c-QH~9>lS>wz_$UO5%v76N zvnKI<1I}`%_DBovI~x3XY)(K;*Bo)wK$p_HNWRz|s1sIi8%Yen z!y|Tt#_iI?sFd3$k~81s@z2+r$h`Y^&iMx`d6vyLb|y{V^qUly&i3WWK9s&iaa(zg z^Zq(3S6tsHd?(ztF&Z#z#IB<|gH;Y38nsR|-4eEa-&MQ+?BYIVO(`jUX=;h$a>?=7 z&F|Nq5uk9PWf8$vOwh*+{HKpeP-mPU{a}cX*FT;im391cJfrtnka>sHcNeobFSEF! zc!vAq@~>-u1UK*+9uq0(BVX1et}L+etqK|%^WYf1&V0sY?CxlIz=L-QrY@v23)lRJ zPN%hQb4gwPx~Sc>q_0-FKAI&|sPHk3VMS-=QYD-8f@1v_53Ho`Z_3?xj>@P~EKIl=OyKzZ$kh9a8NwZz1q+qq0uacq2y;M=oY(8z1 zw}O764JCMCyp3j-vQRvuk0tbMaF!^`CAM;o$margxc!xO_fK*6^!R=d7q%3qR?qC& zcF&*HJ#DLrFf7c8+dr|&2ec4b?3TI|cR~oz(H`^#Vk2r0>*MzuDqB%=-cx(U+87`T zpFfo90#>6w$$-2bi)sPrkmu_>!Fd21m~cgR<-2&XX zTx(0B^zq%?kral5BbN;qZlI(K0V)5yA`!*b#^L}wGJgnq1?%RQ8+f*9hm*&%` z1F@&|!?%NjY;7bGl6d_RMz{QhNbPwl^#(*3nV1*`ab0U$RdQk48WesYO<%JVDw+K+ zAC&@vZCPN^JW6=AxJ;1zoz5F$D2&6$iqaMVfOF|ZN-})SLAQz?idN+Iww@v;dLACR zmZRYBRw*Rg2Sdhi1B5^B`rvDauy?8<6mx1N0FypY(U61HY95S5Kam8HQjc_zl$qWs z5;}p9+c|BjnU$?ALZw;3;=;DOOg#_M8K^PH(#?SWV8wj+)J!6G+pxX9zY?@SLKrO5 zDqU;l30)8gVh}bD2A!xHL}<9TEVjNv^?#<2?0~1sM)>0YuFAbGu)5>idVh1&5OPo4u-JUlo|&(&K)uaj9O%NyN0EG%#c z1k4n>Sm~wD^Iq$EU!fW+v%llY38Zr_wv-#SR}-YkL9WBF5@Rw8E03h|V6)FQeTbuy z5luJle9Jc6;cshu{V)%gZ`G$jRk3L_Nb1E`7X%8FoL^(!w|xO;=H2I?*9spE%yQi! zm0l2hb>)7Qi#D+LBOYF)(FY)8bXkZ$g4q3%dgO5KI+hj?$Qi;S88!IW9uurmh-?{} z!+k4Ws`C=YEsDiPtW2@PAojIr$7!~<*ZMS|10)zlS;61|pFB+Y=+*6S1o$#J^Wl;& z4{;SV%SR0+T=A{)3>7fzX+zlR%*}!o>;#)oIKHb(Zr%RMkwzAr0ROzcWF*&?@-KQe zxzWAQZklx+SytoRjlq1HgtTb;k1|HqipfwHmkzaZU*EGU0 zBwdGwikvP4NA>E~O@2pFED>0AYIw{U3jm@H$7+4Uw|OkB$N2KjW2~DcA}f-mKnw>_ zwG51m!nEi77i^nZcTzW|x-=EcS)xF^!Q;}`o&c!;niS}lj9QXGEh1_LWawp$$ys6B z%3!d-16|zNj7wih^a-}Iq0`fWR^~^Johrb8Nzw9DyA7#!Arq-&j4BcE6aN@Cf) zGMsY4dW1?r-2F50EJq^hpNip>jvZv1ZMvtu|MiRV1|CR#}`z*N0y++5Gpv4z=kjk@n(`w0)p0u;Y-|nWeUkSN!u# zV*6#jU)tF}6R~o{&*ak5%lWJBaJ;p-?sDkLPm6s+`?5=38b7;!Cugwh$3W8c@Hpe0 zHPl;UCwy0axL|&uR6FgDjhdN$>460+<-SJSDeg#{Su%F|!2OyFPk&h3d>s;~o(x{I zP;gaaW#I35v}w8IcN*-Rwf;vlimz^()@Am|G;Po6SMFRMb#ptezC%yOP0^9O`Azb_olkw*Az-y`+1>ADDG`OX9;`lk7O%XG z^xK!JTbP&zhfBC*N-dQy=Bv-Q5?bk)sni<(V@xiPVHf1(eu}b=Ke%B8p z(M(zo|5*{=&mv~Qw#CP%{W4sWV{y%nK53H{9;y0BNm$9kqP!)8UVwTbkM$e&fM?aD z>kHh8mYuM;CHJdah!8sZ7_=tD(=hXJZ~9qP13bZFID=fTOyBwv5*dhHG=TK*HCq4s zqX=-!s4a@!(V|3}2s#Ps$CeXjo+v?t`(Sy*%oC(N;IAB30r9eO6iie5?ZB~1arcy- zhf)mj*RsD+YtTaCDiR(4=@Ry^jo)Rftr)0rgvm|3^wGC)plc_Y2Ds})jaV~8@xAYg zd~Usq7^Lc(FDsiG)+H27kk0`fL}yzT=T;&3_vDuhVvpwe>55-%;^j%-RadD`B}GCE z@Xcj!fgBL79IO;1!>x~`JGh$#m#jy(gJVx37xC(fXsbg|?+|`wa`9p2;dd~7hXzOC z`PdE=`t7%Aj*gBG<7JPIkOqb9rxdw~aCB~DZe{}*mAI%f+5$-O69KV73%MS5vWSYY z!VdqD2LIIrN*4l0=051+6;U%>f%dy4+fzlY8-*@4piz9(apyvs4Q49k* zFme8iZBe$?Yvm?vkeu)d6C717EvD-h@;KSC2+#esFoUW5;pA5pe6hSJ&+qCFcppT= zB~Kmo-xN$fSxg@geGB_B>>+=M34t||Fp0A!DK!w2e2i;6yo~#Q_ayO4jIc7L3O~E2 zxb|X0kWXZ#TkE3_iCt!iU6wBvZEw^~XpT@2e)epBhA5e4NSB4_Fsf*cZPZmuX_Y9W zt%wQ0Xxbg6c(tMkpPA{kp=+w^xYjVv)2!KU4J`T>EkrozSRRxCO#_=czyGO-k!q@y zWbYYHG+;~~kYQ_I>hNOuA=RPCh%3hH?!*Ya%(bcJ*>i1qTNP9I^#F6zhXUhdg^(e2 z_1=p63pOWIu3YdllD(d)&bKC|;lA7FaJkc37B3HbORIh3v%Y>LamhlDcl;slMW;pg z4^N$#ad^S$QxdnjVmyXr#7vSm)F|<~U2Qa*62&Tu%}C*@Wj{wA>xU5C&MvW+J~vuU zHQh4rl+`j2%}V7_VFW9SR^F7=v<=HFniaF9(~Yll*h_5Q+PP9On$0NN{+7~V;X~C5 zYm4rfkDKZl^!ZJu9IbxJn)7G9AlL8uI~N`vSCbx*-XQ+T^7QHTM0Y-Ea1Ct%mVSgX z1;`oT6lo{UX=E`W!r&oo#OKb(Ysj>Xg*)4R-YVjk6#6I;rIKtNVIf+kbpZG~IR=40 z{y5WiPtT5hk#4G87e@>*5N~nU9fTSwMd2vAU@&HMQo+&qnfO{T`6i-As^DWrCp8EQ z2V>YaX!5uhO-$E)@JI^WZ=m5P z>lY}Agt#cxW2<=Cv27rF``prBZLTkGRk?@6yeaMd@Co9dFgy_aNJkg#KU3K51vnhs zG7v=&%X>bBUI3-F0IB!))`L2VPJcf}-SvJ02e@4Nbh;oQi+I{rCilIg!$o zqn>RtN9K7&H0wv|#=od~=SJU2@#NwaQHPvN+E7dF$@>ihOB{ycYnES-HsPf-d5>`J z6eKU9ldUxKL*%|7_2H9Lr|$D1uNSQCEF7D0C;uom{JObbQ~1#MqGbZ-J{HRE&fmIN zeyO*xlA+h9i^9E)Yx;j2y`;N4L2#n8x*qU~uGS8f?JB)eVsz^sRPKGk%RCrW;; zY~q@y)+c`H^}TR35I=V2;9d85NqzLnAZHzQ-gyQ6vckt5Qt8fXn|z!3Tvl!VoXJ;z zzvta;@8%n2aH;u_bm6)0`+~kZ%`?N=A41}#XH%$lS3}=sv$1kH%D%V*;!c3`vHlG; zokufACq#rSP4uE-k47waK6%}Z$2a7dCLfa-857C0p|D}gAQnuc%L~dP|0gvwvfOT& z*MtUhqqv%<#dO3PxsbR)1%1o<9~}k*7Tpfk0*OvuRQ=giYlM&d$h?~=I(B13GBq;_ zJ|f*n>7oHZ`=>!C%{3xsWJ5{!M&wnSn~`V26;VaZdkA&Z0h=p>&8T32yNL#M^l{fr z<5wlsTFCZK_0qJZjgKGKBJLsAvcNyyvBl3U&L*0`rNyg$x1HiR+c;As z0suS6>47!nI)n3ATes7sGDJbIB|RpQdJ>!rE62MlHbwfsVpq~rTJdKhm0C$sdp2y? zchOhRU(yDwcQ5SKdSSY4Lf8T+3oM1tEz->SvkSN{PTDSH6q3m}LVAav(%aECF4AJ+ zMgLkPW2c2tm{C}`6>}#XrwS4nmaR%%m_O-j zF@LQjK{g4~3iwFC`Jj;h$Czsp{kJiW-yd;ifH!Al-oWSGqt8do6W{JkoM@T7`a5}u z7XHAD8o!lec63bfsy`cUwqFfV*&eyv*8(a(?Ih7Eg#3n~=ZL#UQ}*i+Z0I6)AG%3Z z0_GmSRp`rJg@HJ>wiI@M{R6Tw5(|yHuPs_A(^R|or`77wvyXRBpEt;tIiMoEwDdkB zF>&ijyFq`|&dP4}ieHO*T;KC%a=g=WFqB-eG03?s^0T;Gy@BBxhtEql*9SWm`W&=q z7T%laKDK{YW(ntxf}!H=S|RT5JxhK+()yvdqMgru|BJJ-OFm4p_IM-@MeXs>iN3p< z$I6_+6dfISxV6UjMi%x2HarI0O03(M!B&WH41Ucb8dg}An5my3YW7Uug&9tx7Y~bZ zX!12_a%^+XJ=!mJb#8AgT~PdtTiCV@Yj12@mGq?gDc_@9>9KXQU3Zy@BUvM1d;Esq z#q?k`Oib-0*LX;C$(2stXVYsB2mw54ka z!4RYkJZZ${V-h&e61FzP+Tvm+B5?FjbuSu{hi%=uCXXG@OP@M|(D5^Ofr$`1>GW8M zyrYM9ierKFuU(u$bN-StRhc^hHIGJWB=%KrwOq%+QufvLr*9E6z}8m>6vPr$^23lT zOpLX$WYb?}p=~V869zn&9o{V@CeUdysuV`8LOiYH06D>F13p^f`!zbcil7G}IX#44 z_Rw3+Gan>X(?boZVc@;vgN=45`uzQq@3If~B0t0=RF>|7YdZvbvD%CwP@t=Urfn&v zYYo?B+`82Vh}ZzMy!N`U71%3SfpZKe1P9Faz3Va$%VRtT&78oSAOx^+{yiLSZ~qMM&UVTT08qb{$Sxm1;)0m z%Orgqe(13m`Z(20_k?1&B86~_%v%+!&HnFA_KtXl;^Sp{SYU6cxW%M??(&jd%TPJ# zTz#3fJN&}fT`e1(W%MGpOMRX?g7WUE8WjimB^~d&4}{;}$$K)iawYeQs_@+Qz1kO8 ztJE=a@iq(By(y5<))Ha$6nwqUdF?}YoxAQ6zV*iqXFR2)UU=!vT?i7g^cRU|h>Z6q zX=Hd5UP%|WvSl4x>v~a;W^J$2B+@8aqcSg1S@xnqhH@4&Sa8ib3)5gTefU^f`0TqC zy`0OHm5sU5W!ukb#%N5`XTCS;N)=t(GoqEo`0pvYtu#pAoBbuorp{RS9P%HuF50ZX zrjHPwTwR$v@?e5Lka~m!tieliKb$UzSy|>`SX%4%QtnF0LFN-DXQoL-BHh*xXgMDRa{eGe^ zgsFpPtF4`kt?6!eO8!`cv=}zs5EO~@Y<<Df^b&2sg!SOZ4xd#s& z>KlGM67IY+Wu-F@F?F)$kLi=e4jwyna>u{WGBX>kCiKVsK$-|i1${5$@UAC`{|g^H~bT9$uq>;J4N$RplsK%?n9>jN`+ronKf?JgNHX^(!a zWP5tUY{0Gu_GBBYC=i{_fTaSwds#t73Bl@g0cJ(~LU2Vmt(TFg!vXigCJ?6891?qu z36aPIVyJr2ChbI9C|axH6*2#?yS$ak%S|>FklN?lrob0buDos03_#xfFUBxCX6HdRN#+bP?HQV z4WFKj0I@mAE5pOKKYvT{M~s04N}Of>#)dD_`+VY3Y980Mrf6_5uu2 zcfrU-xX;d(m#91-xDrnL_Ws6iz->L{2Sd3ymzV&Pv{t#nmHYOQY4XYy zJ|pWbkpVR?W8p#O1g=-vDU$Grw;WCOQdnb>jpvGb;kR^r(3@0?C=edf&{@9lwmd#D z2*oP#VsYwNZooxWprERx8&9|b;wIEwtgMWRMo&I~StgF+KxmQOEB9sq7lf7B*9HRe^iFz56cf*RSGN;uya=Vp(!%=JAL_+3!bsj60bfntmRkOWr(9 zId2}DRFiGQi*LevF_XvGw7@e@j=gQmQIyV)+i2#&Q94vJb!D6>Ryh{yNVV2W^+7Q= zB4cRBis-u=2F8{-a@sFb{UfmR*rzAEGcAQF8@AA$SG^N=_)K>f-mx?!cee-a z^7X2wJ&W!E$6o3QG)IzSeX(n@x)lPP~Ux9kb$5AH}fhri_6SvYjzxkoz+fs zn<%ZB#llBHpD9@QTwyHn+J>|{(NxpvJ&)0#U*}zDSa)9|@0hTk^8&07x0O8qqFwh( z+^|{muh$N=rH+!}aT54N;@3`SZ)9Bo!W(gOUa09JJ4-TkiF!cesa!FrS4 zSh4tn_IL02&@L?P*a@54KKo>;D)I~PK&xZ)vlak^iu<0(^YFl{BfAwlL47W}>AmuJ zO*qHFm}lIYqt9qxRgoz6l3LfOl2L|4?+my_!Cpd*q#$&Yt;U7(=x@QDaCKD%`H-u< z!071#ZRua`bx}zai)KTtF4a=b2?pb``8&8BKmH2&QRdmN_)xR%7;-bC|&{&_zlD`1>rwE2|wdxc8mB=BGd8kYMN zFGU=ffQ0P0K`jLNia@?t@JQ5m57iQOrHq~sV9d+J^O;yq631EM&IXvW&|QRuG|}Md zBOc=DLsoYpn}LSBFM$x&ya1Fg0r3o%XHq=l-(4svrKI#m1^LgBfAMyUl6bRyx5|lr zzgb_s^&-8N@qQIXVzezXNf3aE<3SY+CZ!fXfY@CB8t$CmtXb1>9T%XcYYP_|8$&S2 zagSap{Gr@u}J&h}1%+6U@}TNA)Jmv%kG(&kZn28S;%-H(~zSI+4|V z*zfHvr|Ra|^p54TXFMZ4@9p^6Y*%?@fhy%f*1QKN1(HVhI#~-G@nz8le`&u*lC<=i zBYa8y>#AFiJ4h~dYYsl#u5K~0_pPSejsm`VFNeW`uU7AQlZH+jbkwm)O26FrU_pg+ zJD>Lh8G2DnY`?ZAmxJ!rScQ_+^Fj;j?B!T&0l%y{U=d`nXTm(Ah0o!HR;jAV=o_sPY8G-*`#9_$aniI#`OIO1e#F=|GgOK5=6-d zi)Rr3^L+1|OxPmYQ{NsCF~ok%LQhVB!-IqHHzXB+g9Kqw;-A2wW(*&%u%eS(Y+h`4 zFKrp0!e_um!nBCJ4&ePJ%||a!E3vx2`Z`ee3v}%o^7=qLi`?(o zoqqMn8%;1VE!vS}>rUGZiU64n)oY0lJ5KV(i`*L&3Bwn3pdPF(*1BS3>IV_O58Dh; zUtSgxrvooLLXWI<-ye^wqt-twjB00^mY8N$1Q6?hX?1&?7rm;0djmq`CtOil=^1 zoi5|NO*Hfg!ay!*uwp*9G5^3b;b}w?V;UIe;NQM&8{wN0(pSwd6QBFV5Y7eLMB`3$ zs-Uxih0q&#=v<{bF9?^Mpt5HDH%;LCFQl+)A)TOrOBSNGv5LnqS)d+M6f>&Csg6;? zaJAr~4S|nH+9j;@WC-K3tRQ^xs%A}+kzs$LKT%`qWqTpCn#8J8o|YsS4DU07fnYd3 zFEvbbr2p!o>w30wce$)$9}COZ8NSiz@SdK*9>Wn@MR(M0@|}0A*}rA3f0>oj)AWm` zTh#wyGExr?cch7Rpf z{4RZSYoIruMi9k#Sh5UG4Tgm!pz3;o)^E340_E<))vGa(7TI4^*tZW&HnI5dTI`oj zt;AQdqxEr`^S>Mq;V)=A#L{UfF zIY5?s13&fd#i|2@_BRXjtVzZZ;X6Y^b??eQEM_wMVm3*;!SABG%Pg)d0jv!v@Jgy- zxjcs1`|OX~gD1K`J0^Q>F1o!o$QB`A9{qdF(<4yla zxc}MJy)6}1jX9zvR7=zI3#aRkP3JscfB%!czJAH1>OhgLN8Bawf4VMB6hG!YdQ+d3 z7Wrw1P}dAs&{tuNmtURu9duEvW7x+wa|xLasK0wLey6+8=b}pckBk*{eEWSQS0n_T zV0AATs&HiSNz00;THCw+f(|T!9_T%I3XyijLAnCCX%#+ix@mH}vJ@td)!-jHCX=p2 z&ny;r&fsCq7%p94&86g3zwvs@kIt+qD?S5S_P{#Y#-Pk>#x~Y*dlh;lU2E2!zqW(1 zc8yzO=XwJ!C2LygN;}b6tJp!4gZvv94R zUQ13ietiTy!EIKQ00EJSbd&fgK8pRPK0G>g zh#Rwl#g2oz(sTldHQ1z^hwc_K5H7YOes|LP;oX>p_|cShJs?&cZ08)3*8J~D!(-7=f|H9re^Nx`W(09X0;Yc`!u1u zbW!8`E0?ZZQMq)e3oBCzka$-##fE!A!abkBbwDC!Vw~ft@Z6KavK=wy{K3J&yi+G3 z&VXLN@=xEsp1rT8^hk0P=Gc@qOSss8LyeN0MSQkT;7!EWc&*j726J%~98rF+u(aiO z5uvb_&-@~S!wAeKVdGod>R@*iU0rRM=Vj1!5Z+-J%fWt*kjuIaCKx&?vSCF8jPfz` zPUPc+vT3Y>UBJIJ>Z$;dx1jef8m4Q#y!XuYp%a*dBxDI5J@0lHv^&FB5M2lTWnT`} zj06^G9sS^z;({Cb@Ln(297a?j9Ve}vMc>b4$IRv6^v4E{l2U zu=p%+sDEkv^d8ml;x>?=VDB7Zse|~n4OL}F}QOQO= zlMNxw0a}W;+Vtmg^ET}gd3Z=+emYlBc>ak=S|YcLkL7|cp4x3-uJf>t_8|QVoai5|5(`7C< ziq0c4L2JG*|yz0VqN+Dh50LVYBD$q4i|Z=N_5BXx!W!i zcjbP;I_E;soqUIUo_Q7>&>kApO5VfN%W|na5^d0`^~gbS`AX4bwi<;a&?(1@6*6Wo zW?#>G>gpKD%Q{H)SUgD`B}yQyUT1BT!Tr8WCPx(?XJxTo2x#1G=Sgp&!nV#6u@x7eWKs*w~2q!v3!=kIsCZ{>`}oqul$1!k z-Of0=*4dh1=oi4Ksgvb~pG^;VAn@r6e%qkb)&9_B*#CBGs{#r2 z>V~|>1T@X|E-|B^8Yg{xUckb=TKBiWieMBGyLUC>!qZ4d0kjJG@W>5|XRN44;tn~X ze;2_srlLk};0a=GDfTdni|M+*q6&u?25y8WMWTbNPH$Eq^0Dg}>DOl%nZ*+;Ot7l( zL5Yir^?<;<5p10VN1cBi;s4kFm#LfYt~CkBY83D)Kj6~i#xwuORu)=j67MVS?S?)jlmb%&htZG&65XCfRqwNY zCb> zyS-VrEbuIDnX?mpl&2s#&cPZ-P3O2L6e;{_piWp&pH5@Zr%=-0>~UBxy3THEdx)TZ zfPeTdGku0y(8D6x!us1MJ$UR@!^ZW~uY58KX0hHjvt0kk>3z+fV)kcfQhID{(-HZ$ z8<1oN9tiO)7+5E0fJ_NuIh_u51X=jGzPbHuz}ON3U6LOQx*8@xNbkY3I)0ZS$MP91 zDwmv_svZl7D>v}$5L4Xw1FwFV6xxx4*xTFdVLrh`fg@Y!R4w;i?w!j|s(f0I-oG;j zV=ji)*Mil~kJ^RA#fhB(14^?sFNnStPT@FTLqcH-2Zx1c!aoG)E4H?u( zQi=w+v;c@nQKdW9`1}#{` zE?AMQC)^sGL9>=lPX6nVy*-=GH8|t^WOk78Az=HQJxlWOye`LiE4EiSvp+wh8}hVtLY^h8 zgjFX^nIhoQhws~B8#*uF%R^L;F*IR#ccFS-Uc9L3ctRC>n|3R!D)*ndJgRAn$eB`VR&>z)U-JS>2m1F3-;@yM;gS_m zy04mI@#e#=9(T`(d-u-TDA&AN{e`N}!DQSrKjC5BwDrJ^AXn8}sT~8}*%F%f)1T8- zcfO+PtCYOp*50#HghfA}wl;{f`5FDTd1&;e88Zd_sbY5?&nOZDT}oYhrZc1 z_VsUiNiGY1(RWoVTGVw})3c&a|1tZrP58i&k%GRG)dA&G zJc8Uovclu(7yhJ}*Q^oFgi!a?XtF{=)EcK*JnxMB%9X-j z-{zSB?mp^5yWHtv0`}Kk0N>?oDO59J$xkd!U`A5qC#C5^SJ;#^c~Qd1x*GIuMC?pI zW^2={w}HT%#F)a7?O?BX;t-r~!+=3O`Eo2+&}Nz0C~9fs`SV7ge(E=ATyAiAcUO*( zOQB=gyH#hVld%g^AX$@cr0oV$3WaSHW_vkV*@|1+rtvw+>gX)sj|h3Tb$gB&A>@(? zp`wD8_iN3i&E&5F=}r~f9cD09DO#R5Qsba3Y;173`v%rOUQnbVKWK{g_Nq&pC&A>? zz(s+(@xd>~{vM3~#6W4fKOX6#J4*aDv^+Yv5}sApYQh5?I(b=uz$n|d_Z8c#8X6lr zVUxB#Rx1BI^FEcNoC3*(C%`+|k|gkqV6c?3`bbh&U#KkCKbapDSSkxjNHUWO2ojp=6BLA%X0nosDTL|ucUfKjtZ9?P8#7761(S(vTYA3`M(!l zMn_E2i_pkRd1&v$Z=aw5Kr-L|E-Cw>Fs~$P9dl}P5p<>A4Rq|tw($3`*I-wO$ z-v1m0`o?g&8paJOcv* z(svFlvhfA9jUZCB~qfL|-1g9~kHvhs^dH-=0~N5v?xzN<`a^Zela``uT5rV;#X^Tc!G&9W1-{g<#5=5RlWGlm^wgKV8C@@cr#f% zGp}tC5&S`E$0v6I3Rj3a)`4ms7;eWMOee@Lc=B=1?**IQ0Kp@EJn2e*+~&a7bp*%Z zn{EsH@0`vYQj1__4nD~0pGG)jxGCU*CW1}NFYh2E*pc<8dG($j`djw{%I+6ikHhpdXVcX+*E*swE9~MCf#*xwa ztPH4vQ5nhBS6A!H)N(lrS@fW!^M3lK*`d08`FvbOh@2%OrYgve5^cJTUZX<)k;p*t_jR&<@EG-X8YYlO5|dMK$nZptWmFsq&q> zjCC;q5`EKdP91=2J-V~n=Qq)-)z@EoP=m_$??c&m?fl6v=`(kX<*c}Z(p}EX6Kn~n zf$+e4+1>Z_?=}_3`&Y=9_4c^^tMKCcZYe*(_pjkWjr6f;Wou*OjMcB`es$*kpA)j} z7SX?61f(mm$b~Psl6HCj6dRq*G=0RnFreo5W4!t-XT%cn^8a0exmef|DbA~3%x4MOB*MWeXr!26E6c4M zEbf#UmVfvy-~GXJ+3{Bl+D#s`(elhS&Eh20w!h1W+LS;MtLT3nZMp5brD(_5AaQff ztV*}&+u>O{ds1niUQ_jrg1%7>+iV*~jAI$eiwP~vFn)MmO#90Hg^O;P zoeO1&SIT1bO1wzP8((^1*GXI9o4c~}0!Id;m7<9`ClKLLY+^Kus{6gK<0&LHiCFC6 z{E7$XBWP0mXPFXmE22tj^&kLCS5+;th=lBrtV?+8`?@S1BuJbvl+>h>Gdf zmj6taJGJ59-y{bJtP&&w*R9Ae=E!Gd-V|TBFq#Bbf@yJ3`0Sw>=1H2=(8m1O$@xm( z6}a1mj)#VYIikR1+2ws0;c?ltd2=&;jd)})BngtV} z9PDAVt)*1`;)X}?=mWiK=`LFiv$*I(P}E`rth#w=g8uOU>}4(>_?N+u&0G6QFpntf z0OWCTb30C5#k>iEWgHF`s_+~tFq#cSFk?W0FPaP2iW~bM%^DxTbV^dr3DP4-xmJIB zkjQN?3XvdVJ{zh`9UP-$p}d&n)xAjN2DO)LrFA22L80gf{s&|PkMzrquf5_AB_Oe= zU1b)xNJJOZWHcD}%4qG6k#bD7$UqQMHs^J5&a$2%$f=S2T>^{1H zT8S!7rBb`mqd5tPG(GYHW)IptdDRDA@o#i-t)b)B{HKoopDue=K5!jZyk*Y+X}hJj z_?Ex0;n^#_TEo+|nQ-NA3n|E%KtZ_xg%=W%V zRYa&Y8Il6_`7Z1&&QIG`;ywIkez+OlCS)BX`&5t-en0zkB8!>L@};h=q2j9ZDh|;u zKVG_MhG*B+t6TQmsJEJWAl@`^@%q#IgNZ^n0u;C?PZob#p~0;x=1KD2BRu$HlDLNGm8Tf!9RrW!qwlB z$2w6wk*Sx0IA^%$k&q)2PzS$YtoHK?Vz*nMZaAwDcNwf7NN2=?ewG7;thS@bM`+=~lY8oxn#Fs5d96@gQ$un~PDtf<)l^rLq&Wb{5%1k< z5nB|A`=2CSany{hr#R_zHOxh=UK_cN?LCAO?e& zbP{0*S~oym#QaTg(W2pg6DYIgAY>!Fj~|Yoy>DSO1)J*}$8X!EjPv0|ke3`G^!6V` zN+6z*1*-sS~rMG42A-LGbPgV2g^>xti#_I>aHCR zUBxi^ySkhKAcrBp8w~geqzO~a+|vH!;FoXnr6c&Bb7ofWMvaVL`zg= zREo?{c2X2&B-tbx86h+Cf1Ewz`#j&@_y4@^*Xz0KcH#P5=lLGT`*{Z#$UsFtaSGYIY> z;dRui%&*l>Zm15O?l(n60_?*akTP7)I;`1onGkqGbkt#aUZJ9iasyS&%lQEBhI-HpUo@i997 zt#o?j$n2{p?=PO*$isMHU9<7ZH-62*ksb-mRt=+nDt?M`U`LrhiI(B=m^k<4i~*1T zK%BdSSLbxJkNL`JJNq8-TN=MjL)+n|RIfe8LA&A{-Gi}JqV8^o{Q$GOm#LYBs3*MN zf9NJ{&WC~{Yp%+e=yHm^O4Hyr?c=IDe_3~pw%67}H=nL!pi$G>WUyxs`yRnxH|4nN zRv9r^-l1-J{JQse!h37VH9ET6+_Qb_nK&A6eW{X>8q796xhMLVzH9-9I92_MRvOwB zREOAdwy_1@w&pwR_uw9*{(trXOLYqvMrFfYH7Ns0bR6EA(58Uf-8Rhz4mW2v|y@d3m5TyA`qu zY+nx;8s2+YMfA=Z&`&A} z2NdNYQSaPxUvu~g?V=3hGo0oCwN)=prjcnDdfY(p8%;0oX+uX$pdZ*jtgqX@GL+;s z@a4DMk`NPHohY6Na2ZxiLCgaC&zun=hfprF#m2Jz)mGB(Vgk+ero*zi9ThTRcYMu| zyiF4t5<*mD(a9%*c#Xm#uG>&&W+fGYXUPaUIGApF2}K0@^y?4_dvML??kyS%qy0## z1Ro+)DnNQR#ZG1q6dgtR!Dbs;?>sQwfgMp~cZ9&IPFYA$z~Cwb0f9h)rfj!hQw)z> zLwk<9(bDS~5d8uGR_}F%M9)9hAVB=u`vB{wFE5O;zG13X#dVo>fSx8Wj8io;1 zyU+98J=%pWPHD4}cKh~?0UO>bd&U2e+EfOV8awT*kj5-l3!H3JCE^eWAH?+APBnFq zwCPa(kVo1rqA5UlX!luOB%)l{%zv}uqd1g*(fzDPxqY5x2`CuZk;jZ(NK`bCBBsWI zz7ICqWLTJ4ccMTA!4H(S(@?j0dMud<9U-KAIWhhtJW*5mLaEy{6B84p@&^*|4ZFB| z5vM)FwIF*82M%J%D0AIl4~A;kIIYKMH2$GKr>yB)xK`MYf7ftP`NtFkes%TehyICN z|GO+$pdAon`5ZqtzuVKD@$c;F9}y;HXi6rECST+|nPv?#U(Q(Q*`B~y=Op%$OL))M zr9A=8*Ilyc|Ms}89a;RG#{7h4m;loj^X#Yny??>Lt{s3g%k zL%aEhCQAo3B|u+ilv00FF71KLr^mNVtnH)MPI>I33VtM`CotOXp+kUE1v9vqm3GnQITqZC(m3-aA(5Vdx_QD2upx0pVh#HjFcrUVnYV z))i1!H9vbDRXK=9o}Nks!hRzmr8ZEB-6og9c}Z!rEb^vREt zdonT)0zx-r74{xK9$~Hs!JgY9F0n?KH-j!oc;2XT)o{@eJ#LWQfbQ<@VGox=KBU{X zWS11faro4uSRvHmSY*}J-+uR2|7Dj# z)M;_nUe=RMHn_oI|TgB>>=;J8Q3GZ+Qk=O$*L z@%`6HIym?>ur0E}isr|oqbYIT6r*fNUJRd5x$_|aS)7mn#bsq@c0Cy?)*t*;@2;nM zXX%v2uSPNp1NevghbRu8NJJC{@DVfsnC_t~Ln0YNjo%HNGH|>Nl@q`a!b>26AGs8O zoe%d0jX}(p`xga`+P(t^UR)Y9Z;r(oCUcq7ldv!_1W%UP;XVxnm_+usNlVz5e@ zm{aQiO*Ls$J=kgMDe9>~O>yGCU&Gh8CGa8sZ0;t+{XacLS5hN->z)6wZ&{Z zdDrVrYRj_`G|DSmsn*x*m%K^yjC}xX=RJlScoroJ+Y{r}*w9WN%-BCb%g|0uaX(b| z4AnquqYQ)PI;Yzk(=udyKhmbH4LSAu*wY{VP6js)`z2}*tg|#SK?z~R5bLOr+xzpu z0TvFHM9USz^(h+7+i0~m(p(X|7k2X^3k}DNGv~Mjk8aY^I8`Ff1_Mbo zPWsDdSGHbX)EGGtBKU~Wr!MS?s&E3MuEsTHm02omo@(y;eYMeA10zHt6n0NjbbXx* z{I7}F01p1 zR1_XWc_&QS*fm&j{9&q2Mx*FG&TZ(2KXvg;XDFClNuWRzs}z`GT!RZbifDbSLpNFc zAk1_I%XS1G0BPdN{Aj7b<@QUf*J+|e4Chx4fr3d72omOMR>yz1fh9vE^bXxlA8Hl} z5u#^cVCCTn#Xfoc#{AE{Q@=WRh_ot3c0^gR2ln>r$n^+3sDy#mhk}W*%_t;q1QbrZ z?qc(K;u8%813z3Bo`AxtgMI{egG4Q{KS6gztexqYm{ujMG93Z!8%O{!b`=z^&EpSP z{GgF3`pz^|#B$sHv5w1K5QbZWiegp%2aM~GmkHhtM*BB|Zz&%yEg&YjA~PCwCCr-v z1tsebcqkqp_Bag_e+3{{MlHZl-<>H#f+GV6Q9c-q6G;g&NF1tlDm+emNLP=YhKA-e zLfAbN6nA#Cq-h!jR`-jV*s)zO>#MrJ+=J&Xbn#nwl7IBMo6aOn>Slf zH0B!-L5U}GJjHYHi^O$)W$yDY?#D7K#A+jFohB@H&%Xb_-jVqi6kP+e-BdDfbxwS5 zxcF~mkU;V2Zq%sd$JQ@FET4it5AMn7J0^L{ zc)!yJt9>*4yF-(vKIiS+y#1oUm8Y`bnO;mlX=co0MeD$B`t4bhL-~3hflD!8Q+<}H zVH*$R8~5-#qzY_gip7uz2{Rkp6D>tnCu@kH0hrfn$fUK-s0#jCCjqeW3^#i{RcP>~ zjI8E@_pvZ%=47+uz9vfjO7NeJdpo4KBVO2c?84&2YM^t|yH_2%@YkRQv``iVmv-_UzSO6xcx0#TS6Gf2f>Ta}C{CeTEGQPJLT8Z$*e@U; zV0Mbn>ZvYH^L+tYD#B~Q6q$va+j=%#x;oQPniLJlY4G`6smE^Q`v9&nueL3)=_lk11?Z;n*8nXF@3^T!u#aH zX@h)&oKfPLMBF=K1*kATQ76u;OnfKJyHW;!aV%~xM?c2S$s^ZrBoS% zCKs-MI$sW#6L_xJ%jvsEW}xI6A0JonoXzZ-o_gDDzfnnvml$)wIR_PPbKdV>Q$AJi zcKf2QH?$^q?Yk{PLrd${5skb04iRY_vx%lrw-1O!#Gq|@qnx`j;>b=@kCB~pe!7p- zv4Q>1BwW+AlDqDSX$b3--KvecbQ`T}MPIa01?}B$b$>-ur^3F4yxa1;LB}+}$s#X# z7J^o}Cd>~_a}55?E~oku|F;vL%p2IJ?2v><=WE6nV`cujiVi8JN_jFB55jl+@vkk+sBI>ysu7V_kdsHjzhX%ulXj@vFOdX z6^qcl6nV-?W1;ovZ1<&*U+zYqua^JZq|vfrOjOGEh)Yx0dShAXkdt?59w;X>do>)n z`F18Zu777j#zogT{(2uX{f*Uwd668K(Mg`Jx|6ygBI%WN5V4Hy=C* z!PoF0cpPFQj7X79o633}xE^t<(-qD>UKZfz4+kEtG+DQoq+c3pkVuHJ1CVG&p$Kmi z99Q^po`3NWr5n4C-x3JQ`ERDJJW;B$bJz*~l2!rK5DuVS*Y zzM9|lwf)CJee`aG!hwMeP@XpzN|VdX5n@o+mt*kfy|AA2#VM~jSnR#Xxzr59F z8en(_TwN7FrwYUGl!$wWvmE&CQ58)NtNK09b$onbur1%arwxD>eN;8=oe$?MXUK9U zl91;9!u5x4Mxr}r!0cQ;po%)>?M_UgAlMvtRnAmLpcc$^7`4JV_5Qw}4*BqICi;Vu zBW+EoH;(3SK_iS!r3)0b+AAnjNP`W62r5(JCykqr;3EAx{A)(aLB9YN!!&&&go~7k zR6o6IJ^qZ?w1q1jQ2`9NEiUzrsz#9n1(f^h_N&Y1v50H;8(J`;nc$VCqH$224rJaj zBrS6k+?whW8qPOqQ1*~bF6eWRN}4ZuV5=l(001@QqQk;G;zrKCXsIjl@*uslwDiY| zJgC@F>i^yS#Ek3whTRefq9Z-j)YQ+JvZc{t(YO@GhUqPdl;N0U_T)DF3`i6w{<@N`RX05ucS@hE)qCiZZvL)O z{pXi&J2g1{lFc$sef>PIA1D{l`KWOH^5OA0leX&9Ybh&@IhqP%MX7wVztd5J; zg$M%c;*wXJUH7|A_eshx)B0LC7_;GXCJYeCj{V3aNU9ZRiimn~`8RoE=0x%Dn1_%; z5m~Qi=G8$uHHZ@bDw((KGnEKgf$E9qJCkyl@+jz6d5-GtSnYtoz(mZ}6X)LyX@lD1jr`4%q|Dli6%c50 zMw(Qb4K*WD;kpE%($De+-3dWq9LHNwMy96U8&$XW;*>$2-K@2MS1?~ffeRVi;qt() zsjJLJuKe7#6Zd`PcEv$3jtRT_=er6cx0a)C01`kr7g%%d?q#Z9v_n-uwoBGB7tC#M zmn!h)zCLiVu*F7hpN58@lvH)~+26T0Ofo#CpiLtTAFpJOo%nFD(>ogY%3yA*Gb&dF z=fQ|ts=SZ{XOLh1x&gW{4ci&-#^9KZjSVIjzZ&c&lq#Y%MM?bv?263)n>YNZEiSO{ zUP1Z+jGW`W4Kx;C7-X0dDS-)HWuVG`8S_xC-@Dr=O`mYkkzrNJfBw(a=)Y01JwZ#K zu5hbNi0;bPVc&9@q~WSf!2&Mo8|mH3FDaa0N6I1yQwkkg(sprlkDoqtDJEzwueGHg zcfFLN$iI%>Dwvao|EA-MGWD5BYKltS%)^=sm*#bU&3Mt~sL5A8-bPJ%dm$g)CLwP5 zuFhH99Iin!U?8CHl$FM8lQ+72<(z4POxccix%`w_d#?Q2X0O*P9vZNDi>QgNv{tn+ zy8KM=*cB}XcVQZO8oGka?N>HzQqy4Ae{AxKrBE|%m?_)jZH8|B#>w8JlSc)MpRjd& zjx8B}&O0~SaMhY}u>8B_L0*rIw88VO#xr-)gLJRxZ8fbeZ0nd$R*4B4xUQN=l^y9T z#cN>ICWl6(d6XI`^_)2vy?A)y&`b==!bg@dZB!Qy2Yo<7=1@$A9)mBZNAKfWPyx%|6A{6dSZvBG~afgbSRh-y{cNBQ}6Nzj&-CT{Pyj1shY-dTdVp+THwR_k2k5g@3jEr0Wto~ ziAhNM1?URgtu%T~7M9>_%ZCElQ@yD&(;AKW9GK*2I!pw}CN-9PP) z)@KI>1qmbYU@zCa?dM6-T8#mvJ457buxe?@XQgm<&mJo9KFFp`{I-)86#`M!SBX>^ zu9fC4;lHIOsmXno=gmqVhGSm550rm~?B9(`IiD;|@Z-VdHqSk2m7%LtJE3YOKL|)4|B&Vkdm16MLhgATW*l|1Yr6T%`LF{Ltu9QmEI85V6TP7Ar7Jjsm;rO%)s%7P0-Ror48aIg#|xU!Joi2@R; zPx29$H~+wMK==e#t7(TEZW5Wl<1+xE=1v!-5VP;+h=z&c+~L(IBrqfwJ!h1Dv`OS& z1?NBNPWkP>N|W4mgeKQoG;|4nKSueVTNrdqIo$(`0p3RJ|3H6}cfILI4XNew%)P3A z($z!%%gswc7a=}6w?|+);joh5*3Dr9D_V1wb^AZC)I6cu=r>*HuJS~@z+Ns^;0M>M zCw1{}lelx}LlPZxEEDffZ;gHNi1}tiyui`X!w)T@l#RuohTl1rbks>F`=RZfldBRl zbzF1v)Qg(T#@$j2&ZsMe$zRU@690>~aBABdzX8t~>Y2+K%VkP&ckACQI^{-ED_lCu zKbtfo==q6rS(qdsQ0vGX0DaQEb=v;VeihG{N*iWUm6eqRZaZ{40Epsg93(ijPH-Cl zul*<5o(OEgduT6sB(N6T(D(RMnm!)$O2RSJ)Vy9h8k!i4Z5%=n>hhdmITk?zbtSzD#Y2c3b`MG>^>gP$cy0jYkAoEi z7D=D@ZB6+NE*Cyzb3|W|JT!E5Zwlt@*JB4c2z5>mu@Awj58e=!9=o2g@pTaRz@KG6 zhB$9}1cWa#VZ=7mymJN$H?m>YjbiNMW=92HWTto6CxVI8WsiIVB3&up4J@}`1Msc~gvgU^$D)oQ1aVyY7^Aq3 zV6i>*FEga8;UGw)o~}kju)BOZys~pWX2-H6vnxUpGu;RL*W(7E#6_iWwYk~w?c2Af zu^J3~gD{W*G5u9|T3YxM91?P-@*-|8nER(OMTO$ic}lXG3ZE1zXOskJ5y`GFsSGh4 z4;+!ATLCUhIEwnu_9hg$XyTGc_Hh6vuM$uPzk9dKTBsT-IQFe=6L{Lcj*ZO^8-eA? zJVq_!{XoqKer#0yRG=AQ0d_Tvxz>%p+jM*og9wxZ=n6qI(7k^8vH~wI8FbWH5ngri z*l|Fzruut(&Cw;_+hKJ(%EKAj?ci2ygq8_TmyK~MT5IAUfiyqsobj~j8MB&{jLd$7 zVyq8z_nQ8!rMQfChJh>a4Zj4S@8_m-i~iGELFLp&k%YPq>g9JRDeOgfkXrlJ7$R1n zsx@!3Y5_9upOceA-;s*O1c4cs1@KNw2& zHKW}$F9it*0iKkuq}}el4;#=p?>Q@=I~l)$=3}LQqp+}les~TeDTz?E&oWwqFusA1 zT6A?!E9f^qH(Hlb^qU^%vuFEpZFUVz`^{nbPBdT%F_CVC$f0fRZJ%#=p?^U;LQqG% zxDEhyD!;+Nt31bkZLD$JxO+@Bz23t%fCZAKG-L-G1JEpx8H?ryQ=juOFfi2rV<~*g zOvtY!vQCM0Eiet~H1yJU$z2T!>LE+9#AI-6%)YcO7l|t?D~oV_8GMqof1+us101#Z+9B_LMR3pQpJ(CGp6Td%czdG> z+g+M#LH6$tA2Qju$j9)`kWWKEOUJ2e{Aoe5&cWc_?V1nOE`*GG?0c!L&Muo;!}8!s z@w3^&eD#GX;ZcWr`<-g@9bm!Dy^~ORX|3VHKi+w}Y2$>1>2k&_-JfIjJtD}Z&9wdT z9D9Tgv61tP&rwK8soix#bKMmpsDp4vT<7ieD8OiuY=z|HBCoA+KWDUGSC@s*Isx*U zoM7YKX&qs(=M>0i80+>L;BKxVQn%=zzJWxuVZ*?&K@y|DS_M$Uu=q?IOcC)DB5R%` zC!a+UG^M7H-4C$brV3ZK(x~}@x&lUcCXh3*n&%kXBp{Ll0PY&uVNgpSK-C!u&pLu)sD`Rfsv6|I^vfC;0#NL07Tsrp!?5%LKjZv&4izA zzugR11N|y-f2zRfOfo_<{jnFK8F3FG)%}OK65A&ck&%CeLXf&a7r7@*bV*5`k&8}y ztKs~sr+&tO;-$aCiS#$PZmB7k>raPUwh4X#os89S~h zO*hW>!}O0A*qb_1NmKS3LHm4TQf^>JWTkp=lue)FdWgQ9!L~CLN@!6XuEFfg*VlK5 z-jakcOzu5R{-Jn+1f~1pyjI32kZr79okqN#g^lw&TE-(R5d#?=+W-u1__PC6g3PH#zdwFq+1K-bnJ8ocBDpERqYEY1Hjy zCdyT=NRs1tZ`ot&+;wv3isbs}{d^Hc@iWY^-;HxxXidkPEKbMKJ6bdMfAvtc{RW(bwo5!mR$!SIr` zgz@#yy*kvHeMg;!n^}o#wY|Ol)h_wyPqUz2WL>D`k5O_XdILDD0GCM*PY|X9{BAVR zD>c^!&x?e5>^cxwUM`(9=-`$Qw7f{}3d*SamV-Q&fQ9ZvadkcRFIXnlQ5vU#oU3m4 z!tBK>k&fVuDmV?WkiAA+O}QsnJWROW(op;_E&$+bS9k!_KR4Qr>#rXLOQsD(QW+)U zgftj50Ysk^KVx#p08CYL1SldwzT2Bc9p-BXhz;bq!dx?q5;>H4GL7tWj3aD*N0~;N3S8JXDlm(@ict3um**9%Vu= zSesQ6b7)+ohtN5(nfI`5LOuK(daD zGqGX9^tuN%6WJvM9AjugXh{6Z?i*^7E%!9Sl)@heD%+7skDX8h&Vn4{J%srM%5Q)C z;2wZMA32%n>EDz>J`ps&)uMNvsSD(SMGKX8E+Vz0p8=li`l=1AtXBY^5@R2twx~SQ z?vDj0lg2g<4OTJjnAd=S$$F?<#npfSve_`un98|NZ}LB-m_!_ujZX0$2^#vc49Mvq1I`+XhFIa)_4KB z{6tJ=iI@>9KR*){X%dL}pmCAwt-CMLJ`fAgrhFyF)^=2a-dOgFQT5?BNH;b&zYSmk z&|UDgYid~PC5!V3xL_Pg@@0H;bKoQ-Vpdrvi=9!RZf+-LuK!QPwj{nlJWY0~?$x7; zX3T6c&b0d(pj)}M(^8&wl%Hw;T=HE^`)R+0nP0Uujb5E|!s7o}i&skc6uhfa$IC?_ z+Mr^hF#Vb&=lKKvMa?4W-^cAQAAiVb%$G=&dXQ^z_?``um{(`ebe;F*jXX}J3@kKW zdw9rVzfTXg2OVWY-*iaTbaC+4P0K5+{*IM<%uB+K@x3w!B9xYPW!+;)Tg(-}AA#d?w z3x|8XC6;nYSBgC||Bn}ON37V{G zRa)BRn@0)|NRg5(kQ!g!y$1t-e62alOT1G|B#6Bw^_LYQqiW&|M1gnGqA&Vc(+ zNmk}22lTL3u*rK!V1awxI)Ct~iQ5(s19?q0L|CLY!Z6OW?Wm$TagwPZ4edP{ynFsW z2UZ1rs(S*dn(~&_7O`A4f|= zv_tluekfgyoJiIlPzh$7Vrxh00Y{IZ0a*Lde}d3{2EoqM?^%frcujQ#)Z zqio>iy^c>Heog+8Kw`qzA)-}==V-*j$tXq)*h$Zd!g&7f5URhcsIHlTnFadFaR=*j zW!0X4VUEv#76@c<%>fv_6H94y+{VsEU}S*L2(_@zE(EZw|8;27rP{1U?Bk&8As-_l>)*V| zQUtX{a-h})A31!OIAD|g&K2UcYI{JNA=bsvg1EEhL0qNMN#Kw%B3ZrYLI}2jvcK>4#{VE(D)83Czi$*}862Ico8PPS=x@9FuadIAAZm5a z&nS)Vf4n3`_{4|el#t^f;&1S4eJYiNd9W6HB2(n)NPo96w(CE-$pAH~ee*snhGQ2VKU`lPQie%;D`gz&Ji4PYHghhg6A(da8z@88)HT)V6{y6!3QBj*IM6Z`I z9TpOzj&QgTs9#?Ia^Cv5^Doam+=8RDJTZnz-n5IwMsL*toKvDNOM#Su8GebOdr zp9b#;VN4Vayjsu2b?xcXr>QY7{lhd!;T0)kQdM=h_%&I4 zlaP4!d5PgQChD20Xq*G<*u5Z<#ey&d&X|}{HXy($-=yInFyhN4%qqz91xg*PD zdA3Y@&t2DWrT+bPr&YUcKzxo~wr;<%lbU`7>z;i(_o}h9*ADCVTkqj)KW}Vfv7%M7 z>Q4_uFfIOLXEB-UKQW-^_du4b`*4b8+d7)CrU*Y#`p-vL1gI(eN1Du}--np)nAp6A zyYt~Y;m%Fd?6dG*IyaJBGbkMJlu4N3-h`g>$cqqJJ>8kDi33&p+f|E4(_cl6a$QND zwchA+*-A-7Es~h$NL%PrMs3{Sk z6f%nG#O=em0vUH+AIms(*%n7cZ@6OO1X&!COo23R`>;3Cg1Ev$OmduS-;bdc6J!wq zP~^S3^MS$_hyl?UyE`iwZd+lopf!);u~%bNYaEv7D&gOD1$~DgJfH(u zNK1(E>ML-QFM)=;T_PYd3mqXbKaw#k`S>=15GEmHXR78BH$}E^ftu^##HrJPd`P;u z9hP;klQoI)JXt}8i=8jG-xnBYv^!L94g@8+9v3K_NYH>}M2aU=*mTJa7-3=jRS&(e zcBC1?u>&BqcEwOwiIKz7f}1Bisudi5V6;WQhfWRD0%ZNG#M_H7^SnBFADSOL5YAhM z^56!N4qzp9JW~Lqc&2KAj&(CkmGze(tAWyI-9~7YZR;i~BH(-V=f>A%1L^7+>nzRBf|tLOpol0SF3sK22ndk4BS>U(OchYugV>IvU1xmGR5P@23I z?Kq_m=Q0s0iG(^Nz@LtZwl!81Vbuuu2ll|c_keYBDjY;9sO-Sdwkh>6p>>jdVzSza zsmf~`Ie!*E6m?19#S8$!Ml)kYx4Ou6T!`w#4@@ki?gT5(Pk}uUf~Q-C8UnmaTxP61 zAN^~ZZwml`&(Sa$zh-BC0tj6@}R+SVEWZiF}QZ-gz;w&9*S?P`3fL zO|e4FN%pldmElpP#``!6aND5cm(x7zhi)*sUg14ld`a3N6vT9NbYq2K>>6duFD}pM z-EN=qdRkgKc)x}7;wG9E5`rt%y13rC#keZy+i8{+-`|F3_{&x_XVtC=AH5y*1PiV*FfCrR^p4Hv?pPrPx zESUn*(61_xnwskGJQONhqQJlKZFT(EXoBe~ti;#Mw)d-Wn!(ws2PASnn#L$RWIqO( z;2`B;^YMserA;!JEvPAeb6Khwq?!g6!@WG=vs6pIrz%~JnSB}U_zy8v#khqZVwH=~ zx-C2VwW+D+h}qmx&ykB}p)rmz&R>njABibT)S!=kRyJmu!HI)@E!ws~!nWY&li3RS zlC7?GCn2G8K;`$X@uvrrC1pxxzbn9Y_2t6HYfshv;+H0qdknmL4ZZ^x@Sl1Z78d5( zT+Y9~bjG8Uvp>c$+)s{*ipqEUqt4~xSiiiJjy|^=Z1FeuPSCgR4?3}qjpj7}2U7~g zecC$bdFn~N_a{n{nfNu5UOzo)wV~RSQL_4sVU4~I->3E;*KX&1@O#yYTP@q~7tY^6U*!AcgM z++7BxZ35ShdqwT{78Yvc?AcIwPdh}?kwYR(t0Zgs)rZ`VYAaIj7aqPONlUp?U8c>E z)7Wy){f|n+CXr~9oPl%Up|Le*Uvk$xQ}S+oWpmp_Wy#7hMB(lT1-F8tczN)_>r+c*5qXELCMc+9xf^|H< zuk&B@mUui{bGc-lo%cj^4-6pmYF1HE4c{+FNGnj5woH{baST^*k*>^&UQ+nA{Ic|% zU+#6kylK6UZh)qT}|VOZyKnwg<>mDrD|BeBO_bMN6RHtfFU{9|q*R!E5B z)={w#?U3V-2H4AQ=hbKDeQ;#g&Pz!1Zk~O%n!Yu#JmrIF)>HPJ&976g`sKMCtE*6A zVQX*wDp+>@smy_ta+9-yWqtIcTLQn*t&uYbXgFAip5opC$*wbr-!=!T<(%={QCWeV z>1Khh>|wE02js4&ggrd|=-S5bv*(@$y)-(QsTy1ssJmT3Uav?_u6>=xgj`2oXvNzj ztj`onD@wk0e{$zbezjO5MSse?0id?L`N2k?9 z-?^x?@jsUmE8_+ocgA06^=$iO<(}PhX zO_3UxcJEY4-sPh`WoP+v>B-Ca{47-BF_B{1l`Fbtl9hFoW7ZiVi+0V1bpRl26HAga$p$}`T0d{;y>rxrMegIz@ypUN@ndDZ;x;r(f^s`jA%fhKg&qPd9pMC7aaA{RwgW!ME8m)vW(n%n{}-cDQEH z)lo2=eZz^!HXf$7KDlkAf&^us$pb#@(3)*+-CEwO{=&v8yg#4XUhfn?c5upze6NPNm$VsanI@r zM^0}{VjG|7C`RkN)lJIskxXW1{c=CfFS+{^{W{0cdNh1_zJD})RIyfWSo+w1-7@_; zmv3%S@0OHhEsvZy;rrN2Ah-0*rY=cZLTFOXrLRv3-&Q|6CnwKt#H&5q&e=y$`qIfiY zuy#=QB=;}TrzKw{@^1O%S<=ut?s%!a>Q>IuA*#luzMqu*!sN;)afjXyqr z>twpRpG6O~gofnYCd#wmvD0u4DZ}^&^lp$l;woOFA+hg{}iJfiQ0W=3HFN-m>K6os9p&)_rv@D@%bC%A& zBl6-sz%#?{-n|U%|Ib-&WdBc<%J?)9Ooc5gLWs{yDjay*fgZ9kk?jdaGK;;)k~5? zU3j(-Cwe}*GUMf(3I5zH_1}4FX!yjSS%jd$i6&F7jF%TXm$&}!X+;XSX4~Yv4rl^<{m|5Ra?&rR=ZiurNa4Ln zT6#LMLfBwn;(S7B*qr%JmeCdrT8Wv~?5D1UPi1mP_Ps^*uAv~)w1iOYRwAw&Wl zEh$T>YWAU_M%q~96ZajJOFF7z`X!6z>uj_;a!@|2Qi;xmNc-uLXT;#p7LDw%+3VM$?vda@fUQLbGo? zZ@=`7C7z|72L_#1`832n)@EOPlcOy*VyJfNaCwR9zpeno*q^k7w2psY0>3<%j!PIk zEbx{%#liOR)@oYH*=WkTO%$tFcUj8q9J#$JcF@&5E~Djf_|@MrccpMg=lECVHT#q9 zrKSJj4y18Z6}cDvr}AKI@bTkUle|>G$i*#^(diZ0K!q>f*xsSo=V&Y7dQL?a!79RT!CUdDh%5fxUo z{e~D+n9sQEk_Pc%&dSO8;dQA7QzC52T_j&LK4RyyJ2EnI)sPkz?+z@q*De|tE%eIX zxO6D`La39$HFqXJ$fLQ|c0* z;_aU2wM*xQ3wvs{G8L!7Ja&y|ERQW^ZFRZz%V)yQTg7yyKuX7YL$Rr>O!4IHSHNJz zyrt&2<) z9~`>!R)RB!u~Y80U*6oMY=bR_)K1MySYA}5rF>i|Se6#+ba2a5`GtHN_8dxyRdn+D zoOkP~%j$Oz-aO60Vxw|;hgForzRBt)hezH;Y1}_|?TAWxt{&j_>OQ|j;=rSW{w{-w z0u>i`B=1Z=fPmcJd~A^ToC# z!LmewZPHIPm$&2i=eM0pW@rtdxpK8-;IITfl<(+Qd=@H~X9aqmzo_9ZVopaKVlbP1 z<66dG%F;W_zpGChqeQri{;f;MX8)ej1h1eP&c3g*J<5L8h8vEJ^R9f$D@Zvb{$J%xTDF06 zO>(fL|IUv>y%OCID{`*)(Mnd_R*XKE5jZ5=;4Q(pZNKxSlg?Y4mbM0F7pV3x&1vRt zlNUFwUKC)WZ#}v^^=NJ;HLJ#XT2g+(Bx%iyTQ#{_Pg=IbvM+wruOD^i>3b<>!mQ=L zzv!CPaaHsB4KHJa-4`#($VcB;wAy7{spUWK5EtY4DWtgD@W79(;l_a>W#!#Qb&=e? zPE?^U1d@VnU-D#lja=-hU0$f|!Pqi9I2hQ=I}*U{+^SD~7i4xjXk%k@&(KjNetF(! zd35}Ve6a+kyYjOi5kkIx{rcU&X9_$-@8Qai{j|n1;9f?$emG*vhV_B@)A3!cttS^6 zeCBj|Qc}~orN!{vJSe>4KmIMEE^3+~GXSGwRf8-Yo>|XWqTHHS%ryrv2EX+~9BL5cSQ>Cv7`l@z4&P?*Z z=WC%(a3t*7Eukv!<}B6b9Tq(fnd5a`tlN8|_FopAtW4&m*{D+&XEK@m`w3_HhRv4I z?TKUmXjOj4me+!aOvR`?w4#ke&d2nwWQ51cuO*fMy74V@* zUWg#YXu*4%+1&8+z5AJ-^O`XIw*NTvu{q~Vo{~y2clnL>TFG7^q2#5F$0CI5)7uT1 zL#<=Zo=ZHCB)It~zh=pY;S`E^6Yi=D}%KT;11M}>2_T@{|Gu~s`( zY+O5}p-QFw4g&p_|qH%H1LzbGg=Agm-QfF;uoXEO9hhfN5A> zn^_<#NU-2b#u2H&hxsun4tYuk$2FAex?gTpmR3;tdg5k=j}+(PhsafT?1Z8WI13wj zn5?SyRPOa#WX!I=d3yUM!$oant)c0WpMqueZV&cbPX}hC$dvK;q`g?r_Ix?+rQ@w5 zzWJSF{|N5POW&Bkqjot(0H|Az;RstmFM>%=_7{$llateYu1MNeJJ=?EFBe#{ABHT> znBq(P75U24^a4r#<=M*UT81YLKi@*YVuP&L&m&1~BTO!b1t4ZFgPs1rsiN4lR-=&G zmqIbqbbQhzcHTmXic0%(Y~OK))+cGpJ8q1elqI1)<9~Io=Q9#(OnbEw^*^oEUu<*x z!6p*TRFqY+Rb1@ISykTa7x?e%C`O%7JC$)gTRLg@!tD^D6YogUJ#Jzzbd*~zDoiBV z;n5kJSM?~NCJrvX6T8uykm8rW-$g>6zSUtdRAZm?6hrG=uZ^OXghr~Yx8B-`1F;_t z-KyHpYV5;X<-IDk#w;wonlUIA{Z)CB*{0_XEiq9&T-ohDm`SGYP?XYX(LSFs*z5jc z>J((`B{W{Pg)J|{FFShv5EkIFnaM!DtX&$etq3)pOf)ny()%oz90~mJNwjSUXUW*r zzo`>bmwiyPx7k;t7`MF8Unynwr|OpT$@S%PbM8fdKG}uez;_cK+EeRVu^j-Cs|M8U zUw0`}QDycI`sEF}lqRG_ouMe7@hX6K1AX9DL@HNa%=W^^)7;dY(UV>ty{KvkhW{3^!k~+RxBhrKWs} z-?-3Q?nH8se*ecO!3P(Q=0Wq5mZGt&)OzLz@8^gIjuu4;l=;X0|8Wg+5Ac)4XMz2qD ztHBo@rPu=Jf(>haH)ibA*vGDTG^O0ZLe;6sjOl@3$&TsILpM+NEY;he?wRTn5()`6 zo@DrPbopFx{WYVgYz`}Fk>(g)RD_G>5sC-6qRj#>Z3zoyciz9{@qY96*;m&)w9me* zC~UZZ2IS9-v~vCQyFTu@SRKrRtc5`2b0u*dOu)xv1@tJ@Z`yDH#jwM3jTrH0Pe{GdrIQ5p_$o@ z)ye~EA!QvHKVWlsFp^EiXQONVHLjiMCs$5 zu=LAQ$F!z)w46)aiHc~GtD*zHS=2?5uFrjr`S(i?M@z3P|KpL^)lxF|Ms#<+ag>GP ztLEUdIFV0>$=4%`U0G=(N+o&4qWoQXxX1O>qm%)dhV|HCr6~ z#`^`L*gW8oc>Jns@fT;;j8_*YmXKcX)8H`# zY-VUJVCCruF1+zWVeD#DWqy}?^cuNj0GLd)6snIxw3K0Xz$-Zev=ptzeAC9MvfcEp zc~-7ZOl94xTJm=G4j$Wbp)`S#lSr9vbW50PZvmpBU7E0Ys`i=I;`8HejFRPBE2YzPib%0x%>L^AiN zX~wXR*`jT-c;bsMUGEQRJW8~*iGO7NCS72M<}+T~k|xgW(v_`^4P$1uCHE@wY7-u9 zW{yvsGiN=~a55z3ScD>K9=E{?H9hunhnLJ2) z4RTg8CfoJ&%JmJL({vj8HZU!pemOfK%`|-|%p_I#bs`R92#@V6!A_V}Rf5JNoJhY$ zWz?-UR7_?3+Oei9_u}3D9%s_xqTm@zNT8fOD=hQso8N4&*;4PU*z%9~w-ptE*K&PT zX7X#_&3Dd}5GzdK$Lz3jG+p?jvv^$T*QFcVFH!kY?&H~+es&Q>|3uY#hQLTed+A$o ze(%x#H+GXc+;}}>e6s1pnW`c_z|EO1wO?E04rsVs$p1Cvj-D~G;itkhjdVnxi?^fl zflEybskO>!ve)lAhJ$)k=KkDmc(jv5zb&ax*5}-n_}U~~z{6T>`nF>xB5OKL_MPgh z?)Y~O1-1L4@e8aE!sz4tEk8Mz5M<}0b#gnNzm-f3UUGgD-EqWbS8t+T>rPo(%8Tt6 zCrnF0e7sMc0 zwHw?iKBFgLdCGSu&fmzBgfO>_BCm4qFs_Mv7WOXUfncf022^^R%J{6N|kp?3#STwg52qMPD5{PRna{kG6ll)jgq-zw7{=a#oi=QJ$qm)hRvCvWW@}a2FD(ClYi4P7c_Id}M zi2LK0_ht4$a(idtC2P~D#Ndb|pDT;alJrYbewn@m)twctX-I}`9Ow2 z1sZspA_<%QYSF_Sn#laQUv+3;S_Hk{V<8d2=O7An2>6wX&dE>FwZ-TIC-{zqj{ zGn5=CrW)qsG$DJ>((#~L+xP!&mGtZKmH`1@!DJ>hSaORVXHM8l*R3Yu z5Il*pi16Q*(b6D&K`Jmwh3AF*n&2P+SByp9iMht zi*o1hoK8EdUUhNffw#q#4!o+S6(*N$-}S^)1yXe zr}jM(64H3|#m2fSNrN((-1yChRnZ{#gaucA%m|L1;;9~v;XfOgvn4)7W)}13?}#bA z<+zXQR?_u|3wBKXPg5EO*F+uL`DfSSPsQSdwBW?2RV^ugdAoM+khVz0uNPr);-mhe zwB6RTkz#$ResV2R!Mb&MEUEkHTU)jMf1ZK&VoJWZ<1SiCPi1x*Gd|tSnYLm)lz*p7 z(GRBeE+8mo3}48gZ;>Jo!}sI_ukZHU(Hu;e;?n;=(%u7}>-B#hmx>ZenGvOd?3A)8 zDlMt3Y%)p+*()i#L}jH&+l)lELdtH4NJPf5!aIBYu3P7v&pDsZ`Fy|M|Ksm*>Ty(f zjr)F%>v`SRWmu>Au;(UISYoAYYj#Y>#IOO7y1mJ*KWiqw{>cAQ74x6Zq>MZhnUbZ} zqb9c#4ENtmOpsi+mG2Y(D#6NL*$-SA(ONaLs#1&ZeU2?tp$~2{e`WL?W!iRrx>yc$ zvNf~A)g^Xn5@M6~_t3t~@oTIwyuJK@06M7mZB6EmI?eGbL?7@6CGvUEMYeqS9~R7om-e>OXpEoWVbxl~6Y79xUvk#x(&tghUnIuTpM zaPRKd3^f;Yse01M;P{ zaQlQC$G#t514>$Z%be${6@vG)h(?`uQ2zIQ0t{(PBJ%bmAGg41!NhQ(BSIQ$M8|bA z>^aoCxSmOl?lrfq(pGAI^Yc(in!uQs&@?5xce9np?dOxtqCu4cDis1a2Y`aS*D88P z(ZdtUkFEnZ3ppBe!>{wKfC?TLW1Q*z`@%aTlHE)?kJfE*UwTWu?mr)cRs^1zl;wu( z{KdGZ*eLQSZW}(r?39X1QCDNBwZLm%UrOeH2(}Z;=Oon(EpqQvPua7iY2#g!jdq4| zhA?M#GMgOd(&v5uM#6_D!Dvwv-1Izio^=hrdh2;{bcaHPaF?n@zp%mOXG#SY1>#)m~laM~$5)!-k zKjOvPi&@=>i-dkfEv_)Q<%8=PwX?$8wjZqB>Wu`Z6P&HaaqzqE#FGOOI@pOT6{ zqP(_xhWSZA!gZR?v!g|cjn-4A(gp<+yoT>hGdwyR^0o?@`&S@X_AdYPjH2qK_=OQDpZgBgUty4nwPZqSzS@B*rkt)KBld;uBfMsn zAianD(`@!4#~f9=N3TH30a%?qm)zR)+?e)MnVs$Vy5Mr`+vi>WPxqTc?w6I;t1E+p z{rcQqSM4sfGTGRR(dJ&?%}>))x||B}}ysNv)kV z5I7d|a`;xX`rFwj%q17IaNfH|`M~WS=G$is4G+}YcJ($KqaV*vp+DI4kOO1iie|s* z<+rBkK17r(Y*{8O8k8o#H;J*E7IGR@ND|}s2HFf3a*JPb4|}@L6dr#N&wy}U(AuR@ z_lfI|dG^0v<{r-@#hH{vuPGsBI#)f4jw8sv95-WsM zoOa*$U#*|6*yZ%YO>gLm)@$FvX~q6Z=cp$V2mU>Z(KQ*3(Mt$PNIAL7)8xEkjx>oH ze^T)|Xuk?y&_|Az?nwX3HcuYg{G4viie;=mq`o7HODc4b@5>qIyQsL#q<4=6l|4ZH zB45PvNBz?F$CA~P*w36kefMtlAsKGd3ie=Y|p2ol#p-JY(tmhOR@b^Vg&KX+A zKb=37M&3J>(T08`4!Ot1O1ey88|_npRjF^?$tzhAV6)R?)Ma$^t0_}bl3DWCY^HsK zI>9yXih?OWrV3u1n=RTKCRz1`<6gYA-CyS#d`qow**xF(+>Tp(#pM&vlDyRRhf$JQ zgAVibZNIls;$)5a=Vp(L`pZ^N46`D59~|-aHslLB;d%Ip!665Y8dfItpO0+kTg{K> ze6?s4(oP!dzFE)y{Yzs}_M{kd=34`$OBb_L;{Tj-|G9o2u6vUAg_6yx4XBZ zE+^z={oS3Cy!IULS`eUvd&YP*e+2I;)O8jAo?&CHivza-eiD&`B&CZ=_>Xb!f zWMWb|FRh}SI6f+@a)3#NS^OBD$P-JC<7f5jH1%nPcT~{!IfV3i`lp+z-ny6-rR`^y zrhNj5T1`o}5`!h~Wy_DOUX5r>MfLiyAl>Jb;<~q2_sNM!b<1(EA#NMgJ}Ht^6Omr@|V^hI-a3B<;ZV(!Nrx^XY<*m3s+T6LJ?(bJ~f7o}R+B0U%nwpAISW~ap zDpemYiOqpxT@J-v^E49~hVp$*60nl~BU`UBM?t{5HZq_Fx4qq7y*n{p*yLX1J*|iQ z4$xA&idb&2)5P(4$XBtA_3I=ZVcmvz3aG4Az&A2lwgX0jXO z27`{+GrW~J{O{3#kgSF*M0c8M@2a*^KS%dL1gVQRA%ORRl9H}Ns3DX3tU-Zb>gOiO zZTajo@%+bjR9)vsm+;2*9`^xn?aTcdZx%Mh1#=GDyS~nz)O|M!0tQcVSoIb3IJu|0dC2AVwP@@1 zy>1$|`ROM0No!|9UKUfRUf~w|v#~w+35AMdZF%W&^&JjtpBZs7zVX#+ zc3D>+%rz^|TR3{#y?wLo+`XRBz0WdaH0s7$=G$gmI)c5tCQL?dyuD$1%1ui_aHBm( zNpP^*hxyqzVaKmB&jw$8^d&CNO!@wP6{axhFzL#AmAc>u{1Ia+y+SJK`3lmNv(CDzmHYcl@B7(~If&qL(<*s3)BheM`-3 zLsW0g^CS6P65W!1vE_3jMq&M5T0eciHf#NIqV<*X4QU1i_W88n`PS=e4L%z-+^*M? z;~s}YvkfjnTWJ1Je(<*uUs+TdCpGtv~F`z z31x-a9HodmKbvbtuIsRb;HY(XrcJuP`B09QTJ{-3O^v3AweBrbMLP_tBK9f>erSBk zmsTk$WNB3xS0A~rGDl`)2}Wz}l)VeXG~|`*fA+$GiF-nIPODLUC6k%R#%^Y_ zk5F^PX*lH|Ufz{XZoTijN&()smOs1W_**JVrrcP1=oPEf$!p6|fKWZ%XMc77lNx3Q zhyA2FTfbYWnfK_wUnCWkWnNdHu8Mlq7nk}CEwPmSMr`<6BZI0YugHO`dH;S*jfmXx znsu`B?`OQ6zdxppbGT{%{F_UPx1uN1)H_y2pzMGMOJ?=*g(yfhpvjVXQ$6yT%6H84 z5_+mS`@#w?-v0Y&_4gWsimJ(GrZnX=-?@PYQxm5sJmeY3qHp|%5~}1aYvzv7>-}HF zFU<{Y+&5}?)gby_@?apBz%g~S`^T8x1u|Ef0ojA5Yy3b$ut-o++ML9iwdBr153y!G z*e}4GdAXlOncq?ui}Wv81^xv-f{l{m`-L8dHVXh1qyi#yG3(o(#Fl^cU4)f7mn*Z` z+O^%OM#}ytWebz~UgaZ9VL<^2xup(FDngN}O3ks2fEmEad~M22>FF7*xW4ui7T6n? zmcG>3xA~-%DV9wHkU+lzZwU~ZH9;#yA$7;uJ)vx))ocVI*iQ3H1ohvZW z-n6SQg?$4?uO8tAF(--&Z-mdjBsW1-XTpa?nJ;%|zA?IEnbh8cO%-!;Qd9FP(TSDP zkpjFdQuaao_Dq!poxS5xu6g=(S^8>TBiB3ReoTt~YR8=dNE_1#2=cGXd!gpR_kX&q z_xi^eKKts`3opA^cFk(8e+_|SxL6miBC~{84lYT#FGx)fWb!_2ZKXu0d{LjE( z4X|b5uQMB*0Huuo@K9~;DGJ;0aIQdL-+eB#M6X9k_mA#aAK|yGa=P*C4=wZ2#IED%+j2!4tt_`w!&I3bn(p8@h?c zm{oMo~=(f5mglSDJv%y zt+drrv1Yn$FD0F`Mn|PtkE};<^)b2NE8tQXeWG>+)1tZa`$jZ7RQ$+K41TOrr}<;+ zld1&wEjSUelCN+51ER4${Co4-WR*qN zlpvm*=#&zYdqX%;POrt6DtCyR)|24CPu2d_XM$Dvm#WkT?efAEEvySg-5qL&jtEqjcJHS=bFvVT zT!ihF9QjYz1sJloS*rW^o7C^G8@96_QNFru-wkz56>F(|VL{qkrG1ZO8GP496xm6l z2z0luI2ZJ_@X5)?O?@;hqud$)AY;$fzgg7vbpAw{sQ7h+?F*M99F)~j;qoSWdSz&3 zXkj+N1V+{$WU1d3QWY7p z)#>aCTaLGAb#WEMZhR2%;3Ee|k!GrY!-)st)r7HioC6&^<=6YXk zuFg~}X)m8@_dWR4TY6_`{bj3RVo>d6krZbuqM~0Tnd*AT+}hgu=ug6JbZ+%@_L%K6 z3|%4eVm50x7U-q%v7^dtoNd1oE@|<=J`p)D) zT1RxPhdC(9xF|~lg#8+5T&1TpjAcX?$Qt1HTW@ip#k(t|Oil}!oZorx|8}WUrQfIS zck0Z9B#Bag!+0dVbf+bXs1yfm0C=XS>b-);a~;mFvMgw%Fj#k@5bYENa5mc0ipN1QKg$FVuzR@aaB zxLHCy`%SCsI3zJKt9ASItbN@Nmxe5Z=CrxqwAbMEj9s5z`-?fjT+hwWUKElq2j`(V!S&qoTL zTO1_lF}D+GUP#OrB(3(QBziji?-Ay7=UJw7i#WcH+E!Uw+W)$-A1y3IaJu0@#uFR- z^ftxv_yIz4QW9u3?>7D7H9asKsODjEt{?NL(#?^2t1aR@v!bPd?P>hlXr z;;nbB+nS*z1Ty4`p}Dkwv8Df>Hd12v_`73i`L@=+>QzB)+6 zQ?8dtYE%7dYD2Js3F@C4>y1>pzyll@H2NM(+s%~>CRKKG%h)gkp2@7y4hk_?%~HmL zW|#xWPrVC$jkAHY

    5-rln9Orc^MyDwbK3PNHfVYAmW@QL9^Kt?rsg{x8U==?3g z+%eM7|0Bgjp!9$&ZF{$_@`T=Es>aXH3)9oe8prwcWNwYvc7NK(l1Ug3^I$vx=3jW> z6euY+VwoDG?VKnSs(k56CDq+C>Xu$uD6byR!sP3)42;zTEan?o*5#m|fvY46&rcpf zLBVFX{zvkoPhJdUHPf^ze1GL%y2iUFP{wuZvOG)m6-}@Gi$K!gne8d>z@d@Mg;gv3 zG1$0EaNhwH=Cb$ybTfa?mbk#GBGf)XZ(n6$Mw9jV#fs(BiYk9R_h)?|!jZGUYpAI% z93E&bQow4Bj~Y01K!Bk}iG+)rH*X%7uWgUewIQTJuc6tydo0Q&yuL@j`wW&@S1B)R zrrf}3wNS%}%Z5=Cc`mKfU)iAG(^~p!y3Su-h$MaA%j7vlnckb;z(VS|Uz2GouB2U9>Y#98 zCi}MWpumHd!!Q@UiAVSOW_J#v)ZU8Z!XN2u}%E z(DAD?!Q%bBCZ(t;HK!iZz>{LXR&dcNjBN>(Q5YdLv>npLdxCukV~ud*KypO`G?K{C z(47-=i^dg1@62ti4PX`kQNGMCdK+d!zwhS(%^zt=q;u?@KJ#lo{{`B=s}CUPg38V$ zwi}qgUC`NS)%@YAGkFq^EWo2ZbV%;c>p*S%>pG0G>&xYEDul=oh2D72(M;<;GcinJ zZl%&)Es#{7o|Y4Q35fY#o$@W>f(+=T2V!uvxLrd;~9-+lJuBY74Ww=}m+m&*;> z4HvXd7ns+9cB%QBQ{M1I`MjbB}^z+Qxki2B2XmU38^K=Z{sGbENEI=!FmaO zgiVvWBYlNDC3;>o^+o%08T-5apw*LY`#+4aR4@LI=(al#ur*aM#`V8na`A6W*jO7r z3tC1((t7eW28^dtbHcTcnfgQ6OhR)lMbl;LI6mQ^6f@66@w`NaY&~=4?Z$3s1HAb8{$M*e`Y}C(5Z-J`@ z!t1Way)rn5-Qn-m(x z)H|FO%_)dlM@40!sS_blz@QOf<}uU36N<9M;#@0Xp0`ruT1~qKGO8ES_w(n^tr_~J zi{__0K+B~BIvnKXEd*8cHP+0}4@1 z3P(E#%e~)1K_)eSq+(ZJ@-r^~rA|1S{C528uZI6`Fa5tf_!WyY7S`T5Ua4;W%5CV% zI*mVeFYWI#+hI#iyjN)XJntQfqUpeR3q1U)^RHVasMbmj< zl@{TrkAglcFXbOJlNZWXyTl>{z8 zB>jaqj$xmb6SDIJZikbcAZ^!eozf&kTpUs?rj-|4U@4M^AL{k<9?_9Ip4~}K|HoLR z1`4JnXO;XqF^)6$!hGwTHO%tw*MmwA-;W4c^GShKAZsvQN6e1E^tw)!{It!^il7g1* zuh!gIg+m4P&1*m53?N%O;g)7SFDS%w&{;^NjSP-Y-Z>XiZZFjFT z_D4+BnSC>!Pq+N=8jkIj<->WX_Y?l}Lp)bwf4m^|5aDb(rn$GQS2)U+DTlf>q@iHY zargqQY_Xko+xD+{yfJyJ|59q`UZ|z|Ki_FbMFyADRq?}=MsJFhPK2*+7%kGQJ?J@S=@cfh<_&iC+_lc97?7g{u#0d5z#ANva=wN%?56XoAWG5^a7t@|is!6|CYsqod1 zXWVkGc?CJ#M#Ln1fAGu=`Ij@!6f;IeTYw<<;Ss?O8dZ@ep{c=IM3E_4gD6d#AXK^Q zTw8HgR!iUe=Y(4Pb#~CXd=H*3@(tEvtk3vUOm=G)XiNWrS^fgd7A`WLl>U1NL?u?F z$9_$P{JaYTk3$`|hdT5>m>(^g)0(L_oUL!0hHOX~NggjJ!8xL9Iub{MoY5l~y9+?~f zP^ED8lVb<+PPRLBT-o`$dS@$gURbEdDRTPRyo$RKWS0_u#`3(@S%39UT5a4qUH18X z`aeJ+xdJZU(K;s>e!R9&n2rvd7R~KRn9!Q<4^9wsdWJMQYC>1YMpPg zTnmKfKPb$87`~@4bT4rPfkfDD$t>lq^Gh2Kew7K=!|^{Xf%U zd1g2$|1{kzJ~r!rsK`1}PP7o_JG^H?U#3TpMfM=l;7p5CXg~NNnz=1DvR&e#K}byt zcb|n5H^2W{UcKr&-NXliP(?E{WTWm5prG6M8%8R&umhmE-%d&DryzYigaBUbk)rD(}Qgt zdgnQBj@t*@uu+`P>-(3PJo)IjJT_@{uUk~>&LW#s_tVYtL(bIMNjU|AGB##cj9qU! zCs$XBHI(ReCrZCgeaKrvUt$z5JS4fc?TcVy0lQ_=Bz}Ekx4hST;rfz5aPI%}<4vjR zMOYF>+6_W84ytjZWs02jPV|}NlXo{qrf1uCgoY0qPI+jIdj%~6+{ zm&7m={@LeD_4pdL)^!cL)TOoz&}ZJf=pzYPeBOkngBlt*fI@{%$RCI$ox$lCn!_K& z%&XWT&&b!4?x6~&m6hwHFG0ujE@S{89>=^PrGlo3+E*Pql4VdA42y{HgBQYthdjIA zB4|Owu@$xlZC$r)Uqd^WMnj`=HaB&X>QUyU@DU_pMv!nEt`sc_=vxba6?lFus8`|W zZe@smw0br?MEYBcco4bvA3n@t$_`T&$YgG}`a}9>f^febd{Qi9{K#G5sI*D5f72&`GY}Okh0Ie}c=$!A z$cszDOAXS(`(StiN5EkFfjyh8KR`>W4YdamUD|%wH?@z*^g+mJ)tWVHMx1B86o?oz z6yA+7&f&nX2YZ9)Jm~lXC{u^91lSXF8Dr{@1RH;SM5|&`4U2#YYzyf3V z|Fy{Kg}V9}yZS~OdbjO3?30KJqGDhxcpv(1u<;-w=IL--fQdsf zPN~bOC7fOh6CL7_L3F*K47?SJ^E5@RJoc_wIYds`slU+&))K2Di2^loAze&E&u{0- z0s~4}ZbrzV20=4;1GF}yqoeUkOx_G(D_V4)E5^lIg1XP)_e+;ODwdcl&KO_3g3Nu5CAtDdg%;nk5>oNc?AK|QnMvCwneR>&{BhzE)Tq#cf%614nJdCXu8#9AIX{m-mS|Q zTkqh(FRsPbC)S+{Urz$qe||*oQoR-s(6bF+K|T@-5gePYF0818m@e% zvTsi-mNY@y49?c#c*gf1Jqqq-+FdQY?9|?GaNjeWpVFEsnjfEsO6P9*@_2qaq7@E% zmBl#H;ZuJ`*lw~bCl-YZT#?srIT9N%G&B_7mz=oOYi`nlD8(WYTrM*aaCD^t%5`}k zk0&!sY2at*5_tDn#^b~wC{vigrGVhJIpvjlqU69C%1R=-3U%BU+z9EAW+SGHbrUYK z+(aRq*dv@capH+j7BcrY=ya<4Hjyo|*W=vk#VM{FK$+_(hC zVrW;I_~az?#h+fg{cy<|HCbYz!`3X>{EPCy1n{`k--f}4F0(RnX ze%L0}A-4jeY<=w5>a{yJS|@bH>oh6&RU%%uw|)`d^40&jgzzU}feYzW zq~nVqSw#uG!9J3S1MHR?$tPAX=@a#zK5FhWPGPI!2Y}xheAMqyM z##$nw0Ft>0&^zTf>2k_@2Vp%TnTwyG#buCa8DAYz&H(&QVSa{K00?r~HEd_V9NF}B z$V<2cX$UPz(bwyozc7us9SmQhp)ovM&SQ$G4C}`BKIl1H zet5_LGb8rQ0SyhO?7{dyxBz9iw6LhCW!cTbyH9V4tK~DXG^Y|hiUr5*`BR-3F5{*w zTW^|iSk%NSVb@=ai(?Efqt=N)jtwqCPIbZH3|-Tr#*u>L-P&o(nwCZ) zot*pFcdAw@vQB&!PqVqNp^)-J;I|(eyx|cb&Eh5WN>TUoUzZdymm%`u($Xhoogy|Z zhvR??)G~*gtkRSkMydE=|0oV|bcm!9di@aw#*NIZZ z&m)aM_tGELVeyY~NTMRfCZGx3f8@x@pvcbd?t7>gA%1>I+Xi;ZZBBVuLjkahrJ1#X zT*w{wK`HnlDxcNW&;TA~N1XGJo0SyO`lPY#h_EHBYKjM(OveXX-c(eqb~sv9SyfZ> z8o{=Y=3ytNK#RjyjG?kZ$ao_9oed%kY5^};95CuhC%errCx*3XByAV5o;imq0I z7%}vIN~v5_xCpg(QLACU$FsoaqxOBt%gtcB9ErxL9eO{)(ZtgmRtb(CBGpX00HL7y{d}hF&w;3T=g2XW_RBkM4 znaE9M@2ykXqBoE*F+T`}uqyFE4d3(=#poAj2$5T07c-(FsWc#987?2SM&eeIK5?*Ei#NZMGIxJGX-L4?F}Nc6(Q{mc{HoH2?TrIYrRC)vSc^(<5_)%Ebq#cPdvdR$2T4BpoDQx5 z`gQpXR9JqmAYnZO@s}WRhz3UOuws>;?w7!q4?jcTB!w?=fkWOm*`PpiD}cn>o2n}2 z?yMMx10;lztLpagkmq@LDEcA;rzD&K0xF$z^eme)1-7W&Ar?S^eY#M>h7XD{+~7>& zsHxH#g3(DOYo}Ag<4uXFAi*cA*t22A(;+T2Bm_@!|G|TM;56{m=p{ALBF;_iK=D~d z7O86i6l7tIxCYi2eh5K#AslVe?=<)&5HhJeyC4vM^zqmHJ1`?q_N8ICm};S^$qJLx zb3<)PxP5V(@J+@TX7se=?L1AD^b#lvvW?iixwV zQ9fA-wzh&SlWuLUa(e^f?!|2Q*vxgXVPacl-jC>3!PDN`59pXbZWSIFxx!m{Gu24% zz)4M=hV0CA@d|B&Vz&vGstDCZ>;0SNjx8N)&KOG<{QNb4UDtq^t$)(!z`5u?-A^wJ zUKXB;GL~FkXGXP}e(|*pO4RGMK7Vy8$XI@CbLzbl-yA<|P-2VYh>Un(*zL%8HDl?W zdp{_Xr2Z#s8rss!rJaGGm=X(26s<>J2!C{)_37Rf!$a$}l1ej)1%Xn#0!%w z!?Rv>wY|N)7<_?9ZyhQ-vW(lkUwj5)E~_0@SHs?$obM zD(U!7=of~nBx;TDPusWcmh&ci7dpp#svbNZ3Ud^&k%Sq7$Jl2J63vL^AAD0`jH1{u z8c$JUQSoX0Q4Z^dAyn&}PI>y5`VgIm;3Z@VJ4>bR1e-4}nC|Vpa=EIS0ba{-kojRdbMbFz!uJvEO+HlaKnX&_*TAv zsC)2$srknNAQa5QyYw5r4ZDb)`N%&rH(tc{^7(se>#n(Wl!0(gkfl^f^uUe`64y^% zDdw5bpC;~0$X=&(UZbu?no@uV4=w3R$bG>eF`zEa^~-)zd|_U=h@KOYESyK#FCyVb z$+=5nztY5|J(WvH+=}6VKNNE`N|~!YU18JU^4o(*<&QNplK^T=@k3EPuj=R@b%Vj| zCSGfwba){?J@;*QK19Gxym$Ee5d$`qKfdNbn!~*^y8&?QlX)Kh*kU zm}g?*_=lju+SMYo+V`z83%7~vqfa#Q^xW!9$>671-^bD@?YQwhU6uO}uF&pF}+j{4qX2`2dP0pU6R@Q_cLiBD?ZQ4JQD zYd{*?l;BS_Ii#W?paEQil&~l~siV`vmfmR=sN9x?75c03P+anYda*V3;NABdx<+>E zYpP^h!$uf(O7Ec3zKiQ>e4qA>#KgwT(`%4ls3R*kXQ{$%gGB$*Qe|j9?EbJFNEHlJ zvEb-|oUj-J0)s{95C)}+;rHV!DU%)~OF}4~jk%gg#1p$o%trJ>9whJ+Gi&+TpU2Y` zsEf;j*~E=sEs>r5`JwFfo0$UGMVX?$FyTQNtD~bsJd@Bte~(WW5vVhN{rPvu<1Wdz zVLK=zKupm_PR|nEb^tWKug>0mlOc3500xQA8(Zm1E;J8_u!bMkV1WT``3-^N>npdN z(qZkJf&=Dy5fPD|*rh<2b{o9Spof7*j@Ckp z(SYrAq8ZtVe5OSi{&cf&gA^62YFgN~wo^p(bK?P_akZVf;FD#Q_FYj|H+j}%2W`OP zlaCL@^DW`o^U&e`u8F2xT%sCT*070c+in_V~e z8O0wi+J0t=Akl@cr&zVgy4fQ9J&}N9apfj30Z?i_s?H36&j=nHkeNAJ zCm(^o1oQ<*!aYI?8#gXS7I=lITQ&xq0xhizw0+(^x6)z~6U?n4E@tSIi41;v3;KX} z4-T?b-I3!&t+l56a|E-cL|QovrOrY7@J3GS!SGG5A0*F0BOl-leuR*IE;CY3KP{FU zyx!R7Cdw6PQd+UGL$M)(8{-@LRFG-X;VWrU9wbzGF0X|hT8Kb4Xp-u;j?KbHK%2|C zYxD&3Qbd$JVB(c^D;l3lfvmoEp@$UL%6)Id5g1Tzu0svGAr&dX*S+`2BQd1V3Do_e zhmIU($czrlDkdhHET*=D!CmEKbpl6w-p0g%K+X9-BWl!q%iUzTT?)Rg=3Bmvtic`Y zV1h$FGz_t>t(_Be)GvvOPp*{ z{Zh#Zn4b`)&*XT)WtnFe`rF8oCQ=U~QR_D->hh~}b41k&AWXs1j-ZkzS9h!WNJ?-^ zTGp-SlCocdt84#qsHl}uHJsQAeF2@BxPMO+gzwht8rchN6;k4Ls)lch7>BpzH#mYR zp=PPjGq^eUPNn^@PlscB>2kOzwIO6b{Y>{`g&$q!qRYmq@Fg|^_*UnrFLeCFcD!)B zmAl9XN(%F&rZ9&&#^U>KiR%XjIgPuu}-6Xp^mbwgad(nZ;{AHClug z^gxJLXIGaARw}{9cX@w;3=T|`NQwvj#hl4#1&gJ`p3`XsV{4I5oK>dtIb>FF*-|<- zAB-@PLmghk#zcuoVkMeL}C#FL<|a<4|>)6>m|i zcbVZk9Y=rytz0O{~u8H`6^d^oqI6mWwyN@jJ01)Z)pT zq61;W*AJ{~ex-PerufCTeZpdOS?=RDz}{$=mI3-E&c0|GT37i>MhTF@?_C71Ad$etTgX4=98-)INII-Y3 zv-|L^))^W=4(-mtaH(E8wjgxK+(Qy6d%}W6vndAfEPsdfmqB_v}*s=J->ddh)C0xFI`7XDg`~Z=c6_}Zu zn?Nreg6ebYv+gD)65xaQ)24f4fqndVf`0Ax{Ywg~(!4QD0cx`Zph#)s=@>uQi(vSc zT-se)^|%d2iEZ{drB3Kw0R_KA`XZJyCEb*p?3R@2S=fAPXPjDoGTVkBu2$=Ax@07( z=WCdH9e;FWgP`CF3;^pKffk_DA$^EHBM&Q6b~rVuZHSF$ypnHechF%& zGxSQMw}gzI0*Sl%2DWv>qme~3OEJn`)H3^T`G1~G^ohT6I4JYEOV~wmA?7T`(9S09) zi>+v-QBTb6 zXVkSyQ)n=eA+ZKZ50-*`l^Y(5(KPj(3@`KI(?{&PkSuuZ!mG6UiVkhMiR0-V$NU$q zlTJJsUk$x-NOy8do^8DF=FNV)!h}t#WGYGEmwAxX@=|>y9p;Fu3>j^al77FM8k^zH z*4nQ#vL9o8@jg*^U|}MX6Mi{?8E3pRE_9zl$v2EfFdjaD7*U8g>9eRP0d6CB44FTN zl+pSn0nQ30p0lKrLMTl<6e&9}6X5G`bf_#v)Zc)FUjx4PAlGFHLa>9Jd!4C`V63+FuNHiDl`o+coj&lHQ;44OAkT zw$^Q_+(wK8>Dk4o5DXH^+s3D{jm1q$mz^K{!U1b|Oh?MEt}7t}8PvgnjxYo#h%aPS z>u~Y$j$7g41z&71WAaQ={6|XbgZ93pS`TX{w9>@-8nPn6J?lhI z{Mpj+HiSI@%lCTQ4lK4dH@@|2=K3FNGod#vlhh5DQ94|oUnoywLVU97eut!a6S;r= zU#{egSCPxJvy^J5;6f*Z<5=~=FwTWWaf-|09)tnRJoB0gZFau|y6ibV3d_U;=|6zg z6}`qti)&<@-BJ)`h_Z4gpMckX`b>>gt-J-)?(F^-QpG3Vt8ZQ8NB`UVZ(Dy`eTx72 z%+O6iyR&QSi~_bdUy=975ZVLW5eAq9lfuxuwBxjD_%+mb0>>Y=VM-yYm7FMab9p8z z>dm4D59>z5xVB*3{P()G^ z{|2oc5CLieUcPzrW?N(fTBt*@yO@X;Gs~6dLX~Jwh*fbqOhEx?zxsCWM9+?b46>#P zuOe!f9WUmzCp1_>KVvjVNdgdIHDMD+NxvcY=Lc>YmQ_wxL{ z0_H1lqh%s!AXdWjipAEr7<>^a86<7L3Qa9%`K)k|E)(M(wDKO4_V6l_QL43$rq~hl zd8|EN1W+o` z7Ip`J9qUB-j2sz@Jl1S{y@Yka~B^GBc>c11(+ z?y2#f!Tmc>O==;^VzFo;b2zN8aJH2!E%(U#$?JY1Ae7_uJu5rC17-6&Hc_qKbWf~q zOZ}AMEh+h9m-lM1*-73zNgr2c@-lq$K{5BSvtQ1CIIQH8MTiBkqb3Lzvr0~T<1v-R zcxT`Pn4rNYv2hg#$8rq~-ucYpu(+HKZcrPjTnLFY#?BF%W_2lY%jj z9i?g1Y!fKv#L>51^U11^-3g6Zf4(@6)kx+brU_PdXITfGX*RKot>;+1Y0uUfk;T@Fs6!9m`xqx-q*(OR!EJ|*3^+>gJzI@& zxCray@UIChiZ8nlhj(gB4ZF3OX>6|>gQeJFglhy%hFlx@I7Uz^(B3UYX>%niiv1VU ziBNVh8DbJoMKg2Z)#I?#zWu7IFG-#-t7MIpb7w{70BcCefeqP-482^tIM9MH+l=yd z%fgjbEEQ+=r=H^29R+>-N-vPLjZc64G7?SwbY#5#N zARdv>k!Q_3`*}46LjI|J04&H4M-5~*+^)jpu~oPZvqIDvUp**?v6i>+Ka9XQ7QHAt zL8B@=UjZKk2C|aL?t|kxOssLYWPEcm!5HOOoX5y=0LW`ItKfx4#)EtO=;7k0oKs%* zWezTT7fQaZD$-&hHStjd9(3$yn=)0C<8rS083U?WiBYvOm?7A60-x-NYdjp*5i}bl zP$J24Hze!$E?vQj=^o-fx+yGE4UOOeO)GX9TrmD4z!BDeJbbt}lvj1yZvd%9H|y;3 z1GYbeoVQJai>x>lBTva{V6zyB$$!-Y0I9cf16Q#*o&qB7TS=4J@da z@jKr<><#tFO7cg#P8hjv#*p!f!f}9Y>#0*zZIqtPp<3^D-C7cn-qW-$Dbi_Y$NR}9 zza{J=5A?6SD>gCJc;BHzMH6zy+3Hc^)+4dId@fyD5-abycBTKG*k_LyniDcXE9Z7k zJ{H=rSYuP&Lw-8KlDl^80^znPHB^FNk5Xd++fUY!81|q(x~mA|p2cJYT_$z2lOZ!O zMHqRD1&ba7lh-?2o5NTre{caje9;F7w?)2%^Di(ZjL`;nSk@|;Zvnw~f2 zIPihQR%XJ~p#Nbz@FU~;L=D(QC)M@Uc1e?yF_^#jmV8_0cIXT8FQE{SkhDovsl$<2 zd*gG!lq%ZV>{JA49lu2?Ka92+V&=cu=d1!H5U31r+Mj(5jHsm&Hn&kGL6q}_n(euCVY&rp z($|JB!FnO}9cIP*P{I4w7@tSc0(Vext4~50X+G6U3yfJLhWh}BW}pVDjWv)cc6pB% zE{1Lt3o^`;a_A!c^w6Y-k^>#yq}R;wKJsF6Q?<6%IZe)c=*X%K1MW1cxFK-OOsc03 zkWup~TXs!u`0JW|bf50PfcQ9^(6L$v; z;hB_VO2pcRT}XMBY1_&j^KhxPAy9j`cZT4Q0D#=im8ele5J`;*OzA$B91zRl=Yvv> zm<6M)bO z=mb{k1R$dT+yn1ttTzB@-ff7O^!UvFVm*nhoQS6SZjleYdUY?BMDT4>#d<>!NU7rc%6PI5hF8sg$NV@Tph7K-{>`@5kvtRX>nhA^ zH(H<9=LuvPbnkMt@;fm>d%;JLAyZXluHb9m=@Ts*I46c5l=Vi+r`nh;LkW%y4iMsi z@_lNl+ea2CtDwImBqRU=+TAHy)o=wsP~q&DEYwfDbI{jgbUG%~% z2@p+NdO3Fq2ADzmYVl&R&%NipaMVh$6Sa}?#uBjuAz1=J)R+<>G#P_~z?e<%9b%bt}++7vzYf#{(!Ecm?RB&7RGRB33tqMe8 z&2Rx`pr$|)O`2I|3lKPsfs$i6p1n+MO?3@49FSWB*T)J~qH{05uxRnQt||`X@8tlw zLmXivOUhr660cRxbVeFpL+(JW^ypn*Hl(Sd;PJ79jZs=GGAqG;vwb%|T+Br(ND zi9z%2+c%Sz+S@Yz82PpXffX2=?n-|S`mB&a{x1Fmwykv$*RT5md4x1?$J5Veu`&sT zW@eH?;IO^Pw{i|wd!}W2=JZTNiI)@)#kO%EO6!zfRbMg{CY|;?ar=p^Z06y_4g9DA~t}_AXM4DC}(oESk>>J z1LygH=ryy{^HJ9yJLsi=eVsT`kT87n;0T3jjiXZ31k+6LN6K!DA8(onU| zbNu2JCO+(QyUc9}*bL19=@AsaajqKgtzUtx#8tJn=K!_!3F+ULCRH>;O3>HJlFk_Q zwsIQwO^a=kFR;{~^qUZTZ2XY6KXUKoajW0<>Z$6f-%q(wzm2-%Y<<7=yK19GIM$>) z|M(hj6ooAO4e6;AmIiDDZGg*}1823v)CxK}Lbvl6dCNC}#B=xbS_8M=Hs|BuH}BRH zVT#S*N0E8(#}r+yOSu^t8DvOf1X>hwoRT;{#W9Jr*astoKyGDmSiO5`(>4x7f|prMddQPp4+6mpoGStVLuDok=|q)2^u zdP6H;Yu~5|`HFm33E)9x4LD)NDryjd@0+xHkvnR0OqJT6HyEq|z9T0633GNK!$L01 zAsA2YlwcnN8qfj$nqTt(YxDhN^l**K5o#9$;9dj@HuFRx`0!tBc48*4ysHYhJ8-fn zN$a&>&ogg}rJ({_>=jDnvRz<6f??w}+G{-W{cX>u6wVnh@4(qb4(o8ufN;>Jmb^0k z`My?5Bi{PerR9VUi+H3QFAQMIHh-AL3#XmfRsi-5ijCz0wnRgC*2$4axH0)8lPMhi zC0^ppVKNdg8j8HV&-c_R$wtDaonxCe`x)<*Tt6t?wWcIXICOY@5~ z!OmvWPTmy}sU3ErhPhvgZ*Je}-AMD3`N}G*Ez-_zqs{A(t_Z#P+O_rVW-8E2SKhmq zoF}nt$=yLX|Ckq#y4g((8FNXWUk3R3O=YDoP7(kqTp%E_i^U)F$-){jE)8HJoQkx{ zDGzxZ=-9MnOFPj7=&W`S_?m@W>VflHCSNa37NEWXb@sDG99cLZ*D-Os^=$Zwvz&;j z40LLMq1VYc8DYtwDrwIJ=#RrNMw26*c$15$NRUKZuY}5P2yjCCZ;#^kofm% zkAjkTtCN!r=$^GXU3yKrbX-@PuX#<}!nS z$%fa@5~;0Gdx!uG+magRy3RIlK(Z=UY7O{zO5M}ozcD*>RlUTIR939bAG}L#4gMFI zGN9<8y;Z$Mq`YHzJ;=YXV80+#i5UTKQ_Um|t~`9bB@h6d8?^c2L8&e?@$1R}Qy&cI zr}mu(8VAPWrIbV>R{*_}G4P&s#DH##rF+b94lo-GI~Eg~7h&Q6Zpoi$4?fD==@*!Z z#pkN?aQy3sbfZPJws)JrjXXKTf6FH;<_aj{D=RoHSIp#2{y);*0xHX`>jFguEDTh{ z0xXnJ5EK-oYylCGmQq5I?oJB@5tWigrKDbwZVOTAZjhFam(DvMJf8T!bN~Mv_c9!u z!x+T-K6~%A*P3h2xtu;^z1IIyT{z`$onJqf5#L9&mD82+nfPZVaO&U@`k;QMUjB=A zcLM%rcC+*~OIUgF2M(JYUJBZWTn88ZJcYCrx0dnlKGA`q3~Qut`N#g^E8VtB2+IF< zjKYXZMX9r+gFqnL?0XP5%fKSpF|uRz{VyU7Ri6N!NKLaor`c|&+W&p{a0O?(?VbvE zi;KOh3f;Hoo|s(^WfgMJk&wl?mDu?% z7?rW+0otZ*&MO(;1EtN|^-xl1niAm(UD_dTcub zGANRYm5f#t_+BIxbZeCTPQ`&bLx3tE0-S32qLbW)dxL0XgJKG8ms3@YJV71JYrBkk z*RQ0L-~s^hc=Yh&{kF;3mn>^Q;K8ID8?Q8hqaqWjx%2Bp%<`PO3K8p!+fw$0IDM3ZT1s@;PN*&0_%#82aGQ`V(LRpISuPGfgdqwG43 z-}v(OwbBw`lZ14H$nAg~#mecHPVz{gowRKU88T?v!5bj)nL-luM>U6Os*HGWqB}s# zM*D?O7{to;tutOY+gjvgCaYS(JDI1xD65>YE;hPB3mHoEdZGtb#`9+nY=7xit9&7d zFoe>ok4ZGHt~|C5={s_FuQ#~DkqqNsqk(1ViWgTlFIaCD{nz_NhVNx@(fY@4kn;u< zQ3n(~fLsWj)=xUgr=Ra9cqR(KHcxr3SkY2hgSxex@*I&YMe#4SvXnOhA}n)<5-56L zR+uPg0mOLY-cE1XS$u?skWztz)TRp%f{@nnJ>}W0vo)BRu*!-+$nGL zzR+pUHH}X3bAEJ3-+Xm2Q0{Io6d5@YAeE4}MTMF5bE)47S&0p|aetVk4}<%{05t0k zYM?RQQ^1cpO>ThfYSra;EA;j?B-J7}DEqLH4}#G^6;LFnw{R!F-MK`*_V$r(4k(=W z%0x$hJo5PJ3jM{In%pC|ig!gtvsG8o*!ktgL`OfgT6W(Q%}q{pn+fhBlKDpzb?B+w z1FTjVBQGhCk4g>y&J}(OJV~1-0Jwfch}hM>CC!0QeBhRBc9_+NW+$|A%I_7+3F9_Of<}${ zA64bklC^a9jG|Irq2?3Qb~sA%%%wLUbPxy=)G}0gJ^MxPMBE13MO_W$n>vSk#O+h3 z;>wrnqo^aW@LUH$J0Z3EpVYc?!f~V|0v@2p1^etm0ggzC078$KWJoQh?%{X|(`*at`$YmDAyavLr0?`?Pwb(1Bdxb5&RtCdHGJ@{^vK2C%RY-AiT zLqhX$ zgJ_)o>u!@hCb4!p;tMmz7oI>1iSti*+BueL7V0+nmBh9rdK%IvHlCGPLAT*W&(qH} z-yN7Qt(h|2m*cSUg}>*O)+7d{%m|+pF;&+FMFI{HB=^s_6bL_&r(8S~NUlC% z3fMs!2L2@FK42#>HhPFX3{v{}LY_B2g^18c)XNr`*$SZp(3{_>=!um9TOyE?3>au1 z=rrh|c4j=m-kbtl38p(ue`C6IzZ)`!E-gE74TxkO$^D&I23-P-WHoa8d;1S_X`!JM zNFBg8A-lx|@ZIXhRLS>fvr+jL$iDfi0Fvhn?3KWDJLS_UHk2=mdwxs9K|)sOid!FO z><%KRtjFV{%igCrW=i(he)A~J3J8vD(!fZ2#;a137j%}~Cltb|`A3)jKW_Z^C+|gV z-yL!jb;Q8~>Y_dxJ&g&O>L#IltZ!pQltex0h$8V-?*m9NxQqxe{p@knf>9|$e*kb& zvPaa&ESvxXP&~S}BwULF2jB9M;quEoD4jsum_Z9LrgjoNh`aahJzFJv`pOnUwifs9 z_}BPHzd9qGS6{h5jCvq+dhJY&lX1_!?0e|e47`;2n0tKFe0he-`VuOVC2N?IEcbGu zyW4J?Xs923A_W*nL2ptL><~{k@=Fv^@Zv6 z9G7f}(yDaMA*dcfr(E;q&81Y-!x(##*oPXZAwectB8z-L!HE1>A=Bb8O4YL$i|y83 zdcHrw0U0xIz&g~TAJFnLf{!Fs&=7dDxPl3R70wR9&%rlEM^k6V>*dtsY`;KsV5v7S zK86v`g)DkUE%cK?1Vy>f3TXE1<;#~#cda9jf;)p=JglwdwjD&<-`Gn-Vmj zoW%uOyiZrM=9z)JHzVKcB=1GSOGx^bs`s99W^H9H#V;T)j1cfMH0uH(9pg5wMkk0& zx6!6APD@ChS#%S!U!>8)5Ze%XEp?Tmi}Kgy_uyCIH5?}-V*o{efSdLJ9UA8p!rzao z9z_x;Oay$Crp%GB4n0UHI3FYPaP5PB-W5x;}X1?xQC5x4ZxXC?4+za@ITqv+qjy#{*GbIvg^O7 z3UgbRs0!f3{&F}7<#y&JuebQYpieH2z`@#(QglV>$KC5>+pZxmi|xdb_|Fd+^W_Hz z{5+2pt@cAnaA{OVR`!xI?>_ymFcGpx`r}sxhY)y?2{ZvK=cVQ#4(8AEAT(A@%!mA< zL`1KlTbG0e!@8cHo;EV12P@!kzINritpl7d^_pfFX2xw*D+|YI`W%?Do|ks<>G{Pa0N^)6CU~q`T={4R?8Wjk{!A7(^>V zbwE&^`1rOX6G0EYZEleuB>`O>85tq4ZDK?yfX!D555*x$j*Qg6;enIEi&c7cdb~*F zRuHSWVD_Y{@dERe6T)CxfoI!}ZUbRHG7M3}ZqNu&F;Rdb@dRor!dQXGWsw_$wjyrF z@ku>_*s`_2+>img0?Xb5axEH}zxo{RJ9th*R9f~%`e38&5P?#YN=^5L4@UTQ8PAPX zNFv0qCHf#qNyi{1rVznPEQPMh44M@}c0$m5(5bfrQG9B;I|S)C@@1Q`pU!xNYLo+F z4U!-jC*1f%9VlSE3CU&QZ0WIeNc)IPgRQ(mZy%oD!w@S=4}e<}Ca|cnjc}^AKixW()dY+z~udRFEbrlAn$M=6i~> z4Vs8LP*@_JM!^j>H_p6Nu7f?1d4m_nlwmQjM)dhx90@(>PVg9i>7lFuv;l2hyF?5% zf&~OYUxV}lsuVP}2t~GsNB&O3tUcAFs1S#l)d(M38n}&u8j^Kg(oMUm?{8jFb52$k z$}@0&)KQq6fLe;EQy@eeA>%#)Px%b^No{RyrRc~IcpBn9U0KRbY<*u}Et?@hhP7LV z|K+%)yk8mB6;$|M^ln#>-qFw0${aE)7xY96FcS4&K3+x3o9(^vLsQuF)ywI05LEgA zpw0zP8%K3|-y_aaw80X|hn_g4X0Op!)tOx=`PI6Yz3)m{e>p_R9ja<6J4STla1R)5 zT#d*`1s{U$r!Bg*Z)xGX@C_c>zb-2rGF(;M?5#1>V~}c)TYl^gpnTYHmi4nq*iI`! z_U*UXZ_DbAF53I5Zmu$CpyyP*SJAVDmP7P8v3WrecyEyEmOssW&cASad6(_C_QgcY zmJx}XM@;!Gq7@MV%jGnqodTU6u3>rj&gFH#%t5&%|RoanN5Q<^ontE-L~w^C5sU|w{Gpq zYNpCp*!bdTK#{A5hdd6En1GPwthj`P?9H1I=q!VxS$H!M%#bZiOhW=B?~&~@RJp#- zf`j96kQ5JX745!b3Z8)6*|YZw5>P08yP5c{)rjTLp-a?vKXmuWO|{VI^9GPp-Zc!Y z*|33g(s*m(seqyg@H&0@ej1(FvU6t)XbX9Hd3>oO7S>ecQrs)uXK#DdHI2|K=OWF* z%Z2Qe<-mdSsG^Ha^-~*yd}W7i6v~F2LHz;>e*wa5qhc*lyx&roQih>HM!$CVRs?_= zsP@NDBB^Y3%d=KQKUSyq?Mo1yVgSI|%&D@>WeT7WLF~nk8s!+)X>zmj^Vd%csu{)4 zjn8kQtS=sld4Gq>qR2mQR%xTnsw67m<@%?di0oW`N^!Y9Rl%A?R;#O5H{N95q0OFk zxphELMfIGZ2w{)<_YbElGQ$q~l0!utbK<2`ds6Ono_}37-I`66kn+lzS8{g3%$gEj zP0kNQl)kMZOo!jM&}yHFDsei#xs~V7#>Mm%Q=&X~JEj%TeDsD{*$s{ZIo2m>Ckq{ss z0%Px@Ve0DWhywOzgPwd9qGzfzugj;GsQKa)6VI0jFJ|GD208P(<-LMN`X}5UfkGO0vauiV|RlBssQ%`GdJ>ZOZ_(kcNt=F+W=tCIF?^x`R%n_6bkdQquN z_&(F;%(Y2$TVnraX87xw%Dx`v^x66(iS7{lszkc=$#k(wQy!`I^g^O(jK8@6JdQak zq^yseFv?uM(mCZhZ5n>oDR*D#gDWA6#IvS|_AR<8jkGEu^lB*UjI~KHFu5~8FH9Yf zHR$qyY59mkl(PQ2o5)UzDJ;0t^$w%eo_q)-Ys&Qoh1wffYOV+LITT-Ll+h0A6}&nm z#VeG*ON2+bnr5vuk`aQkWRDgqcR-QJiCypN^tgApFFiA`{uJY?)rXFA)LNkTTaWex z*?i;O51}|s>vo;E0>k6QgNb#!xQ7g(26IrO!jqAq)n4m7YqwnggFCVHtg-bp22bnX zUu)HJE`F-}CNhA98Npvi8i}&y9QN84~lsaxH;C@(HyQYAXEPjW= z={+`&CM71DQvAU7*;Cmq>7WuLci6nA{C?rk*h6b?lzrN#pRjzG4@#>Up$m|e5jEFI|O6$U~?4;swI z2GU1@gM#9ac*Y=ifz8bxQ=!#KK`rvjmg}zqL*n!gp%4)zBP^@P5Ao2rA0NU}6Cg%@ zRUlqZ`fz=t<)goz$FKjp!ndY5aX?%-?uRdh+XDA>#df_-c+(<3_LRzTFDC}63|msx zZ|o(9VA&}s*iJj-OqR$bU5mSxX%UCIb$`(8(^gnDi6UnT6gWYv&F=T9wG?V^&E&0) z>-O8#Ip%iE;iy_l={V3QC1lQh{D+TaaI ze6DlrC>B8JQ0B}UzT|ETRTs@%lQjEwQnezGF)0WHg2n27O9eF%ibApWM%7RSZx+FDt8mADN;3d;ST^4RiXZ! zZo5hTA{|(CMgM}8Q2F_cWll`O%`|H(@Jz=6Zb~50l)~-RFpg`8Echk(<8?&qjG5jT z9MNMudbL;NVtB%ewPaV;v$dsg+BL0CT1H1imB#MP+G`E4maD`zYqMKj>CsP*%oR`M z{GU5Qq?3)cRBp^rt$OkS)_iyAMs4=(&KT1|F?AA~Y<#-JWekp`p;@>IYf9Y2#l#T9$!9TG?L{@M@vp#$*jEPKve@ZuuHj}@;UuaVw%aJfh+%Pw`( zEz_hqyyeH|d``N?N{?LV$}r4)n7C}!7OH1x%SYTsZpA^mZ8baZ|8a6yu#CT&M6zyN)G-GnY={E%;GGtPY-C1-}pb@UGxJ^uH;vJUdM|M z;E_{MGA`F=-e*K?0LKfV>s|^iK2pd3hYIvt*gh%=7h0S%4dOHXGHs3o(d)&Fuiwsa zQPzu{hyNqngAvEYWg>4`c4(VUT25~ZoD7Xulb?SUJgd=te&xn(9w*(;Yu&n~3tanJ zx=A=1O%X6>z;(rX@}v@a_tbY!fd~fd!PV9Es-9jf5cVphi!dCxgfdx5K|$fG#g0|~ zezdRnh$wxyTTmYRsR_ol|NNLr{g_)R@AEX^_@6f@Tl=TAPTxNd@hztyZtUN2jl#>N zN@si~qZd01=?X`84N{$}nHB>ljE&rgi#KVRNZygTAz_MD=LgmG>CA_$7l!T#%Z@Z3 zd0l*=j)tG<_6n!>QXAX&Q4@hO>+Rzc0qy~tuyD(EZ8ulfaw>Y|P*hYg;A^?Mxp@}d zTsuA4x=H(FE@?ToVKnGb@9l-0Q-0uaI)}y*hw_DY0ug=x@e$hVeIQNF-<+8^d+*PL zu7k0~xHE#$``o|f1T5@GySU&T%59WQwAx-nAFYFfCA@_lyW%vlP)JFq;(!zZ~S2WKE{Wd$3eg9o|#@^3GEHrJz{Fyp)4cIP>0PTdu#yC$S9 zZo`OT2=Ql~u3J4355UA{N-hB>x z_^?fbvVN*c0e_N`dMVmVF8%#*;0@VAmPl0U-`={ev2PdEOR_z!!3YJG~Qm2ug`81>aGDvF8x}H-nVaO(rL9%y8LlS zoEEV&Wf0pxc!(%HMOv1dyP5l99|tAIje_ntqpVW;3bKntcuL zu^PNKz|n#Dz#y1gNf_Z`r>64G3f3HMxyPuk7(~T$Qx+0`Mq?Zy{=Y#}=Hz z5irpy0%*=OsKXM){HqmI*;CJI|R-gXvjGk5;T+4JV@ z4qp?KH2~0e2s>l}l+7Cao$~Q5scBd)Uj58~>MG@Gq~PNOZdxi8P;ra?>9hK2A?Ba*}<>x5R6) z!S`Ko{XW|+!+7>>AGd6EOt?g!Ed4n=mF?AS$L*J-!tL(p%g#hvew%6Vr8BjyNk7kH zpr#V7AA2yzr_+V%yJXz~+b>+-Zg|q1->%X3O(xR4&@n@))%`oYYQp@;>vEsQ{kFxd zzMZY^8QwE9)R~}0pc69gQ_`1@Yzp>{?VqVO;@+DJN+k?@8k7e=!J8)*Q=yzZAFMeO zI0y=gK+ z@78)R9VLxQDp#H3Qd08s=eYgt>JKcY9u`wFF}=@tCQiyl^KoukhemQ3o9X=Bcl+%X z+A><#WwOQBoaFved3c^Lxr=RJzE4XqvBmuTbs6^tdDg5O@&}q10jTT1t>F8&ZzI-7 zr15HYQaEZ>>0Kp!&5)^ly05Fn)ChM1xw%b=cixE?b46_PHt|91X0V%dh|5Ng&zpJ^dd$Ye#n*y32cdVz#_ z1AA-nIvnT@c1<|tfUfV|kPsEcg5*G4rzs=Zv<{xHns^ilG`T|YkizRgDJ3Q@&dyt% zW~@;ZA}kzcaBI1KA=CSo^tDOM%*;fhUrYi=JRbaIqjy(Y(cyYE*ks7YyV7Mtt~_`& z8~n)E6YDBpelj;e-&Vyu+2`==({I20&#y?}qVPtAGrX^KYsb>1@#hox{XZM6P=Y~3 zhOg%skU7oF9Yl#T)|txAX{~jC@aRm&!7WX#+ev*g=R@PV1Y1~RElfSyQ;yD>Tb$bY z=Buf7#kqkkmgHQm$GW@w9;tj+unp<=V~yXrlP21F$l*ToG1lqvJC9%UXAWQEGbza! z{1_POf5!6rHb<__BtqEG3mT|FK2h1jUH8atk3RJ7%0blbGqwXeW{>&F%}bjgUOV(K zE_NumrBqd$)ALW1l_5EIDIgyT{mAGW8L8V-9&U1?pQ8X`Nw1)weVOx(Ccv8TynCW! z;@3=REPy!!3a_Kqk!@>*`{k6Cv-UR5tc&X|m!r~uQpCpRjH$!TieUA*;%t9UvZ>!qjdFU?RhjxBC2JNHw@}nn0 zq{EJskdABW`-KG>-lVHLaw+-z!fuT@=HhccVH>;?OpFo+Gz?z6j7stF9aeXiy)B-} zF07@L@N%lzZHsZ8$bq1pa6*#P(TQ$IfOb6^66$5v%9JU}zfK4qjy^UDgsdhG_J|U1 zfVl;-$h?6C1nf5=PUKpg*yYbh)*?Fc%N+GUTp}6^D#5AuU0ier>c?>yX^#sny*;Op zH?ATLS=JUsexLq{V*c|f{Q3%kYN;6dI||7xu2Olb+B4Jb@bP>3-@R(DeR<)wU*m<| zn{VCKrnUC$l?(UBWxehTQoEpRm$+9+IO?IB?Zq4MoNH>YdU~Z#2z5s4aT@17 zJ3J_*=W$%{iS3%C?M17j$A3H$v)W`>ZfOkh4Lr)9`8Ey_gQH+w#6@PB=7_iThwrNAz%!dq zZS5m>_qez7GaAGNzz%SLNDo;(zsdC4-@AIfKqr|ES>+N=V8XO7wqHc4wc!vd7}`PA z+SujLilB=C2*JeqP*(~0AifoS*YmHXAc1r^N?KDKzW>~X3-Z$?<6u7X?Rv6??;uro z+N&X9sRTXV03b-{(kFq@);$Mr@|^lq!;;mfld(;HZ4Jj$q3fcMZT`;S|7F7v6*(|d z0zm$&s$mLlh+vX(_-^4Bu+HmotB}5DX7@TRgB{)G4ASbl%rs3s##s|wCz^{PRVHAO%pFX-J|R%3o&*Oi%rE4(eOv=W}x8klae?p(2q?>Mw^3R?bb^vddq?2$VxoLZi2;JPDf#9uG}~W+-r}nT zjbAoQ*sr|I4*-&ibY2IgIKR;kCs4UMX~^4XsEJ<(%%WHWp7J>j^WduGZQpYe&hxmQ zI!3tj-PsrHHM#x3_To%E6$R%69W*w@BqYo^+}zxx0ic-W(aBGl1rh)y+|gelIXLMH zGbbWcsh+VOBv>*CPgN)Z%%Gs_?$abHZk`(D*I>Q$z**KjUaibIrN3VfwlJdbSoa2h zGZa+&6NX1c(UPhG87Df1lyi-6haqOiTpbVw)mY7Lm(>7 z!RO9?rYDl$xb2=P2l1hxXam`|5PYmG6kemdY*s~TH2EdibXvRju> znMQWI{`($8E--xIzVNOXqqmf+s3_~%JO&Ck@Skk4y-4Kgo2U)RCkBO`q4+Ualu799 z32BVT`V^x~Qqq*DnjsJ6RToVU@@UyFSS56JMXcCT(|y+|(_S+0#7l?^#j(2PtKWHl zzJ4SMeDxhCEn>mp=r_(rFIgKYaOX^VWs1HMNh-A*Bmr0kJcIe!k4;zDdO(~Rh=!%c zN9KD#PZQQW3KxLhV+V9}1>EQ$p^uljE`A3M^?ujT{UchT2&B}1B6`a#WEy3n1th3Z$9u7q1qrdgx@^cW}?4moY2rk z61IuhOyubkXr~^7bz>9ebcWCDR+jmwu`56V$TrbuASW*Z_J0GTr@&n@1O~tK5p{`* zHo2T=oYd)|cY=S#j`GL+E)j@GpAZ3w%q6Il2okXF|CJqHOXd9;mwJh9#`^7Gn;w-T z{k%r2V>X1&m6kWE8*g_kGiq9shx$?~S0??2x-j?V|b0uAV@4ex8}o!5%58^u^~D$f&tZ5k9HOm*k^&Z z;t#`2(66K;1_-ih#%C#5uSA1R?K5jL4zD$MQ6&|;1MW<^5e3Rv59Y{Y%XGSj={IG_ z0!ouLFo-Y7-^|2Bf_pT97C;j@4*?}Cc%L_X_2Gns?ih?rfl$U3cJ~7Iz(J2gp3muR z!w8|pX=11Byd6_Gy-yV1QUPg=m#?pUul<)VUv!H6dFX5$$zV6>psOb)D#}{p@c8^| z5K^O%u=@1z648~>>c=t^OXcko;Hgx=Q%K+mBx&-H+i;pXy~Be03)yEtv~2ZON&**F z&P*?RxBcS}*RMeQjy`$8w^PZ#Ya;}LV8S|ucu&xUY9?Pp7Q6)=BeY_%fVUpU4fhET zF09Kn3e~ST;PS;I)#TIezhPy+Hq}2rFF_k?m>d;_wTV_3#g*w*NwSQ6-WwE3&55QYsVUcFhefun4D{gQ z8%^}eh|1QxwISU=ZfITwJD!ex480gfI#0)m>mI&yr9sp6w zG8j5s%4shrC`DOyMkqIjk$Ve?#r(}`>-z7p%PbnUroFVo~s@o zeYHupZ(-l_*15hd6S3_x?M33@dr8h`Enh_c>IJ2{9t%sH2Nyv`jhlgK%S@vrua)jFpbJMs6 z4c?SgLAM!&@a@w#x=0RLj6(9jQNX6V0I3mX7^F3(29Zn)=^-u7z&IXuv-R^ml8)t& z_^3oow_pekTt6k5RUbr(G=TXP>3BLXcF%7v0Mu}F7KhHYdqnZ0m0g4SG*FFLZ+KV# ze_93t#K*@RJ!t!$2__E@i53Wut{;i6{u!eAIBv+84mHpjg?oE+EX^{n+$<>{#d%sO?eYFk=8^HkRmff_)Q4QRZi&jwpc76(O(+t2IS zvzJ4;i>jdisHQ%0bE|-WhK|W`A%!2$9#mts_!?Oxz9e5&n>Wh&_Tc=n@bT5PFMvZC z4~YOP8=Dw@RP6HQYFt=Ehve4&e$c!t_jw4kH4Z}dmjUx1*=7&f*#fnNR~V3xb|_|$ zs4mIJ;1?qn;KEE*Pw;T{8`H|#=jTDet^$`$#cm`IXgZPBz|inD%mi74Tjsk%K`A(g ze37#vosFbqkbVyKAI6Guim;L@5w={tdh6EBn_m<3yW@>UcOe3OjSDIWV`k74hQDk; z5(ev_M<7~`xi%4LX=!Wt7LY}n4>dOp)MDiItC;uC%b!gGjYtNro#jND3L}dkL0dU^U*Eo0e9!WI@`w^uUE2@?$K(K|7d$n zaW2>Q{uDf(S)9{!X?;LmJ3p=O*p)daI@QT`*3vHaGcOcr-EG;U2im!-Zud2ir-U6U z>!#&J*V~o_vA!}kyq~AGx34Gr`{FoRz2SkHou^J?N^he>`E&0KKsKY?%GF%wRYLE* zJemEVXRZv3nruI7;n7ayv-ehSHmlR}O+S>1R4vCYUDbAgNAXZ__a`Vgj@gW9`)ZxE z9IS*%P1_vunmWc*CS2IymX(CudM!mPlOz|nB)E2QkWyzdWcI%+7(>!)o3#k}6VXf| z0Kz7m(cbcKw}L5vycl1_C0dS<04tZh9yJ;e;O6-t|3KC*j)NU^x_Y|a4 zIZ(y+z!0ets0ToI8qznJfws$+2wqJ4hQO5mQ_N*9J)V_B7Zc_D7?S5EZ28g&v(q~ z2%x{eHHCid$bWnm`2nAv*AWuz3*wW&U6;BnOW?Xv=hynVG?N_rqCS3}L50X+>Y%K6 z>1L4t&kvzr0#vYnX%*B||)6$aeeNdv4OZ3w$k?(Eec(<@%p3q0z zV)+JfaCKAz8QCy#737bg>DP;QczEkt_I^}#<#=bBm<0di;DH0ZuRVm=w!UJE{W}UG z_tSXj*Ck|r(gM%h=CQMPH8Q<0Y@(X>DHMG6&GOhIa4PHP*-`}%42}njSHU`K(7=$9 zXz1CrK1S_w`%9eC#vcQTkQ{bsD$#k5XK{bVA$?*gwKf? zKn&Ymq+XE*w1#3_7;U}|C?NG6!{sjjwUbgjR3Ga>@JsUT7iL=)tLfyGTaE2na_muW z2G(2*h%6}n_Du?hSSvxn)v*QnMV>1i;378ifDvY7>fr7P7m|N&_G#U5ZJc7p71t0z z-UK@?SbH>-1oBCv@Q)gsCPSx0pe_daVy>U3U(>-)1j&if$!hokfo&RjiL6F&FjcKu zsYt2fH{jY5(QMt#kg5SPLp8#rSYv+2H_v1cqPXo1U#bJN(Zw7yj)GN5ADFhl*5fKs zD`0lsaK2A~ZW+$FGE>bGHv!8Kb#-B@w)ka>pT#FvC++!fT0ei_or~u}oz6H=U$GQLFGb&>~z-pp8@x-wsd5@e=bm1rS71X;DUGm_Wb=W z65QLg9>*P&4&vqhGA*e`SPJvoO}%YMz&&g2E>33wZN2+0zVh}dVn`VQQ#0nr@R$04 z-iNd$jRAB7qV9t2ugYM-Y9EmXltW`k=+c|IdSgh{x}#FEkx+z^HdO;CvtKi+e#B@|VprjE=pdVK z7qm$NJO8IeY}gSkXIwBX?USXrH_hS2xmtD~JG(fNVk1SQh70diLJzBeezt>}hR4<4qGYmU#} zyNWT(miBA7?&Y)H_-b*#O7DOu8o#gm^`*Th3$A@@6*^0&N_ze3i_ zK$qesU{6^KSGhOn+E#VXj}J7+JI;-`G$eoos0+&h#?-i85hajcaZ59Ue_|X&tRfm4 zvM3JM)`-@5qFoLnXbC{mEoXNmlxbHY1Z7drt%+63RV5IFh6Ds<9iR^a ztKRGd5w0Aio3anB_FduMNU_uRv!UyTH~hCq@vmTd!dloqcFfz-c3rq%zy?|6l2q|z zH5X=yiLrg$XAgYcX8uys^-#_eo(t72mfuZ=S17J8^!?=1Z5~2odO0mFbavFc#1^AS zqfcVlc{kPA#}^(hq4F}B%#Mq7cl7==_~{nMb{g088xLO93&`oG_5p6qdf86nl3CMM{k>M<@R=|Ei6x!DkZ%RDsLl~9>@FEi;WN)`7lx{1Ha|&`@ z_ibDs+ZTuc2ckz|qy`J3FxI+0%Q~?^pQt2oq0gArL0XYOq)it6(5uM+gA+5iS3`ts zveNkWEDxdlBH`BBkbu#M^SC<+m5pAj9WMg}U15pLRfF+ZmuOiYT*s5(c<3pKe9UUF& z!udqFMeA?rZWGZ$jx@FMFNVy&Tz`LS2BGte3Y(^Hgyc2Rdf24nmaTHWS!-1^m$oNO zMAY|ej>rkN`SzT5x8?_p8SZi^Co>A{Ib(I{zKTI{4JT_~!M8l0fJHOkHUn#fQcJ7k za^IFN9`)|ac0-eN#&rW#CJpgQsh3Lx$dB_!P`ZJl^|53rY!@Gx;fIIXk0Hs`kS#vL`{>BFW^E6CKV})r6p&wV3YRFqcY=$~nqAP zWeFTsPP;;sCpI=V>67x_&M7!_KjG*SSD7vv8mBV=>o>Uh+%4c$CodaG=*H@r95h7Gjf_n>0&in%eoP zP1i9urc2$RSC$H|Ic(mVj0>aPSYV>dk#*EnsxxQT1=WnJ^eP9Hbl&wD@BAd&9$%sr zT_N{ebNWUOcl8ri2f>UYsSfWACvuCGEptsKOW0FX?LzWgwd-@g8@5B(tBY#VARjWa zF}z)G9Y^PF+MZ$XZMh7y(OCFNN<|MKUw8!xsg=76<(W`@_%;%7>FiK)tpccKU%H9V zRMfyr_d%2UHZlUR@DEjKt-Ka0!B2lX;OMOOR z85HK`a35IHa7&iDKFi)v#tV(1KA3&{I3@az&HYE7d>tVBe-Zvc-34jUA~R?+=trmJ zKCE=y?ke={RB1~Wiy*cmk*WbL6$oh=*3N55x!O7&Pa5s>O}`yzGMUwCEPxv8oa($$ zI_E)+aU(^CLyWuJ(nqY%C0iFxo6n3oe-~e<)MC&uW2nj)daHS2amM8^k0N%us-ELB zd7)7B5u@h>Y}O`ir=bSj$QQdAmd=FXS*iv?4#?MJ0Rtr{b$XQ3bTGn|n9u9&@83(d z0O7=&sQNu7d2nGXG5wlfhi zN?!8fJjknBpM$0~?x|@A&?wl)u`)AxbVe;fqTOKVD$b<s_RWA^}>9nco#AMG`t`=`H2w^x5|Zg(x`|>a*BRh}MkzufJj!(q^10 zykMHpub7*8Xf3HmiicW1c9cAY{n(Sl5%Jl13yyNTSNX7ynVg<;7ge3z<21 zLFr95VcgM+YSYhfC@t*-^j%&(Gt?%baqqDm$H8^c1!zGqi;U+9cnVzu($kPQ&g`-0 zLUY4sJlfHcyn@y&&IP-QRqK6_&`ooK?Jzn|5SA_msWIP08gN%bd%8bW1K=kCUVOJB zniPOaL8P62fRIT+agTqw{!8nC&AhCg7{2vqXfbPrBW{v?OTedECZL%h*jAnakfc-Cesvp9(P4I1HwU%9ZHI*O<3hwXZ|P z9Ae>|g3D?xDn;eu7BVnWl|R7bJ0fygaN!3&~}oeT?wT7G4Lq1QG9 zN8vc&_1ms1fvYHy*^l2=gKu00EJOu`hA;vA6#;D++d9%D(ZTW=V=D=s^WZ)k>^Gvd z*^uB0GaL}`N231VJgH7T^Y#uWX6~W;X^`J^t{ip-l`+2EyW0_Bj+u0P-9&N(^K~$- zeZ7{Z=9FFC^DzV>qM|lP1wqUWRCv|fsrFG2<|(1IOjvDM&uG6V1{;AjWSP!^NuvWq z^R^*@Xj%}LtCdw+{s4A}kH3F(bGG2300xrepx7&1@t9(1M-y>ggyp|W8L27hmx5TE z^~Hx!0_3nyhMSqnS%PTS3h1{V2PDBS8+*;6NI#}e`(s(wS**Nuvamu5?5=D0fT zCQH-{Ue^o7zu0+mi?De(O_Ek@nzT=dZ|0$xc-SqC1MCADZ;%g?Qv}MK{K$Fu9b5wX z`YwM2BfUl7EHZpzumoP$1hkH66>Y|L;2B^*FiT2S*!ybKwLlu$$>V7~5dn~i^jY-7 zT&@fatXm!p*W%XE14Hn_QwiIEio1||#n0Pj=KgF*B|!+< zVQ%ZVI!Uw~_K5MD4>m#;*2(EOVw1ZJP35I-3h}&0!TOa~;~VqM1quGYAbW}ox7K7V zqY#POS50S=dOS5ER zhT!CV`LcBdKo@S;km3RVDF#YYW&?Lo6? zGR|jUOl4;^kz+(7F6QTSd(1SsyAN~~qm#sigTG_nS-*(x5D)CUJi6z~E-;N}%;U8m zL-#IKLzY1sBV7IENU8%C{UBIWzB=c&g^n)oj5`HrQoj z6$rn+;UAxg`f7=3wF(3(JJ0OCq3_N7RRxb|q)`iN<;)GP$t)~%-@tA;q$ACk;kC?f9 z)H#NP>y!WMqa@}nN{n?T_tY~NGiygH&((ah89fOOBEP=Z5i6zS#s%O&M0^r>lAoUs z4ys}XM&mX;iHwZwdvq|k6pyFdn2Dh8800qDHj+So%lBZa0a{%NuF<;f++m-c%5g74 zf_NlVgI?LlnMf~FH4qKajPT8$$M`43qc;nU=7S51)VafUp)!hw?Fh{~A=82aO*+u=^9y5l3Z?VU8YznJAY2Hx<)ec^K&YFl=? zW@_aWI_~H&C;v|WRDIp*Sz8A=-BgPG9IKw~gdXT3j$?AdO%LQ zjJpJ)zepVZ7)-_D_PfMyJsO6!e-ke5+l$oz%7WSvFboTHz2i1A=ArtKK@&}e1EOLV zFJ1v}sVdXbunKd-Ycq%)M&N4zQ_2Q%;OG&JCXsbkERk98@Km)=A=P|?O1nV&ST73p z`W*XAqCo+?YOB&DVs0r4)+|OP=w-19UIPsSHgJj1;M&cYJjxB3k9r_q)D)6K+>UxrgW5;YRM%B&thAXH8C>Vl7;Em};`TtG9rAVGBVO8&-#%da@|cKdiIn|vu!(ObZLDty@}_RfHxOcF>445C}SMGTe~EW zbDEo*8{^mH0l_PyQfFOxNLhcqeRru3du`HwRbEC5KF%-=Cph@iuBEJ70Zz==?ETyPCU^7wXkoK`w^}PI`;wS>}*~9zVCc&unW0Gk#SYK8h&n|Eq z=xVG=O3t4?YBx0urz&etb7ELG*pyEoNIMHZ55m1$)qcE6A1^D9+Ew z$l%Xe7$@aJSj8QmSaJDeo^Q@rIBYt_4=JY|0Yl-Xmw2$%cC0UyJutSNBT+f4wQa_T7nnrE(NCc9`&U z;5Ui*kCkQcSo&rLKM|!qx%u(lsWC^#G}Xzn`L8aoHT&iR4kdkgty%v`DVcKXyTNNw$ji-5_C zT2;RaMgD;C!Y<>_w1*$mynA+WzdG<^F3qn`E&OINW#Kah6*bIXOWCtrpO#i$+4vm6 z0Uek@=fp(vSElim$2n!uASPI3=Y6rzIEwgbc=SsAPD1{8;QYT-ZT#HMDb;ayg9j5v z)0s#$_GUY|j*6u+m1!#Gz1Da&%9NT~V$3nHL&ZhHt$bjEE?J{b&T$u0%R=5oS-V=Z zfN$@93XQ&DX}0t2=kVCi`2&i5KaROkNpYzih^!M6%~|ByqI`X6q{;adTM1J zXwCi>{RsDuaF@d_er^3+;0C<+G_<8OfCSv$CmVOJycrURspiQX`WShV0XfGK+>93| zjMW3JyZpEeo3nU_PNENl5DCJJFwRhYr$8+R#I;W}9947Ug`tdXpfI3F9pcFL9g{~7 z+y)~|-ZeGf_4f822^z9H2xLDfIpYhlJVfN<+1YRf#)JO;Q{N;VHX;A9$}B3wA7EU$ z%gAXl;rW?gh>b}6>ZEx~rE$u778$sa7!}cL7a0Bt=KNZd(vhXQw)ENRq-2Bfg5zIY z50)sCW`8<#oRNBGUh)3YxQl6<=WH&mc~wY!MT&ST6Rk>)i7WzFrkn@qh5aR&oblP4 z1;?j*IbT(D=hj5%SIy0)D>$_5k&@5mp6wR?v9oNT^yFSw-r#^(f>UDL?tc6Wa;KW! z5uD&Brp0^*;geS%k>AN*DyO8h^H!ko`MCi@N2Qqj4GjFpIC7@i;E#JjuCD|tt;;6| zl44)$zykXbR`ljBV%TImW^)zW*oKFP8<&e7%tN5uN$a;yw(e{>5p&Woq*?>enWCCo z?sSpim&u&TY!+5lVmV3Xm|o0r5XXqi#wSjbdpi;+4@0~5o!e{b00iMU2*4-A7>&uH7?76HjMp#jOt>FiJfo%uRzq{FVf(cDk~Z4ei}%~{~e=rwq|cCaLByy zc_xEOMoLPLe>|*%U!%Qh>_vQ@W=luNj**@ZK(jhMhVdh#|>w}$bSU0!c z-onXFLI|O3oJW^{YB(h=8^2>e3aCxs^%kdPpWRCfyF=f0FX_vV;!>M4ZcJe^<6XX{GZ zT3wh7EDVT0$920rEH-!uL9!jjiu$~gXk2=LU;Y`^k|rh#hZNrKh6VZH6o#j6#La79 z?g)RH+cZo<0$^Hh$NjBrSQCINJPqX6HZb}0xMt+9UEA@=WrGKzJ{MZGAUMQ6)Of;o z0O(+~W;TkNeDEF8R6TC%qR3|iQ$~^)GBQGPoM-RLM@yZZ$h2zl@HIeMVVHQ3#h{oW zqQpykjyU&Dr?CYG;KoA{AMn4&>3$i<69=Qag+0x8#~pqyID_;=LrH}cKT{E zWBx*z&*IUmF}`QR{vY<lz-r#;CEP6p00}ApxaH%@IXKKx{}6RFL9O1f(~O zM@11(P*A!OP^kjL(7}R?BT^I?U}#E}Cek~6>q5wra~?hC$*=FnoBRkSjBwvq*=6mu z*B+lx9$3bAyIkLWpG~dojpV_9Y!v5Op+@^G&Zp&|G_fznh_hgSf7Ln%?y=@gt+WcZ zc?w-*OKpbKmRgse&v9gOKe@XwEY`+);~U3435pY&S_bZJs%**GXVY1`uD}cNq&RS+ zzCjQ_>cQalWV0u@{m}Lg!9sPD^bUGFsD6rZI+-kcT@Xf$i9}#L7H*TEpa*&s6j9K& z>fW_=%a%HfWp*Uyk_`PeK}Wl%dJUmpqA^8!`(r2jvWyns4n)NSFkZqju!Ta&itZWhH6I zUqel8DZV{9$tNC4=RkjiguG1Y75oIpycrk%@Zow?uQ*FfOEGr53~yDYIg$JV{3AQC zV(I|Ocw*#P4%ls6x!_Dc#DFWv($^A4q6b}DFLX_bnYv=*F?rJaMAErqD>yjFOILCO zri%3hn==Pt*82Mg_o5F^FEL+CE6O#D)i?SCF%;lWsqro^*Bk(H<>#x`uSXQJ6f7wZ zD23*t-Thv%>+T~@juQXWh4hgDJU8y@z=wzcGtQ8)c0)bfKciLWqGMt_U=u~(w&5H8 zrH(WiPh&bh>G}#;?ph2l`*oW}!teVJVhCz%{Hs-33Si%zxyEB-B)a0sXfLeE+x2YJa+0ZL~@J zmD=I=7gE25+Ly?eie+Cb{;z9>=hFmrxGi2R5RE@|>7PrlD1O%>1-p#hsEbX%5r!rp z%gO5XuE|#X|Le2-5#`LF+!Fj+{l3_~fcERivhQx8A$ADHAq+%#v*yoR zIGepn@WyJ<1EC%-HWCl6{H-jbaQH_W8g~>$?(bycheSif1^ch`H8%d)(PNe=!aOxC zt@MIR^jGd1R3v`=FF)=F8veo_4UPMgYua}AU)EFyqk@jAt1F&8dlpK!dz6)xfe7wF z=l`8MccL+j=G{X#wJ_X)gWtacG}}ElI-AW#G`;2S4OFO! z-3JIj(|tM*m#-gnfa%XzFe({u&@CHl-1vma=U;?o3) zsbBEPj>TWJYAJT9@)z=q2nf|qp5y@%aU1C(`OAMC%uLKcfKi7) z+6u&|i!RZJL(0k&D_SSAnhLwxCbH}-aux{S>fZbQ)zzq!*E)IfT|BCH9|>HlFxlMn=ZRyna0MQ(1CB{^w@!ExV4D#9R8vYvJq= zUy|eMYF0aFI55++C{SJtLQQ$7>rSu#p}VAY#6=B{VOtKJAXXzf`mF*SR3x?x?M)>)lTSM*=JDgl>z?9ZuVCtnEW55y zQd+vl)YOz*SezyDU%0;L;TyNAqvlp{;*7x9{Q!VshPLV)c6Y$!jsKq)zaU*Pm(3|e z<<_E(z8b;te+(ZC#iY8ref&O)bR*(;qwqhDZYllZ=;%B~OGpqQwStRKsaSDOkY2uC ztk%g2#0UAP_jA}bHTH(fC#fk7F`~PT`$DSCGBVJx@iDQMoLkq}C2^%J)?Tde#%0&{ zZCpkUKB#B7LjmmqM*?HI68_bAX@AQWsyfag7J$vrfmcYgEGYZ`4o!g-R(ub2l>Aq`CDbJv#2eyaY6ewa=tKu!F~rZXA%{D-9NSC z$5~&RfsvAY73nEy#hPV$U$zb7%3-`MGFN^pLZU&RRqpu2*7ck-O>v}%mBNE9vY_L> zljp`QBheugVzzAAx>XMWBl*aaqmj(<)@-L*R$Tb1l`BP^;voul@r5ub>66CHdwUUU zaPEuAlQ$G8TXbCL_P(7tY+^&misK8sBt*R*;b363tA3(x-M-z-EeUpnoWzjo0u|xK^LUXO^R0+U;7DjpylD1%f2`1fa82B27AqGRcNiku)Ao3kmmDK)$;nNA6N$$T zA6^DB#$q(u$zN)z&345pshz%U2)FOACJ!3=p+vD5#PWxehq$~io<2NZ%lVEV?(LLG z`+C=0r21~tFN_$O{EL@KI`%CulPCuJeYP)~bKayQi-_PqN2P}0OJr0OS8f#kHLf!; zlBQ6>8I>(e9^%T`s2KW<7&`mS^z$L6_W$~Pq0wtpa5@(~Pa^(m`*u%cx7QWc;~4vU zti&eVH2i@U?w+_uVVmX(;d6I@tbtxeiH-YK#unT^pB8@j36A8_rPyp-`Jarb(#NyS zoQq<@ooRcZQium7aE%lzSud$O~PQFlZ*&;n)d{mgMeGpFRO?L~A@VW-a#iJ)Njd{%3Xb?4^cNcqoZbH5ka~gAGSd{ug81b5l>gOubf{z4O|$-< zX8l?6WZB}LDM@?U#Yqd7t{2lkQP)SYwbwO2Cx4Wczwm5i!g8<7@63F;GE8I zu}I{r$SK8|3PVC{Mjy$I89Vhw=~~|kq?$CqQ9*C@^cn0d<>GG$s!G1B`D{{muJ82Z z@yqM)qH3n?Jkwt8Z#Ut*V8ag(+nb@S_dVCSp1sPLIvN$uxIseQr`vJd=djB^HSX%Q zB3L5w)?f=K@Y#jWe~_Oy7msEK{I5RHs(>kxg~HM+R9jkpmMklO9lnsp<1+Y>f3kMI zX?07TiQp9$C!?H`!DjJKTfXlsATqG^noD9#UrS87clnR|`F-GAm1lD$X-E|^ zKcPYiSyThcfr9X?&hTTC0Vx*wqGkHr937Ui?}UHH??*HA)bBqL<2>$=zfViai`kS| zg}4@g`^=PxZ^pH3P9yi%vMIhToqf7l1Eoi>uB>D0Z@VeH$d4*dAuI8E-L)J@_<37s zhk9s(nDwg@ZcDsn;~NahKxdapW*_Sv&^eFc%#ssOL1(v>r2ljKTZd_&o)cw^sh)?gb{5TzH@^B5WUr(FiL!>+IwSqHr3I?ie(2SzGHHQn8Sx_L@A{@Hf+E5`!z)yi3Y$i|&l` zPa`p`{6}=+c2CT!m^?73zU2zJbh*>?&`_yVb^hg|#Xm?|P1WAsdwQU-fHz1aPp6gX zV9o8=9*kiG)Y%L#Can7^(w?B+vq6K~g5 zM<7wXnhg6cGFcMQEvb(z-t{T8-1t$@55s>voYh<5uMhY0Wl>lD+QGz+)Se!P=}2|Q zH?Lb84%%QRM@O+Uv!+Z5*X=~eZ1$)5|8&`;KeWQg%0xRkh|2R-(wib*NgF6^n8V(L znk(uS--Lo_kP2I_D+mFxQ_k>B8-5yoK>Sngzy8WHG_2q>`A74=ZlPm)Iak%^)_xmST^$5T=6rK}aZeCbk5=zyP(e^(HNBx(u> zF_Hr6#Y&?|YY7LRi#UeT0x)diD< z!|lL*u7__kK0#;l2aJ{7cA4e^knv!8xLGPA_Xxj$0Kiw})kN;!L}@t(3>FT=Ge%t! zq~q_jF2+-Ir4~AGha=CX_4G2(aXDFbjz5FZ6i8Y=fwtS8))s3~e)`(0X4!#MYgsS# z7|oT?huHfT)g=tUDF!SnC}=9dst9JZ73W?s+pCZ|$F227zUEZ7-Nco5JS zxkRS_u}v3)b+Q^E$#u-Gdwkjv{SDXAub%^F=-X#Kgp#Ej`sT$Z!C8>IIO)fbIzn~d z-UQX$Ma}!sRwL*}s_a#qSoKMFLX*R) zd3eiK9L)!kA1*$W_&^bldqad6N$5h;tC(%DetfyZF0ez_R}215FF)fxSl#JT)=H8p zQUd{A{@xRWF67_bl80cc$Oh?DDjjNZbNpll!7pbU|fx8hha$G1? z<=0)48$C^C-JNW1NXXmn4u*$G5S^G1LaXrSDKn{2BIX8Bi0tR=iE*2d%k`d8+sE-l z5j+7qjSsuuo~!|*Sc*=fw?^|98CV4qGhhLy6J6@K$&V2+E-Kqww0n{*gJuGDMn@rB zp|H#7px6~Qt1P2wI8FI8JauOGo8+%)wY+BuYp?W($(DrC!r@y`@$1I$hT#7VZ$IAT zs^e~+FcV0^TJgAZ8cLV$ySd>M%E1tp)`^j7R|=MUhbPR03`iPb(&SG)15P|uW(h8_#hcBKa!?OUXIarP2s{^UsT@czJ;1X% z>*R#;MLlN2GlwN;D~9b+%0B~bh&3CI0Hh$XeK}T^eb#m9QgR^bp&nzK*of9rPZ%gk z;%0I4=COB9keVLZ*0yIQ7>!jATVVmimt0-5kW}Ki(K6XFJkBmJ$cG%1==QWv4^L#+ zS+GV(oB>suT=bokoArobY`7h2M`iX>Fs+78O*=x2i&MwKc*i!Oh?g-4LtGjmIrz@Y zWd$np@=pdJNS6t(^+~;1I^5M6IXV4S4hM|hu`e4Y!P{^ue!UWo7mevwM)5H0; z9mN$tJ5U-QQva%>qQ+$Qi4)IpK9iXg}8N=*G?gJZ_bw%lpZLvZ4coVUm zeSV*HK-F|_u-J+a3+A^FM=a_^ZOfiW77va}7gUlWc(@=upl!+ITf-Z0Ap8t^l>jf? zwg`gg*oN5DCjV6-FEtE|aXskhJAerr%UF|gjt}zEX=BR$ASYixQmeB*1OYLN4|GY z_Sv1Eb2Y#16ufqE(X0P*NUcemT@^gLF+&Wbw0ok|vn0$7O-G$MxLi8%jJpMf7znK_edLfrl!u883d4eD! zuLD7B{bV$N*vH+g1*Ch@HS!K{1g*Y}^I|IqK$zkz)n*#8@PAxJ6$27i%hAv7rm+59 zQ`uAcC3^pPk`Lhm-LY^2fm0am&NLFjBcn}TEph&of&y53Qe9v$^0jT!pmrsiST|TD z@&Qq?KnNhZ@L`Nc$awFgE+oV;#bOvoy$k`tDa4n}7Z!g8Q5Q2i2Q)L~MCP!w#yZRy zFe5(w!eD-SkZUIk+QD9UnKS6D=z@vK!M1P_{?9f|+NSmEv-)DpU*V7?y;~bVcyVQ5 zEYR98OP$^Yry)zCKn3)@tOvah!31GAc;S8~y>hOGkL;=_bP?+)9}X_l)=g$Yl9(6{ z%BkI5Yy7?y1dwmO=7Z_4CZ%$6k#oBslR(Pg?>z~zUD&?6;rIYyMwH`LzV}3Xu(*oc zST9Wv;hFO&wBgL?qd3IZNq|#7j=7rLU_Y3(KYh7a*|)5uBxlwV>7R(@2D*6Di+6{? z!Q3y}S~Cv;_#?bDf|H`X_7yl;XI|f0X90G;VP?MQZaG(s`KyB%h1bz7cWuUiyH4^% z0T0*ryn+4#>gE=`?-Ut`uvTH)pdWab3|1r@p*6h4I1YB79$Z5m;&H_ZV2<22<)^#Q zLA#Ty4g6kW2)%-A*iV?__mnzH38Sdv-$bj<2FMexB!N22 zoz<7;^AvFc6-EW>@Iu#!A31}V(5y?dFEM0nn@IJ;^N6l2sw^0yTEXsr)dUit7Sb`q zo)|NbLG`YdwA5!4K86sw5?hWBSRg}SJb4rhDjml06s(>-f|=+%wPT-c1GYI53Ks^J z7pBCK2o=7*?98VoTm*L*C2_rNhJ>3zK5D%Cbj93Iw9hOf3|7LrS(Jyy4G#2nxC z6_K5AbHh#BL2k%St#Oh-6-d35^mlyBaM4H%avge)zbyXPiplEuK&G8V{%hk_} z>64iUA9$XGq13){;1Z5VgGiKXT*eC@8i@12)mwY5Us{X=KSZS)$k$Q^x79%maFmQ< zB=vT_eR}$3oww3eBY2M60MCRuW5U;0RnMt-0*mWk?29Y9q ztko~LVW5w_f$;^%NYYY?4qEa1*zBy|?6_LXqtU)RiB|5=p$aJbmzdaZZxSslGqpsY zFGq-N;lOm^zr@`=$Pft&%>Oh@8Uy@~$*ebk z&+OF50=_1J5G9OGr&s8u*>sUP@%AX8zXf4nWqA$G{dM!6_-I6QEMT|Ggi^87XLqd@& zp+#j#ub)gzxE(${$oDn85z>L&WKDCpPQ>dHWV)PkqaT-4b~w|7LjnkJl~Q-39C5T} z)c~RXAr09lMK3+B^$L8s%FksX+H=@!y~RicmxG~J_;qQC$gl9Sd;2!l&66Aal|8UK z)&vR(96EOE3U;+ci=B+K6pl;HGV_@hXnS_GZpZc^%oHm8x1v8;*jq|wI(LHz*AF%g zjxC%g1TWG~uQXHkOf!0-zRZx<$L86}vu35E-eS~}^yf!z`c|G?LspdedI`kf! z(h)>`v_K|9&vP`=lM|l@PCuXubL(tZFb4fIJ6o+mz9(XrLf)}Yid{)@&N0jcjKqyUIDkn-JJ)Q>hDF>H`7Yy$du?g4y3egF4r9n@-x`;K=S z>Ne0rH0=}!=&Pf9yrR4?pXEu-1lW)Zm^0WWI&2=>Qg|MwJ1VoJ%gk)-wGHxHJOP=ChQMz#zcb zgS)G;Gqt7=r0K@JJ(|zEQp-n;Dy4#>?Mg#c4#`GG59Gv74NIGwv zY{lTQ&4Fj;S-KQ*gzgZyQb4_sUIWr+9axR#bf>AJ%J0=S5VetpMKyKECzcY2dTYlC zNS5j06ZyW)yNXyiJY<9P)Ap1h_*(_T=LQ|Dq`Yx4mb?}@dAO~FiAig228g$scx{se zCjZi$5 z?#fj#;xSZ?Y30X`y#gh4Ey>XkCkV8Sj%rFpv|0VdY|C^ps&TX#(Qa-KJeOW9@!_JI z+dWxlhlBS;!Yg)>u!Ar_Nx#=Zj_oF5vH*@GS|3j+sE}Ya<a|*y@~i|U-#mFhWpZV>2m`AN^CktiXODIh+Yr!XPN=UC#wXQKG352G z8Y+bjRrz|0G6)9gh=|v&7}gWj8m8w&=t<_y;2qVqypv ze#7m3`c(x4Pemep)6ESd>_uFlV*9AN43g7lV9==ajPUvJFKVRrV(O5IdZ8&vIgJ^l zXN%Z(y3_92Y<|^XZi4*f+UY3d5SLz#&s3gu<)VUwM@m@cJr+7gaQ5oq)7(+VM#w3k zTL7lvA`UDftp80IWC4Jyo&?rs#f=cA`@vvoNz|#u-sl~Hha>$GXe>@{>&ffC7wh#G z<9qrLX`Lf}zu40hwu+#Mgje_@uu#y6s`Z^n!yVeyo0l%dol(t!{6dup7okm)h!CYr z(kb&5Sbb#MSwm1dTH!|^AlG>(1{rHYCeRg$guVCma32Y~x`2zW>nI1NvNn6PQ7AyL z_NPmD_jJMfK(XLt0_zcs)TTn0p9_H-?ig{#q$Wvq_B1EYhxl+0fbq({Odp|UxZJCY zXr)oW3giHzlV&Nq#=Gk41GIWix(qd1Jex7kH4j@LkHTC$4}Cf zVOVi6_bTLI0{c>60Y-jQGsmwG942&-AcXSt!Qf4$Z&BjNHygYI)RXej@}fsDp_4)5 zF2CAVStvpzV4Dgi(HiJYHT;OIUr(6h_z>7-{xPL?e_>hh34xP^s7myny=bRKrIQW6!Ndi2Aa zB#(tBKA35WCMkGj4rsl!Y6evzoSW=$SYsIYF5-|Ty}Pk$g;Avhh;PnVT(WD#QayzI zu6MZq!kKHhJQ{_l#WKA`k0T=wNM)g7OPpEL2^>m%6#45d=1Sb$VT}Q@yB@0V`MF3V=*U}nILBRJ>=+0*StgmtqR9H}xM~`k)*4xkbg|eIRWU{2 zeD^nO2Gr$F;PR-lio*)q>*Ume&vg@P)Tt0Wcj%LFdKHvFjKc3*?Gk#k7!)D(@55hmlD_yI+xnop! zwd2}xtCks8Gp{u^_jI?*v;`*i*BI7BN1JDsp$D8(7lk%raoo@x5@;(^Ni$wPHZtHf z3EyLE5F{Hq&pMhNP8FZS*3=2@kVB;*<{lQF6oAaX*g;N14+3F=pV=AE#wUkkCBBRwSO9 z>s5^&IScHKgGCGkVs}Aj^9pEcLm!fGn0Jv`8|F9RMw0;;cP+CayShIs4 zsj7uWaCn~ZJii@qBNotrUM=V16vhBMrlz6OaBW${laZm=^v^fo*>!sRj6CHlUlmYU z*_Ha!3EpdW(d{iDxc+;8FuCIz3HGH|90663{C&|{%(2-0mDAa0A6JX5Ax)V*I*yPH zCI`ANm#~x3G~)Wx`{8Vog`P;z-|rJ*4yE;YEYw~vA@sk3`BBrbT0kX`Ii9>M?^k0{48P{6D^5GEuSij!P2E?6-JshwfJ7Oj)B4>Jp#@oMiwq9wVv056p zZ%@bs1hXY%;mXP!oe5JTy>=}2lLd$;x(Wz_{G}hE>H(`>rY|20DGCb`lmVP0-EHsi zh7y(y`$i$le*mkwGveR$v#qovRr0p{e#3E$o_5;nA*d0=!vTH7Sc)#neB6| z&RdG19YibE3BQjto$qC|g9Ah}uazZ6*a*H7P|sdiu!pcT?=S?5baRs`0*M0=0(G3V zH#?jn-UEh2Rf=#Hf<1AE473^vqas5(xwrv-jDNW%r+{a}l%tSUum3U41>gg%TC0Rx z`%_OmezqMf{f6}qk+TrI57Cd*L&O$+{KT(HqX#3V#g^Xy!ny!On=Q0wBBE{HP_?|! zS-xUyjUU?HaAR<~WROQM@mQL4hpYnm)db<=;=v?XI#F>OEN95FOlsG~$yWl$BlUDO z4UGzuGDq+rNwW0`HY2e{QN26!KFC4q&%F5Of_Pldg~I_*Xe88=spEs=0f4xRudo*Q zDd&&gNq4A;NXt$@VKvc}o*Qets>i>tQ>2lbga7| z-1(6xnOzGO$JhhX#mOl%nJhtf@0w>1+CG25`9Ip*42H1#m4zI+*r)A7>Cjoufx68Z zH1YE~m?`}LBSv^AP!M8$>bg2}xB3}!7jb(L>fDq7RX4G^IRuIOWaSR*a1%Wp=753D zCHj=T6#8Ti!I}yL2j=enmlrzAV$D`UFCydjR7kI?MxTgZkAlFdoZ|*dX;oVJgl) z3blJ6`QG|4%Me`tGmtqT9pS62UErvBrF37zoS|n!Z22TpZldz(+ zeP9?0N_AA-5zRy|N4}Z>`#J3O>xq4WW8B2tPOMc|AdaJ0ztv^sDjochM0u|Q^Aq&BHGABd5XYr=gymrhoP<(kAZi2 z-P|XQ2Ml1n0cHup-P_f)k&4}!9JfKpTsUgD+S1Ky*AiX}85Q@=iqy-%rZD=Y{O$m^ z_S+r{D7}?ElJO4)3~`mDqs5g2h| z<4EP$2;{bR^*GI2pnbX&W$2|{ofK8n9Eey7yj4I)&*$1~xk=&+#Im_@ym2Ds?6OHi zGP+;uc7zNaywF)Q=3UcF(ayo&Ep^O9Js5Edp$`rg2~RQxP(li0ltpWhJWITS zGSN8AS;#n1?=5?Yp7X8h17Cpp^Sd3`9-eW_YR^0 z1OCB_f6f~9n+_=ci%*%OPA69#-horvX5A$^Ipw67GuMmU1&mZ9XON%!L-uqwa*Kni z{T`i6693j6K^#?re$SSa1ksg7Tak8v-?RnJsH9;vl&ri+$sV2WT+%Kmpfeyga5`be zv>>;o-hXs^ctjwClaf6U;-P-A187PBE@6~2P(OErtx#0RL5x&~Aed-Glte%o4$z+Vre z%U}{pqw5#15!p!E?a3;xx#%|i%H99vm5s|24OI!uf^5QxsfPxKT!en5SPyY&v$!6NfPeE20M@!m;ukQr43sWg|Qn!kkmyMCqG; zxBn81{%wffsweJxD9Sv2q;g_H2~|KE{oIWt2^af7{T``W-*s zVA|ilh<^s<;=^fAt?`qQ()VzY$?m>aQ!PJ~1gK4ZFRGkWpZLS!>Hiuk_&q3UQqFC~ zl$HqP^>6Z8-@_?t#s^#{43@#?zHt|Fd9#tkAry*V(0BjF*AL*|hra)$e|%=e_ZR7p z&&-)=`aSr3`ZMyE{(hXV7k7F^{`~dt)tOFq{=6#FfBt)Q{$8Ewv+yrp|F%2dNJ0Nt zp}$w>|LN8FGEtu1b3XOWF4YgUO3OBG+?KG1{(Ak5Me}F)Mf_@fN!}=Z&+2va1y}!c z>*s(?%QpVtAupA`URfz|-!rv4&Kz9z_ttRSGrK>Z_Or;9plbJ8>rsKT`LUpZz@Dhu$;tJ99Kk>R!Dwj_%V{Q?Q{~@;j{fu! zioE+pdeibE*7=#!%JqN#?$n<(XVXMOF4C_qp8`0(@exYV`p}pmd@k_f*It)zedgk- z8K(IHp)nt46NQNH{6m{>M3tRkx=3J(3jVE+h3=8p>RDh!m6-9bqFMj)S;3iXe^q&{ zmkYiM=KkXa-{Pl0|_ICjA zcZ~EO(3Jn*!pL6&StrFS^nLVS{8K+B$-ArGM=k74cHe-&LJs~yxe)1|gWbKw=tpic zNnIqiPj>Km*~CDcODXsN3P69%EszqZG}-axUV5iWu)`be$xl3cbKs9qv!s+Er!)TJ zF;`bmMH7tFb~K&6#^bFd#KRUFA1%zxddzYii(`(|l+~1@`+F#4qB!u^Amw|v+UZ&e z#VSmCrSC<$ji64T^srHPaR~oFjn=qM+J(lTykZqDiO_uEfCrcyAC=s1*j1On558C) z=U8&K;0#Zp%sX#GLNGtHyFHOv?+6o4Yq{Oy;47#!-Wum!I~tKblJq$ZNOjA zZq2WT^Xj!fa*4-Lku%xe`nfmt3jz(^=52noaimj@W;)+9^xRB#=+Is-mHw(773SFu zJe~W7ha)RKj}9?U+VY84AHA_!onOm5NZY#fnN`cZ{6oE(@>&AE+m+WkZcCjQN1xUH z@s8R9T}E+*VFTMJlspg4#ypijErar*(g9JS^k}E#l+EKUA>OuGR$sg(TGjJ-AHUJ6 z^&d^1VAYgQ^tgI^xs+ggJl3A{-0eEv%v>zB(cE5X$hE`a(y`} zLq&?O)5TWA_;5n$aXwn?$)08b2naH(QqRf;+eb*o-A!U0z|lhvNufVXYa1`3^;UDS)Oa>p#B3Puz4Cjg(=-GI}gG56^SQZ>^Bb@rM(OD z(MUXSJ6TWcWq831Q&*FB4-e-!R+@%COASyLUg0={QgppkUDZ=!Jvx3HTBGuzK{)-7 zeD$$D=Y0Df@7;@ya|5H3bu33ZX3YzVcDwjvB!B3lbsgipm#PMV}mdXy1WT6+E_gbbc8d>vPFJ7#tXA&3dL6n-=-cmc`fbbTR|m zvLD%Ig!Ohmc`N*=!tSw%Uu@sE_!BQ3JK>FDGIUSRV$F?-Ox;kSiXvv|ZGJodjRW)yLK zxze*1n@a0W$&nGCt+D%JGwC{W+=D`l1d1ah4R&PsuPExjw$?Fvg>=FF;-FBmS2~ED zsofY=UhmUaHn4|>Liq$r#Dmd6MtGOPk@hUdgjcIByN*_+HZD1Ow%S^0gSQRtGRPW| zm-$av<-fo9sl!~zBTTI7=}v3z$@_X!BVnUP$}bvELwBx(l9IRXxQP9i=MC2d(yW%G zYVGwnK(7+9udICIWRhW#@O&G3uSA|a!hni2=;X4>GCg; z({5UL^&EpIFGMHd{OO^QQgxp)9VM5M%5GUq(y$*Ns)^?6)L$EuIBD-36z|rS1@02H z?`94cGJl=NClD+_Gku)?h}_$Xn%;#0$gw+GkLH-p{Xm0IC8F zA1>$5q5LB92P(1mFOKhP2?#0Lk`0m-HW0rt@KnYrAw8g zL-_%fwwYT~KRwjHD^`%mlep$a#9W%-z_VFQ$>tv?IBt`p|8#wTd2pbUWp{xseLO^{ z6=GcGk*(~Z_KHTGWU$Bc=<0yd9QqW5(^52s=c&7U$ zFaJchP^q|5Ym?Jxqb`4X`{9{^k&i1i=-ceu;~Q!meI~l(yhFy`ws}5(qF4ODPZv%n zGGpFaXIjR%YnQuz%X^2nVb+siihSqe?h${#lfK&4$HtoVSi7oa!YlqG6i!S*CMrK%hCe((!qu9>e!p+^og>_Ik9|^kl)HP|{l>Y8JhM5EY3U;tuaggJQh7R#`n0LO;x0eJ*@PUp^xdM^$B#G)0D5Y z%pN&u*&Nj9^!XKsW1F^S;abYYyOj=Yd<-7H_9S&lzhv3jl)X3p>;lYHN;4%{Ts4O{ zuN{4N{^g#zWKTFRSQhy~IZ4En{kk)+r%*s3=+4`KvcREgqpq#ujw+4fvGNFQ- zujq1U->Pz;n!hEc{@I(eeWgAdJoiPYDDU+eFPvy{-vv$ZfXFnPn%aTNB-@|r7s~hu>qXX%XV^1E%Qo89o;0oh{bNy?U&csvxG_t2 zbk71+9u@G;E$cnPyNfrWucGjSlO}@gO_u&A%{t( z^?fg8u{EjA(1vV?PV|PB(%QHOG4ul%-FAub_P)>Cdur8IpA%Ir-)t`Jy}@-8r#3Eg zs3%}zP1k2z0gjVL&pnNndvf^5EVggk@zAhf8O%U<4S#-Vo^RhkiUsQ$<=Jb%c~h{T z^|8MECu!mgf9cc}{70WpZGh#OB0tD$F~>&+3S+NT0H$uDSkFlfKEdJ0-LeA1x0@ENY5i;! zqBP!QewDtcS^lVU;x?mL1Y@dB>*40R`QCg)TL^Ow$3{q7m=`b{YkasJO@^x4=yMjn zG3;0*zR~@zfALj*F&@p7r#s)J_p=*Pn;pz2tx~yDPeX%`Qjf9q8w%x@gvjx%rjjR2 zA61sEY=p9sr>w)LN{gwR0DZn?8MJqMH)IQy>1g$z-Iy+_0xxT$na~=!L5>$8A=)`D z3uQ7Vb`5`0RB|qmM>~A#SpNe#bzNP{61B52JKqPp%1XBUzHD*TQEFTe23Rp2+B94b zXGYAMv=WUYvxTxGx|`pBzA}Rn?ZmIVWz0Oe{KfE3lutZ=;EiFiSL>UO1_kJiy_DP7 z>1-}qX?gon)_c<94>;XiTPG~W@{UoBsZB!$aE*nq?CQI)yon=^pbx(xs;y+b37Hd5&PdL2_hPGjaXhga{z!<$QDlKcCqE#6Ar zJht3+Z|BLKn3;d|VO(6vtd4Bg&e3-4j6mQm>E1&IJu7~E^=4I(?;W9yCv7TT=M$SGpV*P4-hD-AW7yspyXYxL z(apA>3@}oKj;lj?(y2vhcde(@&yf)tt9BMXpXbM~7IpK3?XtD5(wG<6@Z{0n@j=Jo z7A7aPx1iIoqTb23oOKj);m16#d9$dIysQ6F#S9CYy`bocPCsw3g7z-pf_n z^J_~J&W0~eQs2!!uA4c#ZBa>bM?B+zY4IWDkYH{Hqt5*2NP&-^}J$ae^;K|iK0*Mn7D~JELJvcyD6a@K;*w7_a14So&iVPSKVzo zf$+}X-FZOS;O%2G$L%7AL}!>DGS@Oa#ZANowP>@B;QOsU$TM-wN5 zL@1P-(H{r1ny``bx6+6)%pR*eM{m@WICjKpW?%AfYh(FS#C)~6*t+b&J;>Sk0?$<> z=#LH}MQso?-w!D^qY)@JFc*nmFqExLzi~(BlSke|JxWXHSy?2TT_m>2 zD&gJU%eCY0!VSH*Nz%=dre5tnuq@VRMSUocN!e*&K2ihF5r8y zDqe41_SmBk6 z&ix*}WX44u{y*wEt>;qARPqDwzYRVampb@H-8;x8@{c{$jf&O0aZ|i9I*}psMc(rH zobXNYN4U)Hal1Ngp50#3EEj@-aeenHE$Y36oLl;`f9|-Kf4;4EpbF~;^Oy;7IwW?YINV<(`@UyHq&qh#b3GjD24JkJ2K#Ge(=fGL#;+t zDGjmdZ<0nHST0s5-I@1W6C^PkF3xhGhOF9tFhW&G*&{7HPH5<@q4(H8=U8pUV!=|P-OY9FgRsAx;dDwWcbK>4vC>*FH!md#!Pa@pKrNW+5d&U}dHGP%_rub5El z!Z#Xu#GOMxaqWHS?$=)mUNr^y^}RUtTk7zLlDRJwU`l@5rt>S;iv`QQvq$qp1cLfQ z_8$mhKDfqTC|#@-_vna z+``}Y^UXIKsGi4hP|Q$8L~rky+=g6F<=C`y=i`pFsqTswnM>nizFZ=p$eUSLpL;$~ zDV<|3rN{}zfFsuFY8f>SOr&Q2comuQTE28P?bjgHL2u(?HgEO?&K=D+KTsd5V?HyfU>Dyrv$hz7)RI9i9}R!kHE)XxG0Aq`Jm0x? zTnTnqT&sb`*celG(=HRx1p1w1Os^wjViyLy5`|NSg@HEy~6R^1Y{B8tS8^pa>6%ALvVJ2NP!^cN}0SNf>(A9=*0u0{GVJ`@sF8T>U$E2-2SJJvl^Xxo3UOlRxI z6J@%!_CdRKb?po4J(XBG>4^;4{u7qvr%UIQkH#ZEk*L(FWmnV#j4;cHm$rHSTR}*2 zoKS^Tp=Gt@Sf7+*J3?;;_l{njoyXD|ef3{1n&&bG?TEoz$U*wnt2{b=8Yz&&dki2B zl54)oKuhi-&rY;{8@x;cH?%?kN3TZJ0lR3PYj^@y&nh?#c6n=OrH=EJWv>3y>J%ANR}Ai#ed3%7L{=faR?rWIJj9kq4mRu%Xy2s zwxoXDN*Pm{nq{>$^PX^rhi*p73a$M6N2+B_l8$vZ3MCI*scVc)xt&Lr9>9N0o#vxa!PVI97bFH$Iv*jQG=Myse`_6R^{S^)2eg}FYy6W@B8j>^k zDvTc;PGlKhj&5A*l2YZTBmMR)>&PR1fuNm(3?VIFU}l!J&dd#78wvV_{OZkCW~Zxe zlU=^3QrKN(ab-9_eFl$D2YqXP+T1qB+O2KewIZid;VT3;&oC9Q`bDJ2C}6LkVINX>ep-Sj9?&qg6U7CPuydy-O7l7@D1B4F4G3*^Nxd` z3Iy{;LL`HBwLe{E!-C+VvWlF{P(|U@@lk5D+HhXRKxUB4=Rhm(O7l*SvXY$Zd@1HX zLlGBF0}2)pZp1ywOiUcZ6L;wS@Syij*Lrx-kayIG8i$ZCuE~>ajXAP@PA8 zJM3fjiFW+l@48xgxp!oBu$C_r(eU=AQZwQAXdhn3==3R*9n!asa%kS4V$fZglBKn^ zXu&Zs;(Nvk92;z^aBp$9{-q!_lssmZ5V5BD&y$pr## z?96X*tPQ{jSrM~9J+TdO1Sd*Sg_Kcr((z_5C{W&)%}nq4B(soGWa1w&lOjL1NHH;5 z(#m_yj#kkn=1zJ@7nzUMN=*tSe>zsYZDFfvW}mmYQ&`Uj+QgvOd#6vHQr_yirk!ZW z+=$$n+d^T1KwC+vx`3a~E+;DpTb&)byx@RiOL&8?)`8+k!{Cc@@{P>fioO?f%nC`;EZ_6w$Xv=rgV}TVxhn0*}DzD`y8-4mJSo$=`++5736MRMlO5ehZx<_hwT%t zql(re@o%;;AISx^XSv z{j-K#v%-|p<4nJ7ZJiw*X-)ozmmd|!mGY;FvYw9rF4ejU$kOoe0o8atFTu{B=Yz?v zN}h6A|7mwc9c@O|?XWiXOlpbPnsupm|1Z^+Q~N6i0K=&#AUyOTkDsp2jnQj)^h*AT z(ZUXn;FGo|Ek9n#+z}EL?Ts`X_N}Av31GmO1v5~Db3tF zB1%jS2Cy_JE#7=ghU{@!rO5uP;&&qCgXS^>HN3SQO_5cU?p(?x8o4uTI7h(SqJEcS zJ2vwp#N$Q}$z_&bcpMj(5v#5dJ}TqllmI8Q2|2n?OtK2Ua%)DxFwwcN{PY0Eptjnc zRxlUlkmQL)Z~GkIyYSu;2ss#`62sue6p01GPrRoL|B**ys%u>&?#s&9cOHvFZ}D5yPNTm+bVjdEOAs9~vKsnvfJw*(P%dek8LCk#NY!6^_=PH8?!s z0`K}OwOrrJST8oxGOJ2?-)SC~Id@>NrPwFcD&2N_ht6u8Ukzk7)<6F#_WDKq5n@IC zJVAA7`u6;I_WjE$zqR;UO=UL7`YgAZFm^BDL%gx=CK zP_V6!%NlYnOqkJu}I&7f<~C zmp^`_@>{HqlQ4mO#z#L^_+@1^bWUWIJfqdyW-Ad(KL%Of29}o3F?CaOCs)_*c(1#+ z=pRLFOomJ#liZ(+woX2Z$wsPj&6leU>9vBcOK2ezjoCk%jRal&LC3{jgv$CdmO+sH zx4Acs%}1@v?o!gzKG6)2vfj34Y&DRUp{YbPm8KRb5L1@%}M>qnu!ieLm;(--v2`s zN;8P$(E%+rVuO3;SW{e64%O0Zd509I53`v21^DV2OA7l5w8=k*#uxrLt@vru`1rED zsYYtHlSQM@ik-@HC>MvhVlUFanrq>C2-Shnk0`GToF%*rp|k_%j)@AmmWiRx_7-7Z`Ry1`;BX? zSsESUOSL}t7W;HM7gC+hst-i$M)hd!`Qk^m{WaR3@2Vd-l6hre`c&*T8FBlkx~LxD zVWu|I#chxXv)|<*ko}xSef5zVG`pA&*{zJIz#%#0H4Z*DR8Cdd)Y-W|J}Olg3gHVd zd0#Ua=bBj(dGw>(2Ja1CCa$AbIDCh=%sL&^ExTTIctIKBzLaf)j(VrPYK!iUTU_St z8RnIifQ*Mv(CQytd((-A{*Pn#2WqoRYD|&)rxnmTGSthwG~J8GuAokmHI(0fL%?;c?fp)}jRgk$2RHRVKJ?{?G@yt*#i*|x z{(xThAQ^+l)Ft9QfCp5*=0_@VL4^T+CaH}#7%$OXKOOL08o< zMFHL6!-k?lUUI?QPG4S^d@7Rie}CaqjJfjml+eVV7>(Q0x23j5e$M|_H|(RITJo`HGxaa1hvr=-@p7m zwEjK6DqYN}4#P7R$+Qm%02f!R_%?#9a zfUW3QSjf>U^9+%qU!#EM8)O`S8fFy(R5EnSWsA-J?-q;O7dgwYV-G+tES@~S$#ulo zy!GQC$<&9%cd(l-4W~soN3RT=sF}WT*`(p057%=_b->{Wz+t-i*aLQF7iU^=P1=+~ z)KWWI&qn9GdKezvsx_V?b2i-tln|nu^bN3SD2zSJ<@ogSaaXJ#$wa{J_s%4%cn7x~ z%HWS+PZdn?uEwbcumT-GttQXb{HG+451Y_tDA6)G2ZPI70svn=ukh@{9fqyUS)c@8 zxs){;|0f&kB{Gwx6Uq9jVRE& zy~zoIU#0#FEPMH*falQG0HVYs^@p{);m?d+jR@yR0G|$6;FukhIQJJg+x34MKP+Oo zPWy>O4cLu%hV$wmLm~Jsere9TGwMx~4Hgy%9tM6i|}sX27k#`1rS(24NY4VWz6zjihXcRGzf{5DPgLf$@e3jPC?&G&56*=%AA3249%nmByr%W2elmdtd;Cu*kwzXOY`QtaU~af zd61H~{>SaOJV+)tF#L^9K*F!74MQo^Ct%$cQ37D&Yd@@X&IlD%%n21OOt6YqzA07O zT$yGv9!%hw&%qg#|7$gCv1X+b@J^%mQ=hQ3ocr}k_5V=M6s|!5+d2S}lyVelCAu&= zDPqYHF|BOG2kbr{N64N1*NIYW%wfe^5`U~e=3#BJf7#$BGP6ClFgo1a(X^|Qe2iWXCS~{MgCOIV7Y3Sl?!Js!|fA9vLq!2)ti0%qleb{TYVw%9WGn|Dm_*PA39Z zN$5Zh2D#wwRY;&e6D3 z!!$&%0o(e3f^ql@2yINEJAvy!Sjrurg*esc z8Z~a5j3a0)D01o&fvN4bG`*9k-L_%_@Rjum@-kubf56fp^Z?MLFnO1?m&|!nAt$%Zs;cUgA`cEpmvbMI{GjE0IkK@IK zAAXcYi#EGFOT4ebMRPBT_OS~2?W(g!hV-687I6_M-e~VcDL*PSA zBjDG||L%h>%-nC{4=0}DjvXl)_6$d3})plUwx)V!E!8kqLY24K4dF5iBLhf!z`kA7G6O z_u!zxJdeyYGeTgu;i1U+DS>hAX6tbfhM;cYn>WhXttdfR|IRgcGyNj%6Q=~Wf(u|@ ziqGl$8N)5o>7u-8u|xDo`X`ec?T+{TT!frxwVE4GkJtjQ{J?%YcXE)pPWAVjvJU3F z_V(_zw`{kA3MFOJZ5nY}F%%GJdwW$l=UR8R58*cKAS6aU zYf02{l>OSpQzc@@5!PH|F^sHJGJD%QGDleO$-SYGQbnIY8DM`8A>WTHfw;0tSc-tL zyWsnCYBwP}LJ_B8bNq}|ThgQBx;*LX%P)WTT4LOXZ{+{}?_0b;l~2y6f2@RPQhAqi zYUmo)?kr{dJTnI!a(4eia^qGdZ@cL~ysEd(y3a8>n~D((LX!vbrT0Z?)5Q{==`a6e zyB^2L=e7Ct9yiVLu8nK_ywMpIJHMtpY3vl9PF){LbmY#-+w~AyWO) z#(&QC-hQIA&7U&{PJ9p>&@K^JZQHh8QL-T9#m(l9PRO?=7gG;eaGIk1m)9};QfsVFoJI29gkgi5{llJt89 z{G$whDo0a){%sz02idyOMzGYw6xVza%kUI6=LkFAA^ZBZo~n*gh8W1ioVqnSrT`}# z$!0rW1gzYiJV*qN_vYpCT3;J&syjVWO(X1#oNrA{t>*vpExh}wv=RB|M|wgaU>_6M zmHW8kcDQJJMY;sI*zoqr%5@PU#)>E_(}2f&`vadVB<6*CD>j%sJf3Q5t8NwZCQ9&FiPr1Mmfq+9bCP3ny%sdde-Z;xl$z5dBiy)TJcvBZF~@MSnk`!nG! zwh(sg1A6N$W+@V8*}?RgN}`$iL{w7Z@{S!X@YP+Dl0tjp!cLFEu0L54dim`Jx$gNGK0=szMez9mUr7uy(?N-^=Cv;M(6%Ft zq}V`CD2>-3{$S9u`yxXNELSl&xMt{o!k-+C*u{3Tl>QW~&m+}+1PC-TD2CZtKKPA6wDqT$q|IX0I5>#n z7%Rm~Ux~<0JW|cUqQ)n}R(r8K8+g|e15o@L?5L`%tgDQzNH+>6fwgkaSAiqB&CU=w z2?qzeV^FP|Ts0&)g8}Pd{6pORSAOjL9F(CBi!)P*$ze#Cm9ll7KU8wMnXWErd?IUb+;>d<@e|yA;Zmq zH1IpDMegbwA%`IydE`p*_~&D)-*v?i7A=Q&W_v_=|rcJcr$OIffOlx8`)yq76HT|F}Xl!F@GObWcxn1M%g9K@-lgie=* zIhB95_i7=_dO1Fx{vErT(8kw#WmXooU#$DO$;5}{>SmtWVDtWd`ileL_r54lpVcx| zFw{&HU#)R23PJ2Hw86|v%n|hhc%9c%+!sjwkm8B7OnIof?%acWVSQGp`H4^Mz#1;$ zRg>?z?&-qsEKl5X1AKrVTRbr>pEu^9n4OCxJT|#T*a?9soYD6dRgf%Dw<65XfTe^J zwD-{;>-;GC@RQbh<)7&J*@bvl=<96Br$8m7F>t4#rn5tB7vvMP;%}av34MQ46f$UK zX?c=m5+dV%GzB(JU*3DY1T%NIdx}FZir!Lrv4m;al^h<@y`lL$G1Gsesp8f8qECeh z!{&^@nHTQZW0x+zUYu64#!0FAZi+PuRMx6rL9#KFcQ;?pX*}i$VdIwO5KK`TZrPBJ@^@yWR%Hwos1a8+Gb+w_v?cv{x5J8a_fUH|2zrpy`dqhW*01>!a zhGwDZZjKbRd1mf|ZWjJY3$z`VKW(Qof=>IZQp8YJ*v0t*7EEV;LoMUW-y+2j0MV2s zaGca?5)FZSWxb~e>q~CNGm-C7^?|z5%t^|d_0LbQUQb86`26p#Ge`J8T?aP{I^oE< zBI%>wRN-bGjR?5BWsP3X&2>hFdq>Nc8_Cu37j6i-T z{6hxbyTqa{mg+AQ6|K92?mk7uuUXfsLLEy}R9;v#t-&I}lHKT>RFWOUNM>%CahTV3 zD2o)hY&!`|)$STiyDouyl*YeUtozwPr!UFQ@xEp@AyAudGUvvtUmSdQWpO{Psd+6c zDM8C3C7B0#Bm1VOPKnJ1m1VTDVn3;$PmUiHb5&LO(lhN;(J(naor;ZK$N2EI7ertIf4qq_uvWw6+GcpT9-Tj|5^~d+NyMZI*C?OSwX*S6kZi=r5r#v#k0y(L#q9Rz6S>_k8bnoyssR~ zC9ul#w7D?tOFF~AO?sZbn#-^|MYo2f@XU_PVx=E(K>Tuw^{hgStJX3QPh`#!BNJOw z%syvZ{C7P{G=?%KrMPDhsa%}`61OaFto6D&a^s+9vaste4;!@qKQV#~cx#r*_vAG+ zp!t404P9?nr)Bpub65f8cb9pflzAP*Jq>+-O(uX)J&Tcw(%{}>ij#d+i)mh0TL0iH zH?@3Q>@=6E26i0M;3n)SHOR2KK+|55{Cor*p<7FlTU%v-m^;umDp%9iZg7a*)0=;& z8}Ny<{b72JOeZE%k~q9=e_gHcap@PNPQm`&7ZI)tzIWHy!%0gxJZ8u0=mqSJ>uv%H zLP-3Ct8DVKW%eYBIk1}b!In@~`n5M(T@Py=r@#S-WDW;=TptH7^Zxy)D6rC-E$hWk zsKA|t0Z{<`u+9ZU#PE^0HbiXS$lDNGo~b51*%1o%DWGa&6eC&m=Q;B#(f4o-k&ULk z>VLE{H`h5vL0zZB1y1HWj53GzS zxfpeqBXT<{LDuq4x&iXl@`j;@M_^09aZRwAY%p`W3{$$q#N3*~g5Nj27cUe3^pdxC z#Usa>529%r>T*5HTdm3VW~>%Z7Y$6W#Q9oNnZ^!*UYA` zKDrx8Nz{7LFN!_)!6|%cP6ge$_MN2fh176XK}E=ygPjKX)t)oW2)&ZQ?YEoYfrvb1 zstuSaD9(fBQz@@3X$+mtb^(G$P} ztLLB@+(36jZbeAW(d?xoHmiKxyB|Cs{e!e(P4e#m9q&8exFH z+`SUZL<+>hPMoT%XItIo4o5D`JOzkLqSj1`#`D7zVkRp_hJpG$eF3d8wtM|Z#ofhs zN^kOQ&8tohzJ#FZidI5I5Z$Y^K_}fJ!Wvig#~)9R92l*?u}qiezwh{>u$zf4j#W)F z>z77s3_0Afe!t@!jCrI=PoxxIk6DoP{z|4NPRpA+mfO$xLzQm#-X|`r9U&Hpj`Vb) zUdh$mdhuZ_@Q21yZpXpkCX60K5Ol(k@iW4Z$nEmgM&s^6G3ufs01E1td5#>G0Hq>+ zd8RJGql6Jy^7&gr><*KkpYZc6v4oKty~;$qG}N)Xa_$-_r6$lQ_KeX}to&Tm2GGK1=9Hz|RJH3wc zwDcm}ha$$nWKC($zy{M$md?Aox+`y|tnENL?)}t0loumXdnCS_o-os=Lz%-r?D&6D zz&%!X1S$@q<+GAEoEy(S(bp6~l>oG{nm|OuJu}bVdO`lA71TQ;?Z@!JcA@IB92#l;O)VZl5@?7 zwwN9X8tyAZBv-Pf=I!?1h(_M@xWFF4c3FSI%GIrOI3TMv!sQLNBevR!REDqLOqDXg z9@^fa=%{pNfE`P2kDd4~eU7x}wNESZvt{4wVKU(hAc!)KGH&g5QM+-y!L@lxmS_}I z`GzZ|&UVm=z05988{Mrk()V#HNGiB}f{Z&80tZ1?J=`n4OV0nk+NmlwBzM|e5! zYLzo<0d3;TuucJI7ij6qf$H%N7xVeMCsw`1=p#gs*i{nvN>RZic@4oa4;~ZZUtwPN zgg>Yee_CG1xuIQTp=htLCzr@8`PKhh+Q?$_)?1M6+*pi@VWTiI$!5S))~J|Tt7cQ~ zKv*MtrIAx68#M4dk~4UD8b0p&B~K#lg^J~_N}x1y_6kT@P%zy*z4dsej?Z(0S|Nr| zuf%gf@BegMFIY>^?gp%0{%)ISu^Gz?wKHU(kPwx4F!*4|vS@)8Qbj31(7 z`06WOlbZEQkP(L}u?l#XA5I%@Av!g2H#8tAMYYO>$M$e~Kn7yeHtZYAD~-$);qe?9 zd**R8H5vHw^>W9azlpcb4{@(7-7U@sG7y(DUlFRup};!tRB@@E5UkB6!eNNf@iW8g zE!|vsBB)c7*J?&Y)(zG(x9rA)*9ENUsO97s-V|7oI{gJOGUH1X$9{_@n}FM!)FVs||}gq60Y z|F!ODg64n& zIUbCtwhjP{!zx<#7g4@s!9mwhO7UvOG#+M<#BMzXR`u4|H1{t=eu5V8Cp3e9l zs4oG1w^uQoq^&LN>BP5bSxvKv_dIGIB|@a+umn-(pAtnWzY|CLQ{W*cE$}~0)hy-D zG3wtZaY;;|uTc;OG^-ODo|^^i>V%9U?-n|&9G zjH06co+CCQl{E`>B1(`gW}mYqWhjZIWBX4QfPuO@Lk=+qJ9;Z`40WVl^X><$*Fo-t z*N&oY({y)+8M{F>XYkG%kPUG_5?$s5SLkgc$P|&QBXVK5-2+94gw^{w=s+sL^GHej z&f3QK(rUI3r}z@oPMZ_{PnG<9uDpL#9~FBchQln#c6C)k-y5}6E-*i9Z7Zm}bTG2O zq!~j^aC)3CVO(js8~A>GAj}SuUzncU)h+PE|8Oa=pQ6^8ASWPRIn>*V-GN;+RZ(71 zVgJo+T>`oeWOw3}oE(OPkaFw4*{B}MzW(DdDd4T!A66AR-xJpW(P?g!LPL_DC!Q7Q zWGmN*T8-*|A&x0AhI-bB%)_Jx;l zkgimg?HmW;ay_z=_v?-xeCYsBk9eh5yqPUyXY-QYW{A-VAe_iVi?>pY0K0vd_hpl1x%NR3FCN)GPgY zz^OMrF|j+B zf3A5&rMvfeVw@^kFD&smBt)9>kcf=T#K$yPV)e@_k!BEnP%RiURg&RU?eAsHxRlCA z3Gm|x1z;HOZFX_cK&FVW#`&(4tdRc5LV5jL3A}pNK1SyrU&6?4G!3}3)O5SzhtuEA za<{FytfYL!?PaU%fs)rub>uVGkh6B?fPw?Y>@T`pJ&M(~&L#WnQ)qQ{o1KeeCfG@_ z*Oe;PegdU{fF=uY0xn4f2HaRpNqqZz3tyhZ0n~|YQ;{=_>`b z8x+4TTXg6CWs4T6^xkpbl^J5J>F%vAF9zA+YVHdO7Cx@>ty~N;FsF#6C(tdnHpi8j zC?D91t%^YApbkH`*G^?0Q=|(|qm~%l0&jPI?z5C)5c-MQXCp)Zo}bA?gj_Vk2E`|g|y&Jr6 zfA)wD^@mI~GQWwD;Nn;YtFw zLg{0A1u1Z@t7&b6v90{ozCHqWjjs%)*-f#E$+mzrde1+cWVlxK6{9<5p{?8$+4}7{ zX-}L^w-c84RhPu~iKdRfQqQJ+rU3@E4bJf81Sq<+{RnFSqPI}qIEA~-sp93*9K}sG z+h-LS&)xt?=U-g)?q~1dB2aMPPWnaIs$S%uj zkI2E%9Bmup<}xy*OTc1icm(hY?Hh+$e~Z?i|osDd48ZCl|04in$F?u!HRS_NW@Y^qNGs0XxP z|I)TNac_p9=jnhx4|S5mGy7s~+|J@3scx+gt2|L%ew3sTX=xP(2^MV8-`f{=v|gO} zM&XWv3R_nvm-1#_2|1#{ANuR*toBfM)bBR#k<3Uk%MJg?8j&Hf&J()4YFp zgVBAOm$9JnXrWAT+Vx)w`F82z>|)2yFPXhmSsy?nnY#7L=cjD}=!h0}nQT9%tFU=9 zY0YcIp-)Wf&9$q(2DmgjGdP**=rrG+P>9}(1+@XIy#;)Ld%9jKQax_5$Roi4Tz(-o zRhqm%1Yr&Q&NTrzhWPm8Z!Fu>mENwH-422BmOVnuz8<~s2gPfyLbf+XzeLPIeHO_| z&Ds1~jhp?2_qFfIWZRAS`3(oPjOAf-KGXAGnfWe{hdNDJ%2bhuT=X^S))kpDr3*X{ z$`O21cmS#N_1J(E9o8wuYqg?&-p2IOeRjXq*PyKsv*mClM>1cQ#NRL8e?4XL;nCaa z?%CCz%`yBmt(X6x@8QdhTlMmaB+UB!kH8=b*wyNPbfnW~ns}ji2a%GV?}DNdCGu&yx(SF#we2MOA60}tHZH_KJ@SM` z0HdXL#*oouA+TBqRprKp(0t^^Es>F#t0AKaLTVdK_8l3$jyKMh7;V^)0|*$~g7U=Z zL_raqbwmbaO@-|8kZzHEkT+g?K;m*cp1y`GxI4PDNYKXqpZqGa)mm|VSh;XHd3U21 z(v_+r-L0!@@8f4HC3LrrBR9V#@pp&h1GH%=J!Pvd#UR+Sn>_j_SkmSK3KzB)avZL8 zVG^s1%dGx&tYbOqy?gv2>h%g73Twnk8{VcgL&i&m2JF6UI*tBCy>!+ze`S%5E2bWLc?)#l4i_vfx|?oaxyqT?r*F8HQpA(SNtelvM-7X9#UOhI0%&Dv2%tJW!2R= zu}9sDXjc*K$p?S+k>S_g=)m!ZB32OKYFgRYHsZ7O{*edznS8<6QR2jQrsq0mJn)DJ z?|4<#W8-?h-wQsAqH%?Wx9d@&8z}0>j_3du*}=E4*=iIQ@p00B=85?*b zK!W8Jx0MLeu+oDBtPoQ?c-Nr}U>&1M{k<*m;%90%AgCM}u0kY9z_Av+>qTJnuy4fE zEA~_5_2=H?w`Z04U*xp`(7eoe0S{pOLF2}C+G*>V^Mw#x9Ad#?nUN>9yjb7n=DrBb z5Rdf)g=xwz|Bx4}xCh`bL7xSi1T7^Mat!kiYsV)ZJRaM<_39emw9tA6vycS9zlD`U z0z1xC`G%p-hJXiQEaAXwObDb&Q>sM2({#NUK#Pl>|22k)G1H>RtTZKsm$-jy5SB;{ zs~!z~U=|l{N7kKYUe!`@*Gx*2(>&+BlH^gLcT%Ffz*=|A!a4I)@$b44W7xT3E92IQ`oKA0pSzP#)OzKn*?5>!llO%Ev}>=hWEMt-%ZcGdRM$cYX$n z)HR@GH;_epX9v6Vu`@#-?>$8?I>LY=>HAoO2Vig&t+u9{SaI)I>{G@4r^e6~ba4k* zVn+!MK<(D>e(ZBcZcsZIc;Ic)v*xXQ4`P3Pk>31Whx|jNieBl9JX*b*EQFF?`)FpU zp}^L0{n$v6=b5;Oph1QAaS#zfrukw3pZbplppobNl6tL6%QA#DMYQZX*il=rDsENo z%vzyw^g|L2zu1=&mB0zf33A{35ZD(la!DLJ-wy|uAHG>?Ck<=G1Ap80biQ&9T`W7u zv#|4IOzC*qh(W}jM~B4sNDly4cJq%OQvg1h1+4tQeBv_^ro++_eC`}W>v4g4V`}m` z_Og)79zf<@^D?rHttJW}!s4!jT=~Tpdy;fO7x-EXVvx#E5OZL^M{udw#5VMGM6?yY#Gf_oE;z9MVsF1| z)koHT?{CqtypN%7{`2Nyw+_Uy*KvJ1TAyf9z#cUBhjvz$?xDuYm?DU*tbn23a~xM`wX@MOgFz%E zayFa=1b!125WrV6)HUO~Y@2)GHL_AjC876d{lh|`_? z@#n(5-bof8@84bRdHE4WHb`%Jm5{oSRebaUyOH{M&}pVl6LtFaVGfpqV;-NS4jK0K zsup~?qQ5eo;9*>OA6DWzsm(0jCdtvXuTg3?PsjC)s_EjKD+$>JYPKN25NPJS*=?E^ zNc)d$)}9SjFZ9EHe?2&+)xMSKz(Pon+5d@;?X>aU^NWQiW|ErrlOH4~YzF-KasWxD z&DSjF0KHJkFf^<3X-^}-+Kwne4zMt*u`o|5WY-4?WB#8qJsCpT+XX;@fL|7fNeyoO z!DeK8vG1PX%a@ZZ+I?OFKXV0A={6_HeD{^1PIiM9L6#2_KR#WptQUuFE5*N={&=_& zQ)ERQtq@bFY4J{K_sVXA5^7Ftac@}Ytefs>zKUbe$Pr8`Kyjg*W!qZsWb?ssoEgL4 z${^y{Wul@d>T11E%Z4nZ;dT%98Bppk^&djoXyb z_qPHRew{;7kHH*#)nT4qnzh%6f!RJlDGfuvt zxt&Ei(%%sc$>*;%Zc_RK*5@_Fq0Eh&EP&m)+rlIsEWO{O$C6ilaUM351po`BxD|pJ z^3F(O;NBlI^~SliUX{I|pQ-5!8TqPJAEg^!n<;X1M;kCsX&=Y3y>C1k^xhrpv}sMu zx_*P+0xj;@Nx{taMf!)i-xjrkv#9GEpX?plZ5UBFsj*vVd9v`q=<~Ld-&=%P-a7o) zoyP6-Qe*`EVncGDR71mYbL3@M1F=$TsgN1xukcQAlG$$UMY#do-xaV3fQEkY3mVk! zepSqDyZURP(%*&$?%Y}Q!|qe(YD*-WRQZu_S`Z@y_{-;!dxE+14wisSf#6K z7{Lm}xIWyL27xkXtHWUCb}jN>^O9r6E7&L);TvO0VNXma%Y)W#I}u-L9^M>#nkBk5 zvik9!U;%IGKUJGrzs9L8b=FTjj*vYlkHbLSiedP&>XYA#=-W30&E3v?ecm~!rftvz z*`_AccMu2c(|oN2CMPONI^21@YXKd+L(gw}12*MtHMz+xn`2e@vRd&0v#i=goBJ0y zuyW_#bB^v5y2qBXX-p%ff08b%wW@Trs=rrudr*{eT3;8V=E(9$T-N)4&w5%7Cna@A zv=3(w2l|vGO8!;R<=x#}s2t78AH0?G;&x(!=PD=feG^nl(8jOrK%oZ1RC6`Uvh~r} z1mm-l2kMq!;b#u>spwzbb800u7Vtp{0mtFv{Q)FxR$VnD37i~KrxZ>C5Am7+m)!+4 zP1b?nJQbRwbi|KYrj@lT6laTpI;dBCYYDH00GmQ=vC!M)6=Q{$V6S%fQ^>rM?Z%Hc9Y^2x%0I+ggQs-fO7cK*N02tl#|0MqAn{lx4GFgZ_E+bAs+|Fl6Tc^4ah zGh046(A+Qp4}2Wt1^N|WqZgFv4=soq)qmWk6k4rdAr6nte=A{gr|$Sii);Dhf)A0; z;;-yuzun913<`obiuy|>EFJ-p1s0$a?*KaS*1U4dy;zOm$xdEgXX|_8K8m`<{-HcA zUUQAlyP)N7Sj9?9Y5Nx%q8E(78(tP>4M`*<0hs-doIEj1j`=FTpRT^W9;(WBHB)5u zUeimBY)j*EBdgUVMvFUe5g2_)TxVpMdC1j^)0h?Eq9R`S(9l&&E3UIt1Unu}IiwOR z=*`=GBX*?*0PW$LJVUc@a9jfRIABbq`@T_%`hmqq0ih7tJskQom90wJH!@9F`O{|q zo|evN8eU)TyqP%-+Yx;_9%sY_{C%z~zx_vl%LDv{o%+6qY|!c6$APWdTY&r&bKVMB zDGLczbRW1D9BuQ!WjU;m40j9U@AKJsD8b22T^Gsj>m$6n6F4x+Aw% zf#o3;qDR?ZGbotSua&FtUvowb%RUfE5x9MgpBG1C7S&olwZ;;T_cMkYc=F4rnLPkzIe@0Z;P`W29DIC!g@&QFjo@SrLL z2s?ycy*?SoZ#(>zGg3=D%6jbcE9iv`$4vzl^3m!703m_KzEK>kdky2^O9c=h_2%w< z_CjMr`k4=_JzYkIbGUg36yIF_&|@Ur}(a*6(8)a<10^ocXv9svCUmx|tY zl}ZZS2~s0GEtG!yE6v!w|Da3e(w~68WO)5$OW+C4XV=;^o~e-jd*CV8-c||zB7hIf z@#a^@QMo~P$aTwt&9hm!J5j{vJn7O0K3mlM?zs)kIKuqa}A{I~#k?aYhI9G~K6#TT@18!>X?hBl!J+HY7x8F}>L8&GCe$aMM2FRI$gI z&g)gh%oqQV|10L2qu;kLNujlRIdviPpTmC#KKawDXT^NOUgp`47I*9|Z^UWqacaM7 zH8?+At{57$4%nSrFZ->)$^4IJ`Q*XKcD9j5);Cwt-4qGOs5?7OaPbFXF$=E>Jv^i% zkN$-Zs;gc+DOEiB#O#_I5HohZgpKcrV5f7Z?KN;$w}<*lM9{mpuk!x^BCz?v{w?p6EbPV`VV$BB{?4t}o%8$J1>^Lh& zUN=v%tr=6y0iu2=mDP7`zK#husKHp{*Zr^kBx=QLJ}e7=;VkN=AuqXLNMJ9!H!PJX zQhsq(o%vEhBVGceT=EN+5J|`V1H-y^Jimy4d>LD`EX6)rBqShD-%S5Dm_Y>CK_NM_ z_Z32aO*o|5S_jL3*!PCSgx?CNWC-%s{+gYb5zmz4FsvJ%L$o>@0qyMYI`frsFYU)_VCF`;)AEKhUbOYEjYIuA-XK>S}}H?!vqwFSufKn6p?} zNGYM}gMv+2y)8wAcj}XMNdaAaGFYv0)f*LC_8i>`iMUH=a_eGFJu9>UWF+mmskP~} zJ^5MQ13BCi+c(H)bQ!!+RDt(&(QDRTCkaEh+R3jK>zzim^z|{jxz-bWh@Wo4bdl|P z7;%wQG}a;-^@1)TMDtL-Di#-UpF8?nDT|b#cUl{lm#1C!l0+ zQU_k`6%I%`TQrU#?DSuAr)P2B%(yuD%)owJLsRUx^W1BXdv4*c_kTxr;Q`hkrbiuVR zboOI!1-`sxVt=49QTYJLQ(P}mcN@+DNWCU?faeXP4V4+A^Y+_tnd9HC+Z2w4+)BNOio zm(>LHXbtOx1-T7g?bJrTzFje8#Nt#c!o(^tOG> z=J@w}-2-vK!$6^~XbnY#6#N=3H#OlwIvqTGIBMN&CbJaHQ>dp^Q&@?aYlR$v8ySVM z^@*VIRy@OJU%gV%%N_s_I!LJzk%@oN9JHvY)D&28Rb%@y*u@-oe8%@=c%~Y&6fO;k zefZ{GuN)pc5>3bXO4pR{*U#I*BQKWZ@ShVCw&*?g?jj{Mw(3%N$#`E;`=23d$N(L0 z6)g}Ts+Au-2Sv?ijXbD{mJgroZN#6C%z5-hk5H?CMuz^>Fvs#wTbUJi6Xb>^{pE&U zdZ}*?Z;al{sdIzBc#su@o2i3H`}J5zvA>rT27JT^(}nT}eeCM>uENjdb=UyCNxV)l zkI(0Xe{Z|OI5CD)R9b~4$klE%aXi%0(Ne13 zGC2U-3=|gBxG=4*oOo>bC@2u*s~*HQ*{YWVAj`^`{+?9UX_S7&Rb7yVV%!RAYW%Om zC@L^0|0_5u>We}cIgNd)VN-3xd1fT*O7M`5rU2e3Wl${>xjWa56z7Q>cR4*fH(Q*y>_|~jY|7KnbA=S{oe8Qtu_4D$r-sN^CA41ZUdLCx(Hkv$ zVMIH2Z{_0`Qh10c821_kr8I^iZX+hoSM=R(PS)}9dlfI5IhwIr`5-mo)qz+CTJ=*d znZr;fbIj02bjZ2LK`{#a|5vO5Bak+xXsIT&>nhzl#M#L3Mmr9B=Oj9Ne6bCoX&V}-oo9k7;TZ+JDhNYWs1Cx?)noL_#!_~A*S^~FH(u^YVb+B z+=w%J5nQ+FekzQ70SR_Q$-BJ~hG~bBZa;z%0K+_|t$N~SL3-xz#OST>?|oIayO|WH z^_dVDD*>{6TL>xpTi-qNe`Cr`GOo%?Dyw3*%ei#u>1<)r3eoPeUL!K6ie3paB)mqJ z>Ng76hYEpMaPse1dNOtnp|P))3eC9jiB37y`8uN29sw@ROJUl9ULdXUK*QqPe>=zE zQa6+9K>CKv(lD2w2` zFMW+bP9m3I1iFX1`p3lp6iD~r(itf}o%aE`+!6$;sqPi+6uRV@`el-J;vebA`>F2K zZTssRE-8tCuS`q?rz* zZ_~GR%!Coe#ncC6GonwTn=LHMqc0I+=GTal?#PiP+{F=1OITh*pIkl`SA;gEVcU~(};BE{SYaDa{5KTWG&0CR&^&`YS>=z z36LV0u0Z;gzZ6*1+N3vifnWP^E~-@!k8=?WmhSx>DCuR{96P@elaT>W_&)y?@RC=i z-8`~Bb)7Sdsqc3rrYVI%6=HV$g0i7O8G>LU2AbmP@b!U=R?CMNg?}RdlH+@x-;2$J zB#eU4K3lq5`r>^d7tc{2w001bZ&3cbUP)O#pDtUP0@Ep)vY*?}+rzgoDZI)unZf6W+l^Nk6=NA~c5sr} zpcR@wx&r_uWhmWRhmi7h?|JTp;pW5;rL7$Phn%>y2TJ$t)S6MEUO{=vz%Y|Ecqx*N zlcZuFY##9VWAZ8j!NnaNwAPH-%FfH2^5%cGJuSRX-d*Dm%aI3Yc9}~d0G63x0;~>G(&tX600QcFUMzZ+y=I$wGP_;}|=4{S&ZE zmj6vfnoJ@BM@#Qt9V2>uK+-KqGbelieyEY51*3E7Xh|*pdn~b zQv;fXsuO(mK_+ecT?%r$5nHCs9tBT9Sg)exau=CJ+m($x;|Ry$zU59w+%*o3E9ODn zCgBuJ&+0Ubw4Ebcf~Ml!uJ3PGoITD76g-1wWSptR(2l9`>$(6kN81tX093T03yEWR zFmN#TLjrR%c1`%(H%~dcwODDeZG|d4_10d|7j^jI{h+^B3u{@K2l0hL@DZ$1N zQR4phm+21IR=DTgDOHkg2Mh1`dt`sfy~?fS~*kk$wy zqfjyyBGN6lo}qLCwRDRGyQp~Es+@jy1Njy#iSP1N*G*%2)Er>z|GKUyv;RS0jGyDi zTz{$!Vdd_(g6!@g%Te1Fv@9JdrFN;yf$jDjka?a>*gCw;B>Fuh{#}MA)DeDW@OoRH zmD)dIV`z%?zzuh~$*+a2+8KF9&3{UOZEs{b3;@ zIY)!w8`KHqgo~z;K$I98ph1AlYr0aeVtF{rET{3(q?+U>7Kr~Bmio9g<3wEuU0WAs z!1r(EHb7mIU~^D4@x{84Im1Hj2og=nw?BL1f9EbluTTQ6Sygod30PzRF3l&9co484 zV!#O~l0dKxM4~!22B!4d*<76abG?DouFmAkJs$?Kn?NAl2^JT2C8CvtQh$D6u(yAO zj%WIKc2?NrY>CL}hINzodP~agBBCp5>;70`4c&hRS~{?mj_AM+;!70_V_d1}@`+2Q zBg?n>@D3(_sGOqAjHtU8q`CejX0Ta<|Jv8D-*0U$$?xKb!>L!eb>80}p)<8sySBCC zwfFsX8@hEKmzBwNLssfZo$FO^l;xONa3K4`J?3v_GP!|%AoTA(4&fQ0XeJVus3^GV zC=I@L{I4w$0!+DYGB;H#Yuf$ZVhiC{vcU)6eGnd?MMgH501OS zsy^?1@k}9IfK6z{PanvvgOv4Vpw~CY9(W=Z{?f=+j|U?%5kPp0siqmah69{>X779NC+t2UP8&9kLqx<+xy;2jLwI4i41c8O4T80*#^;K!2U( zva$2`)e=FO0$EAV?$yNJxCpAWq*hQ>Suv!dvpbX7-#0{Cef{>c7dCfU zdqFNZ*8sD6q#gOkX#-S}-7=Ssp#i`h#1+!}q2PU|gdBh#H@zRRa*i1>=UJWhdlq%) z%tUc|sTDsgbNGoG1i8ol9w*>~D6?GziF$wVBPyM6TQouESbSVLNM`p4nd7A4)-vA! zmbs!?gs&MkXyau$KpL?-1{>=Fc22t{J~*yEi7~5n6~>HBdYYV=_Y@AaUz|2hRukY& zG1S1w9~+`4cDeo+jV#_Is8qnpc2)FfyE?T(o~RkOF?`i5a11+w>!K27zt-IrCfy|P ztS@PjL}z*QUak%Y`YaVSPoybVb~!r5oVRoTUYJ)qH?}AM;|bOqqWajVd71Pwx8&g_ z2PAWu3DQtuz26xizDK(QKP?{57C}4M5?)Tsl9!I|^w}*)0@LUh z4qqvQF8t1q0{tbO)}B=cNgWiXKAymvC@W7I2x;4SBeN%erPM=ZUA>S`KmY7omPH-@ z>N%z-Bq+bm7O15O8y)ugvibeb#Pkv=Fxk6*JG}N9Fu+aRYI(Fgxm}^d`-oX1#;WL{ zne=bsy#*g6-bZXuOt-s-e1Axc`tWCMk#XY|H~aMFL!OQGm%?4#4+>ou(k;Gp#xhU~ z)%gpT>;FG=ePvYCd)O^VDX9X|q9QF_(vpIdfHXr(4IvEOph$yA=OEqP9ReaP-Q6)F zF*Nt5p7Y*&?pp7M`8X_Q=Ks`w_TEp}pybw%ZKTyC3NC5djh+)lCD2`jIfNm0x&QLW z6vEK3;y={8*BtK+RkK8WbifaM8KF+{_7`VQ&-Q^?r*CBpx8>JWYhv}n#ii_tNT4hX zDO(S4q2Ry2IV9$NeKx9k?P_XU=MN)ME3cSB6locIUvzhK4d<(~9J}u~M63jB1wY98 zR1nU;;EQHOQ6Z(gvAh(Z#gNqjk`i0XW{XA~tDAT_N~r~CvR@Th`>XLI|^*f|;zuDp( zHX#q*E}O+LZ6hN7u8zS9?m!K}|cWT`qwY{3!`Sp4@a?nuR=+-@YO0l+>;?aF1p-+x6t)vS>9?yY8uTxwQK&44+Gi zY~wxK7ffaTFcVUs6@{V6HYDX*?yt3P-*=NQRP z9}J+!+5xg%U^Rg37dN?|_ghNAPA`VVm5y$c%oEN0(vFtK|G4duzeU`$rG&L&$oAQQ zFN(r6ptBzC^|JAKDe}8=f^qD)#k)U|$caI3cJj*mrvGq1OOC($_5@PTlV_-^;NW=R z{Fo^GTR+duoS?&^+t@eT`?xBN?}ncgx8PIW_Er+V1?2~np1UQH$g2|_FH>gNzM53P z1D0hojmPu>gZ+q>kwtFWwNMNF;q+vk@%&Dt_1tu=7*Hasd^);9T8L8sh>V?CSlA zp>trXh`3rq&^sWC;VTbp_HzWgt5>xD#YzexGpmH#LP$W-5b+$<%dypmerQz-3_)wY z7Pw3>2b6^^(FK9-utRiW>T`}1}H=f6bNd|Pqb0bTq zcKa3y#0zY-W(SM!0Z+vZX+15;LOQq5m6seP;(6NS@U7Q)9|(!}k*c3z=>vsYMDGTB zE3)yv$7V5R79Wh!M4$jJBAM}auJZQ9ggQ=U(pnR;mY`r-$!cc3WFcD&ZLxYL_i>gx zYq=Xw7;iaMtRODB&)J~_A}A+^YdtizLcKt`0)@ERX6>?{ncG&eLY){iU9R~~SBfQ# z>89jKNxdGrR4cf77euqEHK(-IZbxY+LHMdUoVML;us1Yx-vQxd&SZmhyny8RgF_{P zPCiW}i&*j{EG4sG>9n6ucR@R=N4tUd=QOl$&e@W6wvut;S^$=`Yn4drd6H0df#Hi{ zZ1~e4@%C1q*n-zg;-G=Q*i60SC@NQyv7!3Nven66hHRr&SV#z)Y4Y~y@apR8mPzcU zkrycO&y^S6LHD$;SuaksX1vw%#Em(}9PhR!XXx0VhEsCfT&t5-zBQ{*N&(FqS4#Z1 zGQAoCoX&1)RpW_1QX;B;SC8&+H)MZ&n^Rf7cT_Ep2$ldf1)mDeL~xTo(6Pqpk3*v_ zj~%+h`z9)|hYg8;&tz=`|0UpUcjTSyjrmul-0xQ5=qo?DafEyzc@sGT5k4$_H@9@zXSBnx|`cDhC1#9L00@^n)nDSmguan;}j z0E1nH=l5&hFN@dXlA{;uZbg{!-Zd~P4*$7vdO$Q}U#^tOt0278%jDav*W~j>Vyr~e zEgFU`h^vq4b#sUC=zjS1>3i8Vfv?>awQ}@^W+zs~W4rTPA;HT_fQ)20f%Tq9;q1Z| zhJXTLf?!fh+xFOawg0`tZxu7^Q)Wec7_6!vJ%jVhRM~G=T4E#%S?qh#+R)luk=CGL zZtme^W!Z%mi9}=A7kb2gei7Zt=OTQxbMKu0ov22%+;W@Qs-6 zaIKr9YABY_Vd%AILIP0EaENxwTuXWg4O+M%$C+f6!LO;Y->-mN@s5o^k>9@MRei zSe_g$87~SXSSUN*DcvD`1-h+4bkm836XXu&66 zzixJSex?n@;qoH@6Pi%70>zbPsfq`7sk8$F+_?MsLb6~SM}fElx3T+AgX4-{9{3N@ zt8LAiUer1+<-j@NG|7<$BEBeKP!!cz`+jb17$8>icT>oF7e&t_GTWe@Qb01J90SK( z+U7$%X>k8METWnHjU|&mPSNa&3S?$uowG|E*iQ5%z2s<25gZehaNvG-b==3s!-*bKT6VMGrAyM%FB~g>ce)ei)dGd1^wB7Xi7{8+Dm3{$ zSrJx2vG6OKc}MXr$I*+M6WzaqscDxddB{b8x(XT~8o(jgoNxYh?QjF$SMUovj2tzJ zE)N1`>p$htqTTH;fqQZkMf=zts(GUA9%dusFH&v#>aJ{CZfz{dMjIORa-+JMlUF!KLm_~->hl6gF5 zX97mhmOmXX$M*JehjeReyC5}!6>_vujPrm!dzUjYG;9qq|4)Af6%A-F6w`4NfLmnL zrJ9YDK88&?9Ci%`dS*8kO@u`p`!>6oe)|(=p5yyuEzm}V^xtAy!QEtH6Hoq z9G?;Tu|<)%ebyh0>L=QNX$0r*m_#0G*1j%!G{R_C_(j6?lqeW%Y)y!<>HGPB;Q8F4 z=|k{>*9vMKA=YaYyj49nStU}-Z+8!qH0!&R7iiR6M2zirFVr4A zr4Nwpg-%S*;1e^eNUHFhv6Gs#PXoau!tUmZh+lc_0+A59G0LhhkE?Ktf=9(W_9HF_ zGS&36sh&GtJWubrQ?6Fj9arhIRYFG^2m})!-KGVCaI5Hi_>U;!13IvpI=&WS4nfoz zzK0nj#x&4Cy=@+JoPe~}JMI_mDZ$r0llW#XD7`N^K1FAG4X#8~w3OXq9Q~I?cVoOZ zUzaZ-0X)t4hwx!Xaf2OdOuItM;ZBBVyk zpHO!oupx}X?(rN}QY4P_5cKxs^Af^)-%DN(pjqzcP8?G_2vqddU6#V$?!T zef`FGeIWF1!{U65MtYCAxN zf6lvuQ7&hY@D{39s@w4>0w61T-_DOus?FqaVJyI21ksH3uyoz3L4(b5I@kV)A*_E- zfI2LAnLle_ew^C7RM?>u&>ai@s<>1KfV*Yi+lr9Sv}aeqwWMXElf*(`**RNYnJ;H& zVPRgI2jXxP^U(E!`@9Y8p!3Dmd7oie*xOyT+}25ejtx?-={|#CgE6OqzZ?UcfcUx2 zV+v0(?H`3&?tOdA^M0V#JVvB@YBWz`#4u(y6eO;b9ZPeWzv%2vSxo%x#zTBZ6^GJx zhaWxsmVh%-Z-Ir6;(0M0Mc^gU6^g1|39MAOqU!BT9sR*HXrokTzm4om?(slrFrSVt zDXA!~N9tXtyFdQmRZO&k)j0U4U&%Xz(!Tx9j*zK3c}BYW+?e;J?DF^}<)+oV_d+s< zA;b4LGw&=_>gVpfNQuJ#E!(ZU+Xi|tXz`sJZN)%iu%tWO2oNnL6(G{Aes;v8m}tBC z6c^>0O5?Hm;;Eh4%Eo>}U0v4q>8i$VTrM+}RbBs%01IyW-S{hO4 zuP(1JmlG>?{dQ7CkyeMq(}sU&Q8)^>w{A4_6U`dcG8GYb#FZb2iH`zi8D?yJyiXxKJuS{p z)9DWPl=gkZ9HL*KzINUsj&bZ>US1n3>Y<5fN@h2g1NKJB{l`6KS8l1^lQD5mjI`D- z_A5ZA(fO;vNo(Py&=vO~idq5}mdjSwH&Rtc$tSY{GeXq1EqH&n(ay7m3cf`eKpJ>e z5I!V*4QsJU>7&IFj5HlGl|&~>Tk5S@I5(s8ymDOkDzN|c6oYa1K^BWzFkC^+DLm2d{76l8Jn;Yy)wD3cvH|-;Q@i|!y@Cb8qerfX07Id@ZJ+|&T*@# z#=glE%BzFs!&4sH8hlG6_6?iB3W+xc8*N%UrzFrdF@ zDdFaO%)nO#dE7yoH-q%3sl8-*TMROhPlyH-J<2dBI#{3dKOc3uHkel^Y| z=kAjUu;sTf-j-diQ`!xaDb7?Jtps;RR?ATXh01L%z_ml>Toymb%@`bQYVhoelpg9? zb3eB*OTBt0^b=*{zIs$tM`9Cl!I_VaULGZp`;KS70-th37lVKsmcDn98NLahTK+r5 zwCV1nO~bv5?#_c}TYfn0`tG}=-GEEiDEdcU-xHG$p#VyYD@xB+^0|lf8@Wuz;$jcI zDNnE6&AcPXd1~oYAgT^~*t;`k`@)Vpzv5WeY;BRJ*FQUwXYzlIX$UQ-(LVNdoymvo z6+Saqd;yz&Qm^aDQ)Q<%SXlIJjVBRS?#zZP+x^zzdhI$;6Z$E2U@)t~HZ8dL;{e#K zF1D@DtD3dkHK0EEN;uHpZEWOou;MEnHrnm;SfZ~fhwOdzgkHv3{n%(>k7JRt$eEq4`qt01&}IH3bj~kQIxIBRQ++OQoI&49R)Ui_ zTOp(8i}KUo!|a2avNHL=H#|ERXJ&MS4Px@R6P7@oR)UAAg>IbvvronYXd#eQy^V-n zj??FQ2dxVfk>c%w($C5sXx5ct(_wO^DdoB69A*ZbW&=WM(UGN{8+!)2ZR=qeO(o^x2hQWMwY|7NX&9Tra zqO&&0?@c!#s`bAq1!(AFB=TuAoO}uJS?i@Sen>>vaj^7R?r2}9KAPXv@2&-=wY21B zIJKD`a%<$8^d)pWlRtDoSB18Fg6Vtg+J>AA_^JmVt`lj2gKMZ0kQ}coU$j1{a%07N zx8FfVvH@xfw7N(UJ8?u4IX6nS{BTInR0Sit$wqyF%)MgenQFC`jpGT%H%1S*q%{%} zbl>Y(m`_$Q!zH*TAD>VVc1(u~I40kO{rM?KYf2h#=>jD9*uvrxQf*b{ysMySn&OlH zWxnnG>`HmMNO#}#bt~#`MHQ7`p=}f^#OEdTScBQ6%VGxs&V=5le-|`eu6o%S=KyLOUdL>zyQdGX}KK2^Hw}&Gq0M;sFWP zGd)Uy2Qe6<426;E4U9(P5>XJ8LNn%^FHuT@F(%-G`| zHkQ|5OmL9ljq?PgFmK}RiZobwAJ+3K_AB?szV*%#(4QFgE=vT;!H;-j6H2CswvK&v z1k~B6y=BHHH4;6alS%SZ^#NLFE2yKaeKzk-){$S!<2;g=akfTMjMZnry#Y>3`!0Cb zhaFbLX9(9w^@UOmgVSBuczCA)OL>StTshWJuJ;5obrol zp^Z%`>+oRO8j3E?o4{e|$p(@pG1!8RiR&=s;>4Csg{d zAeq7yK+&@F?z=~ZhbtYbB;x?i?1Odl$=7Vdqw;?56>s&Q>bOlmxeMX%@dq!b%cS`u%Pfd>~DBF)h%*GVNDsnP<9pH>2@_)nA~!%ocu5 zdFHVbadtRHxR~mpGB-NH^w5iRb4qn@x=|<%B8Xk>@6Kx4e=A>2)qSoGmax0{z!znM zfXDJf3omnsEU?vuhCS^s)av*^CaBC|Aetl*5T9vNBU={Unw!8=_K!vbBDe??jvFMx z?)Fx&5MJxi{#!XpInT?Zpci}#CT*pvn@{042LbiInK9Nh{sRB%!xakW1vQ9u2EH$A zkM7?}f8m3{NzDAQnKe1kcLZZ??YpuNgceQ@M>J!R(|Q}L*K9K_IjKqh{#0oW5OZ%;nIrm z_~~0eECv^8t+t*&+Z`0nN!9-~Y1~J9EGXUQjRK6?x=Nf#AK$*F`HVXapikoukO8DVbLeY*)YJ%BtV2~Z+&$*I9?6#u0yuZpF>-^ zC~VmgQreyl#=<5x>?t}blBNGp?*d;Aew>$FgBAU!cfSCgMZ3Mg;0o2tRsy{`EizhqCGty7TO=NfdLrN!Wq ziC;Y+e$%BuA1^|ct22=}Fx+^{rpgI)@)1$Z(tqB(4~)}OxP!T3^p<7F_$bknCS=$u`g!=xni zrP#uhN1zUB+Q*E#uG4r`eSVxF%`rH|=z!N4fWPKy{oKenPb1Uv>&iMMAX*+`#UzIq z+}#}Rm_4hDOeU;wCt_-us9D%flHH&0cTG$=rx&Q=YI{_r8AeWeyjM^h6dBiT)?Mfu zt!&d6>Hd((<2a^X@p~P+<&e_^WESV>yU=5}8C;F;HShO0eU%yo|3BjL(3ZHbMLZzo z0H+}{OhtAV_8rMLTf=CRRlSMGSY5_HE1}E(s%Uowl0mv!Jm2ZicRuGPNZ6J65g4?D zD(T^|xdT8T^%DFWH^l@n6XKu%Su?O>+V2{kEZbh-6Q(j>(DODHWD2H8dHX#Vg815% zJ5_ypVf%17&nQML3I1>1;e$?W2ffjf-5Dp+RasgTvnjlA92YY1sc(BvLKyVM_&F(h zBG2J9;xQJQABi!`%~?%UJSi|`NPELLkaV9gfij(@I=}t&01)8LcM`_<8}TqLh#Xb} z-OG3^iEv)EN5)FG8D<=9qT*5jyYl&_7d18m5o0|)Zi52=dTqJ3oP(O0q0Kd*<>l?4 z@Ie~vQ%l-6hvmiD{US5T=*RWne&3`g(|$agWH+kMSexST7uRwThi zXXtb4q1{H}QsX~^_j+{KMsF}Fm^zk1z_;~lhNE$7gwC_NEw%~2+t)uIjmCC-@ z71p{}v(r!I_yI+u82zEgkREDM1sL+2!~_WBIr ze*>oR=G5tODWz6Gq+RA!Sw5L_PLRtI*Lw)9jAe6nx*VI@DF3cGv^lNktkiQ`tw3c~ z#*tuulB0@JTX0(166fD>8?rleRJ-xeQ33GX_P9=q-vk|Fe;Jo=aG;~i_?k+!<%+j)U0plK z2dt-aMPVa3XoU3S-fT4d^aMgE01|DoW_RVh;Goj;N~mLZQfUzZkl*&if(y;NMW5>n zz&S0{dQoL*IWd?br|`DsHu`f!kuuF?6_8DJkV7WOhIh3pq#>{o28AU15~To%003~8 zi`MLoY4`#zTyYAY(%c)ZHTv3HzweD2tR zC-m;M;V6SAU`J|KqI8Ac@l>#6B3ystW}bsP?Z7(*o;6IoU*dp5c$d?P^k*-d8^W%K zwiVd^LI7)_pEoD$D~ioGk(0@@8(~2T;Iul~L@`+xwN950Je1TMpD&EC{iF9yp~(5b zJOI3!2;g!tDh*z(CRf#nV=@Qo$rz4|tevP0qJaR&1FE1GNGx7kCsXSd%NV;a zJQyoyO@f~^Xl5jIONT4igUD@TJ^CRs?=R{*(ZT_j>ukg=2YK7j||OS4fRp5 zO!p(b`&8x}r3Wu~HTiuS7>CjaXMgSUe%;l_-!?W=oL{l{KPYkuBRSf9Y$i%x z?+{c%$K-5daAtqS<=#(zFZ&or6*XDA%17AUp)BJi8gjlMMA%;PYpU@b7WX!mn!u?T z>CKZxF)g%iW0gHghs~dc9Nb5*aF4bNQi8Bj_-U3u=@rM#R7Sd4?wvR3)}4A$AI7>; zR5$W?UUxAkKOmrU_LN8PPA^WY(4kBo{bhU*E5oz z?A|k`Xo=~TpIM$V^NkSs(OItryH5wJF5Tst)PpU5jEo}u{CTx;|9r>s01fN=+)ryCbnWnK5QD!vZU-hRLu%@rIvZ=Ch274F@Ibl0vN zq7eF^RYA{!=d$Q~>aCwG&uQCqI51h}eSL@9mX*%h(5?B?*VZ1$4qMC7iSSw<<1~uv zFBA-%U`2&Czy0g*tBbYWtI4u={mOAHy_(21j|a~_aSf%_u9E}PVThHGSyck3Y?1AJ zWBsX1|6($y(TD4Xn|;BQ;ieuatM=244YAMsT%|5$tO3Z~;iNHr%aXRtbrXc%nWr9t z!aUTOP0wAUXuBx^R;+89eWH-~TPwXMB5RpHin2FDVl_Wrm{+p3Iis;p#NP%K64WbN z^Ns5QVMFC z4;6$34CAQ5i;}!DvUFK(2@+0OK5W4a0N z5Pi8@Gb1!-Iz!Fd>#OW z$tNsdk#puA{{nP;q+$eRBqDhS`uoubU+bcRXJ?w2z|y*Ej%4kG!{BSV*k|^>&tiW@ zn|gOC9pXjxDu@+HjMOb-PpQ^j+CwhCNC2ZI!5P(_XxY%6%Jr8aB*0YRV&Jok5`!v7MjMLCwePeaX=q=?dv*PQ{ z1yM(S=7DC~TI9ZNyTJKL7q2VukmFW77k%S`YLWI6?N8ArC$JnPv?865c#OwlefQ=b z!Auv!1xdO1plI<6LLMiAKKWqS=Sy5oTg^XNOJx;3mtrzWf}f8s@jTNXgF+et?~JjcRu}GjLGhvt!s6h=nS7} znvu_){y@g%Lt)$ZTpEhGI^pWK<(cBN=L4*;MIySw(Dv))NOq3GhrdO(dLp-s-sgA7 zzWVI(UB=@YxIfNK=vK?$T-B+;RLatKA^x4oEYB`*c_)%<%LpD2gi*-t1$_*oIF=4I z^v?b`mDc~U;cd@=)ImLF>7EENB!AQiIj3ak z$^9$ACr(E7)j_xN^1#ugR=$M~wz&0|_QR`;+DFMEO6PFqlE%`HoD8b-4)VCl%Xx-P zS56$EWAB#HUpKk2YloK&SgNWHZk<{!Jk-&DD?femuD^!B~B8J(^Cz2dsJz;GWs~qMf}Lh!Dm6kLpD}3Q2w5FLM;nk2f0- zz|$84UQuV?Lse}xWz-GqJ{=JI;BV}srV2AV$AwdtG4r7e7oD9$8_q}Q;oo4xcmAds zb9z_n6L$`9cE=xk%V>^U#H5JmcSy9O;7z9!;7vcl$D5YXJShKJtS`#=F<8nn->S5Z z5kGw{+G3t^vRn$8=tWwYpnIyQK+N%8^t$vdQ1}U5o|yrEy^0BHE@|6mz>ngIA|cN* z@c9Ae6m3{4$)uTeBzV)y(5NiAEK)(4@6nM)RCrzwztLJ2Pk-vT6ngsVDKObDhS;~( zdW&8ZS`QNESgYhm2ezA^u8}nPr0)^2K6_G69!?eI2yDlk8j;ggQnShp(l8ZvBW>=L zuRb%3syV@SpFiGQzWn<0GR;b>iJ?L@gL$3hkT=wIrXq*v4wRJthx}2$+~?1kkDlA= z*-n&ZUzAe`1Zvj7;{y+FN{y%?>EG+ssVr(E>zxO>R9|PuPY66{rQ!M|1DF z|IQ6zeDil#aPb20gNFO^RNK~GSD2b!+=Da(KMH3=&e9w+kPjqBI!)CKE>r^wY~IX} z(UbhWY%!hqzA5=`#^ASC!clZRlgoT(zhqfLrDq@hMEDhH6zX8De)|&QdAhVHk9Cbt zc<()sL~f0AoKf-fn4w9w8m-F@P|3c7NwV<6Ug24$3cYCaGs1>l9Rs(^o(g?I#m?or zjakAUM?3rihJJy&=BL}tWEAh)C5hPe(7;9ZEIO%<&$LG0_UL70f4NurVIf)wz&-HY zT6`)Kk>aHdxD+?dHyu-{;K1APb+VJC0Jo8*mX0?Ln@1K}8aLMsHP-9~D6g9v&rW~s z)y#YIg*@0=*%`-h+IKiLz8dK;S$IBwJhh-)NXiaX@8ZbIEB`nepLpSzYGA)!1C1*@ zvwl61uY$2Tr$dqyOXtQHK(M1P3RRzieM?j$(Ql}}J%{xhXLnxkR5Ta8LI}IBBBF`R zN_M3CWfM5d7qaGdP&1n|%?20yrrOH~4PgDUL(bod8&$Ryxi9+Ym0rymS<1X!Gap)~ zUhD03S;y**2=N-sSG&G!b~`poDrq{=wj!)y@Ir{4)CnSpB(%fYEE+#zDW8W2raVm- zOB#LoxU4@xiON9jUN)PcAO#^oBeBD&OEPl&jIO!WKv8DF%kAmKiT6bif=mj#V zXoFc}+&i|UCDzS`0-OXIzWFJ@CJ$9io)6&YTy>Ybp`5PrZhWToq$-a*nfzHloB#m) ztkuRZhwqmGjMapI_5mX!aAO)6FU?LAPU72f3|RU7KG}QyQCwz?-ue;3bdIv*$(ASV zwsR?H7*&IZ=R4&eN5IW6j}7Gn>ifSR@UMQD*24k7L=n867P@G;AivSLsiui|t}eE+ z<{$=u6$Iic9H%3)hjdd*9Ra_yXQlc2R<$`$0xSz;QuE zXvd$Q;$nAUq@HJ}Jgdg~Ma}%pm+pPpuY1Akjb?8Lmodq|AgJri!=^XLcY$>h- z?1}^fl@Hax>(+xw@1e(Q*1P8Kw7EO}7ABHspKe*=0lwNy^;A?1Xg%k%SPw ztG8m{tG)E5j^v7P%vW*i=ZSx6(cLF5%KDKsSf%!~pICHuCtWaVxzd%W>!RcD9j^Ak(Lb zz27_@a{=LySmC&b?QtOG(#1HQtSh6PIGW_*r~&B(@9s@ArKX!Rr+H4P1E?g>mE;CNaDTY?VePR-?ja?4qRy_*Y77= zxW4*@D`NkYv$Z@kT~JOlQ{qUNxLYZEc=nW5 z77sGtSZ2I33@)(p=jl#0Z8%CtGty+sY701g5~TKG_Y`J{Sa z1FF91sw};^UY^1{)4|I#m5#SF6i};}@3r#M}g{dVTLEuMG1I#Wb5a^Aip5kAZh%I%)nBs*rC}6)!r2 zTZ0JOyd${Gf;rw}&U`q_i2a{PH5fV>5acA_Z$XLo9CxpG7}jsJo2DyiW-?_X*K?I( zrIqq6h8#mb4rd&9sdyDNj2DmHiEc!u>V>X*$cLCtSI68!7iDJ@hglx2p-1t;{)tr< z+r!miQNHU_iQphB0WsHY#yXUuFNP9}8}KHG1TX`CU6gpU_lYZKiq^Ph-J&s9;&0VB zJ;-kshvrh1pdhopr9w{njK`!d58{>A2wz3aH4I)|?Ub}8aMe#ZcBHYm zJJoS}ZlsvP8D(I+BX+??THb4WHNMTB?;Vgp`E zWBDq^=}Q*~W1Rc$opa9m<~~uebjuD6&hU#0=tQ0CNtrQO%e-|BAmVO$A(uLg*i9tD zoU&e>yF!GXC}*cjc#)Bh7c%l7wI8sJhva|lov{sB`hrQHF43p6ZmoH!PJ_PFb=YSO z1h>UayiU4}etV$#i4fgyAw3BtYYpSuW>|H8`Y#v22n!z_*qQv3B0ouX$SDx)L6CC| zQZL3?K7alyNvrPZ7o=Q8%|qYQV^1vuO?#UZ6e$g(OW}t-)sq{^2CZ`aBnA$k*k?>= ztmN_Eso>YqJR!3x;=l9DYSTl&37wp8ywmM%db@5FbHK`){>^=^AlqitYO8xq$yXOQ z*Ucv5g`CuNhl*(q7W^UKR$se2T)FY%9Bg0GLDdtIOdR+o`&|in+#PU9QGj!z;Qp@G zurtj5A>kMza8fpX^i_&5^G2KvnT_OD9fCN46P4O?bua#HeuGw4@Tk6|F9uE~o#K0I zH@|6jSw_Zm-=(j+-@tHxM$yT#L^)ks3v}oG?Lr!yimvfv zsfpN%C+^zkYZ)g}fTJwEv1f;83g=O9M->7Q21j{NeHA!#twLDDE)pk<1@&fju~-;DCZ%VWX=rF|!c~^=Ju!)k3j11jMxb z2e>@$z@NhcGP(v}Z4JwLivW+nQwBQ4Cew-HZgUhkQC{JkXJpu0s1(Tr$7DG;(Z zMX1>{J#!TfsAT(oVs{U@^+x~Jji;9`YWfG?Xza;2a~+*JgI~0Gk#+CRA~~*q^*SDi-5#J6m=n1aGT)$|n}+=76%Z zGn{lORfcva`gf5KzkP>5&(f{Z{4t#oc_JUldtyEYEzXlv=&Rt_4kg*)rfd+b02e{} zawiKhrmvX|Oh(Dk(OClfxuNQ!>neRu;@sC_Boyj%A2gpA@iRiSPiopN2Oh+FV(LH@ zO$X4WBk->Uxu?vk6c&Xn>n!E)v1Gr9znH66an7H*X^tN&kQ(g9aqPX=N0Sckdv3ZU zekI(O>y7X_s-uUa>$!-L2)+#tyr{6fKO_4=I}f1y&7MtT-iun3`aLl?niX9$96RSb z#~TTP&fmF2u>tz1zj1vKuuC$T`Sog46?n4MYvyRn(ecp3y;&2>y$sSh?6-+tR~LFO zgvciG=kae%t1V!?j2NeoI}^*6FXtUABuU=>nP_=ZY0Z3LQN1QDB(1MkouFF8xL(u% zOS?hd_(+9Z+J+3Ithp{D1%eMH{y?Ir|H0ZEmmpg|o_x({W3el&cYMpmNKbeh30Jer9Jaw0Xc2C$1#knsEg2Z$p9=?cST3@%? zazL=2kyhIUV_K8^0wuM28XTrP@9-@>S;52uj`9v=u=Q{LhC1ww49~rE^|>ED6(W7a zyRNM{StW?}Gl^rgJy(>>LkTPt04Ex#*qrAJ-7yT#@Nfo55Is;+kJ-P&_Y$lro@K2iKe zmbC#oS*zSKagPqb1R>qYds%UQTn#WzMdfEZ;^9o+Sotm>;P|*5Ctu-5!43iHM|!-gg%E9!e)G%Yl5_EvB*S`kl0%sy-t^yb zb`Rpbg`5ND9wo=DmH@+NLT{w=WSdsnL9gVoM#%$XwU(_hIb1C6_@V zE4!O#BCyNXpp()%^x3oC)+8VVLxEq>2c>F7XVS^>s3pm97`v;q{tP+7MA0#qpYs zo~Rdf_UkPx=R2Ja3Wt<)m9p!mHVYZ1ESPuP=I`?kq{g`J*4oWOrG7n=|Mpqx$o-+4 zOeJ|0xrkzSAt*ad>5m^ClFb0;?L7YBQVYVN{1^zLMV_pw&1x{U+{`#ww!f$R?YU4e z31L_yXc-#1*g&{Y@F{L9RvsF#De$DQJ2JgH>@QoXw#C|>K=SgTEFN?>dA-B%Pall=pFViP-?^u!TsDSTV^_20D;Nh=@ntxTj?6hy*xR7* zd87OWXkLCz>*uu`9}SU8@>mddL*cR9G`gB4J*FUhUww6vb=t*CSKJ>7(cgijPyE0b{=A2%PgrMEE}By;_0uKI+OcSNkmNOVEG<$++f}n zYxeMw|89=r)G?WWQ}h$q9=SC_uVR9a5ryAFGxW<<`;H$|jtk`9p%(5ct&hUvS>Jqn zg3W$)NdHu)O#JIk(<}lU5F&lfZa1#}|8&RY&FT80DUVbv^KVPlIj*M&))b;fMRA2g zXGtgP$F7beMtEMg`L*iUZmkq(#2voS*_@}!Rg)uux>-yChUBj1R7W5=2!VE+0aJlL zp*UU~gWxdV9zz3!P!d7!=DJFQ5dh}9W~22+^uj!D*)$( zGhX(42lUjP5s0GnC!QTnDGcsC233e)RQ1uZ38LB<_pFys z$ee#_J0H4I?-+HFqJ5dmZ!v;tJ}gcGT}iMSNLG5*SMRHBKI@u8f)BL$L^pW!4S#^F ztlb8Z$NUi-(vi&nYi>roSog;UH%NV+10M>tIzJ#lqAFP^Br7#jI)$@6Qx ze~`f0DO#~EDU8#bLQ#9Ho(2wCgTobq2#4&I6^A~{sr%-0+9ZN@>GAo}fW_RYsoo)o z2xQGw07S(;8259YcAh-`1nxU7D|p@_4Iqw@3p)x?bFENFtXhGOkZXIDlQ8`HDr;Wl z5SK}3+=HOA@?oBX#m$L@ynTlPng!oXU!EAn;rJZ?>yhkoC5uCkxGI(3WkZ(xKcP$Q z?_AROBweHIodhLdy#mi+#*cMG78b2hO1Caf5}K+fI+LB}FhVJELIABc=*N=98--6=Lj033>QVB*}5sL6uv|flX>>d>!MM4 ^Q(ho{ipfE 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 x2<+rKYcFZ-lJYig57)sjjC`@}(vO!K4z=3v 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%0A6i@0&pY|7-?3V$ZCM}a2fFs zba0c9+bbpq4f^tTF94R{kC7}%W++j8eZ9cVpGw&~UD~dliNdR^Aums<71NU4<9^-y zsC>n|8XlEmgxRV|uqz@6VaJS#08dC7dUwEDhMOEm^21`EAwa`+oE zqN&*!@rRur60ClByh51ez|O2V6m(+t46ViY`W5dOBKYEoR$xrpRf76jqQl(6JeLbf zZN#q(3y~Kl-v5`AIwAE}mmFX}Z%2A7q8hqCs#m0XFyF=v#X**vmu10L0|_&=T0PD; zsw2XV%z4fwYyL~EJ@ozZwoL~EGS~OIY&YkTU!J6V^D_4)9-{na_sX_Mcr`Y@Wt|`t zL+-RC&E>)7$&!aDX>*L!Xv@HKBf;T$pX{wU1YfdYX!%>9QX;>k^Z1dxb<8noy2G$c_>GWdRTmRN_V}qs zd9q-SoNWi@2RyWBY?-Xn8EM9 z*CA~vNoSeLdws)He&$F`DVFW1q|BS6I-4o@E{iEP2<3HruTcq@Hj^i}_iAoj{Om7? zC3A&XwPgYJ@7FD00(7HtZz=_pg<;he^E98|T%~6mc<$a%n`;jzu%T}(_ zGKYpL1TRWK2DgjSRy5_uhDdTJf)A(R=dW$V9W0b62yBTApRl8PjZiDq?PeJ2wbHbx z#DvmcMfZLk@;79A@yWE;km1v#Pm_AZFMbk!9@YzcQMSRzZKgTk(&s}09<6t~ke5Eh ziPU#-(H)JMhaf;6*#32J)x3YHf9-(YS+iBraFTU+a$=$jlz4e*Y3YeQ;ET}$mR4{p z81j-zHt7eT7aH{gygi=+$-3*e(xipbdkDoWEa>BPTxo#^qqI?1eUY}{yp(D-ma8o2 zrKw2*Jh`0W;$ri=9$+KU=A|gi=q|bLGBVXI!|S+g#P-z}P)c2n#_uAI(dK%kPfZ|hcQRuHAmE{>gsA%tNA)|+w9`n#U%cNrb=8D4Z-2b!7{fo@63$-Rbb^X?}Du^aekkHZDe)j*k2=UfCv8G@!&y^)azKC{lRyNe}Q zoLK)mGnD6aSZs>d@5~b(Qdn48YSMalo>g2NmY3#Q&?BTs7t3>ZItFZ0{fUN-t&2T`R*@7 ziZg*4nwl`Pw?Ce_bT&QoVoSC(?NnZ>tDKHagh}g?$hp8%7Xon{szNvi(6_?2S&};i*+#`AKVfTeje_yX|_RA)395`#E#nez)++u9wvyl`d&dWFBd! zkEZbq`_kJQE0$FH`(CO-&wH6}M%!ksSh?g0q3Gcife3JH%dW*Bb! zhw4_h_U2C}JuTga+qIy_;iN57#!us%v14$fu&$t)@Q^zZGuo<_pPwIY=v!T^P~{m4 zx+W}pO5FCkgwhFnbu>A#F@HWeARU&PBN;lnjvhMsHTJN4_M>u|DCng*H<3iy)xNvs zkl>87Quu&*!_scwLq~4tGYRqkd2!L9RRvo@lNg?iMkGJp=&dkUyWe4NvKjL_X+*yN zbyq+1;kNeV>UisX{q!UKbjylM+|U&x_w8@$`O`xM9SU0-w^Vnkp8L6;E16C@ry0u5 z5QTRG71TdluTY#9&k>jIf{l)hZ;mJkJkk_%R$NHIree4tOBs-d;`F z74m#6730YqEAWvvx3chEKK4hNY@8a7ZWYYpF0*0Aa6GWrVx1qQR9|iVsnB4~?&O`x zfvwO2xo%JZ ztPC1eL2D7hEjun?c6Su1SJK&LIzOp;E!81(^QZGMfmU1Dr%qD~3qW))kzpEhiZ`LU z#)oT*6l}=2u@Xp8LcFAq|AWXRrQHt|kM2TOF=N1OXfxS*FehH8PmX_2{HX*Cxc}75 zSsAhseSW@tv-IE@F;!Mm0}i&{A0!nj{_)`3JB6j2z;nwFN$s-z1*u)=4(H!jt6!3$ zPW{o(+^SVS1U{f2d|$<}g#`s3mRcGAO8BU*1Ay9j!I1#yW#tP^#SF%90~lNl3O~3f zB_*lV+r2JrI!1Hbucsd5&7{!>Yk8G%N_oN)xgg+CLgkVXdyTN`yDjgf@l2P0uWF3v z=m#GCmNJ!G%Fo-Y6Z#0C&@%ve#XZ*WSfY)6KMpQ!n#KL?Rf_v@Z)_{IR0ph*)&hl1 z9w}sio|>9!SUDq<+JE&N9x})a@U9a$C|)X?Q>4fe^Tv8G_Uds*@R*WMq{4elK!M$T2e)l+52-`P6`9kIks>DGb@8C_fFR@Pfb1L{e4!{DJtXDc;QC zQ`6lC@ZNfA8XXn}4~cycKtQiYlBUvJ-MGm+sRb+UyZ|VBHKw=!enoB9m&SQ}vswCe z8yc{*bfQ?&vVtXWJH+_?;Z};&aR=JMLN}C$TpL+PA~SdFRnc1@sdji-nrJs*F@MqL zWa)Ogb$OkWzSaie&avvEOS%^dRZVY-==YlJ{!@#ox9cn1AEW5B928+KHx+`}p)dLc z9&)VHnu7Bq_35mJ`UuX5Mio?3%tH*pm)MSD9RX>d6N)NT?yIkf41s7rZO&WAfJ%PN z_t6q`JUc@#K>dk48~Z=VD=yAu{BP_nOzu*XZ+RhhGdcy`y}&wIO>q&x3#VE<`*1#Q z#4p6&6jp3kTIs%GFK}BZeDXU*Ws$IogrA%x;O=}ra$$FFx`H+PRk`8pX0+~=fEUzK zNZ4z%O#dg1kmC;~($j4+!at(si%`^?A>k7*d)*a+2f~hu0PUFzMNQUC#ZID_@*j}b z=-bGfLJUa^7O%GOSm0R8x(j~_K(|=h+ZtpTm&hV8#_HF5;t>U~;{h1|bSbWt-M9rQVwqbud zx5vTS(?zi;5nM6aWAVtmr$izCekFtO#f2K%mIs+xS)mHJiVV-jXc}wP@bvq4;rGb| zc@!~!_*BEa!Nw-^Ef3hQNTH>Wwhd;M99}HX5fXg6gB#&Y?u)!uHi?U5_Ja|feckTG zm3z1rQ+5rPq)_~~8YamSD#~O|LwjuFHl!vp#glNJ@ZhzVgSu_S%7qPXOo&lY=-YjcNG}$iTIru7#SIrYwv)8OWi|iFH?F{A4{*wW;M^l$Hzxk z8~gtCAm1)SxbXeud%Zt(YvF4kATDa+3M92d0aCzB*_#0cp4?>}2b^(7!SlHye0Q3m~g@oX`LyJ@ti_;%9@abCBVY;`g z1iTNoC-eqoxgwgfvKT@|! z#Dp&She&Sn2f>F6m7j&0O{<&V%bl(bAN>>t?QB$ zm_~cJrOeN!pO<=7iy&DxckUak5js7sjCtXiVDMdJuA5F!X}=7r7Z$(6r@PpUJShQf zamQ~*+_ib|;g)&%kJnuQJme)w8lZ8;ZBR=+srQfH)5ndBOiC5zcXFc}eDJ^!t3a); z5h*WBjf+#Rs_J^$>1v)Fz*_e$Jb;CYf*9Aj%$AyKU#}}fF0O_+QwGB~aAJ%jJ8oF> zvncXY)zR6-uF>$XG?t)ULZFkl(ho^%mDRm&D&4fA=)V1g{NzpZ78%k`+y6jSP|!QC z%-#y|NnvgKQQ4`K-$~J7(IvbiPNDz$nbR3Qlk%`yHJSz!If1+0ylJg z19rbpmpd^w7LNlv*cwN_CqMJA2ME;UTsbK$rQ+NZrUNR6L#eq}))txK%l=5s|53hR3<-xtLq9k56so=MO{;5ZiHn?R|qy z`~{hX=ipsb5Di^iM6)PY@{44~2m;_CI8z2oBR~i9hKLXm6Vc-yX`)uClbQ`fn#ser zUk}%mLcReN(hU-1e^u#ddtIy6t~0Fv<>wjmrXma-0W zK@asnx6Cj!%taBqb_=mJOUFsjaxOlDVu;4Vcq4lGr<`I-XZX-4PV>Lg}UR zalMA%5Aja}-RtHdgN>Ntb$@jW_*Q}Y{k+?d4v;^bQ(9v{p7Qp26 z&aV{SXc;OoY{Xkw>;%Ki!ogxdKEWXk0oEfWCf3>bwi(Ds7)}CjBX%yu-V!L`6wmAJ zKg}15yAC>M3r$NRbNHH;?EwAV!tm~aVYvySB-aUx3Rfs23Or1{gC2pfK95x%a2(+) z^Y%k~XPjzPra08;?rbocSN+E#V-L&g5Nafl2!e{Blq8dxX(;?DHhL?nta^b)0kAA z{*PY6A!7N94RWYYn$IOdEfZeP4U4pND};7B)Qqarj1mJoF@Qx=Y%PPqk*I7j(xGN# zL_MSbaSUz*CppEs?VGeWXX;2B0^O2NH5*MK^k0{4X9R>4<+UL{Gm3hynL_qntJL&R zLciP{%BO&}U;p^aI5^wPf0G)OIXP|n|9~2TL^=XwA(9J=DlEYTVbHf{t?>qe`MhoR zYnw4EA~c;m9=^?+bKCh~w3H`+=iI?j;;A%hsy3^?zG(UK@0}1DhiBWCyBUR*BIRoE z2BT|c-BIN)W@G|n2=)4XxQg0|L(93E1yOz)j`C;{B5j-KHN%-4ZX70_FbR@}NI&e4 zwo==E3DpO7V&iwa#*2We4TJK@?0zhUEBAn;B=oatb@LrIL;EosI2 zL|Bv*|A@LpHpx>l^YwXIHpR#pG#zO+#U5&6Lyo>}0)=4fH6TFLSm1;N(du=a^MHI{ z@3sLlk@&?;x*$4TYkGl3RXY3G+UgdCYAZI{^(LZC7E*nM3 zpjG!32!?)T)*4{afPGNscduwH7`<-hmY{ppQ*^@2vF|~1gFmoqLSxr909#41|I_+# z?+#iq4mc?%2s|*VhzxjOnrgppt)Ls%6{`w^LMR2SCvV+#>oABA{L6uaKp-3EunxN+ z!Hc3JTX0}osm^u_j#J8+CXYZ_=7bgaFB|G6sa>GaM3LyAyZf#2V2XNmI4H-UqcIKO zN#7le0fEKrbUvl~Tfi!cqeKOIXk|5&S!c}x4-t+)+W`kApy<q=J%c5f^3Nsnbbz4w6q;&cLh_YsXgo6wa5Ud0$N}|gG?udO0y2E>ksfn+w`6Z z!p`H3eiy*0VCVu9bQ^uKga#;|yT|e#zPTLj`euIF=(UrPb`_zCm4E7TROHz@}3jYgRDQ-#Kh8vO57M!^jsD?9K zgSV9=fxMP?!(D}h&o&Sf?=q+(2r+%Iw8(mO{1i9z0+kCTSQaDEJuTN&dXY~nKXmfh zW3(JxCUjfi<7lOI6N@dry;LA5)G*+aW~D0Ig`ht({imse6B(BJZ<3)AhFsJYK=io{ z_p1nLB#-1DbW|h@_zszOgv3Si?=ll8rQW$;iJ5o%mP7Gyk>V_ozDNgU`O!E*N4MJi z5Z{PU*{G#s_k`1&Zx0FI)>nY}|4-r&bV`!MAZ>Uz#z|cW^v&OZ!1kdCJlAs+!SoU4 z7vwctAtnl8dnj_ZT2Zf_?1%fxu1oBu7gBAnx65fQUeL(*{?QM5NrRuE7GiclGYl|n zQ72pN%l1wPZLEG2&x>GOt&~S`GF+0_#y^cm*IeqqyhdT5VljI)h_G>j{z;Ez5*Lw5 z@SH%cZ5j6+ZhF94Q%}M%Ys=|3?;Z#Fgg^6hINS%pc=EVz??3YO*bqZPZJA!6kj_|& zFp+%i4>YWZvt*+DMQCnbv2MXOKDqJJn9p>ShELa#7t=(> zyLy|TF6`y-X0yrZ?~xSOo%}ywiVNy1z?!*WB(_lBe0L`mxKe`h0!N6zF)u+2EiMdu z4f~BLZRd@uF}XEB9!yKiOIi?TKR?$4riPZ=UbWz7Ezq3W)A)AC^KMu7WWd_9l5V;R zxbJLWwM*a4KvskhaA*|^y6y5(omN2`E>H(G-*R&NL6<3Le7gOHJ7_m(3v6E-kngGr zKHQ*IrP_3$f;Nq1k7nZo^eRW@3z&>*x!K?49Gz@tq`3Mi$+MMWe>vSFG`Z#o+dH{X z_s(3ouBi564@~DTz$IDJ?$kUm7DN790u<_7fcie~^>AldzY*8Wbm5CxrR{Mx0cNsr zJ|961@cz%YFJ=ilfdNCX-*RJ>1}H#v_?8E#$RH?90Kufnzypij`a2l$DKK5#Npszy z1=+{vf~lt5+yJ+O=GtSO0+HlX|G!2raCw15zDt3JRFr?rD6S2Aj0YS-N)|nBKY3jJ zt>ES^1JusvcNOFmJwI%}*nf@b=_B;zhU*S6WXINs2*t}(5M33F@v`#$%HsXSwvO^e zh+y!^?uKaBKC4oO>_7bmaW1ES8x9uBqlW5#kK@1oJF071!4P>SKb3;6^&eMM+|XMy zPeju>rYoN0lUWMJ?mI1+C`$2d;*U%u~h`~#YJf)zR{GtrWfRyWz%;$@6 zI~NS!&S__)IfiaR+%2iq1j?gjjP3x$Hvw%(geRqVriI1DIpyW$Y_;cKUx*P3x%2Sv z*S&(_Il$;WVlfE{aTqjH$*27SiP?h>(kxK5eW28Rx$yKwngwmzW~Qd!zZ`&OdYA+7 z*DoKm3Imxp(HM|%O>CMBXz7%$mxuEBwl7K*%%27QHjaM{qWctA!hm_tn?1oAXD}e& zej#iJY>$3u;V#W}4pPes>XY*VcZz+A^P&r>%X*~pCk6v_={Sa!*8APo1W@!E(jU-reagH5f}IhX>a{9h>ITwAV4@_&OP^8e>SwF^8~!4gC;VP8{9U2mlJOrw9I zk|Z={QL|ZIjSP7f`gbot758S;DLo{@#qv?GuRd#T*1*WDMrI{@W^=P|cnN%}w!|vW z3%V{IYm}nb$-PmiqQ{)oAdFK`g^jEiDCnQQ223>_iL?F~Y$Y?@#Vl1X!$;q4YP0}FN$3#d_)6U#VvTH>&qbS`s=yg|`P6l@svx~qtun|e2%RUyI)U_9B?Y_wN9jMe` z1w&|c&6J2HQ~VmZDLREG9~a%;hLiS!E;;(19&V+-#vm}9&GJ$wx3(^yBS63idj`nJ z0kL2sFzc@tFIpsFTB>CuPIGjAUdtt&_9+@nNP!V$QY@559`FKm3A2K+p%;NNgG^*< z{~wa0)J$CxY#$ERQ>4HQ-5ysW0~m{d?fwJ3TnVJb54F%51gU24q^9-4E*o&SSYadt zG|V=3-#OMUIIRJ!Uf~;ZyDud)wXn9%tFKQ?b(+neTAsf~sRBGuM+@MoMKzW~t6ZhY zkTLLS1Q!iDSk_-rT%l-MmOq}<0Or2D*EJq2@6#y7Vjl)wwJb0OcgA1e06rT_%dYpe z@{ll4m&OB0$}RvrM+yEKhGrsWw#Ck zP~1%~;U%hb82H=f{Q2lY2m!MFKsrdh;SxQTu14B^!=& zOW|{*(A0fJ_%t*TbzLfQasP<51by>+}#m=KBgISJpDI_mvsLTs4Y>k)$v7bE-q$0xSF7nXi2VUm=E#9apn)Vsf< zGO$@d2q<+YYC|&19#jjp-#+h>f+w`Z#zy+ou)lZ~Dgx8Omwl=&3XYmw$zZ@(eJU)j z*%@ewrx_9o_t1I5_2}IzN89yx`ts%2I1)JiU~1%xlRl%B&=&s~{M^r-Nt!G98?ff@ zG6ZBhiN6>3M-KTD9)L=})@QH4e`p=J`9%uPMGAM#20B_MkByXY>{NVUb}9TtL{n9j z05o(60NXlt4p=G$g(dpw9_QO*T(E~~fScX0Qx3EtsD$M(Tgz+?StFzP#ukrC<~tfQ zNDM(H)&bJS@m&K@QUQ-_0_&M#=Rj{xUWy$WY+Oo3`NhTI|I6_%RAXR+%yI|;ANm+5 z-*UrV+zu8)Sd|4F`M@Q76`06Y4ckuOMkfCQa&mL zabz4I1zA(iXZQiGHbGfIZw4JuXy4~y<{23OJUidBCe50;9RL{&O0o|h@;t9}2f5!~ zIb$~=Y>fg_!|zP;)+JEBiT-Mzs9%qgF3`c+B7Ha!e&__w*Q7b=)=>Hos10wQN?6QK zI+siZ5}CRIe~)K7JDLVRGm^K6reBZeO%n3L(pDGH=|aD|-fRL(4|X+|3IyKz zaBV;N|BC~-wF3QMD@BZ4IjIjp*(@SBks%v}w6Rf< zBw-_&RVqVLGGwZ-jhQmfNn@ z-}mu)c~$3Z8}IwR*S*%YuIpM$oVImz{z3iyhnSh~b88j6?C+=YOD1!@jP};g70D^a zT)b#EZ7uTbq%`_D+LYXk(U5|lgbBSulJM?I5xd-r``73i9K|{Ep1(fIr2e@|kJ2PD zql{ASrH%rlaf|+;^jiZ`epP2!nnMMZ$3#uJ3oypH9;X_gX2aa3!6`jXdRqCq7gz6v zUWKdw_&Iv9bK!nZ*}}-P>8*<~l!4ImX1ZqX7E}_=?Sa*o_N1(u>R#Q{F=sRp=s!S( zXJ#R-*CD!jR6PJ&xmJEDn z_ryu|SC&{i{S_5?WAo)V85vc6$IWf+>D7yK0y8sd#+a;&#f!}V`Vef5$jSg}o38oO zi}ccrrv>QELh8F7lRR{-#ld{J=JE=~Sh$D{R=+^Q1 zm+s+V7U#KBJP=Jj$VOnjl@&$2U?XmjvD^Ln*>~^Z48Y*J5bKr-$KAtU+ySI~t3hfO z<{YIHm!71wyaljchwH3>DaxZ9`k>-#jcl&_>j_3s$$!wCy-b00$Pj7>V0da98rDFx zkI$j=>ca6qHHfq{3- z`&5is4mtE}^HG2gBILkR(%$J<*}lljOqYQV0oyi1(+H1&Z7uL?Z~Rvq(y18T6crP5 zg1JkGoczas{_RvnBY=Qy$e%(1BKtCxIiq@%|$})nGxm-hmeqO4L#Q|c5(y& zK~4e!-*0`vOAeS$EW*h(0$rJ^M;5|>fVS|bf$_+TL!BN%I8^2CC?Sg9K;8gVx*5al z@Ff($0e;u5$B-ucT&Y1I5!J<=cI^CbAPZcI;q zfBkPR1{HJjUu?UgwLx!h5?~2_{Bg?k!lhALgx7MfZ!q&*C;Vba%5wf*W;$aGz;-bN zH-Za9&4>$H^+3sPYLNVqEiW~(vzP_xdGW%gP!M#pXVGvU<~3Is1?YkkmA3PIvMNDr zG)vXS#-?vK=YKQF9)LvXaI4rM^H)UX@2vPxa)+!?axYmtk8saSFchKv4&P2XZ@9e{ zp03?>qh&4pmHe@|I3*{IQyX?0y}kW+A3l`fh&dC}qW9T4woRk#(gffU*csju+#Qvx zhU6xLC?cWz8_l@xU+d_SDN~jyX7s%WL3MztskN)3t5SmByIvw88+(v>&Sy^ht1p|6 zzqrz?5Oyq(bLGUnG7ov_onSVPW0zBi%I)npYMQ;u$YjdEFTD35qfLjXDrMx@b#kj% zm01BQAaR*7#@(DUV+lBGCCU7DW3GlQ?+T-Y=;U)+^%7f?;DqH*HB`tEGAo%+LF3db zTtzI)R!MATTXiQtdmV6HP)_*Td_F7PdEcNV0&BlC_#xy@AwsS#|1pe+$|quRpod2o zScvKfxc9Itr|JW7Ytv2P22?Qd3+oLwV>STa{}2wwmmAG>Cb|BcV$G^ud*HfS$Fd1Q z8B`BGu3u>r-ak);6gi4d_o}L}srip`rMEY%AoX5@wpGP~5#cPdg`k*Yf^DU&+DhHM z(rYBOt8pWc@j6c=o8Rd%VDtiz?gST*mai4W@%v^K+q2;t;&3+LS3P&-=t|mcw+}hL zMDdQZuZ@cE@h&gk6f#lN>4id89t?3Hf?dvWt?8@?Bp*%qbriGcD`_f`=Wr_sKwYP) zsp&YEQO$rG>w&6@B(5kvR!L zV$_@sck?PaTBW1Tk++6l8g(rc-tUyTgJ%a z#}6URd-=)u>xUYryE}(NQZ$7aL|;tSESR8Qv9+SjqB5V*U8nOWSDOChaVC4GV920Z{>MA;?F87*%e>S7Eip3?QXg6wlCG zlyCIQ|1`N@4^1s!1kzSrv#7%%?% z37ntBJf6{hI%6#@50^#EqE2*_$&;xW&ji9)LICG%#qg$_5y4MF8&<1La6#K-(Ws8bGlvK?W`nul&Ecs}^k% z+rGLvyEch5d+~qb*n4YZ62h(6oiJpLy5L76I>I)rcHG!>QBR}gh+3xlbyHKZqajVx z?>{nKX(3MrUpf4_Z6i61-9=WR5enUd1Uo0_SXLz>YT6MOdIiI6NWg#)2CIq7KRL)pl< z0V$Sb)d_5%4J$(9Y0aYQqBdMwztP84ha?wmDEqj0SID{E`x{xc`pP!Q%s0q<<}aCRWLE4f$QOMoFORcn7x4kd zjq=5*@=b+kL0{m(`oNFV?7Ts5yy%`F0>lwScHdw01!-I|S(atz{Hg?QFhW$*taNZB zY=g3+Rsi`#BRP{MIq4oZ!wmie-+p5ovQLu! z;O+1~2A1I;C`stS%wVV>$0g$jnIF}pb_q6j3EkT--83O?6XB%SQ_EOLOim8$SB*$9qnjgKE4+d2*Q(#$5F<~T`SV0@wGP%KwoN_2>tvYZLx)7l zs_-eZic$`v?iX4Pv27&YRg8Qrk=LLF<3MG~t&67dHc7mIGT*kzP01>ABRL!ul8zWQSgfVP}o#TL6Vdr%H6e$x;54f1b|Lo)kesvi2? zEWd3P*c^K!XL!La1yJ3!xwpY;*WWsi7;O&Xs3kXxJFFT{`J}H37yOr$1;}y8G$PvT zrtu?^kuBM9BU=NWyAD-p3D+zAj2T4u3!t#oOmW#J2GkU>uoqZm5f#WEA?v}$&@$qc z1zC7X$5bgeEI`tF$EnOFXw-fr5cEIU1?Na{C>wnH3={^_2o->l)hNRN`V9u3pOYi3 z!Sb;zXz0Q5@C7!Bszr-ouD0W(m*B;V#~QGp06MG#L}?`O(fQYXFbH70=m-7o;{*xF zCaQ?29}gKssy<-CV`$GR>H`JPbZ=M~k35ry?rUKQE08#qE$$&OIYJA9dZh^(h-&$9 z%*@OR36gQpohzc5(7ccK##lF=inVS&2j5mzVhmjaO6v|F2v*c*{}_YLJQ>3JsoWc> z%&?ixL{KIqAK@z08@delin1{Q=123kE_^H5DM=J8Zy++pJ7Ua}6 z09$rK!(8JVJcm|*g0zm)xZo?+a})LgAp0(EC=$UBS~V~uxerpWJN_6lf+J(YCB+K4 z1;F^deSNAHK;wp^9RrzO%A+rc=}^JA`|ib{#igO#*Agy5fP0niyKb#aV(faAkoA%n zbASS;czZUc814v{pB18b^u$@Qr#~r~)t>-?#-H(l=nLsl zV^8aM7vyjTwhhAyJELbpggNPHN<=BR?-%%;X;JGe$?*&d;_<7a(RrVihHDJb6%?X+ z3#Xh9bx=7d$BBkuHDfYEN#fb?GG2-g9dN7CjI7={z^!y{wv@xQ2S7$mJNr*k53*Vn&C1i@yc|0~j<6}dvv?NOtY$Hio=tMn6qmwOJm163j z&0>1ePrOd=YSP5~5_k7dpB#i(ud5zanv5iUceS*ndnPc_-ueuZ;x}*Ie?d-}EX*8S zb(Q1ObB~&^JKT0kT*qIyDY&_@=@#ie6TW}{e!6D<5gZB>!51ncSh?|-CxClvKnDhL z&a|aeM4yLrNyL^uNoR$oIw*6~|4HJ1IKgP?qHz^t@#&hb$|$IqLL|5hOfGsSUv?%LtNb9PDL+h1}Rq?wS}>QevOr5^~qs{Q_(k=t~h_L8K@B zj${2I4bakf+^(dhbrXl1atV^&bdPK^1h#Xd%UGp4_Zr-p{7?2>0R{~W40K(>vEqD~ z?dPm2kDpgld1F$(7jGM^3$)*QG!zP9`Ozn;MUeZA8tFU?jlm&`g>VrM6;t`5lQ|9r zXA4o*wE2qP0yT3VV@$HpT|OFYy8`cT9<5{6)X5RP7s zTJQyWfAA=agvM|jbSMtpxp%JtVJ(9$?>|0FEnLIHqMYG+vFpf%`sk6#BgXoP>RbA`^FPbx zS3lZH&epngYs^UWqfxJ>%tkwmszOMHxegXM#A~fQed}WAJi=^DQKfRo`~bP6Zwu43 z#{pCGlGe4ziz#KJDP_x+4MVYPduuF&Zf-4y#5P9Hi}N-zN}@u^FH`Tlm|t3gEHChC z(hD14^h={jP>io|gPoWd3$>f~-MkgXXk4iKj}nJqb%=sDkJag&@Oppw>uE;DXd(5) zTko;MUW+7k-BEUBJX!O!p=U_rP5Fg4$;ojA{XFoXt3RkN+u9w^7Gh7xN~&-_3Th?6 ziA{<6C6MN8-&$n7w zdAl{^;(Sq^6{F4haGE1tki{IT)AP;DJYoHsDMY5Sw`P6Cn5STu9Hf)wZ zplcJ@+K&qrG9_qB<^JUD@KI?FJyN~SEobJdH)oG~2|S?^^%06f=Dq!N0;yv?+ls6B zl*g)U?5XVXhR1S*XUo^Wh)?ONOX4R{{h~lRZ3wcs#1TaMp>Jm`Ssv|(qCPQX+kCWc zALS{1j$cEDhj1(DBnn>1|5Io@I)x|Epzc_IMLiBhoJq6r3+PXPT_mlsJd<sLWKzDSPl+UD8|OL;_TjS~ zt`SpE-!c8WO3PtEPT>yFvg`lNp3pBx*b`?H>SN8c8UG?p=TwgdUk2-QBJ&ny4;RU; zgF2XY2H3-wcPz%?gc+q5ZyXy{jI_9P z+E4E#d$ou^Hl!n^aYp%F&%t_h`bGBsub+e?bv~h&J}+fo`; zF+MKmi@DvYMUBsRJ`~grE|ldnuUhP8XPaBw!hPR7H{;Pa=DVF8rDw+7&?y^Tog_Gv z?t|Yf5UH)rlzw?lUGFnrFg6MHyUp;j5CLqHki7WYy7=gm?=nwn&p%l8QZ(jh;)kkY|km)s*zn%TfHqNj@4u#b>a! zKd0y+n_L$WCL&?{Lm*!7E3fVkbNZ9(b()E64a6n+Jq1UPO5A z2=pR%yC{vRYG1MUsWZgM6jzLHY&1lYY*N$Gk)2uN)O_o*|J5>Wzx|*lFQF zen?u9HKdJ1L1CJKiI-peCELT5RnM7EF|1QBKJnC-5Kkq0T;458m#arxRBRho{K(I; z0%(M$VU^qxAB!_Keu4Bj#HScKCV=O8d7J!LXukCCXL@;rWUDm)koh9)@0@8WX|6vkRKRQ34T%hFij0-PhsPRI#HkjZ7=5014 z_$tjp8e=i%;Y0^FLM7z{DOCrN6mbVZBCA&PO=FiChpiYk-`UeS;|7?)bs2Xp+kdip zwkp0>jH%OO-8O^F=w=jE)3kKA?qv>mvffpjD|~2D-+X9b#M=6rpD<^7Ue;$vLxp5;ZKHkvU`Yw~) zHT^(@GXB37V5&IEWtpg4Sp%r4ZkDqsJy^PPu24fe{cf7d`&Z}H@r{NyC@LzY#uJ?M zkhGpk<70mSJp@tmeg@a^vt;7pyz0K6nB!E((84=?s`#MF3I{87ZnR8lOy?sz&d8X& zXlD5tu6)h#NBQ!(T^x$1WAo8dp>jrzc#7#YJb9fQP)2@Lb38=2AL1s<8B2w1N=*k2>cYD(G8@a(|dw6S%I{L{@d zLVb^7oXh1(M^DQQ6MNtsi>i8ikFvczyt8xnT{nwv{l;fo_e1Q$VH0GJ6>TseTx%qX z{QnS33M0<8JSrIOUAQ0`$KyVM`))l33ip?_FPq-YouB@9eUPpJ^}+OXPgGdoP28Vy z-fKcd-qBc)%o=QsJBVF?xSDw#osGjK@5!md&IY3cUVlPT4K6w%pntj^q zs-Kxq?WS`uLj%?d(-SycYjt9-tz&7MrDA|0*XhC2>KYB%)Bd-dH#f=;OdUo~jTTD^ zziI5AueBA$2HptM%(zkhpsx6NQj&OBm~=o8{kb2>at5gR05-B}3K|S~{o>(aXRHL2 zN};42fNH1#Z+j8>M7Z1i=`)wLV%d8aZ!H80QTb#Q4Z4A%q~4K^Lc`AsUht0qp2LAa zB|H6V`WhK(KALY~$?K@a15#Q_ZpYfFn>M{uraK~%^Kaf)Kj;4?@{s3=@MR8M_ni4v z0QrQWdqwl4^ci}3uHHrSbUQR{hISaj?vnJ3+A+X&xPEJuC4$a3#3RN!}Pxk-peHMf^ubk!yG#TQdi?7s6i?wfT3 z1;8ViuuD7%Nlxr3UuG*vC%NkxKJ%RU0lQ})#(VdqVAA4${ez10O z``}w?wt%1@5RAv5nHHydFW>@#j?XQ&&=8ZvaFY(FpOG6@KS314Hv=N4D-*f_KKN}N zN;&;``_pfPt0#b2k*31fv87I-MBM-5jZMXPY2L`Kh=>oZyxhkc?&rLwtEq9?*|GUf z{jQ1rE}h@0w7gSf%(B`IX2x*$-q$ia% z;GfQQ>P|ylIjYCU?prrJ)+OQTv+AOhJLYuI)5e<}3)NAc#^U4lOmPcLL!Q_%bs6-| zbS}f)`KO9!->5uNGPQjjqxE%VvSw+lJf^PhjOg+USDxEk3bZ^4{wqJ9vfHbixBC#z z7-z4*6O%kR(D3~`8aG8`HZEEH{ag)-`uK`lFuN6d{~>yX=d0ZD_!a5klPfFY)Sfju zpX^0+27+FMp;u(R81CxwcFuC!MiQCFQ>Puhd(OCUc1ApA7e(qmRf}QrZL9@>-F1_h8o{D7) zJ2FRT32l1^SIF!M)7}NLbzPiSN6$9aV;>x=PN&(D@UG0;)6N>5 zcr8|TIYYBy-MQhi%vqAxQD~scU9uXEP`V+rOHP!)Zl!LDmE5YRqh^k$b|;IsbY7>@ zqG%7TjbJaZExrGSvw9-zNYA^^sQA@v`Zql6^v@3PGsvbUjhHK^5qCPKE#wFh<=Wq6v&TX&$|0+b-1Is9$IfB{4P)#}FOggiGuSh< zfK$cyz3E-gv^B$_@rL!h(SI(K`CozUp9{s_X^65FC0{nYmeHNmx4?I)wDGH+uXS<& z!RI?A3d=95$PvbNJf%uBV71D5aHeLv!iemyq{lc#;TiI4N(5`ccKYikuz}7L9RhUgA}RGUbBi6cGC{>&{Nb8mY`GK|amVNPOTX!unE1N#boBQWelmIF z=izasdq@x+Y$0Z7_zSc91EZ%~aW!?cZp(YWT6}7XDE3!ko7sqD)1a|b{ra5!=@O+A zFRVB|uU~LK(*2rlUg0v=%+$gCwN-gj=21n3m*4$tlM+sUS4PuLm|5P>@Zx)JOTusR z;tfyVBmcTO#x}JWwN&3#wg4jrSTcSgNW%Drw4)X3xhpxS@Or=78Pf+rSOC@8<&nRg zDro2Sb3mYgH&8r#=!;vlj^$hV^g5l!cfXCEY>#xTccO3qGj{p^8SuF00s~DP*dQ}o zws&wk%~>jL=smW%DO55O8eIPrOESLB7k?^DF;p>CHudT)zJJ2Jrii`O?}Cu1^RI&N zm`La@15^>RX`?|V7fV&-FGRNqQBd4`716Bn(eByFcfx#)jdQ|73PCDS^}?Rjq)-UV zI=38=rXD9;kdjmP&9f_|!lRb$74nBCI+HY@gUuOf%I^DiXd#438AVB*ZQha=fTBLg zl52BQW%1VREWL=Uetfyhrc$N~1Df;kEQ6Nt%qtUMsL2|A9RB`cgO2qhsNS!0m_|J0C1p2ebcZ!?I{7~)4$Q~v$m1*`)jmqooK?p^?*Dq(^Z307 zRbtc_R_6EM*)pVH`AP3nGm+xoP1LSk`$moAgX5YB+>3KYaEC0OUmANSw#-CjOND573{#-=1zb~T4?lI%iMcrL{u{RG0 zcQilrnB{3`b1G%1qzx=Q*Nv{IzH+0U0}7mXo+x2z&tRJ|`D?9cfJKg?tI~;wOGY2O zqfC4d92Iwe8agG_@e;ej*7__sam{5OFISISJw4i66BL7G^K_q2PB$){&ex2qOQx}* zxY>#kz4}(k$jtTWddFyUfqY|X@>yFLZPM^n3?shAHCA% zVGlC;Vcp8C1Fe-9FZ^2&_U@=&>~6BWv=kk zE9JZ2BW?b1BtuCVf3Kx;6gNdgLsBid5{9`sF~(`x|0msRr5n<`hba0 z^t-zZJ0#v{W~Q@YZDHh~jq~ua(aESmuegyN+S<6RRcM;s|Msp4R>0;tn4pEjNC|%U zE1yEw{51e4vq5z0I9oIRqt1>;*R;Lc!K`h2yMD<4m`HPPu22JDE4yryZIu z|6@(tFP*sjo;|zPN`bC{UCvU+fVcC<)18Y|zxtlmx|9TKvAiD?n^@c+IZtx1BDK=? zPf5)0KO2W3=Yb@jH_V_qZc0BWNFsEKL7m~K`$H11KfGW5c)fTCz{a6rw{eO>^nrhM z#6pj63Utn5(4=jKk@ETNKd<^amtRlTPVRfuV^JWNnhOsfxdVk_&K@_c^1vPx_OvOV z`OcE+a4_PnLFcllW=537z^6PFoZ&24;n)tXMWx#%8LE!3CVgLAOXmb%YFx={AE_l> zGm&MLySjd!KJ;m7i`+aBQ4hJT9PNYDa+_+W$*7%IgbFOjTL;zSRmkK9y52hsmD_|q z+}8^w+HGm=2si1CAx<)|%>#;cT=NiK0m~PaeD@=^QpLb<_GEJRAyPy89y9LH_ARq9 z{eL^|oUXiNz?`;xPBQkf?*a;+3nnR*@-%-f5p zFdc^-r1T|8y%o#PUo|~VhTMn!4HV9yVmKO%+V0k`gQgddF-d)olsM@Sk5Se;4NVXt z`;Yu*oeaw%wj-WFB&fdnyz+U_zKM7MDGB92>^}ghyZt+l0Ry3bFa$vJF9#HXSl7R$ zk~vrQ5Ocv%2DO`sU1rK$1H$}bx68ZUshJ+NqkY49I;KgWQ>t+eZaT9dKG`XZqoc4h zkOc_=c?`K2cY$(styElE->}L@=Gj>;jHGx6uY0y~dVp91ybbhtc_}{cMG`a~j(c`VoQ;ZuNQ&ViQF8f1fqXk}Fp_tcngJg^wR1Qm; zIt@V@R4kmzX@Vd%)|S*UORw6dj@H}#acqY)x0lIWKAfJEx=o3z11pdlqiG(0QZV2) zNk|1&K)JBN;p@e2 zKW*bgvg?CpW;h$xL_>0_U8L1Ik&@J2q}wn%)vK ziPl!k8zsxGhZy#_b^%fT&royW<6KB$Qe?8XmPRXUzqtC>$k4w|h{1QZUSSLr1xv(O zm$714w(zb{$baa?7z1C3*|%j+Mal>ZE2k(~;sTPgq}m3Jd87+4r|bP|Ja#c;fi!ssr}$Do;+YuCkJ4t{+MNdVQ$nG8l} zZz%A}ALQ})VdTu@Xh{2YrlL55IKywMJUSDdAqr<|GU*@($BoA0-P083or zEeoW^h-*eD4l#s7nC05rPjD!NwKTW5*i)|oJ+#IJ6;$s2{of{_&xo@jFra zcSr4*#^Rr4_g^<3Q|}&S-gO#(W__+(F+h1d=MWDaH)kl%1$^}3JBXnC{$6Ww&)UL3revotibxEz0D?NbU z@?XR@17o+k_d91i>tn|P`QqVuuTiSD?9CuI6)w9qFG)o)H;ORj7&Ll`EoKeNlQjD6 z(-Xq!%3*RU-g&Gm4y`^rzQSlC8k1))YetS%rYvZ(esRIGu zndB5ff8KE`ZvqgSp1!}{u|`I)-U=8%KKLYZ6vXiA~J7+?WX-f;8JCy#~x{# znyGE66=6^peTVx;*Z4q3RVQDX0{u83)Uk(6=l5P8po(3*Fpic+Uxj{Lkj21Dc5ls$ zmY=R(qotcRE1johs4jGxJDj_qN>+nX4pRoIvFB@O*60foPjP-1;R@$+v1grx`4;yu zvFEaj)Eg*JRy0$)U{@7kCQ91=_JN6VR)H^Wj=*YYYy0YgR?6$BMyuH$;N&3e}PXC{o<6ogu=sgtQ z{-WhYnkH%OUzWsof3)36>-U{{t}Q7e8lIAsC7WFt?BQ|hvkFNEwd~h-CyZ`7hYBrq z32Rwy#}82CZMzfnBE@iRDF!BK)!=G5yE1v5s=XBssED;Oy^%zH1BdW>`ugjr!P;Ki zQ0+0S(6_Ef`9n4hhos63cm)Ius93ZU`%LbB9LT2c){QVrdFmrm7#4DkYMcVi%4(#i z_tJbsQP) z-@_fwl&7@QjvvF3ZNUe_&qRvx^0Ron)2u*(9NPOb!KER~WpvRI{@HXt>_ER}1(5I8 zq(IGFHc4rzuBVI0?Z3Q8UZmUoK>_(^!~C>q+#mJWU+bgqSpwc$JnUAy zo%Yj>;x3ykiJBR}IJlYw*F;iQRxmh!{F*qR8&!>5;y(_VH`EQaHj8+iEJCUQM;2Sr zAnW3`v2vT%cD2_ce7Dn7W+(PNuf;w0sMb{!GiQ>P#wpyQ#`4VxTvR=&s7KYV0z74r z)=;*KRLl?Fb)_q%srkMk9;cSuW(dHt->0UQ7L9{m>8rFf@&b!EePiL8@3yi+i;rzZ zY~MF0vDq0?MHuJDs4O1mW9Db5fjS_`1NC-_==+IXC>c}kv`)FCoZu3mdaO=izisPH zV0u=ir7_NFJvgWrSGRt^$oDHxxV5i!+O={eqLX1wcb0fVI*iaPJp6ni$?AGB7NVsjS$f9iuQAe$f(dTOUe>A?y&vCWIBkAdpoT;7h@_J4voqOmp#w{ETO zLVQ73*qaMh2)P+CG2<5#yNPLd*JC1NIo68EMZqN8>azi$f+5AlA_q7)IAFkl=;X4Y zp8n;82L@9XRQm*!mUVrN>hM zjksuozy6cy0FOIpv;+hMr0K4|yL%3H2@=soz~=tR)V4DY1;b`1&Pr{Q11~`s9~B#` z?Zo2X7LRBs(q{PXih+_G+G)7UKnU^v!R@sqK-Zo5GerrpCe2c23BrW1Y^D7 z0j$IkTz%^5AWOph7JU$Y?NyFDJ`nOdjm&^TCIgp@@(h_p%+H$~@%oG{6x$Ig8~%SB zC=)yiEKa;6j-WTih=_N@KV(kSOv5pM-`ogoo1I%EfFo?@`1oyf%1WRNjYhhSFsU$6 z`vf1f{m~JXF~k13%zJ*1j$X!yafMTnQmbjGoAKv9iTB#R{(~TK`R&;0$TqB?_zlVN zhT2-Psi{4)VR8AR?>HleF~WCJ?pox2x|5{&@orkbasDuS_Hy0VSfA>%Va<>P3<^rL ze(yb*YR-^yN1;b*B24|}$3DZ&_?o35o98t?kz|L0Z8_RHAIB#pai?0e3rNNr=?MPlVipnW=O^H6&bLt3gdheY4To1@7uKAK)Xt%ij*f~#W+!lhu$pX_F)`J|%JlW;G*=v<88SqY>08wSL(39bw_@p7 zXvs=&9w=2SC@1V9Wl=zI@c7ieUcjVChZ7aZ)WJ?oAbu6~01Di-V3;t5Or2?1b^!TM z$v}Bfs^mtRLun=Q9}xvK-1sb;Hl{F6)@(Av((OFNHHk_0<=82(?U{iGlrn0Ouu^UV zE}Dod8dMYZt^6=5yEupU5+kJ~*kS2q%-phc?rGjlA2LHM0&+nD72ep3s2`|UC0)O4 zKQO%jDk~n=olc)`8<<_0!s^POEtQ|1{Ms*-@X-e0#>U5oZL|qnwNpPl@DcB*};&| zK>$IZ0`PB0m_&5W&C7}~Oadf_AHp{)vEGR3BeLDpecz3a8ht}N6yfUsNjo+>QSDg< zKlmg_!-p)jjlk>mhtZRI|A#;I#5=@hZKmPsAik$_j`1M$Py0$~hg~F9fPu4G;-b{ z^&$<3A2R}&tYtcs`vZ^bS`ei0q^^x+!AcA&Q~(2 z`TsvIyw7w-d^rQWJ2UIZ%OiIKrF~|Ha`6Yk<(c_VsP90V0(1s^nRj-`YUo&4gcLvZ zU*ILQw{-Do@pjLyM0grZK;j+YT;4KSLrEVgiiy?Gv9OQds}#MQug#{Ad=B^xsRD2| z_$4Ho&!sAaHq9FM;%4zNf{gd&Z>l!;9SOG%zw!1;DeW-_T&w`GyPvD13^rlv)%?Mf zOB=aP>j#F+{LCa1`wDs&ZrOjSNVpGGi4MS9wPIHA9I{BHi|aorYF&yq#(p5$EpR?2WNQ7z1F? zcP6rf4=YmD_?UHXPekFdHIexNA8OXw*I*-p?Ml3wR5iXgI&Rf<{lw@;olvYdwfl;v zHuzf*S4(sZ#C71eQ=jalPU*>7VQfGaxLOVd7c9XK#qd!O-N1d66SBC?N6b$oI%i{X zwzl7kUUc6F(<@lU6VHlR0%kY+pp?1x`KV4bOhyxyucEa9g?%`WoD(^b91PAc{zk;=Xc~y#2Oo0>-RNNkbg6+9iO1ss&sUB_!|RF&%E- zY+ffMoRyQ8~?rN8$ zcD#bspg^=(R)q zW(^jNW2q+>AQaBH?ClbM`Tf5QewF5lZBBzlC(t)()U~PdMzf8i`sA7M;(*XJo>=?7 zas1pg#rNa>#JW#?01UdoS})~HRfYB>Y+f~ZY|COOOH+#Bk(;v>1x_3lYi4#{ubzE@ zLbA5*x5h&mhCV7>x3W8Li-zm!+ddEN(&gZ2XnF^2=wr!uJ)woJovHM(?;a0u4An|K zbB~goJFR<62Zx`2j*0a)MhVrX7U{N2mHp(GEB6b5c@lPCnWLA5DAMR0S!&7Isg~Akx9gwQ=tk5$Y8P=%E+CGnt+l$A ztoi2d$4=v3+1R@ELqM|fa*b~Cy>g=gV)!Xx-0g*LbPZTur>2{b-HcmFxxg-HPWaiB zu=2@AV#(sIbUc0)vJ?MH<@2}BubcbmHYV)PCm=P5a)w&*w~|F<6jce03=|Da_wL*E zVOxs89by|Sj|*rh&(j@2Qm#qFrO4eq9@+CtBZbsBB-dMyYFL5lYu7?r-(dq7dM>7p zj!}p;`}vM0bPXaeUjr-fpHVX~2Z3cR#HSN3;r2MOp?uQ;?063g6VntNL_kWZ#y5+> za9|rb>timxnk<_|4Xbb(Yz*#0c6Tw$i4q|1#pdDyC=8j#R!H_?@T=pDJ*)wQSjRJ; zUa^xSxlE96QCuUGo`{{DT0AbbXOf6@s|tJYEUs1lJ9lJDMtTE8E>O1$;~kexAG&Dg znJxBbn2lG&X=cY%<JyMU8US8=o)9>`TRuJoIb8=ik-0;m z`ND?iuOF7b>cN!{Nu=o!vq13a59!$3FO>Mf<0W;(yvMuP{>#sjQuKgkGKyWslRU_ zn0PwAs?@tZ)$mXtw>;U0*yAbLp(8J56uF9NeQOmTu}lC+~^nT zA+pDgu2w9>&6vGNeMV`*RsNh_c64;faHN$G>?MM`s!UBh-qBF=vdysBsChPYC@wN{ zu?&Rg0Zf#&=nv#ak!9?a#v-YJ{!kAZ) zkpoU;Fxd?T>mU%vff~Mr!^4c4yiXz5g9&9QGa)9}*|@5w2d|wzw!W+OF&sSo!vX?O z;0ap=sp7)VvW6*Sk{FBuj&6|xcP-E{YZ_I~_h&G9Tz-no1bz9EX5A6k3)htByeXOL zK|~z<;e*{F^XQb<18h&;%LKE4i5RAaPd!JUoLX`#(P@bwMK5Z%aE%W=4bEo#SRokD~x@T7@B-R^4)E_ogq8O!A{V!9=g8+{Ix%8)^_l_ZW@)YF|3v_wmHg z&``Q|@k>PcJu426V19mH-_VdB9v^Q1<9p)a=fXeOJMF)QT^=D&HsikbbsqEpV+o_CGo-$a^~ii zFpq*;yF}*3?~L>(emJf;NjQpIl(F!_Q&5%jerGGez^<%%ShWt7m&P?$a)sOQXt1;} zhK=sS84T4iGUC-;&!u72E7z}wG&i4Ib$s^t7Txu($0DQelJzI-omP@lzFL>AB)>br zl@zVX)x7syI-mH^sn3&|SCjavqmL#%USpL=!YO4G#qz{biAg5VW)0lXjHW1Tk$a?h zMC~K9w8z52$?$OZ4<9{s=H|SEMl&a^hZ666!L31=WQYEbD=$O0C;q0HYWudhpKu`?nG#-N?MIUgj4Pv|CUC>tmc^4PjFm zc9E*;@sNN%7@kGp!~EhAXQyGlCg|14km{*gCj{Ig*Wm4=PI2EKcnucf%ftBsPYfGF zP8s$#@u943Y+myl90_E+_?Zu-qB`@(h^$%LH(i{_REXdwKiLkjKKY3SOPN##+Lp#f z#Aic2LoLzWG0<&S1JFif2x}|n(9Xu<{6H2fl@HO=*jNnM(zrBM{xXe50_)FEa76?4(_hLu(Jw#biPs)^>m`137Bqu;zaZF?VIN~k~*N&dnX4?#NP9=kXg z6BZ8Ej;m_j+J+GcK|n=7TBTdMr5iy|777B=-3No-!b<&`#I-*&inoMoj+{SiKnCP|P6O9wb!fEU{N zV57?yuvl1FvKkww^%B93Z}gqd6BkMd6mSK6IAk&1I`xj(6gekOaAl%`cGC%9w}96) zHyBRJ&cep_VZ|A-I!oEuc5Xn%GqSR>x(!l*?ZOJMHQY-gjya6m_ z!2zK7>iOS5kHeJX=brFWiB%X$mL>Sf4Nv2}ccm1cg0? z9M6=}SIUA9Ba+lJo|)0b!hEf^<+Zik4N-W6BqSusn$3to5I7^3s6Q)#i-gJaM&!tm zI}7#?tM!(t+RVcT?OP*F9uCO3IPH>$Z7CM7lwpCL`wHs{LOEYuH+b`^Bys6~qc#D% zG2Q}-h)!f!)7DI#BAOqjkoL_uwA%SPz@1pFIowgSnJ8nVrw@RTkMZtk@gfW%G1zn4 zK$i63oX6t~v$8jDjL`XNH4dNWpKcc5Oe5~hNK1LDfK3;yNUy(c2ksE$RxpRc#J&k} z&I5;|l{F*G)V5ld+se3Vz5f-#Zb#Kx0-M$zz6VbONt;sn_ zO=Rp8pivRr`=i%%vy|x$KV_~UWiAs56G_oca{RbZ=3y!)ojLIigwG zYZUA2M^7beiKxOnpIh=P2$L`ohh4sa6WW<$S@e8jqhrPSMd~UeW2c&ef~Z0H)d=}c zYqhevPRww8GQt}a<`Ek>!Px=$WNPxLm&=Dgu__-1KID*j|2RtW3o{9R)`n=RdE1ur z;?y`l0rEHz*FkUZMhZ;bCU;J3?86dfjlZ=3 z*!6l`7^#AGy{flbOoRPzQ0yT#vM@@J*u5#kQ+yE2vH;p#2{!r;ldlkSpLBKR#xit+ ziv_s+Ja(Xrk@&@eSTLsMUkQ`*T#i+&2m8`X?D;>Jq|!Q#7hnu`69pQR<<_l&yO|Pl zhcpjhY_<5WuenI(P9EF_AP3ItB#L{g48-C<@47;e8sudO{{Z1{BXAbE`20I5GIX(7 z&CTh*e?R4$y&BPp7$PDnxpR{hM(44yvCTd0Br}J)XB%90y<1=tBV!xE!m*!cYa|!< zuSM=8HhgdfRh0pl^&Nv=$BMgICgQUC;?*l6h9%VT@v(U!J8cXfz$JvY<5ydPvA7E` z+(+$|g=@y=(`^sL-eRzsRDJ;DxFI7J;g|>+FmH#43b6rZXz1-sB2Vff8OM9$%F9F{ z$X-Qqi4nJ!HmOJI>O`<>#c5*-1{>i(0gFjRdHJA*ZID4R-MSU?$Ba%6g(_=UrR?qP zeP;S%7r28YiWD1`;Y1|{WVBnx*JG}fZP%uHdx^z z@NJ@L+yI4=M^5#ScBvnfrvMBaz{UGpq<_8@Vr0c(&^(#00C6ux)Qv4Qzw+s^GmKSI zr;EKo7U2X|^)8*H4?f{l5R!90+iCqn`>eTH9I@5ho1M_e;*3@L{*gXrxb#t-_tIPQ z0ZO>>);I&YHI{8)3}vJ4@aK3DXi+2ZEL`=f2FMMV0~>`x+@Ex+Ov6OVAton5^8X`i z#tP=tBeu4y2e3ft!9PoU*@qv%UMZM$A!fbi822KYZV>IObzV_HE`_TboMrm}Y@8Jzp}^7QzZNnTDJ}U(xX-98Bf4(H zJ`4YGqse{C44uEF^&kY};yT4Tf=dl<+1Fi-nTV3F&MLw`c_NisD>-`bSt`v)iX-s` zdE^x$W|mu*?&;{rTUk-8th~g+JXdro{UQ5uaP}9cCr(d%JZB{~wXfM1TuU1W%Xt{u zwbbDjs*n@denrNgGAEX0w>~5E zf6heDv7%5qwYC(n@Y`0Lvo}Qjpzw}hhQqDV++&C_QAI@^#yp7689qM#H~GR<@REl? z-4!!i$hQ$QO)xc-#p&^-wv6ar`uS}v0$i4>4K!>aM=N<$N2H|COY8aNT%*TMv=MnT zSno$ti;NQZnps#>8@4_7HhFDDi3D80rDc1w;E-xe4#AfPj9OvVSy&E>T&^Y#A*CF| zYz)NfJ4W(M*u9CS01dg6V5Sgw@Iz)6SX6}g#eydrzPx6r935hlh`7~-kd77=712pb zW~Qc6VtiQO2IBT}|Cc!kQ1wu0?|)Lbwz|sev8|_tVx){3g)%%}J}FTMg`}^zev^CY zwb~+>{^RiZo%welPGGF}-Q=Ou$Jo;xWEVR-JNfOVe}=XjOA^&!W1a(KtePfh_lqssXw>|o8xDcB-birL*_>|aplDW^N4Fs2MxNeL`Rho2<&pZai(+gvPoJ2F=+(6Wu zP@eF3CVFDWPq_l<&>U{xesmOK0R_LG8e8Xk`isZ(<7MJ7xfZFkvJJ#xs>W`nc7Ag6 zk_!YBntssNtzzZWDQoNZ-jD@E@qJ%+a7T3; z6o4EA`Q@6L8l3ZXQB*?t_4VX4XBgv`o`Rt^@`Qg+Z|qkYwqf$UIF`Ncdvp_?uVAZt z(;P68?7|u9@Nj!TIVTT+k2b~yZrCV7#Gw`)HYdk{*}sNxChiZ0gy(QO z%r}erH>+|r1j3Y>ta)BP@B&8u&}=?3n=e-(N(P03DID!CL$@ES9X~MeVw})(Aw+z= z17@t&1~W*=$j0&BytP6H13&K!)|n|hZ?B7uN<9*%U4vt^d?Nh_J|s+O3T%+j(b0i1 zV($rRqTmli4mRj<8Tg&!PiU*H!5SBK)tT}flO)yHQ+T7@^E)PKfr02UZac(@VHHQWK z_rf6^6sNs}K^qf-;H=ct@O-QOG@%$s!;R}^;P>H85F0CuZOD|~{r;i4xGN0Xa1AmW zI%*<-cwaxaN+L>M$Sh%nv$3=Ln-*FjELC0}_4v`LFc++L&^F-!zQQ&HGgnxB7{y~M z|DY3~h7hO3fcPQ->XJLm@Pl`U0ECF82nP{r4FEx^i6{gI{EHWr8HoQ>OU)=VXLJC7 z^c&?F*2uC0v+ElBxyE^C#Ec*OXQv{q1R$A(L7KT%e?#7`E01H=At%0jd!Gd3JT8$b z;5kLt0fAU0$NjMfdqDlZ1`wvJO9>Fcj{Dnd7JOvZm_IJ9rQ@p%F^_!6{(#b>aVk{P zBmsa3kLe27&F9tBB#e&UbJbTwp;S~=2e!Nlr5>@682|dYj_8aCai$T2PH;VTlv`sI zb~G)`KK<1VN<95We)2EHB_#|Hyfs*`7y^R%%=@!^P7Vr-bZ-rhmp&4L;o`A4L+oJA zZHfRMmzf%?`xX?wU%`5F4Qkwc^u|E49nL?wR6e1~O`c~l^eV932*cUg89*&tN=gcV za%6ZWSTEaiwIh?*10+KoPlbocB09cW+!S^k}ZN9t)T7`Q-@t`b0`dQPC_!#itON_Vc&)j=#>gh(Q4NY1v!7i&w*G z&|Giu-EJUN07=l{lVcz*=Ac_LlxQt1{7B#yEOQfNMXeRy`_?YEEe6xQ-jmObFaebp zeH%s_9s$GmJYFhIcwQ+>?LV^1j$I)B0B|8W=D$Uge*~m%u?C&Q%Zi!JYjXd3Vd&?= z%&V5@o3!WWp7r)#el5m6SyP$t?HhMiT-<8=iu=NDqhnLXQ8O3caP6P%@8Lf_b3byH zxEw(d*#35N>b|nP{Id+PLk&$$dF39W-~KmJt#9(tUo9U}G&jd#Wi_a(=Bs>2jrH5e zeXHohW15`i=5Q%B_(LjmZ#6km2@B@J#*DkyRNKc`Ti0RYgn32=(lQd`T_u{h z9QBE~jPMGazO{mK9AwP*sN{LHO32vPDN^!YTg0WtCH8kx;Ezm`XFDcWh2s|$6`xbO zdlzVdm;L>&PbGwObgc67AX0LkVA^C^;{>16%=m*d&0q15`@CJ4T!JM(oE3nKQJ+3x z4fB&0prx&gF2!_9yC){q@L!{iIX_mGTi6Fbj3b zy{Q3a#U8J1q9;t0fEYM%l4cvyJfdUr(U<>f^f?E~TLGz}_)SbZ zkSw*5-}bH%36_L|keuf^V6UT4iE0OOoWCYna2sJ_`26~5baJqz_|*32_FP)FYzQsF zl-YD6p0qqB3N1$z3_EI$poKw@N4tR#3WW^YfUSIkIE?zov82$jAdJC*wdd`89q6e9WyuS+3m9*~At6t~YF`~wF-r706@THTS@ z@@h8~(DDDVSB2-5v(!RO?%F3Z{>L_6^h9vP;@9}Y^nY#R3%gYNe3*8PL}6H8MYXhp zr&@~R2B;3dloRDrv9Veiq^qw1lYPE?B52H78XX6T{ERH?%aKtz*@Dr<2e17+0Wp4YDT?Yx2lNRV=!mK01) z^IpUm%c9yAl!7OJp85;UDd9|W^cZFoeIpN6r@KN=8Kt44qmDu`0*V0MY0Et}F%c*! z20pZ^bI7O#tw%4ZH@;eGeX@`C-nc)pV`hBW46`4x|Yo`c?<-&7bX7 zFgGj&>|IUB6*3UC4Q%2oNX3Z~88lEY0Sr`CRS`81{VA4u1jrKdg{J{L1yBh6D}^9g z-uF%s^Wc)m9HI_@Ws$O53djiPjXNqT_y_@_UU0Q;W&pMbkjpoLV*FtJcF|E7VPB9F z73SN#x39bZ=usamF{GE|lIXT1Fwv|W9H#Kcq<(mRzI`|gE0YEoXkHUpcuEjPx|_?s z14U&-PIB!UI!8VNr~3?MQE=Be08tK1H(>wF%l@_U5oEgv2Yi@1)YoSMqh#PT{p+)< zr3t> zdH0ICRBGmIVgg=H<4O&poD?9e)KdA6$9~)2_-`K7S1kD=O||ae7O~k(y{%3yr8>N) zPpUA1YG$=h=fbtGyO=cN-@Wv~91Zo-$-^~2*}D>#-$X4PPQVF9eHdC8{6(9|= zPgT0Ir9Cf^l?3hdPsF3y!Rwvbv7M=?$|xLjg?P-@m4eUFX3xYCmHZR`cX2*S)E z+1yPIaatiTEv}!lpEbAz8MxYg44U@Pt5M_ksEDpa2f~lC1@%;cf%f%#0l45x`Oo;! z4S=`tuTs_B-MMIE()uG^ZME5Bl_Iyq4l67iu*b%vwNN*H>L_w=e1po+oW{1*%$~y8RJawaZ+(o&9jPdvT`?^j4Lm!te9zOC0r#qs?-%|mbe8cy{9-4 zFK_eFQ+GXku~aoh&Hcw?+yAW5L5Zq~!u1|W5K`KK(@Aus3JM>j5A@pL0R3!OQ*sli z2Efgbji$^NnEcIh5Ivy`;fr}pH+%r|-+6&!us!*}4@s^$Wb%Z;3G+|))Zpw0LWtMc zYUHSCyRL=?icvg*jPrwW-!-{}28^fuGWBI7=EzL@67P zqAE*E`%|PBy?OK3w0R&r-dwW?SIGUjHIoDo^#(;jDii?`nRsIvv=FToTqcDt@lf&4&AnTgBF1`|!hmF%pWdw!agk zW_-hQE)(E*fieim$o!?=|DK10L(a*GN4t1G3k?*E9^}hf4<4NFNk)NP7{o4qKW#KW z%rg;%EWkhWx+N80Y#{cvf4FH(tOHJlO?xCi#2P|nc>;tq(nipq{D6gI5q9=XPEJBK zG!Yo8d-@ z$}|G#40--}2lu`8+tErBMeqG@oybgzFTbuUXW7BDBo4j$;io(AK@j}`W_EqAu9XHt z8!Gq+K!bB(!s|B>tJ&c2O}IU@F;Q*-apAApW7YPhATm-?Bl0fIi!}pKhy!qe)6VVK zGzV0{=u=KC%TI+@Ai%w@sJI-{y;uBePU^qNi%QZD2cN^~xy4>=%{r$uuu8acRBWyM z72lxzViP(V2)lI^oaqwni$$pfHCuImhW<3#W8i0NM1K2*u`%HQeFik3pNUsucrJPQ zeU6Tjs%oy<#(k^l8oU%8ov(NmBI!_(hv?W7PFg(m&IkAHTTNcxQ76$k*yb-@tuhKR zUws^o8#5D>Z}retkY7y}s_F#qC$GswT#4z%3$hNA%hA&Q^``K9wb`DaipS1tCas9} z)sA(?_>7lo-rj5jX_<1m*7)8Z3?EpLJ~_mhY^qDwVEG8gkp>E2Y@W{v+Hy3HM?}Qx zA%{~lEn%^mw8i5rHQWHxWHprAUTg3bX0nKT2HIWoKX{+}N(wdwC6HW?qBMh=n%8$v z+j_koDJn&t;d~Z+q-6#8b`Zl3YhX&DP>|pWK&8<};TcdR2)AcHn~V(lK`J||EwyR< zRv%!P3(*q_el-&qG=XI25uMLrd%BJ5KstT=fYg$YAOOw;gtz3wgj#)yhzrbG;eR94 zijeNmiYRG*qX;U)f4$>x5_uz_(U8^>a~5`}T|f@-?(CNhpRpTQmfnK`g0HWHZ)>I; zoiqSbV88+>s(b%&VE;}CY=@>9D4u3gTy_?whN3-RhZ#8zTy%})NY3C8DG5o1&x!jD z3g&N9)y%*J7xTRe&-o5R!D|@a03uN7nyOpS~*hhWCCxC zy0z$9aq14~ee=;`1biEI+baMM^x*%7l!EOV0L{VpC2ix%WH0-N0DvecC~!}w+&0E} zEQfEnJQ9Fgzqn}3=UVTl@An1>t|G)o9|)Zf)EgiPN38nKj3>G%@oQe^=l=l4E*|=& zEOgBKlacA@15boN_`~ZkFAlgD5DFBWHP?hA8Y4S6h7t1LV&+=iQ-U<8i3M= z4>GVFjC^m~&kA$Fu-5am%y6sW3dcnhUDrp0fJ)6}>D9!mc~jI2$|1W~lHNbRw!usS z7)x=JoB+fX>5+4@u6f-{DCyE(sZvDXz2ViqEr+-epq4iEhxksHi3@cU%D+w(R*?mEsjq2X2S6+eHy{pk# z8nd>89=NJ*cok<1AKQ5D}S5cQa@Hk-7$Jk4)Q!Aam&XTv;k)I2h+?uTFkJXpQ9#Xw|c`0Fk^9FL|N5k!Re8c=vJX1O#=O;nyps1Ke2jA{-&lD zp9(dhPM5qr*Mx?e0H|p;?l?eO00EU?f8<9b2cIQ){xTt97&ZrAjR`r9$E*`B^nvRK zIHd#9S5Z;1oNE*aHiA_JZ5WJ*sDWM|fCe17F#o058?8Zt-TL{iyu5r1%ShY!-Wtv{ z++I>rQsm@@H@I<3vGwQh&)Ic2iKH^VPXiT&ESmlyYsFkm$S@V5L2ZM>K~0SiI0C?} z=L{OcZ9+0R)BL8Nu8GdMFbQ7j)oGD9-0ayVk5zIZX zbo^sA-z)+%rb_m1tD%#Ho#>$W%3asgzVHRS6>@1&u$uW{{Lns{(nBWGn9R?yQECQVkIH)GZbsfCBr9iaYz)aL=(@Imx|0d&ZJ$!oEQVhn091oE0n zYH9)|>9~*nKwbpv?k{PeQ!A($;8qPl=gS&S!SyHwP#-M-XD#^Ir2@uLLk@rM7TFss zN+czNyZ2IL3u+;8Kx|jS@c?Q`DP$F8e1<{@4Xh~(t{o7&b|HnNPlyz91Sl;RF({8Y z!?dQ6LQQ%okwH9saQfes8!BX}X(}m9^FzJEY-k(fkq~OJJp6LRy0D%ghxSFNr6%cgMaFer#lRO3(CqCk)~Q~70-x<85NZRN%F4>wn(kyWTsUeC)C6n6k)FHZY(CT=2nM^+l?6`@*nPP#_VG z;pU0ZS1D?F<;!>FLgncb9wdNLR=Oe|rvR-ExTrxy2XdTy=vmyaft{Jy^%7 zd)g#HAdpD_^7(S+kfJ!P1(1tKodYTC$8@(Bm%p=C=c9~rMqFm>W(4n)jF1vCYZ{cOGWLLP*JpX+ES zOSIn=%_uDD1-kAdupjqtO_D|_AoU#xqWfK5K(s+pG!~{0l{!#wTc-*+sLRV^!+sQm zsx0pWCvD6gly4E`T81dAanEd8(nV-2)y(ZS65cXgOK_Kq!{h% zuH#_^ol8!L6FnTDwu7oD6coS*K|b_k)*g}DK>+y-XT@lYvFKi(do%)ZGND zAlgSEZ1M8)GAKj`n!WZscUlhn-K+pIW=zieL&T5G%yj6Q0J#dBEsLNr@3ekf<+*DN zfe#4yMkydq49nfyqt=Pkol#b!kD%%T{m!_GV^RP5VW8D z2xI?@f*H<1ZN(GnAOj~#%^(s1iREh6hGpf$j{^e;w}g07^@p%y!Cj(0n_~a50I}b^m5P;GWMp8r$n9HL1q2w|IfvN$bV*^yN;BJt@ zeFVK$C>$d$%^-7yet>o;I>X5EeDw?!*l19=;Vj7X6@{`Lf-gZ~ivs0D4wp*4c^ z{a?rok%Pe^5&i0}1n~lv9)jGUJ?q;87oP|J#bm8jBWqx%+|0r1ghRrxrdr#XSdT0Y_uzKyaN5*fT9yMga zEHD;5Q)*NxCH{(_=JZH?U$U9nh&+o0r!AFx#S8_2EGUYqPE%J`+70zWLybJCPuYHn zTC~PNF@kIWL9NH$#yw_Df|q?Gp4&SaQEOSXy#``NBvS25yVs>!KpBTYoaCEbo&9 zfoO!s@rx86fd>mH#F2sGA#NN3B$g)&KdxI|Z-BJT3n5eXenN@l28ApYj35NcL$YMQ zYGwn0n6be!2dBFu;+DLEua}2#G{tdH=#FpnL-`ZS*xRg^=^sOQhiR<7q zW(b70)C{y+5P5ALK&1#u+CbJKgOvfViY_-Jigg~7V6QvWQBqXz0ThA`0}HgQAp%Uu z21aN!^@6?RKWuFOMUM3`%P`r6Pxmy*jMomVf1h2**1(d-CO99`9yGDhxu)7_Txm>B zx$B8}JC@+HB|b}G&qGRl|5Plqm6s(C8&cnXE;l(jpm|s-XseA&k&?pSJGlH4tvgzE ztc;wQ%5s}wssvu7Y3smPw zG~9W08;X5V0-wvecFLLf=mQQ4>I#&X;w@)|FBaUV=Nt>`vy-o8=)R{(`2I$$(wUkd zZ47Z#FkZ-cx!ku{&&LAkjdFG`(AGu#j07XB-VaNaOZ%b~k2oi7DT@x!n08s0BjiW; zw?fMXpn?wE46;~s8k|?8|Jd8s&8&ma0jl(+*W`e8g@csG`==#bx$DOvmdDW8>9(kQ zQhHULorZBS4U6!E?k0;Y+Xg86~{Fud=QusKv!p)i9eeF0t&k#kN%V@wOo zWyl4MX(&`+T;4$f4q6KLoq0QnTOd+^lLzXG$?cROvQa}|i0~)H|0al5ArnKCaOaZr zHA!I0bkta(i6}3@u0yJ`pjInxvx1s4ayj#UknS$M*$@R}uu|@K$`05fAu*8_+*Y~C zO@ANlA_|ew(NXV{{Culfke`C)Gq=qI9{LtCnRI_+;`-0YVYdtfSV5PlD|_F4rj zB~C#aP?{iG?ggDfblHX^2!Gr6MiIpekRe1O_E0PR0>T)HO_SAs$R=JSCU!v|vw?#i zbWlLHVFW<{?mDQNqvJO;!?)Tj=SX9?6BS@4kD5?Lvuc%7G(;62TwQSR=7 zMMWTuoHDdUZ|oz35ohfW0iK*oNJ#iTEPJWaX{k$=Ho)%}IunV)nq$iwen9;~7AbCt zQI7OaL846E2fQg%eJ{&o51(5bE79RYGFOms|5Y*FLWIXKUYnQxIcEk-q#dQX(*dxcE&NlnYhY2Qfe~C6yKIDXzdl)^6mnu>VU*wXeha?Rhp3 zcp5=xh~)`W-UdF-<&qKB@ZtS|X;whU7DU+Lqb?XmH*@}v?Kn)*DP}6qy zhmr-~ykfvuvtmjsXXFA3T+u<_bG$O0G3%b0H8j&d)ky(v`3(;$)}OvCoZN?nhOy$D+)$}~%jhx_NUb4Sh< z>)e|%Hzi}0lBI_4G9U`C#a-`@{dbs!gsAGEfMnNgjH-Od&(C>|S|>{l1>?+bl10$$ zzD>EVTW3#$v*Elds*)C`E_0~{B+7L<@DL)sex*-C;Ooqyj-4yb$Jn6Gd1@&T;@!rj2C zM%-}V`k_|@mh~v~(!lYWF3Xh*XFWKz0K^>q{lwSWnytlqpN^BWbg&9}?Nd0^K-PcA zl@wvn;vE|w-##=T1f|*#;QILbNy6mnAzA+l?hMkhn&CMb(9j6HMGuHBCZXSU*OMCZ zBxpWC%!V4kyaE#U+snM~V3Qz-7;Xunyr$(;6(gcf1kDtVA)pmNT13wP<)#Czn~E+e zDl&#%EC}z}MQqRlvlh-?CT!TeVF>bCs8%APGo%v|_9XN*s+gHEg0K&AdM7Bw#HFP@ z8QzBj9%`L_@G1HkI^^#BntY+?fCji->+z^2wPFo4DZ zbJ(y2fRn-f&ujl+0wl9Abk(qH05tFID8S3ZE}hUna||$Ms@aQgWo5-u_ec8FoBPZ# zmXsIrs2I;oP?;h)YSr~>7?y~LNV?zIF(NL7EDq@N?21dAKIHhzlJ9dLzpnp^vJjeh~$$CO1Lhn~^sqL>2aP3bl5u*)^`W$OeMVD`QjRRLm9d3(`je z^VORml)en3wfK_z*=~EyS!CtShGRIHQ#gvq|+6t1Uk#cC0s@*@t zw)y14-u7;&-PpI~4^J8h$RoZS;sOB3YS1jP5%B>mfl$G*9ReHi@Wvd z#T|DMH3YDx064mUYmI3EV6RA0Dr#i#gXprQ4a*sWZyIbUDhTG%0l}>}AaDZTI%1*_ zf79<95GLBKPycMTSS09;rR3aBk~Ze* z)t&wRrmme+$F=zeo7H!He0?6apWDtosfe=U7OZVsCLor+fTygK#o;!X?L3Bea;kxv zL(Prds|%D-J*kTfg!=r!)WX!z{E6SIZh>`*)*mm+zb}MbH$NprFCzvAh~1OMx^Z+S z#QinImyo7f1hK5BUkIjR(ys$b^K8}O%)Df9V`BqJOzwIeqn--}Eq=-+uF1fbXjBe3NGe`Du83%xL=meiIAU?%1p- zz2}12($lU=Om=j+6vVsy`uaXU4-RBCj$WNJN)bsHsxH z;qQ7QHcpNnZ+b>-eSO=+(vgIa<|YAV8%DOqi}7(?%5Uv?d=v*;4r}dmcGMEH@(h$F zo{piwD+4lB@1sslrNVpgV9|-HevUFY+k{;7#qB4iCQ+eV2!Ea<1A4xj9VhhU-|%g1{n|J`Z-8`vf^93t z8?A7l29q0H){2N6K^=EA;dlDr6?Dy2{yB(pcpA{O-DorV_VBZxB=iJ-ocz-Ybpgau z#-}$^n$hw;i~4Og=@}jF$AwsS7J{$_jBB%DvHX9n0pnU^DUlS=l5%Wp%Bdum;3YLk zR$sq>QbQJ1@_b3$$)kS5K`_7X-f3bTBsyW!YSmyFw7k16_f+#3ocaE_@)kGcvHR|^ zs7t80IJ@WYGb2AZx?u5g_VYIm*=*s4cWH~873C@}IU4=rmFzKY`ab=S)8F|YvG~e3 z;p|>vu#`QIPE4jyrnA2iljd6Efu0&setcI_rvAbM?fajH@7%cDv9X_PCE93zoWH363l+3GVCD&}FDp?nvP_9o9J2m!^HR z3~ck4hIS{~%%rY-9P15h*76Gr?o{>q(8(FYNOzSkZB`DA9bC3DA4aOAyq&ozo0_jI z{>sp?BD1aS9LRM>EF%G-O>De=_s$=hd-(j$FpG-V@PeKmo#N!D7+YEf4i4HIS2Fmv zB9$+h?8_@RCGD?a`G|5Qy-ze06^xEo8(wv~C{9a=R=E<im>}D=_-*sN3(i zB4V~d-7T{5O%|U0o$l?yaV$GoS=m`QVj1FlD$nL;XZsOz5g(u1(MyhB-k*ErwMwzL zdo+0npsN>rN?VKfI%7hi59L`1t#@JJU47_y=6L*$8n|@O+d(2*B z0{^dIbd0Pq;lI~dM#dcA}3BMnMpXeq?AFIwKrR}ezw{<(CY+%Lo@o;}j#~X-l1xwA(6Q-{9${z$d ztEI39Elze_X?Ra?j6qantkwGQ@M3}wip6{{b z?#unvE0J&gQ$Lgb^G}Cg4Zu%)t&#pTVRhM7!AjlyfeY(Em`t|t=^E*45lt3}9H&4C ziTPizeJgpGogB1b&sM&@z56DArGSuz>I}Ag8NRHv#()7)=RloY&s zcea_1t@T{6lfP@gR&6-niV~X04#5Y;mv0Mr!%u(Ng|4oej~!jVa(a4-G$)w2n~Tmu zyBYFzf&9N6lK*R6&VAerQxd$-0G@A28PU`#x_nJ zPnvh;(Z}Cod@jFeu4kj`%9Se?8SVrW5`ZX_ly-RNm&asR$IsUx@joI8^!O59(L4Lx zrwRAV6EtjAp)qaDjE&|JZ43#W=3;TkYOYP`621P?o7yUcK=F2RbV${+_dBN-X6P&w z7e&Mtohh{H??%(aHawKOFT!Lo|LKKK&Th*ao?SAD~DIwydt8kmi8AtEAPC@?1IQAfltF4=1X+yY-K!g-xm+a6L34PbR7`* z@O9&eh1=;yKJ>jaclRTq@5H*%`JoP{Rqn)%;%6kL9E+ndtK;8EeT2`V?u*I~@=H@q zVcBJw$=0k|zjtE5^tV&twTj;^^PQe~vc67B_p;WpK^!Xp%0?1EYOu0j1it0PJ^GA9 zQ(pD59ZM;}o4TSYH{)x$`Itg&e+Xu80Gu(CzT}$;0v_cjPb5QTyw|^evjC5I|1$%+ zSWSkwsvpk3+c50wsMId-|M0oLs1z0;cOmR@*4pBLa<++Ia{S*~fQ4n^k+7#!BE&OQ zJ$Zbl{UrHTMl)pjRttwGAYILWZALpVFaZ6-g=Ght+N)hF&rNw{`BUjKYIi+dd;8{& zo^s9F)6AT^i9LD_9h;mOz{qHy6#O}DEc5j}C!AoM_08>@v3H)ivRpjcJr)lvmeE4J z)V%))4n75;A9&LYspdn%a7IOny{fe<#`(yrF5oCbV8JE%jH1V8up)x5yxa4GST{Q}rsif3ym3H(;PsSfTG;YUly1y(RIm^izvv8U>jNN|Gl6iF=$?DsrfggPhNrZ6~FV1 zg*HxK9FbC(oo;e|010K|Owcy*@?)bk4R1#dTQr@WimfX_(#51lL+`L2Shv2feUT_X z?aDneJcknuznc8<4keoGVJcNS_jmF|5-jF8ol+TJ6PZwo?Yl~&v9!VNejg1#(doA) zS2YZL^30aG|AeL>&i4DSP0wo1i>z?R0!{rSM*?M;G}N+~?hKbMjR^4TLlu)h)`u0f zg<_5V)R33aC8)-GultHUK~l8hwd$in>3ezGuPQmk32~ZD7Lx_79vNOdpQPGtm!2aS zOPo?i*UepidE*1^^pL-F+c^u`vtFFUaT~2)FH!fFWO?j}eS~G7SW#6?CRxdsTQ2?< z4QS-$d2(W?{@KT!)lD8+;%8 zFU#V(e_yEevHg=35K8vG`U`Pt(&OIFHEc`LC(1vgE4Cc5ol0LFuVE!WUZah<;w$c( z>RRP)`t|aYklC8bXFrOp;WH$7btu2VW2Ld>i+WjE8RWluU`(#_h-GjxG3mnk7h&QV zUZ=S8c_Fy#YF?oy-wIg{?=PX9ng{?`MDPh1W&EAUIXV9;H5&*UO;0yq83AF=;YIp1_=Odi+N$K)cC8lObObQeN`WYaqf96@z!io7jg8ExS7-0rA6Z9=jKw0 z($?k2iDkZsy(BYzBR((W0DX4GRr}84S-THU`ZTsydTS!%we;>EMK>`kPpQRiD?BQq z!y8q|GBa`bs;PuH~@!N=%Xh1hfU zi;FBT#p{Cd%;++%xE=8Wu_Pr}?hfB^>Hl6wpBa3djX>M}Fi~Dr^&(Qi6j);mM<-@y z-!$-AA%%|$951{y5qx!Z%mQ8~fZK8?l&(hR=5D*^KLlnMl;lW<4p$QXyjM1RKP`7AzE3(uLXuSI=z*q2Hnn*F;YIDa+2)*ADCGxoles91gB zxkM8y7Y**Z@RXVnv#fW0%#mS2@`bDiWB15@EKFbn+_a>Gb_!xPwrJ69&b*ghH4IE# za$KH)JjHhlFLpl6aedy7rs&3*>ELIydPDDezWh;EX1HLABe}#0;FwV&`*DLJ5C-6Wg zY)M|2p{U%M0$x^D1o}IAaqCeAKeI|x;ESf7ANcZ~`#RINu#>gQtnu#OY}s<=I=G5q zWEOfBDm9+GrO${tA=a0`zkg@s)yP4XExg~~Yp9c~WRWnhFDCrcfJ)YzzU`v+h^xH_ zAHGun+ME|R_K zD>~+SPQQabSHNKA+wANWQj!8mbLwCT!-~>?IPs~V0gSt6 zDi`yDUb=rYt(tz6^gwX}TZPC~_mTCeT{&OPag6xMHg|d6E&7_Dl=iJTuh`dc%{6Dt zWObCpHp+Etqa8Qu#qVPm-M;VijHD;_JhitC?v}n_PyUM5!i{k6*1Pnk@gN=D4OF{=O8>h#xl65m2L?UoOejz;gDX|qm)y+QFr?R4 zmM?T%8g_AfCPaiA>XrKNU0$l0%kx4?v2*&Ll#LD?a{VUE1?_)7JDjGT4$jJHOm6_! z%|SC89Zf!^`zJe-2czn~C)?Btl;e*31%qp=5jL#Xvcv?{nbf+Rr95&QX2~hr9TyaDTi`I{>)ukAR$E4kGfE~)5%x1E)?481eksR0OV)^MW4zt$&L$cy zIyrx*MAVnq9wtIU{}+zeOpQmM2TY&-T_T^Kx!^j`KEg&U13esXKLLbS$mVBeu5rJA zg*W7LerZdT-7eE2iv6KzT{tNrPH*+ZSM1PCRH|hiK!xlCBTsP7AG(< zn=+}_#M*!EJrEMyJpdcV%@O69=ZUY^&`(!5)9dPESH_D?=Y7JvAJ=&LSTdGAC|Qor zOdqOpz9gEJV#RBYqxkJYk`NV@Z00+fx54gLXMV6y32m+RyxUVAXo}q!?_ark?d6i# zLWD1s(v_{5_60Su^{?oj{+7^2v$YZ3n}w3?&MuKVEXp@za$IiVdeE9qoHS9~VOUqz z%@epZ`XFXTztc-K$!Y$_F^B!nd)kX!%o!;RmM-afBGv2tdGQfH%q$KCYG!dl>_j3X zJJzpbDV#0bu0#sq{wBZWab4mkx4T}r5lh@gE8uD;Ol&s|{|Ovk(^#?o27l}xsi zK4Sj>snxg|JiOzV`T2N(iI=t$qe!>hpWxw~4{RR`Y$pwr0hhH|tbi$o*?heGloo9? zmc;e?xhWs2KFk@M?$}A9htYB>xcc#58>6ztI!rWw;oyAT-ntpDd2Po~5GiyizA7Q32HI*rg&DT;da z%OkO`n>7`WZe<;O=;TM?7hzlG7zR8LeIb0O@kF-vo!_%dC;ATsRCOwT%aGOnDja=J z&t!X{`$_ES&fY@y&3T$K`A=NSqh|XY-!H{a{lRIvbWqive#xz`p-`YBM|X)K{6p2P zB++~|CTt>{M#b)xS7pMAn97^WzVm1I^uT3qQ=#Y#qI zUV(c!vU|qmz9S}Q!6B>YhsACeFWr41(D9_*)90q{wZ~F>IW9W0%lY?~XRhU?2Za@p zFjL!ny&Tq_HZ}IrFy>)ss}m3Vqu>36RMk$OxVZw)^^sk8pdKk;^XpxprI`DU{k-I5 zi*C!?+rPB6Up?;mT@-&yqOz1gn<;=E`@?r*a&JM+4t{oYcy0XTuM0c&-Z9-X*M?zg z%*I4|cLuv`LcBok$5$8_B^6o=e^mAhNPzC6}xtk zBL=EhXXj&@$Ge{Vdd+XJi*5hzlx>_JkIXY%fSs2nU@oT0uaEur*He|+Uk=MA6OTI| zaG~D_AF(vO`o-8fdB111s7dFoH|L@LYVMmw(~Qsmhpl%CvMljPYPk2h%qu376grhw!fINH2$&un~)X0M*+nI3X$xjrAiEFj`pS`_193*Y{0t{gqB*t^79dEapO z`#O@c!fIB({jl5W^|A?CErm^u9tAFNPiN5gCR_Ve?4(uKE7$;aw|-$UBEc|rEdib2 zc}!;IaWCw>*yal~<>Ih;cKESM!b9oVaN9`$B9ka)o9TxuJ`67RQz|tM2}hfX10fP0 zV0ZKE`Es=W;i|~NwW$hN97(=6U1pI#=Wc7qUzdVEwt(WBn*T-!hU=LOe#bMOPi7XR;+^;zed$Yo1x0(&kQ9`hOc-IlJsj;gvwZ^|xb#N2J+Q@5^55J%)6Y(z)n62A zwjD*YRGL4^Q}q_9-2ZR(%l`jizqtR4{rcgfWdswCgzWoGkc&9dijpJk(w(kJ8ZTARWSgpw&{~7!DbcdIXAly#crqr~~+!?+D7zK~5qdwEUk32&JC{^uV zuN;lue#n~goET5sb4s-a0BzOzk^+Xa8T$kIrR-;T z4maxY;-LF<*S>rA%VUI^>fs2P^?@8)z~|>61U{uEIn^^FV8F4%wf^1OUFYSuEYBxx z&!tv$+lS3nt2Ky^vlCDf+218`Q1l|xWhSeS-JiWRFJiFWLmhA&RcXGYcE&6CiNNva z)a%0Siz3@+PdnSABulIoa^4hvAt9B5Er95^hN|`mNlvR@MospNCtG69**JSPuyxyk zd2@o(@4HHUpGV$WQLM94qQ3G^ZX6cFUW6Dud zRirxDvsxe$JN0mY_BP2v#IK8y|PZ^SQb zzm`T(S$S@lvc0X)Y}@IG97lBR<{u~83}F{u7gyL6w|#i zalMv;q*Wj7VXNEQbex!Ta3`ri#4Ysh9=3{0ZcCtsfq(FOhIzTCCp z;+q3H>zRYcd%ei>)9`V@4f^MrL5T`a#DrPYLL^9iIiQP|UryjF3$FB*HIK&Roa(1~ zWxB68b2~fjzNX1D@RqR**q)l2q|1=Ta7@q}LBEV*ngvQG<9p47Ps*!I{kT|tk|4|y zwDP%Fw)%L~^vtcoe<`!AJzI0r(gAgvx0+MhHfhiKgv<6eVTy64ChEGdxq2B4@_ZfV zq|~+$qWZT7EuTM>&^fM{FHEA5X`CoA6OaL-$>iswV}_)ndeJ-g}Ww!1z$ct+lb zap!ja{XrO)wPIj_B418Iee{e@vD!1ZM_Dv~mh*qwMV9W_>GY7ZC^!%$Y)OiIe+Top zhFH^ek2K4m4OCU6xx8Z1THn^!dX`_~lts3+AjjOa1yTf^xH*~Zjwo)={chaInWw~d za|+=jba0}R&;dh~w|hjUF=lEI``b3mZZVOe&E93(@H$rF`jsTu*~}HCtSmkBfjTb8 zPq~4ZV;zrup(g|nUvo-lw zC8_=obI?cY)0HzuZPtervxeyLIV@$UV>bY7buJ`*PZi8HdDo zb?{xl-L++|Z4ShY&uzCa{G#cqbEu`Q9bP7v#4t38g* znPi11S+T_wadcSzp^rz|&?H7wfYWb=vB_8Q%wq%E{wIHlf1nJA?>IGSU0;eZfFcWRX4 zv(z(-i;pht3#jwnhz+k1tW2jXHA%H)t`x-sGMdP=c%LUZAI}hv`wNfNPyg-d!>{D~ z$9HyP5%2ftGX&!EscfThv=>7E+qW)0b(GHc%v8Q7E*Nwe8V+?9&W5TrbFGYfNj0W!C(?iSa7iq>eSoic?#r2WT7W&Z~ z$6KT%opTRKJ~PPCnc0>`^9q();8E$d=~|ciX)^xcLTUCMOWuEptHrPCRqN8n5^3pNR=F1hKj$B^I+rZ zzX>LKV%Z)Yu8h{us4|Nmj!L5VZtm=V(!Ff9{>Ey1QO9x76vcTVY12=>pyTHYGxmQzb}&Wa=Q|sX>|qrysatFRz4Z`a48P_%_`0u=B&H9 zFN>hRN|<)NVvna&F_7W5z>wg+E6mUw?8r9R@A(QW$>EvwbEq!3O?U>ZawJveoaeWf zB}Yo_U#*GFB(u4BDTa4FAzIM2#X2q1=&7gq`H2IbD=vJ_rD55t)TnHXw_Z^)uYZo5 zb2je!l-*0ZpE6DUEgYL+8}+H7l*z+!66Hi3%gO}v^>k!+ly~kU$hqY(2WOa zmCr-&4ae+Zk}aY~RSy0VCo9ebL(K*w?!Oc<`nteit1WRS(|KzI7TZizufw!w48qm>pJLrhm`jghP^qafvpW8hKK7*{2YmkNyLkA z;>{zrw)oxK-A~U>hL~~2$0!*w*&Q~{T2VyC&Moav*aW=QR$Uqrz8bq?=Y3h~mtKkZ0vOt5a!_@NuT z>AwbkP5q)V)wJU3=$>PS8JM+ib9B_+afZ^WuB@?E*HhouX8dtAd|$tE2Y9-m2pFhi zD3l?eD#eR2_lp??iaDYON(&06zTT&o+LjI2UrEBZe#ze!v z4mu!8&(~RN{)dtH4-;!IAphT1lpkK==;yr5+WkRT;j6X1qgktg&}e?&cSCKT*Ec$t=~b-EvOwzIAaw=1siezkw^?EW6$2|8(2M zL3y2NJDWJJsNTJ=PRT=<8TrZ(dOY2~DGE9kTcr8SGpf+mu2 z20po=+cfMkmuv6ZHPwC0p)8L*Zo&=P#v_M3M5{^)mLD6}2h;LcO~>t>u$K-}hr&5H zf)mZ=5h-!2Hs(uv4B5@7I&}fdNDqJS={}B!dA!HCnJeENx}6Mx*yxx|T*;zkU+jhY zH2XwFKVTpp^x<%JvP#-l+O|c9%7rUCopBws^37avGl~J}{R$jSa(Oo+l6V$evtQI> zEy3`o};^L1D3Z7H9^OSL3xTL(AiHFo&wl7Lk* zGj*K-1-zFM^*EEttT>#R`>&dciGe`VOng(${0O4N5~0}8f~F#- z0iaVt3{P=Q)>T+pbzUR^&aQ2TNmIAT22%Zv>Jmf zXv*_D4!3bAm+TW@ou#Zb{(?z0(yc)s)!Tb`ND=18{Q5zcrypfP5fY81LJ{+q zE2c&NKa%wl=mdaTg!MD?bLJy-8;9EText`=wH@na4KgZdQJ5@-m}|TEI4I|CFXwCU z{4)L$WjT)L*`)ew1!luZKa?dZ|3ujS2S!hie8XM;{pOTSt-#R!RNZi&ck?u<7T@{I zsl5yXd+nR1+^T$aSkiH#@$pgiU4n!u989YfClPYK&ULJ%PJ7QWisxi_<__dT2AKfB zJMKo>92enrjU>$Yz1JsgytJIR7LJFY%{sK?yirU4VRfby=8Pk@_P>1Ey?eiHXa2hu zXepV*@a-9T(K9U+Kxq8ry=tqd#-ETtB=z+(hD9wIouz&791(E_=LfF{JTVS(Gj7W$ z+gW|WwaodTaiI{gZwsXi*4NagM^X(&$H~dtxAK0uiOUJxuegGf_lCi}`zb@R(wC8F0y_ zBKxYRAH?lsfOUYUC{t?d2j9jNp@oIkB;L&wkJo#H0PaDVnu=w-Nh#hm(FIdiw>P>$FqBNhZBm==Pd`b zt5cyPFT+0S z5CQ00JW~prDvLM`AhtVj<9hq9{SrC0uPoC@gmm1U20VdT@lG@;Y3S@Gz>C7T9C3gA zQ?}N&5-g3aN#bvOXszxo0}q>T^s~ZXi23?H65x`RnMG08Mzz!f$-%oze&SF1?|s5@ z@#48$&+};hKCKfk<)di5yQtPV%Y^d9)ySb!R}8A5w(a~9kjjIi!6a8)+Dw%tCP$#Q ztiK!ugQu$g_Ge7YGzH|yR(xX*O^@4qO%Hyl7j9E59!o5Yr1mh3iKdz9k<3XL6d@8T zvYMar|FDvtpx!My%w)$s$vs1ZZf&!$(m2$X;j9x=4sIZhTQ2#9x|*J{V6%k~d-%7X zny&*s7rRk#F!qkqZt&pAzw|eUHnH@2b?Q%Dr^nIwvU&C>aF$u@p5ZidV z%D)Prab1JadOn$Se5j^&4s{L2Qg}yLjyu#&ll7 z2F{1BnQqQV5lyQnohxO{w^K+ssuR$s^BNG=8oR|^L>c!RPqJa9>0{v=onHoHSk z&)z%h99?Q$y)&|{1*X!6$R4)Hu&^<9pQRbiHz3eAO%j}V2fO5~kMZ^>37Z}od+st# zyv(6UyGpJ+)$#CJYqCDRP<5O3bxA~a6ueFb@f;dyvhtvlt)1q-j-;{MM(jPt0tqA- zN+xs;P!|8NFn>@-S)IAxz-P95!o2!Om_7HYwA?SXXjyX!=?EO=Mx`>12&EY>`x*RQ z{c*=V)wP}6cetN;@4Q%TuaA58=oB30t+iIm?Yp^3h^AhZ6`@EZRuE#qdbWc^(F{K; zPU;|+yn>{4TT#<-VPglSu8ih=zEV?sZfQFxs|(*Gw-3fGGuqm<6v`$TI+QFnT?!Ys zjdB3xkF!e6R(Bt=S0wIn4nD$hJqqQrsL^56X}fS3u3z3dZr(&ar+-7fKwRt|+lw~3 zisOUB84(A7Ry@9h)|=T}9YuXFvn^W>#wT9xqM|ZYuT(OU{x@c~|GzQ&k2miJv0vay zI4HROkBRTU6u`6<-lYG9*&k*zQwJ^wbw62ax}PX{ueu_;g?0C{D^hNflx;q$3tm`? zj%NGa-1|S2{)QaY%#3hSRHDfvcUb=rh<#r7`&7K5V(P^5scNQ7(N2tIUm#|G2$(`g zsfb-Vho61$4&$1OGJBp7zj9{i49r(F;m?gGfAd)Ire~jX{v(w+K_W58ikvEw%B&$H z7N%KTmW&z+t82dVGTcz7O0S7He!LCpi+g|@n$ZUmH~103=X(AQ4@;X@o?q*|F7x)0 zJc33%T*St)>kZe1&Dt%$H)!eT1&*7y@9%m( z(_yYVLbdOmR6I{%tJ7-g`ZKZ&!>#phF-^wNedg<#48kAh2g_8WU)7M$#xgT={szs+ zH%?Qy9{r<k;cY{ zFQ31)XxV;(ISH7pH1*V9zX%Xy__fGsI%omJD=Id4v~0!qUqOQylGCisoGBVA?j`2n zKtfjrKLjeryH;v0O%IP9;GFH$=&}%A?<5zE#0;xNFrCx^V!3{7^=`d5IjM_w``D?A zokR1 zvot=lI{hwwZkB=n0Q`oi)r?%2IiU9wkGmYV z%c!Xj{tYRUMcunoNvxL#0lyMHF9D_R8Jys!}u^VF)}8jK&)M;o!j=?)1W^i{xGlNU_0~NvpCm+L3@P) z3@PL!mDKDM>D2J~fjf5PXa*yPxInQc}>&kA3Gt^6P`ZPQobk)uH4Bx$($OS@DF0dq8I&P{+dg zGxi|(Qt*>fnuAL9x^fCak(t<`xi^(Ia}84PzQ_^O2WpH%6z{Bw$bHcuqB~~%aHP0T z$%vA23LmL!_kTa>d}2bjPmdXR#4n3-4r`W|?WZ_Io_L}&jRuBc&qzTCcS0C&9|5EmQv@rQ$&^)XEo^Jh?F#2UrF=u73wX}G4x#4sr52JO`;|2ST$ z!KvlR%`(xAh+MAwUrnj`v4r!N?Flr#Fz%mN(Ru~L#Ubz;;%}L2bN=CExV?D1udb;N z^wVh#(d1|dRFK-CygVklT@zF=L7* zF2}fTA^9xb)8+E_^)m2pCZKnz|8&uO*{l&oFXPQ|^6AK~KvPA^=abS=xbaDRb2PEz?TLBtX861+>U@n=SS{1#UEKT3py2VQR8Zx~xP<@dmqKwg z$zKs`|8Vu9{m{Yr1UJS;8$$(#90&8XhqThUtwu2z|M@^?Lb`FJ1jI&ZZa4@AXHd_G*AZRY?isym8&hiwcW<<*_ZZwW>z&GGj>BfV^2cToMR^wy z_SX7@-*2dSZSm6XptWGi^a5zQ zDAj|fBocO1#w|h0H(W5@jbU5dm1!(n3s)8D-ErGW!&6~Nh#_Xw!0}ROjMk_Ea{;Lf zBhHTRi>Lgy$P2CzVb!!zH8i5l&BjOJ(}*?pZi~MtFbm6za|-AEH7Hy6qndImfW!qm zIwEuN4aKM$YN;yO9hPCu$bK9`E}71n95rIWVO_tDa?Bpp0x7D}0VO&h9BxM^ScddD zaSVQc7M6u(W_iu4d?~4oqIy13@u*=8oaxwPT&<)-V5&}6kk(-j?$~|_VsxC*SbFVN zstNLnhdm_3O!TlX0)v0h^_{pb!Wdf*zf@*^udVMt6jI)>vd+5epfvHIfzm&UN&3!D z`5oi!w}IvC6?I|OLD?Sd&3MIG(m^&fLzBiddJ}5;j4(Zar;=@>>v`N;Pj(zhY!tb});KtB*dnQi`WNpx^+u56j0mIXexE39@auo z^oy(f78l>RR>8@q9om|LPH$M2NB%Qzxzg?g6YMl>V{%v`6?mUnLG7R@u_uPve@~c9v&0$NRaLOQTwN=QcySVwc#0WHjDk_pq+rn;rNBXzj=D`cIzkX5&#c4uO zt4ZJ;dfP%*{#*Dd_XE0U1q0$9NP6Vqk(^ z0oZ3zOqrb@weoH#aQzwq{uh&D6_L<;LaC=^l2;b z^6P?Y+QPHP#R5Y1`RnK>UOBv97ECidxcbD*F%dnk7%AJ%7%0UtDk(W@kZ`}RZ^1w2 z#mK}R@kNXVf7{0DS%dtp36?jjV1&pt;w8F;CUWLzugNTrjbLn1VTP@e3Uu9u4~v9l zaiG7@FNfvn2ea)ScVSy<*z}-j*{ln!(N>j7W9j$H%6f=45_7G%S#F$Nfj5z9BTrR@ zbV7Q~35&-)D`@Bn*cFS9YxLWPlvml7FxG~VPQvV~6Vw7*#~hX*Tls#PxOlk?uv%U1 z+u~qT^qx{}wUa?nT}o$eQrdw80XM_s6lFI6P!}eV?u#+@M^t0E-nS3u|Bmg&J}s`O zO7QCgCNgJBMkuT=OFKK_#GH7z1!lm0jT{k&j*o_ANSq5h)&DRiun@$=l}^O=bS4!r zDNQlkAlNM%BCjay2jh3~`xJZnvC~Fv`5}NRa8m4+R2GMY4}+c!RR8hd_`;!>FBAz5 zgCP^M{QVIAGl`A%y9<8>9ab+sOf>9~Oq`3h(GKJbK zd9@lDjAvHUz|OndB4_@D%k9uZQ2kx0v&lPg%y=S)@Shksau9)V>~cQVv+ z6@H=}!!}+arP0nKvPLE}*@Cz%8Uj1goe<%(=| zS#X9gaM}+TqVs2CqAWi*%Tg4!=0jd-y}*tQi$cUgC#ia6u)wl2XRXc)fNsGnc9=C8 z)Q%|W4oZGiX7&KF!L9`hZNV#SunesZm05sLP+1o9vLu>Pw(&PekA^5}4+A>YA?*6Z zw!zaQw@G+X*@b0eDyd6PmP1UDqGu<>km-O(el3M{OTBPTgTFK?EQxsP1NLGF+b4?F9egg$31f(`R#(DJV-aY2hju?-{oLs8ex1yzVnK&qGvUC6q~ zi6r|j_|i;4b6GTKPZZl)RFVu+ zrLtd3CS*=8TahPsg}t-LQ$pmW-hJ>7i?GAvj1BqEZWD6J=TJi9ETeR+)tus45rKL3 z(cfXs2rljlwjFfeQIuMWD6l0zZM;M*biHIO9T{jmF^*l zcyx6+-n93LJ}rCT0XlM)Cz0T)m4Pyyyu!jrM$lJ7_6tK%?G$`~yI>FrQ=>FoPa5Pm zTdSnT7P65+BrNG^j0Jd3j-7QZV+<7jjfqhok>B!C5_Qm)6Q40jjGsW)OH2F5jDGKEN+O>mA z&>H&bX^u73fF4347gbjn>Cs6)y`pii0dOoP-p^ND@XhOSjX|R7opZ{aXv#No2?rN+aS4a*ZXPAz~o`xpFhxWB$ z=KKkhQC7VeKixWqTl|HI-pn4}?^xutzEDXlcNRh{@hI`w zaJ0DCyXyd0=XX=aWOtqH;G)zbnohoTZdAHbIAsNFlX46{jVOUJ0)UW$KTL{1up&P8 zP{2sh9<}B(^i}mcJ?xQw{V}KicG7lM(O}1-O{i|&f7ptTEaCIPZH?$N6tqYo?pk!z zKa~(6+5vHz&_W7bveFFMys#JdD+{Qzj~XEjCa5ZP?o5I5g3?hISRk8`HI_I->tIXu zEB?Gjs`luOd`R~LhZY9eo}eX+wR0+6wU;baPE)&;a>8y^S?$1d+T0rfFuu0+?H0K) z#sJ2J>-hyN&mU3RB&Vb!BAymy5OopP1RW2aM!sqk$tNHz#c04XMm{GJhI3ulgSNwN zDRNXga7tO+4-C3E;K2`$v%9)F;1W-mDo<1{y|R(Sz5%-dx=Li3t)!QIiRYaZR!4JX z5%N#_^$#8Ny4$d~vs$~b$phENwol!JE={xi;|GfOwF_vgg2CVU8dN1Yeh`%ZdH5V_ zfBLJd@Pm97RP<&drzZSyP|%ZsoD}!tpr9v{&B{XkfBrJvD(KDpaL|_l>~in1eKE1w zZtl(msDd+l#rZg_PSrRL#*TbU)_|}_Q^jUT)+VdS9Wm}IZSzjg_a2Xo$We&Xx{m(4 z;`vHo?u&$MRH?j@s4Q|Ghprb*g{Da14}A?KLj)#4%C8P3%z~^)W+LVO6CaC@3yu(B zG-^&`b^#0R&aw8RzFGaDKp{k*f*(DRGm}nSX+&oUhr4LQE$fRQnDeId@bK>RV}~fh zNNWf~?8ru41n<9s>Anj<*VQr4zxBlH`3@3Uvs%l6MxJ>Q!@UHcht}hb$0nc4t54Kv zXe%Y3)>hzk;N_(6rCl!%t}xu11?s5?N@xeJ7LJ(z-H&)uQ!}Q;AjY{t5U&tB*EWj; zwc^CB#Ja!s5Ljx68o@JQOC=yJl}p=1uPRb%onnVEJzjjS5sr7o7yBDeP|%#;jHW+3 z_KylzQ&P-4o{V9yj~OEfRXGl&OFjus$Y<>kzCJb*A;LOA;We$BY3f9Ecx7WT_x+~9 zvGe1PlRM5M;CIDl;BX;76%yZQ{7(j~1muDRhK2ec2DG7`jG>5)q2o5grSjZ+kI#eN^eKc?;6`!;6boj^j7k6mF``1mOyGE81xV&0Vf0B# zsF~>v-n@7R0|}rq?3r#!=RPkmBFQj?-n%ZRFCPwC zO=M<~batNDCig`YheXn!Hp1-? zQzkzDC{VeuzB+#b%TP^(Ljv?A$a@@6q(O-A>7|PXx%xr-l^I zPb4Y08C7YnKP2VP<13>AepW?}|NDUwxbbsBl_2+0w-xfYHOOb@=`mgIr9OyYxV!$< z40_K!k5B8$Wcodm=i30y$GbihY13YxWzZxk)%LsQaL*&@`3P?Q@mi|fBhsSN-5!(I z$5Cw%=K3cf_tzW*7hBKtiLPhFdN!d<_NTQw?=v>tqJWcG_R6|XZ_AeMu4P(^oO9>o zwNBm5zhH2RoS4-q`rSy-rYdNUvWz>#%`^ioZ>DD}IVc5W0?*KA^2x7%5OtOQk>mb- zDuEs4(8sIN&Ji%62mk$SZPSR_JCN4 zga@rK392ilByaIO)5waZ?4>1aUkSp$g0 zZw557D=5U6h)@+a%nH~9_<&y0Y$7@^GDgC93_*L0qNJkMDpUQD4=<8z2*&Ymb`es~ z$=xlUz69Xi#6SGz{U_!9XO0S2a(eECSx~XCaZ-ghWKBlMpqat|sd04iZ3K@Fe%JwZ zMh&j^J;;qBSjx#<9z{86QJ_MZKYf@j~d(U(gr*tv)^~c8cWD-KNxfJDtI%mb>W!^7xZvpRW0#B~#21}xEFQHzx zfdO*qg&U!BYX0-`QpRZr5pNLOa-0&ZxCg{>ME)2_TmA#NgSl=GKt)=?S{JE8jM7s2 zg2fDqg(&i5E#f1lX_#pTnz|bL?u%l#i!#}-Ra83E-Om5x1z1o~kxx`oux2q}ppYB? z?oP%k>9rx0d0`i)tPnA5(W^iGH#&n{PJ%$OOP0n?5UY@&vO=HsfQ*4cjwh}$77Gm) z3T9~ZKr(7gDz$}h5aBbyw)J?sydHr3sB`4=V$7COegN$9w7Lb2h`69fHKL;+(j*xm z{YnpdN(RFX5ToGz3J{Er`3yutwC9f)KI>P|@S86y5pwum5spgr0+aH3ub}RH zC*3b&+&lh;c?81S^C#)!i^6q^!w8TGNQWa2hB61VQJX7?0bneOpdV#nsbe1zcsLLA zwnfQ78Tdn%j(X+Qe>S*WHMiy*SNG7EL}>z%E}=bfe}4#hU75O5uIE{l!yg*!MMIaksd3tuDU2$wZlpx%4Zw$;$e44EsxCxB<4peE2ER zh|eM7#QgNgc}-~yrN*XLr;1_%Qi#tZVnV>cS-++0Kms(PMdI->h%ulLkROPZV68BJ zhfIn-n59Gwfb*vT8LAV}wgeeWCA>lX9>i|jAuN0ObN%g_dF^c+qTCa(rhBow>f?oy zQkFWG8O#`g8X@jR+9~I+- znITBoTvRh!WKmw6{eaTofZ9LeMML`YS<~EjJ=pq;Th^W3^c{JMdXopkMpQ+e3lHc* z4o9v43}6CD4F&vhmeM4^0sw*$0WgOC)f%5_)@z`=OJ9s2(}{igw#pTalz=6-N=5G6 zR!XU25TElJZ8|WE>#60R>4VlYGh%};%wEK2?qo<)F|1uVlpTQ|gM)Yy+d^ja3HI`d@DyDj#0UVS6FQ=Tp`g%i zu#&7bAZd!bLyw~19}-+W)}M#%g&mESR+>q{N=Sy=r<^ckgHVPMglS57eoAV6-_f8x z4ybwW`yA|{unp|-B#&}pWkY92A{4a&n;LTz!A=?OOq{YOND_eybo+Sy!s0H=G9_r2 zJvj;e`%-aH*#21+i6WV@HHZBS4A1W7vrjnVltVPD_@^L;x zr?+2fX`dO}PXMbtH{;9{K1rvm3%6^uOsJ8P(SnK8G@?X>RwDXLI>jMEhmV<@=5Gy8 z*BrFmp+AjkzNk>M2LA`-2l@Qg4)SgGhkPqpo@r8Fx&?1L#Jd~E3i&wHz#5L8_z2N8 zKL~O^Kh=?gym6p+io){o3@Ivu$qYdK(-igLx*E2$)K}BFFgSshd2$H2gKG>4!-)o5 z#&nNGJxAZR^oY&(d=bvTq@Khxl9PQ$uD0~_GTR9lW#q{}FQAr{u`~S&Z7aZ5U+0)q=6-N=V%#_^ zTr21E(g=OY?J7yMP1?EBPX24&{BXHav5rB#tYGrf%Jq5b9skQ{Ovrf!JImOVPPn}i z#MGAT5SFBf5d!3o0;`ynZG785^@rz&keWMoCZ0*r?qv>;>VmpK$%Kak*HpsJW4JYpJsJ808o^Bq!*YtK z(sq79nhjbV9TV;fA(if-=}!dNSmpUsv?Goh&=aH|LMkFFYurZSmHu}+oKzQ$94Il# z)iMFNgOxb}Y3j|Woq^CvYVAKYaEuDoe+N{#@3{V2fheE?cnsEE)HAksmQGNyLMUVs zNlGQl&3fp?L}h_4i`*x}Lx!23r|L;Cw|KC3~Qm9?=p3AC<5i^g(MoEL?VhCmmSRk1a24UaPNxqro5 zJ4UvV>rj@RUr(4^6&#H2T*h5Clv`{JeH>f-#TSiv?#nQ}_Z8wN-~L{A^GtL_k@H*PG#5`iJiFKzt@4$DCf+Gd z-zD2|@ zT%VMUu0xfvx3cbCppO*1%$?E}nwKMLy0jTz94}!aj~80%k#Teh4>I(#Himkt2YsVj zV3&UO==nf8YC9qQnlcx$-7+>G8+i(gi_8m5&x>Gwa$%ZP6H3zv)_AJD_UelVCZ) zlS*RbOPt+8U3Y=IEs-|k(xk9--c#{q-6d<{9v}Di1rg?o9~-K@1V6t8zt+V%eCv+h zXhS>wn2mT?E;pOIFXc}l7NGUr(bRW1r6q#G`f0#J4e0=oQ|2FevP>t_CZ0*Wou6Zr zF77ku{4o$f1>hP?w5Vlk9(I|-Q4wIMi$YDGIn(A`=lAr5D*9*;C64l**2MC@SW%#n zda+M!T`~K?k!AFC<=PzQoh$Uh{WB2Sr*`w% z3EA~CS<}?%JF?eTb=W~9M34PSX*&DQCrYdl^ZaI$$m3}T^IAVsD*seqyyqo7nzP*M z?!YZjtYA^-HQ>U=l!IY#Nu>P^^?Rmc6nJVUHA*lu^Q#?$mH>+i?5w?iL=!>Iq1Q6? z7vl9YK*RMaZx#=Ur-Wi7P*yf?X%Adum=PFOiVBq5My8(W=WI)9w?^V^oaE+hy*GMP z0m>HGXP$U*&uj@YBgE=o>Bjy>aK&mFty5hraE9yVi0P0L?mSW>dURdF_TjKwWT@h` z#is&?7Wr*zeiJW^AcB~TqJwP1X}X#_S#d0+B3^+8pi)jl3otFYPOSU&ON=W!#SH=x zGBmv0$-h=VAylq5cemac_TMoSIN6TI3C=J%+ZL{iyTzjAUxmzGPtSwi_mdI@$6rFN zWooqzScfp&cTYf4RwAPP$1 z=yb^nJEXC(9p;$E{HF}F!?`?D^u^h(MQLS$fPoO7=cFQvy1EIL*9qie%asHRG6awt z#r^$)@8yfWW~5I$co2u7Y!1TxX}qA}ME+~Yyov`W)zrr(`?+SOwk@Nd3Z;OyBJcA| zc#W&V+$A$>g$9B0Qtz$jysYiti}D^b&H4dsFMw zQK2j;FNt^BAv+qR4g7RKJ=u2K1mGUD82cwjE^uE9Z4pSYu_@)Bo5p(b1Yf)m@HXUa zm%523<5H3}`(~3?sgj{jEOas`g^;U5*y1S+?7m7O43JW@vO+c3yO#+^g3wXMk(oSW171>s-Q&JlM}Gtky;W=9)dlAF zdJJ`C#rsRsOiLDMV^*H*AT{xG*yOgJvvc(NxxPvOF0tjBJQ zlF&pR(k71nxj}RyOYdTC4qykEf2j21 zLBW!{S+T3#!|ORUIyA~~ON+LW1&+1#TsB9fa>46b1FvX-NU-hyc1>^Mb&kw^5L1!; z$=frTbV8$0Nk1*6J>1X(daNpHMZQxk=pfr9BW&9j7T|K21WUZI)S##;E$LB+QqBn6 zKoEuEqNWoH!_rEGVKH15ja9K}_}H>GQQ5Z&Qzp02IPrPRZ9`3_E|Z*Jb5?kNC+xm1X;zm7U@3v?5G#@D#zq*8 zi?D`QOFNv7!az;=z&5TtxHx3a#49Z5NvZ|_u`UkmaEeb7LfOJ|tQp<$jW`!4rUOWD zhHyI@*xH;dgI1Mj!lP48&aaPFCCFKhj$>C>V96vCA~#zH=5#_IOL6;@M5cOC(mmEO zN}1#<6Z7H^F-oMY@Mad6MLQV&B#T5&Whu2SDxJt2&nckJxr|MAkLZ59g6d|_7QC!V zepGz3PbMKE4d*ob$o-$JKgg#N%49tx)#YMo}mx;JU(%;q@Um?;M#Zk zGb&>_xO&3c7j)|>?Z(@0G6|jxSq@64xVbv`|55eLF`~p>vUhODwr$(CZQHhO+xFbC zZQHhO`_23IZT4-_>HN~2^gpdSRp(UcbtT_3`sfIp1Ka=LaDIeJ5s!s1h#Ekw%Tqzf*BdQE3!~&Azx22xEaa~)DA<;H&FTRU-|BDwZG)FC8J&am zpC@P$RcIsMyBBl!GlGG8g6XV5Gsm6vJI&w;H2)v3qZX-`joP1m9n zd)`OsI@TvBNaNUb4g8=NTzcFDp;-VhJG=vXyxuMFk3HB-ey$srFbQ>@g1KBd^Qsk# z6$|8V)Hpw%CPT6y5^%jbJbo%Hj^aNgv!;IwU1H%*96vt@c?uKqWyoa6_aB)Wc>Z`1 zVd?;POruvmY#EnK+DdWaZ!9E<_@W_L?DY%02o6NzA$AzEBw%lN9BXIWV+XFiUwq9C z0M-m^_Xy17}0RxpTOob3YdeRQ9eA!X#TgtancGb|Y!xrdA-~Y&mKUGTq5fywrkO9}f zkA5|UXIicQOD_0qKR%$&x`>G5UUm-;U%`JrFcZEYrM`|za(_NYCMQ`W9Y(^-*M}2d z`y5$|e7j^c(u7<|P`mCcPvR=kdF7}2zJyC~L_C$+VhAFvgq&MmK#gAw_F-|E&;bI2ZD-GBx7er8>tpzfd4ho04}6bXqkn zhh+t|!M?!Kb#+6_l;?B97R=?4*d`-{c6M_~K(!pF;vQ-e9~=)d4jQ|bqkCl8A8Jlp z(A}2sNSGpm4f7O5M8b0|o5#RdoygKv(Y-rFBNPQl-oUfLDyqsMtEun|XV_}eV9hJ? z>1D*-c9^fs$uCFN`5}MLLgI*liR%jBoM~_*d~*Ac(zmG>_SgyyWcp!j$0KJ#T1KnB z6p3n(>ARz*_BoLE7;}MqyZMLXY32*#=PV+*qUj|v;|(-4cooIJNnON7s;+kTfX*7< z)KT8m$M1Msrk!Fcsmz$n*c9mR0N5QNODT-n&S*iUlj62=07Y%o&GJXowze_8xv)j6 zz(;U}*I_`S2Xt9NW|oxp$@|6%`c8O#N)?~VqSQ;V>FGsHL626bj*rGHi8M*w$o49f zCnx#*5-J_5iah=`o~B3Qndd^3)j+jcNP}@$j$|Mdvu4@sPAE1mtQjKzcmjCMfx5Qd zmd^saJ@w4HRs-#qP_Z_7nayuagv^%Vd7;Zc1>23j#;N5-!hKU+Xh40 zp|Mmrk?WLzhlwFs2(IAJixEpImXX7=chn>)uN^77A^N#QC1hqrUbmn>FM)UdyTM=D zfD@4lheR!v*?`Kjq-LBi`D%_{Tr5b;DyH`4siDwZ)TX9z1EmiG-PG7IXT`RL&SgT9 z&Y)NBAkU{2-P;^exCCRGRe4r9U%2M`gQk{&FKl#=g|ZM7OB4!CBcuHCUy)iiXr{4W zl6X8f#)+9}@R=bZzaZvP)6wHH27LuihJl#CEt1@moq=`V;+kYMU9k08jr&tbF0E~L zX=_L9&PQjw%mPlsjnwUR751{?3;x;z7psyxNJ4TP5qiNT&n-Sd$=BdBY8raS$mb=( z1^|HVa7b};XvB47V~gtVkE*XEPHwbb%)qbr88FjuBI^59o8`Gh9hE9<2?#0KMWK3e zc0o~ASr__b6D6v5VOEwNo3Oz(wyR6~7=b3?Stf(>%BfX}47XS9m-~~L=NuSc1a`fd ztaAp=sf3oaCX`OCo?TX#OjV4AkDKuEaEna?!@Jxv^!|uDLqs(f#jHBPa!Njvm(oaXokN~^dcKcm+K zUi!&1dwZKB1H8Q2#yOLtDpOJ)x*sF*uhKyx>E+_p-7!q-IIXJ=`gu9gNTP!L+_s>< zx}OGol&isw^&~BPeU;To!E|b_RO3)@pMw`;OJ90H`t0_E-M21<#`1eFV8jMZ3>RJp z-Pp!3oz=FQjunR_f!@&8LBY2iD7e@kLX`UiGs3)P_6P`y7(56~z%Hh+yd!EF+s>0& zicdLUc1M(>1tm z&D(2rOc_dHXKMyBn`1rto+Dbb~lw#u|P{-Pk~N%%nYP zTm!LdN#3EOAxby*;5aH3C>=<8Kv<(4#I1QnJW&1_Z;%YunA@vN2th%t&Kj_RHC-WAJ+N8L$W}G?S5|e^y4RmD+|FT5mTAAHd}=U z`l(IHNfr(6GT{fh{?N!SIXS9mSmi-By0N=+?8XC*iy=h9u_GHrMl0KAge3I3RL1YH}J?gAdJ(pl|-c7A@lZwZDo*+Xt(L98Hk zAXt5wH1_sjc=H#)JHp!_qv7Im1hWybf>~cP))P69B`Yk*%eW>YHfV+HBM~4h;1Fmo zNNuO!h6aV01qQFGO$eaHrUzz9gyjS>)oH3oImgPSW8Gn#okI>yZ!B2S5E+n(%8Ot0^z z7fD=2V8VreL8r+kHZqz;``mBfMsY)UWD`e(wCslWcxJ%cN{#&sC9i>rprpa6Bh&Z3 zGRTAxQ<=kP5m$-=v07G+zJqb>(gBqys67%odI3RXvs&o-QqZqEdG)r<`bE{E`t=Pv2wq3uIwxW0 z(>hG10W&hKchCc_c@h6#Vb~aan0n~|N5{_ZCT^4%EG4f`Kvmv3u?7i&s2#&SPFshI zDPx%EB{ELVSxKBlP)RFlqdSv}@{d#FYOm_dZv;e=9G#Zrn9{K+pYWTmrv4w!9m$fX z)Yq1twQ*WjOIcr0j;+XK{D}E89u_WwAdn56VhvXy4Nu4`?yp8xl!Z&VEFTl#BI}szn7eCOmh{z8 zJu@_oDZc;i1*j=%UG`&f5_5A7-UT!!7v`G5N5XfTeT6uQZHd(>Tf6uY^z2@ zy-+}F*{8NHw!(*dHAURW@c^P*Y6L8>A9uP9QNh?SX^m5N9uD^y8W#zu-Uis#20SJg zJ+;Oss*AdHMT3D&vH0iPJc07&?x4TDW^Ti50GccL5>YV@d{;Nq$kaMHybT(L5by&aUP$T>Qdy&3%|AiS<-WFQ zo%R{zIju?|ps+i<@OWP1&*KWOtpk(kPkaw76Q90A;V>LJcc)1eIvEiYk$Kf!vZ~T9 z->{Sv3XXqHX~w3~2@Y`&@ESO#miozeYs#JBSRLSCrbl>Z^biu`lr#F~R;6t{fy)$x z$nBrsHF03^X`dhui7l@=r5Qjkq;2af{U_~>X-%da2;xK>FBqT)J0~imQz0M5>lYKR zt=8$6b6~bom3Qw?&|aVj>Q(9c!vt8?+|oaUT(EKlWC*N-D%gQG$RvXnFASICXdHqG(SRL9W@HhH6$$F z(J^>t-e^#*i~lKhivg31@0)?|tV0|qLRP*dT4BH9B?|Gyl+ok0ED@}vEG%w|imtG~ zpEs!`qce~yUdB?}U5FA+(#|x*BY|a%)2Fx^mZUk_uwKnH&TZ<7H<9e5(IE?_Qm`H__OV@*rcPtwxDH&#g&Y_Cz zph(S3&Fv0T+!r87?F;ws*PKTP=96$x#r8JaHOAew2gh>-F85Oj@?>jR^tGbXza(~` zW2N5oS4MFf0*Ppmw8n!*~<{zG*e%8@Bs6_rrwa1Q`7V6vtjoL?zYKPt{##_Py` zXq2z0)Nio1i^XkXW$I4F>kh~8jrdIM^X!x4bdB?;()lKPpNz5jov~G`neNB-AgmzP z$Wu}Anpr1~C%G6MH!88+!6e{D0U;2>R4RuRDAwQ0F04vwmiXJA^W_aZJd=96Y;TVR z(k!_o?O#UT`fIakGEvvwH#WQ6V{dHJ)<#oiH4O9SQt*x*YTKFzuIqCBjEIZN3rnsD z0t2<7Uf9a(N9DO4aEV8QS5`C8^i2%H)0?!t%I-{-MwL*gh_8~6R^-apMi9FA)yxeS z?(Hcys_(tB1BMGqr5_XG)=AsB##j5XY-4O{=`ab>>GPa3$uBrU3tFQUR4Hd3nds!o z`ASD;lvzkg)zwyw?M-v@$o6Lf@K*3sk@HnK%Ph`{>$}4Js~sqw^j_6lpa!9exL#RJ z)v|R>T+Cr**(B8Db|b-x94+{Q3yY9U9bucUvL9QL6fBeSJ?XHD@tsHSKG`fEDx_$v z_hx!!qzFjJjt#A>Vfsd|EGtQ+@rX#i2zSq# z=9Qc}MIj>o;#C*ZVKwbdeFO7MK9XQs%J_t&(M1^~2hQZDY^5ew`c-X-3T&i4dlj7z z64smRI*og-=M$Y{g~)XL4a2N>qTcO}tjVqsSCaZoF_`^ptiy+y)cG^Hz$6ma&fd9m zK*Pky%D;+MmqT!bfMN`XAn3#YKo*Clm|UM0=9Hu)>+YR!USPG5BLL5aaO-`)WZ#B^ zVq1=8^qrXR#{NMqVbyoL4sIUff2(CAl>-=ylX?%RvhOJO=_%(#`uK4j1{{83TFFS$ zcQg)cHs>1tfD<@4AdpqTIHW*O9Ys4mx-4v|NknRgOCa=dN?5#&c)i$U;R1WuHN)Hw z#kQV0Wb<6$1>&V;yoF^8`rB?c z#5+FSSL9kB96ekwSSAEs()TUdvmC3WrEM9}BK6abvyJ&{84DszBB3fP&MiwC+7fO# zn@BA23g#&p{nbCQ-tOq`uV|1-Fc$QBMa=eUoCrUQx97BFLEUH@nNr<8+7<|rI%#P1 zIT!Z$r_4kqgrpF+I*paN&@ef5Q|nyhoNrAuvc&J<0Y!uhZrl6u-uy-Lk@rp7_OA#%LE}6jsNAnat5zwJV|CiMCoKW zoFm*iQL}q&dGz1w>yUJe4U*ze%O0x{3zjwIrv z2^#P4o-aB_OU~4ZC9w}OQ7^d?jWp*T1NNDs;$pU@+ihlX1PCX#>ylV`;bO3 zs%t!4`WIy45++0QOhUpdaH=$}b2NsiZ3V(;@$MA&OH zyGuszPB~hINuIhVVv=i_`bJbE^N%zs3PF`5dhD*bGW>bg(YL(`n4lRNL3rYaPxe-1bS^9~Ibvp^%Z|y8q#Je^;|R z!hahoe>=rSRR4cP2=PDjA@28VivKez^50^SZ_1=NO{eVVGVa~?6YFbxOAhpfa!AD_ zmo5?>I)|RgLD-cbu6$c^WmR;2%7Yfh^?_Gnu!iIJ#F)$plYv#{=`)0);R4kai2C|{ z!qoAogoBX<@_hjXup>Kkws&L8BBPvXi5Pf&5p1*X=>02|u8v)uapz=c&GN&9pzvw( z{et@rPI?vn_SZCKr#wn37XS>V-~Cl&1_U01ub7~HK1KIsCUB2xaafU+U1u{AZ+qq3rDyy17= z2Yu?F8&9n1%{|*{V)WRi1-rUjS>J+il)`iUT1136ze^rT+peK#+{uRGvclJ)nOWba z6d3MRBl4m_nvVrnb=^%91ARnYieOd0q%yt|r#v{RB-NIEn~S{C9)FV32!i6UD5COH zsD&D@&^ydfEEO)%vr?UsmLa~_@BA0iLHJ z7!TgX(b8%%dTbl|r!LOT4*SriL^w_c$nkoX$zc#J3r23#b#~XboRkIUV@1_(e`^Co z-J|D20^X?Sc=K1_9yXgL>B9O7q@NID6fq$D%PSVuY4Y=b>e0f8t01C7OtQWq0f8&Ck zj843d-#U=}C*oGooMQFK5M}Zsk&i>94Ckoh&RlwJG?==MoJ4Ua5KkZw z(}x)_I)TiBZAE7}fr+4u=}6li3;Q_{b?qlmsXiwoR{7UB0SLeE1v_nonV|Y9GbT6YP9vhmY;so8uyQA z$Q)At_fNU(;sHW>nyX`K?v7Xp{%8`%!A9r;)4RqRuzE;j5TFgN5*C*?RNFN*9RkoW zh|(4bw7lGZQ=RRcNavF}-cj{=T1U80t*-T>!eN^Y)1OTHss26mW(wR0juq19!=5*F zOO-eE$dor_X5i_WS~Z28g1WM{WVW`pHe$vF_4AwWNtO(eBtc9N4-98WhenSvb^0Xo z_&(srLRs;<3m1x7vpU}G^^-9jG-5F{rslVx79oKDiGhtB(;LiV#R}<6my&%sxE-NF zpo{E%WLl8s`{V?$P7_Xpr%MYG{Aehx>4KQ)toONL7bfC>GWC4^(p^-_1zADwsZ~mp z=y}z2J7%=tvt2CYo-JTSn>A}*Te-|zTN9vwx3jAq*wPNq?!p2U#XMwDFmfPAD1SBo zu10TI3tBT9v|c_?OT?DWmre-rUY3q*f@pera7xvw+#y*&`ErBz)494On5SgWIbo{sh zC8OCIVcpI!r0tlSD=n>@4bl}LVC~MGruY48Fd3E(YRy{JQ?>gATaunIlJH!*(&j`S zMF(Is@nxm_l?J*by}3+Of1K4v?n{pDLRm>Qv%t+Vb2$#;xtxQROdmvSWKTqxK$!pR zrpD{M$!bYgEz4MOt!HKzv_1DXXhyb7!G`u!iWuISpNiDQo)0(&S&{m{mS1Y zskqtV98}azjdOT14JCUNVC2tV9dLTItA23UD16rWXtd-d{nK$@UlxDvsCIgfo1Ofp z{0#6=rmXuOeuZ|(F%}anp^vl|lyuxv5pFth)1HiIZ|H^%5tpfEFa*)dK?N_t0z2?% zVto1pI#f!nL*2y0{EcBYx7he*5SwSp(*{m)4-+WcL$(9_#LwSeUxRh@yr$apgnQ@Z zPMIMC0(H?inzp(^G5Wxw#qgL{l3B4( zp!9mnfppO>C7JiJ8|J4BhB0G!cgcuEuVZ)gflDX+9FS?Qp=MnRGY2D}Sg#_9@5}Hp zAnbX1!AsW&7`)YmhL3-|tteEkT~=+M8yMS1Z_BvrYoQQyWln@#;I;|&%Jt4*^L7IF zGNl$#?+YE!kwd%~?j7GIQn|sJJyK-s%*1}I(C^-WmZpK*w>OlYsT7)1L!|XkR1>wu zZc_kFq&5t#q@ib*mdAQOQO?)AT~wXJqySCU0GhXP!jSY|fs5f#aiz5Us6)TxfNK4G zto@b)U??h7)l%4ZllLRLmS~R4>5oN3)7BR2DI!I#6NNn_(9-=k*sfsd7kR}!Pv9sw zFi=|f8!Uqr%_wrj&y28TN#`VG@-~CSRt;?nqo-vh%_}lYHYict4FDbPK>D>j#FvOE`vA6F{MHhihs6QeFE2ApTPO>_O55vrV$kw0*Qy)4T?h%Y>`N*(rs>!cKP^EW7B?iVu!sj^*$pg7A{Cl(qKUh z7Xh?_mc*r`_r(VZ_N5_S5{EcLx^) zfQPtn-*LuEKEJsI90E?yVDpL4Soc1 z?j53vDmVbsQ&4sqg~Fn>$4jJC_)cd(gGUUu?IHD`GPKw8z4U`%YA}+tL6m1l z%$^z%7!Zm_IgD(mymG@AgM5vHIeKe9x3~uJ2XRC)S;tee=gU8moX%!ZT zOF$8c;qSgSf_u@;4O(1`B*9q86Jw1qA0yQivBh6Lbo>an&`+5hbU0Ovn5X25f^qcy z)rFo50r3cVf35UL%c*95ezvZCw&P2Niy9gw1pa=@Mqqqo~3@_)*Az$@cEZGn7L&f~`_wijI?Gr0I$DZCkHvhJ7P@YBNBU(H?JE+4gmi`ODq}WXN{t*V zu02HW0zp8_0zrPSTBsElqB(b?aZA(hP1K3m=}x>b3w;AACQEu(B8K)FVJJQZ7qR1esNZ56xVY5=3% zf@L*Ug81~;mhI!$`uYqWI+bDGEp|U1XkB=0RdYhTN&8q&KW;l+xtaU-=r;!Y?;t5> z;KvQ^08~dU?~sNr_f((-&T=#zOPT(TQEXQ%_rF0isR+BzF2k|N2ht(YAfck6T9#2O zTTpK9LMU14`f60hLi)N`s6MKJAsK&JBLW@xxuU_3gPU98{4^iXg>9^bE^4TX(o+@L z21B~KPS8wGl1CDD1O5OCGALs;Ec>y$LAQ-PQ$qnFGxk}h1;>`4lzI4Ltp3^v*?#$U z|0x5|$V9`a8t};sz_@Y)b`PScN-{aLW3)?bgIde9CT42J$d1c%;ZZ2Rn7 zpu?bz$nIse{fR!g<3M4igR94u=6MFTf!&DoU}tUyOUxn}95&B3gd56T>xP-#EM(~h znpYtq`y(qj@*EdgAh#E~n<=`5t;y3~q^mE(%2OD%NOLG#>5W>N$?+CEG!u~_C40w=g72`*;!)HaC>@c zhWZXEb>ZeIF40yJUh!=ri4H`ejljMN1JO0p`h5`6eP99%dGpMkc1Y!VOr_ za}b)rxH8vuuN-5yY-OTFnMPVE)BZck^MqY&$F5}6?}4Is)8%cp!0}tZo%z)70QMgxOx^of#L4d9U_>Qg7bF~l7t^>40kyS zUOCl{P`?6EqYs~;9~>yO4aG-CP!UI)uj`0WG6E!(9lc4T>CI%cxZp*xf~w zlCuYp>9TMC5N_7hhN1ZSVrd9PqRj2%YAyX|QSe^?POtA5$^B&Nftxkx?dj(7S~O5S z0GC|3Q0!D36>?@)dXU6F1bR&yeH;L>p_%HJ=6n~}e7{$RsfQ!hcyFY`p>h}VqU#$; z@h@JCus>)(@H4=}lxPdRt2Ap~yspuby0Ptx-wqjezI7EAksGODKA~~i&Z~aoS~oCOh<~ zNguT$2lz7agWJEdukGur@wKlFT=r8$H{_UcJC07w>=s+OdR0QDp}ebQnU%WRg+(OL zlav&Nc_{_uh7B?jfOy7Jg8NVia97r*a^G~G`$?mK;wXF_%$O-?Hl%)78|ZM3)baU? z>0{2hP&zsz)&zvgmhYoV|N|e}BVFamEuJo!lKife{#s zNL^4r?(_)qi<4Gi5SQE%zJC1H2Q9G;`f*Lg02&{zXlqdYC#Qd9deWxu#6Yv$EDB0g z7k=^*HhQoPR*|G`D^%Hih*QAGTYY@O&H2zwimRe!zipzX(NzO%uueWN><2Z{>93h) zAM62!aG4ic+GAOWfD1cNtEaEs#2rWNxxRr^8LzU9Q+p<~MKQ{G+7lWa%_D`R}fDB+gOhelLT7 z8DN^n`%QzO1&#PiCN5Mr8+u6k_neTx<9jq$Dpj6$-Pxt=k!y%B&JGUFVgVJ{McKb) zv87K;+_?a=0ZK7wy!mCk{5w5W7XpJem>>6p5$*>ClxJ*P9-Pzvd%w<#j0fPWd=dP8C=xn>xh`AQ*42u7oHN4R(VxLf z#kyT$Duw>?1CFX_uHBFqmDQ(z6e_fb$had@s__v^0dl>W~eZoWAL`C zSiEQ2jL|vV567bsS<@#4OLJL)iSEF_x!bcsL-g6%y_{p~&ZZE>|KV<^e2z`4?hrqV zUAf5JW zvPXW_O!JzboUy5%E04vy(oAjh84fQCCK!gWy|=%hcq!GU-<8nH!|l`Gc5BPDXOO9* zXO|Ei!8*{iVJp!hItX^el2wEw0MVQSFgXB3RDLldtIVr(Omsg%%K{_}e`zM}cgF2& z>>r$^>bknXVk3ofyQUze5suR{6|kp^F>y#qx%YU_pg`AJ)7L?d^gcBAy4(zNZNX>T zMvcWY-7GR7;v#(=Fgnz$4SUPbeXx&>AGt>bm+2UVZ9p1y5C6lRc@QhdOO{t}57^{Q zM6$ysknA9EbfJb>l7^LATC6aqTrbRE2>V zv|4!hb0!`m%2o($l>2kVaQcqsB{%TVlP*9VlyEzRIyw`Jr(wX?s5Njn0Ln#mk#9ef zNL|C$|G6dZv~pmUVeDg(kP;(o66M2Ys)Kj4P9F1j0t_iL4om~;UA~>?_x0LgVKhth zU#R$rA#~@#Y64B2(G2nIWiWh_E&JRc5pmhHcRwIjs2M~c{W~;_mQmtLPD!0-B_nd; z1IAFtm`}l~rQOFV6rAk}L6Ixg&o$(>!L`urb(W*IIn>BAv~R@8O(@7kgKppi24$lY zgabQ3N`r$L4`~n3C*&q62PRpoB_p~gXp>Si+rA$~!4h&Bgr{{09OTZ7$sH|4la6lB z7C~`>@wWDz1zR^PLFDIyi}EkchUTzg-v=jpz0etw;986cVEcOY#uk6lrJjXVW+x|t z_~pO|t5JXQ@xOZkCXSMw{_0Brq?wj9`L(-Fl$T{0Yz@K6J5ka2=m2{}+NW06GP6jl zc7!xZGv>pqvD@=K%FxKfj8z%u2T~aCGyX{DT$wNj%gV-+dRS?LP{o-SGBK z^~9BeoLoYdw{M9^sFqIYGO&kN!5f1ZmS(oBV7x>pmb!eKZP<;9^rb?b7JX2t z#+9i16T&UUD2rxJb!an0)%1W9#`PI4tFm`O&fnhD>);BCI6yf$ju>C8b#xf6L?a}2 zThG2Z9ymv#V(B}572^yMEa_IVv+FsMJ!YrPCx@z_dmpC>1gbQ{j*r>_hkhEXTZ>6? z0(ALInud#B++`Uoj1T-WDS4>F&To>&>~BzuV1K%tcP7H9Cb1Xj0kHv1rRI*9gCS`b z#u;;r4b_lI6>HT{w;sFZ67l;$HE-4=W;i57?imzl<-YXhfqtQ^r|XoMe3V(E=hZp* z2Sa;a5_W~N!N>Mi+H`fLvntYR{I--kctxC5=q#+F@a{v zp{Ai#q>3BCvWqn0h~Q4Xh9kRCO4-r{AGLs-gsLPj*Al34<8Lbg)dx?JwC_!X*kuLd zMBhqeI7k!SyD6zP4tZo1#O&a*nnjWSolPKd7KV_fju^64Tcl05*u&k*wvDAh3ojW2y+@eFdU zprJ7_z{76%3XgRmYZU}YdPdW6ASl)HLf>>VZt^OOFr&Ml?BrPxg=m%fomMasjRd)N zy3jpSjKo_V1U6dSpIU-S-BE?hAnzPIGo0+?)+u0RLStJx4z6(8%QmDm61$=O#oA=>IN2}%pD_7ymMs!AOija4?0R^<`O z*<`JB2|`a91b=wR?^TOS0gH(x&1i<&eu}PEV6EX#wNE5Ui+eIY2KQOn3xfzq;*^;! zmAYMA(wO{DSyY7!0qj;W{?K?>nQ7*H6WAKtG0LW6Kh7nFFm=X(f}cNZH0()-a=33~ z(}!+?))TNUoW0+5C*s&CZ((o!S`UC_J!EuY!S z5*5mKP)P_+&Zvw&$31D5xDzq&?c4C+acR$A7kXSNIt`E9`VVL>9M*c&tN>Fnq&f+3 zp2>zDmcik5tPT_OuL}wf6fN*D@x7yqIW5UMJ`%9BCd@RFNV6KR(XMuEjpZ(R;J3uM zQ-2Bb{zk4T0Z~pwMU7)5QTwU(;kQk&X^=>}B%i4@CaGQ%?&y|Gx0`LA2AFUx&kv@z z(g1mIy_YwcD?j(NrW6mKhe#X?k}NrGwy`1GllVijzO^#pG~a%)Euib989Bxi|J^-V zuLxEE9R#9{NGexnI`+oFMrQ&Qa#c2Wia^Od1f^yXz4-8T+4667c>!qKdP_ zR)M%n*WApN(u}fCTiMe~7JPQkoYxjv_(CMa+s>!(F|Z6{C&>Y+n&<)@o&2`S(DWGR z<|}UdX$g@d)R55ah|yC!uKmqheK7MGYMf-~yBrQI?NRw|d%`%!e3R#qQZrgI!@R1P z9A@l_YjH9HnSDw}yg5~W-%3^;|7kMee#aGalE9e2oSC$;uP|6pYco5q;MYmUPxTaP zf0>Qi9YI@hcHtM%vNJ8A+gf3Cj?c2~3=ef4QCXuqTv|`Wb0ceV6^+{elwAKI&u4lKQjGih zd$>@h!i60T=Cah7NdJ4u^`m3>zYhH8+}Mvt2I9anS4VVD(e+&ECNAroNfbZD3(4F{ zX51gy&CBO_n{mt2&zhxOa~+NYgwfN+&z4k)l8N(g%|p@ViSpz z5u4M$^D{XI3IWu2GzB$0p(Wn4E%jU46CXD)iY%uwo;oxu-KmlhnNWXcxR#{!a{4-# zq^E2x+T4A!nQMUSdva&W33*a*dWmtNeJv;^f-gWwBs{p-F5g~;ujw+(F#!p@#; zNLZ07-?NC$AC+lJ+T*XRMF_C+wk(S7PHq%6xrUr}g}t_4Vba50u-UO?6CB6@E+SjEQgNwofqoK!C{*D_CxOVKWTP%pCGt@bOQ1=qg7j#Ud#!;kBFk9aN%D9=j7A{ zt%Ze0KJ{_WV<#74t*LVHp8i@hRQ-U*Vz$4zaYhD?uDCy`kK!2S`Nbmm5|6Tqs9%{Im>Hlp#rZKjF`Uc{IuNhHn^Mw;cH3h} zaawpl;L2&N@(=ujGIWFB`R*HB&AgqBuI=LB8@UDWw)A%^$vK{ELYf|C&j%jNEKC!P zEHC$(%4ii+?DOY|e7Yu^$03mvGG7(S4snrBD$=fcv7U=O$#Y$bCc=zH$ zu)f1D)674*Se&Ed1bxS$kN68vJ#{7y(J(f4G^j~DRvwf@D6EnwObGCpw#qmU|)iNQh#1T_Qlu z3r)w@E>E$Pmf17*@s4;X$( zmo{a_A!XxIgB(SFa5M)l; zE-xsvkCbmf)e#>926;cAUfypkHL-OLyG951?wA8M&ORK6+{1c_$6uY&q|w6H|xrI~*)V@yt4F#p_Lk~6rf>Vb1im#*CiwJ%8kbp?H^RrhCqBwOi8 z9y$UOwVIT)YTPWnzb3?KuBqEak0l@qH$&wNAZn;xn7VzXnhI1wopdyjRWxi>7*xlv<U+dT0*wwqhla7^~&n9r{93X!3a~80Q=^zCJP?0tKfaDzwe`2 zU)G(~b&cJL0i8X$qpojQc$Fz(#<{QY?DN7+Gzo`}j$uwDBxpl$6(xUG@zBex@*iQ^ zq%LW-NdOPEJIpT^YUM;U=?Zw#flXXMWO~Y6tCuD|o@A%dmL}L%kKzUyoXpoeE825` z{u_+wG-F-|{nSUzfP|Y2+0BBfRt3w*)hc_^NJ&th-ufFgz=y(?M?=3P$EV28Zfs2{#VN7}hbEjAiydzRDmGam z6+Jn>&^_Mm4dr7>6aOLrXdeS;)9xHJh5%B5>rmkxT(AE3!^4!o+Zzl@KL7p?=>gP* zBB7J>Bz^Z)jNrXH!~Kjs*Fd;jIC^Fk$YU3=mjc@eXrTV6VeI`eYatuzWe~D1f`<8t zUR6fS2=!vqSf)qz7bh}$o1<7L?A@4FI{Tqv_<;9WF$QFG|~CQG?==1 zWZ2A7>7bh%*tqz2a(FTQOUJk}2b!cv4Ukm)(6_{hC7W*SN*x133nW`fwU0T~r;Yx8 zUc=AUL^tTXu{J(J$*xB~W4)0Y$3@IPW zWaV<=+bC2P|0r!hGwSI%eu8h|dht#8g`}^l-nH39Z~h?`3^y zVxfBb#dO2qHl1kv1%b>AQejWrXr&o#ADKQjEUN_4oMTHj#*X98P!;d6Zb}*hp@hv& zHEnw*m;6>jf40A4+*WPy-nEE2MshSk`bu?nrF;m$s{wTa0OD(7O}gW&KYo$JvS8-$ zUqL>EzU~|%5C6<96iiFVN9Gy2CZkA#Cob}pnFLhJz+898xpgo^Z9}HyWIC?-nY=!9 zK|7plAMzlzNbx9@J)ATDmPl$At{!xo)eOU$Z_>r3m4`hEgbDneLk|@qTOx^gO>i{l zL@AzbVNG%7rwIoYuLV07RrrIv5kanz>tiPDs|qL?&iy2ZtV>l#_MClxQoV;wcDujN zm}uTwBec94C626Fuc@;4^U*>9Rl=*hn4TusbmM()j4eLf0`iGq7f}aUUw!B@uj{*3 zT6_y$p~C?V5uQv@6b5w<;P`8@GI3WN?^ELM9;K&P%z9vx_~%|cC$gakq@cxWpqI5= z3KCbbyd`y*%?;ZG=S^PqUqgfA{8YXAw?{DR**q3M)oCU3$j^uk;h%lV^MKaiOy_Xr zkaDR%A)Zqf7OsKni|%`+c73`>evzeUHM780n~325hplrA&NTYAe5YgE>Dabyr(@gB zo1|lPY}>Z&bgVbFZQIG@fA8Fxs;T+5>-l`@IcM+RT5BUZ5KV*NRepBh!W=g*XB`_j z8v2E&`)FCKX>2+Pr)|s3kCNJ;cRw$`ArTyg_jG~OH3wux3)^j3m*mO>iX%(fc))#r zPL3chP9v~46ylprBMrzOlhrF6-73}7^-d*@XOJ8Z%eX1shjv7D+@DumN5>Gd6QQYF zLoZgKT9mA&YO&0cNDpxB@V=}V?n_A5VVrR;+ZFEZ{mfpsDR340hlL!$OA4m15BaY9 zShtyOSm=}n(uD6B6dDTV*@!?NS+lxhP(U~<7Wh$|UQ}n-ZcZARh6+8&H#{iQn~A8* zFM#(TQ=sz?%BDcus^r2BWU$D)(K0ENcoypVj$%6B7XG6Kli58HBfH-*B}HQVh6u8p1fsIGeC1m<@$0=Q zeIaK;5ef;$zt)yXpE(AL8k#+hhP=qPuHGP22{)cmzdbwDGu4(h)is6Q!e4V4(myvk zq2M3-*VLmk7EoRXkzYHCk26q&t^r1qhfasiNQ%wduQsE;wGb5x_qz zFhXuFJcS~tiitnX5^S{c6M)>ap>4y#{4?xCLk`Y_3xdimN?fb|6zq%O9NNFy zR{&-_+-W+=_2=0Vf}7~{Ca`fvTxO8aNfuK-grOCp1P{oEU7RpB z3}71yBAl%QrbBYbj%3-Fn6sc8IE>lhXMMjg4tlDKyIs+3EwF?wXeaTr1D`p!4VwZ0 z^#N&{_^;|{w46sMuCFNSPF*ALyz3DCtDHPdzA|FQ6dWzgD-mu{>d~)vN||spVNeY| zhh$w(^c9 zYufl|^LVbcMNM?Kqb#W6s(Z9E=d14PRX?9p*kT+Maw3R6(W}j0;|U{zC zhUQC%+(YYW3>P9--V(2B1?>3{M8FoXmJQ0{?1gc=$G=wq@Ki@*Z)k1qbL`?wk?H=M zAc{3we3$>XpEcOIQw#qVfB6Ub{`oAOs9zqi!7ACCTTAR*8md)gEpPb@JeNTx)%?4* zi4?h6)a;ema~f$d&JgGO)r`xvSTO&Y0?FEp72D|$@NAz$G$SSIX9zp<&UbiL{=zV* zG}ffKuPeR7Py@L`lH#uz)4WH18vgWLX_u;H%bI}@HXtG4bS?=K*Zml{Jeiwiy)$}& zB26I2a*!xA9c2%=5$Bdb&t+!l_4ws&y5ObME_+lgpl5lqpT#E}DE)VgG3Y|*Tl)Ry z{ji^kJJ}z)$0bbN$05?Whz-Hh8p^XvHtNygtDiqzOH?wSgzL77M07BuVA?OH3XTVt zY4&LG;Lkq@r;Qf(_b)F&xf-_g24DGE*J=lLS;9jDki0MTMzoY$4mxQq6Z28-WS}ek zGs=nK@Mj+qZq(E9)p3y*Pvk-@=IChT(E=7o(Z!Mu;*jRDZSG!zmCx-b49P86^v5>1 z9x&#gJ{ZE(;DT>p#Si1*AC| zm5Lxz>JBKeOnjMP&t9j?>;4nOwZQaV(>?J5TZgCY*WreK&*$u|)o1UsIqXLjIbz>4 z`J$c>+WhlrilNRH2}0AxW`CncX^#0sep&md^>YIar3#4EQeokFMDFUlA-GrW$HWGE z6v(P%L@Wt=Pdtsl%bUfxvSLJnOmgs&^g#DuOiu8wjt_5TasPo(o~iyUo*0Ps)Q|X) zSKhf|B8v2}vuDeGiu~xg{L6iy3Ngo_;_y4IjW`T*D&Cbg%0hy#JF`8~7DytSj0rgEg1B6=Yq&rWJWfj(C?<^+Z(X4n$T|?|}V?3Ht+m@=2p>UvLz#`y5jZed9hNLMi zJuNC#9V>ogVy?;FZ^GOQt-~~K>gW@?&{tO08<;97z(RP&Pq~YKxhrr?Wbd&~Zd!Pj zA*b;j`~bIa2mSPKZIs=FTN_^T3C()Jm*zjq?Q{$I1LsqC{h-oH=J3=CY}ye9T} zR+T;rhC&!_?87qkH8DCK2JnN{8EpKfu#O{(eh4e06R(hQ^dpb!wy z7lTj2^6#%n5^|V((qD=v%jbRisEBAAybt9nDZ~%Ce{;r4%B}^z#Q14WPhN19YIsXtBM;W z--J(5zT1PV#7Hw``@{{T)Wjax%EY_jTW>(|$>}EYWg6Hl!R9DaZ~{mIpdg_qd24cv zeyTBE-Yb3FX|I3CP9#z%920n@B)E5zLT^8x-(Qs*KH?X(tUcEZ%2&E)?LYXs`rDgw z?O5QO<=vuQ_Na>iQjp~=$Y)*{VzDn2g2(yk^To)y&n!KkV_*ONdQEa~&2f)_<=WAK zhM*|J52#LQcJ&=9a6LV)8yA1M_>#TU^o{26TRZA{NN>bfezp6K%yJK}{z}uU!Mg|)n42Ab()E;tn!sZxHDbn^}L&nV!bx9eNE=k1-lh6p_6s z{R%l;hF_QG%?72qYgw(Ya4?~)#~A^BuiX#ieCRG>_CF(SG~i95mWjNK7e@`JlO zr98_LyJv6tJxy<@5icUUiLKXxKY1g_L+S@;O$?&&?YB=~Y8{kuGwT}F&vqpn_J+v& zVxhL*IQS^$qgML~xQ9E^*hEH25SE0A-L~$U^s+{WcNHkGG6+Hb8VA#PAxdH4ZQBNS zQDQt{UpaeD{giNhw%veuFxife9X~*g!;^6wel!U3{)3rt!NV z3lyuC2n%)kD3_Xxbhn1-_YvT$(nZ_AE3qE~Nm=Kt*P9xc8pmA%WdW&X4{f@mRqIp` z5dv|A9E^0&A|vDrfj!AK30@&y05+_A#O5V)hig4JTh2j^w2#Q7khCV|4&XemmZW~L zrFuy!=z{0WU(EO*MY%dMo68R)?_GuOJ<_VN48k=p++3pa$*q-ZABi2hT!#j z`5A8GCnUABYI08&RAGg3PnONqWpeF?WJm@u>Wxe5vym-0@uuC2VYmm&Fqk=zEWsDm zjz8XuocbyX&SdF{I|wGGM`=4#mq8D^~w@*lPiu+15S19bjlGRFHBVc^q#t@@(a^@;D$Z?52FC>&7 zq;_c7G%l&}e|Z(gXQNZ>j0>fGfvDM%JW5)&wRzjjYs-!8IfE};dQiQcBE2@JNTf8? z2X>Nw(Dvtigch$2^0E)qJH0ZD@MQoie9YEGNw7-BDL)%CV{$C8nI%x%c{7yFV~{S0 zNn)WR&vfU%_u9NWgbFEBRv+o@pIeuVKE|TZ?pXI_bszHEGCMM=jM*$OwCQfjzL*i- zHB$u!i^jXMW~CBx^!-XkvUmBdt|C11;R7KT*Q)zTeze6a5}lHYWQf?y+bivfE!IO{ z)M^+)R)f}e%aD+UB_F&7!mm~VEYr56q0Ozcj+1wXaB<(-2ezSA2m7@+qunX7kqOxE zo4ZC?_{TU1h5u;%A1%O#K=xjcioFg<#e^ZSKSxp9IVDDm!@U+`yxWuhh`#$@#;_MB zKCv)u>T+6D{)f3hUb{PZ5ZrRSp9VTtXM_OM~>|*JNPKhEE|=Ln6tCi&|BZ?m4@zOizQ^0__^ zISOCh!H?d)yj#x*6#8-$x(J(7{BE^Bt-(tP)NjAMZ3vppP}q|`L4^pFAh5OwYLKu{ha>%UC9Jh7E6Jcw^e{yqw@pm+ou?DK z0_X9oxQh*L7hJ8`tn{NaeX@`0+l5!E$E~2^h$rMhC!{A`nWSWbt2=#1^h8kpVrfqb zNo4+(h?S1M|?Zd!jx^f8z-&E7re{Etj0x?9@6gDwppB2(8Ed2O^7BU^wX9ge%v z_KHRAlg4MpS|(_2t?=;hE+=LU`Lq-M?U(a<+i+D3xBGlo04HJUb|z`RoO!X@c{-$+-_YAbuAz5@6AWOL}TC^d?`4f3uHRo0jz|kU}1cd%O zKtUdxlqM2=-bg%H4CiKs`c)fs#{h-Jx ze)3#rxoE;O^{Bd?1G&x+a*8?5{#H%cxxuoYL3vNa<8YBPJi{zW%<$(3+azAtL69I* zG;^;~W#j+hlmtF$C32Rd^}9{is*Xk7r)($lNg!#OEQ)d@9S%*YAEDTZT%n|dXnHtd*X8TF0Hb+) zW?0%&=F?`I)8%JnlcD0H*`24)$CG#W7Nr{YIFs5G3HFF#;VtixV|m-OtxOgB&zRVU z^DV52Pb5%0IdIVlM#Oslf?ZLF1E))1(FZ8eS-`RdBz>@eBGMRgDs?g67leM+Rc@{; zaxq9;p^XADa2#6!f+@XSLR}d<3SMsgBJMYPEm)Z`XPNdcSK|z}JuIK-18ILzNm++a z+_-CrMZI(%y))feUrMc65;pm%BKhUPO>MJZ<`~nM_Ep@^gx-JY19-y24_yyIXE; zj5EvMkz4uqPXq~`2Ot~c%?60kF%{KAG5m7^)p49loCHQV_o-g<;%iNFtSX5Bg?mx#N0@Oh5$Kjw(*qPx(!*e^)6v*& zgRC+<8{^Z*FEJMY-S9AK+8xhW#pq^dr&fgQ?68Rp!jb}-164(cT@h1s95O9z47tSu z^Uq{$1Li+DE9o@rG}ZfF1=vqO4y11Ww3Zfb)YEI_B&XgpliCM}1O0WvBM;mz@#YcX zU59IELf&Oa0aw`bV(s5eW{QA{U|3V;SKw~gYW7G4!^@s|S&T}BaB7WdJzI(lrj=yP z;$B*lK;GGIXpCM|OISMDs{GLFWqb-C!oQvfe=Tsg&KnW8864FR;&JZRv`5gpby{X+ zc9F#ZIBbaNz)%oss}&WkaShOSa)FyF*O+0c(Ql+G>g4;HXzs&+I z6P9UdL-JU~N#er&tRZ^9MLUONxW3S-k%q~0%2DO+I%;tUL}^dba926bWn>1^emBM! z8}9O|jcmw9y1>jZEqF;m;soM2Kf)w`6~R~-NiYymDhpHC9h==gvq(yR zaWtgCps%1KL?NBy=5Bc10PvV;`~DTMowq!jE#e={Tv%ANfsJ9rl&V&&T67I}PO@?e zEX>S6AP`O~3Pr@5%drfNg@vTj7Fg?AJFqND;O)(Y6NMo}Oc)0vX@XLyWVkb7*%Ycp zm#-#DjQ-gVVv7@X$*=#5+xd7pPh|M(?)c}b^YQaq0j$MaO$>eRMGt4YANwy~`*&T) z#=IZFSZDNPM~K*on~J&78}i#TS)#4j+f}NBzUhN17j&P$OC^TfDC;c8-CVnZ+cJOF z^H&~**%Hdz^%@K(1+lNll5npk96F>YI#LuTpWU1gOVpwX$gZzW!iKkO4$1kaN+6{g6=RCHs&pUTsxY5!`v8#-YFvx~DhN zTa^iKAp&`&Ht7R3YnN`je)Fo2Sb$P2BkgJlv0y-5@4=j2jBqLc`>sI!a(E60Q-iel zX@9nIY#o3ez+1*Cvk9qbvj22#QpW=k7uHJmM8y9OS3#Kz|8eM8GmVIaRWOGDQ@ZqM z2n+b4erji$Pz7U3dQTt)2RI@_M4mh182aR?%P-Y^K8(SV4!=`CE*`f4c2AzjT%hqe z{$u9M9qNs0m zI{|SGhO0$@?{}5s?XA!WyNxyCUy;)Oq`P&xRGfJMiz;AS6asM4!BQ|=ux&;ZY9J&t zYPu$!Yd^Iu*P$gnnYmnq?KhEnRu)Q|h1e_IjFMI7l;zp#5!hTTu_Ev{qwoAP&n72+>HXO(gWLjinU43#`tk9b=KEyh2XBiSDQ2&W7Tk z@yD!~Nr|4*OOzVqNGZc&G$7q){Pff#o=^}EW%S=Sc{zPVt%u0`oxwmt&73$L z3f`NVGKiM&t4XCKr=+wzLVR45mZP&jxQS-@5bW`m-c3t-^2V`yEY%#yl{xP^yNuNo zIQSFG*V8r_cZM}{TT726r?JLlmLw`*t&0oKa0>SBnbnEWDW&evh+f||FLwg2%IU|> z88Nip!QTWM8108&*?g2oyKSEPiMY8(IU_?Y?6DZ_SdfCN%42)+3?r13M7{%YZ$>|& zF=WCJ;0?t5Sh_D!Xt8$`ALO)d>nZJ&XAPPWh6__x@Q?b`2%v|QKrYS+otn%`$0rVD z4|tnyDKSFC8{Df94f$PCWgm!KHuCT6z)!#f*4+>P8qa$)s6A zIA!s-mb@3-tlNR^DE#-0zpIxhJTqQGX`$(zO z-W%h#Mo*r#JPd|xOL>8>B72#i;$lX1hI;Y?6P`GPa$Xd%G7S9N4Tmk@gH?@lX8!ot zz*jc5fnV=fhK}181Q}u^qwJbOA1-cKW6};4KjuG+ zLj&57xKkY;PqV2(wndTU5+8$Epa3Bv^K-3@C+2GRHbR{RXDP zoQ;wlGjg`UCKcIs#+{yw&_+5NeN)NMD2%^=?B=3`FJHWp9;uT1Rl){C>+3gt1f&bg$Pn?rjW0hZIQS3F`q*JgKCoC2i5w1Kj0)7Y zo92;R%_WfJm^fmMt$sL;>SOJFv;G^%QuL~Is&1LXHXrWnmF-SDHm0`%2gU}&I4%E# zC=liasIgU+`K{KW6&{#Ntif7N%3wO^@vv*%z}|D?`3sKYa=P8yDsvUN%04bDKF_D1 zdY>Y6aX-e*;BuCP_f8yo4lEV}3{gRwZzSK{nu=?{Js-N9FmbU9A)lCjGr}7O&$IjT zB5$5N!bV9RQTp;uyVO&@J6X#VKSG+BzXy$|DZNk40xY?_qx^z6SV3R!`bwmdKt#)q zTW)`s!d-T*f?QLe$e z9XDN?euCbjLJ}`r!9RG?K+jtKe?NIXxQbUJ+?+XL`ockA-qz#XOXAw8LIcVsImf^U z(#(M=pV_zCX2%gs#5Eg}mVlNe0#p1}!e4?3OpA_CdZHIEeB{AfJ~YR?Qx z#NLZiB8y_ucFD?Rx5C(OPAKd(#vvVnNmKn zb`)Yf(_jJDc7P;9^#l0sIa(k zWYmvA?z?a?pEYI=z{laOZ-RN!b2H|G)$tFn_|Xk}WCg3?Hw;Xw$lhZK;!A`x~)wK40}^ z^t0QFp&6l2G|pcM*@q;DJ;W8X6iP+066E)YtUyn!dYuYEdS}M9HObdHh+F%xV{pj$ zcROAo{Ai8RMhz%fj@OUpp&S&fBY-kQP!E@gW&{X}ls(F|7ET%d&vElN#gzBx_qC!- z>l$-hc@!!txIRMUFYlM@&$qRj@u3Iw6+~GyWiLu7 z+I+gxv_J)9XAzL_>-<$X_|~i7g(}1p6rw2;h|vQvQ@KJTn@nciZ;WrXljb{m{O{5? z&To@Yt$G{+4)lG}p9=)g7Ni?>)v-(4{*}c;!;~01==>U&Ipc+XauHN0=#wlLs>(c2 z6yx3y!)%+ODVQ|G95-$OkS-?*c4#8;xM`#g9x#lxd2eC4yHO*1vLm0H$>*Y{;*O;G ztjqiMswbkMCvcsQ4AfT*hzDLP6{6Zbl3OIr9V@7@tg4N+*|(3{)%G(pXY<*M)i17q z@p&9iyrsV@+_kRe?#zsldM#E_&`rmQ5@^Gjpxmd45L2FXWJqW~E+x9iI@;f`V^I7u z>c{~Pix46%{T+=st-dAo^^dioIa=fOb=$%=y5LhdH>fmoS9A1;bzgV)^jZo3_1(X8 zzyYBO%|S(tN&Qb8YzhwN((y>345`#wz)I?NKtXq+*y~SbA(K|7n9a_q5lfuHX=j#2 zrVuWy(|_U|Y$%4YH~CS9SPxjhhv^MA$vqJ&mRYe@Pwx8lIS6B}1T%?Ix$0f9rR2q-WSO161tn93P8FImHB)9f2^?|9w!(=OL>@}et1m)@>HMqI z5v_mPQ$4-SMvPriUvJ5c)(dH~aK)8hB&1>NuElx~5p|+#spw-lNZ{(;|7tFpJV1Md zE5yDm#}yaZ@8M#M`q(35-uW~tKT-0jiwwOm1yArnziHCmj8@bx_%}hADDBiZD7iD` ztM$HTDf7~H4TQa6B(9uOkTQq4lE49)QpHtT=Hk_b7L!5}Qqq1THa+qHqKT>3tD<{~t64V@Ly>s_w{s^(0W}S2C@^i{*oGI5C zt1r-&+CcsXgRM~jc0sxq19@WO-FMxH$FfvJ`vB-06Z9wQ6jY|lS4Egj_K6I?*SQ>d zM`Hg1jRRyCrUzU&NhNU3`_-So((k+8TACv%UD7wTo?+qDnB2PWRla~|AI>_{Uo{gVMJ&7 zcX63)}JmCHB?;S_Lbz`q>`n0375eD!mbvQtc9WmKDKBnL&Va{+6 z!R?<3%9B2JJYs}fyK?v$mk%gg%vSHZScZs$#?uhwSe(9STM##`v|7pXK@I)MeL+~z zHUdRO)d@CL&N(6bTC&*~k?x;nuUaZjznsl7^Le{6Z#5Com>{7-p^dUK(7qK8tkh({ zr@T~)67oIjB2Cw_RA&in_t@4d+?7)@!=woX^kcB;vAtDpdi=B8;PqnED8n*rYDP}_g z@#S8*O5L;I3NWB=IjZ_pp9QW6XpDuI%}DG#xCDi^7ay>eHI^7%6)K(F>{8v~(+zb+ zl{__gApX(pr}erlBPyhOrf+(<6Gz*}NPJwbuG=^MI4@Jko$K?8Y4d4x+F(_4{jJ72 z+By$__vgg2>xpwGE=++%)-TdnW=mV6(3dD5h;uCA4a{n4%_pl4Ys7 zV_&wDBX=_fqmkWj#fBOIo0b<4#iK6zT-24<%PA14Pp|#RSZSU|p`z@%8fN#_aGITx0B>nae84wyh7KYZ9*R-ne2~XOf zkn35mpqong*PweSfuxoG1Z4Mmx;L6;@4Bq9K18o+WuM(Be7v^}NdHOH7iB13S}s$Wv;k8OJ8N8g5>R- zueJKa`wSgJC&==Slw2dGP*tUwvfJ@gL|>Bjspcf1#6mMrL$aM#(?V2C0gBxc*UPZZ z)yQgnFO+sa@Zv1ljw75xS1ln<>yPP22`ju(cSnEQkhnCM4_moFV&ySJGH%Ap^w!bB zoS9+W$r!y{{tEP1MzYH5os~o!yk{wFc;LP4>@Q+@qU7uzagD3P_(|4R|9I9#6(DZi6k)>8s{7XBFGiKJd zTLaS|1_LTu$6x*7jBQIcXeapfF0Zh0^D8BmcC0hDwb1oM*=Zy1_w$G81R3OzjM)1_ zrR1%V;UID6G>L?EhVLXzw;ft!Jp6eP?sEe=pMS|%}n zh^{n@M1?DdJ0xEdppYNp1-~dy1t@Cj!^Q)IWVwsta8COck+f+e z3nj(aeo~Xao*s|9hKKX~Qo$O^!~EdR*v(u%W{lZ!!0!(_@$zZPsq|rpR10ZvcSWkJ z(5X#;(!jyZM;G$_p5^L;q=_MNE*$zfDl+mYb!rmSqoKBeiG*Q@(#`1}z$Il7^;GBJ z-Z4pjxYUz)K(DD`-+E8!(dF{MYEJx*7C?w+LtGy~-cnD~s>m~m+OWVWT0_J|7ygXS z&N<%QMIruQjo5$2{@=yd&YW?UX7YDYQ!tl#%u2yM5hm}H|G&%8nE&6$uP0WD(;E;o zYJp->hK!oE3wMi-py}fuj}-3P-6JsGihsj;d6h*j=6#*wPyIbEaf0(xUY$^slN)A) zB9adA%ae6xYgio~qq&?S0yKL_66di9D#^5Hi?jsC_dig~aF|Cb@V9r31sZ8)m+Rco z-`)?fZer_-z3AVqsl=Y(>eg$+3R{+t&1lTyJP@?xoqC>Gi)^P#Q{nU9R~+GNJ0-OV zM*pHgu1^SkKjoZ1f4b|d&QxCoTE3K4H4FJrd4S=lc&f=c)`J_g*XGA;6U z?uQf6=V$g~{a+qkrJx##N73L+39Xu@bEY&lu=&Rc_A>G~Ges8fVmkQ3T$24Bi8k6! z_Ooe=Z_CKy*|asgxY8IsxjvJBej}d+6OKL`(5JETHs|V$WB}qiyDiB@k^wQDs7ZpD zinm)NF80Q~o6X=$Q%fi!JJ}EzMsY4NW0cxmY{wBZ)%!bs44t>;>*ROOmv!SFw-h#V zcV7&Mjh{uepsmTSK=4*%BUpswU<)+VV?Jtw!n)8s z^^mq(2d>8%03H{PV0Z%;M5jf0*Y=;=Lau~*0bQaRukdbDYloH2gjDp$N&rV+-~11= zoO}*#30FDrEw2r6(;U8t`1qA)59Xcd;N^03$t(R`!v)hxwi9KdjnLt8s7JAt-6NxL zS)@1^>c(&;4{7@8MAxW3io<(afl%LDh{x*qdYxHtI?T}yCE$&c2zOLJlqSJIbK`2ndv+n`e7&4!6I# zCHv@|OYQJ+sv>!Xft#3nNl_=e>87zk;ur% z+Q#}m;5?kSx3{QbxE8!t)idu8IYA^*RvbE*pr1+70cx<0ZE$Tm(JJI3x3+>AV5~T7 zT17vjwElh{XgB=nZ*}mzEO8QTU}_!GG`W=ttis|gZ?4=nPn!*_Hq+N*!x53ql&xhC zyv3VKg?NRo8*So7j=*>i?sV}2W6AHl-_~i_S%yYN{&^(^p9#b;r;9~~xA1iZ*L=OdXG>p$GvJLU&z^f%Jh^i4K$e%*#9M{#{Cuxe!=8;+ z0$$0;9HNReiJBu~h4R~Hcfjt?14U~^=IM?wSGZ3*U#{6HW?@mq&hrm z5%(jslJFeIcT2oOnx&gFIT?)xAli=w0~*vK0tb?w$O!Lo>^~d8^kwvO`D=r?HtgVC zykH0?UeDkC8#M|_iZc=sA~1^?n+CRld{i#P;pD z4n40)|DZda;YS0_x{oY%BLs+61^63DBdUn(K#F)H7))8wQ&kmuSK+d4N&Ik?p z#og)*Mi{JAf$Z5O9A9AOIECx%TQT;t2%A#u1L})?HZM%o`>YOm!-B|Q2Gc+53 zi5lw0a7Ba((s3iEP_y8Fr(%+#JuacWmo`ft&4}Dr8H@8b$@u#MHZBbeultf;3Tn!+ zPlPv|GvC+Hy*3VksB3>J!}Le9*)EsUuySj%MfB+zXP3qVKU3!C*<%Y34C%KSGrr%O z+weoTLW%w8`@V5fLk|+Xthzx%=7{h}+Oexj#fIXp>*L~^2x1J&jOB$cNUOcoq2bC~GZ6zE(JFq-lJ zWJb;e@LGNmd(K73NH4Cd{K_D(ByuG4E5>)fs+=$T%=!2=R(a8IOZdifY9*SG!9 zG4B6fAD6m7-@FWsLko8RjN#h_^qSA7tP^_AXX)iENrgrnmG(pqk}K!h98A8zIm&Mo zEG-kXkklY2orc$-RpzvezI?)n!|;4Q=M|^Tocp*1uJ58LB}_p#ya!D7HNsu#9Xq9Z zA^u}J!ZPNMXceM?@fb{I)P3z7YTP&}5S}&vd?Y`=Gb!OugquyuNIP9`XR`~kixS9z z3E!`+%tF?VY%4=_((hRgFrx|IQKu4KacYWi4uSEbGHKUoCGqHy(E@jLwksq||42Bu zJJeDEU*VR2*Li|cJ?MfKW@Atrz&_ylPMCY4iCN(OB`c;2+vc%01J*6B<;PVv$udHA z0k^QVvs+@T!j5a4f+9VZQTM#8VNf<}L>x!hS$gx)R50wTdwkJb=zQQb;=snWpkR3e4He$cdeMPW;(l zr6ECZcp&M??)I%NVGFP0f4y{>elkgR_oS%w>e93^4G-894oxXdH!0mFIfbo`XKK&< zOtMGD{WXw>PW&kTQ|p0qgF|6D(>;iXWl~nWC&E=0>PAf~S=(BO7<^|iWT(8&$4tgY z0wBet&kMg(wxsx2r8!X{L@a&_f(Cj}==)n%J`aU>H}vZPBVR`jASOD=n!WE1OSD`UA&30Oy(TFVsfPjXuw=+T{enYr%9~p5Dr6h99B{>Cc;##K>xlx zS!QBKn@$z0qk;@^YU4mNQsNGaVlt(&oAmRpTS_R)14f?`e047uZ&!5 z=@;L`_CW ze=?844xE>p6E@E1>hyEuxHw&f{mS+v*7W4WQ3v&|WW#|oB`#la(VFy;dw77*0;(CO zy7(>h;)||HY1+^Vp{YWZLjvKq3a)kdUseJlmqYg6zK>#p&ULbXnibT=ZyLn*VGH~w zA;Z(~k_{}0#fF>TXhMf5v}O{&RlOuns%*NCpANgnD{S;I`!jm2 zXbJpZ(ED)Dq)kqI;ybrOR9F=Z_?!L>yVTEVR7az z+-*NlWf$YA+k6oNvE>y=x)Ntu0ai6M>Gbf927Wm9`QppiR3fr#f#3pg!kj}TOgTmc z6a_6)&`bwByjtu?=SKqxWsphuu*1th3R&Qt7Z)5}bSVCOAaGV{j<=J9fpMQ2fAxLt za4C0{24BssvWOftf}+S!bn?+UI5CPM##%rc76%Vi!pLXh=E>}d9REdYwtX^elMT2% zvDK3Q?)_>*Jd+huNw3JL|D~C@ay1vfmYNO6m33g_w<-Ya80em&81<2bpAQ$n=;8`W zYzr>NsBU{`i!4U)|Ln@YC+uqOnF;1bP$@x=n6J)!n;Iz#GG)>Vc$sf0j{iZh+u!tS zBSwmMq;`L3Ge=l+ap8|gULotrUz>edf$*I`&3&k@zjlW1-cp%)gI@Es;(r}PKOaMD zjD71wX(Lsb06pQbDeWUxjlG=CbZdGMPOzLnaM7c%ogzox05a^|0FaBbNMg7lex;ka?Kq`ryRKS1$etrjX_Y*fRg4v zzQB`tJ0IeeRF?+&yAzNH=u@zBhj!urd>r~31!z%d>7;(0{f9X2!k&iwH-G%^9``>Q zx0^4_|HB^H$A2oSFzWmXf21iH!L7|3zxt(C9buls&>F4E>~p7JG9TsCZ$f~vqs@h5 zEtp#$XMWPNBW}uo{>WgQSesL|^C}7x^BeQyum8Kz81J((2C=MA5 zoBp(_b2P&#u#8zi6!`k*-J=RRS^&yd-DNBH=>1K{T1|Q97DB#Gn`@ha#A2qeJ3yL* zxh9Sfy%1|ekeE`iN-Qt+#|v0Y$JOtb8!oHyVJxjK*zcPc1=B<}P-nnTkJb2L{drHf z+SHmU6vlW?po*w(5h~#-X(A>|jxN=d&$4@{%9l^Zy@H>`+Gp}V?b{jAHXDmy@jK!^ z=K3x$mf%AMF&3{iGDW1SwuN1<6&ew_5l2)}aH5YWRrVHjxRaPL)GxTM*}BmO5Sj0C z4Ce#7B$pxOl!9bXcO9YpK{oIE0xg#G!Rl^13^=krhv6WSBC9cc!5F(FOm$40%+$&5=nsQoREPNw1Dbj{CliJ}rXzFsI<%yMDr2(0msFyB%Ic9OJc9}b`M;}(-GIEMUh7NxB zbb7_a(*7H6{!~5fcnB6`tEJ_wXJ~nf&|DRZZ1v_}(q-YLDtl9T4Vvya8OMJv*Rmym zoP#n@;qy~Xz^0zX*5Xv)z|o9{z!{9h!~QVKyJC5VMo5~b>qRs3t1&*^Tz>hASN3#= zun!({@(!bXj&wEssf-%99dNneOz$1>A?4GFPA~LnuRCs>T3WQNfS%dK8)Ei{^X&6Y zYq4F^K#1X^tz_hlH3hgS1~=Fxy_;>K_moh-AM%>frZ=C|b7ba2m-8sWcna_f7?t6| zGxL`v_7jir@X4z|fh&?MLIGnfRlO^1ax|kL$Ex@Yzf7<2nrjFZUlSQ9{$Ac{!8I9g zbx1wwbm@qAq@`|vmOK`h16kWU8heGl;!LnwzU5T#Oiutm%y`k3QUJI-hh-Ec{`al{ z`lR43xlrYDNh{xPFsHcqtQ~6v`Kt7L!gXzxc-E0mxOP{1QEky%aYo+ zjRHb3KnWHm3ayP$NFUFYhr!-Uol$>W~WGg-X)*#F||oq{6| z+pgaUCbn(cwryu(I}=Q7+qP}nw(X>2+dI$qzEAD%VAnqB`d6QIRrlTNzJAwQ>sC2Z zXv-|o)Wp7iG4fx8j>xsn1olSq?vroj!(jgnxTz*<$q6-|Bp??=maa!%)Rn};%b;wI!yL<^TVW{eV8+#Q zPxhiFK@wKmA9rU5Fury;28Eq0m?<%**nEhB&sLn^CW5@lr7vjb`9pCg+FzXnXT&eBp zI^ZkzNrD7FczZu3N0a=qyS~#isz0aRsb@6`+m!+l5qZ=@uDxqm1RiP*U^Q1ELh^z{ zYC{Pl@Gmvi%@d;@$FQI^sk}qJ!@`ft(~Ys{71WJ!B$`t97x{H$%&lYQEiCH>PJ0E; zxbp^e%jeMl@al-|8Yh`kDmv$xB;LY*BomO19ZX+GW66Czl-96r0LDV=WPJ4ZDnSiv z_|ks6BRG}!))n)tVNxNy?;g8@6$>_BEr38GR>BzCNA9JL@o2*`->~}2>g`U>eyZWsfB;8IBWi@e^B&AyU8QZgrn zqkbyFi~5kCV`bU5J##Jn-19>e9-W(4Grc~!fFGWGSqom!Ee6n#li-*iZ(2Y>1K%a? z6wiEHtbY&EP+1+Harj-G8BOV79dkkKd29)MsLwb*EOUF^rlm15M$TBO-ZOr_ks#-{GAF1yi* zZOhNypWfB|A|-0wWZ9^NnJ*HgQf};?>s!C$BV{nhuvPKA=l*g`@{Sd&59S~kRXUfC zR%9MWl;Eo}>#G$c#TZiR?rYc?g-tF!HtsomIB(v+y)LU239{X<96T-`{~iJpp2JbF z{Q)m>1#MVB%;D{^rCKoS5nlYE^i?$L_iq9AVjF#s9?6FBqotiO#wXBZPWT6-_u#?*`?v$l4QOqxV47164FCy`jA%m9}og zp?x8%>5iA%BMXbSob)ZL_extL*9M4nbkyz^g%=Hsm_np#{P#$OaS8v?+8qk8w{vVF z0kay^&XNO7W=8a4<`0#i-aKJAl3b&)Vq8-k2;y&4T(=IM znATwXIla{N!uhBWGE&cJjyLN%3RAERaN3e_uZwC;!}!p4te&)X8Ds9`9Y5tc6Qj8E zdJfD)tYe6_kv4sl;OPC;qDoN}358M60OUxDzp-G)*B}u(Fg#piA`g-_sniJr3z429 zXsz#92NgACKf@;eywqofEE~9X-BVd5;6ldsK9_u3vNXh;bS(_*hT?$8(gf# zcalfM@8lHcDoN^{7^vZF4=g7k0r#woMHXbW3-5(s8tdX3JE#Kt+4YEY=KR*p2V3i^ zIi=tkyCnk&pM=0nAY2@iY$36m6mHy(Z@hHFb!kSFlkG{ z$J^{H{U?He{q2A=w$~@ulK`s`mVoQbJkkTBYFLfglY1-A10{|N+I`zRofGU>q68@g z*cJxu2kd&=or8%z5r8NBt>w5994K}H`DaXosAv_K=(#GGE&hQ@QT!hR_H9Y-mk<^! zPuiaE_Vqk2Je@Z)2kQ5+hV>YWeQKOgW}@X2#zk)_OZFtsDtF0& zTLG9KLdWGkL{zNd>>oW=>o1vOXr|$OyAGzjde6c6w;L1PynUT0xuSa7 z0|g(Re4m98^#<^s&vpmB)L)hJ-~srHZUC&(&pYPooG$SSBOGa6uZ$OS@qL)yKTrF0 z+H>0dCsWU3?c74meS9+gPxcI(i6Se%6AXszsRvek#0@l&G4GtsiDT-?*Zpv%lSTu@ z$jXvUP!^f5X zeCvRj#Gn(~x~0VG#F4B9l=MBXOcBFRP`q5qTAs6vvKJ%140C-{7PWp3S=|k2mOu^K zUS;)2eVIMGTA#`r2pY&{ zyiM&)4)^$}tz(l_w%7W*qp+CHunTj?!c1xx2)@4B;k5uOeesF|pHE;vS`~DxudyUG zMBQ8X-vI(CoOo@RPmtF)yT>)I>QP(Cr%!elJ8q#gGHA!DfM{$r$`F*{b(ctjYy707 zDS-XjeI?z^Y?`x747p$!!{fS?pi2TB5f!yhC~2Gh;_c(>mt!Kz6sH*=aV@9mk79uQ z#*E|6&heM-d;9Pi@@_7Whzb@^nM`-ZRgyTbXDD_7CY};Dl(d+~WvMS}a;Xf@FTn z4uvsr@mMKCC8yCmb=kxHL&$Dc$<)jJ(oN}Na9hu%)H1u{YsUKy9Tdpo3>@Zgc@3Yb zR~BQw=n+^wt=_r+VR--J;R%Ue$zz_F&pYtJ%L0g$aL!rCIi(~2_tD$pV*dZUG5ep_ zgzT;VqQ1M9d``s{mHD(=N{cZI&-c}Yw>@l4#+iVogaEVB&|7td+L%<6Umt|OlZAqI>x>?dznLFl)>1OlE4nYlv zyfeCVfhSaQ=kjJXdX3?5ZAn!`pyypr5l(JEg7?0#t_bRSMcgre%gslD52n)$lX!Ah z1iUd$vKF79$HY^WobPh@xAXAZd0H!If^a`+tPD_(sJFN16CuXyBgXs-1hp&N0;q2xzOkMSM!@q z@F&wF_2H4rO{y_m-2&;b1L^gisW7GO+B+T5orl!4Y#-(B=crHj7iZ`b5xduxA(Z zP^Ohs1Jdp;8*;oo#HrXz%vua6L@VGFuPa(rIi$fb6RfPze|g_^+6z^N61~8dE(r4kDNs;I2@`^Zr@)5O(;vtuv|S{Ur!+@+ zonO@y6g=#Hc=zwY7|FVdwyu$3WPBXP5!&d7(=oElixVL#lr5S!@~((bp}GUF2W}f7 zhz@Qaw(2ctyUj%)f&v8z-3n`Le1nN77UtyvRjEZZHL)_KUD)lnVqyK5CRH@FwF_!$ zYOG8@f)vYCSXfwcOG-kbqNaQ%_&^17o12q~#iMgos2JJUOqa@4Q!_Ho`F`R0FhlqY z*xJ&Kjg6T%X@SAx$v8PZ)ZB&6<{ilY4+PZ1|ABzt{%yMGvrjQmbh)x4JJ>!uKsLNi z?CAFw59G#0+hkMLbn&w-Y1~Wk7J$o>txaLU57cOOcLgRV=!O1}I!gui;otA0+>VJ> zw8WG-H`-*u(Z+cdU>W2o6g{08KUsN5Hp>TWobfGWX9uUV%AHg>J4LKVM%9Je2liVi zfw$+b)b1FH#3VH*6e6m`w2VE(+-!c1;{xfP+r*n@1QTNZW!-3sDhpL{xyw?FiBKn! zO}VPMs^toyQKd~yn_MoznE_)c6=L}<_S}5XKQEjTP-g}0@_zDJMo?*IpAu_b(;5lgv=L^OtXe+|FXx=ckFM9GtYyeYw^+h z(k0PkFioJDB;|e6N`Vwbh^1yBkP7=Fex>Jhgq`S&q0Ul_yLsM0-_aMw8{h;wJiUXy zaWSsIy`2V>+7@1%wHV`f2w0|IUoPyBQjBK=JrOMzrMS7?J!iI89R@FKz@#?^PIbFS zUapw=r2lhmjLBc+_~IQ1%lB5KNj;tcU!bjxRh@t2h`Z-bXmb~i8syH*b;-ZQwhZ5( z2C_j7#T6yFnmD>B%l7?I8^w%UUF5k{T%QEDIXT2-mcMWt_39b3Z^)!^~c0M39k&)?~5}`+FuE28LRJRE4o_^+xRXw1}q$N)GO?sQP(i?T=&p zW$Ku+0EOTC0&37BjntSY9f{xEUHC?q-mX%9?<|ESb>9g{4re%+T^3|>)WeKoP;daq4x?-(IQWFh?nQ7 z8qE{6W|3pDMs<;_ED+-6ZU`clE4N6{`1Uf1a6WI(*EoK%?E|!9dAO&xCLk}`O$G9F zDU_4J8=SMDK}fu8595&+3%zHeg^a2(X@@qrQ+*)o`j@1joRkv0LpwrZ5|r%3op-q- zq2LMTe+Q=mQIt`4j!s?okRRp6lOwA$@i;I#f}b+>-8mb!b3(; z@`k-Yo1tb8l~OW$Q}p=B+J>Y4N}JW0eu|J`H7%&(ieHSRw4&{VZMx7Ud|MzA3P)iG z?l_(la(+@fz~c}W|06*4!{6s!$w3_u0ppR+r~5|^-jLBskrwh<7}SYtEUSRO6jq)W zIUKkX=T(ua(Ivrhz|Lfq&xtsV^$;}T#5=XOSmGi%&fdq!dJpLW zZ97BjD=fQ_oI~q))J8xH63YGv8$6=6GhBFO0uI+_qS3Rs5tkbocC$OvM4P<6-Uu_x zS`Jc%X9B&Y{|QEWVwC}iCet=bnaBxZfYT$}_RnBX7s5G7r&NTuT`S#Ud{f#&7e;&{ ztIez@I(E0r`kB3VOz4-&qM6T3Rss0fnSBB0g&rm{o4*B{{&(<{y|Wc+R#{GbcJ}z! zy5u6<&S*RW{IWa(<9vmXqH_Q=w^A$8isUnfd}qtF={^Q~FcdHxnNr}kyKuprZ>cEJ zlCb~Hy)6N~1+a=NY2%2G%vluCG=!vvV`H|lNJ5aDz-MfNH;HTmAbt^o?YHj6B$2FX+u>FWZr z5e;cev5)m~6Dv%s?q@e->&aSzM=!|XdsP>0rT^AJzlkmO$ASCG3;dAc-eeC%YMM+i zU;@I#$^~=tqD%2c7v5h|WBFpfeK)7{4uHihR4j<`)q+;yW%X|k4>^8{f02brlX4jp z#oyz0;c2io$n`^O{PENSu`+=Q3djTdH)AWphEH1-#w$tL9@<;l5wcU;*r&F{rrG^w zUP6l8P#XKTq*tHjFE+jb{=?Qi6*(3Riq);Mz)~`=;~M#ij{W*o$4}>N@NvIxAk(ms~%6OwD++Lpj|C`C1s|pZP$d=Wp6MLOL2u zVE*O5BMJ$%IoH)K_Dxn;bba@$ovsjqaIz4WWyZL2rZcx{<&|C#UhL_=l`q~G&3K(t zJNK!=a&Q1zrr=TD(iklUs0&+~2nAp7iQh*sr#kHlw;!D&s3cqlFNHzqNyV)|ej z5ocGnkFUZ$NiO8cwQt1i#=vDF9897~KNvSOe)AOkBvd8fmn7`yhkTYF$>>}~q%f|s zrOc<@Q8HS*;#flF8!c+71+_PLMgn_{(Wc)kuRSj*SMRtOn;SDwZ{H0M{J{rl!h%#{ z2^}p|4ZUoUcsm0giQy|4H=#n_+3C$MTaHvSRdfe%>3OLOmfcEtwumtqtut(bo`@5d z-n%-{rt$9Z0sd_$4AVv#?m5s8WBGYIVm6_FWgRx+RAY+gL3!qw(_0bgu$)K=RxK0F zEr3KJ4OQ8>Wx9rL{RWU^RGBK-W8ll3k3ekj*PK=((>~??*O>Ri$o{YEBb<&v1{|&r z^hZ~Q38Cc)1(&qyM@yzV0qL44F0rs#1Fu3(p6pMP@JnWd=+>r_7j#Ii1e$y-gWPTC z)ggW86xCiPLYRBM!*XCcvZ;d9`B6+8R)%!^o;8c$24s%@5Dq%SGKgYs`8HR#K1c|WqY=qO#~!XO;V(GyZ;R&nJcC_BMM$YHT~h;bjF`(RL0DUsmU0j z)Qeg8d;F@l&%-lhev{;*I$O3qVbIN_8APdQhx6}z@l_t4^YbKy{C)(!KyXshPd=OvAd?y&hme2nR_RWKE}+%c}okb zuL=$Ku*QS}y|p^?<=;J!lMDi4jo3ge2EhYgG!PBo#k`z>aetRe(>Z>;5dS-d6PaO- zjN0hbWDp7OJ|lyl*4-QRdq=SfX8e$6nHc|apkJX+zB5-q0a@-5UNu(sm(?}b*hWEx z6+Lcsapi}E7r|?-8K5=fo4aBn`wTPHv=pV4r@zc40AR56hI{b*GE`^Y zO3O(|@C@2QHKKIfnDnPKa@$xzFyi&g?$+l_2WbEK=89=RN8Q~Uc<_NE-<-ULsAKAL`%4NZnc1cte?!Q+mi3Gqeo^3^ zHvXC1{!Ioq3WSW=Z37taqRmjsov^BV8)!H>cfv=a`9*|)Hl3yOGOc?mT2*1yLu~awcGPAdrrs?4Y=QTif5m5y~Wl|3FC&#I5?gF00%BH38;^yHO7Usax1=yLGoN;gCnrmx2!Wkn9y124645+bJ zfW3$Sg7?~uOhs^gM5A$zzFvB~qYktEE%fmgg}CP>?62QZzsV`qU3?eK$arpjLgME3 zCh^G_3Lo(~*3j*)gH6?~?Of-FQ8^Gp{H5Pky+VKkQUDfGQ9Ap`wGy67Oh*JU9 zp+RSGLnBZ2CO&8`x>m`k(jOyfJQpWM$xHS*(~0t}v09_gQ_6}lIwQfS0U8`)Ju`Kk z&6XfkbIm(sZhCkn@?(k}F=p%hA&4xCXw(8?xD?lakN+TzJf$dZ9*x!>5xz{Njs8mV z|I*1apA{xnH8Q1DcqRzhM+P5lTk7rVgZ_~pQJi>alUTprYGClOL{!1p za+?8sO-)H8q`dpn#E`?trUWQ^84N`DgBMm7 zOX;^34{?sB>p%)sH5E=D`3i{q!*FOA77J%$s4Vj?U|JFy*5VANyc!TpX(5aqLlKwL zt+nQnUe1g`)PGJj_jdjaHTPWuviG{kpLmIdRWD=Q7{WG323+NqJ$5ss`#+#KIw3k%5;m$YYn&OC)yCP~~ILv_G^l@PLB-j^#HKw6tER=cK7*FE#c+H$(QFMAXkxO4I|DVRN|5>t zvs4NGtzpl-EKb)5Fo}eTJp5#k9$xEmXD_paD(iU5Awg9^+OhjR{8gceXC9bS32ZWM zHb`pbSk4^UJeQG*zB_E_!f;`wJ0`4>bej3j6`&lJi_4ybc|A>Nn20KuAKyHAJ;v=7 zdkE%H?!{-kzbQ%Mq-LlaFEWgd-nKF;(W45~cmlt>w?aC4m>lWm0%m~tueH3Pv*Qn63_p+pJ165e?~zV^R1IEw<^f&ub!go70qc@fqB*)VuFx3;wj8OFX^CVaPuoX zfYc`L6B=xZ(X4ec{j=$iD=XL?2~~CR-RYWbebNDhE<$hd$zJQ}rz_FCQ;MR)8}>c&&R@bT=FR(v)3W>O-m*s(0xou_m`2M8t4vZb)b+SwP79zu0U| z*}WSR4bd92H&+mU*^XG}l7;lNzUc(#KUFxv?~T8jD{qZE(=JAu{F~$MUc8L)+9Vt{ z6tqgZg=hUCY5r9Tj`9u{@n@1&ozY{?F1G|<3stzu^xaDTjGx7$E-^N@b^Ka-kcop* zERWxWSe`wA*SovefrobO)o3sVl<27+Ku@a255M;4N4s?0J^L=d?ak&I2%N;9$vP;w5pr~Y*J z9809xpfsS1-25x$gS&G*JD9E`Z_cQw`ig{tH9U_ebk*p7%XLE6%V#p-M-S(cWQ`mg z_ky|?KWAK1g?CFyr;Eb#_oH;D9eSvcCLnGK?OKtgXn`^w=JHtL}BjD1|LUB4nz z87iS{N1O=rjN5o&a(xiV7Zzu-4dg`&?yvbH{{Jqk{RFbj{Qt6??Eir~|I2dF)&5I) zzSMr4S;Byc7N64a?H_1u0;%iUqmE2h?~Z*@vD35K`jZF?y>S zYA`GMk1xP6H5Yptb$po1R+v}(5wd)5t=dmp+R&xwVxgF8Aq|7};^SK|5$Xj0X6fwojg{?DoMTS;Bn!^l#X{m_MevMbV=gETybl#(O5G z_sjVtWd!Nj3#cO=Mlt5b^tGA5G^%+3RQKF(RyS?>(%#ba|$ot%|7XVL~1p|D&k9nf7vE|aF1b#@O5GcHO@dh?D*0bPg$UC9Z(~2lw0ax7 zZjeXJLFgE1L|6aS)RCqwc1}0Vh<_KLrrs!0yZYMJuFN$Fi}Z4_e^-2yDKl;~SVJrV zNFo_M6*nw=)ed3ZNW8q$7GKmOBm6S@6N*QwZ$gq+BphX~4`;~CPDf$9J(9u00K5|GMv#WY96^4|JnFQbPre| z>4H{6nhnKj{BcY*6_eM>{0bAfs4KpNHAM!MoN;?F&JSoFF;fxo51mbTSoV;kKNgqP zb=SUzv_$ssvGDk+M4dAi4cu1XC{yuQp(2R;nG+B(L6$B`9qKr=x3|Z+jGZRB%r9^I z3sH^?uKIp`+SD~Q4fglL7#Vp*%0A4lq!7hPxc8r)Y;_Ynfv!mJ4mDEcAFXiR^lU~b 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 |RSX%XBTa{N8b5osVE8v5 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
  • tA{IRn&#sw;z^)J~$jJAQ}) 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

    (wW`_E0XAlqWy)s`*byeD5FjBuUP7Z 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

    !6;(7lZy(`fes?(pu9MrWJhRZaE1pS{7 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%0D#-LmM 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

    `8|95ns1{pUv=;)1vIFJU#2NE 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 jUQ2ob4UnEB(fyzhdJECfx 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

    3|hg0oedWE z+-aCP1&TqIoDgX6mvkjlfmqKL76D!5XmLqnbJj>JT#7w9uGj*M$aB=&K1p$tYMy=3UB5x_PxEwIh0JdPp_giWqB z%b!yYi+WtgdQ0#uuzFulpa=G^Jwx$j^~=cds4Kk3fe3}ICQ4~(5h1sWZ@(S9ddugC zkMUlW5ktHVVPj>PO4jEG9-|Q8i>CPkj#e`=yIBYM7b%eAe@<+7CJDZzSj`l>E!#0x z?>vl2eD<0-;W&i{H04=n^(SqVSsY@zlCSZeq9s%OU8|E75v9*=uD?g{hO1V;j9oqbld zd1{C3bkfty>8b}1E83L#P5fe2^-qj-izNOBJ>k#hJN`EmY#1JqmtBtM&nqXnV#(A8 z6e^w6s@_$XY}e_{o#Q5gtL7JE!*P@Cb4t$lO@qghKs|`YGn~pOrp3qK)l&r3o2}Bz zf2iQKU5--FlQ+*^6S&lc6jk8-X4QmIR#X}z2JVHLZKg^piToSC*I`NaxJQ$p zZ-$8f{gCbZ4d8vh0lMniop^P}(GdsEG;yDStDa|u8hkktP^do0F}kT)42aj@wqN!! zepdwLxI9?d+P&Qun^egUC)uL<2-3#NTdH$P%2c$YBqesJqj4sEtkYM9SbYGW5NUq* z6y2}lAn8q<#w7#x92&jt2n?aj4=11Z-|6SF_cd|{+xs;>v6E#NNZm5| zS9cM{Nq0kjsWmEemLDN>d)U_{Ems%;q}nQ5z7n2qSh8J?6CP+J6+kd5IAvH8u3bhK_`V1zg!~u<6zp^I}*#YoA%aHh0EZ+pl>MZAU~tL+KUF zEH_q-4VV)d;#Ab;@55xe&i@}6P%*4?+e4*GFvQ^krr;FE`$N)B50W%(=+9}4@piZ1 z9G&ySE>%>WFRih$dQKGsGWF$g31wQ2>ZLg#%k-ao%#!I4F;lU)cc^GNQeN_e%*hOD zx@{RnF<$ps2oQdId|=`sGRAAVSw**~r6xyqGpP+M_;s41;@d_Ksi5!Xi zXJ6}%?D@2OF7bUm@ZD}lx7pHSY^VP>U-eh~8?636D5(P6#+S?;0>ieF^x`S@YL$n% zd%NT!Hd>#sUNW005z}!>Ub1LI9{&-h$JxgWUHcb%!PE>PnU_3NBT>ZsW0C6q;yrU7n8SAWTgBdH>0-9u{%j=8WRS7g)tcATg|7n6 z`#N|gCbenp>D(GPkl1O94MdR0aY^FeW^}g>s3S0dUB&>_&rZ%n++ib3RBP*n&32h- zJxXT)&3v&FU9%O+gh%)-0BU@cn2k1^itl+}RB5yIC^(hiqOiL-xq1p1e5@}AO~%v~ z8d|Az>ySVl-h^TTlJ#CFiC6A_pgz#FFsY`@MlUP8VV(WwihUPGf|vxDRka>Ix{fBL z6bju1#$vOC+nDuY6wvIJ#(O7rGTRZ%y*wuK3-xIo^Yn2DB|cfyUXmNyPovUHBlRdP zT53nTuVHT5%@G}c5>$mfig|Bl|F1j+D|ZsTru67E93|gIpd!e%5@Exp_QH0z+%HqU zC{$WFDf^SY+b|YQYMBVqVxpM93$i^>R

      -Y8f1@U~s{we)mz8#804rOCkgaBA*^ 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%0DPXSzTSF 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

      Hmy3NnrcmU19zTjuVT2HK82L{)Gy0bq}yf&Mhop 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 z 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

      euKx&Iv4>n!bB&2I0L7;u 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 CnAE0)IzDC8@p=wK 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

      Hn_-eQ9fR)(||ClMeF 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

      WfjGhtF;<8lv=rKJG-8FyDEM6v*f*jsU)Y+t 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 |DB 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 YhTBgGRPARDDcCmb(3 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

      V18U-^$jJ~ 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 z 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

        +Jlzc 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Ψ?FrDLQ8s=v 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

        Egl}GCBt$Er5Vj|0_=8MmG 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%0A^4C<{He+{}O zqR%_Ha)e_N=j^q6kiYE~(sAMmYkG!vRak151!q|4ulpjFr?lN@aB-Du>er=idKP(k zyZGJX@b2fuS-r4?$EdpP)YZt1Y-*NlM*es@CAe#(Z2c>8q{YX26y*vZ^$>PH-4PLrIZEvT|ci#~V+MrKXqvI8Gg|2XH@af^{D~ zqJytBI5V{4@ZLJWgMv&ur`?;;yNvg&Ov5N5RBeAmab!v>iYRoOmU!yB+xIF!Y0>oz$#XnA{B=buIE_%z<{SAiD^OXs70Y-hzlmcgKnN)yvj^m3G+y=@)Fnaz(^u}ydNYqoH@+uccYcy0LuvCcD1R~yq4Qu#^|lK?&o^a27*IIsh{;XGLKqyDaE|*(jv)Crd~ogi`~Op| z(*2KGr6bT<_08iINZ`9lLj5(+UG??qB zkkIeyjZ%caSXt+6MJj{KXx!ehU|@3pNOs$1$#q+|YIoCTA()zdS%R+)uH6ATebPsv zVn(oQkCI$*R269@T{sPr=HOfw#m3E#PO97`Y$qWsM$blY9(ESuH=Zjc_6po^o8Cs4 z;^|e;f^l;B15K|&eHFGo+Q)Z8MU2}hY1i2Hv&TzZp> zt`AsPQ4Su)jlHF3DrM@RQWUN}sFO#`E8vuCW^@Bv&mry;XA|SbMu5BADi>Ld^<@-N zNwY5(u}+@;D^gP>JnoRnPA{Ezccb?~O{+QGYeA+2Uc zdF!WL%*M#6z3~++{pX12!FM|-)F9vDml2)Ihh;^>JLtiUX=ubvRAyO^NX_Q2Cp*AzDTj_dg?I(|^XHs@lQ-RptKYneay%THdehd?uUC5q2aDmk-_!U$SXV{m8du~dNu*fA zTl_@quR`jyQ5qV2@5Qm+(&c_hEY39#Y7<75aqMHpR&Nf0rwCnBLLG#WF-Kha|kG-h5Q0to{~ zgP9S$FjkYICq}SXM{h=K#&=f6(fScAyQ1|^qJQ{;s}jR8Tj+*P&!a|kW;KuW(K?vP zrgkMjT(DNJg@B&Xn8z4`QxIjTOt+M2Id&4mn*zn9k$EDu`Q&ykARun&-Zbep#gSjz zv+29J1X_k*%t1k;58X?nvsAgr6HVaDs-v-5$G*DOw_nBPqC<>F@?$a*4QHA_Z^V~- zu5~A3$Rdw7)3i&8gP&1W9^vQFmQ^{ry@fMsNgWPhQS#sKJCR8d{@>PZV5t<5AQl5-x;rMxFtXeWT^`ncVU} z3ZhFU*J2s@MIBoBwRCzuI_+nI+%)vKTYWplf4tJJCi*O2u8Z9Fh@w~*w#-T_0Smd0 zV@8J*JHJmx?b|V}p%Q*5X9!`*L(U67nDwD(8x;nF2JFRC%#7U?MvNxfe9QS?rUT{V zV0yz0+LrXsSLW!a#JINy?_1lB;y$X_pM)2brt)mmO-5YN2TJuw0NR%fe-06r19Pn4 zB73_6&NpvJCJ&D!O3X=zYL85ZHF!XRAgRD;ARFiRhS!G&chkc3{Di0BP6he93e>}l zW~9#(58(|Jx6{A3zyQ9V)pjI3FrdG9gaU0`0!}_nDIm4n6u%$w!g6)PigV=f-{jBljGMr<3~@l#|dF$B4<&jsw>uH4eg3 z@G!bRybu?K-}rH0>swMeg$8N0c-U0kJWsa*qu`B8&E_Sxyb%}8Q?YRkJ>0$*0T1|2 zwOzDiDeXjTkU>qE;IU)Iv0ZyrVs4=SF}0>h%_Qbe7O@Qh#xhT<5uoL}<;3?U)FhcF zHs$x(*!Z1q6~b!u?w))=cuqHi&Z6fL1f{{qrF$US$QLx-{~f{B*|aF+#dDF_o7&o? zBl__Esk-mf*)&Rii1m4BFLewlz;SH=KZU-^HzC-G&% z7L(sn37n6oXvhZWz0v#%g>zs&pLojAw{FV@iy1je9NXcTI4<&j2ByXU9{ zA#x`y3{@VvIN{P!u+2udP-)S@qXPy_2S_jUw%L%y(?BJKai5$$E?c1N4@-|x* zjW2T{W$y<1`jMJyvX_lu@AJ@G2t}Y(%7x41iRQ%`=oj`bTQEDILSd|M@9miW&H^p0 zbdN;$7O}Bk0Zwwz@uKVXrE_P5bK$Y70;+h~5>>8K_)uA(gl|G4w#Par$x@qVy$(TR z7?Q4M$-p_h{kIm$4DpDC^LrGQzJsB&ZA|UWKVaCXNMkkEkUIV0{Lv$qS}>q*h%?Y` zltQaWWkLm?1Z(8lKe&jDsl|FO>x@NB-hBd;IRNJmK$!!b&i95Duitw24gwLZW^=%C z=0zmtC)9+AYwMPgc-X}dmbi_XWjr&kwHT9^NA&7_{rVpq;w3lu1m>JLti35+!tYJ) zXLX(K=7uoG1~x6>>sR%yu6bz`jj)ev97ta;nuhqlT0nxWW3VT_5T$6x9{f3)r|jYN z22HQNl>M6u{^{X^fIa-%Oj2g<>!Qi!;)IfZmw)SWUtzyn-4w1D-InV*p<94i@HE>- zLGvlYQ=OFCv#``bA*;pMfZJ<(t#KG;vXtXGe$+KQ`@p=@Z~u3^)2Yppoz}?DT($~V z0%DIe{u|ZpYB$Ph7yHmdZZj{J{<_Nu@ZL&UrafEm)yGpX>o6c($VzkC6cC#%kh+wG znAv}#&Xzn|#?IBxqNOsqA}Gf>hDtYYx$|4wN>o;@7D{i4t|8UZh|~W`6*d0L%;Cvc z;ABPQUOjlbp7&x%CnwognbtY&n*s=ILw=}EK&p*0EH*5ISvmMinj4=f3_ z0jMgAZ1F|v(gkw_7&CpRJ$o${>F$Od!44&X&x7u@W0v4kpC~k4)D&l@(#3pq*RS3A z3Je_iFY3tFn0h462m>eAawM+7d)D740gAH_=_w5YqkE%aN)BTS<8DK!9{RXrfNWo9fc@Amfb?~n)>Tx<#5O@o?i&pIh!d-&)H9r2=&djYWr z@zrw|B%~G8w}lIs`*=UWu?)UEbNYpLv!qR}wkFJk7`Z#_gUI0qH{-fT!%bONn&D{R zGGVapYC|z7B3uDC4hRl|d3BKDe(a;QQAy2xh%kMKQ)#kA=m+z@KTkPJgxnb8l~Kzi zZ+}NG@$4&YT#;1iRqB%AAnIwt<(b7E_xyVk!m4c!ZQwG(!eM*8bGOs&P1Y2h!Cg;;`*FG9Hw zZ;O8sh)25-rG7PH-P;%Cg6Hbtkv z1vvI*C7rdwIWtCVEbP3-&J6!5gkongxYS^#qfDXw+l7j7d(+BpWQ5?lEjQaQp!UI~ zEFi#x8=Ml=*$(PY`4%bww<>T_Mi*n>j>6J!jq&`LRa-_q5x+LBNgZo=CVGNo0WjUe zxETnas5x$puRss;cie(m009Ssnis2bvhes2jOB7cah7kWB8#(F;B%RgqsKCgd@|b~ zE4@{}8uza|UCPLke2Z4zo=pa!QZ>5OCh}Al8u{hy5MXr9-K{zMD%`qsnj9$;XJV&Q zx8jEB%bfoCCU{Qop!J3(TaR~gP7Co5md?1sI58gQInkijk6A5$j>Ew`&cN1`r`Fq= zl&kX2W2OkxwMim`N)>&j4C$FAOlo(I388+DiYGh@mcev&FuRn9?jDGL)%E8mAPfFK zw2J&+PrI%r2IjnY0o}k*z`&OPbw3|pASpFs{QA6_|8x5cwyNrNSyL@Vpm1@mJf>k{ z!r$NjlQiKZ(1Mhdi3etJ@%3t8P}qXT&Es^>@*69wf=(r3{lWfmGcP~91v?hDzXP$< z^<(6x9>w%xvh>-))t~W7A~O!ZrJax)?at^1A!tjh?IG2GHvCna8MV}jX4kfs#q-hM zXE3TZa=Sw5f_bL;-y|q;@;DL?}>E^u}1*%VopSfi~x2y>RjSG#xdBXc5a4w*^!}LX%rg<6P8#_5fTn(Y&yl32^LqdSQsbyL9dwq z(_hIXGVBjB1qCEl8JrO54~irsLppJo@y=0`j%QpL>1-e$q&2d`bqB<2ra67a#MVLR zUXJd;k(!=(`Fz~hMYKH;V(yRL94|*WST1lTGd(e(tLUlAG33DCYt>j)*Oh=63N7#uzj8I@te;{}`n=5!w6=EN=)t|=%22{6sXm7nU%9;TDHKuz%iWrJYihGrH{zJ&<(I2~nPjjd?6nQ{*VZ z;??r*Th~_xO>N1~K zGLi}6)CH%~(FgXX{bWV`+%Cs`>Y!sYRg1=GY!osFZ$cWIWB#Q!{YDzTIwUyi`+;VB zGx!b#2yMf#Z;VhzD`8&9QjJeDV{MrnS^+m-d*aZ@T^1jJV~C9eGqeaZpW{2?n^nL{RZ z#qnC&J#C*ltkx7xsOYu?6t<}|=~lkiM`)dJ@>Ji3i0i=e@6GYsP*`&at2~e}(p+!W z>`%7_lf22l3vicP=)c*9eG(+(X{nd^Xa=$~&SFmqin*-NPDYbmufL$?$D_QE{3u3j zaNaU3+(xD(7#)b+&BBndgq(tW|5KulABlch!oLoFZJ1 zyzEmM)VgsAD0%JohQUc}0Jkxl$)3^x&a^x%?UXyyHa0!viaqlVpn_>GZ>+0=>o0D$ zJEH^J3%IaYBM$EB`Q!x$Cr+ttaEqCdKe^A0)?aLUwgI<`USU2}i7YT3hKCPEvtMe& zOEz#b2FNmh^C~Oe$kL6KsUrZntZ$$(T_3Ph)f-0a&NMR_}=lg0`l!J^i(&7S`EUC#{~%tU~P%%JpkFKO2p#Ov_G~Pkb5n zS0@bGtooo|y`avXg5xdt!Uxm|7E)MS-GH<5>~3^`GClaJi-Ud^C)9f}lWm*KTcxce z2YYHVL&Ss;rManJG)G3vYPu1vpn%g?Xw1ufO<7dMuKbU@Kjd zQ3}dnh3}PruLOZNou%KVRU1si^H>x!17{1<8A^W}8)B2S-9V4Tq}3C6U79=F@iapR z)EGSQHg>-wr~nPZ){FvIcBY+eHM>tlbG%VSb)|KN!{tFr+?F>EAauciRHrskUuh#| zt?MLppSt3mdtj>r%}I^!M`>>y)Ym9_5}=4M=qpY+H-WmoFPtr28-U6|G(PhsQ=Y=c~jRL zxEyIV#HXW^m>L=stfwCc&+Zi)Qy3o<8~s6I#~uhPRll-UG=P?@DS1LOtv0lPfO}-l zEIC3$OMqVpVqOPcHvgROR4-`ZY>xQK=A$0Xw95roQcQL%>%qX;c8tA7QyRPvWQ8k8 z0_Ot31Q7ry)rM;Ku@y>t;W6**|xh%UEu_03cD_pHI}yE%!g9rAd=F| zq%U7TG!{@V<$@KjUb(A~$5u`$O&Vd}m#2Xo;sRQV{ka|nAYwp&4D{^E%|a@MOn> zxPbN-eD-EmH$Hu7>1j&!>W!gUB6Qk{hUHSS+=SepfhsJJt750NI>p`));wbi(O6O7dkiWNHs*}@XeSShJ0YGLacjP-4|R!(BZy`gT3k=^6l4Xjz&Pm? z@k#lPhGi)8VL$YmJis*JN1N1F!$9F+`@Z_|Qr@=S=!b6ll1(@9M>pz`{X>RBXu=&8 zr{$y@dFY0y8u*Qi1}U{6mCm2Wj+#jLjZ8WWI($h<`Y@Pjom1DZ`a7PR3Pd*=>7^16 zj&?h4;FSeV(&-9%j*ehhUc$LCFDy#lsx#XoI2;OdFk!btZAoa6BqouuNVLF}s7m(UNJX8922dy(wWM%_ zVAL3X@yNL;Ge-k_&jJ|%<8nOXAGKSxQO7!C-tEG9g9tw1Dk3qR+0L9=ykzUY2rHBL(WXa(#i!y zwi3p)t8or*MNvL%Jk^m2C)92rpVvNts>+9E24x49h!Av(Q;ZVBrju_YW5Ubl43wjC zw-N3-8(Mwi30I}`BRkrG+%d+uwUNsspN-k)(5V9rR}@CAB`u#V39Own4Xf6a+!Tq7 zDVj(-#@AzcY7g%Cn5{cbXRgS5@GP_+ga2qW}XNue-^6OaG=^Aa?uYban*xg$&G^&S7T<-kE1H zd3^@F(ni8SU0>$(z!mQxMJiRnlRfp&RI_72Z-DufTe5du=0-*`Qqj4%fU4-h03AbC zbxFmOEyOC^aH6dkdRs_mc?TC(VUHnMLRtXoI=$EA$)x@%T{9{+`UIwAa$$$7_vP;s zmccS9F3-HM2#DbOwP56CT7MnSK4^C3&-eF^C16pWq0N-6`7I>EUP_sklWn3|AVkkD zR;-Y#WTBWVLYZ`;H(vr3C%eyb#}*=eq~}1hl!*}m$bam2*tP?&RTWEppJ4s~^KV*F zO{FnwsmMe<;%(8i8BDa~Dt{cRGs__ClA<0(?1Y-~$H7)g!V8iKu_}XvyfvSw-1Xf^ z-I2?nOh&Htx|hUiH@v8gmx#4sA1-=D1`O#Ed%Fh}&uYsZO*l03;#DqLa1{Q$Ie}qa z|5csGnA27s^Kz&ph{%IqD;a4rhAF**bQS=n-@9hNY@Zu)vnWiE)gp6Q37I|dO00JS zZO{&ci`7JvSQVReByHxgY(3Yk;S4E`54YbMb+(%~vr}c|;5xF4k3%?uLn>}o(Zo-W z!bBN420RS9|GiiJs`~F;KF?n(?Ni$=RsDaTz9ylgGD+jWKuAzUNuWU^^Cg(6V{s%4 zpm}ZirlvMGJgO=^wzL`Nt2%kxo6PuchgI=Rlz>~+_A^P5!-V{Xxt-*$L=sTQq>|aP z|Ewrx>7m2Y)xJIQKV^H$iRgX)`v>@cKJFz1jI>{D+66Q>a*y=ULf0;w9ex^l_Cj0VF2jeqsYnvDCHCNjoDUrKU zbf!tW2d9?!^zL*LXNLa%K0v`VqUwvPrdPQ?hg%4Ne(uZ;I`1M&#b7d8HapHeK61pw>O9<0wq<0}qO|5$|@5z}XI@ zzJ|MBXyN+=zNsl*&$C%kLKA1QiXOHHhK9{oVlpSAlGc+S$d%Q;xSsJ;YbRc$pHBQx zHR|JA#lyNujc*Wk2;%8)W8pc&uyu^U zLj5~jGCPv<&BJLp4Mv!eK;M)g5?Oggj zE9Rd!v81&Hn-#y~XcP6WwwD%YPT^lfuekprW{(}LX!Gmp5j2~lc>-l=l^pMXWqt%E)Jw$e0& zfmD}Zog*Ka5r3jvFJi@72)JGC6joOZvwcZ1Q$NPAs&IW}2gC{Q#@ay=p*n;lW?0|7^uB-D zG-DtxxUO^3KlM!aDyfm$vN7EGGzY{@n(T6<3`<85-wz`T=kN)u<|8Wl`B>t34rN5n z>lK>VMS_^aMGexml>{hQ=2Ov6?4O{<;YmMuVre_}UXf2HOAJbr^WAvywBm4E6sJ{p zNz7@b{IS+EC2K+22uq>%qDctsiM?JH!q;ydQabt;D3UQg_C7;?LB_`(Z^!NiQsqBJ z$N3(-=360zYpRcWrvwFWyI%ZiNSSa(D~cB?njJ6fSRLF$z-}*Tp2?LmzA{S{P85B}Q}qt_;dmCN+qrsw)gZgv|refh~y z82=l|PtQK;+aRtLP<32p*Tvh*_RbDnawC}x>BSqCY+vpi?;j5D%~#49_%eFFS%+Ha zUejm!x}Ag**>`x1D--e#iDWNdJ7CseOANEOVh~HCm;lE?5_+Hb^}P`8TEX-LXqW~) zj~wT7BS=BFpwV!bDqAwknEjx0>tQ$m1&JK`v=|K*9AEroxL9!m9f9`QFM87 zCen1;h63fZCZ->VD-UGf%QQ#mMFe!ypxhtl<$P35#Z%WI;8;BFbS(5*h5MQj8mvJB zxenV}UNaarKQ4Io;>nbJ-9jA&$BLFkdLKKA$83JE_`ttio7gx{UT2J`yz<4w<)pnb zO+Q{QxUkY~4sv@Wm2-N!6{*UH6oeM;e!O3Mag-=E#%#q*h#kMi7V}QLmx;-?{z1yg z4CHe)#bmr%KqbitjH1xoY@L9*x}STj1huAAD9Jfm0lVqQ-04+Y1qCBibgc~g(jYGI z;E%c9fNHrOw_!l@*n3+RaK?PyG|H_@*89cPQkNM)R}?u%8UH*|`+b+)LE9?E$2+MS zwjqmXyEP}lmn_rUAIUarfJbFY;){y3m?$|Q;(7~RTns)|~~VD#+(rjFfXI+fjx%FwRa<)qL&SZGG7Hb^@M)zjx%@m_ay1O(6JH zsoGSwmG`QNZ_6oMUjMDSV-HU-ZU7d_D|E&xpfaO&Y{~sAiN~g4O+%iB;^N>A&zmQU z4>9zm7X;IwHTdly=emd2wPnM=q`x5bZy=+>>$v@63DxjSz*LHl-d}+qUkh3)T?-Os zPvF_@9p6{G6M7bi($9n{!w&`v@#I%qk3wtr4ZPDBD7&9&Nf0L|NT_=V1(IY;f{6V5)63s0D=&{%Ps@0- z4|jGD>P*b~dIDo(zh!3=B?W9;epbACJmth8yT-z=4<(Il2zJ|`e|*A+YTiN&AiXIUHdVp%=y@J5jn=`l@UhjP`) zc-_AV$evO_e$vAPr_+_DmDp)Sd3_ZnmX{Gq#Sbnh`=a z(@IX|Zu`_0P+qn-Xhjr=YzEEf9lZzfBU4skht&68la?v$!3W>@YW+~|g-xW&twTD8 z?CG4iZg;-F{qK>M!08w83c&*EvUdQ*(X5Jc9S40iv%}jZzd9Z-`EB4|4dhqFckY1e z(VS3DEUu3f|Bm^4Hw7H5RV!+3_Sy~!1D<$)s(&VAG9nzlSkZ4H?x`2g@GR1P(NdKK`=%z z>o!G`9-y5E=0+_IIy;GGi|aj-Mx%pY%b-2;r^CvzRxBA@bc`M#GTa&TvB@T@6k^LO zKhI0!(L$3AVeX=9{biaQu(9b_9elf@W44MQy=)c9e69z5e4)7p+2^u@T75lsyRuH# zW%R`Y@J>a;GAb%;OZroaN}2Yo4~l8gUv)1`Lj6J*bY3CL;_CgA@>t6#B?+E0)T5nj z-(>NX=D()q-aIiXs|MW^dBjyG7?FckCV968E~b7~wliDKuFa@tu)_3-d$^-nskZIklcjLIp%n?hSO}z5U== z!GYkh!txX}*j=?$S#oi7B+dTw`;IIrYkQu6FgsEyH{PlpYLdC>mA2*11w9GgQs%@J z+2I`R#q2Q-bw3(}TAZO?^9i?#^P?8j`f_5uj`{EKLdDWORA~`CY|#67i?On?O2r#Z&QWPX9{8 zH8+0F&!YGkfvl1tJn6rAeTiM~WCLje{gT9f=ynf=*cE%Xxab|O*8U9AEdFoucKace z)MNAY%Fw!8ej4Y>2TmQXaT!amEnF35RCbJUA=!s2D>k~LD)GlpA&3p|o6oL{;;#2m@wl2Y>VN(?kM%#D>9CWnTfPQ4sMgt4-QepafH;nRPkm1ap^{Ei z*f#jtr;}=(dteA}>-Fq+`bQyA1B%M~go_gKXKcQmU_s0y-`O%chE3R?okOklvaYdqR%o~&LD|_&qmCBN*m_?4QZm+>8L>WI*XQFbAD*sXxff(* z_h#-MdZ2=n4m%|{K?^*uf`7Ijp2S+&_hU#+2nVJJkM5PB3(I?K-#+=2Cub{{N-F^e z&3k!H&p8x)UtC8K0d4}~5lhXQxZMoXF7bXxK5{!ZObE}t(Ul;oR~>S97dT~V!Y!D0 zbpGU&)N4iiHG%*_??fZ?WPu)qFY4-U{z=OTWErR=g?DWN!B<6|7Xh3^zgyg+M_2d; z4G`49RtlcYSNf=w40BBcWA-z;8?#AAqN$uZKkK*pG0;OfE29S$ulb203n-CzG?EyC z!(mozJZQasvpo*hrLyOCPE+?U8?3TS6uGbbL`?bbAFw4`OftV=r&g zoFtX7wc&~Rc(UdOX5Mp$bC^1X-*4&vr4;M^y8T}**yEAB;}}TaHaBC_VI(DyFpm(b zsR>mvIXKp@%Bx&L7AYuu^zDY`!o!IKxA4uCsn&ZM4@|Id19@H76`SLb)wRHUeO>3_ z|DL=rP2I_pPd70uPCk2nNvvgw*l0OFGD$y_$E7(yaW#_cxOw6LZO?J8fP7a6X(Q=NXw zpEaDUp)C@Eg)UIDNuE?{ZE3i;#bxG6#cy3)`QgKSN`J!~HPC*WUxT1&6>xO>n&uqMrC8K4zHA!BUAV$g5eD>Db3iB6ByD8ph{vO~#o$Dk0?& z!6`&FjDldD$bPF*FC$-O(fEkrvcC!Aj*5{s~8LXH**r-d|8S!P}pbh0l#+F{pYJe7t5;_2&oW zg36NY?9sJ&dbYfqDMgqMPCT1fz&%IBBmCu)Gt1(1f2Sns)5l%xVHU~PUtI+8k>NXt zlRlns>ndE&FVFji#oL?Qcn>WClpHpgd}q8-7;-*x^f2A1D-X=gg6^W`rermX25lYc zUe5a8gqcxCMPPZ)d@v2Nzy5Bwvo$>2J@qlGjOCDVljaC+9rcCHi&K+gUe=7mM363( zz8v7r>$VR0iG!5YfAMNeB`S1)-LlIy%);AE)~>5dek5s@;Se%WLH~$LlNa^i3G1Rk zX@mrQK#)mhr)W=41C$!s^-6SeV0tc6!^9BmTU8~4Zh+p#jYa;_J&?M?`-K}e?tVo< z%<((k7+!M64)Fhh<-ZX}htc>n2$z&Aq zDx<36gQTD}Dgqw$jVJ*%8JocWVec!W;>wnVlR#jCCc%OyxI=J-+i6pVMcp-F2#J*RHBvwNF*- zqcY64_eFHla;o~byTK3a@Vh;Xa|`22l1{lZMTz_`-O=V^A6S*USuU=rS|wVfN2-j; zN=<2nLqE0$pc=x+{nY(!I!ld-eONgbb?9lp=1B0e=&i#+z^7m9N(GbGdV3xntFt}6 z)U~ZyLk3r_?u`&_-|@%?-BU!Eu+UHFyyyLV?LbWS@r5BoY%!oQ=W^N5e3nppJ&Zf| zPFlS9v7IQXMdKEWmh zm`=A-@Uu4`1CD7RQ(fy5H^$4lg9V&t(r#D^SJH`$vLN30qgq6$gC-I;R9WC#JE5}T zj>-vGXaJmJH`*U!eBE{!g$E()her=j21z#1fnSE7OJ5)1>EH@x#0C>$t<+%0PW!H9L_JUX_S9 zksRjGL^we5T@1G|pjFZOBg>KzFhN^hREtYij{RwN%v~%_ZjULh0 zx4lY@({42|Do^Yn4}Ze-wBRWB2vo4hi3oge(EST}pjN^__E&4D+s>90 z5EBxKA=-)1x)mMcciG?`an^Fby%7tqG8Rm#KL)7Ka=iWZEZODLx!+lnXMmxFV6)85 zE=5t3Rqk5KbB|q2u()q>sI0l%*+(vlK|Ra?97H40q)~NYt7qH`X~FV?_cRmg@@J`_ zBEI#~W;3p8uJO4cT@CWfZF;3J;(T_|-sM0c3OrB(d;>j_^qcI;RC5{fR*~0hHe=2= ze3j(>)2C1~LVu}w9pb&=?w4`rkLNkGHO@~S9cthiiV*xJs{TRF;Yo-(u1M&UNUVuf z)<&AZW9B$G{C|Xyjzl;Y|hL82urPE2lsTA(lDKe3iiIO6-S@S%0Af^Nk;=)c`A)JOQP|F35d%uq-6FHuMK1EIe|;QzeRbr{kV_S8FDxzKfh zx}b0=q-j!f5d7H0#JfnDCM1REOIgUam3M%0zKiVQ#X-oA55M4fQLmW02Fuv9YHEK! zYq;&wtNJ_@L=|{jGIjgA(4%;+j%?=bDyL zR7R^Za_7aVtXtQlL7d2xYZfF5C1&y0vO~=q!E>i_KS(o`_m;U&xeI60_LQ@Y;o`X# zL^z?9i&dp9)j6rT^!hT>bEwaQ{CwYlSjXjZ2HEWeo44OCSh5LAeZ4J7)YetFhXe7p z!w4$U-e6Kl&FEI#K^H44VZi`+5%V!)5pmw?O4^m{oBb0>^6jUuZhvho!S_At#agy+ z)ZmowOF756wl>)`v_;26zEOK1Y98st>whyHL1tU#SX}HMQnKdB545{%Vb!!L;@C{} z%rJ$RXF*rO}zU044(M$DHvd0YDV5xZ>9hFW5cMXP_<`Ow4n!%U2OS345+9tlgG zao79a$0oUu0MRikqg>QE8WSE}ggEucud0-H?jF7p>zXCGB%p2;T+;#mrG9f~O0ig6 zO>gD#u6$UhUaU;vYe~*`^n9yzf2t^umsIhu)p^bZ{8Oqh9pN zDa7aEY!xSbw~h(v%Wvp83epP3c(nt$4E&r~qR=<%GA3pX>lhEJ)mz9uw5u(u^#PKk ztGP9o0BXwPd)yuWoXisAdx)fHGm*6%gk!sA=uR-}gvoOAQ^eci>-_k#tKj>{sCbOs zsUxYtwFkN*%m}8)5c4YR9Gvc`tsv~^4o?q$ezggn-tJUJ{9zUkefl6jRe4;&Lk50+ zQ(O7)MS;Z6mG6_H>X?`E-k0YkbImaP9MM(^Shf_j(J-ID z{ElEdM2XR?uq!VtQ(Va_INLu+Zn8djG_g1T;5>}Cioj*PPU)={f;qJLNL6hKaFhy~ zTg_p+KJ208%8~L12?bAr*v_9{O89`{@4KRt@%?IBk4k?a51`D<7bQOk)+ga%KP}UN zRW+HBaTqN7ZM)fNZqP3SG+NJhm}N`rUVA#2H3{n(rkc4teVMJMI1P!vE zvZ!6NKch=n(l!C}e)j7MN>fHcBnpOXWdef4+Opus!Ls+Ay>|o1+-#*O@y>zKWlQ9R$%KJ-Mm({3 z8UBOB@q&AZ`z{#=-N({B?*$^GCiZkD>yCXaff}PN?HQWbX~NWXz)SB{(p)y>Etgk7 zUxbhJpxKiNu992FhH2ihc_AsO2bO3rA#Q5wB9^}1z`ox+eW|jP!^c^PWPPaGE>hI9 zDSPfe;JzT+ZMt6jVMbwAy{iGA(sr$?izu_=q9AL%yEbO^wr+`vpUOfUgytk z4%c(RAPD*OE1KMO58F2nwI3kWpOsC2JBJ&zBUY*rJ;g$Bf2)MM^{2U4^&1Dz5(%(( zy8hu=O<$s#|90p}2O@DQ-b6BS^GM?EO)=AjOII>|ecfkkENN~GoY)38&|@hB-^|@! z*48k^)hSWm(S7a?yH!Z%is!2zGf*)Ir1eBb<2d+oTd3vFFdrja@{?b=%qvwof^`iw z@}Dh91B2dX_`3^!70DJPx>BUXpV@uU%8BG53Py17jd)QNK12o%&VDo*^qF09we%2BcZ zXC{`iE{58*H1H6bPbUzALe30B#;hu5;lU%U*?70amf`skEu+v?8mDUm)5n~Tm-B)b z<@ z%&HT^Qpub&z0`#qN*!gMu+Zm+2sh}HzDz@F1IL)zK5J79rQ@PhR-zKRy#S>V55k$~ zLs)j3^`1+*QL_b}1^C3y+*jv{7-1QlLcT zTx(!Xt4Qo*Ts7Ar5x7J2ytRFsiIYw3I;H;QiO5RYdb8Pj;7wUyD9G%N1{n z&ddIdu19K3yr=3#Hoow;8QtEh%*S>zY-jAkV>dpl)H@**tS{S$!r~?B#wZ6}UmvnZ zBs#G@&T!a#_(Z8NxZN-74d*MhSiX?vEFy0CI7mc&R`D8?RoXTj%gUaUV+-eqP?_<5UwxgNCS^c=cF`&^ zF)%>+@s@-2B2VG7LT zk%|+>kxcm%Gm@FbDp-%WB_GR+Ns=9TXV?=5Y3jaNVqsXw`qHkU0{J0~B*(Jiue3>i zoo2)3)OvgzZ6?Az>@O04*@vqeSCYnzR}El^JL-Iu!xc$UcCCa+5E zyuru^MYLu})=oPAc-I?iS4b3qSvra$dOV7Q3uEOB?Zf85hN>;cwVA?8QTjZiXxWLI ztQ+R-al0mclftr&2>k7hU4)3#`)On2!ShYIr0v?vg=ytwr_sX0yi`y+ywb}^M0I_p+AGY0IU#j%%<;W{dKgLV8 zte2R`T6}$OZB_=A2u4dE;GO@laL&Twgzr-C^@%i;&`9Bp2;lzXVqtNzbWPIPYM{1$ z`Sn+=k;bhhANVkAxRx@T{g?0iYHC&`k7YO~mU+JKZ>aHt6(Sch`XIi>$@Jn_vMrBz zzV@Gfpl7c!F4`IuylfC+%JYeA*tkBx3sb_ip&~kQus0<$J#-?%_0Ig_lv`M5pNdO@ zKhP0Ik#JpNK4JYlPoqDi&f@~+10wqT9ceS4@D;t^te@pb)w?3XzWJ8ac=5;HR!{iS zV=L^|gx8{O+$ZwC(VBX`Fw#I11`$K58PzDS9}7Kwyy^G;d#_aj#IlE9ZNLi3Zs%-N zShp{ZTk-fz&OJefNaNH2ylM(;^R$yi|Lbo*D5?!gfXWMM>V$--kWVO z1uCH-m6{hJ!f&M)*2ur@4=H1DE-7)($?Vj^!6U)ycv&&^+vL^Bow`O=bFivobBK znxZomXRfd8II9%j*|-C~!VY){k1pu-o|;7+?r&2F_NSLu!A_kQ%Jw}><3{KY=NRYw zfs7}1zdRK;*_-+JR_XG{4KecAX_2e0GXBlsoaj*QD2-ZSH=63&BZt|U2t9bU)tB0k zg(=E2HsKu;P@QedQQ;CE3sQ4!*O$@N)hckbmkt`k(h|Hi&B;PS@7#60kGCgx$RX3ESs zZ|nE&@T4+NRk9T-3c)-%@bI@31)o%Qj{L3*LJ1Wnff6ZjjLzd zg;rp>9Ol*cvVNYfK!wWUXriy^>0qR(|LU=U2`|;tc|Y;{gqvXI()yK;JV&pM>H7wi zvA+pB)sHO=H}s6+Ni0Phi7RY=L?7toGmBb_QnB$x zVjOmOZ4<=3blH{#l3>;^U?=gKNT{blVjSC3V{;8A7h3^ZGj!+nA!qUviHA&^-QyeC zoXV?UK@mR<_R+X_W@rEIEPVA>$4s;WVqtmkanOtE`=~HeQYCM_J+{)$_Sm6RUps#o z*AP&U7k_{WM2kYH7lqO%ZiUOXf%Ls9A3+&xuBTaOyuq5ir6dtMddJcxy5DnQc|}|k zX}aC+?qvQ86^o9o;0Rg;7T|ztN%m^lBA4;t&(*?|z)p!Q%vp-c{1X7$)JT1@_wd*4 zM`?htIr9&31Q{k++IdRmb&5>vo<~rj5I9or)F%3_|LM;Y7wW)nn-R-QlQtQHw3O>_ zy;nK+FZAfm4lY6ni*aYW8~KNAM%XjU7h2S&dUv8Sl#6q5v(TP;(P2?HIryFRfQtxI z5>oTP`RnK}+bypklJ`}GuJxuJ1IIb~)$J3~8=ooEu?IziKdmRdGT(guoy4LUz9zi1 zQLD_e;uXC-?+0JB&9`^U@r@*jwn|W>VA>>$G2qs`aq%LgpegzCTT*DoCOUX7|D!CW z(7-g^bcjKWfZ>*vBZ()En|?`-?jf;gBN^K%*TIlW0d4yrD%|!HI&@XX$qq`q`myP{ zV=8Km_iLS0g-c!@1ew#vzcjiugk@LJ`pswsnyod|Y6$7SVPMHXKRSEgjulTpKq-Bv zi5n6q;9~c_B`@Hy<=V44^DRQ3Pb)fAE&Ir?st}iJt^2JF{%V{Gy;#8y(~*d5@wT*V z)!#rNGItUx|NZsm^LzB){vWF{{AGwIh3NRwJ7QwkN|ohZMOeafIhBYV8}Bdd;#5HH zuXC&Sfx0H%vNP|c-XXsx*492oLqqj;<>TYx*}$u0PFX#~#R?NazjV|&l!%qg!iLNX z+IugglV+Ju?m-n?h{bEcbQnYOr%#F3Mgd0YJlw^RDpP+62 z%ey8hG=f0$6Xn-6ZY8dTiC$EFh{Gj~VFv}5F#7d0ExCYcj-OHozgByjwn)6cEc(>e zFE`mEBBydfYY{Vs-)bYk{C^JB0Jy04nuOSEPv3%Tj{uiW2(8Ui3G zRyG#egyPK?nXRF6D!=GB#B;WMB+@;!D6fczck0dGl<4s-yoIEsJMeE}5$$yYf#TpF zbfq8=m4f~&A4n5*@8e3-%pJ1^``<36-^swV_0pL1_}aR6ztb|ka&&tsuJ!_5gxx1@ zManwS9D5;>l{xL$2A@XjIBe||d_#Z7qOvVEH{aHeSPN&N(B)}KLTbuzhyy1#Qotn+ z&#gJ=w_0iX?Lm)rp1MdJjTgn}N1RI7*n<6U@fzHly^~Vmr2SSiUkA4wgt~V$Y_g=MI7AmWt~p&IQB8I+McuTSn6Sf zSzee7j#!W1Bp$@QO{C(D{qUyPQ#^sxp10O4e^ZwA+1b}8th&SuuWZOIY<_fyb3b2c zAT;MOe|Da*J~DHd@~{W*E|fI5EWWhyIp@!z<#3QLeI|NB*yD$JZ_zj_E0VGB^|ZUh zqW1|_*vqaR-m`JiA0;J;q&4(1n3;~Zxrj9)FOz*~L&c88qrK7!@3^>o+i6FD68BT9 z3fwS-P!^`AEy3KbWxJb2PZNn7kiIVBh6K~P6uVnNkVhKz0Dd&}W4RTn50$x0eCRBl zX5Ye}86rAjyqYI?c%`5PQ7>fC(dj{%8OmmMOl?xxUvezIG5EjAH7xXGPxsZLNz8vo z_@Uw%A}M%H*JaC_ykL6_ydBy;Y*S7<=qbT`Kq>RPf^}OLh3t!-J`OQ)f1Z- z4iP!+9&RWSt_Jtw>0udf9W3Xbx*fCDvp;3NEm91d+D`U$G zg@&QSF0{&S8C0YBjBY&xHxDJ?ch$R-dE!EWpK*U)H?C5_|PE*w?0 zyz>Ld)S!}*Lx(HIjl|A~V_i-f-sh(~_usU+;=Fm5XH;Zwjo_S)bqAVt<_)y(J}GU) zD{n`r$l*ll?b6Z7CQw!NJ|IdjSnn^iU=5Gsq=_T?clOh*%#E?$jQ?s~`jX%%B5$&T zO0MgyL!tGsEz_bnqNT0FquGP!%rrx&B1tF|v36<7NdaINK6+ljQy;mQ@}nAPQm`4H z8zzg%*E|2HWZcWo4`U~%ZcNM)I02L{nKo5Je>09wK(r?7_G=E8gs#BeD}&% zE7IS7;_eEUqa9XJh{5nMY22Pa>a{|{CThN-cD^_TloI>j1;uswL}A0Ypz?tEh+q0~>7&8k3kSlimR8-IU_dU(mYBp+2 zgf>$O9=TLZlXkphPg!;^Ovgw@Ur|^c5EGP)C|5G@Fhs}V))Ulg;BnJqg;8{9$I2Xq zyf2g~Of5_fSUREjc3^eDK+s>MTxo?ZQyn|lPsCeKOf6ilTSo= z!tSmEUFJq+NAPRH`U2ruG9ucHfS&n=FA$h!ikWHy0uOnJW}Eeyh!y3nK$oPAKWVX@VscXL61RmLpL|XR)tS1M#7Y7 zWD6!gPx=<9mXF&``s`@hB){xD{kiT2Rf`~v9{&|=+GA5^?*8#Z*}LkA!fD%arW~e2 zjBH{8jA(R_RM>|ynbO2U4TyMrmEf=`k9qCaZjnOINb8NKk~}v$L?3g zW~e79Rf;sMcvq-Vn9#c6ki=<7E+SZ!-dy=A7T~}kgjMx2);Lz3<=s#(R}v%&V)w&= z-<*44c9GYdKeKkuaMs98)lSv!oJo_VLI09MlXYq4aAnwbz-;-u6}MSKh+c_w!OsFM z@QJEif_#@K6}eUDi^86$K4$6ipZU|fs%6DYR0aYRA935}KDk0Z&0%r0yey8uYm^Cj zUngdBd3^(~GkEK$_cqf|kRB_U>OsQa`-V-&ch&dan;TI*AC@5b{{53*d-^N+O})65 zA^jKM7PYpjy`*KelvO+ihV#ajY8cJUX-W!OEn3Sb^2Bn!^pLfl7>@M3wQ=7ip@x+Fevwd_sY%_T$d2|B#5 zoaSZ!d>u=XsVlgWa-4PL#1PQkm@Kpqb31L_$3SB1L)~TK=F}|$bR?Q9as4hOVn93{ zf5pr3eigrZw3NdzbG%5z2~WhpYo_cZ=4cKSc~TprtYit*%{Zycs1r)=3DMq;$Fuh6 zIcxPU@??=0%4iti=?o6;XPBRp(6h2DH(JT!jZo*8`APO__%0tHqYsi-10GFEmT+gU z_4Kg4V&NV;7$wpmAYBm2tv%t+F@Ie(o`|9wY>HT#fsSXQD*2vNb&Z4u--q7aWrQ5G z@3HEgi#!PH7`KS(;5k5Arka!vvW6}KV;d%hx(7|eN!aAx5S=pGdMPPik(|9!@#BW$~_8&4gmrSP{i_pFYS5eeOzF6 z1}(!yto6fvnUWWoElxbpX4xjZ?UFdQ4x|JxGbuF!vK2C8$nZFS$+(t^y{v|6-0}zo zrJwuS6y4^=Sp^2Ih{VzzHlUyfK<||R+PgS0RDu$ru|;q#ZTTsHwK*Gs1;JdKwKqfm zrM0;o%PnJtl2+*N5L2Hk1O9auKu|E*7ZJ`A+|!POhYJLLNeNlk9qs@m;A6 zr!M(&YCA|5+88%BKy!`W+_wzE87vsB_LDZm!{kHl`7EK*8GyOrD@~r*X;m2+3~uM5 z4DFNZ+f+B2oXC@yLuzQQQ5%m?lLWybfT7%~JY*b)O*eb(8i8U)%9!f}DEXyCvc&cDMF673o%<%={&cFw2()s$c~f~%jdnjo@aWMa zLCRkm9;5Dmy1EaZ+w2EFaSQ}}#>G}WqGTE4=TaTeoj(LZbBiYAQ#q7Jg;`tHql9Cc zyd2%Y^x(Veqs8ScX9mu$?7JOVFl{^?R4naaQSagYd)T@A(CO?7tc=R0Vn|qUM$kd4 zKp}<3Qm=UYOQ>ksP?1fMQqGv*SxxHFierh!bYj~Exx8hP%usn8BayTk=4sSM%e7m(!BU5m@9arSfpKPZkIZ+ z$j=2?+zLWKe(hRXw3d3)7B}Cpb+o*LvzROVM0v@i%LxaXYqYeEoa+ns@Os69kHH_NF*F!;;>;&x3+dz3r0d=l(e4;UFf($bqAC>eZ~ zwMVCwh(qD#e$*ZmWicNS`owYNZvXBKdM|`8A(C08bLXTTjEr~NXC&UbNCeKkjfpP$ zLhG-k)zwUp!x=q^cvmXYL@t|-Iq~HvKFYf$OxB;H+{vm^4porSuCx+*d6r(Sf{d(w zCQo*rtwR`*L5u2APcPv@=nhDcDV!@jzeYBVcQo$;Tp~J`()V)nwnKc8SJNGZ?eW6p z{>vGpEuzC6`f>Y#UIT$-yUAKnc)-&5Y|GdSPT zZB49`e6eKP`mcA56V|X*ib% zX%c4~3xE3M5|7BnzH#rBv>pQpbS_~~1$5yOdbry}qyDntpkt&Z5p45id3qDr(IHDE zA9S~|**KF_R(1oGmDyWSvAPi%Sl7gFC@#OO@X4D9__F##NoJdi9N_udMV)Y9!7$yo zYMnCJ?TN_Z#G&V91Dgh+Y@D8!mO%Xp+(q{C93Powd5I*B5S{L@(W5x$FNceW?FEXq z_GoEqH7~h+DsJ(n_DVe^qT{zM@YJT1x2-S(zT(X;^(PLDk7trP zYv~<9BOSlCb(CifvjSWiv^{r9_i`6xmSL}`d9mVr0`RZ|MtV{_o*<5g8{N(jGC8P@ z$Sks*ALI7YwU*q+2hCt57G1+ba8%2s>#aeOd9&&2-q4sOM}l#loua31UYnkmJNy1e5|>Kw0!?50Zl!GA--05j0l7W}PUmb!`p(X+P>*)NwIunYJDG~4Q6P7t0Ku&{ zusw5#73w(LPkpapeAQRz>u2uiWq7xs7kI1VJ`u4EYuW;5(8kUCD`U>{Z$&!aD^uMe zj$nz_81=}Zn(gcwq-%8tJjSq@tEIa(^j-@#}N<+muymNgE zhgex9QhWs--c`3;d|LGKas$7Nz(LU}*zq@Ph2m#N2R2d)rR|Z5UI!gxJ=vecoPdi% zMSiEs=F6Xo;8b=`R9lqwn>B?O}Y~;rCxp__jA}V5yLWhys zsR66=l`Z!d0S6Zq?tOdO+9crPcg-?dN#E6mLnIAgyQ25_4`LEX=n7bhJfiN9wkvJQ z&sZaxfO&MS)`=M0zwSX4 z`dY4MR|-Ew8G0|UU(d=;Z*Q||1GnU8N9e>esTD-Py5*-WqURD1;_-KV_@}caJqOF)`)wk-0yap!2DHGd_5MTaM;_Js5?%k15lk3 zw)!iyw|lK|t-0hUUZA091Moa?{0|bjM9}AN@+1xN2yA+vO!|}a)2-ZSyTNiiA30v1 zN@31N6$CXbfI9;{KOV;LBxzM7g@gbhsVEhcRxz+*t6oEMf;rHM$h<2<|l)9US$g9&J^WNX>F?r_nLtO2=mdMD4DWxs5&K zYcpghX*q$(`D*U>Y9bkuDpH--;u#VvOSzy{YbLox(2idL7K=Qh8S{-^8X+?%oK2Nc=a zlH|mnmlwXix!x849R&%@b&BcLu8)N@72#Ek>KSH&jd%8 zuW?QE=LkPD;jtz^PfDBHpJ^xqvYM>snFOW;-&f7G`YIaFwMrOV;9Hx!=n?0-dTCb~ zrq&Y+)amLTAn|}n++`QmD^2Wk$o{5-xs}1mPg|t=wJg}gxIi;j(vwTFv96K}Is$`w z=lv|-t&wI#KU~JkS{{R>dT_2n+iHt6RF6Ni0eucd(#MHp6tn;R8b)>Wy=NSohM~`Y zeRRGYjtg$?GQym1a#S1@b!Vvdngus~>9x1ilPE8bYv9Y`k=SpHjJ!cs>45^)u)!o< zOsF+l8qOj=j$A1W5{?iNwG5Q-+_BK~iuXiHMZCCi9X<97P0PH5I^d`vz{ht@mmR($u1~M%h+XgP#j> z23qtM7U1bB@ZOYX_94Usz|lT7`{X02+JKN%WAm#~EgDq0yj)>il}LEAM?SF*L>Sw< z6z!SByC-Sjxp~XC%A2jIQN)6J+6c@uE@r|?{C!2QHqidhI98a@uOOXHJC5iLn&_fQ zW)d3<1Y36odg|d0AKsUj|GosOjllDbV3n0v>{wJ)z9(Cl*svg9pONkFRA;BS(fd6OPSu;^aZP3i%+@9Eeu3Z;+tCW5S zd^(R8gp{EbLJR}1PycB^i{>gHDEyYNVtJVVDK#?!xuZ z^3+}OZ@~VT`;V35!}$0Akd888Zi-0MYp#?%jyle1U)Wdx{?Y~dw}}}eK>4x{$J9x| z4@Z>vD77On5quYa4lDTZIacVerRCqr`^Rg3X?TlL+x{`fVF_iytd_74Q95x3L)gI}$%e@DCK8I1Z!i$$tP(r~Ee&_4|jOkwh__@o&l0|1urL z)9!=+kmmnoI*KpX0!mT07mX^NyI{?m& z^%!yhb^hLU?$$`Cn13tCPAwRJ1AKLQwmZWPDH@j}=BT7rOk+U6W`d``mY`4_xXqxA z1WY=A6MxpArG=dHMeSm1Y3CX%f|LN$d0C|oO&-+}3)FY5mKiwsjM2nX@x_XukdUG| zUYy5|R*ML1EaLvsg#9U$uB=SIu>n@(q=$-UwO^T^&f71^Hfjlhc3^p$x8G5L>jS7LsRDar$8U&V>x2DAOrlFO?9|-NpN{8e{Tsnv7VhaUrwX})_^9ck4 z+jP#9b+-oJ4&Mxp9`HSK`4ny6@!c!W+!2X8%^1>DS83rO;>|!VFrBw=;*%d&)2x3E zjb7hGpD*F;1C++qRT-qA{B`79(AsyP%b2wYD%i7&viKH%Y4QIQBoOhQe%BO1r9c(f za8GlYW|I4?K4)0cpinJ1(!X9WIOMj~6FjBEsAH5;sjn5BAre^50xHibXPc-d+bv2d zuqm2S%Is`^Ak>m#gsohFAp56WFQ%tO|@Q3ml4+Q27y4R6>cH zcXm)xjXuXq_|R*JH)&fkN}D#8f&s(36(0!@u`D%$hQ?|~S+PnNF6&59KZ=797w2f^ zcnlTgXqOjcSkaOmUxw15x{G9GD)2i4a(x-D!753xT*cgAao^iRpy}!+<~&*KjTnbP zYIbnYX$U@@z*4fI%e%UOmMdXYkk|v|e!Trl_v23iA{}FSDu1@?@%SXhJSDF~g(k;} zU@w<+M~<$+z#GNIXmf_KCI`JbA6K_NB5+kR1B!K(x~^E1gDho!UfJdF!o*$aLjjKA z$qc3WHg$mV=3&{|K^bu|A6Ejs6nN*ekmV@Gxmrx;u03Cd5_hUcNu9k4Pg{Su25)$s z&AY^>h0;+{PR`zS`%?!&hmGwGo@|_lq{DEwq4r{H%c;G3cX-q|8#N0E>1_Q_y<{s8 zt}$YgxsA&IMFCfnJNe6t+GhF^@ruN@qv2DUOCvt?hKfF9Xo{*)7sk2nJz%kMg3;yZBp~HLX)$~#i747DvI-T zK8nV+d4KRGiQdx%*|f0t=(dl9F;slx@uO}q{a8Q6UwX2C4()t6;b_d(oRk`KVc_90~oHa20)GWDm`fWDP<)L6SgXr>#zx zZW04+X04x94#_Ijxka z&zMrg3Q23Bp2b{o>VPpyCnbx3M)xxoPrPyiTT;@zITYRRN%h*Ccwto(Lv2~uQ-E zlb^Cehe>|+DGEIqreR@ch$U|^WYWtottC4HsjZu+_kZg@Dq zT4WQ?*p>^~92GcSUl?hh6=yv3wReMO^tQO@CFX0lBK+D!YIMrTMtCtXe;$nP$5NSW zXrWTDZY()v0AVd!t%^?V%#k8b!x@DXk9qmIQDEB;a85~!muJilX!ALLRXf|; znbN9lzk0I=b3Z<(N*g)XIWBk|+gV;NvCym!-ULzt+qP0SL3v8mZ5*Uz+=Ra?;g^3) z35#9mo{l&(tXu=?91ZHsrID7q@_!=^Y%9U@wz;X^_a0jz@SCc3-&M>c@qm#SYq?WEZz|=VWSB7oC zocvsd+#K^nb!J&q58;TFK8jDr4Nb6J;6Bn9RmlQ@%;Q5uH**Y)U8liXRVu+%Gi*>j z>G4>dSo*EpgW&s<_PeV>-%}mvW*TQ_h5&itT+8uyr8wj4sfrm`lRb0owpF$rPE@}0kddm$ZPSb9M~i9ekTjNb+~hu0z6$?Ffop_{!V>|i2nPzr7M23R8R7G&pr(b*}) zDT>tQcdq)W*B}ZJ|H{ES!!c4|#m(6fbA3$C(>ml;egPD=%m7R&OubSnocpq2ReJZ) zjxl3s^Io8Ct4!G!(MLI_#;!bVm|aYgomEfFz^V`aj2#O4T>lWO~jjcKB))O zg3?O${Vl3H))xaV>c+Fh^cm(7ku_bZBzZxsHCr+br!&PR9Y{f$5+T+p4J+du6N)DRd5=38J)3s@5kRE zo}%2A1~m7uoUYVMik=yTtoM|JxX=Z@v{~p7xrTd#oC8^}=b%Zxh$MQ&y(JMXn!t&~ zro#o0R~ueK;I5))k>ig*4wNx5{Cma(mwb=Y^#Sg^FS(FmJ&HaLK)Dg;w+0=;EgNw+ z(Tg)R5>v~TDYcGWqfI8F>9Lm*39@;99Gr~?a}A}S+AVZ@(a2!ZVWme*gyra7oK2=8bnnH`&&aKfXIb7TSe3svOs*h=G zz4i9p%)LF;Sy6-s@9)JJA|nHC_S0a^68=FPHiV=KKeGeG=GvGSsP5(Aoz_x8SF;zQ zEnOLj2yN?YdL3&IFuk6C|4_i)sc(zhVO&FA3#SAU;tU%->PR->=TLUtpK+U_%!4p; zQVcmlK)z_DXXA?8i5~qtP4+CeUL+ai7(ev|v&Z|SNbRP_TV?t|2g8#Kbt7!+rAoD)Bfm4=_r815Ga~^hiDOFHi2ZtI}HYUi>Juu!GUh)^m-4w zS?*i7FxXP7;-T2JIvUA^1tqpoEv2=Y7^HPT zs)wd#Do0?>x`~YlOq^e7cMByKa=aNF zRQ(LWvcKmdVxkfb&MK*#D*EmePne@_ZmCMCF(0naNQP9D=ukmk`)N9ptM6rGHmvoq z6lz$?(On?bUB9>641vMvZAY`cbpTI{MPUUYur``Wrmd$E0E!`7}GehNvNLRdd>%o&k@{@_^|<~;I$ zy>g?LVbUI`B_r-;?{q_wwuQ(OkyCn6)8IuHp(qTuPj1Rjg!-$`iYB^Jf?S`x( z*}7P$8OczDLP$sQ4LkiV;-Vq#2RKAH_!&xE`ccq;NKfqfm=w|Oz zyXXBt{SA)^cx0v$G5`gPlGupsx(A%v{q$wvyjz9eo#%-sv{5-(9~5MrCQ96N1Z+3g z3`fW$xocqZujzVtwI`eiP(in=+7ND@P8S@VY!GcW@J%uJG*JV&6i+{wVw80RMm}5y zj|2wa+E77>z?2UhX~+sr*!DSC8376#3d@dZ8!}R{TnK%jg)Ro0zylm;;u|EALhyq* z1cKN10=D}5u2=7xL3@$y7rjR?=liq!#p{X41EXN6>YLsbNNF&vum#AgmsKQy+&iK3 zuXi3m^F3C15WPe;V58uE<>m|&aEmpEw3C;jcLPRS*Okusg}b~v=*Q7cZ`MQNrXJol@_X6JSI^OqY_GS zfuUOJTOH)0o6!_Y+oy5OTJ1cXxMpcPktccPJ!r*Tmi3-Q5aH+^zZgKONH#9UU`06LBB%>BPMeC-2#JueH}N zepKhJRrNt%{#C`LX(^h74I#Vgz9ah{#Xt23=*h&7(?&s`d3TWMIs?_>s_S&sLm0wa zUC?np(*C?Vw(_V0^0ZO?OHDugS9)p^nqDXKKy+3jAwr*g>La$@P${b9G(8QZtP{i|q{CtLt(uDS8na;SQ3s1TSAAfhf3?Axoen-oym-S~I zmZW+6u0#`kt{3*BXma30`BZ1Rx*MX|#jLAl{kyQH_aqjlzahxwQCFCL$a6$h6#%AB zInGW+!33z9H7>0=U-5M*l8Np)td$)FfusPR{;`LZF%VD9Z@k;;i}bxj^@K@g&v)R( zsQ*Xei}RB3d6ce;GvBkl-)B9PMeV%efM;Rde$npu$XU;|sQHu=#EWq=#+V&t?6(1W z`8%LUYa(9Dlxq6m!?tb#1J8cbe?7(6rOfs<7$s#$7yBRi)P@x18jzX~F$b-*MHq{^0+n`I&_xUYFZS z^mP3ZPu=<6wV(3yv!2LX9KZ7ZxN-@6c?4@m?sceh4SHTuJX}t%QH*)f*`f|HRug=f z`mZIpnA=#LD+#>R%Yz0z_tK{J+Mu1xeWdR@u1y*{ZjG{i^Andw zlP$Ad6(>6!Z23Iwn9bqalU3vo7uq_3U9XA2{Yhvtko{Y9%Smik%G5iU_35%51+jht zcdvFnpz-CV`{PF6X-of=g@3DqFYyz8@N`M=?q}Cw^t)+7J_U8igP`;Cf4{D8_CgOH z|9E-Jda|F=iN`DFOWbKMpR=0h`| z@y7QF1?96kt0Q~r#Wt+V* zcg!S}NvVGN8Osn%#&IX?ewaNw7R2=SXjdYvn&Hirw60|!tl^&Cmw{x;PP!Y-8rAu+ z!+tE{E-P`Sm+{8mtB@yViLDM8U{?mfA+RvbO94P<-}wQMq=k7LDtfk`JZo1TQ?IR7 z!$>j3@o!cDWABTht&%iP`8&qylOM8XG4}D#I!Om@leYPe+s$|j)&!Wu;_Pw=XeNI> z&M{VAx<5%o@cdH`5Bk}~i?4=@I*!8NM*-rdEZxEd8yA0jDpAh(`*{^IGMw}ixB?3V zGl!D&o?N1ddBd9aySn`q|Ka?uN7wh8LDd%aCiAz#rTwk-dLCex%Z%WQD#243Z}NS= z372wKeWV!^N77-pfL1h7<>$n6OwE?4<7H>pmLtzUT-TvKnY$x}p-WxE94i`1JsI<% zM9*z|f~lr=Kl5xL2l;82lP%v{*wX$eX?{A;q(lmkCsp>@ctSarsh_J#C}WKq+*Z)4 zG}9VD5@MUXsIItQr`D=n%H5OZ(iod0%L z)l%jyyI{=AEYH{f!d)bwl3Y;oz`NlqG2=1hqrh+Kr7*=)%`+`Qt;7Nd%63+0GxNfA zt?p1U#U417JZfoond*27`*>FHdyRA(q;IE7^?z%+iQuN25bYZ|0VS%9CYjp~%v@cWg1#ecMcP8l`+U$@l?&D=D+ftD`{RDn9P?BaSvYzn%3~qWPY^=N;c08^4KbODWW^|2Kmm`t`-}ZE_ z+q#lZr=+VgQfVykyx@5}cj-e4rCucM8(@*e~jGv4d zcs(P1Z@oWaPouHI$W`g=o21L1-(D9Twio9e{C^4rq(J-2YBmQ?;|Be?HEs5un@7HG zoOPd*)#?Oo{DM9gt-Cusw-%091~~XpJs-~{R1;&0j6Z8)aN#47eY(INHsBTOwb zxwEg=`zUi;!S`l{)&Il*4MfI5uSN}iWPaLBx7PUE)ef#>_iPisAq?5IpD)*LJlvU2 z{@;_|uf-?swoj6;zV9c=7wtbJ-)4xn`}5C&>Fm$I^})AQ{O{UCNS80} zADMq!al)k~zNA{ad-obDP`G`(gdth9jlAM~i1?rK+KE`Dt$i#d0r^MRt+$iz=kQS= zw`h%o39jF*&tFduFyC^0Q8W2^sJHlgpCC00zF=?HB9VB;osBKCvunD4({L7rk%FPP zwX~4MD$r0GuBBk$L#hD`5fpUq%f}4;@=(9DwXJPDHXFh3Mv)hoEy|IWBHXYdWY&#U zgp7rc^>`JG-5oi)2{6WbSVS1p##hTC^kIT0DT+6#kIS+n9m^w;yz1}6XCvNa42Oys z$PXrAMe_Vg6%wq5B!up?x9PO!A__B>sF0y7DK(R;3La$UyOT;3`u!B{xta%`aeXjP zfBTvTq#cPf@2a%4%8zV+~r_rLv-h(t~(QInuLnNnfn;BzAt)8lXz% z27ZHgO2*|x++!e^q9nLziY)OB`n*dwT)s0w&d%oVsLt6T?GBfas1eU zps*!#lgJw5j7nMd@>99>P6~+hnC4Z1ya6dOH?9;^cuD~85Cc9GrOY^=C+O$= zSD)}xf)>pfGlfSN_@S;f8BbM8uIfPCXoPafAi4-n z%nUDWceJ!kjeT+2=tG$k1ay)m@<<_twYUyd@Q$q%{C8W!|ImnxUkuqI?%qMPk|58? zSRn6G1ZI3&LSNC@G#Vq_Ns8*fD8;ED+E5qJ>3q zZ>KXJiF&)^6yoTC7QD~pLPkqg_gAFFXUcPn_W=o*73U1C|K;n642dm~Whkx7HB5@O z{ncP>Ys)4Mv6^qvApZy1kQ|!wFXtS6%z>`jK9F>Pu$_>d3@Iyj(3uPGqI{OHDKL|p zgnf3BY0{QkIs<=k1L+kO@4DXwZUh~~tTZB{nDY`KDNq0VJ8H)#GcwD-wtgJb{1nvIV zfgKUF7P1}fjWZ(U)(uj9d#sHS5A63@3x3thR7BGYfk~bW*UaxOSZND#{2hvVx97}p z+4?nj*J}S6m4%F$>kiDTc~xRhBG?~->auqmx{Oc;GmZdr@D@K5Dh-*Nc0KYv?K z-|%X(yyBr#aIK%J@`{WNRzJ6(J=@t6Sw0zuvEXlnWun9^r9vG$I$Bs-Vw`cjd0SpiketwRl-9@p5o&Y{vabEUMh^UX^hKA z2C!<%?HacoK!2hLw2mKl%Io<*!SukB)G6nhUs|6*GxrrJui74LSruHQJW9w~i4jRG zDBml;qInMq29B^(x=|)pQ4nLJ(z?2-B9LzKuv{EthcpZEV8N47rTKMrT zvw2Z%WpmSH=+t}-gPdw9J}xt2GE-2hEWHBtiF{F0!tl39|Iz23-uwAS2q=<33X?n@ zTi+3E?V2U(ojK8rRY)0B0S6g!9Puyt^Sx2(40SZfg@eFfKKY|F4cRjRDw+~S*@}u& z4bALe@8P2Pwgmd2h40O8x4)%v{C<*cZS%`#sAUNcQUm4BEY2VmX(mlG&S%~pI!OT1 z{n;<4i*1C#ODZ@C$x=*LE*dKZ-;)N;F4y_XuCQnCIN-B{noWD7YpmZg zUr7GWVaQ=EHl7$EqGg4MJW;-%>4I>!-^FYml(*;bv@OCmAEeCY(jIxB-&e3y@gJnP z46=rrT4XEFz)vBl^sFSou4uE?J4LbHlqcZv-v*NS-F>yy)y%M@%q?^zI3P@DdAm5Pul>HNHa5fKed_ag^KR$EV_f`$8w-v^{^lZM9)u*JPR z6{pAP@Z=pQL_X_CC?wGNIOn~eAv}=fJI*KUZDZ8BdTOr0MsVws(cynjQ!KxqNFAhN zDGwKl8H^4i>%z#%Gv1w<+S-AH5k9ax92ZA@e@H|U z*BCzWP{YMF+A)K+T8vjQh#ZkVR#SkctZtc~O9#{`&)n~L`4tHkgWm@X#X#1Y=AmSb z$I8#Jf~2Mb!)P^`n55SMpGQ~;Q$q!Vf_1)Cn~#oR7! zY3i7{`-V5DX=2)S>By8*<7NXA~I2V$hOrs?~t>iJU>gi~;oot{K%*5el?8gS{; zMWl*a1w^7d{me}hHV-U6A#FW$jHAHK{~QZIxgbMX=_7%dz_&)8q|ce;@uwv8Vg(BX zqaRg%*fVcbng52mAl#m}vEU$fM~W4w%m)jLkIAz}{(!%~U-T?@`qC{+p*%jHkQw)$TQ zLlD8rA(M1IwN0~%2yF-nI%<4E9+4_ct9+Zr?pnW^c>3|Nse?gadgYIw?;?3z)QbQw zko5@#%~;N6+3yf?;aI;oP8fSzCjQ30QL88qDYC^@qwzz`lXJq%H(NOO7zWTUQ^8Tf zBsDQVVY~_1gR?QI-?me4LVy607Z1NMj^Gp+x){dQg`VYpn!OAp^!A8hnGlnCT(YM2 zgw|2iG9>}TVf_6(5)+`a$pOltpXd)IoyOA=F zr!EcdRUv&zU{|o;F!%BZUW2s0r60N~V`fZdRa8)&=v_5Gp;fp7B0Nd+&?fdwaGnXrjo|urkDQm6(n96Kx0`lS2Bgz%MKIumCM5+ zZf;CTzqHa+M9Y<>%~{XOou?6g|3`)c@wNXIr$Sbyj;Se{I3=@r2_kC95iR!<( zEM_%qKv%F;npH`UEiAxv_Cw&bw2Bg#%|C+qNI`ec#)Dq?hw`K0)klhAZKJK~SjC>PUoTQ+kGul%mMfDST zWQG@sZ6L^d?;ZoLet-}Jhm$`ZLo>^ccnXkF0sv|j&=YLc5{EZm5`fLt!IkNRUaK!y z!1_9aCBxW^Y4Zcc*?AE~S4vgU@7KwQ#4ZHIM||wl=>9}BSam3C8U}}Yh0Y=5d?S(>Pr=PKKv04);p-jq3e(Uc^*mN9lXZ&XTG>qXb)a(-4!`=xrj3G9 z5nWw_Hjgw$N7~XJ#ZsQ&veM^Wk1@g;=xddERg2boF;NG?>L+AJVKPZnGs_1XKsF*% zqlrBk4?+IMhxxUU+1=4G+^#$bpuuTri3@ZgCMAPuFhbc)Y}=WjN47|8m$)ZY3xmeQ zY9AV3{cfBgh&w}4pU#>FK#0@Vl2dMoKqmf2z>Prwz51VSfJ^)0ghD;?@zY1*>`!ve z%#&QJbJ+J)oH2=(Vxp2l;!p9jt~ zGe~MFGZB8|k4fpK?#-f_bIz(r=MKB}&HKB50>xL`uH&7=5jRL%It-7FxOAAiI|YR= z_*3AQ=a7(%Ek&v>uYktIMYR|L{`U|+c5d#B`FWMU85x}Z?>zGSZ!DuzPhSqbw_fo1 z->+gJ9T`H_=x4t6D_Sfa2rO=Henj+=y@i(kwi-;I{-geX zj->gYIR*c_-@*^vA^*b*(0lP8O7h)jdqn*|l;qv-w`&ik(5oh(jSIJ^0XP5s>kWFV zso_8Q;)WmZ8v<+dsP#>KP3S4_17a?tL%vY zk_B=CNbO%h!}k-k&BqV0Q#rp}^C9M)|GjMtkh-TRP=^FHIPNO~?$7+@l%sS^d^01r z7%1^Sl-`*3Izh84;bbjw6`4dW(=w7Xro0ksLFwe{l z9n+6p5reG#8uPGsTj3I1%|@?bDXS{_{{lrdJ=u=E(8!W)oWRT?f^9qinuA#D&vPrlR_OS3N*WQca21HW*M#0w~f7lYe-;2vI{mit(G6*aYHm zdyZqqD(UD>-oV3JB{9=%*%iJWa_sHc2&tNn*m8b`Zv<-b`s9TW5A^Vb*Ut_tUw$Qs zCTGO1>^3Uj@6VM%KqE_#$ZYmcoL)t}U*Hsj2G`ZM5BC4f*opq)CJ7zEnRbh%lCnxs zO+{YZEhSoumM9jg_71fxD*vN$eTdyFVrNFtj+-fc20UcM=14Ok>}CR3SfOkkQfuZv z>PA}lEnh7JRG0OX<)wvZlbT~qDmW7>#7A*PL2PlXo~q;E>)kygf`mk=s9LFo-f!N; zRv9V9j4YQJAJ4C;NGePC3af-n$wDphWj7wa-I_|zL z!}#=^yrTNJz#wsna*Et_19Id1Q4m;dj zG%{a5G9E7-fK8Mam;X6a>hHaFX&u)Lc-?q6NX=_iO;c%2p&_&QQUMJO zonqk(-k~M@6Vsz^rs+|?l~`fVQ45XMOv(y#$PyKzN>X^Fq@xC?q{w(x!SkfFng@mT zv|)<8J+hl!o{uv#GxmGG4U)M#EDL`# z3E^F@-z>?q^V(I!Ll7!rtvCn^Y9edQBMWN~t$Co_1S8eACnb-M*cj&}c{Nd9WTXf-e=Z&0SpI&fNm{3d8lrm8;; zKJDt1d8BMZd?LW>gxblHPJXE3YqZS;-=O=E!V-4pon|9?F%}N4fv0U`yecBf8ljF8 zB%nZtW)RMbx}35REm7a1kY*~155mQpEO%Q7V{<0j3_40AQ8U)icB`@z91aC_Ax*8XqGSif-&y#TS-xdF{Gh*|=4|erFlBb0 zk#T~BV?i5W_>R7umS(oS$wDl>R*_GhsTD%m7CQI_ZCNo|%%v_Y2)Ir>(gz5P$GY3X zKFqR6D<{H5M}eC6jGV~()dUbEu}IRS8MLoUs!9tBD1tz*Ca|Dau_!O-5+o_|z@ehS~}+UM8VCyy8)004>0G1)m)8q%W3X#`P~ z9>c;e&)@HB-Bybr>%*w8%<=L%iBjv5xt!pEcovb5M~-sQ%GBUN;{MB+hEFuEQY&Gs4RA(}4fTC16`v(w}%mz5r#XI%7{H1OWg@%T^nf=sgg?cE% zKs1*%F)LYARF{@B#8YMUdRShTL=&FN6VqX5rCD?cQNQp!RTxfM^>Q3|@qHDLD+=ue zC6Kgy50_nPcQ`b3obJYqCP$p2D{g3t6@BNKR7eu{gCbw<@_bt()5Ogzd}YD(89W7Q z-yYnN>!!DyE-Xy2D<4SG6^fV;Gj$~6G(*$$BJG-VQUkoi3n2tfs-_H)Yicf=d6*;& z9ALS<(y6^E240&W)1X<%gzO(CE9mP>N@k~z^6-kGQN+d7LSC7k2@|_)W)}M|$4(iL z)iEOG_r&_t0?%hCy^a>5hNx=h3HIhorRZ>F@->Ks0bG|8hK@k=(E=UA?#3F6y3McJD!AaQ8mPgepBt2o39(V-v3s9gCi3)#mveav(eNC zppPQ25;mn0%u)i7cKq>uv7)4{SBSU&O{@3`bG-N*l74-}sQ<`|6g20WEwxW{du14C zwPjMj*v@Dl>Tl1wvL%ga4(P8S0+rn-Dr=x#c!*AiNYAM!Yt2MKon%RJsa^D0mT`x+uf~zJv|5R_Cw$EGx!3?aivc` zeP3{W?d1172b`UrzD(~T{x2EmQeT<@bN}Mw{o-k@>rH!bXlP_?>?Nx+d+vB2n*R~v z;}Y>hfaH3_Kj;ng)pn^`|I-L`Xzy{5tp3==XR1s0sR?~WvOwuHA(|%p-&JV;sSN*D zR~OEwqO|a-DCs+Xt`LqhZNHU@Wsx|-hfv?5vwihv1x{1*6R}M$FJwt+(NNP0i-*^y zf7n@5gJV^eq}yZD*4AJkK)x>$F^xD~%aPco23Xda`d;gImxe9okO zx5k{zUi^2h>xHD_-#a@DNqN63k@X1-_T_MNd4IaZtX+|jQ=yq)!oyojx=sY+Cb_mD`6 zGnNO@ojjT1$9*lz5uCOiAZekjsAQ1=(308PI^3I`>c__f+vm|nVlw)Di#}-=c+!VC zW^gZeK*zlxoch%{4GRDC@qBuxGMad2tQ>WIPoMn$!zvVPpVY=q&P_c^vvr4a>4KI{Uq!!9m+d|V;q!3+^k`IH zxun#LFv%HTl|PT)tFKRT0Fj}Us*Q)F-kgg!hUD!14Y= z_1k46xc`%hR*bA9HN54Y)SBXpTh6SQ^C!3@=-&zIPvX7X&6dISGX`QDy1}nxJ|n7_ z%7Brj(q;9(!g_OtG6OBB1|6f z%nUtvOWr(~>m4 zN>+w_%DJ2-+KE0M96z)a$2N#%+tt_cPPr=Xt`YN3A+1h<1XBVqBnj|T3}z1>>GeRq zb|6zp(DqF$3M#~{npem{5U_yRQoz`&Gp>)FbS}3IC=9{m(_|WfB7?=2l9;R(%^fXl zWXaltx4K4iuFz?dIF+}bYs(o@{@_`e@(=QD@WMtWd=YFG0@&|m9Ge{IA)cQTuWuzV z6G#aqlnygcFqHLC?Be^xbCk<*$|*@!a|TzI#`i%>moNmvD1hK;cJPl67Q-OdZFG%Y zXrsuc0$Y{=gqp%ciYgG~NU1@Us?gG7aylgWRCYuiogw+;2(wCYB83nvh=)yS_R0U8 z5XXqKTo7m(n@bHB5v*E7q>M6ygE<^Sg2#TImP3%Zl3}@qQSh(#_N3s#x)?wt>2GrZ z9@UoHpQ^{#JNnP>NWO#gg}k@XV%BbTh67PIf+(rBN%&sy%Y84dHU|j#u-QOHTw*iI z#h&*ELAaC)#t=~=Zb$puG>`;3JK&5CxGHjF`%Z!5r76b>z5w6by_3gq#I5G34D}_A zALX@+=m~~ng9Y-xDG$XD+>u>4G_)J*+7ElGCxnz2h4l6asR?@cP-^<4P-o>#!N-@rw=&;3qs`N8t$w zYPwaZ!2#^Y|C-05RpEuNVDqS`4@Rh9;d0alub^~18jl<=Dr&*%b?75P8Cx>vGsL)7 zbcY^=FwEXZsZ-oo5E}NxEUt;#=MT*+l{wbjP?DxOEX46P&R?}eGc~5=x?93GEX_x% z42a`|oCJS177^p}==AlRkkG(RU-*K%nQZQuHk?yqI!#-PjcGi7&ytMX&` zlh6GNNW|flN^P%un6)PD0wtxesGIZDlFFf+F+PJ@!-uI|+l`P72G-8{Mc~XKyR#NY zsC9PlJoD&PB*j}lp59`k z7wiPml|(IXAh2VSW|VBnpr-wLu5j+AcCsyuuk;Yzxy&$Erx0Pn`}GNS=4maeVYA4%TW(1wsxs}X@Lz~Z#SkfcQCJZNTaT-j z0}_*^+-keLdk2&-DU?zf9}oH0-Ld!*cjP4vXlLJz_2X=F59;`k9E4~+u~0M@$={O5 z5J0#gu`iN#y++oAO||KV#DywpJ;;c;8f~I3`%Ft0d{yQY*U1s@{+rn)teL_RBtuIB*yr2msiAWmKmzfR? zf}7lMn_tAiEYkBRLKBbYyu+=q=aF>Sn=YOtAO|gx>3}Ye zr=h3!-@QndBCYPY$ENRm+%4w&kJ9(49`1Cdq@;3rd9%K_8?eNOM!gA&p z@59sCM(gYA@IV(81AbpVH>i7qfLeVe9bbH>^dtxFwaZRC;Yz6RUj3qkr4h7!Ei}aW{?p9n(j8=vDKeJ!suA84)o2@(dNAF5 zwMaq?ZIBs}8ZNEQJqVA!{>of5j4-Rh&i!z~z*Q?5*7hg5f>{OV1HgzeySmdN7CQjn zhZNiI9>0=*R`Hj04NT7y)e4^bJpQg^>CA_!M!Fv|OJVj`hXnw&H>mm-y`7e~7N2Ul z2-d4BxNy{m-GA?#)Jy(yr`=>r2SY2R&&mk68&geIxq@9#+DpsrZ-n-`xcePF-v)OF zOcv*-eF_2ryDH<3{7<6Yg*MmZpB#b!VcQwnu!&U@+Z++`vR|c%%p=FO0$SMAbr<(>9 z5+N>RnBXrMlclF{9S?-=^oY}~1xB>S{DWnX^Qk7Y30TDPb&?L|f8#qLTDi^BoH8Pk zfVuz9ZZbU^1A;6S%HVS0T59Pl7#98FljE)7CTM4Ih7HG@kfrT-;n7LOrDRM#lRVi^ zYaYWGraDG6w4py1vxmiF%#?8cK25SadE^Sp=kX63U7+6QW;`}|A8YIFJ&VE40koLv zU^#U2_AFfa%JzlwT2TS8$tI;uj`TXYH~w8>r_jt%+=;gRueh@HNudpxWXu^+iS&QekGE(^)ZLWz2zY3_KsRN=E>gte?)6x)(T zYD_9>(c$hFrjByh%;dy)hSP2iH84+Z-=eDX|1IcZ?^at6boGaDHMbt2tQ5guR{EPF z;Mxgi>k$~?u6J}8TQ$RK-o0>3d);+I&ccpuAsNWyiunWS9*)WL81I?SW={&34j4 zat%+KejtvoP1Ac+&*G^M3zoTn_a6&66xR?ngd;&iKx~bF@>S={?K-B3m8@{ZH6?() zy*I+VY}q^z`6)YRzxvnB+Lh}&iZq`6C0HaXvh3)G`a6>O1IFc1gOgKKn>_MW#UA*L zQ@Lq#yFm_sD{ut~iRr?!x~zq0D@o?UMMlZpqd$bRd|mEonQ^E^R3BKafNx~xF-LXu zSW*p$ZTyTvb(J3Aj|A=|ZBKs&IsKAA4>#63c&PgMzaxwT2F@{en`}j1p_r?)%+{QM zr^`ql*VcFps^ocW_umd-1`oP^_s>lHmh83htKFscY?mGOstSn(o6$2+DLo4zZ5K>k zJ`ZHo?roNLtKrE!vSZBjSG~DL+0;q#!1lH^!zt7;f>-9fRQ}z2K=w>;>J0FaIA-y$ z2OS0zvj0FC;V$9+J&2co!ez+2B5JG1erEE`gL89yZr>zz)+F9>IwgjXoxrs$UMDCx zMmDoA_1OP~Xo(Kd(Oh*x&W^aW0lI`9G@D7PXmF2wU&-WW|0f%#PsaWvt}Hw6wwF4S zLtU;C3jmXA1l#zG8-liXxS#Sva3*Q&3cupJiF_v{o?zH(MJg;9i37 z`ouYzX|v5uK0aSa@r8Udy4>acQWgB}6i!$QoBiZmrq4N*D`lZJI4xe(vpF!opyu~J zMp-3`d5M8ruyZQ!d@sbCJmTbZfQ;>ldua&l9Q}8CG5xN{k0(dG)@Yn&g{Y8`EEBXT zTV#X)^aZ?hIIr8?fKaK3&WB-Q{7yNFV~^sf_Y_So>(2dremQNJpC4vK>2wT2pX1yH zk6j+JDJyAqUuhAmK1m^yAZnuskFU4%-S(4>NxtM<;ml`oPdR4%?K6YvaQaz*wYX+~ zIm7MiJHs+TRz+(GndX|Ga%RT)c&}@Q1*N1QFMt2`8U$~ zvEkid2Ap0?5A+5Cc);e{_1_xRBj*Y+dC_cS)A@nHe_xp0!3?bD2CPqC07a>m9*34O z>SY!);*xL=J!i6DUk@OGUXsN|>F=9qh|Z@Dt!(>o5-0@_`KS06G*Mo0=X$*-jj)+L zPOj&YRNdi}#?NJ2L}3{Ec&5s=)!DzcblAd{KVV#$(_9#`x+(>LgE0xgkZ`)#j9deI zw{Ry*lAQjSn8M#4NTufZn;rZ;ZrwVV>z#cs>*9JfEkXMFhN4{Wu(0pI$G;0VauQ*7 zc`u-`7v1XP5hv3#_wRRFjb7=;)-8j_YthXv#sOPzbeu&q5S1-%72}LX(O?O}j!vc# z7>rj0mInzS1)N||cs^&~R*PHsc z)z{M+zvzk1vDfR}FBkA+4A|5}`EKqL+L|^!xb8$5#{--G8CO@TT$!9S#aW-HKQ2bh z!KG41{QS28_0x&g&jL^^Ptk#^$6(o)e`~!R$6{>wOUT!+5NR1fi)#Na!fF}QvNxka zK(4z5xO(4B@wv}D`}X@)>(`B~H@qH$U(3<;8y()MMMXvOuYTIvICFDzUvRlx!gqIf zx7Lh5t>yn+I?kY`pfK?B!+&)8YRi;R<@N3{I^s2l$;wc>C8(Taf*ChX&6sTY2RK2}t?ysa;!;FtRVy{?xRzAbQSqq~cM zJYq#v@9Qi0J~{dA9eVX}>lNv($*UQO!npH(ih}2cHM?BJi4J969szO$x=N1d22aPc zEo_PJmSLN2(Ce0D>UG7j(~TiZ=*!WsF${mXqp+oBwiB~nl~~Y~rp;XgE;aj%N(H$l zRyX@xQ2qt7F|TjCJHhJfT?y6H)%-En`@YS0_{DEujKGGk=hci(Z^-tWnn$foxZ>}W zWf?dgU=Jkdawdjd@y7K?doTj=19ZzgINzO>z;(nC0cgE_N}mMU%KQTxUfHnI`o`6< zq~+;PB4sZGskml&@{sCWMVi_wgd&NAG2XP3-YV)Y&TqeQHEm7btKj^Xd8+BM@@Mk= zKeUoBmd{j^+#mGptF4bq2ToozTZJdf(yy__(LAZ=B785-i&dSIv3A~`uIIn2UXMK9 zDRDk-(p99QU}7hshvV{oj{7~*ult|7+C_(AQu)A4JbeTyn}1GU|AgiB6|wsWY(%WS z0So-G6Xor>o|`|b-qvxZgD0i@XRK%P^ZfDi1Xx-b(r(gqu|3SKvjgFS_LoCg7iFj-~XmsaJXk5VMk?7gph<})@%()J-pc5 zy=DenDQdl$(wKCLq@4dCcSg;mRZUFE5EMW-sl>0Jt7dd)iza9!a~kmro_`y91doZn zUd6k}fWBo~YX^(dqiD8D4fW$z)0<9LbI1rfqR}tmcvSHPeak{~*NGXx6(n9WG(Qvu zzi#pGEVd~}k>ZKG&3@$UB%|Qc29vqMW!XRk=11wa_lI@;+mSN=1EouOJS6Y5eT;HO zU!wrTB@sXEZDJi8K0k%4-#mCXN@|(!`-jjabd%nfNs-_vKtLjhP0F`4uurU~dN{w0CczsOFd3w-sQU0 zg?+!J=WtpcM&jM4KL0Jdht)NKw&lRA+<3GUe#`lOc*^`b287z7|ZVUQBuUHl%FiK z*Ha1DW`q5$+K0}`@+`S`*S8<#EnC|w#tW}gb>GXB-KvMY7bzX9;?-V?WcH>J^apJGV5?z2nU`cUm3C+8{Zh@oEgn( zB;2$^Wco)xwCeEJS>OKfz1p zEu(!AYv)-E!cUlS;ia6zt1NwV*2W5ygo^bRyflQ>a*dw#Sw(_%lCJ8VNwQw4<+3?@ zLx?!6e5c1FY-@d9Xa_g_Q?>DwZwGHKRkKJRx{?0c9^=w4C1%i&gLtD)H^pi0HV?I? z*izMCmnS^{zQt3Q=gv?%C66B~ZF4zglOj70AG}{OJk?BoDVQmk31XqCsHkMJuFjB< zF=qK)94i;MQ8mfAZ}2VXx;_g}o@X}6yPGq__j5wzBcY<1rf7;mp?)*XHeaqOet{sw zWMnLEbCy5y^;1px>aB6AY0Yb0TdCzw`duZjY-)EF`hcWZ?pk3hHb>a;>`9ZxkPVgw zB4~%qQ)M}bvq z{`&+i)1821bScjD(7^bT_N7`5l8bT=vcm<{SMDJTRSMrlAxB%ZdQ6Xp=XIr7WlYN* zC5om};bf#{TA45(*y9bQqSq;^DEO0AnXTk?al4fZ&~55g0h-$}$`|Hd=zGhorjX_x zJLk5Y*AO9&@Xk<;xU#tqw8)o)BXiEB3o6Huewu@)z`XBsb^Qi?9|j_wh1bR!ZUyK2 zCdr-#If1~k%F`Dk^9dBaeXq+%rV-W2sF)@d+=;zinR(kn@T}Jg%g_Eu&Gdn?dcSh~ zf(z)PpVyjNGGD?o(T$%gdL4C8rdB=t*{YfPB)>je1PJCt4nbk*d?<6V+q+DgG$5C6 zcxyHoLzd&g!KA<&Q2X|KY(YxhTqGoJ3>w;l_at~K)`T>D{W910 z@NcwZ{H=X$e-pTyoy(65Y^FNIW%rDsghUJdR>sEZyXM{Xc@nIj(KFtI>hex8}vDDOfsRkk6y???Ku?@<| z@a!s@!Mdi-jkL_kR>sr+&6#M14*PXrD;yjK(+JC&Sh)a~te;z3AAWmH2@3U5Y_TU| z`$Q^{ETf#;MBRGpG|9oM%%uCKKffY7{bgZE`<8oz5%~cy?f1$6Ih7(YZIJjjXu7QP zh>99=vOnvVIIqVVk3%$8Htzf>Mz?+wXHb;dOXVc-pYM*wX1-M$`1R1$2r|84(n*Ur zn0N=|o>vBzO_fYe9RwK>&kpS|BFgO_WOd@|5)UXXhTl8li((BFpus6D)?xZCC4U>J zAhJoOr#pP6QFJ#bqcpE+Nu$4|SoKl`(4G z;MAD_76JQ*L)P-O-S$29kkSd`cg{*c))Q{Uqm>^&b; zut6;y<9lTG8XUvRZQ|~}>g3o$i8pcXS~EJ^R)A@ZNgj9>*y|q4yaJ6Zzer7asD(Zz z)T~DQV#kqbFqXhaW7YSG$aA_n2tL>I1)V4>Pp|#-^4i{kfPknmg!J&7=wCHq znzq{6>`3R(*4vaRktIrpX}fy}DnI2H$f3P6rUFTg{Jq?t86|G6+8R{j=lyS-y=7M% z-SY*S06{{4;O_434#8al1Se>47+ixxaCdiicXxLf+}+)7KfiVF2e|)NEa>6P={nWD zYFF*rg@Tt64n9=Hm*w;jb3T$&o*}&K$G0Fz7T@Wl&hQITi`g~xg@dG8g{R_k4aNNv z&Zo%O!zKXzv4(r4V-ng*z=b^$1+fz1bVzH`RGn6LOTn<7aHC=KW&MP7$&M_`%gFIL9D3Y^m&J;e-wKI(#H%me9>LIU z)HVc`*fNy!bAuZe>wwuT!g+d&3mEBt8h|VG8+*&AWgs^ zp<yE-CgOY-|FRN5x|28Z~ko zZW0W&lnYy~R6$Uxh|;l3kD;*uQ}%iho@D0>K#e&maXhSF>!UTk4Az4DXc@~JdejsG z*g!Fq03h4FTlcCoen2w~yqW}n=oquKKnbri=WTm!WU!@78w zQWBjQ4)p8r6Hu^AivN(wC7Y#m{}w$iC36*uy3zMCm zr=_s0x=zbCF%hyN!UStXh!9=5WlC<|{vedr$V*vTER?!si2f0u|A&h|f&h!H;)73J z^zcHfQCbDb*(h;JA-+Zjf81TA#P&rUEGxoN)(?e(AN-DqB{zk`FT2p>^cdeNz2Fuz z+oXTwaU+{lsjhy7T)xFTu-`AmU{KSXvTBLxY9eYN|57{Cj{#qfgUe5^OdaMRAoR;K zxgv#chL)mfrqdUBalEfD$j-%&oj5@{D|&0>+l+wB!F4@`c|1c>r97F#Dk4PtDQwmB zR>#u!WL4jSN`m%#ty@)0yM1Y-gObFlTCRVG>7}lFEJU*?zVV(a9H6ub6f2~9PCSaYt<3+mGjw+kN^Scfl+0PKFk@ty~T2gOUBLyd5 zflc*+MY4T)7>3;%%o$2*;z?w4VMq2mT7YTX=mYq=D$|434wyvwJu66PB$`)@1WkD#ntnRNc=Y_elWrThjNeP<>H zq~57vBWervXKzzh2unw64xW2**1Z3>b5m+VkujT4#aBR0tbttq*+!s@)JTUIeNGzF$Q zF0@FUR*go+7=2t@sNL{C-_SCMNLe!(kIRZ@Ho9`+l`Q``QBbcSxXZBarcjTe$7Y=s zHgm-u$HB*8va6KC>hnBPmMygfIF9c2Y4}ZtYGW1+WbfdpI3`Mcl%%mXf0ZtTs76FI z*^&2NsJ!c5S0v;Ofd-L!&c*gRVCZGBzp!4H653nQB*{;bLWz^xQgsE(RcMmMASaa- zUeCx`XS9ln)k4V$!4kN0qJBRQPZbGl&4vn4^_Az3sObFm)0DdZSG|XqRoaX$W|@fL z(&LP|(~n=#E6iH?_+4UtM3xlG! zxEeVJ=M%pp_vo0}yMzh98GYgzNCh1=-D67s3zZ_g+J3)Q|Ao;U-kuFjwj!5>)f8Cr zijr89!tFH~&(rHz7J|4{ZpH9}8;AIF5`i%1>))$xwe!YOGd%6SJRe#_nX^lsib)hw zcBV122l{{S9x<{Q)u&pe9s{()l{;WdPMt9o|H*`#981z|OKp)ly8%L*O*EG^H>Z zjOM8YgXfvBRX2yHLQVA-Gg+D~b}bBCnP1r)AdzeDHlCP$a2noA0uQFkTf&*p?m8ME z$SvU!m03m*sPw-LF;hL)T1Gn?Ew%V&%Z?3wd^9GtvpsyGJ$#g{bRMpA>ZE41?%P=k zDD_v(&0wWNqtz(wLibX^98>dwLem&eif}o^kkLaf*5%4Bo%(e2d`q*@lA-EG1P&QZ za`Mw~vG4Ns4~x`Yw{TDg8vKaMv<&>v8C%wQ<_y#S+hyY(bL0TRVWW0LM=fSVgGrN? zbhVo@#sVT|P6>~k;UA8J(z~Ige`4G5lE339E6W!K*Uj);gxn|CE8d?do*DPdf`UiN8yo@lA;O&w_v5eEt6@qKU{XeB5cRU-w>Yq?UpF~6vpF(=$*;d@D{cv8;O z`)AjG zVLGT^2BQ|N9Fbd$MxB*PAg+@rqW7e(&2U1Q&zU6uVpRr*v_Fpp>NzDJgIc*R=8lzq zZ~i?~G7ol!?Iy8iwGi=K-Z$;XiR?cd&6k`v#5%S}#xg(XE{Er90)`3hP#LRLn=RlG zo9ke;@)K)xVrr^j)3po?k1Y#n@!_Jpa<`0s)`RC}8a~|7noEC!&{N8DixUEVM=_J^!kPA({RDAiZU!) zYG7--&ySC1vTZp%{T&3Of>0?TXrd=64wE@EWF6M;WgEHsRA28)z~)N(`&phmJe zo=d(S78Pf=iA8Fb3qsR!Ah#Q^^OB6g)e}I`U{iOFFGn6rj>j>zkVOrt8!q1|e_w~z zFPkM^^pPj|e1?Yd3qDL$#qAk7lX6jM&f3oo>_ifIrax;AQk&^^FvMwme^AfUv&`?O zL0c7-2zKL+VdvPS4=8kJG1m|7-WSISZ9T+h5!x6JBKMJ}Ys?sk5?}dR3A$^yytb#r zdI%lZSt2HBr0-QnN~_Z}LV@EchssltBtw-&KvTKCg0r94R}pB58-858d>MZ2 zh6!z;qqr8_6!)SoT;Xpr1bv#UqHn|aGmfZ$t}MlR8z1A{;=jwvulj9yr;R$s%BGTZ zWDQTND~vhovz#e6r~E#MxZcklb+l?D?Z@l1qou8SRh&39ZAHx0x*Us57}F_%&uS`6 z2zW0b^E2JNd9+~tX>5`BxnhEcZ`$l~+&#UC#~Csh5ubQu!=K8qYSFv8U2NGUb~*=X zn2~Br)sHs5!2R;y`q*?Ix#i8=L8=_#xFl)&k#`=)4vl&Xrpn$uOF}iwQp13M9=Z9L zTSYdFK!1H1k3g|=?g&>%Jacqg^;$-_%$=(V^vt)eA%p=L>+9twi8MN`vA;T8xc3#? zLmlx@Ndm6&65P4m7fNcnvMWEn*E0;-B1RZDB9-Z}Fn*dQ~?UCtxPu9nP2=+Tls zv&?ltl@x2zOlIyoUDJ;cq_X0@qcFfken+Oe}u@rqi<;@9`HEt|bDq>EGx9wyz&) zBKPqW1Su6=W`o2Yu^gM7l957&_#6r%5{E*C$~j7Mx$%-h*1j^=ni@ueb>7p^KF`<*gE?cKN3dGZMB1{ehZ2<|4yAE0=c2O9{oTZyEJZiJ5}c zk>e~|-LLUg135?p`7_=x(3$(x+#3L4SA{PG?j0|bvwztI%HhFmT$b{#&yi&`?i<7E z-v=3+8oMA~;)2bdSEd=JA{nK{{hOzt`m~{_X>)wZJ_}rzqbkAZK%Q?!+2lK4kG#hy zKOzwCO70#zJcEND`(0$Zl}bN{d`rh5VcKRq%-k5sT~Y(s|w5r_0A)?!N7)`m~(6I**?@E zd&Y^`g`i+$sVpAIexp&j1K8VZ2eWNrb0?LCdks{Ggm)%8C|@SqWGC_G`n_|im@<)4 zw1?Q&2d|^X+t4irtuOxM#kd_(?>?LErSWl&wO<*#kc-vcc#EO_u?geOnlk@Pt?3|{ zkDq0gMM;|qy1ZF155H)07QeTFhIQmq8BT+I;-|u!{B38NZ-lO)K#v zyfPl?Ka-LLbQjR&_K<<#+#+mEdCzGwXmi#cj=JO?5je~C39>I7L&)i%TdOP5-^I^km+I)ZGn$0-9?js{kK>Z<4Zfy()E!Af_R8hU8-0c)AvycLf*gwQ_6C8RsGe?xbiw%>uN70gVG~0^t5Rp(%I)v3;+LN;7 z3yzSjO9WMN%%-^6v5=Puuu9)|yf)w5EBU_XCE{r5C@G-`9K~!E3nlqcrQ*FIBbHkP zVTBSXajdh6>`OloTArE`rA`Rnm1BZfC7G;JL~rh>>i*)5aWb;iKJugGy3ow~_Z<9P zjn8g3i;+%K95ZRIsdGE*M)Ai<*VSw{s!j8VKZHFJnnfChf?m2>MGCcbA_> zP`Txi@=qRBP^}$r^qe&NG4;qGXEwVswYh4+{HLUGc~+Z@jyc6aqr(ilx)C@;OSyiYG_eDp1aGH5k?l@8G-clA;42AH8 zk2U;Je-2zw7GJLRO?bhwdtGd#YV7tKYTjwM->td?(fDB45;ac((gYUC&(wj@gT7l^rwGsrxCZ?;Zp$+Rw`kw zfjb}93=3zleS_ce95rtXf`MxBF<-~lRjuOt7};{U8MS-oF^{fo^=UxR?TT`Hiku{ z%I%NgGd+AQWP#!4#5G$*8=JP0xny7bBCSnok2JK1Df(YDwh>eWIu&Y}qeXRMS+eAXx=bJ;J!e-f}HP6-XpP-wpu{&7P^L zv6H^OU?JQt+R8Q&pn>}nkir8>8hm#*zP=DRxVWE#gM+)q$E~^-si~-l=;_0spWOlj z1EWUwnwp!D2?!?c&sM9es$3>aMSuyMKR;L5?TDYAo|>7N5pi=TkBmsiNs~J{IsFh9 zx4+!%KIlMfbIFn`SBs5}6*V!T2oDdxy}SFYZ)oTj8VU~w2iMo%&wtaFolVT3)57*} zx78ce3GxUH4K1#${Fu0UVK6i_%quL6&CFDgk%2c<_~#c95#i$M8XXtsUs-tp%KSJg z%!JT4H60uX$31BHB`y8+?(Pn>gGWd>S)tR~;h5Ih?1jmwo3?uXH2{K)d1K^s+ zr>E$oBreW{jlKQx)V%!s>7}Kir6nv13X1?>ia~&Lf-BY4M`_Jsy*uZ$sRi#(-SQB-1%*6^F$gYiz%)fs>JwHD`-p(ovPflj8 zo&zTdA91%~;q7sJ!;&8ZwD@1&-2Ab${86q3m{C+x687cc;$uN${`D?(EpZ}Ka1yw4 z#nO3ye}CKEq3DZx-P+ZqzCM4QR;O`KMp9D0fdTPddv0A_T{1GVD&x@vn{)|f6_re! z7mLLTyVplMz%TX(z#ALh-FMP*a`{C?!3_-@pR~2LgTumJbwPp3#k>F643w@EfCGtQyv&669=H2niaQjOQCUli*ZKTE z^OKSJpRG1By2!po4KC`r>t^t)ziwl8CTVp#Z+K!_I=9yRe_Q}u+*F%%!;+Gc{r#@x zx8A-!C`?Sup5ET&dW%KY6LxPcLT-Db^OxF1vYUg$r^s|~JP#FjcV56lJj?~_Yimh~ zi2nBV^?jL)tzF~>{<^!}ANq-moE$i*+qvp%&x(*w1pID&&7cD+TH4&oN}F@8@W@Eh z(FA(<^W2-k{h53jg>hjF3=GiZhrrFUARf>*=cWIDY@722vhDXfK--+4{eNw9s8bv3 z8?;jt(PKa6>sFG7Rt^ux#+UH%h}h5;D!wo>YP7lRU#Y0D3OCHmB&Rkt){ldYbn|_e zUn1T~p;iV~uK%>BNdJ0vtigeH(LWWh4B=NBV8N4hz>>@_VkeqU%(f{DQvEvXDJqK~ zn^SxH;{c_nW?rf6*Ph4_ifv4z-!+Hmmqsap#epXg(7@^IuTIWj{?=Dpc2*%4wtpR8 zRZ&PC!u0=4hdY(|tRBoZJr7%rXpT+)Anf@#L`GTELeBTbwCexK@YWm!kB$1RIdJP? zpMm3COZYDVosVg*n%R`>E%T#U@H8B@#;ReRq))jLqp}q~Ql)9^wbz&Bex5m6HRRi8 z3=-5=+xVhtTzqk#IJ@$1$y;m#CQLKB!t=!nRGqe=Il}Hdy?WiQ8y1!k)%u}dmYnvP zk{<*XK{6ePb>%C478aJvTe+e%*#1X2G!r^oJum%n9Jq$xTa$m<5E7B}d{uy>n-2fm z0_)go#o*zUxO<{ZFaiN9v(lAK`rfxtlrD%62pYRaiR+70~@Hn-j2shP# zR{NV*8+MiUk(bw&RCh&Wo*ub{hce1wv!wq4P{&4&A3-}T_Pbh__eck((+M|#{yHij z;}k{{=RXZ+*eTiHQ??l$X_HObD^kajK$1z9f`le6R|y(QgU%x@=UkYRPiUhkP9Pke z2a>f+)_5spIGVq5KNmY-i=iN1#R0*AwS*w6urvMIqOqv+r^rb#g34!i+qF9i=95#{ zS}2<*%dGOi(@C1g?OV$%dfz@ni~TPvs$ILjJ{*g{BqB-Cs*}neI*$V6uH0$vW(q#T z0+#CJSIV~}_m2!{zB8X6vKTXY4{o@;IwDus7?%1etM0<7PX9Vih_Jtt_2u&`i_uGD0QyDn7t91;4G=#i5vH58^4AE=xJB>p_?lk->S5agUx}{sDv~xYL8_~)U^ES}cXXJc#KZngL zUb`|E#;#J?G#X0vh;zJI;)kq1)8(X0KeH%zB$4e=9R9&sZYY4Wuz_T_dyeMBlZo<1 z6AWi28Yn?J_w4B{lSwO^+NrT;<(VXN8UW_^aM7{gebT{?WUY+7mf~m}`5ETkS9^U) zYq``B_Q})M#r*T2k0zU3zqUtb%q(W1S?wk1tr-Nbo~~5h78&&M?{n|uVNAk>D3Cg# z>k^Jyd-TvT7H2|9p$3b9FCO=fCfxG?O_(g(EjxzN-SS|ZE<>KnNcj69=Ox%ZxDS>T zC9M0@jwhF!(4M<7aMp^pSkED9Gl^?m(`Hz+@Qb)-Q%Lm52P6CPViUME&i+8X`fDm& z-I+FG0V9r?MQe|$4o+gF;O;Dm1kSe|xaFFZMO`PuHIg^e#s?vGRl>rOreMK&UR#|8 z{DZ$xUO1+M1Q$|yalLPrGZPzoJG3b0@~+#R#7Uk(kZ_<{Vej84?absnA$>o#OK6-}z-0w_dML`tT7+7jP1ad9ga)k^2uii7J1I=ROF_qUxER@yMWr zIchZS&t4v3qOH-G*fz7*$W8MR=*adq51OTtyI4n%9iQ25Cs;7g#Fs22T?SE)Wx0Fz6e_h z-nKM3=9q5Z*24SYK?vpH#;`;v2iC(W=E@%mm>}#!Y$G?fly!;tFwTv<+&uzp z=RLGn1hN9HtX|yQ&q;Iuu?%F20#;yvMt&rVwFc_X`z^(K7?m?}I&cxWxq_yonX|d%1XD zE%IccD7Hbjj=vjQP>sG3%p3$Tm@a4)rZz9Os6MydW&CdQ4$kf{C@6@#WlLn8whtW~ zM=%1jX4!Im2X#UsoxS=a@qM;RYW5(7&n{pe%kVJ)@1(ZShoI)O+0Ef04U;R`Pw#R8dS3_Dn(lc4v3fX^9&LL(VS~Z8x0%mKzL^ zF+k4-EO=KzmB`!i7KU}IE=8BG4qdaSy0HGC=H-WBKI|CMzc-!$W9?ebeuYjfGwn@K zjIh?ZCBxH@alfZmepi+^S!atS5Ps}z2`D=Aq5BwMXM~Si?TJixLmwUpF`Vi?oA&aP+m zix?i6m~eIJ0-h;)K)eTvE;)dMh21<|t_2XlxTiw7TCLG=OtYDsm)E;9bTDtb8v9r0kNmG z)?}d~6_?{NTC3ApPHAZ-Gv58h#^i7;WhU-6H6!D};dCzOWk}?=q2beEZe#{7 zguSCdt|Tg2I10pTu7UK6nk-XYA}mA_8x#F9a3-ytmd684K%i>?EDnIl}Yh{!K2j zwxdHp*L5%cU?Q~^)H~_@4)S_g-C$_yeE<=1U(mFx}bN4;a~(k7p2$6(Pg z7RJVRX=zQ*Kg`UZjqDT0puo@1`bRS#TRsi<5GxfrIk(s7H8h0EjJ4TPhW=1Y^QnZp zin%}Kh~_y(shvek&WHaUx3_Vlo`VTK$S4Gyy< zA)bjAqkt|Fj~l8(aX9obf-nrVo10CaGd)lQ{*Lm}&&KykZ;( zx(^+E2`p;&3wCAw*EcRe7yFl+NKb#wL6aUQ9s^%FYBXAUe#l{*NmsOYel?AEW9*Iw z&Ky(Sw*lsRojLac4uVN;>>;Ue090`X2BZqM;o5lJf%cZtGX6O=zS+%6$WEZBWkkL4 zC`#4YgfYv5XT<@UH@+FX+~%P?*B)R4k|F-Y|_lUfQlu~?*T4cG#set&B8|ClQ zE}2#M^h9j>(JhAsrovP{?7C2c*#gCN$*S(PJj^&_zLBA=(`NCCxZXTJRv#@$*a+J} zXnd1iRN#dh4i%#9*P}Y&;*EROtnQ+%+|zy~R_8`mO?Cd=E*p`I$0zhC^o)MwB{>Yk zOUP>&U*6G0=?~~r=FclU9m5Hy4O11Zl57rf&<7`y%uLfveemzqUaX*Va_XKWtIz_b zVwtV2_{e6pqO6_or~m z-g1{Z*TVgnoixVQjhgr|aXPY^a(s|*b%3|XW<5(-BMJS|t`(d6-%rx|e>)0J!0$Kz zO`}1mYZu#Gm)r&${GLx;=z zVqi<=4doHVN}G5A5-77p(|_t^X(^L&u#G&jQhnAD3koO>&o6SEn<69D3Cu@IU9}&g z>;iC~yI(HX?UU}RLt*Qoklx_3kk5qZIb&(1_yvV#<46hI)oP!{VSTM+nP9#pLsKXz ztmR+dBnxRBEM$O^ApRYWwYT-ZYmR{dyr!KqpPf;NfQG}~pU zxSo4GYRTZ`7P)Q0dP~|^bv$2gsck6rH!q^N#3C-<_}%-BBpQYmVeDDw4B3n)cw&n{AR^C+&cg|PsaV92#Dy8HgOJ9Vf4VQDSPly~<6}VcXIX7dk89sJo({ zlq!TbKcga*HhZ+Cj3!bZF+Y%8)`yc3ToTJphrUY^JSc;>V`oOfq4{@pt^Fy!RLyK) zmr|pf>`3oQDrJkBWQlHQj3`<_o-H5Mse<=1Cc>>d`RNpvB!0(nr-F?kn2IBt8 z6xR07bIbT-RD3C%YN<8rJIfFw4i}KXgAf}yBU^DxpKm!_ssT-2y{y$8VXS|h0|-t! z6dcbqr_GNQ#xt-{Eg-jXBrQ6%R!uD5E_bP`!+`}A9L3lP*|=}Ei&}4_Cu^avdR95$_m0@haND*q6&1;R*}C`Z!{~y zHXb5IETykRt~NzruGq}S7FBkN3ACVW*5wrMSZ1K`MMCXd_jzN0T;fQueNku}9yJ%k z*&CZ#RA(-qyE4J>_QXPA^W4Q1rH_coFdbD@B+4PIxavh$; z)7VPK;X0r08#&|`LS>EBG4_R-<97-#pUL6u$laX3Q1bGR&H=9{N=2dhK9`Rw%O9?F3<`u%t1dW2#54Z^pHAhTbbv8 z^|)C(I|tJ};VEbvA15%@58*unkOKFd(zIi-Jv1X!aONx4dpxwo9)tou+0dj@n+ zsjDxd1mic4UOVSs(*Bh&0tD6?nmF5*hW^nR-yoaOJo%|F$tWnFycTT_>&)2A=VqnZ zN~9=)p0RK;vTSVQ)+ekB1|$yuG!J&|*tfW~P+wFPNTCOdnvtY71k~EJBhZcw{MF>C zwTS_8K^2$^%=;)4BblcpUZ&p##92XoU}E-VM95!ZYI}C~=DemQWq;zEQE>Lh60juF z%EFZ*X`)LU52qx8P)KW;$zpT~zzkUw<$nhT-DF*CdhG_4NH|+i&A+VwJNUBF!8{j} ze79hxYF1#f;QqTPGCLa1?M347Hf z@J6a%X;mxec|rnA+tF?MAluZ9A**(-?;QpcB)Y4C_04ymAbhd5`PJ@=*t{~^=h7>| zlpjW57O;^%($Ic-sH;7LS_C2s^OUH!06fxEbp9*x*p@av$=~$V>Gj$@!^-V zev2Ce4lB(b92whpn=dOpnNTYbR~%534u`Cuv#b>5oS$;c>;hevU9ga(u@3dl*?71H zRkg_(LHW1Njf!i3ew+n!4iLbVt>N`&j7O9?atHwvdDZTRsjnvz6`8k3=33ORRytE* z_4rA~yUep|486JQOcYfVhhdtbjS!&>I%y&jA6}~6`>`na^;nYb&`p6IKqmmOVSy=v zVrAQ61x96$Z(?X4+$=sb>L9zsi&{0Fxe1G8*}0d}NP0mN85-Km*%3Twy$Z}_qb!3@ zZr*off2sEPPkWY8x;!JKJUK6h{nHvix?S^0dZ|uc({_P>JKfg zRq&4YL+i#>C7`aM(Eji$q$MH(fsKv*$v-Fv6&E*Dvz!7*Rj;h9G#|79(f;eK;M*+g z$(7DkvEbX0!t1H2VCst|L*mZCK~O-z7wP<%l@-l_fq{Lm^TR_)IXMIj486q0kEhI! z7^zmZ2}94Wb2!m1q0t%2*DH* z5~AJV;p$T?&eDk2r41e)A4iaokN^nU8ULV%_w4`u`-c(MiH3$26%}z64DO|WnU44HMzuC9x+!>6V z?0?^fSpkrO0#M~Jug5_}MTLNXP^5`hpbyn%pk!r@1wvURJ-tZa7b2oh0V2Z2#(OG; z|3fPOX}?X<$(Wnd03`r#^S9U6*Q)C3?DFz(z!c3FS{fQr(b2*{ErPZ3rtxcCeO=vm zEG#Zg%%!EJ?*s%9;o%6PqN2M82ZHEjypG3n-n1m_-V^^KBPn@#aqBh1fm#mGyP1@f zqzD|DiOD_~!^9(+T?cn_Q#{95+x6 zVdLOXR#jzdYzJ;>Xmr$_Vur)}Edrl+;A&?uGlcE!SiRGYg5%N3q_H|Z9Ut%yRW-F7 zMJh>Y>7LQiP(bH|LAQ;o@eHU$4ULSr0sk#%@3=dJtgNh@v7-JN5uc|I2#h{s;o=(3 z7RV{|Zvs#hFtlj7njov``9^1Et?48~6Jnu4=KfT+sKPix?aj{XVn|q6ntSKP*Se>t zCw^2}6)Lpb`}+y2L>mIrn@JT zkBg7zcWh&Duzt*rsO-FNJ3T)BD)gUACvo%eOyIi%>vC~%ePZ=le0+TTGWn%;)$yGN z@EM?PbFg21e}CT$nmN6OP!L-+5w+YvH+$Ky#zjE^2*#KInETJ=tvGon0hN~tF<9@X zQN0+zuv1f0;CrAzm&E(<@p>Sb$$R0Uo>g918Cg_RR5(!xpmYE{GqbV%@0eVYfzwD& zf17i4@^Wx+;)8^MU}9$e&n*B4X;#b$34t>bCL0%7-HyTD2rOweZA&D0UpIp+k|{9NDh=eCmlq9+NCcgFd!SIM)YN zR!+==qgEN%CB)=zFZvOUY-XO)?Bj0DP**3Uj){fi8$Ul*V^+`V)94)x7+1hbU74!c z-mmOM6wG;(wK0Z_OUf-1&YpxdtdwhaOs;{ ztAJRc?{F)VqWsxBM9ge!vxoXfT{wETlDv!i((j@fVnQW=SSAjEk_?sXLr`)>Jdi?z zb>t%3m_gevk87)0n;t&xRObBYq=Jv)`n@N-5W)(V3&&b&<|||#%3mqyk%^h;XXdAV zD{b|@+4ko`f9r4iil6*1Vb488K>O_Si^+Ck9rz(1)=vEl`$J#p)!dK_s)7e(n$w!V z6a6^UxfmEw5+Jn~eJ z4s0{ryvn1MHlbDXZ!zm6W_nO3Yh4Qbe_J*UM;J4RZ{FFQ@tlZ5c*KnW(SCgWr#7kp z`9e`&M6wMQOn`iW4{40#NiXNncsI2)BQsbP!<-&B{D&RdEZU56YN!xPJ>vRtoqxpw z2Wt@|jM0SDNFNjusw11k?s6OnDQ5;_J}g_Y+rtUu2Z0=+I6U+U9TuWs@JV-XnT~~Y z97LHW>!0RFfn{#v-9v~YSTFd8Lj+65050CCSWkX8R*6a+tWTO|LrnvB4>wfB2~6k- z!3WcCWueu^^=*h&ckC5uLzH_f-`6YkoR%g3m3wX3asSg=WTHhsUHQMUD|*`Wp(V`Wq73nsYhk%Lvl#x{Qy zq>el_P5Vs-kzCsSy!5WL?v|OEIFeEEh_RT+*^I|~DkfCAKl|qKMBHCksm!+}Zt7ER`Kv2#A2KE z6xs1S3YFouSl8baDf8?Dp6Y1d(N&?KkkO)agq+M8bUOt#tAw>{WRH{i4oZ$u4qGo? z$~r;vT6e7?#$zBBeR>OsUiy+rqpLGh^`W*BQzo|PBuq6XQz^1+42tHdHy#IwpSSbq zpwn3kJpQbLeug-yN(Q5?6-AV|dMX@wmAVH!t;j~Z#{`IFF4KaETXL!{xSyQ_&6+`$ zRDmP;Lvi-dt(r&WLxrWq(G;UhD{m@rDb4-?vv|on&<*v2hr_S_y_glXx%4T@m8K!d zJbsJY73|996J;tG4Fp}eLn%EZgtg9;phqKYxoQ&_Lm`{~ z#P`f4tGKuZAPsvNF43k|3hn7iSEAQ8&&8@dyFSWGZ`C(5lwoc7<*}x}hXyTq*M#9O z;tyY72Srw*)>16*?EDUKQjF9!{FM8R%*`ml%}APFCw!g_b9dHGJ#>Kb%W7U>ath95 zoj$BYs93+i9Jd~b>w|%J9#nj-D}QXM?uG0Qb1-6m@9mIU%gqCx%}ILdEZF>Qnf0EV zK9@#Q$moQvHrXzzQ58tdu5~oYJ)*9DwmhHg`_{MI7R3``TFCvI70n{U2#ZyD%E{O0 z_yTTa!Cxrn;E=geY*9zSS%v@ZXT9n?IKO;QNalhFx*6FB+5wvSSs1e2**dqFKC8Yp zQiR0pT2ly|*3ZYf78H+~r$PN}iC3-g|8W8It77&`f1&N7gU&~+q;c85X|!aka2pur zcdhj!TUcmWTH;@QgYBQ_4f^D5^QuE{Tm31(==)*8fi;JEL+0jdg$x?lTnu$nG_^j4 zm$NeWY+j$+82dbwBf5bjr0!D^S@Q-P^iF&GzHRUV>y(o0OFb=^%R3-6;AdPh`rL_X zk!9JXt#kLv0Al_Kj;XVE86Mx|{T-=G8}ANSwTYH|!wRPGL}XT1&Qu4z(Pn;nsUp8a zMW(X*Z(mRFf<9C_l$8W&-~x&pPfGLpZr^wZEME?0ObeY)Jv=yxjn0gBv{4Jh?fFYa zZ&NiVQ%`v0+DzoT<%A+R|e z7G2EEM1DpSzlA0h$2VI!*SBnyS9hoFmz#(~k{{r-7AOv-tg`Or>ao1&kMH1}dZo7t zD11C%X6Ln*HJYM~|EVBn3e*5!Rnezh1AQUYm!7Q{xt$@dWTZEX!$atjc75rISaG7V z0^c!KN@&e0Y_e-w0s<$z+|JAUF|eW#%lrNK=hmq5JDS3DlNoCc3t_b%A&TMolh41s zdxm3GzWU{iQKHxVIYbCHy{;{l`h_i)NAAM>x2-Vn{Mnpl#CmoLtN^r`AciB-37O6r zvJFi+I%nB5ck4?a>^aj@n&3Reu#mqIOJZ~k z_#=!a<3KQDY*KZ0#vsjt@Kr@?4j&R!`Hp7 z-L5m_wVrc0?+JkK@+?IiOg7WE;3K<+*IQC>}O?Y*wZh9 zDp*Yq+cp+q-rfq_HMK-FlBC8sjQ>gXFhnO!oH{z%?m(yU!7WybdbS^d0LIcJqURtH zlob+-;Xs%H@r2p0(Oe_4&bKq0pnOdr8aDZOedLok5G27Be*53APyf zVx^DLWVznvs*%Rt2V7KNcRMNHvKWX7;+Gcq`RkVy03)hwO@KK2^+>_nEvpSEtQ>@M zu47>oc>vJr^*XT=uVX;FWq*5H1XwX?hRUVs+o=?DVjvLt3OpZ@>UurxAy1y1p6<3k ztmB@;FiF{wkdTN6q(n2ba&RQjYc+&@M+V~3YU?$gl$4ZDv1k^P8T_OIi-5q7i_2q` z10@a3KR^occb}*AdfRY;Tx#IUwgC$E%{xS_>TzzQ01h#1Sy|a`0H!V$K_&qK!QA|O zxEbV)lh@5S=hLPi(txD`D0$T^B-T|6sUE;fAMRdvrFsZ59wnuvQu6Wy7;wd^G|w+f}Y^E#NtQ`TgVLn~&S%RC8nWUID zTo2NbJ>R&-Ua*Mh=)!>VR9KQqdU`tDuNtE!OQ5Q?ySp1k)!DpjUStWl$v$wfT>}Gw zz?hgSkEiP`I|G6bfFJkY7fJLH)oYIb&p|vN*0z>-5`t@MYGME!ven_SpKSUFSUPa9 zMzehX<2Cc6_vNBfa2phfQil+~(cd57yzUxQR76#w*D0@}GF$a}4j2)r+93)$mo;rH zFAv*zzi4sTtn=|zNQ80=KJB7%Sgk-M?dlFj5)vjvh1ZLJ2EbSNVP>Ye*BjQ!b!;Dc zy1c}H-jT#WO&#)|P^OPvdVD-PU5&?53yWJgjs@WjmGJ6#Drb@X3KS2S_!JtgRylrG&aAAA{6nV=JouxbfdyE+ zcZZvZNM9q1Q*ErYveFcISbEQ%sHnF)=|!d}9z&3QIedhOzQaO6{NH}Ov%?CnP7)HE zy(E)DSwU2PdVA!Po+_B_-pry-eu>H&@981?6Duvph?QJwCkf^tQ;i)4Xks}z`tKgF zNQBh7wA4Oe?bx)leYx3ohnAPg7)e=gT)fwZ?{#-`#!Bv+78M10o0g@l@xp(W#K>b0 zO~q;!i3H9QZn5jw(2Qo%nuAWh>>1sPDe`*p$6}Nj^*WfU1xi)NtjmP0I6)pqD0yA6 zwbq>5-!{;)YnqA-tRiC@h1M%aSPKR9*;X==iRamqVmaPA)=jO>gpDzLpWlrS3zeoI z&&tGlqvl~St$s>XYru5P2?H3Va#v-Us9{JH)lp+@nnZ><>2?rmpBCE4?ybH)wQfCzc(EF^2lzU>0}CqrKdBV z{AGd^Y)>nY0^S*aXV(4u!YrK-IlDvD`b93Wh%05-l=67leO#z@CS`~^0}6)6;7^yT zQ*QC8cnET_>_6c`vDxY10)_B(;w0fpC=bd>65^iNVuDTUH=|r*|EzN6G?B%^L_Qwa15Th?p7k8=P=(H8yN|=G-7$185s5PTmSuJEtdkBi$*u5mu{SH?$#4rgJ+n= zJmUR}cYbZbM9Uk-XCaxHR<#C)W)hNu1|3IU+NyOL(x@2=kqPysVD*1GD@-}vb^2vl zt?&!4vh9Bn&Z|iFIW6Bkdr43+=K0!|K$>~?b=J^RV+%eTG56#ZOC?4Z(ywuv6H_tD zH9;oP8dQ-Nq*>1X)kd%^z1^;%s&8-^Lcv=mu0(ewv_jeQo@HET;@gk%0r#iTF-a%N zZsZ=Xs;o0?hz!?=T_Y_M8U(I6fE9mK7Md)3Q3UL!%bS{Il`J*UAoJl-&1E-1iyBS;K!=3{DbaYYZ@A@yH$x z7|c!}X_%eBn`7!vr>o22#+{tPr6^LK{2^TGxOku9I|v=tic-y+RFtF*PRP0OswJnU)Ms8)7yN!wAkA!BNyi$#ChYJzHPI!HRJ zLjHB#VI8!I_!p+^MocQQ?bkN4Cm0T}^-#22i;Ey^@uTBCZ8Nk+VpWIWPv&gM8~NJ6 zjITN=x9vg1&%oW%dnI?p!%JQUx#WMQl_JF&DdtY?&zNM0PA)VgB8xseP>Zf{K*^@T z3Tn}iTCEk;>d(%ilHH^|r z_Z}ElH}v8t8J#s4{DVZ8BsOdDmUU@8SUy+m1kcAB?9j7q!a}RQOXa4eHCD8u!G(NyWt8Le&}-?-|Q zDu}h@sb(lMwFK?AslwLY&knMe<*P3Fq9c~Li!C<;=2ROuy8$l3jbV_hX9fHygnLw7 zW&!2Prxyi`+J_bdSNwCX)>US5FrqUhI&?Te?!qTYrr$qkSbgXI7F5DGs_;YSl8=-&&|aF-qzm z(MCg!*i5y(5rW6s2GX$W3myx&|W#$# zsAqQ^51mO*T|Zy!;c$v1d>I{?{;AlkJ+7k#WPGEwqS8-MD-}xP_&W#Z;-mkEwr`4# zGk&*j!^Vwm+qUhbNn@k2t%({pHrlAM%_fa)JDJ$__x69*S>OFR>)g!MJNjiZv!DHJ zoXk(o&qb;31!_*Zo`@B(y8%vA$yT%-m{=^Gyr`TM7mO30KP~#HgToH_eM{I4!O&QK z+>R=DQ~QY$KHWOo;0iOlcEKpWZtq!x=~aD`$wt!yyZnmAgri#cZ#L&Zsg#n92R@_V zw+tOV+({W+l^DxOzK~1Rh|w%`akX-ObwN!UFE!yDRK;^fo$DD|;ao*2cix2++mh5) zQV+GQ9m}X=9%79zXN!l=j)#n58_rQLEAUL~NRqgGsnFKyOVyLXvUlR3M)s3ehH&-N zFf&7X*{{5zj`Hf!I5}!-b1DJR{HaRS^!X{`O<65V`=G8|!bI`Y>L#^3;@RMJ+pLio zlBt=EIVFc{LW-2L-yn6z+ypt>a_%kU%_`6UiYR%;8QPhFVll(BKsvU)Oa4p_ObNam zHm1;t*qcxG;69sd{Gn z<2vq^Jd;NP*{#KPbi zdQq&E@R`cI6fFzG)KyCvwccX-hf7RXE{Ah77ver`o!8xxRZiqlZ|B~JQ%jUupO8Gp z_?W1y@6{#Y^DY{Md}G)H$4mNVd5Xq;e`#|~U8EEgFS=yY!PwP~*7L!4cq|NMreEG0M^bH2<-=v&b$u zJ1bZ|U+*jKeVj=*{Mr0Y82kqqC`^r+VwdWz(TM|IE-!rI65=JKrBO!m;Sms|Wm-pB zyX*m+TMk$Z9y+E#jZfzQ2z@iYD0WddE))k1QWZ(9?c8`vXB;)7z8GQyG2#ZNi#@n0E2+i_z zqwD?WYoS`nzcqvi1MKANtb~Y2cl9WcwC)gc0S5Se0Ea@DBCLk-c;C=iTU!Upe!jh3 zFhuF%)|uo=F@u+qYwxC@93C9>-1LHkgaqjG>7^xJi}bN)dQQ&d-f)z-uNDnDiY6x8 z7oPa?BKM|n%LIgk;Ug- z>haN$luQMnoWg9hUAkI){_t<@)&6?7VmfXE>|)~LCLCXhxvIh|6_u2zn3+)m|6y~Z zKcI8XF6zGaI6?vf8YU)xkojP5Hd0{B>zsN#*!&NX=D#@ z-o)WBgVQF6f#FY6bMBLD&Lbb2_gVTiptFhx5W3~Vy)@i%*l==c>iuNHe_$@_K}FO0 zHZ!n}5MOx!PK7w7z5{q||3*PPmrf!c$3VbHBFKdt7rP`p_wvL#zegQG54H&n4~GRL zZl?3rH`-Sh7kM=`PSK|q_t^F6RZDRRt{H~h^Fo{9@XLTrNJ31k$8_J?(vte$IqewJ zgrzm9YiM9VLqo^eDdXeg^YQU@)(xI_asFRn?KFgC9bH8bS7=XCz*J99lH=O+bW)SQ z(FboI#i2Dfz8Ow&u}0GP3?)nNp}nGjj&_Bi6?8Nbq4gxsH7gEE+p3Zvc1s1gU58Z` zN`DV`m}8%zH>9xVy_Y7``Z+U|j(c@@wrk$}hyp$^rx@0lr5nX)-A-p#(LGEswov}2 z0*oQ1u8R^Uari-BdB)*@%Ox^T*_r;*SD0Js-|dcJr^T7PzB9=%q15rJ_J0+f`cx?g z^5#iqj#+X3(8QZ?42zVC{QN+e1CumUsiIsE@FTu8Spx6_= zL3u9k*jfJV-ySLufNYvR9C{78PQ6;1$C3IuG83Y#h>KMp(;3y6ADeR>P<(Zzs>IQf zc>E+VUsLv#w>N{5iBKEMw%BR|ITp*+d7LY`^C3ndF1P#1DDC9iydC1uH}4<|4#H3~ zd)~1UeM}82KPTOEscm|Mi2E<7AGGJelWu3{dcza!aLX@-ecayTi3rOn&^5;Manx3I z+HZWUHpQ&mpUB)8ah!$oFE)u{QxTolS&{5|Mn*I6{?7dQ4CeUKLChKq%g?Hj`|Ebu zNhym*`3Z?Ib!83L@uElASK#dlnSDk&K1! zxjTP2s6S~5=uBemm;@8Xq1M~6z%3_eNa^7zsd!k?u8$+gu+3c#UOeXzIqP_retRa!$^@ZSBscB}HCw%lKkdFD-)vK-mLyuVeJ|6 zg8jzN`r4H79HDP#H`BgN*rDX3`sy%NFdN zzBGJ?e@F6^IcKY~Ll9bqcV^gk>AQyRK?7+M&nu~nP+oBvg8$~w!H5yS`LMH_)d znW=Z|P)SwM2pH(dkG5*}ly_r8%AEyvW@R9{00YslGq~j*qR;gWkjXci`a2gX+diO1 z$6p3t2e%u3Qqb6_uJS5QHCaBsXrqVQ53_iCq4AS{-@LTfwr=mGh*#c{*+X~4np8*8HVJiC@J5YbUFzKiWCu1cmBS~nEj)Mry^}p; zTvmR53`kH{>w^PNe!ikZRn3R8lY%_3`Pr0II+{oz?3HZF%ZSlLqv{R2gNqT{6ovUy zX#62usb{$lU)K$;^y+jrbPeQW#gNG~0Nrmc zIZ3bc?`asH+|ki*AS*;#P{u6^#BZ0f7#l@qq69yqUYx+!OKeEVgFAN4ZZQH$_?w>D z@o|%tEp9(vbx|}^@dMTlx#MLG_1}%yz{yYL1dvY2H(LunsN#N1mIyFB8n_a<_qJfh zoZ)M0B8A3tXgRA_8KbgGpD4oB9;?(=SINR*zJiX~yVyH?qNprtysQA+D}>4UGVk+}s1@ z7tHb@(-_75Cfs<=Aaz?oIC9%1O)!}wzNNfOAf*3KRP80`O{&8lEk7c~F>@vCBOW!v z$aM#*k`i=J(y>$){wN@;5C(6u0VDqME0(l}mP^#7r|>(+rLv+0FurBgzR4OJvm3fm zI?Wu@S}4bC#z;_Z*%uYu!6;&f9nI8ZXK((EaLHnta%>sP7JBxvaWeWeF6Yzlql1oT z9@QbveTrR6v*wggtBa;Xp0ZPKfj)!n#X5ot(G{0x=Zlt@t2+WJG^Wt8uC^X2dU+64 zA|Bs6c;q{ZK9hkUce-(-o?J-yaq-!9t;g}l$OZA>K*z&7}5 zdpV*!_Tj}QXT~u3UWuxL3{)g7bg6?uVWM467Bj4O#ZH<`SXZ9MgWIu=dr;d}E9^G& z<)|PM7t&!stWOJ|!v|bNX(5oW__A|!G~C_You*bj z1xyj3;NX(VN`Df6+qKr@7<_IB(-A0XQ>Ivazt@8_-?ta9BIVq-;O%xV;x53?@bXX8 zbkG1s`!i*Z&uH~;bAZofi*qdm?y0Sju#Usi1%rCer zHv%~B$wLzVKkx=tGnUujG2pLx-GjjV&l|E8zxU5=($H}G^EnBa2H7{H1>`;~PEK}* z6Z?M$9>Unz7^Qv;1+)J3pM#qiP|HEO7%_yI74P)N?3^}jfK$6(_P#G}ou4avc|D5v z+5FonIXOA~0UYanQP{%Hw(l#XP%r{qc89;Me=gr{!<#zu(*upwqQ@`FY|? z)3o4}6wT)-($0;jgl6XcoOW=S7uP*L=-qrfEVgQQ z3>t&wU-aw6ZWw?9Gs2nmkr4~nVOV9%%D}oF#K0i3QA(9ivLVpho@y-W1XaXPsui+J z1tY>*6FSSHj_osD%oS4-jMQ}F@W$*KGFe#bdG#+mrI@8dYOEb7&Y`_;hIZ zJ9v!1J9nxzY;G5!`{8_OJ4o|Mm)MMJFW+{pktzJ0i%68M!iCrG&UX7x#ngbxj*pQ@ zm8a{0p~hw>q86lb^Sc@D2!bv)d;i+5iB~mGOxPb{W`T;uPl=}zXfGhl*2bwv#G^c* zgul@?`dQzzJPzbcP|nYPkwJ9cRpU*O({kaN!o^hioEI|~U{1m2Ue=6MD_)bSwHVQwNB{}*4L?UJ! z4VuZ}HoHgW=dPjG^ZKEPu9SLWbqWPrY3ZJPXoD3q#a?dBtgm-dTbUkPt2BV&;5! z_Ad%#BJfH$Dla%7u4l(zTuf${ttx05w={ecD(&=96YgtUu7!eJQ;BJ>t`Id&Z#;Lm z#%pV#qrWXDX(X9djs8LuCL_%^rYtU(R%?6(iH52D{5$?77I89(sEB-DeO!<3u?fBY zQ88!4h87UQR7p*z27$L(?@s6~N1&x6(?w=ajB<1i2X;wd5$#@a+F-i#q?r?qe`teN z;cf73PHZU_bw*U_DyHx&RA?AfzJjKION-IoV5m4hVHuvO|4{!XD`7=lmU@@xR%5<` zsSKY<#pbfCVIbc?He8FyM3gd(oR9AASRYNKaM3T4Y==_8!D{W`m4ZG2?DM~2IJ)IY`N`$L zrl+9zXZlqsOzRxqvQEaqd8=fAGUUSWtX^5Q)G>ybLQgAY( z6c*y~74J-hdzc&^?lY59QsJ#gF-57v_?Q~twSvL{G&>bEq9JRF!oRF@`eGrsre<+Z zQj;lD>8ZVMuaX3vzl*+2qIS_5OHfO0?pXv!6(V|g1nj!6FCwn@m0eRnCR;8BbO!5l zi&;6zTAckVX>ULA`Lyh9vvnrRS7~;+6hzg@bWt!R1o|2U@wMS^oQRe@$5@Aq4<}AE z%nchtv>GN_C}$(^iO~tpZh&TM;e;tyq1*k9VMH3B*Igd|M@`3tsrKFoPMY~vy~=}( zge&Xd5Y@9)d)tI|V2u28OAKryq{qdPfYN;h;$4nb-LnOcAW@x+KF;`v{OhMW{L*+B z9Eqw<(YHpytd(>{rz-r&hRh3HAmL@iNq|i#@5voSTC=PL{gIB{wEwaP3g_I@A!^kl z{NJ~U1u`W-T9RLY4dSWH!8Y&FrhtIZb5sKr z195BvB1vH%+gsUHXNjrFi&L1Zyq(1P5^3wUy{z3nxQs#BJp%l5i++$RRhP`*)7)sB z2FnJ~iJ5pCcAdzy>Ico07B8Vx6lNaBav$VQb?n;15|%I0uKDfMRx3`*lk;1gxsUQ_ zi_MGapH}!;9OI9AaeXh{D8msn4j`ym{Okl~_Ct2Uu#WGhd<>wm!AFeU#zkUr04nB;wGd4ymjUje;%G5#9)Kt;6;R{DW&d3lgWE)xzAK$REE6NoV zRLsrhU!br?Kx}8$u(9RvD|S31&}%VCsJy>fP3=GsT}iwIhG+oUZml?UK`TIH#R1|H z{wT50P?|XOjBXhK!QH?UG3Guor9~O_qt$bAaBQBR$0-%#tEWL=HcmNdE+CG=LN|~Dl_cA>?VL~7QR~&S1XvhH0_JTB;av08g0H}0odlllM{f& z4$H~OVLi44!hxiv2T<(AuZ4&h`3PbF5IHsF#3PiRYFD2(rq}(T-@mFYV5^roLYG^R zJGu}u0Jr=Gh|2-0{l#MR`Q_9hU}ubb!`En40Eh(mk(w&4pnzzE=GzH?++M$@t#IO6 z_tRx*Id-5+Z>);gRR68gX|HYld;qJSP|!Q6zP^5IW5fU1ZryVyMtVGPAg1G-+=?AL z)S%1XFC@>Q+^bZrMCt}`8&g+SR`#mR)Yo&Y``znPDd)Th9}BaE<|$sF|IE<9+H=E(rzpGj{G@QzxM`HeH<#opNY#JiRWh4&&`~>0VbSKhbmJTR(bi7!TsS&_ zSX7sa)2AsR*D18l?~jI}|Hlnpd07Ol1Tf^h_&m|8{v^hfZq`^Q;gYXUVA*H*6ZaTYsf-v1Q@gNC! zHCksxqaS(PazBO(WeQ1>>p$MsW9IBX2-oqXPDy1-W4z&iVYR#EAUh%bpn|+_&Iy4R z9VQAh%l9;!$F5^!Y#CbEfSP=ReBhwwMVASgt55!%LEvWwF~!Ve{N)>sDBHy>@~`gi z^Pi*&aN^05<>F-#^SDhUKoU%nWXZ?~b})2oD*L`Yq4EHlL}tjf@-p-_wS@x69<8ef z@U`4@-IHo`6Zxa0uwDm4OKV$#4RvcZa<;^5zZsYzmP7=897kpHLzwe7cIN5;n~z_$ zj955ghnN|R?-C+HXcWwwy1$Qq3iB~fm7yG@lw!eQ#iNulQ=?#mLzAMa_ahKim;}pJ z9=mAwm7B|gI7d2M7dZ)v&R_NkhAK9X!8mgI3#^<>ISa)rEaVsdWSc)@5+oK7Gkm?} znQD&9@J|HD3;!6SsV|Hf-MXmDI;w0#4VJnb48HNFURODmGiTuYS8Z}rhGH74VLgCe z0L>v~o?d6f0VjJJCd5?O$E2qFNk1oi*eZ_d3eKFBoMV{`zEDGjCem@~N28A0;K_~f zFZqQNza{dk#f%HPm5`ru*uJ6o$qm(@>$M-txIM7*jOtF*f8tluSho2D9ZkA zT{enCrO$@x1uCT1zl#=${7N8aKl*_aje{sf!GG6fX{zWFRn!Kd&l}iu@Y(({j&u zZ)>8c1!ao$T3CcJ%3+io^NmzWvyECQBH`c?W@h7l21AG#sa03J-FuVYAJwB%K@tx2 z=LU)tOM~J3bdIg>XxQ;T;L$6rhaQMiPEvkc2OJzQL$*K`&EA5 zF>LygxfUBE51EKvsm+AjfCfZIvOq5YYnsp1v=^rGk9z~?Bz9uJLZiVU&SOuzY;`qfBo4)X^Kd?y-z2O{vP56=%Yfk0>>LWm&BCPEx!J@QsPaQJyXN^N=0dv{u~_pOY(ksX`$x{pH* zoiL&RyLZi0?{yzp>74f0cN*;*zQml2u^vZAbT{sU(bc}C>|)-p1$!x$Y{&>X=HO8o ztml#R6FPi@dqkWcIJY-oY3pVzE79AdM<%hon62gCE0gG87&4di?z{f^9=X zCEE!CVe5bQBeMA8Bt@MQ1h+oIX7l>(O}gdG%X__Ci@^HWdzvCf8Xqpxa4~%9)-4n% zoiZV9`cML8>VObg+QEUHVQ0B@JtH(>wY$!f8l(}aU?TAgHW+p0y!M%Ovt}iJ9e>g*rwHNk zW#NzgUF!2M#5nW5Cz|=O%U*p_$NxDW!ax8bNqN)wyPi2-%IZM5rN3u7M1!(|% z=nJ4Ps**JS>Y!zGL+9hkkChy_zmrk*rZuF&O7uhGAksd9_W~1@Nci4DelxvUg`AW*p5^pX=b?HIKDF zAOCSSyr{)nGnR5qE0G+Htbe0lKXdWjk$jI#^L!U9gABZeB=f;+k+sdCCd6-iW z=3J-cVh!|jaFd;QcWaMkk1E_bjP0M8lS7g^DR>*h)ul?Im3~mJfI&bsJ@NV&{4rk@ zf{k|iyk`IP{9SQ-LU}SJ(UdQMpErGc+1-{5{)7- z3*Pz2f}O3x{$mJKqUYMojO*LNvEoF#yAg2!iOCVte*tA2(wZFv$ypW%_Un76` zcLU_G5Ql9%cY+$hU<<(6+3f$y=jG)E?AO%|4N;;Qt%9Ya28gI3pILz*%7XIp=-OH~ zAfHhgP$Yb7crxJes?Sp_n-i)P0FdW@Q;XGr`q}+#^>NYp?aZTV2gpEyR+!HE=Xo`~ z(*o`YaF!??698;QLPCnh=eGAmj7Gb%CFU=SM~c--~zJ=<#!ZIdw@_3l0k)p#`j#uqJ=lCj{76 zyW+NijGtZ**R_`k6HsSsw{oHFjgiS^_p7}8B*>k+YU96X<+nd}T(bj!;2Lmy3f*~M zKLNp`EdDQ^Mg_ay>f6T%vX#QcoZfXq-`?H^;5+H)>EYnvA#hZcT)egq(gd-<+Z_P# zB%+-0*-O@1tTi9G$l}KK6pRKmyC?`EWBaxM)2phg+RKV1QmFPXTNALm0`iQwB!jo4 z>*E3K)Gix6Ttxsy0Ddw!^Zi0ykWqr+dtLuwgd1Qdv|Q-%fD{OB0e}oe6EM{Hwnp8{9lNA zp+Esh0Q|fL;HN+MlW3+0gNU#Y@YCKem6$g+1os~sq{V39pp2svE2Y}RNH7SZ*`IKD zM9~YcLFeF$Kh8&K^4`H*vw*Iux4jP)DvlO+w$`duVH!@ zTZrE~pzLzvbDaRvDf334(xd_^m3HFa!>f4p9@lG1EX z3OwOx8qfVO*cM1PyTI&Zb?k+l{Vji<3v^kQl5jVTn2`17Imr2-TSeNzOOSi`mIHaw zc<)$IB!pgQ9*yBZT;CL5jFM*sfedp7?dJJ9=m5P=#eQ^fp zmuSZA8INKliNK#!7TD^dh!pyP!PleDOW2ve9V2?b4Y^QMDv>NfQbjLmcpP+mRWkRY z9`oi;`ncnSaQkOO4a8{ldo+)KAANjJNNTeG!=$)}8`D?a3CA-P(rm0(CL_ST2eN5w2_>g?rBd4f)9z)zlp8(&l+5vyLe=j+zFdb@>QAq!yX#yWbQz+rY+Rb zV>hWA1y^6FV}j?kAL0f$N3pSOXzv2A;G{=Tu1|F)(gT}ifG zq9v2FqtuQbLN_ad8%eGqf2Txu^GCtco~g_qbpnxpsiUO`_GuCsE3wOlzr`?z zv}!)6GUWEb!887l{UpsEatEd?&zL!e*Ya_HNa;>P!D!Nf$Xb5e)6JS>E8hhQzb)^M z#ZN1)ZpRAA5aU_JSU9|SHr-YaeUQu$5`OrAX>@aQ-i3ho+7DnrJ{hnFhi0OsgH1xw z$E=R%XeVs)YGuRL=|9DVI8rs!J9?5-Z}fW}>9gGt?e?NsPG{%#+B~VZ3#~*g6zLe} zzr-GcML2Kte(mWn85*3KDAz=;Ea-eXwI(wL5uaVFImzoPXrz&U49spNvRhwRZLN-@ z-{V|OfORPm&alyB($@A&6rj$SqkqxHIP`Wfz~3DBT)z~Gb}Pmfm7A`RRfvem$ze{g z+tX-jw(p_J&IA{p%*^7qBmw3T-Ndm$TIOq&qyODrQKY&3T~meS>`#uTP9UcdjiAJH zA7j=Vpt)7d>MLUx{K_jDuHg*3eBDw_9xT{q@6<3x*tT>n>u(2FqS_b|YjsSj!?IdY zwB4F9%!TPKZRtzpxw&H=&S?~c3I|#AV3;+s$9&b|+5Dq_9ba2Y{xDXqVBGkll7Cbh z{@y4W@r5R**gYTsXRd8KVDhp5s^VG$eICiTEg*2I-TbMkVI)H7g5>kXhk|~s5S`^eS{RYKd zs3(?}D2|`wvu;N02{_ZV@5JsR&w14ZB2n!tFLiXo<(;RDDClD|LI=>@wz~JNB<#rm z`y?2YPH-$%eTx(0;X#~C9MB!)r^Qd zVpH=eQvzR{@|E>J*d211>1`?VKP_pZ2JMW7wm+3Y8N_K^i3~r!;afSo|L|c;tg3_M z-QdPFpB4Kjk-bJ3K(*j!lfk*^Kr~pA)a^%R8^#~Jk^_h73rvGDLof}x7uN85L7dGM zvZm9X2vj(KWWQyw2d@=soV*2Yzryk?fEB$?-g}$fn5)S?V$n&(jqp$U#rB-G@zit2 zm4CDJCi{Zc3C097-jNNVzI3JL*)b&=`euZ>=%raJNGEuFKW)SF6rRbncz-PS6%5@d zcQ$!}L|TdcX@!kx8C!F0CMb92i29{FR zhbo6<_yqUa0*pEEQ@v4*nW4|74O~I1%*f89Z7FPRGz?gR;xEff6h6JX;iq2o_NrcW z*+ruG7;iz%VNY8o*K2p}@2_35FOP7`Oa>g;6#(n_i_5_w5s{Gzxj&9OVrpb$>)rCa zBR{|MEaZG5nq&I+J_tKicKF|Jc7SFlGhFLC! z@<~j`F@=)tfKm0w8H!n-Dw(`Us05XBa%&5Yy;oBaM8Z|2?R)<>)ak1AtJig(fGii` zxw*-8KNHygX39o}f!W-a5+CYSl&$Y+*ULxgjsg3|}LO-!8)G2Z$*8pL&Vky349MBh^aUk2`=y_oc1? z;R)gQ7ky~velZNw_{omuT$y8IC_DI25D*~v14wcQy4?ZFvgy06{k{Rv-3@S(mN{N9 zfr37Fj(~1g_h>ha;mCb!ZQmG3Ndd&EaYskrGBPu@cAf6GMS+C4+jyS{FCr;}YxAas z-aGMT%?yw2zi>o8CpF2Y$MY5W?d>m59)lJpCMHBrg69e=h6;fG(7eSkYt`W1FeUG_ z-{l`u=+iF&1fc+VCi_5SM{`?Sz*g2RAS1rYKKI@4+~1HNHDlO(62NJyQ=n>dAoBd& z?`Eyn>9ZFny(fi_k8pH0(6RjJpHLQFat*6&eHI-<4AjoIKY}wq{JUwt8m32C6DFdt zYBOAC8HddcU)ebUG`IrSqwJ%jqpP-7SFkD)9bteV-KMk1D#d zACulTrkdk-w}feZb~?D{%*M{{1^DC^n;bSE`yv8T0Zh1QBL$F?{~Mz7;TynnItT$k z6X`!Z=ZB{&R;+p?q@c1gV{#8{>|Uyq%gZpuRV~A&KqO?m%92u07>o*ykwrg=a$POx z!tr}V&{!rZ!)Uc=TSj_kQt$jNp=+{QJ{N$*w2aeBCsz}apmGn?Kk1^ zCFW|IZ0vBdg67IWh1om@@flsoH|g6f2EAWeXwl~>3bnaPrWL6KC>+1rCY&C3iD~Ie z_g|u!wZu_Sn{VOn3V3Q))Ioj2LRC7Ocq75)8UcDD#+RQ2r$q?3&M1r>s3Hv5AU-@M zlY!~ie^y_K0*i(( z(`+6sft~2*YFc`d>mk&s!8tu1BckrbE!7Lspj*asp-77YP;0&y1{U&E$z>mx3#^k* z?e|M=Y88|_6x<_2y~#U9hHaE;#_>o$A-)qu<{oX_(_*=Y-uSZJyJqr;RhjuFcgIau zVKQ?g8&~0130fEEfC7fD1YtwxpTid1_OxxDd@h*G6f2uF+y{dx-ot6MFPLt(oW7+p zd5jmZA(pn_6}agYD7(2ypBE+3l^hY|ig#ydJJ#p<8mDZZ;dpGa(+PvOA7 zNYM-Kle4gqd%WnyicQL3u}T%IF7spgZ!N&hx}CtI7+yLNRkI02!VKci@+a~&uiQ(~ zWYA10A{H5PHKh#_v!yob{;vY0^R zX0>;5sm~Wk4MwMC2cSnQ3{;NE&}He10xo{OLQbU%|tcS*i_>z6K>4lOV-_+KUhTNPda7&Y(>ZT z!mY+>p%_mV$)pIS^wDOqfi`LI8nr2h6t6+^lO;=1yuSo(Fyb|Hb?{>!g73@fuf!8qhUX}N+b_oS&ffiXll2a0VEqHpT2nXMbxry> zpwmJUAz6EE{wsG~!GeZDHZ^`iEB~0L;6;J;d>=(sU@L~om;TVly*9vuCgN^02&<$M zl1lf0w)O9`<$ejlWe+E9vVQpX5-QmMI3+_p?~G4jP50dSPLH|}T=KiIQ*5=;?gaTq z!YMMC>Ygy#_-EE-B%S|#@kgO@4{7|GAi*koa3LWPlq^fBI%n%48dI)-*jof%tmbhu zg>pZq3$w0!@r7$6`&45bjg>ew!>=6c!po{~T45cjIZpf{lRGrWP2Sr1miSXBCMxa$ zR@V*|9m$bHZy~{|JnM1T@LdVETs?8`0)$GO{^#dA(LG5OpnRb^!|>fJEuXQBRdLW_ z<9&FWxK{6ylSp3WC*er`^Iz5R+~50&FzDXpGujQt+$-)OE;K%vq)l+kHyM-^`n)um zN@|WjV|LJ(hp~dSOSL{vaZ4&_<5WJg!}0x)OUuV4S|uQ!z3xEFdLm36_mz7KM2hL$ z=&^s6Khd$A_=r-?P85Z0GgY5MdVf*utLL2@8LDzKrTn9I-^<|UZxiQTVO2;`r#r-xqdEIRLfacG@QWz&&0uyKZ->GuGyWr1TDpC*Mx zMBCRcQ$l6CYqR_bMN!?Asl+6Ijj@tiIKBb{?Wz^omrBKxWz1gW0GAW3Wfi!LsGER0 z>MLOZdHb?3gDS#ifjdFACaIb+Vw1uh7RTtr(raH8NAby&K5)fU`$HNvsykb+Z%b9+ zTVg<7(eH%SOHDmwfxz>W;-zHpumLd~*R<|_`|=e0Q7l+pn?)wPA3HPJ?(gZ6ghC*% zXdKJ_>&kn=!x(zKrUuUZW=;-_S8HyrXbuqpVo;EgHJrRWOpT5@dQu8rh>aX&bS$3# z)03D4RJlIF@dAD)sO) z+#5N#2UNJ6EY_IrJ@gJ1NJ&X~9#=H+_&%@z0MNrPwxom>h+K|)T$=EAAK8crr9nxM z|AUS0pUvwMwx1i21Ek}%t*@-F=iJ=50%2^PueS?9J_sp5Ne~kg6AcDD&@Tg6qd(0phW( z0qEntd+ie<6AQJIadzMXVF6_S z%>S&MoUh9}$0InYfW6Aq)zuLwIP#ef1>*Jq`Dul2(-k<=0Z_m?PqaTu0wEbc`UrWQ zL;k^EV1NG{c@ax2>>mzw?jSm8K>&N+`OE~6#m&VR<1;gfz@EMi*pNHS2bjVCAA!6U z{Yij({!!1%CuUY4T8s7BXfaEliv47ShZim;CM;%^*^oS@2=8EC@J}og^0Bf zO2*FacuR+YA)*)~I?E-9q@={n?X_@t_MQ{K4Qiwhz43cNzJ27}WrT6zz2kqdI5+nQ z$r@-sPg*@_khk&?Hm%&Ep?21J+yvpLGSq!CO#Q>|L%!6}4-NZa4ij7&JDnVm^HM~6 zM9E6?!u|>V&cd&n*I3A1M!}3`;OR$<2J764g#ROr*Xf-?OA%@ZWA;F<5(R%Z40gAx zHO^X}@;k?F{vnDX0{Eu^&jJ$A!8EU!Jzc5V#0;A{2}Du=zjhP#ufMh>)k z+{sZx^Gp$W@d zm!$D9_H!VJA&L7doc)7$bDoy-c(Ds<-HiUE~2^Ko6r=T2%(ane2cF~M*~-7jIL*IuKwGf=W; z=Hz<~IIxQd_S$O_iA7Ug;gZ@MLlbGnx)yI__ZF(Kl5}(l5@8SYM z#FDhvq7?3UB)mn%;7>rRj-x#v;lQFo&Jy-u6IXf9R=-6Tq~xSmNa<75i&m2`Wo>py zU%^H2E%Hfp^H0kuNcnDz9l?E?=TlgXth22IH$3pO0p-~c;oywpC;Qq@+YLIu*_G2vO;-lT?cPgg<;pKeR8lz@b{RL>sbeC)YO>4uRCqp$ALC0Jhnaxp{yTk$CpS*y_yb6X^BL{*o11g zlFPzxKYBczOOEO+xlVC?yKc#BW=>?9J_;{Eu>84FL3hjDRd;lcew3r{ZSt&)k@um6|WX@qukFn#>4oT&XFS%$~)~F!`=aZU)ETr z$t-P3wfOVWOGV6I9=QuhhA-Y*5R<|FR}lN}v)xlDR0ld&qz{J-?wtw4QkLwthZdzz z437a!Bu!Rn^eO&4c1sEe{T!f^QMezY+ZOqf6^16&4M9OyXsvt$*6dLds2zz1qYRB< z+BL?UgNnp%iSE!Wp})G)O5@_*zO$XFv1)f7tXq8f6RMWh%sN}W3 z3HPQek2{y!X04Wdwt#3vZ-1rDS;ZI=B8IDB;&u^03~G$(d?AZ{@t}lu!%GpHmi63{ zW1wp}oaPGktQOYw*Qi)L zO@=4U%kqe?k``I~XG+KiSXiuv2V#x0qFOfSkG!c?2VBxSxuOp_g0_Bi*%;VxIf2&u zPDOGXV1+&CH#RKkwgDH4B8#in1}8!0MRVnT}1LU`%iEaRfKa z&gp{{VnUD=F^CTF7rja1JMjH36L3Oexc{ol_i~P=_$i#0p!@osvF*8hq3Q8JZMgs7 zle;7*6-YqbO$5y{H0_9~DJ@KS?+HmwpK>_Ux0&7=KBioFvAeTgeqY@}+c14ClhU}i zE`X(jqW*QECqh)2Db3+;AA1%fDVEtlMgP1Xr#Cx#7Ux=8jF$7y=7hLwDw@vizzC1e zC7EP0vdBHE7O{^n81Bb0v4li__@* zbK|1g9$iV&h{_atdLe*e1agS9@_-UdLmgh7Wo_(qK(^N)zT1?^{*6%FQ3__|zQ2ZY z7R?f@O&}sFeN!T=+}B%Tc&(lDG^b3g=7kG@ z#a~UaaN<@c;nX#{P$N$riL|abDr%mIG`NOp=Q=SSSm!{tb0Y2k^0D5z;zEG<-2-}` zPLl>gEyCwbmP;^RCZv#5dX-2`XN+d1A(utPGj@BKw3O3W!OL#(W0a8ihCXy+c6EyC1mb%6e430{HVv29 ztbRDT)L-e2hRUAR*qOa!5mz;mQPH6h^n*n@>4#Ot^}nMNo@`uYdst!uG71ElFBW4p z3;013+n=9~-sN4kieC!Hl4hm_)1-*EOQIb+o1`Mk<|qzUaA_De2LnYF(gIm~nq_2^9}a;HaQT;x7$PDn!&wkL{Q`YGhnuX8Sv8q%hP~qfuoQ zzT)VUZG!uc4*uX^{`R4(4pJ-nqP_ebj1I%0#|%}NJ)uFg`E6WcNxdxYOH?7A5i_3O z($&SOOEvNu7@X=lT%zyJEXXA*GCn5M_%no`SfR1!KHU%-mvW`vUs*iZcyP>=an-p= zQ!opki6?c4k{9P5TeiH?=yUG#e&rTlvgN58m;Ec{Q^&fF)TOzw-yUhOTZ#tOt5T9z zg%TO{v#^iE8lQ+u@BfkZmO*iKQI~L>2$F>05E5KNaEBOf!5xA&?yezN@X%=EPH^kS zB?Jr7xVyVIuHWfrX6mbYe@)e-D*Q?4d;8vV_Fj9Rwbvpcfc&b>&Lt_n|FuBRWBQF_ zcOUoTSvPmAHGWigdfd|317Sbb3`oU zY5`!BEJRh;6Yo3t5i@ta>x?s^b6T+Fe*D@0lTTn^M=%HQSRpkxH}|?hrItKCMQgPk zfTs3-xOo$3WSusi3eEy@=^eC=1ln%~V{{2^K!omsZx$P!l|Qs>hgVhEUmTeRhlGIP zH=P%}v-A54Er2aMZ@*Ru)DbRyUgiUdX;5(ZXg+jrKR#?nx39kDL!X-XbI>SXxX;?E1OK-xPx$geoR zqyyWTiKRz)r!-hZG3*?=d z4Q6&0`{H!HU~{)Or@HPQo@%^!gPv`UsanAq#-kp|V)V=OFc4vuKx=!z$i zd~n^!@NsJAnw6W|IlHGyYLkMJ64Xz%A{nP5;8corX?M4Ge}6xYtz*c90}wONeSTo; zG%_;cyj-@rx*Bud&3zAyY0}kAo9LR$ibJ= zGFbYRrSDs4c7uWfkTcfXiM)JIsi^@6{1+S+Pv~crmluFiE#XS4s>j^f`KoLE9Ijn+ z@2UU7o{GvhtNn)pHccH(AO~-+*dJZ3a4V%UFNIPh6=$hF89(5V6YX{#ynP2Hxn^S; zPH%$B%?{XKEkqT(!aD!BfC)B$XA@;)ZS-}x1UV4PxIXz+UuNlKTxlb$YF3N;@M1hsvlLAOAO+ILa||R%O|AT|#|5iSGU%_n*bS^`nAB)pI2< zZ(Tj9U~k3*^f#m0^|)pHIMm6=<9w|qDZ>k^8&_Z4z{R~+@G_1^4XJGEuF(+@G5Zox zv391f5~}YPx?ZWL^c)%|GWv~AXHRgjzX#JHZFUUZ#CcYUnT>M(l2-oNA@^79o-My5 z%ju&3idpts%h;qjg}36(4`_viY{*-8?K^t1Y(1>_>@%s^CyG7z*U@FZ9=l^CY@$$|{-mHuF^;4fW^Aq#?Jf9S30%6tm^`n^JDmbLj%PpE2?BHNMEr zLe`%-(6Lw_w;r@(l`Mana*tNhomY+f@h@tJl24E9HesjrMs174=PuK|s8FYrwEf$2 z@~6T(X-K~NsL!{OhgDn^%{Zg#n`LYR_a&p_3aUrdL_I~ASIDA{Op=JkroKTe0}{iq zpAAvNyPx$)=My&Md@^5&&{iV8*`POsw7uMW*A~Z{#jeZ*$BT+ml#*Ry8&O3ze+q9( z#d4}-J2JzHHz~D=d>ffZ)YRXOIF#x!pXtx7|M16$ywq`vfi3CH;HPIM1B{m&EPS6e ztzL+%5Ui_l=}poGtB<|1NT&EF`D{K&hU-fw-}>bli^oL>?kk5$w&a7CJ}kH2v9`7+ zzCH7?BTEx2SvROJ`NKgKDX@pvc zvl+t{7j@*K`N!{1;@O`%u*xg`!Dtfd%Z1PoI>}OOwn4_v2UVa+)DP~&GB()Ut@iV( z4;s2vM(W-`lBA>>{REqWu5W97!mLKC)4q&oe$hQ}?FugVy`G}?=Wn9=Gj0oJY1^v) zZ>ITQ3bggTtYASeIQgDgZ&MEKOGwZdcyh@1DqOAL{9>5FV=nDkRAb%QyG|0>zHJnm%>a4`I-v~BK zSEj+kURI~-6|oP#ggy-X(L8$fHea{sdt-!rrB_cRyWmyv zyI)-0$%QisUBW^Hf5JapCLWfPV8(vBO#NMww-&cEn>4!DChSBh+~c&ODKR=`-|%S0 zfh2*^5gr{QKgsh2sVt~UAYE!-+0r}kl${-y%8Yul)BHD$So{z#tJ&)SM>QIAHbuZd zGy43KxsotTnL9y@e>Sx7*ps-AbZMtaXJts90KfhOdXwDXv35zKwx%D>{>}gC*Yu>q zwDW6cdRO7N2;%e+J6tZ!Mr5OBkcW4aU{EoBs`pdYp-`_Zzg6fb+1RkiIlbl)TcQGO zi=R4i!KxbgAA=UM&LsCWcJ=EwG4UV_oy;4ngQ3{Cy55Gx#cC38wGBjkJa4&$nXgk0 zPQ}8@Rb$$`k@okCCp@f)IEP*M zhczMurlhJB%e(%w19<$fC$cZ`@Gt1$-S#~_QbZ}GUshj#PmDeq=lTe~$DBjuKs=#QSrk`Gg zk=eklIGB;%Ix)lQc@Er|r)EOW5)#y-bWiGOYzM|yq%=FTI?_-1)$W0MR&j*U=X%_{ zl-T&W(Y`%xtB1iUPbYgc)t@)qaQvzJEBnn6bzzqB4IGbXPItqes-@z{CA#&&+l5}K0m*2lqc zzOZ?N#KwSiS}HE_QsKtX)pq|A)@`YI#Hp;>GtjwmcByV)4KXGR$tGsfl8KBrjW;oe z{NAQOb@#4ErFQK7xz!&Nk}FSsW21M+bD~Kx6{R|B3I$~1J41d1u3m~9!WxWiGj60u zMMtUpE$-kcN#_xZnBYs4)c;BGwawDpuz{J*Yb?-r*)wz&)k&vL`#+4hW4LNJoz*?w zDLv3-(Qg*5*5~{-u|fLu=R>@fkL%Z!rLNZabFPD_J3e+_)q;R!lN)+lyI<>x)TI81NS5Y=ngVa@jS9*$#9e{ANDb>>^Cp6)C7fCp}A|vxv z#rS!#jEqkpMphPKmQ`~zciUEG<|BD`b=U&`pY1|DOKUT;=Ou~pgrmm*!I`AyobJwa z1MP=9|9X3Y(%4??QUqwyi{>do6BE1Tyf23E)cbeJ$qn9iZ4Bj3lo@n*?w!ls9?7At z8Sl<>H=SeMo<-bN+iiO-rlh5%;eG7BxxRD-(!qQ5dTjWgX5>l@wNAM=d(|E}ac>}7 z>{hz)fXSz-pWW%pkeNSfTBpiSCWV0XFYv^{`2!p)dAzR9?sw}=>r{<(#4(%HUDx9X zoqhith+PD400$M<*Vl!O2hIIIOBDN0Qi0{q)w-DQz1?U`A?c*qcb0CiK57CPG2l&) zqr6s?30yi|52;F;ZZ5h|FL8163JNZ#dAIbwc+<+I7y`X%=Ocatz4?~WrH04Po&jLL zbm6?2_^E;=A*#s&)Z<-)q@<+rFxcI1ZfPldAbQGt@vazud z_{<162m^-uA|SNS1Mz0HpuRx7oSPY--1nn|=>Jucq2MDx_2;1cN2R{2YEvwtb#q%o^KQXhAFb`wOv(x6yjI2zJleR!f8-XvykD<~4;b0j7l;=KBlT{HXAz3sG)f<%c?>PwWg;@G2%*qF>|qE#HNU!-1K zA9KEXHQI0E7+(C)Ui4MBTGvs$%@$kd>?^sX5c(Ut_i@B=pZ$$< z5(jehYt79&8S`@;Enx5b>4&6<3z1pk4ljp87?@`6m4^LmWqj+4BpLg)$xJ&fAG}>F zA~K;FnsMR%yU=nzbKy+_DbDkx__iv=?FlkH+guAHSA64w0SA1$)iYNiCZZfsJfG_X zPeb8@SBZ+GL8W)(D(Vo4kG^ImH}$C5vkD>*%LJo?0vTCSdhN>@j~LmXC^Wnp$#^M6 zOKw5QrjD1|yjrNF;K}sU4ytdg??Nw#1I^HiDBJzCYJL+KJV_%&jGf-LLjMVudq4RV zzf*wbv~9!+?BlByYulO|Cf>|#m)l-49Olzm z5@!B(4do>hFGR}c5xgHTeQ*2tqbZ5Mvjq)o!W@8#x5)0N&pw!GJ-X&t4^&$(Oxu)x za_*|Vtb)x}N!Rv{fviceFS6Q_GSP$fN!`WUC1rmPCCg?=6#ckZ(NgEk4XM^z_;nc4 zE3hkVOVKQm-}SVd1usYQagg*P`QY{hvD0T#qhH0%9Jq0)-)@(WM|k5l;F9egr_MnW ziL#q!;_wI0qDWR=i?Mn8l#S|l9h%cw#;0XDhCU2>5ER49fVhWyB);=WUR?zDd6iG- zwhJ3nTU^I7i1b&6=-Iy2e6e{GXQ zD54`Du4Nj=aAI5N)cE0$PZetU_Q=il=z=0pn3CI?If*Bc0C|t4yQRCB_DR_g}NoD}3nU>F;om;-tM*>OIde zZ70oq?6t_s^;%0V+V=tZd=8i1i|SCX{NxOrMBbZ&R}CQrPh13GMJz?sofE_uA1XP* zy$TbWR|TFv-J+{2{UFjoD&;1)I%;eZ8~1CSLwx7zt7hOlQBC-8kCMWYYQ?)&Z2r8D z7l*E5G9woJEs$GjcPpU|erY=AalesCS{Dn;H!L)2rClerrb^BY0-ujxd3pdw$-A%Y z3*oMVOND|qKe6(9zo>tYn?RD{w507UnAy^&Ue&}xA2E0Rd8MB+(H)>I@At16*T59{ z$_CcfsM33t7sj3&2h=m)tWI!LzLuow`3sIWlZ-z2yVZw9<|w>V9{Hs@DLoaPQtXP0 zKMb~`bier#6AQD!5>bH67n&P$u2O2sfaMY62mJ9if>>n^2ORdC-dVqQDFQn(H*AE( zw-X$6q$}U@pUJ)maH~%|Kdf3eqk97xOcXs`D~*^zR(|EJyZ$q|{g%PY_3oqI^i6?o z*dk;7+~(&vkNXEiw)LfBfzsrO{8J8D*tHS1=_~j4oQiUO$+-AuAL=LEch9hXJb9F+ z`(TE{UOO8e7yDI5OH5r+n9_~0ox_fU4+}qs=66gEQvtJ0gt&pS8BLJ-*1u3^+TnZC zdo-}bE#Kxo!ouD)UtG#0vs2?)>-!rRiaa)N5(v%NneMV<+I>MR-n*t1UjEzpsnysEB|hi{)?eeM>g{>I4t zF*iZ1WJqrnKd6^8=oe?=zpkG~+SQz_yLPX$IpHB=YG!?UX`4*EBAiNE?CDND(GRm< zx=Rshz%UqKw6BYuTHTTJYgzM?N%vPgXX8s`4TesrQYKeLqjxC!d&N!frZ%d6_9_Z~ zILG;gY_hw(WAQP9WBKvYFSZ^Mhcw+g$Bzw=uJBl81tm2(&r`xB1^)I}nfD)kVL?Pv z&lG;~&BIFX_6=i>T1gsN{$&2RI=}z3ovCQ?sT6@-wU%vc(%>ToF~i{q3Hf~Gam|D> zi`u7%9$YzRlEsFceOs;Nu4vpCRgcmG8H4W8uPKw8BLB!9>65+3&|1>C=FOiK?mn+K zf5qr4UpOIiSiD2}(_Y{C7d^fxm#pBM0TvRwq72_+5(C?h1T(l#;n<^0>kjKN424?B zWwJlp-~Ges$g^F>!&77WC*QW+X4mm7%ktpO%-t*ez=5$Qr2n8IX`{)fa0gnNNV#%r z%f~D<;u9*d!#i<|3(Ohga814kUoxC>AMjo_gG+_GB^ZWsFs^$*Ehb|fXT+Z4`8QdRm^56`sG z*hNF9q^^y1{nl?|^xlnzK*zxBW8-OVXajX9fs^ZtGK&5>*0mjj!kYNmTH=-@=kfPz z$7oTvvBrK-K976b!Y~ z%QM2!9Te(Ox|>wU$MMxY99Gsx8?{LuQ7I_@(XKjHU3{ z{^$Ty=~(++YDyr)_7=2rMds~JNg6Cq{KSAh2J8btVV!gFpy?Y(22 z_=e76%E^fn==$CT<7}8XICH82cEBPr#ch**zWE0=3k%C53=CC60iZ#aR#S7{$W|J- zfF2ecQPq9;hML+R2#sB)STj*xgZu{rp`c6OXj?b;;}IeSS=d{JZ9yR#xECzlJx3meyN z=P`um!HDJqD?H1U|8?jwukv>M`V2^8m{?iSynp{IG&D5k#$$i}BcSwP3e>9|c;D{b zhE-Is14NAGHi?{_DLA(y5D)+t%-w`3YlwrxD`)4^%h(M7 z-=98xy1u@i*3^_brsKZTxKwOgI47jyCI3+q%r=77JPv0LQJ)l$$s>CGI;Wu_84&F+ zE-yQKdZ-u~w;DZmP!jV*TH1W^fAD2E*r2kI5V@NrsL7Z1&GQSvO8!)_z z$>?zBUyp_QsD_?V)6?6mS67RfKO>yp_G1?AUi1>j*R*=5vLiVW@Dn*()2EMeVt|L~ zH;M{9b;|(XM4X#W^8>lixAcGUt%J(oo$=I11_bf7!(X%=?-K+P)Nte(S;z+U48Lkn z3Ri*r@P$0LlBYlW(guCG^QE+{XfKy|>(h*?>|9L2FtV2ITg>+YIXY9X*jAT+?|c3B24&G)yxgO19x;h9zINOSSg!Su z%Uw76o$gaPiETz){GNyQ;~rVK)S>8K=#s?#@I0q>*x@1d=A|JA<5ig&An?Q4C48LJ zrd=9fuL;dFyuU>U+tRv8|FzXzX{o&b$-K`Q1A03PKFWqv*f))ZgA8R`yMIKfMRxF> z$(tWw!<*;sS<&};uv{$A)Djn%nlwo+{Z5kVzF8O4|0xr$uNf?8t_2xztQ^o97afb| zm7M!R8l|w0id?eB4lma>j16^+2Tjui*qi=QG)huMfw8c*DI*zm)3#I-ZaPJ^ha zIRpIO*ncVvYlU3!{*o@^ae>8l>AZ7#$7YQnuJR-N1pT3A`6QgMyM6c%&xOAppE-u9 zmD;yYmVr`9EDKxr4k}{}p8V_o?)7UWorZ5y)6^_6?c^_A1p}uBJA3q|QI>)tla_B} zt=}RpzMO)`8+oDCGYuPa+Gv5=3z32Z;|+aYgPkIdutb{yu19&^6bFs6g__jOlUn-2 z9md~mf9_5i6B8Hrmz1`%y^ow9=6rCjF;8(dbIbYPiQG72)JQSRtY;3j-DR1Fo(i9zp9RX z>i8WTf=ir3pcLO}xK6dYe#Djp{K!Kj+lBdJmmibdLs}s_yMUY@Sj)9+(%1F0lui;Z z=Z~Pf5ZT{b$>$>M!U6eJ@dJ!xa26i6Z;8SFsvIwN+4PgF$?A5s56t4NKC=(D`xi@? z1tby1_|KCqiU$(hIFA}Y z-qu)#ddI_B!cdsJ)~qh5>sXreB-i&}Z%;E6aI zRUYi0Y-uy4C&MLH>Ne{s+E%Z8+R@7O^Nt+vLbzx3lni^0bFLU!c$E7CiN;DQ7uYvr zhPy{5xl^#luVU_wSVeJS8;adEYy}@nhCsmkR1|4owG}R>#h_EhO4aKA(%9hNi-74g zebeH=ZX?H|DooZMhM#I7VjfgCz4MSqhcRARzAIKos#~T^=9$|+g1s78u;p!AjcA_l zLV`%XwcP7LRM?aS)aJ-;UPN=8Ak%e5zZn|`YZTqZWw)r$DBBOBq@sz87AK%c`qRFA zH*fhwcyr{v{gdMr;)E??(@ousV%^Rx{U@**UIunB&3 zPpAd{#iqp*X+i;2& z9N`$P>UR*4@N9y@+Ncffo+%mct|JBaPwc3>R6|M%!d+uHlgGB-BT&>7)5%%l7}Lu+ zRdPL;J3SQ7GK;jBi&yl!2`vkag#?J^stE@LdVV6tC}UtF9q(#U`3W>zM& zrusGM!CR{4Y zExsH!@5xSm2I37@IH7Ij-)SSULz1kTq3WlW-`=(W#_>YVb;M)czJ7XO za1yk)V=k@%a<(b3+40JNPi@UiP9_{29B59S6g-DF%b2Dh5S%5A7Yt2jZ7g@t-grC? z>;2j#=X?(>C9_|$u$17{4ET0gU0DIfjf1oEoZYnAQ-`yCJzzs;Gj^FI;0gufmxWhW zSJMdz#DM&92M}f?V$qcFnTuE5CDTasF^MV7==U&46F}THn$4! z;lLX2KX#DUZ!c%}cP_6!CYIUkd|c@_;qdeK9{`h&V`}WN#SQ;^p3=D?!dAFml}X5A zmXL_3xx4#WnCSfvo}Pk0mH3pY<=?-@=zIEGURlWn{2q6olgz#ouP0k_sXyo`VQg$H zv_1d0^k>I)->PG8ByKl`yXj||<^Lkd+}S_5?U=pp7 z^PP@>W|C8RLtM;FLd0$46W`xhnj2eE@~MusY2nvXWw;&ZMs>)AV<;2uCFrO3p*$Ps zQ1P3tbKbW3$eFrY=)l0D@irNmh==6` z#Op9>S@(w8b-QfQcsF~njOL5xRGD{bF^aN3c9>R_O~{2OGbWSB6b`93P@b%HADYsU zl+zq!vu;jHF%&>VHe)sj#HUAghQ_JpOgn$9byqbu(i|LdW15yHC+Si%;NVB%n|?C-mX((o(n?#j*O-yAt0jN2r1QSeT1Js2VEcrrrP z(B#D2nh|1TZC!hzl51e(ta9pLXf)M%vP0kAHC|>ZpkOYCm~NWq;-aBdAm@!f7+Am@ z>*Af9OpWcmaj2@wDiJhIX0L3A9;An2V;P&ca0FuGK#oi}4G`clB`CN&=hK;S?x%T>Rq9|i9 zNtumGM`K3AV>b58|)9%kiWMtiEhHL|Lx!IZQ zj4H*FH4Xfp4GroeW3ZHBg-Iz?a>RXJK8~a~T_I?Cb7ZJ2he8p8s%S@jU??&CX4b)} zDwh!fS79*CiyK_umU2_gwKw8r)P(XTDw0STIJ}QZ_rX-oCnB{*if1yK?#Wnt%jwkR zCpF^XnkogbJDAYLl#NO|9YaKJ^Bo)!Sq0SU@(J$6*K?y;SuCHRd7^17no^GU=xxU`m-bhXOJXK!q==ADco@$_iup3Xz zKpEyRADhaqoY+{GR{sce_r!HIZc=TNk_BP`ho*N{hQ_L9BPv)LcCwF(c_t<~`ve47 zliJ6>1~B0ADp+=_OpS3n*jOE?417Nm5wjR&6>(?p-W)k0 zAdc>Xqi(W$Z=k~pzIy6I!;g2zq7+%Hs0B;DnJh8cfFxd7vli|CXfOj=2SgcrI%DaIzimJ%1(u9!Ef zAXPKITMRIkQ%*@iWbvpQ%~nyK(v*V60Jw?pqf>ac=d47=&y>;p&qRU(@eAo?nB079 z6AcX7o*?=RKxZqX9C<>HjqMEIP=0RVy*m8x2!kKKwyl%}EB*>-1N0~kk0^Fkq|Y$*q#QZ(JkraRlR&V5}+&Q)1;0Aa6_7 zU~6D^JR*|T(A0D`yKZ7zG&>-FCG&<}-%L&*a(h-=YYGRGYQ^rL-qKQ}bw|2*$9v?y z<%k*B>L_V2qZpIS@7(KW0@8AY`{}M0=z7v#^?YK5PNajmn`%n$Q)h4Py}e|zmlLIW zp8?KD?eVa7dTx}y#_O{GZT6(H3i;ssYDj4k(=_S|)wc$fdIxiz2DA_RgEoS`OAXMl z?py8U-%C0_jZxKskzcQi(az-d37%?kS&aXp+SuDmeImj9>OMbN>gDvB-IQe&HN8Fu zTJ>%X>tfgpQGeR7hy08q$bmwf-;)i&Gf5hd=&^L%d&Zwnm9c--I+wV z0@L)hxb! zre!Y!N`qfnkJ-_0A<6kNmZD$fT^#Cq&s(_ZShLCT?~-xgD(DuYK>cFaTg?~sVd}uP z-oL$dn-%C2UR*8H3d1V)UIQCPE${1N_L5r^@K=0-T8ferf&t0Bz6UL`PVZ7W>us-C zZ+o2^qX3LW@<-g3h=Xx6%Stnmcly0!#K_2g33aWyhSXrM0|qI;!p zEX*`^jv(B!gKB{(UG}XVg9t&Vzb=W`dNiHA$^0nv6P=wyoh?PIQ+ahg zcY95Q+yWkuJ>VpPucC-H1jxUZ$nDKdOjQHbPAc#M+)<$DO0g42j(aevW_-``f8y>t zr5q0?6H-5DM&X*Y+=HL3K7-3(fF)<>QvJBJNIj~40jpDUR>5!5>v}ATyQ$`96%w$F zVD(1|;Qiup+s;+7@Otp5H}Gw2(7#qJNj=~4KwwM~A5(>8ISlehQHDh;Sikat4i1k& z6>^+At|+sFjw^~_g#_GxgzF+Xj_Zg;1c2{6-sw0K^Q$N7>osi09$|U&lBP6&oJTK9 zBZs%5OzC43%y`dLMoHRasx>tw+ssWlpbAnnxhD%(Ea_)f2Aht(L9NSLCv9aAaLi)L z8%EauTMnQ56-)9e7uTjK$0j`@nn0j3>ex+ELPJ9%r_l~S_%1YBQjwCYty=Xyo&cir}CCsJrOm;b;v7=FBeN?704YT5T!{T`k@1_JD@he{~{f@2> z?8_MmJ{UETXwZ?9k}~a;S?=?2kinmtq-*~yB}E?=-D{xor*BC-BOY>#}$+M&aX0Nl0}8@v*36(X(46%kq?11>54Jn|k>k z$73dV-=<=&ffR9==nF<(y;)%^P1-GRi^SPWYdIAYj$!)PmZlOLp{sGClFUVrQm15# zLO7GaJKEgUxL5_&Tq85xWCtN};xIQ>a_OB@dyQLYbk10wddP`Hhk6+uH8XQwZnSh! z^E0fjPPekg%A}1y$h`K^Z8COFvp%EJp2^lp!xsy@b-4v{MZ#@2rp&2Vp3;MS2wBd- zLA&6h!m*sngKfy7Xaf(1+U%DtXFbC7v8q?l*fe9bDPUf*uFL1n$ab)1#$ zfo=W6SWvsjrFOKEsS7niyVd5N7VAGY({AXwd6v{nsP1=Kzt*SwGLgTZtHCuhv-6+$ z;Ec8ws%b-}Q(2XoKqnr=+Cok4Q;#B*C|``I2KOj2av86yrRDRr5T2<7&bB$s&13dG zt}BKI0Li@WC{QV||I0lDk^-s-Y`d%%zx?&7I&OEFH7l1h$*)a{8!tA&!2B}UdtD$n zM}x8*`9LZhCytEVL@JmL3Bs!V@rY`!Lf$gT+?gnd&V0DOH46bG|A{&IedztPkWx@w z%K&s&B@|jsgn&js-;)Y~^W`YODinL|ww?~$N?~7n@+d?l>}DLti~upw{$zv2>mUU8 zhazNgzS-AxiDZrkcc2c0BzwRx?E7M#KVsH+IkRUBS_l(B$2Dn8KzG=r?4G5>A&6%7 zG={@7Gs*6|HMC&<$oyUX{@?nm!){kV*Q)@5j+D=VPNLj)sU4jdXtyJ>pTd#ht1|q` z4wg0lWy>*b=b4^(tvV;m-I}!&i`jZ!0xg@5XfXl-(A$}4^t|k;v0n<~UIh~Rt5240 z&QSZ4<|RlVor?ZcOiaw>^uX6$o~JW$pxslbS!J~$ca zHB0N=+WA^)U$J(b9Y~Trp@{RpG7vt9OllMm9lbZKyH&0 zzIFf)gvHSytE5Q?eTfG5)1Cv~5m$E_R67vn zDy~^gfV~+@;4}vw4wcg$C}hpqVu)g%(&5aW7x(G3y_^?NjS#j-VKJ3pTb(|J-XQ~RF`MMqwX#JARhIWv93xK;x z|zRCF?4542kER8%s zXX6|=j`2Y}1-wH0yl%j^vzTiXOysuiZ6nZ4(kO}rB5pLG>lYtXQKVi$g9cS{k7tv| z{;$(vOm`b{f|fSq{p7M?xxR?)&=Ge7ea&|H@?m#WL5b|U>a=QJcZF%g>keVr6feGW z;aghQ1^?ysfkoch+VB~NYYXE|RnIib{CwL(8rh{~+ft@i%O=v-7Txsscym4cd4)2Z zPCgDW2KMSbZ4AXbl$hrT6c4pgPBi1dGbtIZG z*&u$`p?zQ@f!I21uI^aw&8O#rk|^WCL) zF`OqT*u*iY_N`YCxvrQgbi62)%hQ(=ZfO9z^ft3xIpL5OR6X_fr$j~G6{$Z|@Bpi{dNPYxc%uPp^mcw?j-3dAW=% zSHJT%wzA|KE+jBcVSBlqc{|K3gU2084@(?^9i5#@ZPe#bDcs%?S0j(%GSaWchC$hI zkT6CCKxt}xF+eFW8J8Z*NiFFHl>g25taCnRimQ@)<(S!ZdNBB zreM|RU=Qo_pi$MbZId9k&nN6elUJr)*OGIOFL!IVim#4!Z;z8okl1i-07uUkaJ+eN zn_+#3F`dK`&mD91I;Wi{bDDJ1C}6g-7C>SZ|74I#!rR*$fKB`L{&ZN$>FFs1c#qdC zh4UMKQfX;vdDcF9b7FnVg$@Fc8_)bdV;gSsJ{Wc#WX?V3lamPZp@D(O`xw|gtyWxC z)A8td2ux1wp@u^_GOn9>x#5Xs_$>V@c}jNO%vC)kN_?|uEDyT3*P#((u<({8ZF?jq z``eTu*P9ivSVjEy(9(p`S(b0PXB-q84`WJ_97r31unanU<9mdI(#4Z~AtP!hYGNSU zA7nH@O`-HYr1iD~WkLWJi9()|aWCQ=n5T1rfV-cRws>%PfG!<+)HK9_MIyR71BqP_ z<#jtXcjE-y!J!~|C<={%kc~oL+OMo(*ryUq;T}Y<&4QeZ%5$AnOfpTgbn~i1_3}ej z6Qef36ezfxLm(;cesfxn&=5K)i$F(f{tbIAyH4tw<55j}P|~CvX$eHRQc3{oeX6Ea z4K=6*1y?FhPEXe&#a_d>gHJ|Eyf`&0EqGVF#DnQ32^#nParJ|{ZM~S=K?L&};8|E$>&^Zsh=ER^3nN(e1Eh&?&0DJN)rhCO=s*)L~Jf^}jU%M_x)^BO= zC7|lbFZu(^L5RimnghAiZo()o*=~Dxs)_}SGB*iY|2%Q%n<3EkV2uMe{iMSMkdw{_ z;~E_%%?CUdCWexMyu0M=d9U+oS;uSs+ygfqToVJ>6ZqZ#iTVEwJ~uJ!uiZfc>1^7Pm1HDNigeP6@V-DNRh2CI8>bGogw zy(0yJ{g3Y4`Qw_?dEc_5U@YXPTTK!u#1GrKX`0RxMf|RRJPS@GB4NzfiV)Tj7z<&c z5fqewtkpF2>K=cXx;Wmd0L2)(zy!GhCE+Vpkt`d!{NMWpsgd?4=M-3U<)8w@{lU~Z z{R=drr|eNk?zPG(EB?0{2(Tv5d*~b#j9#CPj3@K{3Ze`7-Fj57>t|VX=HIEDIt-HY zpa72?iS~a)XDSIOsPb2Rfg+~F=|KADK)V4E0;J!{Yhd zF5k+DtTjpyY^_Fx?B|3vFXUNm5M zSGQgMFm(&)+@GU_Z&7FzXa6I-qOWeFCc_}5%^>f-B}@JOCo~pCU!2x&xfq;|fgQY* z)v;;;Q00s2=}JpY^drPwR0f#Eb?$ODP7c)O?0ug3OHE)c3!ID_fP6@x@Gh1pVQ9Ql2PR0+KCZa!B0w(- zkm!=okRzC}_#fKE6MY8~FG8;V5;VSFJ3trD%vIA+;0(}re&Nuwf z-EYQN!)ho7umK%SQ3v4UE32#<F3CTu`fm^Yrad5ukF}z0>Y8OJML!o`g21WPVGB9U4^nNe>?Im*0GF#z5zJQvNvUAz+g|=n`-$XU*dC4uOYYR!R`Kd2P$cL$lJ{p$# zUrG!jE}pg7@+GO)TNdpfrV2V)ywAJ0LH$7U9035J#Uz}*#C>K<_JX|wV^WCI@wLF^ zb_MunInee%ClLT`7qik!*pC-OSd76G5fLGwIC%0Py7z9J~m?Zm3a<08;k6VBZcQ2&D_ zT6XQu)B&tq4)$XGagnv4=@-+tKoHpDWOs%im!)nQDupgRk`C-a3Gv_8tFqPwUk_A& zkQDP8B!Nt!N`dRuL5KbPAM{Bz1f)xdfKKl)0Olzkhn+B9FSp%owN{ZM`_xM&igzrq!w$a1FnzWBzA-WprmEGQ8wKsmeJB;utlHbcCczq6zP*_P^)K|`U@>4TTfx@%RAFO!Z;kH1P5{}%w}kiMm*PE;Sk!Et)}Vp&vF+uUOfjo#}?owS{iHAA0DROdF~_<1cB zay7r8xGP1_9ZLF4<6zUK`~wLsw{F^w2O5+ZUSAxm0~0lLaD2F=;5_H)j6Rm8ny9gd z2%R0D3i9-{X#kC+Uh z$y7t#<9u>*6MnC#f)PUpj*V@m;tE|p5U66{wg7_l2sRzZE6QKe zc6yTcd@7|_8aM!kkb`;vi@ZLNJx^T8RRM6@$c|eD%>fB0*beC0m;27V>Q-3#2a;~d zG_3#eIPTnu4fvpm!Zk6syJxBP9e*xGuv7TP;Dw3%`O30mNuqFnEa|i2un2-waN3@d z0*>SJl!6og%E{8~?1;db)$1>L!o#RR0PMJDSv5`Z-;3up$@nnE-5BYyW8N7hhwoE) zbK}qLs-JO27ZBWRX>J0+RevzaW&QuL_m*LCEm_-e5+Jw)39i9i zg1fuB2X_x{0fM_W-UKIDa0u@1353So-GhBQGjqJ#>vue zb}InfAOLu?83GJ>{~R!FI#9flUs>|HYES6>;&>(HqmZj#xFMv`QTEk z_xVmS(eGLpVFYS@*UHy-PYmQX3D1gsPB9J}+ajTGGk&ep*nFP=SHp=Vdl zIgFQ#u(?}oPCPowZ}(sQ0lApnzXS$^bM=jmuC59r)2J)3#Pf01rjBglO7O|zthqho zy&GOcWzsprghsi>H23(2CLkZrea9;cO!8kol_lVq zp!Pk(^I!JLFNOgiY7-Ev^viYki$FLt8L5wA5in4GF-h`4z=Cz|gu%`P&9eZT3;b_F{Re*i@-IlWod#yi zui3NUwO@XlC-^fjsfez;qmt;)1@k=IB?2h8!MiN|xcnqbNtGBMzZP=9z|iZ916tcU zC}Mr^2Bf|WV9TcS*%l`i=Tho@!&6G*EE}M#EXt){*a0?-sv^bmli%476Cl!I@Q2o^ zG9&Rm9sPCP!$JGh%)U66eQ!j5yCC3R-DrQh-e7Q`X#;eBOW>b#^8hYY)8)1e@Dul3 zP0`J@EECpp21;#R%L}Gf113L*@|4<1Kl533)W0LghXT@xnR{UMC{qak zbxtoQ5TQl=060Z}6RS3`+oc}Y1q&&^PgM!cJ7+w$UV2SI(p!#P2LWPv52?iBbY%i9 z_7FaM_Q7R>JfL18ud%*TEdl&c)>!d$?avf=P+nen;QDZ3pPfl>Z0q15dg?SOF8;o? z?lRdESj6g}e_=<@7QpfEZF;7K_rh*eF{gYGzSiiujt{V2BAk&b)z=p>j#1gAY6lFG zat130CIOI){Td2zA8yM8q4|qC-*UHuuYNu)jWho2R(1>(+nQz66^FfZfSytp0W1m1 z|EDEk;Z@HEb_iKQng`m{L6;Bz!Y;b+)?a?%Z(nS)|Cy=si>XKE0yTkux8?rp&k`5? zZovHdtz5KUvO%*nnfs4if1=;&H?EHc6#qi~H}(O{3%CEc8hGLK`)VLGP@Ep&Z=DRZ zKI=c?f^X*UQG0)Dy~r;MLkMU()qm`%|z7-unr2vK+aPhA%`hOppz<+n#O8<%W{JPJ|J^7z#$gh%)e(3+ng!~jc z{hJ9%@~ar|;u8EbcFeDmnc)BEN!?k0`RK+*WVX`9?lLWn`U?a&P-6s2_%U zXV|K2AX$8K5Al7tf0i)X$M5=i$!poG^fn-tTsq-ze-){q?Ee1gKfNC!-ElR81M2n1 zgfbRB{8k4j>BWOc{?Wo;WwI4sLjHR-2=0}Wn;?{3b7lZX)AK)6yLit!LHUR4f4#-j*q7Lv zJ6y~8O{CgEWT}6)CBG;!faAYbOK=PE&0HK8nrF1gk+&E6XEk#EETr21UagkxVEw@F zCB%&z%FY?;57l;eO>^Y`aQ&~h$j>q&wzy`Ss2>J;96#<4kMNi1{u13E$I4%`?mtYT zzh>PZhsZxZ|Et2}=XN5%fbLY~uV`My`=@@{ZO8h*l`f#lepkAOQCu#5Wc0zWT7 zN6(3&p@oIW;%|0l|0$CEqR{_as|M8nQ>!W(V2X<=_ne)vA|fKvGcZ(DSD(!ie`)U| zfvm@#am7fJqhn%WDeLLUX=~%cz`zg(|H2197oyfY==Kf$mwq*sG%RSgPY>9SVgGof z2aW$5vVfJV-y!Q_!;BS|gM$MHAK%2$F%H-)Oi4x6K=fHyh@c-@_yixdmLH)e*hq>s zEx*1#)8Y&RE^v}`o^}~U=?RMMizw;Clfy=9e2|LuFEBpo&vp> zMJ0uhqlj|klH)qVp-Vd_#wk43E6~2EMhi7%{Sq&Yo=BF3G9VAz-uW)`A8qv&_`i(> z0D^xv7P4Cg2c?MwdpJ{s9AbU!66ZtSLwOv_3EqQF0 zTHt*Pfyy9xiD{rI8pgp-9&I?MlmnfRx@4p|W|DznQvD=J1zKVBlREi?ww*#;VYeWz znofvBj|_)+>Hvixlem#zpxPSEoa!1*7%+WPpTUv9`9Y12-Q>B)a(P`80XZl2ci8;A zJPFM0+1OYH%WqX)1}PwvUO5(%%4^D>4K|#tS$fO;fDi_iH+)pg)NO>DGhk&iS=bM6 z+qOcILddw^v+RnpapD z@}6h3ukU61V80DnJP8$5=;fs=aKzHD1Ac66qY4Tr_V)L=y|3uE$H7IPKCQ~Kr#Rhv zP@4rgeg!ox!SXe_fZ~I(LSD1UjnF6RM-GTd4@k#r8i-dHhukON@t_dol;@?jM&GJY z3G(daG1!C3Bha)y9MEH2_ceN(#E19#AVBu4cw0jYBSa8@q&&n47rmyl?;Zs*5`7nr z47X=&DN2LOYwI+fT1r2r-+xne!gWd_9kWFXc{Rr+pEN?6CYK;1Vl8P{AVMOW1V30N z${~lAubO{`PM!#l4u*ttN-$P?t=}!Qcx4b@sXOx?i(AKLuH#!+-}J2-BP4bv5@6;Y zyj128<&Z(6bcRQ_QlXKeBId13CQZGeS#MxGdzjVq%yVbjN4DU4h-PfNw8qfCwNeq9 z`u^K+ZW#CXDL2pb?{&y2dB&{V>Km^&l+$5@c{L8B0$jspe`sl0`0<$9 z0eQiTKXj%0L?8$dav*AZ-MlGWzUOSYgNQ#K*i&#uwo9L%FK-?D z%Xe+kaA;s_k8ONOFC$Mjlu#B(+7dSQ&O@>w?&ucWJen6=QG7IxA?D{B`uXT^)+NX{ zy8P7rkV!v8LA+k{59su3{=ZoTK(l^l6<%jv-rh})t1qyb3`{*dQX?V|#=wH(Ks*o- zKico`aBsidHVQ<%4Hn3PvohSzEjBp0fi%C7_@XaLa$8P#d{k5}L|FPbNqm!*< zWlEaBJqhPw85$-9m86l5pRB{@vT{*lHDA(mzN{nF^|yD;Rr*G6D{we}d6ACjW|M7; zu@mwgU+*Rn@&5FQeV`z~8n5k~p#8eNbx0HSn=&${Nse97!OR6X`-I#nkdJ@g$rZut z5&2xRt^esRi01KoR$kPsZ>WRcHT2Wkaf3@C?QscCq-7iU^6?rM7rY@{pVbsmqsFP> z()beZ+}%38zvD$uBK`YVr}H(kAl2KAI`+v^A4EI#Tg>Og?Sp38d;S?|vi`lH*!E}V zOXyw^W2)C9kv@mP=53z25ksbH;pMF!F5x2`-Xlnh+pEsF-Qq<9He4NTkPp6QagfJ3 z%THk2alp7sD?o%9umc70y{qek#yCTaiTzT`;Jico=;km;TU+}RASX79 zF&`@^yU8K0$pM=Sg9ltek8@H70eVyFc`*}j464}UPbF=EdLjtu+A4z|dIw)oI<)ov zc)(xC8p>mOpf?-$0b#d$MI2|AuIPz&_6w(SEuqvyw>xvv#FzwZdnF6{oQ^|!CC`_Q1< zmkN5spoIfH?kvOG=Xw^2J}73%5p-U;L$~jp*2iM?PhR;VJ%(JP|gj{^A4*J{7!>?TZsI# zny`F2=buW;`o|wDxT4?^!VO&rh@Z6XZTK4m?(hTzhAKJK*A8R-_V|c0rrXDOAYNBJ zx)!+PeuoxTICc;7l`|JVzlBxE3y*_Y{V(tCCu0k5)_FtIik~>z&$BFUEc`2@r;~RL z*P9+Wn=}niTwa0iyPBG9^==y${3g12=cbVkZ$%-f9B0uSma_g{@-RKI{7*rKm)wmH z^s+CWM+y<2&mNuS3F5EoD8A|~LUlPJ&RUVPBMJuVjPE0M+eTfpunTlgh@hO8yhO0Z zx3Z@#tfK@6lHAl0PZIOb5)m4^1nkVTTigIC>Unkhqlel>S3A#JYO%BFd~FGB$1s>K zn0W={mOCidWs}9s#4i0!LQ5TH*UNj&_VTng!rUjzV?O?+MGB;DtatC zeN7HooRE*oVmMIba0xVlVtd$nl1O4bMq)U9Vz1)l5~L{M0#iwb(9PIP*>wA(q(sQ1 zS+mHpWa4C?4e6<|Lwn}vSFc(T^HQnd-~utj#S+wLrD>CI?ww-Zgo)--Q{uyjkxP-k zP#H`mi3#hXpOcf~h=PZQL#II>#00|2)X)<;C2KyApuqpK1~Fctk*ks?NTY|BAEO9d z0lcSKPBoUS(kkH-6rV4|vZ+G8c=(0_bna#E$NYC5SoiFHxX_vF;#W z$EcCQyDaxzV*99W%8Hd*TIv)D&K3t9u!!J{>-*QS zD@w+>z|^uh!KQ3;u`}9ofh1`p@iOspl+qL!h6miDVg&a5Hmqso?5|#-!NLcc0-Y(( z3gj=pG43aW=zvzQYS<&{w+-S*;sM*LNQx4JTyTG3?a(PAH+F{Nc|Lj^oJg*1iY;Yx z9VNOIddb@o$?baIFCTDn9c_>;8v3b1!k~qX_aA{CRvBEW1b0J_E}kS`JKTR1^t21{ zzg{6xWj9#OtR< zsqbT{V>e6~+%Q>gBHTw1O>ubo(B%F^0kU7(mYmz(Ildv@;qi-TUxZ=eqyU8R(P=G@ zME9h`!Ui+Mv_?Bua$MsDT>Xp}SsGcBZ+UpXh7_8e$O0_>b<=4O>TQibdq)8*MH0V% zg688~WQ)(|p-zF0cSIBzofc)Yibr#EwqgS_*@V#Hz?`I& zX1%>}Ib6^3x4RdRJ-!F?HQr}2xil3%P8d1Agw zr$r^{KPc{#Jo9fH_}@t{0Gv}}%oFv$J7jkTz4<0MfCFMZJ#Rrg6EjOoV`*#_ZTSK9 zVZm+SlM}^9cgBYcUjtp-X{XPBzAS1KtRJ(bj8)Ud*c?54 z%b_u;k(IwuWfSs_E)4U0Fh_+?mWy*p>Ip5#H&KqM%cnY|F*oQZzggyyP7dpL`DMk* zbBCwRXU9uSg5o}-`%7Bn24E8>tDx}jA{v3lLv+rTpGOiPneUt|Q`?Tk$dG z^@GPk-c(E8Rze%Y7#(M6fL2XIuP)Ks8-DZoY+E~P$Ks27YWAvYA*Zagx|`DMq`0gN z>7jURpF_Om9;r!d-ok#iv8`X?Ws6J#d$}6N(WjccltLAvjL>_+Oq=o4RsBr zOw``k-lKYRJ7ve;FN(A?hRV|Hk_+?XvZn8EZ-Wnev2E%gZ0^S{7E(hVJ!P@N06y%~)s~YMVP#gf`jI z?B2hXPbTe^W8u8{(3Z^-l5(cSaF}B{PMU5LVaX6Mwa|a0?Up`TCH%7a4i^m6V(4WJ z-T=+2OhSak^|3~i;Xezo&zwTu3NQPco^C1LB+i0vr;pZ0zPF9Ix6k(qK4_5I-3~`B z@2__*N=u}WX&~ARRPN_|azfSjb}o?@#LGL>(rIbEzON2FxjKJJ6y%iT5*)EK6byoz zmScE1V)q(-1Ef?}6bz~7|2F%2B5tV-G>L9&%gW0mb3N}rc9Z-x)Eg?=lEvM1lP&m8 zaa-EJO5tQLz?pX6CMQ3tI^pfD(9-%g`q&q4wlO6KVhoJw5&F;(`wjGMO=UqObNjFm^JSH1mLz)q^HjUG(}6-;bpe9TE5 zbp=TC8>!dd zRWz4{EW8<_H=hT`3g9`QS1{GI)yh1<3Yr{rft|0funaOv*6cSMXdu_L78#MZS4#v} zu5Zzk)s%G7C8fzkd20G3UZ-@ub&AVnrjiy`2oyte;HMXCrK)OMSLx$g%tnc69ji&-3hI{}7)s+vw;1k@Hw#vOV26uO)ISbn?p+Z%)%9Yg2Zc=g(S5>c5hncreDr&v>23v@nC>-*d_L657UvRobcK5jf6 zt!MEDfAc%UG<*X42Mgi*&>|&K=-?W;7K58XOpeE$ghUD>XO5J{{0%7y^)+hs;FXC_ zzI@(aKGus+%LuqJt%--3Ywh5#c8=mo6ei@)LrMfEB|INrlzbYFGW5u>0eLmDrI=GM zDopr%5FO9jT3|cOv>o`wljUKnBQ_tL*FU4&@DAk#?WXB|F1O;qtq5|M@bOfK$ZoNkMWmP!CzH=nRmCwODP#(+AxRa2?=B#&jBV#1 zfL$4EVz|P?HE)mnQ_hQG94qKRg?aCGnttjp@*__pB6^(d8PVZhs+v+Sx&ym~oqL zgQ5cQ35-A9VVL?4(EJDuBDLf%#=Maf1=hAj(mbYFLXJ2wBMPZPN zimPOaJx@A&jl^ciXkRpE z(_JUj5*~Ff)iIZRKX|otJN>3_5>FigGVpRZob@bSQDxFC zvs)6y`ACVzPF(5cM<#OKq0qc!f4YguPaYFg2j|r+)FyBLl+L*q=6TLC={i5Wj|d1Q zQ5N$G(sw-ea}&j+kG>#1F-ry=(HH@^S4%nV+8zD zg6{UXb+SZnB@f#qpQdLw+zgONpjI*Q-)Q1CEssX)cKbNm#huR4pYP)3Mwq9^5^dhh zB@!HztvZTF1S;}_*DhfKn_x#`V;x=iK%q9s`H=|Rli39{--jnc9h`1k=k>B^EGkwh z@Wy;Xr(vx>S@FFdXHBfPq6uH zUJ#*Z!m8y9WNV&Yt@y+n%;YJ|=G9>^E}8kAP|h;>4}3?x+r>x3(WiT(tRuTWnD}16 zCBhdLpIbSj5EG6y&r|})h2aV+J-$!sY@633*59x%j7k2SsHRporJk^L(aEugdXQJ0 z7hPZIGvrDC4Tqtc`|iWwQmBu|DJws!H*WSIbFGS)7DQ$-9@|R5@uNv7KG$SsF70!g z6w*w}Y5&md(Ama0-T}qsqphn;iY<+Z0UP?Fbu~75$yi|pjA(VcOzw%H_(F0sxp=~_ zGX76!?x2XYfq6-7J37g|^B=m2=UPH6h^I(tlc>1Oep&dOFFm&VxO_{kQX=LDOAbtz zAA>Rly;FmL%}*fmdJ)f41RE37w8P`=t!9S_m%A6&lKo9zl{!o(Nze9Urc{!~*%*=! zcs&!Q##(D<3Q7!*DTww9-RZkqH)W~|qH7y89E%G+o~gYc%D9}zfYrFuYPlq8z5eQX zJVOl%)ksy)NGRhGQWb@@P$1geS$&yaI<3Y>1oo~a5!6{eH#H|>_1xwmHfZb!3V=US zfRPK{#N;5(+x>A~dw9GtvWmbH`HAavCyVr^472#}=##HM^glSjfryX96Y7cjF}-or zrd!FUh+)B|&hOvgH4JWvcYiKAoEb}Y3}b&~iPnRt|5{YseY+o+PSM*S6(OGYcF=W!GlBDl$8Z5)jex<@m(>GyjkI6Yg zQ@4}!xLVMTar^F6OB4IGMNwa=R-$%dd`}Ctq0+Y_sFTJ1z2fvN@9>sR#O1wCv3;SH zKh!wEa9*BI@NUL*%PBDxPUh#F&5ZH0v!{y}0*&wJ9iyEa+2B)xXq7Dqc) zUNjIPG4u0wIlHB$jfRby(v(yysN7z@Wp{VJxp~FIyUzvD7B)l450_$wpA+t5G~8SS zU!HcBvun`q6$`e4KI>3x?O9xQGK3r z=vjYWj;2M$HrFlpuhpV>j z-}hmBF?5x4x7{`LczI}ZYR?GaI%_kzviAIY1rpXU@t3pJj22(BBygsG<^CpwK^I~;-z=hm7qI!BIkDhu<$zhmmtxU z?ze-1I#b+rNg(zK*BhM6tWg542`LMC#!cw~c#Z(9nb#Fg+unk!TQ;aWbGD>jSJ#%e zkVt~L#1$z4%mN}`hu2y!BzFDIS!bWtfJODD9x8>Z?PjLwy7tu9ISKS%gd4er)Q){6 ze!@069lkbMUq>3RoZ@XCR8bO&)09y4^`uCB+}bcCTmLin(*Gm5PYg@jWN;x{tcUg+K2uK zt6UL%G=}-R3+RsDeK$LE4YK&EP(o8%U%Fa2;yyxUXdX4r@VkV~wlE5zZBgr|xU0_u z&K@mLb;4YN9edxJ!nCfr=nnjM`+u@dceW6Q3l`m$vY#_tR4lSSfsI@CYe*#OG^SR`hQSy)CSq zaz5hqxt!zoDd5g$bWiax3JlO~*lBx;%YKAES|T1jc;;)+l}%w;f~w2I>aIKL%L<)x}GI>Po?p-5MsxwG|?TBZh)HKIw#hlVC$fDkROYtx#>keZXKTy^xD>DRqxp zI>Ob!en*i=shujTEsGy~c~@e)v(Zx`da$f1A?g+K?uPUMo5^{7k#h%^XyfNM9^W)p zRx^D}Y|g1n(AJMnzHbQxh1cU5QR=o-CFLF=)M;r(65haMKPL4}JYU!+Gki zUx~7T7WMD-slxwg!rR*FNih#fr-0^mG;4;_e?t+&-&lc#LP0CNh;A z{Pw8yll2oz^{rj)Tf!B(qAQoL6gkGXMEJ9h7@!Kh^?r=H1-eJtXjouvBM-}`;Eg=( z^N)ySQ440~`5oXsNPPg+%ok7+_8pOO$Z5WX+H7P zi7`8Ysxlgy?tj|wc{pa=sYWgs3>j7BB)3Ggek*k0{-M|3cFv^adqJ(wj$b?0)(bhj z_E_KI5zMfqnsyA_9&0!`WOIGHSxDr4tVP8;KW_WPFX83Y=)2Eh!WMZkW;ekLHshuy ziKoruD~cPNQLyH@R-K;g>kKM?n^agb?vFVTWn>cK;TlzSq79%`O~ zWCi`Qh@&}Azw8rFUqt(NHDs4=9ut4~Z1^_QNvtu&$b^kd=4JlbbiRu2r%VzA(u1H~ z)TW2NjF!hG=Hmrz6M>?np(}HQQkg+n3G&w#gGd)u0?l2V4b1B?n^+#bevTW_%MZ*+*UHLfPGU6tYuhaQLc_J+;|2czLM`?WH>1}?tQFV@`3 zQSw;vUAkub?&7vRs=!JPPi?&5?hz8o%zAg!H@@S&&0yev&7p~nh@-%nkZ35Ot4-ue z@v7uqn(Y@EwP!ZMjCt24A&m5ipxK^)V}X8Pmo34#tJ)JnKz-`Snw@!N>sZkB@_HR& zw;s6k9lf%=rz;WRD9z9?NenCfcp1y2;HXz&>YDGi70(^Ig&`26i)X12lArd`7FG1P zWq91*BX)L)D9?dK)=3w+;LtTG38a#ekwdLRX^?52>yQ-iXtjmTE(WY%@tw0)w%pT? zb8b2o6C{Km)}UgOx`2D}9nP<8h|jiQRTr`YTM8*csSlQO|J7##?n?Z1h(qwKjkaJO|Idm;hOW95Y z>%FPs=s7!p3tAt(h$foDN!ugnLBluIG5*2#E@`nEm zeAnOdz9qhW5ed21-?yhG4|`DW4pr}N1@Eb;J&o>mIsfrn>3ydxmQSf&@_n$oR@(`b z-_I>|zlp@PGdYTqK!ht!^$E2!MI&0o$n`QLS2nih4mEK)x~y>(y=kHOGwM;cMe02y%wD`m;xi5~OgNZvmzjM2# z+jr^1LGZ7gBZ{p`Kecdx@6|#)i~@omS+*!=v@5yfT8=$Y+Aa{72+LP|kdq47I?(BA zuy0S6AE^XxhBFox4@i7=iN9Q5xA*RjK^Gz9TvWn9UN$~-b2i>M2y8qGF=qOQkNIB^ z#t<;%5f+DojA}s9OZa+TcRa^>8Jl}6v`LsMb7~3-%0%H@WSQBfE?+_~)l?sxZVb_N3T^a7xdT9f1sOj?B$}_90$(zb*SXw*Oj=3V~ zJU=oN(Qx0QZyWlhU|;2PtBq*nN5mzUl#b~6L^cB?DL6pf%Xu$NUR^1E>=R3?w3Bf< zbEcUwN1+85*mjVV2h7`FW5_#%IIgCOjENCXf;jTU@ebL({Sn2X)i-n>k!Fi-9v;EQ za$ximW0lxg-?P$v)u=K|wpxgc=PY8T*DiTw%a4)4h;kA&w2CfsrVP>9#$kgLN}QRx?(tyAyzi>nU`9_Wh`IkdeqLS%c;P?VTe~J-`5L>B`aTtzPn+U zsCJDB=r_Z6M0@n|b$()HepOF+95ocgY79aBrAr|3tX;(>iu3;52wT$Wt zwhr(vmcH+=E6X3Yq#Z9Rc$?2$)$tR;_a>1JNlr-3=>sHj+~q#Frp2Q$CPuG#Au~9h z_{&Y__3e1&@){G-YZs@&n65SFn7ZU?9YYx>;lTG?qK#Y~7Z;d|Z*V0*bkuWq=y&6- z9kP{~8zXIepP{JX+isR%pU*`bZB?{(PTXO89P2PObURC&?+r+AO{Ze0#%EGtDOP={ z7Cu%&nck0nD{x0p)aIICp{ShPKLf?$oJ=xCkXL) zaq}SqV+0yzgOfdho|Y=~!?z)VQ#sTOy7MSl?^Id=>G@rd$K|Gi!ERuPV?;PFYU9;U z#obny_~yKIJze^Dg*#|4b&^&LBkQKJF#1K~O4XH-TY*;TRF4t2sD|52j1}jt@uH?W z+3VjcUC%-dt#T;*dChPuL~cHOZ$3Ud8fQA)+Jvu&4awibqqeaktE7(2bVQ~MnIkx| zFk=`see~P$$;M#f??0EM^{i_BuqO6Q?4yaM_O4%s4YA%#T_}_SC@Bhdv>sVZ4gNL8eGaMe` zp6)vlj>`o_f85eqj1jLmv@Uc_LX4er!|uO5jW78=XnHQeH@9m{s{nCv21-oDB;iZV z$Xsp&P}#*QVQ;%3e4ljM0>@Ma;ISB4JtE?b^(e3;$ZbGO5=b-4=I(=i>)4^F4t`^f(J z=ch3CDRs&`>piNXZ)x|R8HEgC} zXt%ny;a9UcGovg^dZOcbB0LbPohmsI(EIe8#k)D80*cw*usSbvq(!9H%iBkFJoc|q zCV8p@gF#dk@H8G`cBHJdAGG`tGcQfb>XO-%l*bZ_T-3^g*|1wc8-&fC4Bg3jRViAf zhDYFC^C;2aT0Ythkx7zZCk+C(2*AnZ|u&`y`$H9DZtD!FB z+5KFSv*v^$KR&7r_apjxjO{?6I{8o-%}h^Z?hMPfce_c2b2NI?ZX`5|l8GS(RdqDn zmDAhRf_2s_$ijVGMSog6o-}we)jfP{bltQiK`)ddNi~>Wb8*F7m}XY@k}vzhc#$lw zxR_cc0V52>nRLLJpmb0syG~Pug?TtpUGZg#UX{TD`GQ2Gp(!*9%d4AEUbJ^LaO032 zYR1C)mgsschm<@N^si4A2O}p`%Y-6!hEZc*nmT0m<+EoOR_v9buI~><;tz^ z)*i9rryNkE-POhCt}v+xQ+IokDpCclofNI(Vxui-(k#MmHQSGD2mYyHnZB7)jw?#3 zfMG!F%;E6DB0WP&@zU zOA8!4rm3eD9{1r8kGJ?8A7$~LSH*ASdnBM4hi5sZ^j=XRsq^I)cqUQV2+KhqP|!Xx zhpPH=y)NjQeDN-3_p14=pKJ0|GsCxvrmCby#PJLI1Rnyay0mWH#qp{4*ow5xo);c~ z-&IhLwISYq%eWpWfs`4b&JMVb>}De3#w^k55nbB5WRCR84|_gI0Heo#W#z?@BJr zW({o$ou90gC$~QVe16}fYv2^hxqS>`e>cY@HMncVM23-nE7rY_#(V1n5cbM?T@a5$ z9M}vA+w{N>c{C3Bs!MakR^;{uet&0?;0IyvE0 z9dW$7ZUx`u&J-FFn${oSzl=m^G~^V=Ql|fSOh!$beGlzkovY`>%JwPMw*RIq>Tw3o ze&P7j7xCdTeFPTXb1pY8y7_K9rx!_)dA2kD68qgQdbGRiok@a09CIEo#S=h8oij;V z_j-0Gb?Lp?!hJlSXN5sn31!5ibiCxD3Y*VQXp` zy;o8bWPYylsi1ek)rGu^^c>-!!a1_dsi_M|xe_MQWSp9H2z3>D>D2G?<52^>i3!T? z_5By2`93*146N(j603Y`F=6oG>yg~*u<(;Nbl)Q2P!W>~<+pf)qq~fFY?dZMlAZ1JrYtjEG5t2Z#Dk2xh&k@2c zr{7D@j;W-*GnzgnI=}IF)988}RC8(F;tOE4z)@8dbOXSwF@COsd4@0`msLyuM<7bx?BK z7TAv5Zsa@|&Ub}=CH-pSNbU_~7Z^^Htt%6`7zCcy^^5EaluhD9RxMR9V%YRmxguT{ zi%7{r+1H9%Hm}+Y3)o4OKMQWPqUReu%vpL{C@eZ^jrsa{)y4*8d`6;7W6_(=t#z*544i$h zk#5-Ud}aDM_7mCi<$^}1G`52>6l9Q~d?|b%LQLD3dbazM7v-pk9zPK4uDqFtJwgw) z!&_dJkaQmQ`b{#qPIzAv$h#v@+h%?mB_k4FBh6JoAB=V;p&LPfWrMQGQ`Fw|?U|VN zI!aMgSvc&D8eG(&9#R`7 zmdQ`1Fgh69b^$P@WfvMXKb*n!U(G9K(u(yWy7{cJo3F@Ew}>>24=#jI^UT~E?}&pJ z{JBQMEM8<6DO6v2Fw)qY_f&nzGETirdyZGiQ%p@<69#sPKk+4oVRQNLZ;v zpY&;;Y2)#MO0R-hMUXf~-th(ZE&PUA@5*s;Zx(JDQuhdQos!cX5f*B?ReF^Pqc!$p zs6rx$SU84FtXNZcc1XeyDweqJG{-0_Tit=6%UEhq;hk))Akh|rUUZ&TYI@pE+1eGc zO{0rTfRQ?8K>t$^G!4MlEda)6`zbYHj3ghaTLNr z8H@yuibqD29T?Zmmm-}@(n6Y1o7|d$V9Tvv^BKd>CrV2Ay>uet5Yw$(`>bzn)Djz0 zO_rUaImP!9ig8ZMv_(S4p6r$stujrLTe-t{Q@&!cV%;k-WUrUxTQ(`VMPGb&now#i z#^lk8Rn^#<5Tf1n*m?fV^H{Le?iEkq`jufd8(oNrFxv5%s6(6CyM*uCb$s_bl-FZ| z1y;RKhuJ~oZLUdCTJGpc`!}B@jO@lNxl^1Oa2+Z`XdfuTarT#h9pR@34FjE>H6Bu}}ok+BL-R?Z;YZq-5-m5s5 z#`9`sPqSJE$s1$t3d)jFaH3Ep;%&>r99@|gW91Ojo0J?ZQ&&>2A1E=a$2g$1TynJ! zxNn*6Af#W0?(Ew;?dssSmwqV-HeG8dIKSFIJqSDR=riqlI~i`2AGq44A;Tm8Z8X&6 zOooD={R2Nu{f(|QGhVb@eKMQs1B^aHGUj;W*|%G2j`+I)_%G)EXwWc?RV5n6>Bs%n zD>f3=5jO{`l-QvOldy*yJFCsnX+nOw*YA;lyfS`ygl>uP8>)Up zTk}VTuZ8~u(Ec|-{jG>UF}mg5E&!&Anb44rdP0J~Fm@oy=3SG&1kJos_ZQ)@TJ6;9fC)cI; z?-#xv#N1-GsTkoLl=o%HOd{reX3Q};8FoeYd%i?^*14NaQ0W)GJx>R3=d{PfN;|AP zF-0G!YLoO<_ai(bwx+d^`Ghny$cx->(2kD-@g}Nc`sBv?-Es_Iz?$4f*9=Z6K+BXx$e z1s0fg{>sEACJ;lm&e}mV*PJB_E;4nYu9Ccf`Iq{bafcC?@@Z^+OG@vt{F9k@p?b?? z>eP3iw^-#3_48_dk~sFoqCAVj7E+{BDsgpNzx_zJnb_q}#-(DxrNXf<&)*w>P&<=aHtk%rTapU6W@-&JPqI(<$UeNeI~DcC-eYlgWz zXG;zlt>d0auVhyB56+#DW@I8iAK50ywc7QGvljjgLP<3@sZKeov_D^wz?XMXC}wke z<$KR8&63??i3|;)Ri;tfnK4)1ZT^wEpR?x1?p}d1!E+R$4zZtFhK!HVOB!R^FzZUK z7y0M!i10`68{xRMN^X?o*&=Hu7~NXu*un1BpK?mh7?+WLoKEaPYv?LC^35f3ny7PGVts&LKf??uA$@JJjiXaz+%IFB#;0>K|YWiKzrxH;MkZVStl4lJy`Vqh-oSkm96x)V?v& z5XZt}J>JJFZ5g=?j7)44EYe6CkX_ZLuo>S~35u{rgJB7G+a;sKNF-+5%IW*qz&g>}2r91H0bGxH?4ph%6| zhpcYF-C$rDlGcZ56e{1Jh{hLZ=>5#w9(iVG9>1B>jZkGkENfLZKF+!-H2k>B>j~f^ z@@c=kbn2EW6}Din0eeOsMaUOhoD@o?Oc+eH1`QNCQS^!G`D4^;MX$qJ216|w7+Yps zRiFHM?ku4`>J`5QCfR3FvXr7ko0dSgcQ!@tKu{#bXTi}Rd@ueXecz`AQ#EfSH1={Ap` zZR{|?XhLwt!G!`!WD^yYBy4|8!1hu5pTB0Iw%yeA9wi;=-E4li8Q{g`=grMBfq`5@ z5t0Nw;Fgyd>5Ut25Rdd6a%1iDnGKb*D;caAbzIYUC=316l$76=skBgwj7w=&bJLr9 z`yEtCGYN(E&zuohJeFg%R6=|+Gn1$%7Z&bEgEQQqygVEPY>kl%i~oYeM|}}!oBt0z z|Cg`&HbP;+zRwg>_n46VOk}uIv5xg+{KJzU zA@%6)ogVRJXg8Afzl8(Qk)u*&El~~?N?p2G)*3tiZtp}Ua#XP5IlvYHK1A=|zq#^? zEFI$&KF0!?IwqQV;owfZSXLY(61;jnghq*|?@HyHy0zALLhQW76?d@EZ0>9RJR>*k zhdA+KeCGt`-aoJlGHhEXkc$!ZknPb3tsIP|OIen^TMk6AXh&7w(LFE;Y}Fzpv(wBV zE@zKhkrq}_KZ@myXOMmc0-(gnsoGKVy8Wff;Q;_Fe+-2~uIZC5|KCZ|YKbCTc%EAQ zPnN`u1KX@{XWN?{qJm3%qJQQw@U-w5+WM1f(L9#&&3UXzS?%6`>msyE&GhJ3v{14L z{MgXy<|1{u6bndWU36y?TJ0|3`aV2$%mUz;ae9O2`gmhCEw|)kyT`mKZ5$qTBU6N9 z+IWy09Y^tdW1iD%k=P2t6+k52blv=NU#RIgG#>P(h0otE{geqW$XN5&k_U6+)qDN% zTgVQ&nxDW%>CV)x_A|ZhwL>YT`WJ-iFy0<*90 z_@|Gm(EsRrP;%Be`N;c(#m!3HPdB}Df;U~Xd?~~i7nDN%aHL(XPN@AuF3H;G4%G%x zm1)26oYtl8(!J`0s4^*I(eY8#QakUz47)XhMqg z6}8s-JMYAmtQ^92cV*wR`MubDa0ATLR-~J6J&5&jtuM!@;`+Ey?Y9qT^Ot}3j&fX? z!y5#Fjz_WH4qQmo7+Hww5Ei-CjaRl5T)|~qtoouW%TB8T>JmFzco3}?{9H{ikh2rP5HqB2j6OwJZGN*BFYu7B28v)Vu= z@>NB|;*>z_jS3&~RN2F5>025Fdf|ds!>t|&!m(;t6+}|7quQ5(am3u&TK$@%jYE4b5$fOtEc1{8e?pc0RYL2Qg^3lS z-@H!AWFPY|cDuyVBqcGpzyTOVeHr6t+CHWpUuD`bVP*MU%ym7)pDI^Xko+wPi8@lK z6F*@%NU;%-MzMH~MwK~Bt&y#NF3>Np^N>hP#7xDjEu42p#FdKMfo>?MbUw0q=IBR( zV%{fC&+}@nCv?iaFW#JZa?v{$-)9?dB5h(aR*ixQFsWv#(mg2&;W?y(p=G|%B#E=w z{9Ye=-e*8MLqe`yoAYx5J=;mU^KSJyKI6YmwuzWEz~JL-)~+LnsN*yG^&N0QRv%yo zk~wm{Y)Efs29m&bJkL1GO!)>pQR6miu=YPyV-0xgliNvPbgtV-)SW%FneNbyHCEqy zM@?v2iOUA0w!WYrSN2HoL|WeRM#`T%ZVfmwvBR=%btKpn&3HVhe3Me!xbc`I$*Fux zeZemGW+#%!>$RewF1ngrIbFsvdV;a*;xPzI3V=rvEZLm6L-dTwawi)5c2j=V_t?B; zr?hEaE`FCuhIhvsB~FeMj8vfYR`jAQbQu;r_#yqv3Bm1l`8MP=BCL4$Jc6y>}Lasmi?BQr5J@F=y3UEw|*D0XC+XCPiBxtcS#ejN#k; zGw!N+*}#&dZZD3E7x%CcR6-)h_~oaM{dm&zD89?JSu2~I-}C=A6qS|x)ge#??vzt_ zMqhv7oZ|FKssBf)Lx;a@-6-Uf49cexy}pn6)FAGet3X?=aKkoc`AHVzHpf>$(tp=3|`@WB*O7mu%yrZye{@V3RHHE|%v-a1WMo^V*^zHLpmt{E78FD9x6Wx(eD0|5zJ zJeU9r2`hrsv+%#knlBQ?6xDyh)Bj2!ef5#dIV<`P1UW!hpd-}VBLtZq{)Wy=El^3| z;~yG(JH&03@K8xmYi8?jFE8OG$T-Q`9j5BD{^fM)6W~Q?Y?6(iO;{$dl`6&ug5cma zPAj(d2US?ep}nWsyzFojp;Vt3D}3;!k?QS~nsLAl_@wq{Zr8VcTbG~RF7}~JGMcGgun#yu z6Wmff!3qYqk6Azci8^JO5dE>_NZ3;Ik^k?JEJfVA*o8aV>KI*b)P7e3R)eO)&i7yL z2NY$>$>U>kICvfi{b0R!=O=0IR)rk%svf|JnbTzgoq*Wk2eLI-)i5`7Oa=|(FD$Bo z4oi(KsuH)hpdwnzfm*+MD1Av^&?v5I&tif!7=PymclUVd2x`kYB*fhfomqRF{Bk`< z`zC(#UGL_Al@Yq!+IimLE{~IGeHyTZA#;qt$Ky%&TjdPe>_nBn{Wi=_@GRe`i=?!T zzsA?;Pn#(9Z>ZJ_ua=}AX6J9n|mTobs>9GEb!!YS;e0XE^S8-A6#&i&npAq&x7*Z5-=seHYDQQ z@kWS5QLVPyQH5mdqEl=k_nQ&Jx30Pv=?~ZtdYb0tu|c;lbIjsjLFp5OLh`2SO)zTy zj>f1VmDQ`Bv5~=;-t#y;sW+&O_mtP~h(hu2D(rxE4TRenp92{>Kd-=lMV3?;lbcsJ zXv=BF^2ykbB^@^t5~RX|T#0jc5O3;pR_X;c4@acmNWEd{BE#W`W(nioYX6T3)n&G` zjGybnvc9ft5wJ3F#}~RXPGcOph3ApTiE7c)r>UVv4_^7CQ3sM;blu4P{BONH=iZtU zy;_GKE;)>}-Ek}s@{h+m2~cs!tnDY)AwV^nqRSi_`Wmw<7KcR`lb6Y1curug@;W|m z$DXD@`_Y;|O?8Q~zzb~i%%=DA{^`=m@vrVJzuhV1mB{=%_U0?Db}bJOYNY8P`7|i8e&~`1|bIiMxdoLe}l;3|M z!(Z{Ri={T7(S3S{1)-}^O^?UcHZ)AsmMG$Ind9RV7v@$4t%FgilE`S38nb0TE_*mrXn$~TTPrs#@_`jIX z*dRQGV!B@hk!o9am?QAh_sm^mqgk~)0$JicPkJe+D6V38?ss87ri54MSO&o=jCLS%;F1WzM(_?I-(Yk#>5t$naO*1Q z_V2)(t~F*%4YTwpx?k1vJxmAl6i!_N48o3wTM@Z0PHm1|{)rhPu8?g(*&4Kq7Ak%x z&)B^++E1v#PKRV`rm<@7=8=|el%#e*@`Tpu+$ZIz%4)@NuyUX9n4xu z6#MT&f_VDO)ENxjig#QK?9#H#c4~3WbK11_fxtj^{Ee z%b5aDR2JVzjMH1>pF1iVUQZh9mJFL03Z*7(|6Jz+Y%1apquQsSo_TW@S|&0-=`1Tw zy-hD;_Z@fMGf#B=rChu|sM3dEJ&v;POaVJN&#M2ZElrZ7*hC~QKeXarbar6Slq}Fe zHKvb+?jP^k7;GKmZo4a7J5OYywR$FAyY$!cx_@j zf-gbaR8wNMlvm}(yJwLUV<>H#e5{%HIk9`|X12aFBbj_BV>}XZm+wsXnV%__tzqw+ z5x?LbKfR`V{4@8yTuvX!)wiMKnnI-3gDuhX5$~OWC3NXD&bcQzSlKKzWERcZ-@OO= z#u@bVYkV2UrDe9>oh2~;$61Rg`Ribu{GCY3{^>+`#armsxA$fNNzkT#_gI=Kt?R5U zZmXAXcwZwu-5;MStzy>mp1;08gnh*%cjHaQ2ra)x07Yp|1~`DcRK~pNc?7F}8!~N| zEup4{)wy&c_xEKqb@rJbMc1_Xj0885nr9Jxpx9V&na{}MBb9V`Vk1Tlt;~?^ZpQTu zIw>1lVK&!{_nbS+T<{y?Y;bwQ*Xy$sLKhaDu<9Fv{%G=7UzQB2QXh%}v+H!5XpBguE2b%Bf#$_$ULO{WfkA`_r{e-(Q6E>DCAZxu z-#6<;Qr&T-(e)0KT>5DbWD%6(6h-jdItGR&WWsT(?HA9}jn!MuMO+{&y^Skl;RV#A z5>yE89+PU9oHzbVPnLM*8yp(GqLPFn*~mvNxs7=GWO0@5D_<_1!J>s$rZa zCXB{dyQZSc!yu=_`lrfpy11-CQt;wHyGF?vRsLcm>l-+gSG1I6F459Yu#hKqyUwt= zo@EEu>*R0R#EB+=8(t@OpL4J&gpT1 zEzf^Od@(0QZdhg30y>L`r}uB%HIJw84SI`3EzF{afx@h7L5_dZ)&m?Oo->Zr3Nhp3 zdZ*ie5Xn3Epi8pb8h|w<8cWPg9b)#Lc=pYTG*Z(=8=D7q$GDwFo%qvJ^V@TSt2x0!-2JQo5R~dqe#!7- z9}Pa2q|&_^-oPLC3iVmu2ELE*So_C)mt9+QUu78@gfX1cJ|z=m%F;Jqj>o=*JZt!_ zq5W%R`16gwM{0-ffO_O-QLN_hh#Jt*~B;o=34 zvjjRvO@rP~b{;ceu>f0om~K)Goa~V+g`q3oyAMtywnG+zTWj00+Gh4hTZ@2Z5aK@P zLaL6Ak*8-&{gY{yn=9MKO5fuv@AwD}Ra;|1-Ojfn03@_$(KldCNhC_9ISN{S=y?Asp2p&)mowPmq;^<`NUohiWa4_tH zRM_UeeeYzw9b3&c^P4=t;Khc=Huu9cr#z^ZlD8tZ&-nBDa6qqATk9H*(2b!+asHV! zvH9dLW!~)=89g=x-^}3&AexT8$ADdDtRjtUs%#;yRZNQ2x%{Y8VE@GTLOMGIwcFIt zwUatp5ltr~@^3@w`HwVhs{&W{_FWsZP}=ky_i9>oW(4eXlmt(2QUAqDK29Wae*M3p zj{hBGdVKi<@tPnD(|xxgTxS>h`ARD1?4uHQI>U}R`$Leb;WIKI>h7L}hwqo29~${t z(wHD={!=qt`3X8u#I4q4(KTk*y{6ZWpTREGEZ3Ygq=Ru zrY>@Wj(cB*wKB@|zSJFQ+PtSNAIsC8rEPayf5J4psOF$g1;kPPrjl`YeKRKEFW#%R zK+Z!X{hHAp=@Wp|&>Eojb{u5`?NhZNcQfz#e%a4mPd?#(E@}87WLC@AhfVG4o- zGYr6evbp7!u9v5X#glv&Ztx)RRQIUEAK1$nM{r z$pvXK`saeWdqN>(MZ$p`?{8!L;|=-lMKpydOqMs-6eluD75`LE`9`CHy;U&Jfn}4J zV=f-9ltHa72e~uZP14!KCOXTUBf^nLf~UHLU^-pY0NSHAm!;U=tBKT3-XF+sQ-0y$ z3(|sC^}91ls01JU>yi(52Px1wb^TFVX; z1>WLIyl|UWtv6dNNN?hbmb3OJy`;Vxyj+)QWQTT_LN*@^_Dd*x&*M*|8VmBQ7`uNI zlS)C*=p6FDBGgxYvVh_srYmeD8oasPK&=BoA|$IUV;2a$7ImvKj#^Y7P2=$@Dd>1D zBXc`Of=sLq77X~x3QW}Z2-k)k^c5RSJr~PmqdsULk4x>WIZg+2j-;&3hp-8my#xG{ zeCy=d_t45_--hInc^28$4a(!W4Wv3om_YW8CW-zFI(Kkoz-nfYkA3_jti;bxZnM02 zRMXMUQ>ywhGB2N0&n7)O{+acTk-*Sdvr}2y5Gw$!9WGJ&=-CJ+zv=%K(YfM8IJrpN ze?O@`XbosEs(7tVN`taun7JNuf1p`j)`NvU-*|gazGLxDxu3!4DAU=wufjz(W1^5) z!XPyXR4Xts{uSF(+!X|^;>n&&b^ARp-MEPvp%y?w5S8lB`>wW=ek^WbI~Lo7JvKQ&he=6sjR9)L24z~ zN+rAUZ;ew@^AxN~csMt2>P~@1-;aV`1Em};THz8nS(?QGh4L?~tvN+5Js|vAjqiY( z)JD^S|7@(`=zeCX;Il9PekjuJ$!ruSH6@}h1wni_T3kUEpAEiipW|p z@`jl&Oe;pj+{bVvY8yOUzXotGB(L;WhplF({DS)%eoiEfIpk7DSTvqlZ=mS!Grt>Bt%^(bILhU(Ar?N9$ z`!6xw-PA!tVV{2La5P!{xN$VLl|!pix%VRkuJi}w4Y#G+1!p%Pi<3^fSI7Bv)^+cI zzP-8?T@DCQ)(TC*y`(&(Z?EtT!-`|RE^Z(ZOpo8!Jheqnw9uukz+3n<{P-v%DPvI7 zUda;%n20cNBF6e953>qFePBL9&?3r_k_DZkaRyHU* z2^-VbhXe;;j#Xu1QB0?J%%hIBZ0ms9yV8J$Uup!*EUHgD1(^UW3se^3D<;r#cSg(< zCb#C;W&I=#o%Lp%U`Tb7+h=e?=o=ZGt4Bcd^L)t?tQcuo!>oIKmR$#4(H00`%crz- z7rSiIj#8)j_J^mx>seM{lJ0z3NoSyUgp4;O6I6BE1D=ofH}G10`(0J#JUHAGbRrFt zzO$xsm#Qd;9qwWx==C4bDsuuNTKWG+wEE7J?eo(i4^h{ID%_5k+|G|8*KBj#4aNo_ z%seVEzWSOUz2de2a*C$f>J>N@!jX(9L{{DK`NzzDNxH~ItN(@aRG7f-l`dMhLv9Hg zeBmKJJHj4uFLc>12Xz(V_VDcZduwEkRZO@CC|o8P{+`{oWsDcR#`eusc4`s&%k`8*#!V2ymP# ze;=c<&UY*kG1{2-BA0Xa3`ZwKpHnC@?!4;2KlvIhyrMuhP+^6|g?jVSEtyt!A0MAJ zY}cR}fBcF9U&*3%{YPE~1=7iW`mw@YBNXK3=DB^R9(g&L>`B6^{HlF?oZj4+C2lw5 zC2A+LS6+vWu{a9+=v`cW+=f_OO(&hmbzi2u-$?dI)vxRH1GndeS4J}}b@YvlUHy}m zf3&P<;o+tIE%i%Ve$!3CvmnAoDTR~Rl)?{25WcTcoYD6Mh?Y5mr^3zSoQXPa7( z9rwou&+*S}@W{C~aQzs;o$l`ZT=xZgO5^&E-3V?I*WpOrOxzF)-*;#mR&`pIvJ=HL zNU2ZgdHjoS##YtA()&E~eZOK$BgDFwnJh9$(&~44w`Ma+`Y1yT8em~|^l%f8vD}6~ z8)RT&mK;}2tG0;E@b6WF6}iW6RL#-VBrf5+x8W0jLBrUoI`O{JPQkY#ZDs+k@Qs|M zU)=b@Ag0I>+bbG95b>7kQCVE3Gva4wAC;P{O;dmk%`_xxTKJr>o!2YAIBdBh^6wm1 zS&L6x>VXQNMO_B-v&!wddw%uzH+kf?-{Y*x;{a7%DSbtOos)Iz{EY9LON1s6?aB~l zed9}=z>I?rJG!v}N$7p(^}Vg#s~%#VO~oy%(j`7IWcnL8l!4QUsbS-lZga&%bOT44 z{;?%i#|aadqG?UL>wSfS>-jg;d6?Qyo&AFN-ZXND{zyCzDkPG{MZX~5@XrQXh_YRE z=p*CREAMPf*|$i@x0}MH8iQ;-(hdYNqtIffujN;3+A9v z9Z&^{r6NzC$k^C0V{5$#1@+4eAHSTJgwRc`41czsp`|NHUI8ZEhphF_+M$t^i3Sbx znYKjkwDu)XOG-e)IVt%Rr;_YW0q^_UH60}&;PG5?Z?1A?nRF`#)8IbS{IxskB=y#c zA?ATqXmzr7T`$YknT@wo^k4{U2UEGsmIkz5CsBDv!N3t4bc*6w^IZyc$_Pf|+kdt3 zj~hS#FZknNV0Tl1txHlr9I;ipbmG36#*((NP43TeKWu_@I9(2Mb-Sx0iCZ>mBMCKvy}NCIJk|t_s=vx0LeTx9NZe9)$r=tMbofP^nJy+)vd;xJW)w77h;{U=SC`j6*QVb;DU`Lfufx6da?O3;`_om_ zW4o72!XhyV5%|avIIn+gSerJ<;8oSf-&@@ST$fb5bWr)(ORbLp9`gt?x7})$uRM@E zzCf&V@$IuWhU>KDbntBcDq=!5X^wE|7=p|c@`45|Asv`x(e%sA#$Mr>PY6?%<*jVT z>sPKumi6-pv9iOSt|96JXQhPkJ0wO)a)2x^-K$K-oTeUlWX8oHzr>F`yaMWbh!F${ zugteVtsi%i0!Ld&fj5K!)696x?E~6kG8yM#y$yn~MOjjtUI;y(x%fLicXkLwW~Sit zJlL&v%nzwbkcgyr%5PVobR@KhUrW;xUvx}9x!Edq;sp9k682?r4&U#Wfxc+SDKhWowY$1AsmDScD8YqipV_)vvje_957(^gtRApM+1yFblW z=*if)0~uU~Xv37ogL1Cs6~^)zfDZU^Qmz!d-}7q67YN{g=Lp~$J;8wnn~kr)^nZc5 zGVDo-*K$|iaXlBRchN-$l0UI2d)v?dtDa1sUOMCc6e=AlGMzh3z=EfO7frY71HM4GT664>^l@-<|U~)RV z*A>IUNyvDZLU;Ilt1P`iUsN|frlErK97XgKS|^Ny3B#byxS{u-?hgl=Vin6dPjZ4x z^uS@v=mlbPbFQD{y_&e^5v?|`HV1IeBa=$b^>Oh~=4lLDc+kJYqV?s0_OK+LxPN;y z!lfMt^6|~{i^KNODy9WbyR8Qh7X%(KmRIV!hn@84~6##{Ki z9_RI^JoZphT3l2fiAB=i*ji^7u6p1_dMV%@p^^K)x;pzkG5}#!fJIhDS z&dra%_V616Tw9*4%jh~_i*Vzs$Wzu3W|uLnzkQl=(KY#ZTC@rT<_$I6>E+ls4HyS- z!j1Vn5DxO%;eLl%LyTPxsU4_H7yo7*=E)1tFji(4k%9z3r#{_n9DQfIacxQZ2fS(4P znPnFJWVP=onPlM{Rz6Hu<72D1*29YyKhOgjie}wiTImf3NK)yFu6Cq-uexDP^M1f$ z?O)&e(VAQoetP{hOIo`?;!QW$PO2vGiX7u{+WYI4Yhf0^`^!c`sCP$McCvD6g|GYc z6e(nrVpZ8SzRs9*rM7436xERGspG#;q)#9D|1gtG0V&WV?b zPi&+c(dHJqWG|?NSI6(v*uWLZkq1|&%}4l|+nqz4QH#f%D7TICJWFr~+zZ-5xfjm|-gB0l$m5DcQj<<~-%=MjX&;y9bGDRib((KXU~H1f zG-wUaCw}?fTrm{U!Pp0hIbFY?Tg$8BJ)Xi-3YD0pe&x^N6TdF?lDwM!irggFw4l#D zm7E0{MQa2tVX&ae^pEK>@1>Cby0&%sOrN_<r(tic*HAux7M-yQwP-{sgYm9&AC$mu33Y8(LBUy?T7y?v-Vr|gzW zM6|6{n+!gp(ZRT(;l`Vs*4?sZKT?4C@GU$Of)v_T7~}riM71ks^To$DF9GnOC@N{} z_GOkr8;51tP9$)Q)7oFeN?4IEmm}5QWq#)vmMRccY&vu%QCi*hJ!$?tla2H*3nr^FV0z5I^B@RHku&yN%I z*2A5+K;$<}7@PYfS{ypx5#b}+iFFtIb!QZr5i6n*ls$y-&5PH0r0xoTt-Fg%@|-fc z+~amqVCy~Z=Q`R4&V;{8#;roQq?wDO8WJI?X&I)TE=foIQdoBcJArS`I+cZ;Hi-@g z8Y(3(Qmc*GXZW@zc-{3MY_*H;(KXMUOyKLoNZ*9iUG^Ap5xpsq7qb@lkP645nzRQy zZOGJ+#18RrL*mzlf}owPe6h;uEquI~?lo9rT_B;KwEUTe;Q9S-#Qx`VsmaUCReL>e ziYc|;68$dpRj}?-L9$WUjYq6xyoFVcD$zxts4IQq=E)$mE*>9q-nVG|n$EbGj5A zj!`{5!b%)4Q|hu$D~mjCwo!t{C?_$e<|mPG`Hz;GmHr9G>sJp$w1-s&`t^p@Fj~Y~ z)Wp2?NZ1DHq-OQk)Xr*Id%c`*e&41VVoRF1hDKtxo87}$8+VG|;N}ZbJc|0GOaBGB z+wu+#XBg;>IrjEGF7ehd_Lv|pv{GXEtPj~$04)^a!@=33;aqIX#Cwsr2D@mm;N&!e z!l<|tm)FBFB=eR$`(MNR%_&Omg4Ca~Uw-5vsH-O%+C4J6}0|73}F`-WD0ZIX&(Rjdn1&Wg)3uYILBE7d0!cUS^}z!CgCs+$;ugni8n2 zl{wElzMoNb@Cywl%1JB?fBmlX2BZZ+wtwK?c1-8@8J`c=lEetBd^z~eGKl0zGlh^ftU?Z`>1C+FTR@-P5Z21S0Gn2~#}ZeCK6 zWzOQvMKY*I{c;3scoBIt;t(nF>%WtiDNaK+W81-AAm*M(<`#fk-+cQP)knbM@AEG_ zLb+e(xi~Y~f;0p9;m`XqI$MH3IP5DHav5Wd8E38KqOodguFK3$nfg@er}?*egDlZ{ z=jgqErLXsm0&Ut`A5vgWpDg^xh{m%|mXP(U%JawV5A0M`PxGvH5R&9-JaFF)e7?{d_9fe4~4| zFwsyFth;TZdJ$;y5_GWXD*o4pM50io_@VtFngzYNfSkqBDHy8+RcD`DCjzDv#d?Bq z;6QrNIbYws#+TspOBeZZ__1w`c9FLdG+M6*-gy{329u0$+q5I+!6a##G-_C-NlB*krB?nE{?q+o!#UywN&(PxNnh*@belvjjvAX> z_6gKO+7Bc60zTGLma;F#XHUAk4v~=iKcpRg(Tg?cc>Z0d5adWOH~MC`CNk-=N$2c6 za;IJXT1J_gp0;K^Hn#Wj0=-OV@zckSBd4Xar5rPQEcq=1OxW+ebk_fCk^HepsCRhP zzN2+Hpwt(u>{p$S=6H$zo$~w^r2TYueb*HXmO8mSmx}z(u?WQ=w0@^W5+r>- zS;HD?R{s@iwEYvI!j9|jxKx29_kM_tbH+qVhkdi?o6noEkx#aV0&kETNH^UkL~(pP z?kwTz$5pVL|04_F`hsz80#y(gV1-Nju8N;@XT{KGg8BZ6$mV88(T)Fo4lUb((*W)T zj8U6lwtq0UR8N)RqwDa%wwMO-gE* z#AAM^)K_t~w`59s4?9?nuT3Jgb};oyOz<}RFPC$>G6>R%{?{A-i#i-8goaq>^8&Fp zwdEiJ3Th5DB%~?-8@lWhK$bJv@g?tOwM|g6)Dz}7qnCmhEMuFI#c2ER+c;J$aGsz{ zS5@cvkt#bgJ>OIiW#cvT)YFE`%LzKHC&cC%zMRxs@@ZMxb{v5v-684=wOkE(Z!mOk zJ8&$ou=;jk*4N8_LW;2=2MDbc{~4JB{qrGiNVUpa&_YD5_ht6yx&m`?hwrGI$IphB zm?0w(k4M24g69#&9Nx??sHQjj(=_qAq>+D?;j0#WWKWVty&pBHarwMKsPq(9l2C(s za;A1cXe6(!0S&yVv}TvbHtz>s^clzCF!^_1y$@1NZ=r7g(H)^qrAeiu7oAS~%m>@0 z5?7P0G~Yiyp)-%?sFl=Mz(~ryB=38n6w!Y_0s|}xM}+d<1C2BB z4Kspb&ku~fBD+}tkJwbhSLg7nRZFLW`fkbH5Li^=@V&57n0@raHj=UZ;Z3JrS-~h6R!@YOJnZm5>kem<3JKufnPVgHRmDg9qCdRw!DGj;BHNkW6&s0Pv6J19@wPTAh)=zp-{yltBsC)-m8(w+kBP+iM&4Ep%*ER+JHnRwi@hM84{(u{h+3mdR zv}--NIe!MPq|mCwZ+U~y6}x34WcAmbyj z=>XN9AMtuVcJdK5as7Km`x~M;v#TOcC)AAmABSxZq(+ZFd(c1pjB>uL(8=m`Pdf!L zN2EQ9H3RPMb+#M#Zf0&Q_=)X$o~|Zqr@{(4G6ovR=u$-RuO`X31p{oV2{2G z=f%7g`0rAX>z4Psz_A|gf3!KA=I(fQE@LSjtgv_#TQ&r;6XkH^-sCG@pPl4fnx<=x zRJ~*0zeu<~+q2<$zc90C-^S{c+3sZ+L#A^-gux9a9Vwrs212u>Havg={q-j{ug1D~ z*w5to=R92>E#_QC5yp>1Hrc*i!7|a_Y;`dmccEb$4v7iPTl|gFkZSvt!G%4$ zWdAJti^B3zU;JI57yrA597+FRiD75f7uSLEytz8+9nHRdZQ0}_I3DYvK)Zu z#uEJbsWNGC%q%gmxB$o&Et~A&VRZ&B&G#Dd<2sV5A}V;(~E1|nd%o5l)l zQGH>VR2esCZ+jr&s&G>@mNc!uREi?;=-L4G&zfofyKRP+gS|crZ?x47s7nInxMuDe4dLBrO&DFk!?qq(R zDJ6LlX!S_lE3A!D(c8KCD>qT^4meMcm|6Fh%aAqlYr|#o_o)sY-qxRS+#@>BW>n$1 z5Kg$$MY`s^)~N~SZbb0FA*3iSMKYtEuV|=_yM+!&+-XbwI;=2->l`1dRveO zwm2j|Xn*7dG(aXDBlnjzB%O&v=hGS1TLxZ87j6ujBS@5a9bViVPWz#ezM}*ccZCtN z7;6{j9?TT2a=QgiPN2 z_Q#EPI%V^a3rA8j;V`FOOz9@f*ks&O@`*nO@of_YkAzp+h4RW|)|~a96ZesEftD77 z+Xtg2lJFd*)3QswlJZjfqH^CtxmtJfeXPY_3t()9OJ40ush77byCPhwvy$c4ckYjj zMq2J}#fkeqret;x#O%MRi1h_(C9a_$FS2g5_u*#GU9MANk1vdio~;f5Hb%|-;+fz5 zYq-aBo+g2G?}?MP%u1G%5>mbaubCF!TpNK{^5gBP)5l*I?wJpnI=dvy?UYw5%=`QZ z4O>yGFPe2vmrv!eakheAnL5RmjktYSnZMTAptWM&p58+3sF$~)<9%cd*F?TP z&*71BinHPB4aFSHdOY!6QMBSs-MAkfxk1XYXU;fuSq-~}+*vEBf=6!hasSu-*%(Zx zNA6(SEb9jt`L)28rq84EW%a6;{YN+xYQRH)4b^^$?x|2#7iuT%s@VvBlXvoT) zA1;qu2dI%gv$+@NZ==mlU$_Y>Rnu09Ck@hGs(JMmQD%zJf!5n+)BNhHBW_TzwmXxU zL`^}!6S7d=sWrNoF%-LmFK#C>HBaJscidNdAA6^A0E_N`^&YOb>+|>Q#R<64TP($)_jd>umTohS?Q1`4IB5Ywd6NNp+r(;lT`fRcez;P6DKv=LfZx zm^V-*yToff;YH+OoW-o4EUo?VPh=@=E?(njjY{0zl@ZW~uHUF6aa<;_kr#|=2ASYqUJtuxt?h=K zr~_;eiF9SvvI=hVM!g+uGGv_487NPUM{|pKK$sH%2UMLqa)V}(QQV}qk4O?*SNF{t z#@I8z&IF%ypU+SkBw%`a0WOV_SDyL#Bz-vWU#FPMXH4ks6NbSzK7H!@`l17NEJLQzN1xB!9!I$WBg-p~QBnborrPuif?zQ6L z(>_yT@6BfrBIlCtYWCd3UOUGy5AH-Y326L-4Ca-Z*8KY|FJ!%ERGzimg%TfoVZ1TT z?YM^Hpw}!mm{Q>VWJp*~u7~G@Eam4R#6!3it{{Nb@61rE@**gZ-PyZL_?F>f0svjJ zHLo~&FwRT*Hpz9c{FfMUrT%~D8D>LfYCGN_vIXOR;_V1i2@v&y+REi0WP!Z?jD3C7 z%^hHFd9fBFRnpp;WjP!w=%qQYT4RcS6zHP1PmO?AQfkz+$7GXGfx=s~lUW^W6D)Nq z<3`?pp!ZFpn(4=fsaYD6eMwvJXuIC3>h{$aWODl9*e_e}hpJk0k$K#piyHRnA1Sf>eaFJZs#g2-}R2yCAAk+jtlIeKmolP^YMa1Noj0l8j;cmHa3b zFT)@1gkbwwHr_j=ggl?9+q$U@j-j(-v2$0DJ<>46Q}fyByB-eTU+=4ZJ)JX%S5Aw$ zd1zkP^82rRX|ocmROJBf#wxo}gZ1~NWl4VzD7zhk2+ySH*664Ol__6y{}X|%TLM5B z*dbL!g3ZIQh^uuEzHLe2FFmW@t&ah*BMv&wbSLPvF%VS6kLiBy~Y}wS% z6y}-_VOth8KY%s0k-G(BB94PcDqskCQVEB6v4L0!DEa|0@-*$Pq1h^r_Pt7yqW5Zg z0wlw=_`azmo$|GrQ&%K`cLlFy-NDMEe5|4u`$^>|?#7YG6$281-l!+vOMjW;w_dR> zR_f)sF3GhEMx%aYHc^}z=>MP^%wxAkh9x0Ix2m0bL67{RfBnA4>N`s`nDbzZ^gwkJ zh>33UB0vPx{-Jn2b2)5B`*Fl$%V`CY6_C1&6r!Nsh~;++d!s8h3+}k#))LxR`X%%M zP8Tk}A!AdXeY|)gv5sb2^}1-Vz#;53DBEURw7s|YVG1If#Cq-hIRrK^GESxEEe}X4 zK`(nt8oTFkEYg=*Q~I8E2stStzj<^fnD4b7sYz>f!~GnAXVKOLl5wN4bS#`D>1}!Z zV!cKn^;6{&RVd87EZT7a>Od&CS#^CPvqd$zZRYdx1N({|f8V(Z8s{e_fSU$`SBkcJ zTeL1u9nTjD>0(!L6rFO(tC=MgUc*IOCm;{eM;Z9V2*nL} zd8yo8$SdZMs%bU7O;gIfwZx?BP8>S9*4{-Q(5#Y-z;nR*^qwrKwP+LzipVc>L|lwH zuHcMj__3Yz`V2>Kq7xj3{4K7Mby>`*f^C=LuvRXpD2pyCj2|=|KrxQMHXNZlZ?4T781ZQv6wgaqHZ~%+%rcc^VzB?fi^j zxj73B=|h|OQoT8HsL{N&+Oq<9Vp`1; z4*9I=%Xf~@zxy%DGzcC-l&vXc2AZ3;hxn7tVfsf1?O<*@Mb(K3)MC?;d;EJ( zGMJ_gyXbw6pE|mh{Cd+}OOk)Kxj|T%pN3<}9$V!ixNtq|2~FI6tCBU+FCa50kB*|O zn@WV9D715XP~~0_bgK%H7Gt4uISN$L9m~Id9FR1u0VAI6kiJs=5Z?OB(I?Ans18n6 zK-=oJEixn8Bkocfv#3QB!SI}AxikJVWq5TOT56JFMLs~# z3XfBV>xPuo((*DJ5C=2jysNz>Wsyc$$@dGqJtt-S;_BjVA}u|oVJ7;aM6@HK z#*vZkBQCm+FJzK3L9VWLw5+etl$Wc8hGiwE)WKM4vW0CL>u8wo^+lKKsL`U`)gx^b z8B~Ndo_e!?n}yLVUNr0Ipv4?~>!yW-rif#4D<3Gcrq)GS8}T@F$?L%6E@}VC_`CsL zRX?wFqh@REhF6hVA*jU-8{g@w*|w8`s0@9kstcea@rXUqvg@~3#k zmo`Y7qDSRd{roIct9TKnVaqqav|KmZy{B9(QZgU!HbgmI3G}l`Mnnh_j*jyi%)Quo zPmuL|vIa%RBq|uV#mph%ox4mB^bh_df7btI=C2nf^B0M6D$P0n&iuV4?L}qXRrQPfKr#-)tc2g`D-l{#^hdsSN^3f={C5o#EVmkY6u|v7Yhr+lQ9MRvM>=J}2 zg#)>$MenD*Yfjj-*dJ+CAaQHG`^4p{AmN(#VX@y&-iJp%*?yFU8=Un9_d5W~;tMEX@_&&-5Bi!N8tqfjU(3yzotL5KiQclaaQ$?H&$fRH^NK{pgir}V?8T{|rJP39;1Qmj)fp3BTzUmoz4 z59_zgEI!IBHp;00fA&+qug>PLY=h?~aVNE(C}NC=-4fsb!cZuGun4WN}jtQxtlZbh{4E;WhM@CM`i>_1Qcl z`gA#7Gy75`?#kHRaWjf8E>dFpR)Zy7!j8bOW6;J&+&tRO+$|_*bnSiH1* z9bSDdk{H{~PotwfkM4bhq!2Zc#^v_E*BqJURSqLP%kg7$;?w`Bf~abW0dJC@(7DRm+6TUCnEccRa(IzQ;k zviLXl4g@nrf4r64)X_$84fJJNNe>n&bv$N^;6Bq=j5%NtR)`4Qj)5Y886*j`KYUJ< zX0O)4J==9A6Yc?*O}?=+kk)YZxd>vJYw8C`!aOK&RU$9PejyZH;WxbxHSpD;sN9&EBmN`D0N%Y9WLe!~WZyL=fNcJ6s?o4c8AKFu0% zCrFY<+GJ{+8nj{duwBa@Q-Z*`3~2((-gvH2Z$Fd~2AqpVVOXbkhN6!I1|4sB=70l%sZ5 z;5oWpP&Qv;I>pVi=82VVtEr%1(+_iCKR#+6@xj8PRGb(3K1IPSrDa?SzhOr}`;4aP z)a-q=UK}-%)X(d-+{>#2Qj0S&X?K&!3=~&%w#U=FjYURDQKyl!C%QDcmvfTR6A#dr zU1?*@_Yz9wwvFH~z`DZPw(xazI6rzZ=5=d50U|jqhEmYtxFzFMIeBh=rN0W8FO{gRR zqM)MsC4s3rC7Ji#t4}a~qSC0q6Wr=0D?)R2X2FJ2BHV)ykTyv-ZLCdd%(MNRsP$Ib zDicZCoMP5K@~yMYO14)(1eO}i%1yx8?Dgik0~F!*b)=!J+PsBA|hy$B?-Ke5K4<>q1t4T zW{18%yuUatM2)reSlcn6?5DHZouwnu+#0?9s4-H#)uY2cy+Lb=NC|A)UM*KPUZ41T zyE7?WW37dD5l)YXh*GwjGQg&hqf^!E`L*p(9(vXdLo0Ilql_=f_4`rU5*4eQoCx1!Idk={=`ek{8bII`&->2G7BJmOXi)wR!-xfp$6xD(U=> z?7h9)I3aSMeEC8u4E$XQ1|93tyZwkV?&Q;_BXM^V3OQsr}%VV2QxyBr3RQHeV?y38P zjRlw)qgfHpU?)sIm@jf%RKEWe3$aA< zQ;J0P6_>~7-Hs?l)ww8(K66f8FQ=4g#usJPdo8a5G%3C(9!G$3&*mSxr9K3TFfh&k zJopCmj9Oe;NQq~cUfthRumB7v|>g*MlGl4;`>2Y9?# zUC*Gq@R(ojfwr8M=8p%0xIwf^?!3Q>7VI#IAiu!S&54K4-&a4>o=0m9Hk^dJeHz*@ zOYX6M>+?M!J64>n(ms+W&#~aS$tCV15_?t-Y2uw0Yb`)iAW-i)3>LFfju)o1Ya%@# z^FXJaf8@2cF2CkVr2z*x!(phiek}M^1W{@ambXJf;kIWm*lcO+_Pet9iBi^-Beq?Q zp!1kXYMnq*9rU;LRyUp$`|nkAA7sQ6f1!v=SUEpA3ZDY12DUBR=mKcCup>tevUBU- z_iE=^GZ>muh-PciuL%=Z*nqSW+{7*lK)&1dBFif!4NTE2yuvLH2W8f#xsMjs;HnNQ ztUR+;-wMW`Yu-G3at|Yt>}-28o`~IH&mx|E;WMV{zG~0n5fn(oFx9mh@ZPtU>Ox1_ z@PYPI_|S`2$lH}Og6I z%0c!t?G3EIuGtV=MF7VPQgwC8zgFow5s`F=bKgl1bM%qNbE-9rQe5eJ-D5g^LdPoI z8|4bp0c{5b9z>36?3)IEiO32UYjvJ%cpOK5ClE){+8@Q^fAs@sTKEMjsf{7_w#qzy zd!eYZucIb{Yy7apLF=O*4e^ei*|A9tL0fm6C|Kb4(cU))1(?2zUX;k5)5}gSkoQ;U ze*a@pKuA0!NO6}>N8e3mxy+mJP0IIZZub2cs1v=gvJSHWw_Sl9jH zK)C2ZqI02n_`VVC5&@-@vYz8a2`rJ{GdPoY_Pz16i2G)rxotfyO^bJ=aa1NI(p%TQ zIOBZL?IUlsbD_;A{Cx5vST$+g5|cRIy~!`Ds)YAc2|RRaG}{Z65^MBEUysBI7Dh-E zBv=}x81TVaOg)e0k`J=sP>Ei`Cl;l6Wp+X$6n_#y))C2NxyIEgvd8IoehuO{hpEx0ay`8_gJf zGM{8ow;(WM$@LMIb&?%r9ERfsPFRoY2n>p<9KHESU95;n z20q*TJr)4&{?h3y)2I9FTe26(Xy5ONXW0UE4l~R9l{VXvx>itiLAY5FIT=OIbMe0oBu5r^L8AuMNoR8=A@|-b5k?WO@yP z96M1zd_`mH-PkAf%_fr9UZsRm5@o~|6a2%C|K;d^vv@rUQ@q{*fQbm`{aw5s>u?zp z7yv*UZM?*ySXr(?jndvsSoma# z#+C4Y)^XVNTVvg{jnE0T7nJ<<{NP&%&k^n~KiY5-cXo^#ta!8LqD|*sV2oYQh@0O&Y&xmp%EDyh>Jw%H017YQ_( z$(i$+ja_64oRiZnt0yKe?nbmgE{<{S2c zQBh!573g|$6@Rtat9;SLH}H&i;^jO7Y4hJyUb2Re?qs!~V{JJ~2Jr;92ni$AMJ>#J zGJKSOb63$RtsOU+;bVlfj$k?8NZ;Zq(-FCZUg3h3^kW4=cV=;g7^4fFEv3?+O8m~A zTxs7g{^u59i=}VgS8cB@qeI0%lRvvPfBOd`iOS@dNh5vlODgULB_Wlw5)%V8oo|4r zP7F9uhG`-^6Ku=m@Ms_|x{f;eT{+qP7~2;dEtzaD2^v(sd0r_) zCc7`^gPpRwID1}OjnA&T0sdP3JxG!WOgK;|U_LGYw~;R#&JZ~_8TVcwr&Dx&cYBB* zt#DUh@p^RT+WYwOS_?+6a|_Lqwbf7|94RQ2BTHM6HoxrI+B&`aZUz!f(iFE8t6TLE zTm~H)qkL!sTca^H>HBK#JQ@A^yIj6U*EZk6Hu=kmRf`uQa`DtFJrcrFao8>et?$_L z8;FD|T}Sw=vb{`5^E=*a<+qr*1at-{IZCNM-+S4~8du*EZ$-lAyTosS>jL0RjjE_T z9-Nj|)4ve{hGN6yA|~x+L9Q+HRH3sVY+4bvI12Qu6p|zjk^u+WC-GeF!b2kyuMB4l zaY2bt`L4@k?5NjKE^qjh|0EF>>-P#Of1KDc6nAP>vtJNIInHF^sPpcup&6Wk-{hX&%W63wlsVS-v%k z;y-Wydi0Um+x$`Y-fa5?;LxjplMngPt1L8oRx>%rSI0ft#P=KH)6#7mDY7s~NsjlM zY~&hkYLKEg~ z6cw5HTVFDnlnk^gJZ@8Q6RL6@63%h-=#bfniM_E^(V&$b>sPe!Gsn*GomeA!3+ub2(={J*9`s@ktziJ0t0 zJrZFKjCw26ewyo~c_Rse|D(a9ulTo=x@-UA?N#}>i^iSPoIH3w1eoy1Lpwpsf~z+~ zu_uoENr{C(1z~5Pi^3=KPx|vI`&26_`rCozIANx=d}dE6UOg59cYm}hVSpF!7ygWF%sIbh) z1HJ?s5CoK`2L-W3oUz2q=rV%KW?16SxXOdr5Z_c&A;CE^j&I|@up;UH{k11xc+bKD zhy0dEzVgTbrS!7PUwOaRBH;@4sY@f3&krtqmr-ZcTUijW0)Pvhr)e94LxsR1?Oy|cDx6Z zLKhGf$_ogzAEn#J4xJhLqCCfH2m?b>ERn$4+0|1==x7-NhyvXKpFeWt=OQ)$Y1%IdB4^{kX%ZLbuvde z2lNnW0avcJajAHnfYcQLmnEr{i>6PnNZI>So*xP1yF*u;zqHwgTE}SXg5y-Ado4=S zCujYVCw)9*B6L?r^o!KyW;~Chkvv^6-8#kiv+j!l89Q@;SGE@Wz_0VPfnQgLiq)!3 zM%ji8J82^;9KCHzcH^)DK}A3+sLG!WVaAIgLOh7d>Ig^qdB5$@_qhtV8{ELMcG?2Q zF=`jvZ5Der`zRv2pG$GnAr7;n6{qN8LqwV3>Xb8VNhQ^B$3av`TcesBV$RNoCqVS#?wTRS*U*q#zO2$>(ipy*%sV zlU#|`iTPYH@H@?TpOQtlgOqB+^g~0o_;lWU_Y>^3xVqOH z8_V?D?z!iOhUqrW5@=VrqVqV@uj6Hf4OibLxCr|Ryl9(}10AQB+Bh}SRCm6H&fAG^ zL~f^bZ!qxwI)bkV<_@12<{c^u*P`7vU6%M9{QM96_STg)uGe^Hd;M!qzh9nS zHudc^V!m|wyT~+MDM36KjN)W`$G_*XpEQDy+sguDllF0Ss(B<0zOZ;(Lv|9!S!9vg zFzDS*8cfCmrIf{+u6+MPRigFs2 z@+6S)S8HuCzSY?m@jF^MRf#iF{owKR>Fv-7sv`gT;=IEvdw|ama5mcAe+-UR2W!==IY-E8q;i5^(BQv%$4)Az9`|3oE(I6@H?q#g) znJ5=X7-aecJ}x#{xlK;o$0Id4+P%C0Qk`RmffE(K{5nZxhx>k2@`VH(9D~JRV1ZPr z>Bc!X-@H6E&D2)Ct$07=7O+ir;9LCJxEoYsv;j1HMKut`yc?U2^&1gPG;pT=3qqJs z-v+OcTXCj5qs1LuC%2OH%^|0zVN)MI^37{(a!^23@u|Q%B1rseVMDn{Vqp*bM@Q^k?qty3r_)1?JMU&tM$^|ok^~O;0p0mA z!r*Gvzklv((jUQiH7eq-cY`iyJl{FE;FU@RTzaR@iD~;Exfo)2m2k zxKvHuQrq!en!J3GZuK|NIcF#XLRw<7m+|!DGz9zXjMsd8r?VeBZC8B`ay`eHnx`_D zW5-amVekINce*3=f^WK;Sb=wY}r{(_w!5ekF!`f5c*?c#=vK^|GdO4LfMQ$pWEPI za;vsm627;=y9D+~ww)Wz{m$zBEx=X$<&Y8padWxgcinj9lXiJD*DreA0T=*WoEI;5 z6#Gc1ZL7Uw-*bBSw}}H{Ui=luX^f!aoy8O?+Uukh_t-W_gKXFOEYZ&WEFX}$C}q$e zck|k+9N$Mc_zBLP^?NvbdU`${Jia^_AgE}`m9j!FZ=A#{6|Yt%HpT-WM_cum{gd_8 zH?XrWynw{Hi<#n855IfI4U;;9c&ZGVUwBnkx3)>^f=K@#XcuM){{D8hNkFWo(_H z(y6S1Mut7Q&l%&FPWEqj40~WZ45(qJcz16eP`@8rI^0pF>F|_AO^D~g9}AQGB}Z;# zyjqj@TK}H7zu(J?0s$^``_rUhbLWL~J=#s@qdsT7#{E7rYRIbfy6sr{5eosu5g~CY zDa^IVkuhpi+ZZu-iI`j7-Q_brZKc|ub{SZyMWvBj1%-}!C~Bh4LvuD70XIwloIm!% zsQUlsyjJz+&b5sE&Q|I#w&CKCW4ko(ja;dtU+T4v3onwhyPa$MvZjsDb(oC}?Cm+t zdZP<3H$i}2m_s9!Q@d!nn?1enU;vO#W#suhg9uaXidFN=^|w0rrenRilU$DAKZ#4` z;a`%O-{le`>Wj8fH)nBuTyG*TYJQ$+Wc{#HTT}B)tZFPTZ`jRH1crzz&dSR2IWA8} zj5l2$`E1!5_XZPCaq;}|(gCse|BBXjQaxt7N&I$$>d!awy)L$@%Z-X%&h}R-z_2Rt zh#N-cDdy#QTXg+8@x=&8%o7F*W~DzT%Rv}*bpLF?U&i>XM|;0daA0}5)`gPlkA<5R z?pFLk?teW0?X#H=XR3#NPz%Fj2s1`bt}k{_h1Ih?9!(cB2KAo&zxy-KdZAM7s*#7j z=|$*w<1yD0#Z3;HnwT5k-|+8G2c(12yx5E{7pYtpT7y%>T{;(U|FHly{$D~=D_=9A z*K*c#De7{W9nh`s(C|emk!MR}H1GA?NsQFs*vVDY$&7t9RGIDfYCHxtpLl&12+pQa zGKn2#vFoljPJg~qN#{FM7wVjVPMri{p8h6w+M;}XPqxHQs zHP`ES+ze6b>E{{@{+D|x(hw0)e~O~vc+6$ZpHMqp`ztBNciyNr?lx&(E&3juF63sI zQ-oG#BX{}}&jLuv{_6a5b}okG`(KOU{jp?#F$E_5_MZnIVPMrhe#HX}4PoE?^T$rb ze??H4G3tLeQU3&1vl#xrLWM)8zoP=vpA%AJLP`I5;ak)pGOB-zk&ECX8aoy{{Y0l$@vdBH1qwNC;o=SzXi)5_z+vw8W4L3#LVe@PxLuHadEGU&kQd56>$ktM~Kr z%9@%mcaT9+#}nq0NF=%SpEevd&A&7_|Iyhg0#o_zGw?l`F{pEW`rDSj*l9}tn-w1g zV06nU+`0JWmipUQ;r82k#h&K*h>FMHXRQlrSV$#%B)8+vA8)`%_Ad>>|Fo*t4(S;f zRvS)cd)55*+z4AAzRJ-lh~6 zRKKNz!@z&T4Z>sGm?ApoBS^(-)VI=`SUzJvQiUlmUlk)csHLfi@$Og%bc19LpqCrP z*EWB1e__CurHkzwx1r$|7IP!#TSnYj=Ji3lVJANRYIhdkaR4Ln_J0kJA@TN=*%+<4 z4!`kRT3;weZ$DsIb}PDh+ z;#*gwgsk#f3}@dz98p89=cM;zoKW&*x6fy^oBFd2El2Ik^w?qE$=)IZKA0OoJxjgb zbEzK4aQbw@40{+yt_;-lyI=Y1YVm&Hh-E69Z^KUu2}MDbY?7M7L!?UGr~s@AVKZW> zt~r^KvbD`xlzm~J(UOS`)+ z-D0>;U=H>@*F*b9-4@EBvvs>M`rH*QVu%Dbte52`TT~^k7pMvryI$-FC^!`7?fr2njG8;hbuhZw)-qU5&8L9!(wJ zlbvI_%2uhyTneA)S|<1j4A@B^W((@P5a&EIHqfoS-`Am%x-8{hz!44vi+C!yQf-(O z>4v$B%^zjU2Y)y z17b(7QO=I5OsJDMHDQuN97`7;@m`O)Zb0Le>MYzl#defS-Z1shH#=S;7nGY_u8ig= zw}Iv9gWxm3O2iFlr*R5db>g!%cWVN&qfyD7D5fho?sv0e0uZ!i<=G&^bgJu^CFpTs zLOPM<6gshmpPaamu_qGF<6XXWjiW_6@k`MbFzNH+HsVaaNHb%8!B5X*;`2OQWZ;g+ zJv4vTh4@xu@2{x){VY#3$iB(?`P9cu`Bp^JIZ9)<3Gn-}t*Si&i@@F{YBu$HuJY~W zIFYk1hTpB_Yrpj0r(fWjh{Wx?z_gYkb?Gt(wskt~@i|KGEXK#90?R}hrfl?ki6RZgSAUI?j*Toxs z3#JhLvgjonL1h-`@Py@+!SsgR}5_GvC%B3Da}$8OZVpCwB+;!F%{@>v;#LV zkSnuQ@Ju}<<*cp$E71*zkB=TId>b3 zt*|!z`Qk1A75-7Xuq&~bGV($Q!?vnWNvok68^^IUm&&k`k6PVhB%T@wrzC;y4@A;t zuU`Jg@C&{Te)QMFpYYC9qtCqx-vtUQ@`eDJCe@q+=D{iho}16lV5ZcbX`$%4nxcz^ zCTMo}UeVoUG2(->OWBOA^^qL^^k*F6OdiTQRY_%g9$oC4Vr3~Zqmdms>B6iZ0k<}Zp80QUj#6c z=mbid&!#$!&k9t_emKAvsKilBKWjTps#1^b7#Y!@1mQ$TeSUO*H+CO_!|m7*3P-gm^ivL$@@H93dw#KMlq*d6N*46F z66XRp2b1BwbAEX+Y(~NL_9Cyd*Iy$S$M-bQ*e1v87#DuU3q&}GH|p;L;avg;aX~h* zH|huR5e*R00!XCVb;RtMc;d*dnM0S`5M!4&k-I{7_6CL;rg==fyX#zf){nSzuwx>0 zKi0-R)}C0{dmhX#N$UO%OB(*afD9*rRU;$nlo1`jYmLz1A*=SJNP5dkxX^8-V$p48 zrA)C3yUX42P1+e?$&HE9Q5c-+hmM6dXU?fWLEG)b!M0Eii`h43KHc6^#gI}&L4<3e9;#0Xd* z(zg$m%+EzVZUBqNs=7iqu+^(1CHEv?BeU_7eHQG|HHYa=_rQjv(iDVlQMFyk#6!w# z-mq%JMZ#hol4RFTTRry#w+dC6coTqmY|NRXVQ7^3;yj+Aa-1{N_hlA|W{rL$Wb}V`yYCoqGO`&6WZ&NQ9G`Xi;989JB);AO#ew1{PccQe zroR3qLipL;Ko48ROp*T(9Hg;o>KQ8k!Cd}7zbwaK>c1wcVWdaOZSYsBL6nDwN7vpS zKRY`+SEACR*q=9;Nd&$K9OhLQi6jFnEShR^!>##3UrnkvLP+uNZR< zLY`N*d?)`#pDU0KWzpj<%YPu38SU%%5-2Lqe@hp;Z_eOkui3?s9&g;K)R1Hxn~=P% zf=`(s-O>!&Buu>=h@O`aiAFD6T0yd{O|Oc!YDtjg^mgMNPK;(c^^zhZ6}!5)347s7 z&DaBNZc+y0ZGy_m>A|J}3*w&9QRb3jJT=rNI@Afl10YlAZnx%UUmz(=F(zXC#302X z$=gXl?e(UgCMy*Qxuetz>ZFhsHHYAs)jb0`RCWIW0jjIiiH-`@cE-=g#i-RBV;wL8 zHyJrkfL|wZ+9;3kcCQ{_0;a{!kv!|XMqC3O^mOHoz8$)tetifA>BZq+=x*MMDB?z? zOS=zv`CqFLjx-Aq6{Hh<@Z#~@ZcA=$7gXkIYZd@VP%#=hD3gx}%oQqL%slj-pvopm zA7}^BB-MBp1);rbbatu;680Pm>AE`H4N^$Z6QS192J8o2Z^Z`u?p7eCga)?Hj;Axt zK?*zCV&`>zs*hgYElGL6*RFe5E7OSD^z3#dXD&51JArX@xJCwGn>K@J<_nYN8ZBM@ zTEYG*k~IyXd~*>~xPgy@uW$2!L@mrM7+t>bWCVqNt-{ZBc$Z+)*K z{4W)xuuFaltBd`ogU7)bvN*hbetBK+47SI!h>?%^qxahQFq+Y~cTas}7$Z8~cU!y% zBa^bj(RKdFXE138e!xYv(LsVcQ&-I;#kjCy)!cnX4`^4Oaz3x(80Y58OtMobhE=wx zEo$>jkc(u=#81X8OamLS1{gc3R7s;d71e;3n>G7L0i}!uQzY#S$OTi{8C6K5y1Lo8z5<9F zy@;trwt;QVRi+KcySJHdhd;q;3av~vi-9QPl6Sf!)>3uicZPp^XHn+#j`{BOyb!nr zX)S0}XS$DgJ+x>uPC+X|}X#i*aKF>xkF+dulv5-o|n@0@QVaoc{)i;b+M(Ij6 zgmK34-6*ep{oCMKxD2xR&XQc0UGkjs6!ZXC-Ya$W;G&Z5MmHpBN8P^#3li9%BWMUI zXt*WEq#(BW_~GG|Q2k1+39pkV=c;~8Fl}??`M@Ws+aCA)TNCyq6-3o(x$T?hwYtiQ~WhoV+)6K^a&1LY7S( z2BmE$ZpUYfvv9^AHjV$Z*M^SXL#Ds&uj@M8)c1~}wNK#3okYDnPIG)CBu;pBIJt+W zy?l2Y%rIXDogVh}Z8cnq_QG`K9l|Q2F>&#ZLef0TemTE(=S*IF-%sJH$L>GT|IrQa z|BTO{fbLAqGi$Ag5u=YDHqEKk8e|*rkl)3jCd74>pkF-@4>2`C9)~_d4h;>>u?((a ziR2FnH|)#~gNc*cZFbjKGsB)QUK^j{64eA-i1T zo)ZSlVFRa6l&i6{#15VY^+zsDwBWxC|6KOL9QRr?X6uT(K?@VpV!HftGGwHk;LgV{ zQo$Ah20uf0u8yZ!Cj`fWBypFR3uiwAAw530RirGR3FElF?RE(yX+;_cyke$dp{*>L zrT-P`6|%Dm^#R1tbl+FTtX=jw!bt!CMdjGGm1}#VNh6FxTQUZ&ED%?}OjmI6S(GqF z)p8mCFpLtDY66sa=&TZDy3Y#rN$YCDH1N}}5$V6urz{jr@t{hvv*l7JVJ>j!!LUd* zE;$HRugpRBXZX{|O=>Nc=RCC8pYAS-`qhyn_->vhUDV2sM=#*2TP%`t;1e`iV!Ko= z;a_dP-)rxPco{}TcIs;7adC;WC7R8Eo4`Wkw-Htbb1-*qAD zd;vsxpef7WSJs@=?32tR4gVfhndT+24}K2dKEu|kC`qd;1U8t{q-DSH)e=&q5Xq`4 zqO`FhlUWi0xlTB8i+EM?v+6qTmr<}Y#p}SBvCsb?BrXH~XSUYO)}J;O7%3JVG=OT` zIf?JKm_Q=4G&mMcE@+5Dr>CbK{rv}=Yb``zr3O5TIV1jBf!uzO>+p8}gv_ zao7MOGZaCt!rF}@v-nEMjIFHI9Em8AM>{`*mjhRIUq;|RdJ4#HXiZbriO%LqAXY+J zLnMiYz=1DXXO}YgaCQxpzr4Hmv%Ev$U>9*Pi zZLo$@=KVV9{dK^$rxLodg`Wz?DpYx2`UNA>)bD}uC0!_cS=-j%cl&gA@;km)jC>Q~ znyH+bl=+D;E<%T7{AYQ~cJpBurcAUvuhM3h?}urAj0tgNnhx~uQNeJe)l${~zy^C- z6uH7`%j-`nITKI2y6S}^>m)-AVFI`CACq&gImoUWW z_Gu|6^3Cbh1l}$6fojMo)h0boC%i9wCZl{x>&s|mJE$W^{VknzR@$t1e(5d6?Iux? z;|`oDx%p{9>*>AK(a*38ra+shhMVckBt28ZoA_=_fgZPy7r&Gqjba~{v*F?Iu6wBd zqv7%He`I+47D!t8570-+o>HnJFiQ|9G&Pl;EF34>x=e@5s!~q~rgDBI(_j=cYV%42 zc13$<3OFAHHJaUDH8y-`h+ST%v;{~nQGdU={NV_}+EvZwfU;B=_jJCG%J)v%<-Idi zC73iLU?plbt!kyh1vL7kz#;eO!6S-W=5U}SO*yrS?!@!41+tbGsjt5)aD(4QCi_gZ zd54LDhruG&u9U9XGFn<;IudeHG%RZ_rVVD&45icqy59UELjps?#G}p$dOb|E-qk=U zk_7scJ)%MwWfUY7{^~wEHFGR6dCVDp67jZ8iy0qKW~Pi7$X_PxED7ISey`CwFFMxz zL8VD{seVAkrQf8HEr}05yVdjhF2nQp2{E6n&B3UNa?;+8gmsbD;htEooi{UxQhmZt z6;h5sJ3RXAa^}>Qq}8ntLxbk#xcE6)-#BSn!-Wz^+2R%AmCh7TrTey|x95|Qo!n8| zZBp(`$^!Jv3^$%>_y_ADDttkSh4J}27$3}AqQD#9@E(^Inni?OMKMfB&qePsi6k{^ zvI=QFu;jQTRqS~#3`9YP zIh=hz82zO_@=`NVM9v>{@HO1ZRZg&DRT5YwO%c@gV}vf!Lb(JrY6Rs}tjH%^?0z`F}knl^=ISaAn1?(hi|4i?44#p54W_4WE(u?&02th`|OweS!lv36b0xuC*Jn zQm)zJnLJm1u}&T6neyhzOBR#+yJKR#G$YqZ>#l9X>77d2-J>28+$_1BOdB`8uY^G} z=HAEL4V^@y`P4yuE?*&PVo#FkJ~W>|s74dXtdPehzP-Dv(GCN4593*4r-+9!z$QC+pK0MnC$TItsRS-BJaJcvQKXtx+{QrT;W2LZB^!HeR-{wy>Hn<4w zcba2L{rNTP#*u`iq$I`wB5Z4RqFX&U!_-RaU5PW`IXSso;l(p?Qc|;Wy^-dh1{b1w zYIgLSOG)*6e!!GqK!?P~<2y`YB`io)va_Z!to%Gz;hN9UZnYGwH=UGNsB-GHWb_7N zaT;c7sFtdK{PdBUIv+oOn`lWD*6*m))nBGU|0ZwT(}1`<{Ybh!ww@byK>#ciETW|^ z>cr~2CTp<^f6dyV%KVaRZ2^JDB`F%Yy=@hhiGINE9IAn4P5T`5i<~5vb-<{sQPOl+ z3bpV4%!S6BGMB8EDwon+qa5pz3?9U1px*6O)5wxLWd`F9G7bQ+$!Ph9RV)!0;~}`9 zt@wdlXD}{W8`{N=b&C{ed&S!-Z!&ah83IoQooatW|03iA<5xX@!FH zD*L=dQm;(E`%e?0g4}T~Kd}#;ivjkz0krMRkmTsj9*rYj4ZjKnV zC&}f#bh%^GA@;=};Kx8q+O(j9;fTW=pl_*|j0<4al(1wyq$XnKCkB|^O*xxk1&vGd zgkXhe1zHs;G^Ayw#E?~1QIC-3&xXDAXg6`}YE3N-`=%r3fsev)z5delfY$T}R{HLy zKChc*R*~7=qh-o`+Nkah+3J@ zqj}d&v0@fzz^2NvdEc}dIGpJ_;&=C29RKpW?`!#(Nu*Nz(evB1ZR^e7R1OY(Gq`2X zGkS)41>oUKrUsE`_dO&{q-dRe#WUQ>O>IK)6Nf)DJWxOhoYFHoHN6s8?LrmmR7TUJ zFpg{%Hjz|lmPx&CB&kqw0)dlr#tn=JYc{xaX=NVO-X1c8TCmAJrDA>HUP|e!wPkz0 zC21eRMxXUT)3g2BJ`gp^v@)@yl=s__@!Rh}E0pbr8;BCjF9e7wZ77Z8Z{6629- zXKy(m+-te*cD`ahaVRBg*>O4L< zd79X3Awc8P82V$-tTY3;HEbnR1BaV87-4b(ba)cKjjT60W+1R5cW!Fx1NUeUs{uFm z@>Xy+=gNo109EHtuKd*Vk;w)=$i+h+M0-!1?uZa)~^5LYt&Lgwr1QHlame@?ChFUW)frXmBWe zonJ~a%f(B{cC$o*0)Ld`=W;oPx!*^AM!%6ZU1BF(qU;lT9zCU^PX4i2j*e6g`IxxP zc4=ifyKUZD8GA=}@l|&l6BZX1TewA;?!DY69j+fr7=4bZZ6(bl)`p}UT#zY(tgjqF z={@DLc^&tyv0M8os7oIn)rxHo)l3OIR^4Y(yV8X!3k1#`htcr(rH8_41nR|dT>O+E zc7icf_+uyCl+Ktf-Q#D(!fYwp5qG@Lo1Vu$(cu5E_ts%iZf)PNNGp=kjf6p?bg4*4 z2`Wf;=g{4q3QEHu2#BOK3?U31Ga!;f58VyJ5bw3`?{@F~KHK+x_WgYCAK!6&_i=E* z#Wk_kwbq%x^IYc{n_JxW`i7WU9AV-n>&2S@$XbPMW1jo;Tm>Z07!TH@muBO(SEH83n=V2iZnV$Hh&yS|BjS&k%i+tbC7g%9?%v!?=mF|cKuvQV zpJyp{??5Tb9d&Un96P@pMHLlMP$HQmDx;*dK50Mys?(Dg5gK`F%hHSubNV(tLSAy9 zvn^XLzfCORqjHoj^N7$B+Uc@mI0blab}el~V`gro%xwYndI3VF5GqICN#we5hb0-a z23*ZsjXhbBteiPYZqOm9))<6N8baX@Tmoj6_7t6gBWMPhzhfll{Au0WRFSPBk~mK( zLVmFQ4WW@^N27P2mUHXc-B!-Vr&eX{eH;qMFIx>_z!xc%+k6nwe0Nvn+?JdjcxB{D zWT@}r6YhC{LA``$&=w?hagiG-Avp?9QVAlJ5?=ja!8@I18@HRfoD~~fCWL*}DXXui zb#CP3i;-Z{EZNVoR*x=jwJP6w=;1AhbQNp6|H^o!ygfRXpgtgU?}GO6pK$RRwf~vf z+Cl;xe3DN`3KwfUIQNsvQ;*ax>Abv@-1DI8^O8TZt<^~zU>6b+0?gO^;d_29jAO1^ z+{vt@kpQD^-N}j;6E<?V8OLCW(0qnD5J%^WA9N*@ez{%%pOJcp2A zxjHB5hxjeT$Hi~Lp71@pw{^#o)6iFLWic%}QPMq{$=ox%ZTRVP6cu&f9U}={u`yTPO?=x< zC0PM&-{c{|C%ma2-zcdoQJtpD^@~n5ZaaGNSv<)&HHuxY6h)SRI|Ww3gT<) z3VcCbJrfD&*D){b!ZRr!9q(f#5KJ6%*L!-mt{sKI1Vh!tKY8p%cu6WrtdkIF6V=}x z>*S@^_3qqVe}9Q0&-~cOS|9GegPr$0K^v>$@)mDf>QSBFG;+ab;74?#pSt-;(GApF z@HOIHK|>{w`N_i>mpW0f!0`erq0KAsNOuROjFgCKJj^USu@ZaQEapX?%EhzTCgTWJ z+Nq95O=AU987Fm!&aXvsp9qQWSp>Zb;^u2X*`sXvV#v3>q)*N>My(Rl1ABy=9esAFDza$j@;|ytdLB8Yc}T@U}Q)&S5N46_5L;b zQStzWMIu3BH#6#aYVI@@q@Fk5$gqw(e=V@q%+J4Pbu&f9qCZp1RL@Vv-XeUO;75>P z{#fYH793|XC;*NK;_K8os+af&=5I*P40`bo%zqpT#}?-$_@=|>06_krwk?1qm+9?i zGMqs(xsWL14-9HP`yozz&u3QN?Y6Wq)~0L-&J-(eRKRN~2WQOXH{W~gzYe^xU1VnM za<~~HvLRX7dGDg=L8;EuGnte(Y6N{u>nG)$3^1`7h{e0eCO(i|w0we4`a`0}z97sLORWE!yU@mn&xo8n448smh=|ek$Ot*U6~oMu|x0q zy3QF#!Bh+vPO8P}NlQ)|krQ#?=ba1q#N3ggr`$#r)SW|dTjSn>H$?m_ALh5ujB_|l zHH?#iUAdRGHwE2$7Qv2WZ6oyC-s`N@rFZvqZ8n=*>Xw{Au9}5vk24((7Y5v#af6vw z8C5*weZptlb9e9CjlK=z6MGR)iG{7|9{!Yqv*NbI6>KLzvSHV+xPBQxKle|$YQcu}|{qICZHx*f$>5oxRLhc4U} zVoO?Z`I|ZZD2Gc?JC@OG?KnJB9y8V>?%gwkeE5v9UD9>8G}za_zv3XQ z@A!S9XQbA`y`#(=KDjE6-BTSW=P{ ze(cP9Q(AhT_PSwUTG%X%Qw%A+^QeB_te^A#Qh0E*ZL3;DnJGVtlBmivAbcf;O22XW@-%8&{9EH`#_F)ek0^>qNal>gZ-MABAh-vbnRTM~ zXssWH_ zG9VOuD}TC;wnn&xYVXUMh3(Qk`uCp459QcQFOXUCQ*HX6W1c?qZGE_YfeklcwXkJy(vq;bD4|emX z3?4BoQ>ToFaUdxZX83v_tU5yk@}r?W(8XQ3 zOff^>N_Ky#qG4tpS@7cvTXQM)U7wt|C738sXji#*c-}hQ8&!`e6xx^X#$=9Tx5ZxTMnaQ_O@mE9Bjw3v3YsHR%TY2 zbi!L^3x%;%_3VaZLzjf%b(jS7Ky0QlZI~t$Z!~K2LhgeXw`|BPndJr_MDjN~59#-e z=dBsp0NG7+PpCMHA7Qw))FojKEjjDvk zZ1|X8>_&ssxGWGW(ZptB$2H!t zfnSu}_RzwA5z|zJuG4w*(9i|CH1OU5!gpq#>Lda0>%zaUCe^tkqGW-8@F1g=t1FhR z41I6;;|(!yYJCRwZtUV&kz*{1TcgwL4m3Aa!btMl?=9ZhynRO|m;yH1>evd!(k%|a z>`a^RO$Jp$eb%5olFSw8j7+chnY+ZZyHQ28Tq-eDoMEcBuEu|@*Aze z{IUM<<{`>HZ60TH7j;D;WqlN(0NZe172+R?zxJ-9(S^BS&SzmEJr}@*s?Lv z$A^C2*>+xgX_v0So$c9_h>qSJHKovr*!oXFI69QJC(P3LI9cdjxnaik8#ue+L0IQI zqhBE*cC-bv3x^)qA{c4co=OUcV={L^u2X z!XF3+AOglZ=xgh}5X+0k&|JwWG4r*AX>))!Lz zoM>NZxV?fC`1NprXs?PEI?bcDplPX~SQ zszi<{9ELiy4ym~~w`)cE`;)VnnT7dkl`W@!lDY#s~{H@-!5-HGip*%S>q0EzYj)DbqxkPeE-+NTb_g z1#+r3qK3T_5j9--{6uhf&5-iiFl}Qit-YAUBcY4Fz?vt6a@WcQ z$x`&c)0M?5;Bp#5P$ThT7IC3?e%8TP6T!VRp+=F^ zgD>=L3Y5a94edjIVYi7uf=DtB4@8UM$Qk9CFT79(OPWi(`)Vs1&u9jRkVvXpnIedYej-WcHwq8^4maHr4P|QdS|K9h{L!o zv^0WUZik1`5;A{odj=$|`+t?&v%s{wgOlu@;UknMwoi7>h&`z<(SKp1Kic*IxPb4*2>EL?hjZ#!w5$IDne0ROBGKp^|DJKi>5jzsXo2-B5D zyoeCYQ+irPhJ1K9(sn$q!M4-a9DzsXA8Uw;xVRvVSER`MoEQJU5>#DWN0Ka_e33 z8c<$InQ=*SOKawSd(NWlA(m{Qbcm;&EmYST;2XF2HO`Pp1X2fW#iGmf0(# ztDO_fbD$Uwj8sr>Q$M(#6Yb2ktJoG)^URZ-M+mAwIJ(Fca4ZmHYJ$W2~DG2sR*_C zn`btgo93u>CKbU`vD_!=`2D3RHDw}AsZM+Z{8dm^b>{swrpGP#anbV-;^%QG|fM9Lk#Tct3TptRFdNKSp%$$(><2 z5^}rF%-bKDj=WbU_IUGEU{hHy9sROAHIAeteevWWOlunOAf-M&j`cian`kq*GdQ~A z;^AroYPx^nls%x|dit9S4jMxaeCb~%3#{n~mrfrL)n`Q?l8D7eoBEq%Z@IiQ2Pkwo zm-uS!D#Ra=bMsO4U^ zX&Smap3$q!5PJBU@ZVaz%lN_bEJvPi4hn~3QAp`0PYd-U9E5jDg{wD;)m10BmQW1~ zXykRfV^Vfa&IU@|hoZW-vPJkD`S5W2-FG;4au3$$MRdf+I{6kjGj9(mg-%27qrLIh z3kM6pFaMCq`&X6j7Sncg_&Fu+?8|{E!a~_3i|;Wpao9Y1hdRD1rpp8X zDhppl0r=SRGJ9WNUq1}ieAS>*09{+Vr=z0-oE;mouBM8WT|DqqFHFyYh3lMYl3CK~ zJ++CRnHPi;mU&F{IP=S^Kkw`}V`;k1g$Mw6icY-bnhfoYIRMn;N@ zAH?*SKb0vpL`hJYMTbpkDWxZ-n@xv6mDW~j!pNpTj-yg~t<_|dp{zV5m>*17)v+ZM z6Q5P??$J8DA)?|$lxm>8g!Wpu%Pu(*9CYg~q71GD(g56>iv++52{@$C2dmqIVpB^! zZsExmBBgEo2a4FE8h&Pytn&Hx%Zadjg=PEYmp34$BBqX0i)+I-vvxSBlat?|?K8tq zRz8Qe&<)dMHRqt0agSBGCzOl7r(b2&cX)1VW@lZkByTd_s5(-ebBaEmXZE*Y_ZZe; zk%08)qRE@JdJ<6+UbNC1BG6&3EU=9DRv9nn4AQ>oSSzqbd!4=e1W;B5wv6tV7T4|I zah^xTCz69TsGSEpn07m3D?7KUnwl4l_v-^|?qpq!qn-rT=(%}&!iwU1?8J?oB|Dl} zOoL|YKj&bycgawOH+p&X50{XXEYcki33;4e+&Hq8k5k3PzuI%`Qi{tOobYZdLQ0n9 zxSmxzjDLn7jODd+T(@%=-!K*Cl45E)zO~_iX@{ECl8X+r>qNsXg=)qn>&?OUDM5is z#A?rDM!aJM9u#s<0}A9dPcZuA#x0m#UHID_dgE z$?WjX$=V6}cJ#C5WuU8%j){p$aB3nzu%qy&30okHGd?{HAX8*rd}_CwT1HiU zxdLlE9H04|ha6nkWr3B)BS2Wh(!`1VN_bEb&G0VWM#;G^ zw-W1>_v4%M{A$~balXXhb>a@%?=O#F`y&WNQu`|%%V6&QnHCb@Gr7k5%e9KqYK&pG z*eP)vJwQG2-d5Z%6^kXb7a$QFdz37;-7DG;+Ou#PNZdH9j;+17PBE@PY|*_`W4OC!Md2S*1$`o2nT z7bLU?R@-oC!SiWaW~>#No zga86NXFYEYLw@E0P+O)u;Y==K94`4%Swfnd*}?Ecl>+>r02InoP*CuVt}bi(fRm@E zLgmEb;o*CYqGtueo{TS}b0T;NB9SRfc)&YM?d)Q!s~>$CxerMDXCy$1PHyg6u@kZ;d8J zN#P4)#4vC3ZQlaQ;X9h>7aAEiFfl-O{*E9krV{ zI7*x&3Eh4RdqmJ_MOrT&s-EEEBu$*jFCww9R4Jgp+2QitnNw1CzE$WZXFeuB*sp?@ znvd?=-5dDo_r9+MnDSoZrq0;>da(Hj0kMnYctm<6$2slaJ*f*MmoEBG&PIv4(7;7z z{W@kQ0&)*&_V#OkXj0T`hIMRGS(4~6Rvs*dX!3;V;;>oAYt*6jGDDSu2#7mU$@JpAfP#n zCq$t~12ie0<$Nb~-{#ppRr&CI0ZH{*yw0%h>dp$TgNG+Y1(`i5Ok(k}mvfc}rv;!E z<;U-&US@BxA9l^fEFYNYi*Gqea;i7f_GkJVe9TgPcj4Fw0;?dYx1@Zt?c%5HlMZ_C zRBXh*0r%}@V@u2YvkkG z*)b}hazgX4EHNW_J3-64fAUErn(c0rua+cXRh|f!)Om1V4L+~w_zZG4oN{v~!t{8F$ z@b0cK|1@?8s(xPmd!#V!UILmyJfOLe2-8keQ}gx>?0uB@gl&>n6Kryl z#@X2!uw6Qle85>N5^kHJ@|<|A$uN5Ewdc&)hk%*3?G`4R~Pl5(tQV1aARX4 zKKHd0xn9%9gR>UlaWP|?x^K_6yuTE=dsY!U72GDndK#gV(c(9d&gf>9A#-TG@xBFh zbK|6__|wPpA#z+^$xr?sZEhy*L$2@2AIkaWc1}JC<9td*?|i<=hEP43Xi?(RZiH?c zT(+HgWsR`SUsZcxf{9|_0_I`-8i&CgPeP^1IJ=K`sWzKBz=@B<+D zGA%N1Cf4^16#RYt4ny(iY2OoRZqx=~J>4)rt;C*$ef00088*qf97p=-e%!YV#=Rx=6T?0s$V3MRJpVR&=k46D=?Wc~BYN+AKXqbYP0d)PmE=JqsP3 zO}b+d<3Nu+KIft$+fnDK!jSVu@M!Qn_4EY}0{$D#JJS5X(_kz=-DS2ppiX+ZYp#8?>6`M1DnM!;o`l?}G9MPGt- zx#gPlEzHb9#oV`F-2Z?FP4|qKy+ae*i5Av@OtWXIkcBZn-bIY0Nx5fp;owMzZ$RnY z{Ks?ZXP54`C|zE<|JWJR>TlJ>i!?~JcJY;QImF}$SI){>u?#ushR-hTS-OLGyeasJ(JJB6x-~HT3ni zr1spr*E{Nf(*)SIvx>g`kT8Q|f>z*27iUR-rPeL2{&3cyw>_pxQwR?0t-*1LCC@vH zE*0PUdvBaD!kzt@<&si7TsoIV1>$PltaPOzbt+yLd`DiXvFg%X=>bekG(`Ba;YyR} zO}orpW1asZ?eDr|ElZ6tS9+Mz7)J0g=PXNB3>gi%UoAD|K`9pOamm zHwS{sbj=eu=ec_Jewrh^(QhJ`JUOMlrT5H0 z;|*tix7=Go;~*w>n#|!zzs|J{y);U`lC}Y#q;+z^UZDg08Td*>&yr+p37P(;vM~MF z-BLimDrXL$=meyBZTT$4=S|(y$2d%mq2zBoy4UwPv#QLM~DV=l^XPo60(`>sd>N3@aM!J&02U3>+oG^tAqoxy@@T%z=)sJ^J z?Jb_=85Io8E7yK=waTm?K#S{UE~TUVu_jB?y&KQ= z0;Yrcps9JYB$nQ7$7i19lhQBJXx6Ek7H3o%BHK2H&Sh{NQT~l9`<^Cv|wNvIvE{ zO9iwpx7i0ZP%_zDBg)xaEuP^cEmKB?XMo34xphbXd~p7ACOf2}`>f@vRT?oGpV2&# zH>3d4Xi)V+VH8zrZNE2;N)5Oh6}bT3_P)j(g5SpUI0a80Yu8>eK9?C;Id(``J3b*| zju!8D=9IeG#$QD1Jf&6gLM8N5aEd9Onz)gVYxiPKkJUi{AY=(k1!C^o{Mfd2TA9Cb zq#i`gbYZ^I!ZV$eM96qiKgLa%2=Ga*f_Rz8Yw_7R zTxihZo^G&FP=bP4+AdH+Sy#@E)#QS1MzfQjQi#<<{S4@zVGX8!}IDi z!#;%y{#2&_QmrcfMXhG4gg^Nx&7FKFQ$;{XsB3D9u39@bFOLlX4;;x9#UvztOAQB# z8%%BqBKK0Pt9#GRL?1kO&_6KHL{z4yrw8)#>Kz@Wkdu=GJTci^5kUsh73<1d&kS~)PxM2dUlZ}Wlk~75WFy&y&<(Xy!oUM7lF56t zJ!`N4!F^=C_BJ4;&imV{M>w>T8A8cd07?a!hiTs%u)X(;J=2(i4Xfsym+Jk!|)GtbyhM3b|^+7j4u~P zO_>=n?3envuJc?wQ*1-P_SNvGYYP}d9fZ?RJ(>aMv}w*QnGdfd;lOzHDJ%qJN;rC} zS-cJQpvg2x7d_TAEh9hYScv-<+ayf>Dyq!w@{|1lO|fJ;eHFat&u%!szJU@KSbG?1 z8z#fTO64kls7mFgLsvUrr^!-Ws%D_GFk>E?=d-}R*oj3&N(2}2ZR)x_<_j-jhNiNt zd1W3d#p<$j8M}tnTZb77hxAD_3OGvp?U7pqxsba z=~uc&eoe4U$Roio)D_aiw?0{_$(bGPNKJR*- zfLZ{cfS5oGWD%xHZLRRQgmEpob7m%onoiEEZvN!V7rpK6?F6NW7#LAqbEC2Uiv`xE zUZo3$*<$$KSl(NoFGLwb6Nq_~zmVrJoxt6Z)T?b0+W7VUf{*QhrZ?%7Q(b#>)ma36 zkVU9bfB!1<=!58$4coJ(!$@fzZ*c3(RoC7;Mw#3}M$%Pg>KQ!)H`Wwaj6yrEV{_N` z@SRI|UqtW_XEpkP51O%P>fTECbp;kfJfz@?m^WRcPDFcaaF-o3qN-F zcb_cdL6f?xkYNi|59c2RsSv2?(d--j%oR2Aq>4M)1D~9~rMEQAcSH-WAo)YRPqeOT zy*bCezYp|3JY~tgl_;R1&#-^!kW8m*+Fdd>aSnepx?<6N;C>lMX=ORng+FQ_V0aUpYg=$1DzEOjGM$x;>)I1HCT935kQR|FwBhxmWV--X$ zcPM}2#wwPGQziNHO0yeltSA{7QED<}Spsezsw&v33rTJ-i~ zbM)&!z6*D>vWUi}n8f7m0_gqU{2aB0MQfkAenY@Qvcv`#I84RCwqStF1s>V@r_ zo18aq-UJMEz_ed;N#iA;j+K2#bBiVxr$i(A)%}iz1(qW(;E>1@!E|gxVY=_Of>sY{ zHn+FGZya5V$cX?lAtV=$buNDd)(D6Bk%@}Y+0ySClyz>pu5<%UWp~kL3?=XvbL`wl zMU|N@hK;IMj`56s;!BN1X>Z}uL+QXpq7pfzhG#vz_F@WhO2CQ z;o-nh1b!qnQCEyC-&(3?MYY+ohK80t=gU6aSKnI^^~#1n*qbGhpC;yZcY~JK9&KG> zeb-u$31W)C&y4{2OFs-O7gl{!Dgdc~^{Ri!Q9$g03j^Daw(#F4DK7R} zb&g4RS!fb?-N})Wzuhi#VZ+4K3y1dKKPXBs=7yDPDDWnpox-{j38#a(CS&Q{P6&n9 z<1F)RT)sztin?iATH@qT-!Ch|t`J`5+}5+r9WFU;|$=1ACC5uheWiDBmK zCre6B(bKZj$gq6ifQ{f+vPJFP z6KK+GZw)~n>UjYuP$|#e=Nk_?c*=b^?sVe%uQZ^9vKVy_T&h}KkG!{wx%a_E_b4Q( zEg>k-1DdQMsmYJ7gN8+*UL&3!)Lm?l3^Q3mw?>5eYp02~9gFxKb3ut}Sz{MwLHl|P zWdjE-non;ON;*EbIJu>IRn+Qc(w|+`-*yr|ac-W9diWj{Dvg+rccHx+=nH<3MW9jt z#Rq=2&VTha%@_sXQW}Y^+gE)3~LM-~lo(wxB3(hb+21|18yUMz|WJ zrPtunIoA6F5Q%ojTpbqkgO1G59=p-f0bH2C#yzZvg?cusne6FP+v)XHbzzq}T6Kmf7VN6BwXtG_V=8`WNp(^5sirQKh;g}~#E~F-nd~1B4ogAlq4^nXH zwvJ@pGnILh!EwJ#pt7n*wy9T}#Cn3LOfpCzej|}RIXs+h8(i)`w8XFSJvxzIYA{C?KjjBAoxy zx@VN0EJq!O#5Si`u5&Nw_F_Bm1Tlt5hxaT|$0o~dKJ<1WWiuDlD4Z=4NWXdS`aNSN z7KW_vBIC%quke}6dt0FH5!N0{erD=08KXFSk^46vaF&);G^*$76DVLZmUU945W5o9 ziCa3>K~#}-9k1UnTGNp}BTI<9ZBp^}u6j|~*Sebib?a1=(rzT)D*^&)13{}DA*;=8 zXOEeWWCd$6*H}o6qIy^r-g3SuEK}3cGWT>%>UbiJfwy)&nLvfm^Wrc?2qF=-#(9%y z`R<510ZgaLE#3-jz<=XuSmZ+_Nap^_Pjyv~K_CE46iK@A;)WEtOjJY}5w*cX;c>)A zPoEw?o<0R}#TTWO4K=M7d8F>v%xmofm8rUdmRmwr+uP2Le##sw7e11a;vbeC_4Yj| zF7_1$gQYe=kk;3gkCDoWxqS>JcRNNLpHRgrP*}HrK$|{rT}N>rtv*W4?!#Biu-H~B zeKm2nRd@R)=d5M_qEGr|k6`S9q*&rJoDSurk@}oZ1uoFTsa67WESNO_cbsh< zC5de!OisLBzeG;4Q^KqBTpjB>W3fS9SPvV(@ecY1&Tb!ADuw&L=RTvD4O{dRxPjWX z&ZU@!vX__#2j{+=Onf^kY$zOwKhr!U)ubX$O`Y5vzkB=5n>X3oB^8a0N+lY1Qk6)%_yDJ7-cg=Ckr@mJ;K+kbH^^`N z4y0D*4rR~o2v89KV!%aILN8Fzn94PKHfNaH(Jga1jb$QLyz;~CJf($776o36&UPqw zvV~^V{}suqn3)oA_M1cq2`Mc(IL=cvJIUm8gG7`rQBNUPz0RYG*P5 zw@wv|+tS_ZkbRK$@$IKn`H{h_J+H!yt7V&kN)fOZO49r0*n8ZA$Ll>9Vh~K63DN^1 z%@l*81R6praF#%0vpE%ZOb{#Cb@f!b`d+$v^-yaOs1m7q%fogM?wMVw_DU7EcNLC; zD2Ty{t@p!yX8|qq1B}RBB&rIoT_vh_Mz(tCBH2R_Y8~s7CzF?PVJHdK7SJR>P*%ZV zR_g-y_(9vz;S|h zIO;}>0J-_Ti1`8Y#H-y68~^XYt>l^|6k8k2B^xBrp$H~|R95qd1h##kOJXR=l5M;V%S3y;70zAIofyJ{i^Zz!u^{0T={lR1I3W_d1 z04Cri08Y-mDtZl^bRDt&0N@K>->~A@w>{cvw%||YrHLJ%owaaxPd2Yq0C2<)&)+Gr zU+oHCO$7=v#WBYLZh-<8AI4)U(l898T?n@eS!NVV&MG_fb_lZ(3+r6L$B!w(Q4zTj zchjbPRO!e%FhInlSj0_@F`)}h`&gw}|g z>;+Z4d^;I?V!Awyk)r^d7bI{}dvZCptVq|?wHyse_naw)r@IpJJ*Fd3HqH@lt}k#Hn}Cm90@haxWZNNDB91wW_!%Fc zkWD%hD*+RM{k9XaoQ&G}F+G9(s27#rnP;=_Np9`z!LaM$HZ^IN(1~!6um{9kQahKA zxJA!k57)b!$7dT+7N2{%wKAh5tb~R2_}h*S4dW&o$j5otTGk}T7$XsfOcz>m?qUcLQmbQPWo3`xa3~{bq*rx3 z(7!58N4XiKeq(L+#0}zQeRtXfm-(l&_-W1b-y^RidDh=NKET?${p{1Ql~X+(Ac22a zKQgzl&;kOdi9J3pO>U5Zi3w^10s#nokf&#lqc9LqO;9NaOy5Q992MNE>ezFjEMBN> zIbR>^*cF5xML%GRW5V-vKe>Ff$*~Njd$n76b=FmOvJJnQI-Nnu0jMI8_vYrUIvDp0 z&(nwjhvd%%A5Xs~!%IgL*#JAfCgli-o6X z6PPH|nY%x&bJn$@|2`7_hp@QN$llU>W%rPVk0w^WU>Hc%0K#)X zj?%09vJ&Ut_}{T=qr zE#x`GRF{T)N1OG`m?>Yh{%LCtAN?Uw6E>+VfYyCX*A!$Pzxp|u->3Iq^S%5Y3?9D( z(FvpiNhfas0Hj)*?Zb1Bt7`{9;ecl&!?IU2c6tZMDt(?u8qXlXKPY(Q^^FaBKz6K8 zSJ@)9Ao?=b!y-1%Te08V5a&-A&G)hPKh5ti)A%p>He%x9=XVD+?%tN9*1Q>X4M56) zoUwM0l3=>;)zP$lvP!|zf3Tx^;cZ7U7c?n*BL3Le*!w;+21%c8WLNyHD&=aDL5uHA z3k#=FZeqqMoNrT0cm*_b-iC0_#k>CT^kdL}V^-)XX+$`%XK^M#%@SbGnDA1R*nylk z;1&V&JeQ3D<%#xIhwd;)cma`>-i~wafURW* z{|lSn$7H=o{g*L2xBoq67akri?tL5s6fz&&IGVwo44SL0)ZAgQb0o9#KJhj1dJu<9 z0S2x`VZ-!ZQNa<8eW@i z=-NZ?#mL?Pa!*cnW>>bSAppZtCjV(1wtr_FKv=i7VgSNABP)xaj&SYBODKIE%sNPc zg;B2?2c)Y5*k5{jI)DvEb>u`V{!S_h&7}VZck2TS0~CL^d?+j|oDE#q*E$G}FnKV_ zqg%G7SDMjH+9m4T$y)mQ=ANFZ0GqKVf>c(TL8M^uCodTJ@BP8 z5$OL@uBri0tL%>r`P0|`m8JY{hnSZ|Hp8j$`b$eI{9Y&4oAKH({TUY!k~qJhr^lv zAhU#Km48jr$DltH)*q8(_09a(B(sTB`aO;2Pm??o1yHm<{r{(L1m?8nHr|!`d(yz4 zCVA-kuk)4vvvGe~tbZ(T1O0zC?!T@{E%blRaVJ3LeSvDi^wGxxDJ`wnO|?HJPeMn7 zLSjhpm^p2OAJ^2IgFM*T%~6;uo%HeU@pduSzTWsMAK=DZRi*7+G`3z^%4VaVkyM0X zRF|t0yuK?=!tn*NZ@MDV;w;+2!+%Hey4{`M8bJSS!io4*&rI7}z8QN!uDl4);g#v1 zy<5h!e$|E3W)&F&mPT~rR~cRV*(mh*SA9Koo-$gT1BKxJ+Ezv?|YI@m=m6Zs+CPmm?Z2Jzbf{(e&IiRh1vo|ss8!x zfBY$bbO`EH&9+_xhpl(DXYw`gQoevt#+^KkB&rLzo=vt=gMttPH5}V`}sHbv}?D% zX&SDzprEwzYd+pC!Nd&%L)An=26+dr0-#75%Ieopub#({t7tPZDsu}{^-OgMx zh1KAaI;!GoJdH2nCAH<^M|%>X$l*fQpjq-3;26zZ&?Ka`w58b|Vt0yaB^qT*CfKV% zp-QCKf6@2u7v|G0jFA3ILDrWY-?A(}uZW7Kb0;pYk$tC<;vZ8}#CBhp$FX9@0MEMi z3cfS>TFi~$ag8ERNiWT%wKC)>WM+HGg%%;ayHLFqG>AwHh<3|^m`4>FC!eCph` z=@`HRVPHw+@L4)6G)pU&f7G%)*xx@-s@qs>)!%P#Bl!J#*|x`{~jRcUC3&+>5o$cX)+(6WxmK>pn`J)SpGSP#N3lJo~$ws$a_ETX=cw5dH$u_C(L;t1#_u zdP{iYo~)j?o$vh3BTfI;wNn+YWxwh@`0F{2wOn~$OwZl|%6gz0R#^fC=Y*V(H_fxR zq78~$&J};PMR9*I{|y26XxBbNLdT(51Z%Q+7yDNqEB!xw>{o;){1=DmTRu=d*Z=C| zX||mxu)BWFzmQP8gnx00%B?)>o6ncdAT4B;n3w2GMoaVpWw`RM)|>G!-rP9gqBYX~ z&4B=y%0uW^&L7?XyXOYP*W5JmFX$Qc7soC@`MTXV$gjGGBD4SEhygWn0^FbeVj(&o z|HTIt1RTqqFlpL9*=hgJWlZp2d`4S90?yp}1p!du{(p0U^X+IY(_hg-Yrd*gPV9~y zFoMt9k{mG4&0!^04m^AHQec18^Qj&7m5V8M8}U?vm2y7X?aT?(iud+$S~{Q{c2^Eg z)~0r5{WhgWkz3xojgL@zt8_Phq1t{$)>|}|>HV)OwGC)%Mm}iklxbD-71mn~@QhCR z45-?O7S;=58aGqzM&IxnY$c3I^EC^9irdrC`;(%Q&gc=o7TTZeYE zxZVgTlWCM*<=f_ZW$<^|(T>^@9eQmX(RHTS)u^`Ok7;PKfAEg4W;LzRS7K(P3w?~C z0)vFZW|t^iB=|*k@)4)x7!3y}DEhxkpf%63x3)~Q7;8o*9ddfn{du$V~J`TeLN(WHf$cNNBy}rK@eV279%M#nzkR zP%Gt88{a$)xLsurF|K$Ez7YH06d_g!?8(vf%~WmC*R%)KE4>Y;XQCc9daereDMg`6 zqI+IV`!4h%x@Gi*cWkN~YRw_mAo~bM{3^S&5~4AmhN9(@A6XaG4w_qOMfAgIuW2g} zxO<)`uWW376+KYT^r)W^*HRR-adqe79Ni90^C!ZYOi~?5MON=5G@QqYp3XOHUAV42 z(bL#UA1yRFS`;`sb#}GY(41Dsoz~JsT#wS0)b8UM`%1YnP`kePNnh+`m+FtTJW+_7{cL?$ z=p~om9po0?v~B4qhwBA;$hS(;Nk{LYrnkkT7PTUW(OQNQ9zekjjOn?LTG*HM zjcshcJen^1k=$Z1>sFnyFt_T5?wGR?9`!{vN zu(#--V4?ZQgtfNC@sHlihO^~{wcfMASl7PRNp~YX=Vy9Vl@wnDt$hpQ7)u2>Hg*q= zrc92$-#qGuukSu@dR!HvvF-oG-g`zhwXJQS zbOMATT{;4SQWfbP>>x$y9YkRRp-S%^r79{aQUWRhM&%gPD7_NXH1;TGB^S_=uDeBC zuoT$nF2ZSDOX)yg39GNPr_L#7P=`S*Ydkd={v@j#@Ya-fs z*EOgr!O^ zi-?Yi8TX)>c|Ulk{OMp7<9Us=t#qGLsg8q8C5(#6qGX3tt*%jUb#Y_v>D&24mxC7`o|R5$i6S9f&t$5-RZh> zk)?iS-TPCFFzVT@UP~DFlvT)yD|!w(;iq}>l?5ffRe;$pUhkC0j`%NeBTr$7GEa0@ zn7mxRMLLVaWVqAOB+oAb)?Wn#GecpO32z|7-|{C);bL`V#f=5Z=v*(%h*!{RxRoFZ zy^0)gLbp2>Z5C0%^4MJqg_-+EOGh1-A7lIABbea3w95Bl5)sEUrfH*(a!g?(Bc>MY zl?e%Nyu`Ak<*Lr7ys=`fjEXXSRZufdCj^W_|8oD_pUg)lzxb-s5ah9d1D6abOyyYG|VDRi(r{?AEY>jrp)hrkdi6-e8hWI zTE)mS#fBO`^dMto{XW3y{iY6}4J=f_?qMT@k#DLnat4~Nqw8o>le{uiMX4nq)}*P! zTQ$9}#>R6|`P(B^@O!k%dN9~Xw`RpB^C6QWSN$Oy&JWb9RgIQTtD{9nrp6qj5F69I z)kJql#ptM`SI{2zxFi2gv}dMPzeVbL$(`KQb3wvh`!8(ZsO_ROeEk+Ka5^AMtVrG* zhR+K=c5Cp;woHS?7$Wl>5f9L%m=QtoBKA=vU{IH0&}i=AJz=l$4kRtyI1_I-eZ{C~ z^cw<6j`ul1rJ~kr{MQ%c<&5eII!XhxjGwA-9^u%$9%=*8lTop^1t-Q|_ra={!As>KwaqL$e)aMuS z0X7z1nnC-EUbtrYY9COn*T>+45&y$5Yh=wyLj zFjsXBhBEilmKP0=SC}fXu%%h$amK*`+8PhB;fhN}DWBiW?(T(E)|m7@Y=y%sl}Ugy z!v2$h)#9P4N3rF-clwolut4?bWS(S)qYJe7)Xm~#w-(cgJ;X(WW?H`bqe}f(*8PLt zYi|@YIE~!qtS%I5$S)4IvZ(U`C40SlnNidctV z^DuUT4&YXBysXmJ=`Aw4AWk-6C_@avpXqn1wi4WHW$O`t8#jC>W)q-^H-mw3T=iAT zJFDo|{Ub^&h$ts7EY$zl3h88(pR0o?U>VV5*O1-H)f8*<0l= z$04yQg>|Rpr~65$gLJ8o+QcaG{L_1eE2sr+%G#@Qd>ryh-gK#VwF7f`tt;*`zs%Sp%?;g}Lc*S!A$)PLy)`n~J$ z{eHw#6VdI0?pY&l{G*eZbgzC+bTd^<<3!gYdRS%H=oA|4TW#6!&eF0FZL&F|SBDus zRjLS?rNfxMVpspI2+?lZJLl<%h*J@bC{(QilFw(PH+7gP#W7!7=`Q|Y85kO;s6#Ko5i)SY z{80K)41SsdPQ~Bfw^&j476xGUqUlwn0YdUJ&r-$#}!n_VEc$LJSs=E!Gz^38AZ7vcl#TRV+?PB#@)Jx*ajE-zXW~;D*^}7N+(OqZCkI`rd58 z3TBNERwmo<55;w#yhTS76DEv{7GWcgjZkas=)-IP{aBD_f3Uys6k<5EwR_UM-g04Tv0Dc#iYN{q(3vitPVBEj>Mu+ zb4*?+uL@V6&9}pex6+jiIxLId%b;@mM;2p{pBcQCmP-1)5Ti_p5p>l^jIyDT#XT7d zGo!7-nhH~YsAce{V5~8x6`OiUQoWvvlHn#06BpB37^M~u55}Q;a?p#ps4wakN2S=c z%#qAsWGXSl>g2kTjFtE%%qVGONq@7UT&%j(<+!1CzP9#}y+uWp_njD?Dd+cz+y$$_ zcVoC=t5$h@BOA}&Y!)6Rn7&P~^WF}_(EXPq_x%j&@*?o$!~^uovez7tAXCZjZ-6UT zx`Heku(~HWV)RG{syR1$VC;0d!lU+~lh2i;ZP$B`!tD~iB5ZNGkVQpkn#p2p9WH1-!F z7M9Ur3aE%G#3lmlRN}MhcDk2hs&G$`b_A$(P01X_aKSn(KMGp0ZpE;>`GkB@ z{`Qo&*2lW>Kun*#qVlf&OQ-dO3BT+_?)(tH%2OcUSemQ68-{J^^%^oy_bufDLhmCp zbX#fdTp~82f5cv858z3F1vX?9S=Klh=cbQTRE-#L7t+q$tD3z+f-0W5N0stM6w&UV zE^nx#V%#4B2f`VpfJd^4_dTVQeEPPT{>u^W_sHF>s6rE&(2dNd9bMfj5TDWGo-rvx z?A}05&gN|^npy=^CyI<93$?jmo&K8*h2B>85L2cy+=aqEh(;My&k%ZW2wld9Zf`WL zelJ#+zg3&7{OAT}{X3T_3pjG9rc8XaK;@%g$Xz_}ijN9cW{fbwA5U|2MwC)%ap{M8 zL3^1{Ghw*XcPbjKCW0K4jbN-u{sVg}1{n>hd5M z%?SeAHH(PIMSj&py+4|eJZrhPY~;Awh#j^Xu{w4|A0>^RI-+$?_CgBqd$Y)jDC{Eq zBOV=+KY1{+VOJzNGMH!z47_^~>LZ2zjTw0Flimn)(^G$l4rhIh@*cU@>ZVsOsaNN* zg83^GuaB1gkE*4Ul@&Q;7;hiar9!MmGTC|C)L56f)BLJmEYjvY4}i-T26)Jzx_!-?yaPxl$6gbZ5qt6 zFFu0k!fi&$&u>Xq-cry%{sIk4^ejz_cJ6)|=$y1xjMm>&zvZ|wX?{B7 zwnwVC9+g2D%c52f&UP0n3hkndy#W;>eNA{XUUgN1Uvqx5q9l;h*^gyqn7p~rm~yZ+ znKitbgFh}S5BzaaSCJCxvKCB$qiJ1bfeL`B5Un@3TUO+BX}~I>0Ri*-%CbHz@~Er^ zl3FupG1zb`ObQ;#>11;k?slp)-irG@tWQw;U?lx@2R#~5H@YpeTsr!=voX1y) zzupzP81{_y>g53pUF~*D)#`i?qSMz%??~iB z^(L;>w3(?ZStT|uBe|{7%*J#hLZ<&=M2!}WYCQ{?!dx8r&Tr&k{now*J65Y|8YF`{ zbNjr9#}ei)5r^i+corf^3{5lIh4n4rh_Llnd1E-!2ZYAGTRY(Kr*odKSflJfx4WTN zXiBfx#mub>R6hcXSw*^Xt7d}-UnJ8kuPz9l=CS?7g2sG_v5pIYWD}JCU_ttqu-u;+ zQ#E7$qWXaq>!JG<)IHjYG$;wWaHWmsZIrqAzEYU5(VQXG6e@B{P3W<@qY%gi{YWi< zWj|3hoadpTCDmirt6erH%wv_L-Xf6`LU#VpJ>Gg>iX??BFFKE92^(gu5ULgJ$R~6X zBr?h|vnO1A@W@XuN)F&nFQp_{gtnrfd~SZ+9C&7z_V5BP*7H(Lm9*9vmoY`oC!xa{ zvb$$Dln7VrcyZE&Q`B|REp=YH3`G7}C(MeDVU;A0fJ%di-2{pI%2!4-q?&{slt`^I z!!>;72N!v)4fU{qL}-Lne!1p*3ZMV7>gGb{k`QCh8*9(Q6>*gk$!Iv-pA^E3_6{Jw{AQ+W=~SDB=$FjLI`R-2S&*{S0yAsNl&r@F87!anyoZF z^DS8!XW3b}R8FH7K#3jFy-P+tWP^P4DtVTDT+q#%JJ6k|F^FRKym8}MW?0y6g+v9{ z`K4{S2?~p%0W96!hJlpG#UM8^>IXyN5_2$njUZN!{<#gr&bnIl4*i0s^-2FJ|A05B zcq0m?-SS@VrdR}Noejc!>=MIA09! z`Q0`L9%Hp>#@*N{h=hNkisU^Ed9MdJYvsohxM9T%bvu*K1T?Cv@ z&u$o#dfL(jk;1fF$8+44Dax5!yUk0Y@7%LqXEr_%6GEpy_)SP#9ir5BzB&GVi6?EL8BsSf z+`$-0v4QI~&Vsbw*s;QM&h(K_4EE10GgXg+F%wV)8iKu~P0Tq^bx!MriFKp9Je`qar9C$IFR^#C8TO6CR90?0v9VpNuto|k! z_!XS1$=g6Px)o^!3#XQ%(^l`7s@@lUTSsoRrQyNaC8)6`nr8xHN00^FSEnCDK#xEi zilkL!bCyKWL%L@oc65$Sr2b-A`dyonqLJQ>PF)iks?p|f(Gqud5q6fV1GPyl=-KAS>~8sl zcNMIc4G+f|jk&^f*~=|MVYJOMRrBU#6Aznu?(EE;KP(|!A+C??u%90ycH5WUM>J<| z?li}gcwf|CvYxv-0?sFc&4Ievn&rxsra{gUe->vennjJ|KuQ+cmebaq-m2t_ z(QX2Ep`iOuE4Qi2i^gf3>`B8a#|(UT&%VX7iP1JUnEJj9UjxNw5*h48_)fQvlvs1b z_Y(#UOn~9D`VE8F%PZ7bV0Y5S^j!=yob6C%t!>X>VWC7L-cE+`whMS=f zr>sjv&|n8V*&Eu{uR}XL)cq|36BNsrjOz&vH=>IaY;G~N4Gwscxp0NHlFw~utZ~tL zv4;n2Pf>JtsQJ4W%n4x>O;dw^i$QB1W(z<|Ejnks##fkUUI;2?mKt!zlsak z_S(rNEa4$!pZL@w6K;bLO-ofagZ!_Qs2^&_ym5SW=}bG5+I~M7Xxe9fi_>?QXcgA9 z$LzozdMfdJSpAxk{&V%93&SteIaoQPw}RK$qwOd!7R+tFm$*+MVnS5b#q%txanTLW zAnQ+)$fSm0Gp?snwj?ui;(Zwo72X+P*%_CUO^uwgH9k>3KDHP$CSt(x22eCAkz{hk zNGj2p5};JVlV)Q+8>mwHi?tS&xow?OTnqo|xJDiw0R2Go0Ty24WPNhk;R#WY8(vtp zo+U9oX3LhfFq&VthZfj@r5QOcK`r!KM6;6{Ub>tgTE^&qneMh4`W??3#13;0JGlV? zadI`;Dm<(|QPorUc~4jZJTgfoRBpLRNKqLa(-__mGq>UyJF0q)EJ#V>fxPpPfHNLc z+20MjMP-hoOyr2vu%Bm=Fy?4$zTF~WuhcV3I2l5-Ev?3xTu0qc+uYngrz$y>q%m%4 zjOGg5kum0TGb3?>2OM-UD15< zS@+a)teW}Yd21x29ar;+r`sv>6f(Rco$ijtH3(gquw%FZ%KAjz*qp6xlHO>3?2K$6 zgZ5O^sZCz~Usbj|JH52A$f!&VA^iuf>5ux0cb8n9vo`BK9c9k*oMSE^TF{juWXn}+ zy=pAWetxv24asB56sIPl65T_`UuT^~+?Np^*Xy>+T#i<&r~LFFIbQV|r!L zm4KX(aJa9@PA$b9iDH`b@ey61~Ve}Eb-z^lA#WiD>qzbppxljf9TmWLcQvh z++gs-8yrgmPx~HElU{^K|RZ zh|JDs6W=Met2-X5IxJd_;R)Q$FO#enMT7{Wx0-e}c0S*d^&?f+6S@#F-^g=U+MPnn zoZ6|fHTp$R}I(6WDMgbUMKLNLENkz5hb>t{jIPflNS_*JVYg z@E%5Ad*Z+nHgB1eLshfx)tybjfhh`$Zs-=DaVfoF2h@cmI1g@L#~I(zC$oh?IlxOirqo{41F{q=ec{-PtSU5)1<-1e^D=7F{CRO2XH>~* z`&(=7yX}ye2a!FdyqOrWaQl@!)rX$w3kec%3gkImBk=OFD#tm2WNI~%*q8`hMF=ql z4r;LxG|LKL)0(DEJ7~fc*qAbUOuL<8b~Ksh{=2D}N1HzOEU z=WQs;^_wNsv^HVDMr-4g-MLLYtk189yP1;3o<>!4(WovkfiW#FJl&Q>%L; zE=KP%C38lagKn>=KH?RbAyF`DQ4r9bChmMFd*VeG?!*rgx~zqgqr!9{HuR zlRI?r{Jc*i>=>V1v^J+6Hf(M)6%q}5md&%mMD$Q3biCVo{@g2O+HgBQpSk(R)`cmVgSr>W6#p}LAYkvnv#A6iGj zR@qu>QDRTrb0KViZt7H&;}k#dPOF6_FvN$HWE0-@9Pp$_45q-*w7f1zz7X|U!5SrQ z)1Mfa1-ZhlMx}O+txzYP$AOvXlj>#i*Bot&x|ZN|G2c@r^GRAkv8EJy-y=R^h*M?D zlXVF`N_T61!V`^V^Q*0NkJW`J*GcSRpfD!Osh9)9YIlZ=N>wv)MM#W34KpOX7aq+C zBZi!~ElL34?STcD2;%jkdBV%5r44wt89*r6tKLs~cnk{kIMX*B-F1%DiUv$NUq9u1 zvoD5}eg5P{Nd*y-j5mnAk2AVqwrN>xPSm)9>YyH@LsNdjwS`vqw*Y2-;B+%jRK1v= zDGf~0LP3l#)XHVyvqR0MtAlFgqK2e3U`BN79G|Q=QKCi6y(*|HtK-GLDzkeR0{)XR zL>ij|AGsW`agw_AQ=ztOItn!*ayy>%a69_DXKy|XN2EkFTiz738KpEXVUlj7-PVec z=b54*wx3%#JBBAJPKbE3T;jKP9dF=qFbm zrAI5^=EscO=H(tqsjkbvD&wkji5X$AQD>{AZC%EPR=VT`(LThpywYQ8tLNg3Xvm!_ zqZ$Zg=*lU1$l#1+t=tZ;>JHPVGe@0`G@@X=qj81Xkq>V~19hWwq9QJ}T??Y=?{CS8 zb3@ZSVpQ`v%O4g|VW9At)zi#3%==jDSl8djOK9Kh}HWj+;mZeJOXA(fx-z66w4<@- zgg7I$SjrW{>U8FQXbS0prvS6w+ien5>+8UcQ*W~@XjG&{g>vHGi!kq@v6V^>GwyNXj%tz>gPf+;Heqf z8;y~|q63#GqEj`{7meYZ-i_3n8ckl+M^g33h+ULT*Y&&$WTtanHe&&28tW+#+v*0a zqmb|f_!sitt}wl|I?iKEK@!x7^|mk%eS|q#i-}NI%*OS55?3gdI3;$7uGeN2utc{= za72LV=3@Zue%N}2=Ky4x5iZO!_Z3ubpk_t#q?L{>Y6ApDt9NLwZH3L)e0ix_$PpdG zBSoS)OF;ygJdIYJY)`W3jwuPgPWPO>nzExY@}y&KNec8r&7FzgKVsKNEd0qxi6bx+ zq3mweJ*B4?oNo(0{B*YX8c!wI&^bn_?$j@=lI2Ksa@obfjJg6IIihJ3#OTP-th6;7 zURN~mEWFrGB6FA3?p!jZnh@1BlP_R(TRJRu{u=uuj7C4*yCJpmo!ryH|1DoMtZL@Z zUwtuG{j=h$8jewssG1iNQ0}|^bL|gg$HBduZgs>hym>;=b}H|#+Z+?+g^&Y5hiHMd zCHN!GdWn9jf!fG(K%NQ7(yVZAev>is4ZuJr8${?rROK-+LGyt3RRzb)3<;{TWzbY8 zgwp{>l*ko|f($5ASoVZ%nETo@1Xhz&8marqOu=ayG$h=`v@&R}wI)|n+b6YrO>;w1 zO!H*;^rG^31a|6|j#7YeVL)5SJ zVxuBJX6H#vcsh*VQlF}4K@52Al?fBYE755AI-9(Wn5Mb!0B_0gH083L6_F#DofVI0Z6W#~Qo z`Ih_D`=IC)U43vTA+WKqqC*gWXWV)n-|$wEhz52Z2cyyrKNhn zF*QLR01qFU9(Ws($aqC7+N;iHo?Gts<#TUd}7=r$GdHA`y2SKeVw16DTAn_bTvvbvVIfm$)t^Qf--(lj3m!g z^^^qG|IVlH9QYd>5T)F067>z_I0&W@+-j=e2lCn*OeIG_#ubdC4Wv?+c&IrA=Vwyg z7I>zR5u^UTjA8R4B9?@8-Yo%X*4j+*4=2unJ-h~mQdP29<4$dgn5_R;opbdRxDH}}kGD(C-TNai}Rv>wCglE@| z$+Wj3PRQqwl35gQq?@xvOExplIw%krDaXLl=55bL$}~k|=8Oug^)5&dajwo|1**Nd zwWlLrD&I_s82n8F!UfEil(n}W@?W)7?Y`sCNaGVQr>4SxSJ#lS2lK!C+?#4b#QC>< z4G3SjHn*coym+0{2_Nu&d2d}#T$|C{5Hm1HtfcyhB zMPLADhIZtq^b$Lk!q-H5=jc!oGiGk5SLvh!6u~u}5{sP1wPX*qBG;L8Ns_6FtT6|z zk2T!x(@i+ekJH)t+w>6`A1OOy=?taF)XEUEhs)Uc8KZ$fy2SLzRg*PX#Ec$D5b7tdc2SAIX(Z=GcJ5iv*cuOjhPuNC#=qQ=4FWaFlM2Gr zKCs#{sbz_NOV96H=J`tX)L41ofTnPg5cRN$k!KJr9!%bWX^v8>HlP)^B%cVjK1=Rz z!+!?Iy_~W;&(f4>hN)G1k~GSa;`&;L4D*V@jajdg^H>rac-jo!HHK5X)Q*ySulp?e zk-`+50>RbVpv)TI9C<;)Rk>b@^uu$tE7bYG{4?lnHNg$>=0)bb!k8-QmhhqyF9nf; za9>Jne^Ww(+mciD2x(Eu{4KtBY1U}6!*PX@+%rgx*&OUy*<5+2nX8zJJivPGl41ZsZ`HgSE!aSH8SLvsSooHlT0rep zB5r3*gyWP<%)4pCg;h)a0maq7(*1WK1b-fdQ#}Y1d1pJ25^;F-RTbMyv9R>*7PALx zJm66N_(!T3o_*qcdZD6l3Ikm(u7KV(KG{71^Fy*XnJp=@`eHFs+pWNRN}p|pHn=^YGeypi6WG;Rk1D>xaTVeOoL`f9 z&2n0En;&t|a7My()T}_Zi#Aut=fR8y>XjU9t1TZBN}MSQA)&IWY=e-2K}u1+#+9f2W=Smd=^p1RH*a#kOLV%2W_2JDl%C6iPm0>+SpRkr(BBgw{&m7R;j+zFCw zc0yX9vn~0A)zW7&R*4}3DkX_0N)n1B!qNcEG2yl=#W{PstWA>REzt26zoI{(*J73| z7m!RqZUVx@|JmJ4D9Z9(e*$QqfOlYCRd1l;mhzJ5?8^v_4!gvk*c$*j@Y zlzC~y46Ds=5=tE8d&FYiWS1hIMQPD^JmoP(V<#)LRKQA+t5tJtx2g|VxAvRM^n}tt z!ZNM3J~pV!4k8r6;%}q1D4(5;wc}-u*2|J19|sM$LHWrwQs=hp-F#Kd*+Wy&JGLaO zk?mDk>lVhf4ASCZufGP)2@`j&x-Ad{dXXiXN82%fEC4+*KXRv~ZLOw|u;&ypCQm~& z4c`@_B37yQ0%e9EWAsxJy0CF!>pnK)sou(-rDI3 z6(AI67#Jsf@j$|rL1cnrvZ`g_a_j@^rE^oqBs9Ph6(B@kJb&{}R7KkSqE|_-G-z&l zV*Xp|&LnJZN>eDEHZ6ouWtOPSmhM(d(^93B#+L{k zbB-S0R+FcCEphce9iazbGJ9ld>inQw^&?_2rOU@DO_zKh5GrUap9n=RscYZ`fp!UuPIN;IN#Et`u}TAym{+ z4PdS%gUV7$&PJQ;S$_u7_S7G5TYHE;XVQ?RsBvL+h_X-LxlBrIlgC9~VY3FO5M`P3 zmsGr?sw1%fj`s?s0YjGU`71p!QJ&VOa$0@rztLMNM|mRV7x=1=z%3@MEHMuJtO1t^ zBVas+Bwns+L$-i=u%WVk@X`Z#xC93vn zmp85@dWaz0bgMcmHWM9($;u(WcpEB27Rj3$4c)Tla{SN~=_lbz-IGDe&~4p*HBTgJ zL88q=;xYkoy2NEr(pF2l)6N{>lvCJM@bx%rU!F0(1W%hTTjOeyhuYD;Dq!;ndzLv< zNk#6^Ew;77h)10DQrw0O)ZHj+M^N-c1R}kTh}J(V@5~A;db!)iQS_<;wCXIEMW_=Z zOO(`NWWa#zt9!F$ngX?9J?T&yk0sdag)STMbsk9~;^~1Sl4wg(lxzRGQ?|>fUQ^O~MeyRY z?%QYw`ezXX<1`k)gcrp$XEI0lRxqnpt3>im^(){P2D*9_DY-3xS1qPt6C{IHx~at1 zNA|4_3=%3exiQ*))@2LVmjPF{7WBTG0o8P4Bt98n<8qqF(%(_Aj6}wrkZltjP(7FV4U7hYo7!x3x z9`4M1u>k6Qc{nKsDZ3O6tzwv{i?HY7ipqANTcC>KO^q4`+1=AMr+L4a^?|Sp2`%UN zAl=kvnkO2*pvSrq*=M-M70JR0ScM2;ARW3cVb{`JcD1$HUw>E)!m0ma8KcPpuD9&q zkAKk3e~5-640-lm+D zUJt~iF;dMVhLGTDmr*m|)cP3n(H2Cjn#~|@rS7CDA)ZdG)>IqGITWr~UYFR}&#PZm=5xV$? zS?^e%*wRsu@|L@uHsyF^djlzUz#`7NJzacJz+k3XW5)U*#@6=3VRbA{~d zF>C8_wY0GiNo07yhiA#R)y`904gX@S$7uVtwBk$9tmOL$xtq)3UrZ{&$n#B0@~l?i z&#nLXHcNplaq4m1l9|$*CECzqjwR57&+B7W$+KUgA{rPUlRDAUsL8U#r--~8O1`ae zk?L%CsJRHUqR$m@jg}isC0-N^9UD72rz%7RJ?7FD*uxb83D)yXhr36rW-8zcGF(v^ z`StANMDl(k4w_NPF%j3k)uI1sB31m1LpP%7Q$EkAlsvupYr3o5(09OOXcj+NDfsH$ zWUjE&;5E%A-HX1ETb;(`!fceq&NR;`Zi30bR@^+>RshW=x}8IJyXhu3kjt2(v*Syq zAm9CD4m$UlE{+_N7|r{PI@~-mBG2?ZMgAGqJ7i(7M?!}U2*L{AGmI>xi#-qFk}J9r zTh8ZMH60nRUzVVccDtZ&*iwBrFP0!jLXjYdctC|RM=q90Ly?PQ;2gK zgJG_L&aKa70D@_+xrA|jM|8U&94(Td?m%)qz&eYZ?0Pt>wGdaKy}PmlCg=Pq{(tkk zaA4s^(o%RVg1d2?RzvnOGZ7Ub^f;vdVK{-AG&ciPRJ$c{b3exs?m4BgRRjcb#2tUBP zG&QqFf9rqMr+S{-E`T#XE?Cf%EaX8w{z;=`utzi7d&wgni{N7zLjD=;n}*Uwyc158 z1iCghLw%x;+jO=5E4t+t>tD}F9vM-WpFoXYbjOT;3ZXBdB!zy`mF2EkASW_{Sta+* zipv~eb!9`MzJ--!`j3UIpVheUUKxJizcC&-yrHm28x_3d55I+z!L4jnasMU5>z^jp z#n~NF_OJhyG5=F14)o1F=I<-{Z~cvs0}j41-5F=;#r1jq{&|6?bQIaKdW<;@bQF16 zbLuRV;fq$tmKVg&LK(spa-$qnS$NM~V%2()4`oT+so3NR+kX+9)K8p>GaOl%xpUH& zO{v^e^eb`(plbDmWTFco{0se^DZv`3tFKc3MQNV=+TuQggYb8@!QbimLV^1DDav1z zVXS2(4e4YRedp%`{eIK-QNwRD0Spcbk8WmBSNny4%Nq_%zqS90vZCbizB`tp{Ka<~ zz~3ndn}GLr`HWVbJi!RU;9|ch5>30!otvp@_MPAG{|Eu&Rmdj#(lu$g7=deNfNS&b zbvnU*MLYOmuwz|t!0Kh?UBL@wbJzPS1XUTObS4~WD7|Z6Y!a?xH>_@VJ!Ak`p|xI(yTZ=eL23`8$$6(Y4_^4 z7OKt^9WnRHoEwM$^8fBLa5zo3^{y97IZ4lwRJ4_k_-ovFYxepCddPNeR87A;KA7|f zek+%vxTp2)c(0Q$NyNUrIRd3*_6toKh5o00xNOvIKNE**DW6<9I+(O`5dYKv3s=3@r?={fjD^5}Kg50EOlHm3R#Ud& zRzwi^@v~#B)2E6T9EYu$g(MSMxWL1`Rbba+a&E0tG;C=&Utkb;i{5lmJk@{ogdK#p zPpZ)5d(F_rD+};P z9kZI8)d6$~x3v{WJ6AdR64ew|bNb(X^v>)7CUuRz3BMWn2&8{S z?OLeupO%ln`Byw*f7DBYF|Gd!V}g>`zaoVAVLlERFUkCKExWQ}F+FF#iVd-;CHFZOZ?fH2${${=r!OcrGguie>Jj-evesxI`;2PAix^^J&yYK<3IfaVk6Y=(aTQ< z|GfzWbm)J?ZDjv`{HK2sBon`fTz|vz6DkCM!}2p4KiYr8@&k&W8-K&{Ga5hIf5Y+v zik};Q!}2p4KiYr8@&k&W8-K&{Ga5hIf5Y+vik};Q!}2p4KiYr8@&k&W8~;CnREx0;UegTqi>7Kl1GrGFbt9^xq+%nnJ)Mcwci{HcoA|Lu13bEo`Yy9vKK zY8Jv+HG}12u_a{qMMCMvMIx+3f6Vg!I2%f;@e{GhkHi0LlvsoQm_PjINdf|9FyS9} z*ZFa}DV+BgNzNaqjU`C_$T0llECE$?sPw=7{b$R%neOk8{tr<8?&<#kgn;00@%{rO z1b^%FA2Ipg4B5)-tLM&iByy&W+JF4`G5gb}%f;|hEO(EWy!VDNKmFs_*u28R_%zo> zlf~B>f;t)TySuxwu|neFNs}&hy-II8uHU$^xG`RqkC2%S^wc*rWG<9aIa$}qsjM_q zISrEyJaj|i3knME?=E~6>tfPNvU;Ofv@9XR=cWZ0wS*PrYiHSTIENNwB zrFt<@A-k}!$MdC}qr!NQj8Xat6!v-Ln_u_gq3>Hc&-2kSG57A@w6L%^USNU8e*5fM<}o|>9^XpeZ)ntG$@T0Ti_bcmR3_N5?0LiHW}Z zUvI=kANMSKCf1m{o(v$aE-o(aA`4*cm5@nWXXnB-T*1eWw#!{Fc6%iIwG`^*pWbW> zBPL&HCg*-THeuz|PxJEYc#Ask&j*{6_pPmYT$P+%U6bylN#9Y> zg*ZElSo+RKjn#PC_bD3!f?Hq&OH?`CO&X#JOAq|;6@f^VDQ|fHUO?J;%8lCf`a5SUk{Ire6ICEEnwjIlX|d=T}I*FFJp_Q7DU*^tw~ z*QoWXNLm>lJH%_4ObG% zO#1E9*k05nS#>J&WfeUFq;YqntiL^xQz07$bG0O~rx)l=dYBd}y^{U%CD89iMn;Oj zwlsUEI7$bG0qJ|+^?7KB!Dq_7qp+}SWkIgn8J)y^S9S6!-;M0DGD+YyKb(vMGVmQq zU{%72Km)!hjJVWgx;8IA|8+`DZfGTUpQ*Dn4u7<_x(JQodeYq7{7eNXyN~wW{mi0? zmC3x{k$COKjT`ZaiOfN+fIb2yN)S-6xJDma+jGH~y4lZt=?b}M@FF0L!WWF)fuo~^ zCJahSN&=j9fUE=k%K})C^RKmv`hTsF!LN%#D{pD0iX|uo99#vgOn9yKPu<}A-J10& zY{w7f>ZCqWAuaEPl`7AkU=J6Q?gO%R>C&Y$XLcJX929)E%*!h)KVW^JcNRioZAdgU zGR`d4|U;*7E$L;N9>q&!{L{oG42i#Mj* z9}0?#69F^#-LA*R&d<-k<#l=R;KBD^0%St?u!_rX>8XD5uz9Z%Y59rUsBPH@{>Js| zww=!e?zId7xPCVeUESS)S-OJ7;d1v=UI-ht*KIeN?Ht^UV zJJ4-8@PAl_>$A9pIPvTcA3n^Pu4V*m-AeFW&xE+RBm&*f%FUewY+J6gUWG=ZfiJRR zJg)lq`0?ZF?M7TSaQWgYH8u6uu`$*&XCfjZ^6j(MJCyzR9e@YCad>8uN&2hMyy^H^ z!)rG$FR%Umea7P+;6?7Gc^#n9*Umltau}qksTqh}&&|IBVIgYPPE8H1+-4z!w9^nm zs1}1CkoyE$5lwt3yLC(}8qYIJwjrsfr*{U2*@kEHLWm~B@MC~Aiw~`AAtNVWe0qcH zH9ad&7UWa`Fp#$}J||doJ|ZC@q0|dCnw^PT*9nm?P}>N^KR^r`6c{cS?xlQJI6FIj z;Od;JDjB9z*?bsGJou>FstP{}4ZbeDdVUSc#2Bp=rg%)mk6G zUMU~%w5}nMU7(yX+_Z+FpXv|H3IkVeEMzZ!*|Pc`82@+kO)ArQuLfA zCnjuX8-x7%aqGF6iCbG+!zd&YIaUcV>&t2*CZ}lwc$_6OSQx2N%}Q;rwZmgZ5Qq*y z4Rg)+T4QKCkRt_>$S=U}Vz12Xm9P9|%2dA^)`cDk1W3-WyDTZn%d;h^ocit`96US@ zoUZlSop6HHG?~+<#f88@4wByHk8zzF3 zuAh7QT^ZI;DB;7c)qy+zTnkY1-9MqM@cy4$LV%&Pp2Q=ur#J1K6;<-<>lNRmrBQL! z6%~nQ_#-de$6~hnP1A@TGB8oGO{Ww zJ3G5cviGKv`NcPT^SqC)>%N~qp6mDg?ti*oH@?pEIFIA=d9Tk&g681k?OlZKAG9%2 z@Yu1yv_g(!*LR?tC?um{ccoQIJi?RCD=z4d4o1U0xN8^I@5lVi7{O<(_oX-fD-9ki zlU?4zx$vFQ?S7(q*0p&vv|IDsAwi}fV+{W+?0Qk&wDSc;X9J#~*xX=Rb$$J_F+1E+ zib1JA>G=@}2?uEzR|;KSI$mTpG&D?)*Ip=O5-^D#)6jF$sFv{MyIIzxI6b?@NPXLi z^usC{x;X;lXcLMbF4C88aXaU7_IT_3A$2;+#*JhjnYCu}OypqsBxd^}9Hv6f1oLRl zS{2>DKh&C4tmh-HJPOPz$sxHkQ>nP~658_(Al|(1%BTzZw1)!EgBO>oPBDHSZqMEQ zBllv;%a<<+!Vw(mrAK}DnxhpKUJbS|GxOvtnBGN8yLbOSDRd)6tcvfc6bdE9qO*XT zR?6UdAfud3%>K|7b#=vLA+x3pZi{2#F?kj!#Ie6V1N3a$zTNZlBPJ#>+eu+cdyYVu z{f|GFALjn|78XWY*!}x+!?}Euw9atHPzyb|eNx9;rykuD)bn^8;(p?I>xaWQNRPJi zoL{*nl5~kmi8-_LU(WOX_19mdP3hldj%>|$vJ;#Bc4w?Ws=P>S%0nXaH!>KiN%Faw ziO*oQx_p2)>Rz-*;OWyijzy^krLMpJUfy6j3h58`?%ng88FOFD)bsboR?&8`@$~VD z(OMb{U-HCmF=itL^+Bkpoqzh)O;xu2E-DGtgHucTN0`a?%F4=~K7HEB$qCOdCbII{ z>U47yCoSiZ&z@7;g)R47xpGAzS!Vrl+3;Y$XU{(47rly$+utSLzto|G4$H)+b#U9f zKi-O+B(w6JfRIpeb;MbISGOOZ9soq1&)32xB1iX(k0?%8qm~n8U}ChpwCfI|#Gwto zyZ%)n>IrII_q(~*H8!3-5+u7|W^aGYbuumd+4u~wwczaR?2qyO+Qaz3jT;FfLLVdi z#BaTb%#(9_e*8m(z(AhJaz>!8n3$R>7W44&@%6WH7OFTnIL!a#lH{HZ!V;YI-u~d$ zty`!c5AV|iZOo00A80R*2E-PM0%a^s7fbH?kz0NaL|~S?c(zz_@kz_+3{(t)=RK(f zcC-%ilPCbso;|yS7BVz6BP1N4bS`GOyF=jy5 z!$*&9F3~>%@~De1FgNP+E^9fT?GZ31a-lJZ-w=q952Q#B_zL(SA}NXY`Sa&LyhVri zIoxSExe$TNKy7%Hks;tZ@<`jyIwYIHNEEzq-MV$3NONYT%4d3Et&EI~x%=6Fw(b!9 z8=aH>UsP12(3pWAH7}UyktxtdfsLgGclfZdu;2qTe%kU&NU$$0bS{ZUX@&vo*bcWb z1N&c6QDMR@o~fL|ZaIAD&<3n=tkv^`44{JQni_>SZWksao;-QtSsu`stj$4fOumr6 zSaQMj=_U20$*jVtMaf)?Ev9203~Ue49O|wO_)-e$X4y850J@8BQJM%}nh9rSP3eu3 z20Xd3v@oSz^Hwoo@n`&)d&P``gs)aF5W4f+P*&_zl=dAgyW7%S=k8s))P_WY4eI7l z$s?kpIeUdS4@?no4aolK+qbLaK+M+FM9Fj!Bv&sid-~J6cgL-5ZKGWaQ1es^oE-)x zCK|QF<9yr&{lWtS?_WTa)0;z*9UpQD%$(d`Tbpx9@XMIWm8n!SD=Vuu+g6Iz5iPNW z@mf$3@$O!rJ}k+h#JNM*Ix_wTrOOR!y4SLPF}KPd{;ba?YTb7+Zt1d$%2`E4#Wp8e zJ`m7h)3Mf|GOOCT%SjT}=q61l2cBMDXGkl}$oQ;j*Z#~-R({W>8~9pX(_{9{m(A~rvM~|KcGpMFM7v~5|sIOIP?T%CHpVGJF5eZ%xRVX+3Qm2tnXy~-4WyD|y z8hZ@4Y~reoYv$qMaWK6OOmJs4V-XOwLYK3P%YtX`d?!=d#wz85e;ml|4456<)7kr| zKJq}l-NS{%{uNtMvv>uV&eJ?_y(6XCi>W_ns;nCse68w$ZHxaF2KF5|@Cg0V$jB(L zp|c<)!+>+hD#vv^g2N!MVoQc)EJd)== zP9w#T=5SEEKupV_``ObZwNG}euc6tbrC9Y=aO>>pM_Z4Gk2k&Y{)h)7hxY`vu^8vR z!xRnE-+ubLNAI2&iGEJ@*-2y8LoFExa&mLK&_WzK6|p&S(<6BJ0d(E${E*I7XmOeTeVT}Ta1Fw0=np1_991gRlH#>J9+og$8Vb+|w zm#_|h=RzW{RZ1>754L6VTU?aG<*v1}vtwF+_grV6eX3^9T5S`^AK<_G^9QkMNYf#J zejOttllT(0Rv(_K=xcW_e!s_R*-(KR{@FA+UvQ|)Wqzc%y1M$wm|eEu;Yy~*f)0ES%m3Ve z;DFx8d+SH)6fbBhylymGl^)gTGbl0s)AvG=KaaX)W&k-vZu7-%`kto0FSxTnd<*-< zb9gq^c6I@6J)EbuzB)FmlJxy(>Z5YGi>Q~Cwus#87l|Jh4%Q9W8cBK$zCj( z+PCWm5efk1pY{ks(?}ugY%rxbdi;)psay3yG%dd)Q!9F{z&_xBXo@ zdrcO@On;Y7)hu((jtp`h$p+F(oYh{M&?d4~o}ML?fII+Cd@=uO_(B;_XR_-=eBaQJ zT>dbX8k{PBKKu@m3V_wlGrTEbkZdV*TS_+>)R+oYSW@P`b%sFCO z0@b7Aadn3KuoET@zNp%6Gio6@)n>J~@n&`$Pt^1Bo0$Yu55&bEX}Cu!;-d=TM-%ZW zDJk}&C0t_?2Ld(j6aeOpeD~mxKk&lXGD*#dC)0Um)P5+V@dv;{t$A9Si(75$AlW1k zMjm;vI~sjW%L3m9iGHpesKnd9^TNhX_b0uMJ(tY9?MHu>5X~3hi2H-30ib)U%q_#%HD7+x@RY@RJc*6Hqp*) z`Xk4Y+jpU+|K?OcMR|>hstMJAS-N9A7w@eR`KiKj^o4@S5;j^Z%F+)VgqeAsbF@Xjyi5AmmTIH zXIJi0e_17}p*Y)nVWgOYG%ftVSv*&%eY%IU+AL+_IIyuk1ByQznIn=xJqKuTS6_7m zT^jKJ|7%wKQO2LfRyB!*E&`BNO#Y8J(77~P%2$jXwf5e&sCYOJkScEn-}mps(GnlVzXF$n2|CtR{f=rDLBAlF@ zKU4~5FTY>^#wsH=tJ77K*7J_QknYlefX%7TT+14@-Nb3vif}7}fWg>m7o^`a^b?>9 z0cW^yY4K^xah%#BscQG1YuA?8@H8ZdIXbLS;zYa>YN*krvzISwTX->aAyE?tEw@o6PYC&ty&AKWcTH11iEseR#f59vbYb_rta@o2=! z5fS=TT~Un@q-Bx=at?^S&bUy8st7@e1mrSYBxMJ|@A3}^#xN}dRJF>hvylkK7EpBck_edj{Q z78mCDPk!N~)taT3^tXM?E~u!5PS7=+OAFh?QrFP1H8C;q(&furPgtnSm zkjW$82?HaeeME3{ojqv4d-61H-qX|bw1oxD?|KyUUi*RA zn9+_jp$_}qdcI>NwrS|BN|GWtj#yXuKZW<#`P7_Z01eWG(pS%$7G=>O{x=CNX^PB; z0)j363M42lJ{}U64-Q$c-NFatj2M0UW0CWPr%cs%tnlf&(z-HU_|fa(gF z>QPdz1~6&a?-Zo8C@B<%jpK-%1t1=91R_1WrAP7g5-CNOBcKF^kF*B|2P+o8PD-kH zyQ+CXBHx@83w3pMvZp{IiL+s>4asE$1-pFT^e~>C_x=0W9-fO=w6()cIsqh#7a;OH zxF5^tI=i15^Y*OwxqY(%5q zKP{jMk;ZwZJ0QTh&6!Rpd)B((YV>+m!B2pi(Gzwue||pD(0lDjW%-sWJo2shW`{d; zHFxO2AlqE$h5|M(6W|uVez>)%Nwp1=xdEFOm0uS;L%AAkO2Jx|Gs}vwem86G`exnp zqSmITEXc^*oL5-iMx^U>EZwCU{ne|S!E!gl#`%(O6gaDL~sbNa%}6 zl1Zs`x$<#!JjcB<{`z9Hl16qJmkJ#A?Z636kUtFS3Mwip>RP&{N4nsn`Q}XaQ~jLv zhV(lzy4k8&xrIxzwYixYzyFe!7CR|JsCG_LKz`%3mf2N+&TPyA% zUFgro#>TAU+CSz6rR(>q8(O;mF5!G0z`*=^!$j{N$>Rel@^PE*s-ylxew0T?YCrz9 zc0sg8wl`lr%iN1A%zl^NPyoAGc)LF%yI7#(q~zhlPX>y?Lme8K9>@I;3bkv{5K*WJ zozknV22y|9^W5}E#~36rqJIqFx!GVN?lznzM~WOxJ;idAq+>P%N>YEwe6riQvAn!I zwh`5Er1~sJciR^`$gsq0@jUe0nQmLuT_?h%m6J4rMnY|A9c)?cw(1pAP(N(X|8bg| zj^ew2|9+y(jRbejUpxQnGdArO)5fIoH4Mz#wtaEnMP2sc#8*gl~lPO54bE> zndB`k&ZPi-dRkpzbU$wg_yKX}Tg9YxD_n9Vf=!oLs!&-dB)wqs9PWtxEc8pj>`?w4{omf-NwMty>N)qs z;;%(W&ZPybO9S|PK!5oSubwKfO#`a-bO+f?A;1xeficIfKHHGQ99O4T*ePNsgjK~HJdn~3Hjv& zb!dx`u@jpdS>| zzpgiWcP`%+s#Db0uwGfT?}xB!US0M25(Tq~g_TwD<;IzlDR_K8;*$%WSI^sWT0PWQ zNO?TC;ep193}4QVE4Vm0b`acs#`lk}H zguEJWFCO(1$}KcZHcVFP3@XnynzTEZzLgD000>7%&~%<0P6`*X*^jlS*Ba9p3ng9( zu|}wsumgT0771}607kK2$E9xS6dX3^HASfglL51uhkP&RZnh>0b-DLweI(lL z^pJ&H@J5EqMhRZ`?SDQwtJ_-<%53$9$UWyprT1(a@sOO~nQ76fb=}o2d)OjrRtv5_ zpd{%VfcQXfFg4AJs1efrCoVR-WdR5R#DHHJC>KpCgq_&xsC*d!96v$0DGKcUe5WZX zKrg9xO5Bxdmg4cQ$SnN;qbXM_{oN?np}%>9EM31cVJ`CBEPK{GNtFcVRMU+v6{S%D z_kRv`WrtBW)6dBi`u9`Y@c+m%KeC*tJ*m_8H@@Dd1(+~Dk?a;)J@#HEd+G1i3^OZ{ z5g@G#2dm=sndS+~C<}*#^Rb3x?Qloe02w06EY4DiL-Ke``0c-@mjktXcD)#i4mN)X z%oU>*F5x0VteZ$JE+F)oO1Cijr?DXJ5odjR+F#q$pgnDdj3Jw^1yY_j(-X{0!&@*6 z`30A=Gc$8mF7`%(_LD3>Sz9w1t6As#8t`{^X0yshD(bJ!XH<18CYBkrR5k{@P=6| zpR?w0oz@{Jdm;xyV!`}qDfg`n*&i-GWRpa#wQ1B0$gy)59J>&}wyUeYQG`-2D zW5y5*h<M0w6KP!Eh;R73{#QdH-lrV4woS~}pra6N37>nICU6V_5JdGTEhhTV z=iWi9(rs*Quia(6Ch9b4CZ%4IHRCubP{Q=n-yB&E^TLHmB?@rHBOrpj#{A9Al&m_} zEB`18245?!Rx)f|du?EF&{G93e-TLX^6@D~)qe#+q<8L7dGEve*Fk064_BsV0Lmh7 zgK{AS+=bt7;8{4cj0uoCcw^3UkYDH-K4_@iZV{lxyjppx*7GtPotftCEI#6sswT4B zo4-CWo#)S;S2CX>f*2vyDR@4_Ft$R965DyJ%bIgibBH!l|QZ*Tzr6Pdq_l7l;6ZH=>`cfF+lA^6vFT)y=Bwe8+uYhS2E4i2ExibZf2rP z6Pv9LK#w(*ES z0F{;S)|d|H279HF`CZsBetqSd;!>4( zEV6;e;5djrn_b(JDcZHs&qD4zr|;jc|EF$N)3ioz;%PM-hHpuDZ`zPhvSzWg@mlZf z;9;6;cS%0COWVnq^@ZySOS2{#F%O&EM|4 zTzmkK3ly-|>i)Qcxuel#+fF`ZT59-{t!oWS>+P({8`DlD%Y@!BsGJ$CFBrU;iNZfU zKUO(583i*{sNGsI&J6^Kk@13qmPo*YTN05+K+XBXs%f2tZs*^2!e$_@)`a8SAM_E?72;fMqx)^8)OO2K9+GR`*hw*303bgN1!-WaIXGvLwzOzr(zWOe zrD!usHYvR%Q%DX^uM<5bAvpj2JXFK32V7zMW?fQ+TA>Cess_p?IRzhZ9tH^XLbIuh zZgs!?XX<~#GSOPli+<~mb=1M~+1A!py~;50Gd{uj{lm}J83iX&#Wb56U-(HpW!t2R zX0|ljSg24a!$>7yjjwRt^8C$nyv++Xh^#5jelf!~;xI(R9)V{F-vwowXy^*8vAt`z zly;0e{u8c}i;pJ24TAlV0eRck&DJMlNYK*YZuekEzUXfYaZ2BV`{&xzvH|(Vwy~W8 zyM6#`%2JMm(k#ktkE`2?bMM`E@nb-x~Lah0;geD79pTT+_>1o$FvhG1+-#H1!BtW z%n|SO^x$wk)+=nddSiER@fLa`b(E7flF)|B#a)PF;e$*~f>HQ$Z)6{2;FBW-BKPMq z-26iVlIM9z>>dG0?h_{2C+|aT+6Z%i+3K;zSgdsRhmX4~SMS=KBjG+<{*1wh{17Z7 zvE2z>WkLMJWKe1^W3cBo5L>KIb`{v$mjWFel4G!^V~9i}x6Ohr$jfIyBRJ`2kUS-( zv6a=B-wy9)K~_47RrX>Sb!N`G_j>bK;{ExTZ+%nmB#qVg(Q=z#M`3f1K(p8y+6jaG zEkswvm%JcbH^%#_^JtX}tf<|@(lt?@tB~FD{FL7jrgE*WfLS(QC<{0agvjSns|O37 zQZ>?OOK=|!YURD{+irxTPYBSOb8uEd{e(-@cr4rr0i^FO z@4f3G<{x26XE|Kbe+mzy2GP4OlkXLlnG{K@dq++c2|XSOqiI={3!I^9+J?sCF%h4$ zZb|`Y3?0!b8`5obq*Dsmpejg6wT%L{aDju}%bXSjz3EvBwlBEx{sZ7cFL8}71i!Zq zEB3Qw1GCYU@whcqhg47bB2Z#|Xi!y4zUBr5y-hv8_ zDuk2$SL|lK|4*5@XKRdPI*&yUt~hWskU;k{DDlf^JL-DTw#~w(wOAh zf|#bF93QdKb3_H-RnQtThCz%or%ZN5o1fM)Ij)YLd{8|zp>G7Vo+C!ky4gF6nmU2!o-6&%0E5ujc;!Hv*3g9adPmmbBKLKawa2o=P7P8vz-utqdJ2%C<%{a z!d*q+m9EuV8oUwf=S3y9pJ94o{|eO}Uv~Kh@K{LHGk#N%tL@A?@`MpYBg}i(sKu3V zcJ_wq>Wv&=>U-OhN$Fr&7Rb&3_^|c&hiG&fZmLo?u{W}PVPd;*%&JEg!d|3S088ET zcuJXdTQH4|0`=BmxmRlPSX9^?YLcmu5y{v-a}GhspGNutzCm$W-uW4)=7qz#QqLT< zRx`4D0tS$I6Eqz%!hnCs*a`hTUb&VOy|W}h2k|#%-kkSCvt@mB(3cE3N5@0ga&*57 zBhzrMzE|44=N4j4H=sEXy%~K-(&E^u0$Ok~hcn0Wmh*p(TuIe0@!RkYXy)zp?jyNo%jS$o|VIlOqyKDYH6GxZkKANmq?N#S}r&`Up`pA zGbk2NGb*cF|rxw(D( z3A)sTe{z5O6Am?A;Rzq_^_(ec8Nb;_kN|SIS87tiT_&61$?msb_#2OuvUv+54Mxrc z+3;I9Rb(Nj!o-mvy2q6+6xyW0Qd>;r7Npqmd2iB}2x$XlhNo8veC14wn4Wq#^gP`lb zz2s=D3@1K!b|794M#8RLz_Gt48fKcB>Gn0>I+VR^D;T9-eca_6wEQXmJUZJ<5UuFd z@&66c*v{Vj8nr5YOG}%xNbkabBC5Myp-+H~A4;TJ!u&3R`g>Y-{fZI>wHXkn%cB#8 zuqzebbEq77LCHiMMboDKa_oBNe@N7OPwy!ZKVm~ECO=xqs*mi8D--043;7ithurWm zc|Q|9*}7IPw)~C^Rs^ZIMK_Y*7P_wlk-Hq3Ugs) z$I-WS-`>fP`3cBbh9-ALOE*^evmN;@`XEm%BhgD{Kj1+O*pR^!IJ+y0qaciQ?ro3I zWevNa;;4BL^aZX^w4g|3Jv(fS-+lY|J&h^C5lMyw%xU8jC;mb5(FgYJ3Q!Q#4o~`B z0#wxoTl6i?NusRb6L@DtBUkT`?PxSj%D$%DqZ6eOAQQwNeE<-xDNv&QYFvL975R?t zI062{*nQ#7qta#wrV7N!2DJB(>^;~7iq96)S_lbHYpO3kaHgXWcpp4*0r37ISoF2K zQx*O|2Bi%4VM+(L?`{;>55L0=jQs?BbWO}UA z$kH^`N8`(mJ74#gz8UR5q-(H6G$BEcIX*%6v-g?7Ze``5F6BYhVv&Xvt%e(RYJ61H z;{EYWhr9PHE3175Z?}D&K>kryP8q$Vobu7T`{S~;ZSx}wrz{JExwuM7l9S>qi?un+ zeSD`JmbP{z8%rx(zWj`Igt5#n+uStz4Ltkzr>}@MN&!%5=5X z)bT@ya#B(*A$VlDxh1`7&fjcViw1ANylWx!T_r`u2qGOv2*=oL&$sM;2!+I}7!JMk z9Y;Miyv|W?2%uOu#{w?IEQkjGl~b+t&CZ?Lrb}Vvvs~)PUDQ`qJw{k688eHm6*hXP z1O32)(sO<=BgEK!V5A70Z45Oj)Wty6^N^6EJ%TtY6{Rhr+tyv%Ug4iCe)}~ZBhl=- zw{fWZyB137xP{AihF4C8^MSv|#l{|PDe#@k-mt9YnxSFFjV`H(g0rnPXnh|R+srk) zEVB_a4zR8i*i3H>zdd?~am<{Kz4gD>jQ_?l-YxS*Lc8fYvox-$4vcR%_u|$5<2zm) z-|=laZTFM=NYZ*1+j_JmX%}`_pSz|s{;qpqzy#dI7?|I?P^kHRPQxF!tQpSum%ThF zzq}>n-r6XU4aX+6p85F&p3Dm|vak?hPzWgV=tCa+5}MspcJ^zFwHG9X7ux^_v;iT7 z<9+47?h5Y?@rKO_MdOS8;8C%C%v74?CbJEAIpy+bTOl#A1hkiCd$Djj;v?50Qh8KZ zIJTrj8r}@ljt`qzz9AY{P@sj_ob7ym%1+OQkI(favtGSAiENlGRcNRwOHdb95VhWi&>t=mCxb{xE;xjLSFGt$1-(OsGRaCtwxcW`;z2qVY(^XLY z9^Vj#RQ{DVRV=Q3@!|_@w*>*?P?>s3t~eF>;aJ}pir`q=X*vqfdP};oVo|q4SJCa`*!-Bw83FF zv#Pj^gT5T$CE=pZ>s9qv$=(3`(F?+LoM@b+S<%k zluM~C_o+?nMCZb`yoAJVO;v&O7r_@4iH6RZkiz20_wvg>*M=5~$I(&b8}+_lSB3g} z5oUUuec=9tI_Yis0`E9gy2Bq`|EN)ZCUHT>)HI%?K++3#H#^p~C~ta}A+X_?@|iR4 zDJqj~R+Uk0tJT)H$i&%5;Ts_!bZIfITO}YNkpwOteEaRPTQ{L~9jJAc&9Ra<%}u>` zN?4QsOz*>#orVo54I)ApxORMDIcbrYHg>~Jk7_3JQXkp4@?dQ3BPUyRr_Q}PFC$}v zNXcC%Q{a(j{{90PniOtMo<>$z*E6Gk_?GYxZQj*Qd>D){M^%Gg zFE=G}`I!1E8?V|oRe)U2C;LP0&3>=`_psD|59}XnWhIui_#aezb@h;uSXgjy?Ozwf zc5;vC%mt0kIAeU&zdsv{(+EkP=*P!Ip)r$31W&hSxoFhS)zoXOV#t8-4#DL%o-uS( zrNk}2#o;t~xb@CGegS^|2;?25pTZ0?zMB>0bg>_HPd)A|O{72a;HX+f|C`Jw)(p+^ zdjt-P4(fbrW>?DF=DqlHWtWvh?U+{Z|&= z(8SYS7?vkNyt>X#(gccEN=2rsE^9$2A$!YnHdt0|xiub^7imiPLVZI+G#Ose zYM?gXlPxcv6%8MolI^+f7JV}l#Zgk{s=uaqMYK=((HA@o;EGT*c)LGkgRfFZGefRKa<|qMZWf}-@ObN9wxN{H zPp!1%bK~RcA}*IxM=DrS1BTfHYZrMp#+*Kh>MI(Axrq`ej3da&1UrUY-Vo5LuQAPHB``|H@u|b~{_!0nG1O&9{?jbpU9u zVr1@|K72cs>$G9b3RzRrc!MEsT-^+F@g^(-}>+iRQLj zmRR1R%eX6)hTgi|$ZDsc*q-33)TWD%&+@$B;h>`nx~C|dAFZ)E9nnKY?D@=F$84P? z!qM2b(7QkFxYIP}XD%wIe6RVQeH6XxSIqEUyCwy^oz(Ts1ECf7k2(>ZA!yvPcM58Z z@2uU6KPCZw^|GTwOPcW`c7XlWc?$M72$Sy~8#_BHg3k}B!Me*IfB60e^S&l^3#WA$ zp;LAiNAC|ly;CdbYcy>MQ@C|CHM*jW*^Uz?MUDFF4IVsP|Cg*%Z%Af@q#}8MBcvQO zH2B-@Q%|L(Wk#9JR#^|9*>C$@wE3&uarMD%Pm?E|zJFLLaP;V>l}z41T(Snwvgg@n`9($J5glZ`#Rr{awkO!av+(S$jp7(5FKUVSyWwkXpl}6PRcq9xC{f-U zt0VilCbS*}=7IHnm^D|yT&Hdy~poou~`&3j_UxOI7-rKfV zO-E@Sz8oW(ypNmv(y{G=<*{QaXRr5F?S#1@La%R?t+Ah*yZYx({jaV&Ip`=eW=q+a zKuL#W^fvn(&?^equu+)l`sK1&NuN910!pKZwBX$_g)yG^*w~WI`&BeF65z9m(l@71 zzU-f5{ikqx75A@tt9N7fzmA^$w_V&^$=OIp0oNq$d*p3S&Xt%8;ezbyjC>Pw3uqY3 zZrVCJFG(!+t{bDrM-i(YPpk``pWpZ&Cb*b_f`YeqVxs0(rGI8WJ$rUl`i!&0%)(;A zfTE#c44EuE+Zl@2CoL6viJ8z*2u@8(68ylD0K|L#{CT9eqen+AA()tee|itUkAPJp zAP|M{(H^n4Ekm~Pk&&mPqN1eK5VvT!1ZQFE#RGkNR55sR1J??(m z=FFGU1 zFg^7W@T54O^OEG8;aa0d>siXv7o!ebYV|q2OT_Z$eQZy;?`-|!^(i`vGmp{SoD&Mi zgx$Da$T4@$DGdqLN{jem9Xzjf%Vmf5H4BX0=|T? zzgX{p(22fA{+zZ}6wHUXY3OfuSJ*cJ))DpdBwU(${qZ8x{t8zQbI;kVOaCA21FC z#Kg=*lvEt;?dS2^e=v;6+Nzo#+ExeO*s~Z)_AIjKY}&POUj&e@N}nIwvOUwfUjbi{ zev15oHPZbd&nD0TjJA&s{JdGO>NGic3H?xhAhI^~i=lAL#}=u<+ZHt$E_1eUBBdR- zy&eTP7fPH`XAI4_SNIcyZML?`m{t*778mKU`k>I!qpv|(pl~~4Ac4PNbxN|anOPl% zowf&@Fgx^QVk{gp<-1oPCrrSOT)cDQ1XAV;$^AQi$}-q6cznE)@0ij5cm{iAs4ZI& zG!&AR%rx^DTh%r3&DmL5D#`fcBv%Z!&CTF~ND*!+ILF{{;sPLNy1;8t`cz=1l! zeKBxlB7Qy6e`%4j^Ui~TkXqYuLwX}C1v@Z+zwUJ^tEd3T$m0Y@r{D=a<*>xD6qEY>dORD~t;(?MKCf56 z7N4H31iY&xC+D^COVHpH?_IRq8(j5v1}%)|7*7r1DVcQ!OJ5Ie9rC8eB%sb*Td@Tl zS9o#I`lDd#kXx;$=})JHP}UzU1wgSs%#Lgp^&_KXnZ4vk^Nw)JzPa{X zJCxK&phDB@*AJPq_giM8wj>cCem`HFi|T3JG74P#b81dbCk}=xberTF6UGKxn{V&v z@RQqo&Pqvb_qd}r#geEu1Z0>DWyrI!I_3MfhScXibHV1J;x~TWO|g4^-fTzPKVW5^ zr#YvYyaEQA^FD*@C3LEn7tdjk{q4xHcJV_o3!$B~#{SwEuML8xqSl)ly7hg&Arzvl zrx(#LT-ccm`R}rlk`W4b=85a_#na9!(z}7jbQd#qKCZ$=28C5xGde=ekZQV-GxsWG zE-`k|V%MezMgSf~9WqK3N+KrHmm=3Kmu+y1X%*T~buV&(|Nr-@J)Gi$2eaW$hKANd zA)wHUr?IPAh+jRba!V*^jr&Ov$MM&2aphkA31tQ|cUiK@ayF{ND8XPZzQ1TCpV&`} zbkb3XnFdWZwP4Ctmr>m=TVr-%s*{Z)a}jjZfN+6d?|5&T>|B{H-E*ovVqyX@ zc15IgKF}Vr9l)pn^a=CYCf~s-XY@cPiip8qqUOSsm>K=`WnPxK?a(z2xu1w4n8S6! zQLkV_sWHd*bT*z$9FuPaswE5scC#+FJ6AqUd+`mBSe@PHEKuxz9v(dR_#Zt+CCge~ z(UCdfE7_J&+<~ZIsbf$Q;$FPi!8IX_#eOiX$lH=)Bjyc4Q9aUCOzACh(?6~r_sjdV z!80oErR{1#qxbu(7a;*uA<`#s$(xxoe(~g+MeAMu zL=h`+&Q9swv}T1h9MZSPo2~B*kG0!c3NvM_+S|PHe9RRe2@F^kb+xoyfsJY>tVY{2 zTL76nHY)1#=4rOviYw=woE|hV_h%ZIy7lOL`I>|ptiL4F`yAo`9Sjh1thlo{s& z&zAIwMYUv8iD3&~C<9$ytwRk2;133L$A>N8$UGIk%NHtsNSYucfJMT(SZWm~>~KTK zI~<fldgen)6r#-XAsMK(-@}B0g;Nq@J z78c3md!uiohpy&eP;yhqS z(A9*y4a5GyRC>8rZ!39p7qOonfM)dV{qnOOHR_B?VKh7(aha(@)mWV?ppQlQ_t*b; zvq~Y-D$vaAYCV7*XV9HMBBU(L+MLDfE7VRi_GPl43o(EE3H|Z)lP4P^T$eB^6n*>& z4$SEM`SYY|veP0M1>F%w@S5^TGf-aQ>{w(HIHTvvX)y2OiB$ONI? zp-CnNj|}~iOvNp@nAakxv4k% zhC+w2Yh5h=NOe3qZkj48G5-Er0pUdB?7)O3Tdcowwz^J!dhi#$`^o*hyr7r07zzry z9HfzBEsfZDrrQA^dA#^+`$|EnT^sY^S7qv0JjGkPqDZRNAk?bGd#n2KR&-Iho$sD1 zLAZmJw`W~qhPV5Jf=WjtH$QwNV8+vmsNYT8TFG%+B%-PDB*566|Azhf5~PyXXrA5F z)F))Yzt5Hw{Y7PY_4e&C<8L~zj;D=`+`tD^Op52)4%I+d>6n}Fi?V1-S z7Z;n0iXgPh>|3?7;(*$4dzWf)l((;3aqpu}d%ly3-EdnqgkJLAh1N!NrVF=@zY~1T zqcTy|zb&BT%IE1DmnA_Xwwv-RqZRGib z2Y)6aDt#h@;LtQ0QZ#41s^>xIXakl3RO*;Og@Y6|!pZwQh$NvjZ*UBU< zYr)u6G-_9^)dL1bFYyrdr^p&?XJg>`ym}ujIB$D0lAMkxa7Rj18?&BV7<@L$|?={LYcGSl=W^Yt2o8Gncs-;3*2%4{c^dxMmb-i!&}VBa zLv1$gZ$O(i(j<+)2)mwsoq{pRFsv;Jfmt^OTt1IfH*eNMo+^jR^8?A z=+~}=-l$*q2t!nw`HuA?suzw2r!__^3O2Y3){8%YJVHipf^X*~EXZj_d$ z@$$O6v~b`CSWQRXTUy2u6O44>gQ=#Rti{H(zt=WbKv+0P`B!r7WUuw$js2IJG>wg8 zleF?pSoJr~v1hd=f?Yr}j)OWyyydU6zJ0%zAXI{MJ}>&Ev|#pXR9dhyr6TLE@?LmJ zhZQu{aX@XY?(ECmpqM+gdCL}rWo3al9pPPiZRjE{P)y8O9Mi)Y;YwpdraR1Xs0A8c zH-ZubMl%+}d}c)HDA~T~mZry^XsW8lxn?FOUx2ex^js+P;^>T-Xm-e>E3G=I8=fmI ze22-Z@mM}Ca}?9S#-yNef((qz8myKZKlpRDZWHaND+o%=k0qXKz7Vldg{_2)5yAM~q%LmB7 z3v-=I$|z|q3*I(9lD0`*)@A9#5qnvE6o)pdHty~B)NWXKHM7pB)NZblIF@o$Cv+g> zGnwm2Re&+n4PY~3udpjoFCjFYaL^L=)RCJS`aMe+0VlQN33FcLCx zb)f0v2TfjLnJTc$o8`0To|+8Z?w<>F4DeUl(f)NGg7cJLC+i3zM}bt#E{6&R6&P#d zbteZuie*g4I}81$7KjMWw$+sB;1;J}@lbGqgnaM4KUZ@gIqwx-UFb>Gk2ZKxX(=Bd zFkew}A{j`Xz>B1a7cY)O^AKXl%wQh~JD9h3QUa8@dhXL3bL^fdZ=&KQ@>8u;7QXf8~U%*QtqzjR2RRSB7zQghH`x|5(jU(8y+s#4l zxhPAvjl-7N)<_$_y%>!oli$?M6sdEy16_!0g!#m zniWb~T1g*1oCL|l;uFjTL0>A|jH{V$X+^sDINof=>X8|A@=3V_eZBZQ&;IlTk$2F_$=SBy#I?GsvAhA7E&{rh2Qb! zrRY>f_meGebnXmM|M4t1LmH*_((^znT6~EChxC>Zfj2w$3tD4d(#a7cKc1Z%89XL% z9jy)Sz+poj`K{w^pm<7}nv^n|gi!CgKh(*>2jNGN$ zLega9D#Pqpri0@T^ZI5;N&JS#e^vR5X0I_yTP2vS!7F#+LX1YR>RdA{P=KPQHPY#= zGOBART(z{+_)`s!bDlokq*>tHEZ9_%V*w${z_AmYFVI#!<=$T5pxo8J`)l2{1DJpu zCu4^)olhSivMN3D(y-*DA!FTHXwk9LwI z2Jw)jCY;a=I2dwH=OyQVooe`QX1lcdB7hdCQ%lmyS4kS#udv}GTsij#<0|mp;<7qJ zXcUHQ71y%DssCl&(HS1Tug$xv&-`z_T9%WJLcIO)@pK$z>tEkaVEKa=wSZX2^^2$5 z{jIX|vlF!n4vmccq2a;71Vq$L=vSnzJ)e3{8pc5%-W>5KV?Gg{^BmH+*L`HUxKmj4 z;1mLyL@#A$+Pc*Qg9DDpw{#VZ!SOc1gz{R6AYef5#hc21TNrmwm^?XmnrxE(cLO*H z(Buvbhp98VPCDizJ14(wT2K5}yK!jQWwnETHw8W}C>J|a@)(a--ETTck;Nz=Ri+zwx!jvv}#OdQ1HDf%`=ELEJ+ zz<{%uxYlzzJ^?UJwiW$uY3u8Gnxf~G8x5~rOGh4|HiIjt7!et@xh5q#6HrFd`!`-^ zE=^*)`%y>yH(^7s#M=Q5>u6JdzA>dPWUc-Dz=p7-#>U_Q>sL2R+_zQv?^ETzWaP7% zBacY{1A^m!7{>t5I))s4s|OMc!=%>wwLLhFe7FRqH3@L=T4SZHon0&YAK|aJ?={Ao z6b%An74c5FOVETUYZL_)+;cWm`OoJA0Sxr_S7ZDQ@58k2DPtz%l!!gZiu9;aHK2cC zI>75D>w)mf7>L#pZs`@x5eYAKgW4Y9mRs(XcJInFf%lp~cdWq@u`CsM!NYCY5#SoF zsn*#VB-D|(dy{4^s(UeqTS8WcqYT(I5!23|^`Hc*$E9AdPJU&T1>jp!Qu0=0GpiXz zh3l0|H+n&RXJ>diM+vH8swqAzE-}%@+Up;Iu15Im;Cy0!z9zUN1`&eb;Sf<1ub_&{ z&27yzpGVE%US5*=B>r)%b7J9`xSRGlItoP2qbv7q-MW=CRGaT89?O|s8`}$9)M4zy zqdKzkFX@q6nk9qnxhklqPuW*#eI9l%D=YituEgh;>04sAH||t}ZQsKGoYENVfpwkV zpA9t=TiF!Jk3U;a9^2l4DS7x%*PdHBiLq-Ix{B-kad~jM&op2$4sNBHx%qs+YoKzmIpHm z!>q>IS*6{np{7kkyG?Tc9h>zCyjZU1n1yIUjH-sWVpaa{q7UX#t zr*L0bZv82_G@k~+yS}oxJUA1#;gHibY2N&x#RCInex@%eZs3Q0w{pGKeR z`c^Nw3&tX9S=_B#bi{X7z{9}T5wyGFAQpDlfOD_J9*w7%P}yDkJ{I0H(ou2A$&I)? zF!-Y)B5|OCyKlblwq*9`lRy@PP)~v=COT+S@xT&%`QuN~|He_GjO^`Iv3Su=3aG7s zc*X7p$Zr~&P$&Z8OlwwP-X;>{Odbacn}A<}Khp)A3p#G|D(~+7FUlSFCE@ar4k2v~ zx*1DlCkn-yulF-Un{1U}*AXh7e<8&t0YnFKi&S<8oL9smkhnRta<%HI|I^-;$5WlQ zebu8TDyF1VmL@Hp3XddNOVU`fM3y*~m^ikOEqe-6Nez$GP%5(2$&w{YmYIr4b!3Yy zsgUJ34hdNf&-Xrh-sXKj^BMEc```T2N6ydropb-L>$fVedV@_3-&qejCJoB@?b@0X zusG*TCm<6k?fSSeBA(_UfB#|$>#CI*UlaJ5g~71MN)q#->rVNZGkF@$RcB3nI@*ubQ9!nf@azkzEV)Is$;09^Jxq< z&tDM;6Ys*)koBJJErf;JO5P8i3F^2($Q{kv>&pK15bpSqd=1%lh5~UzbQ53yOM%$32!uU+EdMEcQMKT#?$ip7HS6 zSs-u)A)8W9l<8C$78mZ7?DNS_WY|5Y$6AExbUAUrcr_k}oKjbn`C%Rs239|(8_j#+ z?d67|&3*kyAy2oKSDD9?jHL?q_F4|IYfQ7bgHH{cLJZ2QSp;#q)EXfn14JhYu^k5OF`1aa9-5b^o$H+ZSC`@G`W#C6TJ%>@WHv8ws_k$|dc=mc1H?+3WCMNs{K#p{x!qTpv zHSDW|g{{FnXYMN#0)IGq_J4vNm#L|T&`Xd)shOn{{~X|&Qb)m+>%}lOyz=u3Zf@>1 z>(L3Q|i5C zJnL;1Y5_8vm-~r4dnxPTuak@Tq|lv_(>t_*eu6vWF6-2_vJ@z;nIN*cyv? z9|+E2@k}W{`Bvy(PdQ!N=K3IrJz~-k;=Z+*E6=E`jXD`4B2qpBAZ7Cs+SOSN*}HRe)v{_u};GyXS&Ha|~bfrF2L}uJ(8$FoKI|-t#+A_zSQ<~A(_HeXXn#r*@}Tk#v4Edw-xR4q7u*kx{^8H zBjz>qaoC*>&Qm$`k$(fj_h{vsZ7V=ofN3)1KOh5eM8Rhu0mC8F3(C5--q;>rxcC0V zwO%E~YdiHbK%#E9`U+Yu%te^$#Rp#8D0Q~!p6LC>HCo-JAG83v)OZ(Q^jv|8N-XS^ z4Q;umyq;&RG11f7JPOa93~`uA>z4qJMmR&pXI=#;sJi6$&F9n&rNw)f%fTf^$*?}gtLR0XJxuKygk7_mQ zrB5PgFnRqs%6Y)5h|!DQ&U+SxwMM%ZEn1WZ*MM@C0e`gsTcLLvf$7DWd4{CU{v98qgf%T!k{=>w702o6hFILh42 zEFHy&hDxGTFN1ijZRIkc38_;$kd0JSXb>~Zf9HH?BBJX$1YY2?7C%aay%W3~GajhF z{38MxDf4yC0mPN4WnQD>0eu4luMnr!QJxXa7phiys_*vz+e#+~6or-j>g9hNHCW~V z)0KV*=JY_sV~8#ZR;qbYe;QjCa)iz;kF#*>j8)M1ZTGj?1i;qp4dcEX7k9U~*qmre za70QnD#VWC-Zs+NV^kz?gm?ixKbm~X5xxu@Girf6Li#kD6?_+SW4eBMhF=pY0LoB@UW|7N~jv@O6&W$VUuO3e;@g%)>>POSC)yF%%lx<#dCh5J5>rOO#3?)Fe6) z{w-!{*w@P+8?g_}iVSqBFGNNrFWLFqVYfZbrtNCH4%&j=m=}4IPv!HT+9@RM-Scp7 zi3Ksq5fSYV^75{#EgfEu_yf>^1g5P5kD++Ed2=s1%x`w^Th4EO-qDPW?@)LUggO`# zt}pd)Fw~{Vm_U{Q!Ux%n85BdHU>%oUBK1IUlzR91`qPpuUh5w-Rw2jufk#%e65hF= ziNXNSEb7A}Qa0gMW~!<W_#xSAg{Q<}QXs!fG`lmSWg$34+qMat&5p`^(mk9G z+!H$cj}K{$CotnIbHqobn+4igH-DZBf;{}%5n_nDWUz*P!YpBxGV&6I(DH#to%flY zTDY!e=p!;PZ-H<6M*NWN{^XJ1-puiE*k>i1>O3=Zpr3hr15{B&s*QD_QtT+*DLM4$ zWOUp(z#{UUdYZg38kNjqtFuo%avTAif!5FO*F+-gMtDylBiB<(We%Hlbxcni;GQQ> zn48BZxo^!^GhdL(#l@GWslL~!AGkJ@RVNNi_B;&@*4EPc1mg5qN$M54Z=7zKp@G3o zfbuPG%5+eccx;y|^?Zw)rBTv>@Ukh6V9C*<@u2T_1 zKbfkrs5F(B(k%5uv3jUr;r=c~si0($si=&1#+-SVl=<+Z))A)cRU@{J!ek+&ISQEQ ztueDI{J?^_xOi!xt-${^8OpE$bV)>`-UD+K6T>L*AIrd$Jg@1glLvKm*Zg9DeVTA) z?JN_N2;VO0;6S3Ydfr|%GikgGZDbsVE*`oCBP**!nSKW-MJxQzpFb}w`Y`~73_{1+ z^=q-A29>oNxn?gKLPEem1BH9yiT95e8#cw)NuSfnK(j<2L{Ufy>N`7=-I-VpP011HjVlUk7*nz$! zq9Pdj3=H<7Vpel=BN-j5$@d)T1Ir7bQ4$+@2hu_KBqSA>2PQe-_TFf0{U{4NyGB+y zhB4N+v|tSBzmN*zIzlHP=EJ{qg?!`EGDH#l(ik-=FQBi2-UY&e37iG>p(n?-<+OOo zFkO)v)@o7cu^-fwMjPmJjW!7^2?Q7z$z$hOjgC>7iQ9HA(on18SSx@lpo%|y?zOq3 zE5e2HSZ55$XvZ9vm$YwIord-PxG?JmWbu;r9VKt_O{ zuNz#;%U4YeG?SZ^hCAlQ^jL^DXR5cbFrDhMtX)I%0{~G@0A+jlZVkUh7Y+K%+X~7+ z6q2*lj&ucg(}l^7hsF)msWPuzkk~*lR}V?p*ctYxbi-6)2B69zZ2S$b4~PN8Gg7-+ zWYR8`6`mi03Rml80_7yG6&ZhuEaUEkShJwli`kA|JDE7&U!JZ$lMt{QTTC2yz+q{f(h1V&1KVMx9$GzbG z0OA@{Lnz|*x7sUGjzb+@CA;e1A`3&u*+F$zL|RM~w%@gQ)2`FlQ|LK1Kmh`>#(x(dV0Ul1lWGegL3}y(OU$tUl`0d;3KRsj=S7dD=(vW0s$aJ?DU(arZi-l2KuBrlI#2{*cOol-gJs42o`u9 z&_BoqsR(`;M)B!q=vM;q*#y4h-1T$a1PJ!}=4Qvq2guwhfM_f;<3e%#ZuzZ0Jsy{Q zntEbZ(2<}UuCj)qEOHV2TOO2UJbaw@o=S(lK<(5Xv4N9F^$11NoO@P{^VaHfa44pq zfW=^-&JAoV!0RNIpM6}Cg20AMl1TVENBksYIrkV$^+6th=O;l_#}MY+MK*|jfus<; zoaOMx;|@4~$@xb_0=qQfYCyk;6D$)W4rY=79P=#VyuM8VukUhg)yMV@7r^Y7_`hC?XE|4c*w>3g_MiU4`CVVH_}x$E z7tY~yzq?j&=^TOJch_!%{^Ea~5B{_l@}FYuQY`Fnw97vgUV{$db+hlno=@&6Yh ZJ_q;Y?ouhNeM=#?(%i4Bo}p$P`XA=3eg*&l literal 0 HcmV?d00001 diff --git a/docs/images/survey-distribution-chart.png b/docs/images/survey-distribution-chart.png new file mode 100644 index 0000000000000000000000000000000000000000..1704943d514fb3da05a7d878dd9734793870f3dc GIT binary patch literal 97855 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 z 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�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 literal 0 HcmV?d00001 diff --git a/docs/images/teams-review-doc.png b/docs/images/teams-review-doc.png new file mode 100644 index 0000000000000000000000000000000000000000..d7a12d6dd3ff3ae2c465625e0186283471301e91 GIT binary patch literal 162018 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%0DQx@cxPbJB9ZW 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%0D)|n(4_ol^!VOZ9Lp(lLMQ<+pq=EKp8y( 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 literal 0 HcmV?d00001 diff --git a/docs/task-sheet-widget-feedback.md b/docs/task-sheet-widget-feedback.md new file mode 100644 index 0000000000..d49c429e7c --- /dev/null +++ b/docs/task-sheet-widget-feedback.md @@ -0,0 +1,160 @@ +# PPI-DO3: Proof Of Concept, Feedback and Design Evaluation + +**Ticket:** PPI-D03 - Gather feedback and document the task-sheet PPI design decisions +**Branch:** `docs/ppi-task-sheet-widget-feedback` +**Group:** Feature/Peer Progress Indicator +**Resource:** `PPI-task-sheet-widget-v1.png` +**Resource Attribution:** Eloise Ridder-Strickland + +![[images/PPI-task-sheet-widget-v1.png]] + +**Purpose** +> To Identify design recommendations for the development of the Peer Progress Indicator widget, in line with user, stakeholder and project scope/expectations and accessibility, usability and style guidelines. + +### Implementation status +*Proof of concept* - Does not claim a live unit-level component or API is implemented or pre-exists. + +### Acceptance Criteria Coverage + +| | Requirement | Result | Evidence | +| ----- | ------------------------------------------------------------------------------------------------------------------------------------ | ------ | -------------------------------------------------------------------------- | +| `1.` | The original ticket, mock-up and author are clearly identified. | *Met* | Header (Above) | +| `2.` | At least two people review the design. A third reviewer is encouraged but not required. | *Met* | Maple Fox, Timothy Mifsud, David Tenni | +| `3.` | One reviewer represents implementation or technical knowledge and one represents likely users, tutors, UX or documentation. | *Met* | Section 2 | +| `4.` | The same core questions are used for each review. | *Met* | Section 1.2 | +| `5.` | The Markdown file clearly separates reviewer feedback from Eloise's conclusions. | *Met* | Labelled according to section requirements | +| `6.` | The evidence does not expose student IDs, marks, feedback, progress records or other unnecessary personal information. | *Met* | Deidentified data collected through anonymous surveying. (Section 1.2-1.3) | +| `7.` | The review covers clarity, placement, usefulness, anonymity, accessibility, possible stress or competition, and the user preference. | *Met* | Section 4 | +| `8.` | Each suggested change is marked as accepted, deferred or not adopted, with a short reason. | *Met* | Section 3 | +| `9.` | Any revised design is optional and does not block completion. | *Met* | Section 6 | +| `10.` | If a revision is made, the original image remains in the repository so the design history is preserved. | *Met* | Refer to `PPI-task-sheet-widget-v1.png` under `/images' | +| `11.` | The documentation does not claim that the design has been implemented or connected to live data. | | Refer to 'Implementation status' (Above) | +| `12.` | The pull request links the original Planner ticket, this follow-up ticket and the supporting evidence. | *Met* | Section 7 | +## 1. Methodology +--- +### 1.2 Techniques + +Three evaluation techniques were used to evaluate the proposed design +1. **Verbal discussion** within group meetings prior to the development of Mock-ups (With Project Director and Mentors): [Ontrack - Sprint Planning (Fortnightly)](https://deakin365.sharepoint.com/:v:/r/sites/ThothTech2/Shared%20Documents/Product%20-%20OnTrack/Recordings/Ontrack%20-%20Sprint%20Planning%20\(Fortnightly\)-20260720_180013-Meeting%20Recording.mp4?d=w0b96f239856c4927b309d448a06b7e8c&csf=1&web=1&e=e0uYqS&nav=eyJyZWZlcnJhbEluZm8iOnsicmVmZXJyYWxBcHAiOiJTdHJlYW1XZWJBcHAiLCJyZWZlcnJhbFZpZXciOiJTaGFyZURpYWxvZy1MaW5rIiwicmVmZXJyYWxBcHBQbGF0Zm9ybSI6IldlYiIsInJlZmVycmFsTW9kZSI6InZpZXcifX0%3D) +2. **Open group discussion** after the initial Mock-up designs (Teams). + +![[images/teams-review-doc.png]] + +3. **A survey** with the following evaluation questions: [Peer Progress Indicator Mock-up Evaluation](https://docs.google.com/forms/d/e/1FAIpQLSeXGCQzNpgdOlEv686l91L1ko58_SnHXD6obsdpx---WXpTzA/viewform?usp=dialog) +### 1.3 Evaluation Questions + +##### Feedback Profile +1. From which Features Group are you apart of? +2. Do you have previous UI or General design experience? (Yes/No) +##### Context & Design +3. (Indicator) Without context what do you think the primary purpose of the Peer Progress indicator is showing? +4. (Indicator) Which Indicator design option is more useful/comfortable to view, and why? +5. ~~(Placement) Which placement option is more useful/comfortable to view, and why?~~ - *Redundant Question* +6. (Placement) Which placement is easiest to notice and understand without cluttering the sheet? +##### Accessibility & Privacy +7. Is it clear that this is an anonymous cohort value (not a ranking)? +8. Is the preference option clear for users who don't want to see peer progress? +9. (Optional) If this feature were available, would you choose to opt-in or opt-out? +10. (Short answer) (Optional) For what reason would you opt-in or opt-out? +##### General Considerations +11. Are there any accessibility concerns not addressed in the Mock-ups? +12. Is the inclusion of an On/Off toggle within the profile's menu appropriate, could you suggest an alternative? +13. ~~(Unused) What is the single most useful improvement you would make?~~ - *Was overlooked* + +## 2. Aggregated Feedback Summary +--- +The following are extracts of de-identified responses taken from the survey & team communications on the *PPI-task-sheet-widget-v1.png*. These consisted of reviewers in three categories. + +- A **PPI contributor**. +- A **technical reviewer** familiar with *design principles*. +- An **anonymous** individual representing the *end-user*. + +![[images/survey-distribution-chart.png]] + +| Strength | Concerns | Suggestion | +| ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | +| Option B - it gives a clearer outline. | Option B - gives a lot more information but could scare people who aren't ready to see a lot of information. | Option A - with a toggle for Option B called 'Advanced'. for people who would like to see an advanced view (Option B). | +| Option B - the data is helpful for me. | Option B - could cause issues for subjects that have tutors that mark stuff really quickly and others that don't so it might cause undue stress on students. | An overall dark mode would be very interesting / helpful | +| Placement 1 - the information is where you want it when scanning over a page. | 'InProgress' aren't used by many students so it's not useful data. | Having the Opt-In/Opt-out in the same area as the 'placement' would likely be easier for most/all students as it's simple to find. | +| Placement 1 - does not over cutter the reading space. | Option B - I don't think it would be practical to share that much information with students. | As far as placement goes I think 1 or 3. | +| Opt-in, because it is useful and clear. | Example Toggle - The wording is wrong, we won't have an opt-out for statistics. | Option B - looks good but I think that's more of a stretch goal. | +| Opt-in, I'd would like see the data & would want others to benefit off it as well. | The indicator itself might give some students anxiety because they feel behind. | | +| It is a good feature and is appropriate. | | | +| I'm a big fan of Option B, Mock-up 2 placement and the toggle. | | | +| If people don't like it they can just turn it off. | | | +## 3. Decision Table +--- +Feedback Status (Including Reasoning) + +| Status | Comment | Personal Rational | +| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| **Accepted** | *Placement 1 - the information is where you want it when scanning over a page.* | Ideal location, central but contextually relevant. Given the widget can be hidden at the user's discretion, there is no point hiding it. | +| | *Placement 1 - does not over cutter the reading space.* | Demonstrates that it is not intrusive to look at. | +| | *If people don't like it they can just turn it off.* | Implementation requires a toggle for student wellbeing and stress management. | +| | *Option B - it gives a clearer outline.* | Clarity of design. | +| | *'InProgress' aren't used by many students so it's not useful data.* | 'InProgress' is not a meaningful metric, and should be excluded. | +| | *Having the Opt-In/Opt-out in the same area as the 'placement' would likely be easier for most/all students as it's simple to find.* | Clarity, connecting the toggle to the feature makes it simple for students to opt-out of seeing it. | +| **Deferred** | *Option A - with a toggle for Option B called 'Advanced'. for people who would like to see an advanced view (Option B).* | Out of scope - potential stretch goal. | +| | *Example Toggle - The wording is wrong, we won't have an opt-out for statistics.* | Not relevant, the mock-up was only a proof of concept, however noting that there is no opting out of statistic all together is relevant. | +| | *I'm a big fan of Option B, Mock-up 2 placement and the toggle.* | Mock-up Placement 2 | +| | *An overall dark mode would be very interesting / helpful* | Out of scope for the proposed feature. | +| | *Option B - looks good but I think that's more of a stretch goal.* | Option A provides a template to extend to Option B, this could therefore be a stretch goal. | +| **Rejected** | *Option B - gives a lot more information but could scare people who aren't ready to see a lot of information.* | A toggle is required to activate or deactivate the panel/component. | +| | *It is a good feature and is appropriate.* | Unspecific. | +| | *Option B - the data is helpful for me.* | Personal relevance but does not necessarily represent a broader opinion. | +| | *Opt-in, because it is useful and clear.* | demonstrates concept clarity and usefulness but is unspecific. | +| | *Option B - could cause issues for subjects that have tutors that mark stuff really quickly and others that don't so it might cause undue stress on students.* | Not relevant, students will be able to toggle off progress metrics, at there discretion. | +| | *Option B - I don't think it would be practical to share that much information with students.* | Personal preference, some students might value more information over others. | +| | *The indicator itself might give some students anxiety because they feel behind.* | A valid concern but rejected based on the earlier addressed user exclusion preference. | +| | *As far as placement goes I think 1 or 3.* | Unspecific. | +| | *Opt-in, I'd would like see the data & would want others to benefit off it as well.* | Personal relevance but does not necessarily represent a broader opinion. | + +## 4. Impact Consideration Summary +--- + +| | Functional Considerations | Non-Functional Considerations | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Clarity** | Simple binary metric (Option A) Vs. detailed breakdown showing stage statuses (Option B). | Reduce visual clutter and complexity by integrating the widget into an existing panel (Mock-up 03/04). | +| | Tooltips displaying specific percentage breakdowns when hovering over progress segments (Option B). | Colour consistency for instant recognition of breakdown segments taken from existing OnTrack infrastructure (Option B). | +| **Placement** | Positioning options: Top/Centre layout (Mock-up 01), below the submission panel (Mock-up 02), or integrated into side/top panes (Mock-up 03/04). | Non-disruptive placement to ensure the primary submission workflow remains central. | +| | | Contextual relevance - placing progress indicator near related components. | +| **Usefulness** | Provides accurate, real-time benchmarks comparing individual task progress against an anonymous class average. | Self-motivation and progress reassurance for overall class standing and task difficulty. | +| | Helps gauge pacing and time management for specific tasks. | | +| **Anonymity** | Aggregated percentage metrics - deidentifying individual students. | Psychological safety - ensuring students are not targeted individually, exposed or judged by peers. | +| **Accessibility** | High-contrast, alt-text and screen reader support for all text, graphics and metrics. | Cater for users with ocular disabilities, using distinctive colours, patterns, signatures and tooltips. | +| **Wellbeing** | Clear awareness of deadline pace and peer progress millstones. | Possible Stress/Competition - fears of being behind/slower then the cohort when seeing peer completion rates. | +| | | Risk of false sense of security if the rest of the class hasn't 'started' yet. | +| **User Preference** | Allow students to 'Opt-in' or 'Opt-out' either within the settings window, or locally on the panel itself. | Encourages autonomy and agency, empowering students to manage there wellbeing and 'Opt-out' if statistics negatively impact mental health, focus or stress. | + +## 5. Summary Of Findings +--- +Based on the feedback, concepts to adopt include: +- **Placement 1** - the location places information naturally where students scan, it is both central and contextually relevant without overly cluttering the reading space or disrupting the primary submission workflow. +- **Option A** - While *Option B* received a notably positive reception, Option A provides a realistic baseline to either transition to Option B or integrate an 'Advanced View' feature as a stretch goal. +- **Local Opt-In/Opt-Out** - The toggle should be placed within/on the widget itself for clarity and ease of access, protecting aspects of health related to stress and focus and to support student agency. +- **Exclude unnecessary/uninformative metrics** - Omit statistics such as 'InProgress' as students do not benefit from such information. + +Things to avoid; +- **Placement 2** - Where the PPI is below the main submission panel. It makes it redundant given student can opt to hide the pane and rejected in favour of central *Placement 1*. +- **Global Statistical Opt-Out** - Reject any wording that suggests students can opt out of underlying data collection/statistic entirely, the toggle purely controls local widget visibility. +- **Mandatory/Persistent Display** - Reject a static view where no hide option exists, as this could have a negative effect on peer progress and induce stress/anxiety or a false sense of security for some students. + +### Implementation Notes + +> **User Agency & Wellbeing:** Ensure a binary toggle is directly accessible on or next to the component so students can instantly opt-out of viewing cohort metrics locally. + +> **Data Metrics:** Calculate aggregate percentage metrics for cohort completion while filtering out irrelevant statuses. + +> **Accessibility Standards:** Build high-contrast visual cues, alt-text/screen reader support, and hover tooltips for segment percentages where applicable. + +## 6. Hand Over & Recommendations + +1. **Implement Option A** as the baseline template, keeping Option B or an "Advanced View" toggle as a potential future stretch goal. +2. **Ensure correct Interface Wording:** - Ensure the implementation text clarifies that the toggling hides the _visual widget_, rather than opting out of statistical cohort data gathering. +3. **Develop the placement 1** layout component containing the local toggle and test its integration alongside existing submission workflows. + +## 7. Reference Links +--- +*Links* +- [Planner - PPI-D03 - Gather feedback and document the task-sheet PPI design decisions](https://teams.microsoft.com/l/entity/com.microsoft.teamspace.tab.planner/planner.v1.df787fb0-1a0b-4bb5-9bc9-9b92a428eb13_p_KuipOoIL0E-7orl64gLd0cgAGv3z?tenantId=d02378ec-1688-46d5-8540-1c28b5f470f6&webUrl=https%3A%2F%2Ftasks.teams.microsoft.com%2Fteamsui%2FpersonalApp%2Falltasklists&context=%7B%22subEntityId%22%3A%22%2Fv1%2Fplan%2FKuipOoIL0E-7orl64gLd0cgAGv3z%2Fview%2Fboard%2Ftask%2FU0BJo6N2Mkq_kw3IYFFWuMgAAM_I%22%2C%22channelId%22%3A%2219%3Abd20175d09414f079490a2403f7fca74%40thread.tacv2%22%7D) +- [Planner - PPI - Draft a small task-sheet indicator/widget interactions](https://teams.microsoft.com/l/entity/com.microsoft.teamspace.tab.planner/planner.v1.df787fb0-1a0b-4bb5-9bc9-9b92a428eb13_p_KuipOoIL0E-7orl64gLd0cgAGv3z?tenantId=d02378ec-1688-46d5-8540-1c28b5f470f6&webUrl=https%3A%2F%2Ftasks.teams.microsoft.com%2Fteamsui%2FpersonalApp%2Falltasklists&context=%7B%22subEntityId%22%3A%22%2Fv1%2Fplan%2FKuipOoIL0E-7orl64gLd0cgAGv3z%2Fview%2Fboard%2Ftask%2FYQjP6F8GfkaDmq5IgUryQcgAL9Ay%22%2C%22channelId%22%3A%2219%3Abd20175d09414f079490a2403f7fca74%40thread.tacv2%22%7D) From d04f761187489af083c342c5ac28c1e7b3b23b2f Mon Sep 17 00:00:00 2001 From: baohuy-tran Date: Wed, 19 Aug 2026 20:59:41 +1000 Subject: [PATCH 1367/1531] refactor: replace flex-layout with tailwindcss in tutor's dashboard footer --- src/app/common/footer/footer.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html index dac770abcb..e0850b36c5 100644 --- a/src/app/common/footer/footer.component.html +++ b/src/app/common/footer/footer.component.html @@ -124,7 +124,7 @@

        - +
        -
        +
        + + +
        +
        +
        + + + + @if (!isTaskListCollapsed) { +
        +
        +

        + {{ taskDefinition.name }} +

        + + + @if (getDueDateWarning(taskDefinition); as warning) { + + + + {{ warning.label }} + + } +
        + +
        + {{ gradeNames[taskDefinition.targetGrade] }} Task +
        +
        + +
        + @if (taskDefinitionHasChanges(taskDefinition)) { + + } + + + } +
        @if (loading) {
        @@ -36,35 +60,54 @@

        Notifications

        -->
        @for (notification of visible; track notification.id) { - - - - + +
        }
        diff --git a/src/app/common/notifications-page/notifications-page.component.scss b/src/app/common/notifications-page/notifications-page.component.scss index fee98e829a..b4bc3e2839 100644 --- a/src/app/common/notifications-page/notifications-page.component.scss +++ b/src/app/common/notifications-page/notifications-page.component.scss @@ -2,21 +2,33 @@ border-top: 1px solid rgba(0, 0, 0, 0.08); } +// The row and its delete button, side by side. The separator and the hover both +// live out here rather than on the button, so they run the full width of the +// list instead of stopping short of the delete column. +.notification-item { + border-bottom: 1px solid rgba(0, 0, 0, 0.08); + padding-right: 4px; + + &:hover { + background: rgba(0, 0, 0, 0.04); + } +} + // A plain button carrying the shared row shape. Material lays out neither this // nor the header dropdown's rows, which is the only way the two match. .notification-row { background: none; border: 0; - border-bottom: 1px solid rgba(0, 0, 0, 0.08); cursor: pointer; display: block; font: inherit; - padding: 14px 12px; - width: 100%; - - &:hover { - background: rgba(0, 0, 0, 0.04); - } + // No right padding. The delete button beside it brings its own, and doubling + // up would push the unread dot away from the edge it marks. + padding: 14px 0 14px 12px; + // Without this the row keeps its content width inside the flex line, and a + // list of short messages leaves the delete buttons in a different place on + // every row. + min-width: 0; &:focus-visible { outline: 2px solid #3939ff; @@ -133,3 +145,43 @@ .notifications-placeholder { color: rgba(0, 0, 0, 0.6); } + +// The delete button competes with the message for attention on a list nobody +// opened to delete things from, so it is drawn down to match the dropdown's. +.notification-delete { + color: rgba(0, 0, 0, 0.54); + flex: none; + + .mat-icon { + font-size: 18px; + height: 18px; + width: 18px; + } +} + +// Never shrinks, and on a phone it drops its label and keeps the icon. It sits +// beside an h1 in a flex row, and at 320px the heading and a full width button +// do not both fit; letting the button squeeze instead wraps "Mark all read" +// onto two lines inside itself. +// +// The aria-label on the button is what carries the wording once the span is +// gone, since display: none takes it out of the accessibility tree too. +.notification-mark-all { + flex: none; + + .mat-icon { + margin-right: 6px; + } + + @media (max-width: 599px) { + min-width: 0; + + .mat-icon { + margin-right: 0; + } + + .notification-mark-all-label { + display: none; + } + } +} diff --git a/src/app/common/notifications-page/notifications-page.component.spec.ts b/src/app/common/notifications-page/notifications-page.component.spec.ts index bd2fcb0dac..fb36a703c9 100644 --- a/src/app/common/notifications-page/notifications-page.component.spec.ts +++ b/src/app/common/notifications-page/notifications-page.component.spec.ts @@ -5,6 +5,7 @@ import {MatIconModule} from '@angular/material/icon'; import {MatListModule} from '@angular/material/list'; import {MatPaginator, MatPaginatorModule} from '@angular/material/paginator'; import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; +import {MatTooltipModule} from '@angular/material/tooltip'; import {By} from '@angular/platform-browser'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {Router} from '@angular/router'; @@ -13,6 +14,7 @@ import {Notification} from 'src/app/api/models/notification'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {NotificationService} from 'src/app/api/services/notification.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {ConfirmationModalService} from '../modals/confirmation-modal/confirmation-modal.service'; import {NotificationsPageComponent} from './notifications-page.component'; /** @@ -36,8 +38,11 @@ describe('NotificationsPageComponent', () => { let notificationService: { list: ReturnType; markRead: ReturnType; + markAllRead: ReturnType; + remove: ReturnType; }; let authenticationService: {afterAuthCall: ReturnType}; + let confirmationModal: {show: ReturnType}; let alerts: {success: ReturnType; error: ReturnType}; let router: {navigateByUrl: ReturnType}; @@ -87,9 +92,12 @@ describe('NotificationsPageComponent', () => { notificationService = { list: vi.fn().mockReturnValue(list), markRead: vi.fn(() => answers('markRead', undefined)), + markAllRead: vi.fn(() => answers('markAllRead', undefined)), + remove: vi.fn(() => answers('remove', undefined)), }; // Signed in and settled, unless a test says otherwise. authenticationService = {afterAuthCall: vi.fn((callback) => callback(true))}; + confirmationModal = {show: vi.fn()}; alerts = {success: vi.fn(), error: vi.fn()}; router = {navigateByUrl: vi.fn()}; @@ -101,11 +109,13 @@ describe('NotificationsPageComponent', () => { MatListModule, MatPaginatorModule, MatProgressSpinnerModule, + MatTooltipModule, NoopAnimationsModule, ], providers: [ {provide: NotificationService, useValue: notificationService}, {provide: AuthenticationService, useValue: authenticationService}, + {provide: ConfirmationModalService, useValue: confirmationModal}, {provide: AlertService, useValue: alerts}, {provide: Router, useValue: router}, ], @@ -362,6 +372,222 @@ describe('NotificationsPageComponent', () => { expect(alerts.error).toHaveBeenCalledTimes(1); }); + /** + * The split that matters is which action asks first. Marking read destroys + * nothing and a dialog on it is a step to click through; delete has no undo + * anywhere in this feature and gets one. + * + * The one thing here that the dropdown has no version of is the paging. Five + * rows in a menu have no pages to fall off the end of. + */ + describe('the bulk actions', () => { + // The dialog is a callback, not a promise. show() is handed the function to + // run on confirm and the one to run on cancel, so a test drives it by + // reaching for whichever of those it wants. + const confirmed = (): void => confirmationModal.show.mock.calls[0][2](); + const cancelled = (): void => confirmationModal.show.mock.calls[0][3](); + + const deleteButtons = (): HTMLElement[] => + Array.from(fixture.nativeElement.querySelectorAll('.notification-delete')); + + const markAllButton = (): HTMLElement => + fixture.nativeElement.querySelector('.notification-mark-all'); + + const read = (id: number) => notification(id, {readAt: new Date(2026, 0, 2)}); + + // Swap in a fresh list request and reload through it, so a test can hold the + // second response open or answer it with something different. + const reloadWith = (): Subject => { + const refresh: Subject = new Subject(); + notificationService.list.mockReturnValue(refresh); + component.load(); + fixture.detectChanges(); + return refresh; + }; + + beforeEach(() => { + fixture.detectChanges(); + list.next([notification(2), read(1)]); + fixture.detectChanges(); + }); + + it('marks everything read without asking first', () => { + markAllButton().click(); + + expect(notificationService.markAllRead).toHaveBeenCalledTimes(1); + expect(subscribedTo.has('markAllRead')).toBe(true); + expect(confirmationModal.show).not.toHaveBeenCalled(); + }); + + it('does not offer to mark all read when nothing is unread', () => { + const refresh = reloadWith(); + refresh.next([read(2), read(1)]); + fixture.detectChanges(); + + // Same reason the badge on the bell disappears at zero rather than showing + // one. An action that cannot do anything should not be sitting there. + expect(markAllButton()).toBeNull(); + }); + + it('offers it on a phone, where nothing refreshes the shared unread count', () => { + // The button is drawn from the rows this page loaded and not from + // NotificationService.unreadCount$. That subject seeds at zero and the + // only thing that refreshes it is the bell, which the header does not + // render below xs. Reading it here would hide this button on the one size + // where this page is the only way to the notifications at all. + expect(markAllButton()).not.toBeNull(); + expect(notificationService.list).toHaveBeenCalledTimes(1); + }); + + it('says so when marking everything read fails', () => { + notificationService.markAllRead.mockReturnValue( + throwError(() => new Error('PUT read_all failed')), + ); + + markAllButton().click(); + + expect(alerts.error).toHaveBeenCalledTimes(1); + }); + + it('asks before it deletes anything', () => { + deleteButtons()[0].click(); + + expect(confirmationModal.show).toHaveBeenCalledTimes(1); + expect(notificationService.remove).not.toHaveBeenCalled(); + }); + + it('deletes only once the dialog is agreed to', () => { + deleteButtons()[0].click(); + confirmed(); + + expect(notificationService.remove).toHaveBeenCalledTimes(1); + expect(notificationService.remove.mock.calls[0][0].id).toBe(2); + expect(subscribedTo.has('remove')).toBe(true); + + fixture.detectChanges(); + expect(rowText()).toEqual(['notification 1']); + }); + + it('leaves the notification alone when the dialog is cancelled', () => { + deleteButtons()[0].click(); + cancelled(); + fixture.detectChanges(); + + expect(notificationService.remove).not.toHaveBeenCalled(); + expect(rowText()).toEqual(['notification 2', 'notification 1']); + }); + + it('keeps the row when the delete fails', () => { + notificationService.remove.mockReturnValue(throwError(() => new Error('DELETE failed'))); + + deleteButtons()[0].click(); + confirmed(); + fixture.detectChanges(); + + // Taking the row out first and putting it back on failure would be worse + // than leaving it. The user reads the row vanishing as the delete having + // worked. + expect(rowText()).toEqual(['notification 2', 'notification 1']); + expect(alerts.error).toHaveBeenCalledTimes(1); + }); + + it('does not open the notification when its delete button is clicked', () => { + deleteButtons()[0].click(); + + // The delete button is a sibling of the row rather than inside it, and + // that is what keeps this true without stopping the event. Nesting them + // would make asking to delete one mark it read and navigate away from the + // page it was asked on. + expect(notificationService.markRead).not.toHaveBeenCalled(); + expect(router.navigateByUrl).not.toHaveBeenCalled(); + }); + + it('names the notification on its delete button', () => { + // Twenty rows means twenty of these buttons. Identical labels leave + // somebody tabbing through them hearing the same three words over and + // over with nothing to tell them apart. + expect(deleteButtons()[0].getAttribute('aria-label')).toBe('Delete: notification 2'); + expect(deleteButtons()[1].getAttribute('aria-label')).toBe('Delete: notification 1'); + }); + + it('pulls the reader back when the last row on the last page is deleted', () => { + const refresh = reloadWith(); + refresh.next(many(21)); + fixture.detectChanges(); + + paginator().nextPage(); + fixture.detectChanges(); + expect(rows()).toHaveLength(1); + + deleteButtons()[0].click(); + confirmed(); + fixture.detectChanges(); + + // Without the clamp the reader is left on page two of a list that now has + // one page. That draws no rows at all and does not take the empty state + // either, because there are still twenty notifications. + expect(component.pageIndex).toBe(0); + expect(rows()).toHaveLength(20); + }); + + it('shows the empty state once the last one is deleted', () => { + const refresh = reloadWith(); + refresh.next([notification(1)]); + fixture.detectChanges(); + + deleteButtons()[0].click(); + confirmed(); + fixture.detectChanges(); + + expect(pageText()).toContain('You have no notifications yet'); + expect(alerts.success).toHaveBeenCalledTimes(1); + }); + + it('drops a list read still in flight when everything is marked read', () => { + const refresh = reloadWith(); + expect(refresh.observed).toBe(true); + + markAllButton().click(); + + // That response was worked out before the click, and NotificationService + // writes list responses into the shared entity cache, so letting it land + // would put readAt back to null on every row. + expect(refresh.observed).toBe(false); + }); + + it('drops a list read still in flight when one is deleted', () => { + // Driven through the component rather than the dom, and that is worth a + // word. A reload replaces the rows with the spinner, so while one is in + // flight there is no delete button on screen to click, and the sequence + // this guards cannot be produced by clicking today. It is reachable the + // moment anything reloads this page on a timer or a navigation, which is + // what the bell already does to the count, and the response is written + // into a cache the whole app shares. Cheap guard, real hazard. + component.confirmDelete(component.visible[0]); + const refresh = reloadWith(); + expect(refresh.observed).toBe(true); + + confirmed(); + + // Worse here than for a mark read. That response still holds the row that + // was just deleted, so landing late would put it back on screen. + expect(refresh.observed).toBe(false); + }); + + it('does not leave a spinner over the list when a reload is abandoned', () => { + reloadWith(); + expect(pageText()).toContain('Loading your notifications'); + + markAllButton().click(); + fixture.detectChanges(); + + // Cancelling the request without clearing the flag sits a spinner over a + // list that nothing is going to replace now. + expect(pageText()).not.toContain('Loading your notifications'); + expect(rows()).toHaveLength(2); + }); + }); + describe('before anyone is signed in', () => { it('asks nothing of the api until authentication has settled', () => { let resume: (signedIn: boolean) => void; diff --git a/src/app/common/notifications-page/notifications-page.component.ts b/src/app/common/notifications-page/notifications-page.component.ts index 24fce244b1..da71e08634 100644 --- a/src/app/common/notifications-page/notifications-page.component.ts +++ b/src/app/common/notifications-page/notifications-page.component.ts @@ -7,6 +7,7 @@ import {Notification} from 'src/app/api/models/notification'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {NotificationService} from 'src/app/api/services/notification.service'; import {AlertService} from 'src/app/common/services/alert.service'; +import {ConfirmationModalService} from '../modals/confirmation-modal/confirmation-modal.service'; /** * The whole notification list, on a page of its own. @@ -73,10 +74,31 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { constructor( private notificationService: NotificationService, private authenticationService: AuthenticationService, + private confirmationModal: ConfirmationModalService, private alerts: AlertService, private router: Router, ) {} + /** + * Whether the mark all read button has anything to do. + * + * Worked out from the rows this page is holding, and deliberately not from + * NotificationService.unreadCount$. That subject seeds at zero and only moves + * when somebody calls refreshUnreadCount(), and the only thing in the app that + * calls it on a schedule is the bell, which the header does not render below + * xs. Reading it here would hide this button on a phone, which is the one size + * where this page is the only way to the notifications at all. + * + * A getter rather than a field kept in step by hand. It has to answer after a + * mark all read, after a delete, after a row is opened and after a reload, and + * a boolean that four call sites have to remember to update is a boolean that + * will eventually be wrong. Nothing is allocated, so unlike the visible slice + * this is safe to recompute on every change detection pass. + */ + get hasUnread(): boolean { + return this.notifications.some((notification) => !notification.isRead); + } + /** * Wait for authentication before asking the api for anything. * @@ -155,8 +177,7 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { // A read that went out before this click is out of date now, and // NotificationService writes list responses into the shared entity cache, // so one landing late would put readAt back to null. - this.listSubscription?.unsubscribe(); - this.listSubscription = null; + this.cancelPendingList(); this.notificationService.markRead(notification).subscribe({ error: () => this.alerts.error('That notification could not be marked as read'), @@ -168,6 +189,56 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { } } + /** + * Mark the lot as read. + * + * Every one of them and not only the page on screen. read_all is the endpoint + * and it takes no arguments, and a button labelled "mark all read" that left + * pages two onwards unread would be lying about what it did. + * + * No confirmation. Nothing is lost by it and every notification is still here + * to read afterwards, so a dialog would only be a step to click through. + * Delete is the one that asks. + * + * The rows redraw without anything here touching them. NotificationService + * writes readAt onto the entities in its cache, and the rows this page is + * holding came out of that same cache, so they are the same objects. Setting + * readAt again here would be a second copy of that arithmetic that could only + * ever come to disagree with it. + */ + markAllRead(): void { + // A list read raised before this is out of date now, and its response goes + // straight into the shared cache, so landing late would draw every row + // unread again. + this.cancelPendingList(); + + this.notificationService.markAllRead().subscribe({ + error: () => this.alerts.error('Your notifications could not be marked as read'), + }); + } + + /** + * Ask first, then delete. + * + * Delete is the only one of the five endpoints that destroys anything and + * there is no undo anywhere in this feature, so it gets the dialog the house + * already has rather than a new one. + * + * The empty cancel function is deliberate. ConfirmationModalService pops a + * green success snackbar reading " action cancelled" when none is + * given, and telling somebody they successfully did not delete something is + * noise. + */ + confirmDelete(notification: Notification): void { + this.confirmationModal.show( + 'Delete notification', + 'This removes the notification. You will not be able to get it back.', + () => this.remove(notification), + () => undefined, + 'Delete', + ); + } + iconFor(notification: Notification): string { return this.categoryFor(notification).icon; } @@ -189,6 +260,19 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { return `${state}. ${notification.message}. ${this.timeAgo(notification)}`; } + /** + * What a screen reader should call a delete button. + * + * The message and not a bare "Delete notification". A page of twenty rows has + * twenty of these buttons, and identical labels leave somebody tabbing through + * them hearing the same three words over and over with nothing to tell them + * apart. The dropdown gets away with the generic wording because it shows five + * rows at most and the delete sits beside the row you just heard. + */ + deleteLabel(notification: Notification): string { + return `Delete: ${notification.message}`; + } + timeAgo(notification: Notification): string { return moment(notification.createdAt).fromNow(); } @@ -200,6 +284,52 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { ); } + /** + * Retire a list request that is still in the air. + * + * Anything changed from this page is newer than a read that went out before + * it. NotificationService writes list responses into the shared cache, so one + * arriving late does not merely show stale rows, it undoes the change. + * + * loading is cleared with it. A reload that has been abandoned is not still + * loading, and leaving the flag set would sit a spinner over the list nobody + * is going to replace now. + */ + private cancelPendingList(): void { + this.listSubscription?.unsubscribe(); + this.listSubscription = null; + this.loading = false; + } + + /** + * Delete it for real, once the dialog has been agreed to. + * + * The row is dropped from the held list on success rather than by reading the + * list again. A second GET for something already known would leave the row on + * screen for a round trip after the user asked for it to go. + * + * On failure the row stays exactly where it is. Removing it first and putting + * it back would read as the delete having worked and then being undone by + * something, which is a worse story than it not having worked. + */ + private remove(notification: Notification): void { + this.cancelPendingList(); + + this.notificationService.remove(notification).subscribe({ + next: () => { + this.notifications = this.notifications.filter((row) => row !== notification); + + // Deleting the only row on the last page leaves the reader on a page + // that no longer exists, staring at nothing while the paginator insists + // there are three of them. Same clamp as a reload does. + this.pageIndex = Math.min(this.pageIndex, this.lastPageIndex()); + this.updateVisible(); + this.alerts.success('Notification deleted'); + }, + error: () => this.alerts.error('That notification could not be deleted'), + }); + } + private updateVisible(): void { const start = this.pageIndex * this.pageSize; this.visible = this.notifications.slice(start, start + this.pageSize); From ff412d4fecbd7c88015f3de4cf3cfe7c9360e4d3 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Thu, 20 Aug 2026 22:45:45 +1000 Subject: [PATCH 1377/1531] feat(push): route notification clicks safely --- .../services/notification-route.service.ts | 82 ++++++++++ .../push-notification-click.service.ts | 67 ++++++++ .../spec/notification-route.service.spec.ts | 154 ++++++++++++++++++ .../push-notification-click.service.spec.ts | 131 +++++++++++++++ src/app/app.component.spec.ts | 33 ++++ src/app/app.component.ts | 4 + .../notification-bell.component.spec.ts | 10 +- .../notification-bell.component.ts | 6 +- .../notifications-page.component.spec.ts | 10 +- .../notifications-page.component.ts | 6 +- 10 files changed, 491 insertions(+), 12 deletions(-) create mode 100644 src/app/api/services/notification-route.service.ts create mode 100644 src/app/api/services/push-notification-click.service.ts create mode 100644 src/app/api/services/spec/notification-route.service.spec.ts create mode 100644 src/app/api/services/spec/push-notification-click.service.spec.ts create mode 100644 src/app/app.component.spec.ts diff --git a/src/app/api/services/notification-route.service.ts b/src/app/api/services/notification-route.service.ts new file mode 100644 index 0000000000..57a67aed89 --- /dev/null +++ b/src/app/api/services/notification-route.service.ts @@ -0,0 +1,82 @@ +// MN-C03: one security boundary for every notification destination. +import {Injectable} from '@angular/core'; +import {Router} from '@angular/router'; + +export const NOTIFICATION_ROUTE_FALLBACK = '/notifications'; + +const MAX_NOTIFICATION_ROUTE_LENGTH = 256; +const CONTROL_CHARACTER_MAX = 0x1f; +const DELETE_CHARACTER = 0x7f; +const FORBIDDEN_ROUTE_TEXT = /[\s\\?#%]/; +const PROJECT_ROOT_ROUTE = /^\/projects\/[1-9]\d*\/(?:dashboard|groups)$/; +const PROJECT_TASK_ROUTE = /^\/projects\/[1-9]\d*\/dashboard\/([A-Za-z0-9][A-Za-z0-9._-]{0,31})$/; +const EXPECTED_TASK_ABBREVIATION = + /^(?=.{1,32}$)(?=.*\d)(?=.*(?:\.|[A-Z]))(?:HD|P|C|D|T)?\d+(?:\.\d+)*(?:HD|P|C|D|T)?$/; +const SENSITIVE_TASK_TEXT = /(feedback|token|mark|grade|student|learner|name|comment)/i; + +function hasControlCharacters(value: string): boolean { + return Array.from(value).some((character) => { + const characterCode = character.charCodeAt(0); + return characterCode <= CONTROL_CHARACTER_MAX || characterCode === DELETE_CHARACTER; + }); +} + +@Injectable({providedIn: 'root'}) +export class NotificationRouteService { + constructor(private router: Router) {} + + public resolve(link: unknown): string { + if (typeof link !== 'string') { + return NOTIFICATION_ROUTE_FALLBACK; + } + if (link.length === 0 || link.length > MAX_NOTIFICATION_ROUTE_LENGTH) { + return NOTIFICATION_ROUTE_FALLBACK; + } + if (link !== link.trim()) { + return NOTIFICATION_ROUTE_FALLBACK; + } + if (!link.startsWith('/') || link.startsWith('//')) { + return NOTIFICATION_ROUTE_FALLBACK; + } + if (hasControlCharacters(link) || FORBIDDEN_ROUTE_TEXT.test(link)) { + return NOTIFICATION_ROUTE_FALLBACK; + } + + if (link === NOTIFICATION_ROUTE_FALLBACK || PROJECT_ROOT_ROUTE.test(link)) { + return link; + } + + const taskMatch = PROJECT_TASK_ROUTE.exec(link); + if (!taskMatch) { + return NOTIFICATION_ROUTE_FALLBACK; + } + + const taskAbbreviation = taskMatch[1]; + if ( + !EXPECTED_TASK_ABBREVIATION.test(taskAbbreviation) || + SENSITIVE_TASK_TEXT.test(taskAbbreviation) + ) { + return NOTIFICATION_ROUTE_FALLBACK; + } + + return link; + } + + public navigate(link: unknown): Promise<boolean> { + const target = this.resolve(link); + if (this.currentPath() === target) { + return Promise.resolve(true); + } + return this.router.navigateByUrl(target); + } + + private currentPath(): string { + const routerUrl = typeof this.router.url === 'string' ? this.router.url : '/'; + const withoutFragment = routerUrl.split('#', 1)[0]; + const withoutQuery = withoutFragment.split('?', 1)[0]; + if (!withoutQuery) { + return '/'; + } + return withoutQuery.length > 1 ? withoutQuery.replace(/\/+$/, '') : withoutQuery; + } +} diff --git a/src/app/api/services/push-notification-click.service.ts b/src/app/api/services/push-notification-click.service.ts new file mode 100644 index 0000000000..539c968927 --- /dev/null +++ b/src/app/api/services/push-notification-click.service.ts @@ -0,0 +1,67 @@ +// MN-C03: receive Angular service-worker clicks in an already-open client. +import {DOCUMENT} from '@angular/common'; +import {Inject, Injectable} from '@angular/core'; +import {SwPush} from '@angular/service-worker'; +import {Subscription} from 'rxjs'; +import {NotificationRouteService} from './notification-route.service'; + +interface NotificationClickData { + notification_id?: unknown; + link?: unknown; +} + +@Injectable({providedIn: 'root'}) +export class PushNotificationClickService { + private static readonly DUPLICATE_WINDOW_MS = 2000; + + private clickSubscription: Subscription | null = null; + private lastClickKey: string | null = null; + private lastClickAt = 0; + + constructor( + private swPush: SwPush, + private notificationRoutes: NotificationRouteService, + @Inject(DOCUMENT) private appDocument: Document, + ) {} + + public start(): void { + if (this.clickSubscription) { + return; + } + + this.clickSubscription = this.swPush.notificationClicks.subscribe((event) => { + // Angular focuses the most recently focused client before broadcasting the + // click. Only that focused document should navigate when several tabs exist. + if (!this.appDocument.hasFocus()) { + return; + } + + const data = event.notification.data as NotificationClickData | null | undefined; + const target = this.notificationRoutes.resolve(data?.link); + const clickKey = `${this.normalisedId(data?.notification_id)}:${target}`; + const now = Date.now(); + + if ( + clickKey === this.lastClickKey && + now - this.lastClickAt < PushNotificationClickService.DUPLICATE_WINDOW_MS + ) { + return; + } + + this.lastClickKey = clickKey; + this.lastClickAt = now; + void this.notificationRoutes.navigate(target); + }); + } + + public stop(): void { + this.clickSubscription?.unsubscribe(); + this.clickSubscription = null; + this.lastClickKey = null; + this.lastClickAt = 0; + } + + private normalisedId(value: unknown): string { + return typeof value === 'number' || typeof value === 'string' ? String(value) : 'no-id'; + } +} diff --git a/src/app/api/services/spec/notification-route.service.spec.ts b/src/app/api/services/spec/notification-route.service.spec.ts new file mode 100644 index 0000000000..4c9fb1f9b2 --- /dev/null +++ b/src/app/api/services/spec/notification-route.service.spec.ts @@ -0,0 +1,154 @@ +// MN-C03 targeted route-boundary tests. +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {Router} from '@angular/router'; +import {NOTIFICATION_ROUTE_FALLBACK, NotificationRouteService} from '../notification-route.service'; + +describe('NotificationRouteService', () => { + let router: {url: string; navigateByUrl: ReturnType<typeof vi.fn>}; + let service: NotificationRouteService; + + beforeEach(() => { + router = { + url: '/home', + navigateByUrl: vi.fn().mockResolvedValue(true), + }; + service = new NotificationRouteService(router as unknown as Router); + }); + + it('accepts each approved notification route family', () => { + const approved = [ + '/notifications', + '/projects/1/dashboard', + '/projects/23/groups', + '/projects/23/dashboard/1.1P', + '/projects/23/dashboard/T1.1', + '/projects/23/dashboard/HD1.2', + ]; + + for (const route of approved) { + expect(service.resolve(route)).toBe(route); + } + }); + + it('uses the safe fallback for missing and malformed values', () => { + const invalid: unknown[] = [ + undefined, + null, + 42, + {}, + '', + ' ', + ' /projects/1/dashboard', + '/projects/1/dashboard ', + '/projects/0/dashboard', + '/projects/-1/dashboard', + '/projects/1//dashboard', + '/projects/1/dashboard/', + '/projects/1/dashboard/1.1P/extra', + '/projects/1/dashboard/line\nbreak', + ]; + + for (const value of invalid) { + expect(service.resolve(value)).toBe(NOTIFICATION_ROUTE_FALLBACK); + } + }); + + it('rejects absolute, external, scheme and protocol-relative destinations', () => { + const invalid = [ + 'http://example.test/projects/1/dashboard', + 'https://example.test/projects/1/dashboard', + 'mailto:student@example.test', + 'javascript:alert(1)', + 'data:text/html,unsafe', + 'file:///etc/passwd', + '//example.test/projects/1/dashboard', + '\\example.test\\projects\\1', + '/\\example.test/projects/1', + '/projects\\1\\dashboard', + ]; + + for (const value of invalid) { + expect(service.resolve(value)).toBe(NOTIFICATION_ROUTE_FALLBACK); + } + }); + + it('rejects encoded bypass attempts rather than decoding them', () => { + const invalid = [ + '/%2f%2fexample.test', + '/%5cexample.test', + '/projects/1/dashboard/%31.1P', + '/projects/1/dashboard/1.1P%3ftoken%3dsecret', + '/projects/1/dashboard/1.1P%23feedback', + '/%252f%252fexample.test', + '/projects/1/dashboard/%00', + '/projects/1/dashboard/%', + ]; + + for (const value of invalid) { + expect(service.resolve(value)).toBe(NOTIFICATION_ROUTE_FALLBACK); + } + }); + + it('rejects unexpected route families, queries and fragments', () => { + const invalid = [ + '/home', + '/units/1', + '/projects/1', + '/projects/1/portfolio', + '/projects/1/dashboard/1.1P?token=secret', + '/projects/1/dashboard/1.1P#feedback', + '/notifications?student=Alice', + ]; + + for (const value of invalid) { + expect(service.resolve(value)).toBe(NOTIFICATION_ROUTE_FALLBACK); + } + }); + + it('rejects route segments shaped like marks, names, feedback or tokens', () => { + const invalid = [ + '/projects/1/dashboard/85', + '/projects/1/dashboard/Alice1', + '/projects/1/dashboard/BOB1', + '/projects/1/dashboard/1.1ALICE', + '/projects/1/dashboard/1.1BOB', + '/projects/1/dashboard/feedback1', + '/projects/1/dashboard/token123', + '/projects/1/dashboard/mark85', + `/projects/1/dashboard/${'A1'.repeat(20)}`, + ]; + + for (const value of invalid) { + expect(service.resolve(value)).toBe(NOTIFICATION_ROUTE_FALLBACK); + } + }); + + it('navigates an open app through Angular Router', async () => { + await expect(service.navigate('/projects/23/dashboard/1.1P')).resolves.toBe(true); + + expect(router.navigateByUrl).toHaveBeenCalledOnce(); + expect(router.navigateByUrl).toHaveBeenCalledWith('/projects/23/dashboard/1.1P'); + }); + + it('navigates unsafe input to the safe fallback', async () => { + await service.navigate('https://example.test/steal'); + + expect(router.navigateByUrl).toHaveBeenCalledWith(NOTIFICATION_ROUTE_FALLBACK); + }); + + it('does not navigate twice when a closed-app launch already opened the target', async () => { + router.url = '/projects/23/dashboard/1.1P?from=service-worker#top'; + + await expect(service.navigate('/projects/23/dashboard/1.1P')).resolves.toBe(true); + + expect(router.navigateByUrl).not.toHaveBeenCalled(); + }); + + it('does not re-navigate the fallback when notifications is already open', async () => { + router.url = '/notifications'; + + await service.navigate(undefined); + + expect(router.navigateByUrl).not.toHaveBeenCalled(); + }); +}); diff --git a/src/app/api/services/spec/push-notification-click.service.spec.ts b/src/app/api/services/spec/push-notification-click.service.spec.ts new file mode 100644 index 0000000000..19a94a8db7 --- /dev/null +++ b/src/app/api/services/spec/push-notification-click.service.spec.ts @@ -0,0 +1,131 @@ +// MN-C03 targeted SwPush click tests. +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {SwPush} from '@angular/service-worker'; +import {Subject} from 'rxjs'; +import {NOTIFICATION_ROUTE_FALLBACK, NotificationRouteService} from '../notification-route.service'; +import {PushNotificationClickService} from '../push-notification-click.service'; + +describe('PushNotificationClickService', () => { + let notificationClicks: Subject<unknown>; + let notificationRoutes: { + resolve: ReturnType<typeof vi.fn>; + navigate: ReturnType<typeof vi.fn>; + }; + let appDocument: {hasFocus: ReturnType<typeof vi.fn>}; + let service: PushNotificationClickService; + + beforeEach(() => { + notificationClicks = new Subject<unknown>(); + notificationRoutes = { + resolve: vi.fn((link: unknown) => + typeof link === 'string' && link.startsWith('/projects/') + ? link + : NOTIFICATION_ROUTE_FALLBACK, + ), + navigate: vi.fn().mockResolvedValue(true), + }; + appDocument = {hasFocus: vi.fn().mockReturnValue(true)}; + const swPush = { + notificationClicks: notificationClicks.asObservable(), + } as unknown as SwPush; + + service = new PushNotificationClickService( + swPush, + notificationRoutes as unknown as NotificationRouteService, + appDocument as unknown as Document, + ); + }); + + it('routes an open-app click through the shared boundary', () => { + service.start(); + + notificationClicks.next({ + notification: { + data: {notification_id: 42, link: '/projects/7/dashboard/1.1P'}, + }, + }); + + expect(notificationRoutes.resolve).toHaveBeenCalledWith('/projects/7/dashboard/1.1P'); + expect(notificationRoutes.navigate).toHaveBeenCalledWith('/projects/7/dashboard/1.1P'); + }); + + it('uses the shared fallback for a missing link', () => { + service.start(); + + notificationClicks.next({notification: {data: {notification_id: 43}}}); + + expect(notificationRoutes.resolve).toHaveBeenCalledWith(undefined); + expect(notificationRoutes.navigate).toHaveBeenCalledWith(NOTIFICATION_ROUTE_FALLBACK); + }); + + it('uses the shared fallback for an unsafe link', () => { + service.start(); + + notificationClicks.next({ + notification: { + data: {notification_id: 44, link: 'https://example.test/unsafe'}, + }, + }); + + expect(notificationRoutes.resolve).toHaveBeenCalledWith('https://example.test/unsafe'); + expect(notificationRoutes.navigate).toHaveBeenCalledWith(NOTIFICATION_ROUTE_FALLBACK); + }); + + it('does not navigate a background tab when another client was focused', () => { + appDocument.hasFocus.mockReturnValue(false); + service.start(); + + notificationClicks.next({ + notification: {data: {notification_id: 45, link: '/projects/7/groups'}}, + }); + + expect(notificationRoutes.navigate).not.toHaveBeenCalled(); + }); + + it('subscribes only once when startup calls start more than once', () => { + service.start(); + service.start(); + + notificationClicks.next({ + notification: {data: {notification_id: 46, link: '/projects/7/groups'}}, + }); + + expect(notificationRoutes.navigate).toHaveBeenCalledOnce(); + }); + + it('suppresses a duplicate delivery of the same click event', () => { + service.start(); + const event = { + notification: {data: {notification_id: 47, link: '/projects/7/groups'}}, + }; + + notificationClicks.next(event); + notificationClicks.next(event); + + expect(notificationRoutes.navigate).toHaveBeenCalledOnce(); + }); + + it('does not suppress different notifications that share a route', () => { + service.start(); + + notificationClicks.next({ + notification: {data: {notification_id: 48, link: '/projects/7/groups'}}, + }); + notificationClicks.next({ + notification: {data: {notification_id: 49, link: '/projects/7/groups'}}, + }); + + expect(notificationRoutes.navigate).toHaveBeenCalledTimes(2); + }); + + it('stops receiving clicks after teardown', () => { + service.start(); + service.stop(); + + notificationClicks.next({ + notification: {data: {notification_id: 50, link: '/projects/7/groups'}}, + }); + + expect(notificationRoutes.navigate).not.toHaveBeenCalled(); + }); +}); diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts new file mode 100644 index 0000000000..2f03f0aab6 --- /dev/null +++ b/src/app/app.component.spec.ts @@ -0,0 +1,33 @@ +// MN-C03 targeted startup and teardown test. +import {describe, expect, it, vi} from 'vitest'; +import {Renderer2} from '@angular/core'; +import {Router} from '@angular/router'; +import {Subject} from 'rxjs'; +import {PushNotificationClickService} from 'src/app/api/services/push-notification-click.service'; +import {AppComponent} from './app.component'; + +describe('AppComponent notification-click lifecycle', () => { + it('starts click routing at app startup and stops it at teardown', () => { + const events: Subject<unknown> = new Subject(); + const router = { + url: '/home', + events: events.asObservable(), + } as unknown as Router; + const renderer = { + setStyle: vi.fn(), + } as unknown as Renderer2; + const clickRouting = { + start: vi.fn(), + stop: vi.fn(), + } as unknown as PushNotificationClickService; + + const component = new AppComponent(router, renderer, clickRouting); + component.ngOnInit(); + + expect(clickRouting.start).toHaveBeenCalledOnce(); + + component.ngOnDestroy(); + + expect(clickRouting.stop).toHaveBeenCalledOnce(); + }); +}); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index b5d35f7f32..6cf98f030f 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,6 +1,7 @@ import {ChangeDetectionStrategy, Component, OnDestroy, OnInit, Renderer2} from '@angular/core'; import {NavigationEnd, Router} from '@angular/router'; import {Subscription, filter} from 'rxjs'; +import {PushNotificationClickService} from 'src/app/api/services/push-notification-click.service'; @Component({ selector: 'app-root', @@ -14,9 +15,11 @@ export class AppComponent implements OnInit, OnDestroy { constructor( private router: Router, private renderer: Renderer2, + private pushNotificationClicks: PushNotificationClickService, ) {} ngOnInit(): void { + this.pushNotificationClicks.start(); this.setBodyBackground(this.router.url); this.routerSub = this.router.events .pipe(filter((event) => event instanceof NavigationEnd)) @@ -24,6 +27,7 @@ export class AppComponent implements OnInit, OnDestroy { } ngOnDestroy(): void { + this.pushNotificationClicks.stop(); this.routerSub?.unsubscribe(); } diff --git a/src/app/common/header/notification-bell/notification-bell.component.spec.ts b/src/app/common/header/notification-bell/notification-bell.component.spec.ts index 9c96f4a585..b78ea13c22 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.spec.ts +++ b/src/app/common/header/notification-bell/notification-bell.component.spec.ts @@ -14,6 +14,7 @@ import {NavigationEnd, Router} from '@angular/router'; import {BehaviorSubject, Observable, Subject, config, defer, of, throwError} from 'rxjs'; import {Notification} from 'src/app/api/models/notification'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {NotificationRouteService} from 'src/app/api/services/notification-route.service'; import {NotificationService} from 'src/app/api/services/notification.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {ConfirmationModalService} from '../../modals/confirmation-modal/confirmation-modal.service'; @@ -58,6 +59,7 @@ describe('NotificationBellComponent', () => { let confirmationModal: {show: ReturnType<typeof vi.fn>}; let alerts: {success: ReturnType<typeof vi.fn>; error: ReturnType<typeof vi.fn>}; let router: {events: unknown; navigateByUrl: ReturnType<typeof vi.fn>}; + let notificationRoutes: {navigate: ReturnType<typeof vi.fn>}; /** * A stand-in that records whether anybody actually subscribed. @@ -162,6 +164,7 @@ describe('NotificationBellComponent', () => { confirmationModal = {show: vi.fn()}; alerts = {success: vi.fn(), error: vi.fn()}; router = {events: routerEvents.asObservable(), navigateByUrl: vi.fn()}; + notificationRoutes = {navigate: vi.fn().mockResolvedValue(true)}; await TestBed.configureTestingModule({ declarations: [NotificationBellComponent], @@ -181,6 +184,7 @@ describe('NotificationBellComponent', () => { {provide: ConfirmationModalService, useValue: confirmationModal}, {provide: AlertService, useValue: alerts}, {provide: Router, useValue: router}, + {provide: NotificationRouteService, useValue: notificationRoutes}, ], }).compileComponents(); @@ -533,7 +537,7 @@ describe('NotificationBellComponent', () => { expect(notificationService.markRead).toHaveBeenCalledTimes(1); expect(notificationService.markRead.mock.calls[0][0].id).toBe(1); expect(subscribedTo.has('markRead')).toBe(true); - expect(router.navigateByUrl).toHaveBeenCalledWith('/projects/9/dashboard'); + expect(notificationRoutes.navigate).toHaveBeenCalledWith('/projects/9/dashboard'); }); it('does not mark a row read twice', () => { @@ -547,7 +551,7 @@ describe('NotificationBellComponent', () => { // so a second call would do nothing except tell the service to take one // off a count that never included it. expect(notificationService.markRead).not.toHaveBeenCalled(); - expect(router.navigateByUrl).toHaveBeenCalledTimes(1); + expect(notificationRoutes.navigate).toHaveBeenCalledTimes(1); }); it('marks a row read even when it has nowhere to go', () => { @@ -560,7 +564,7 @@ describe('NotificationBellComponent', () => { // link is nullable on the api. Refusing to mark it read would leave a // number on the bell that the user has no way to clear. expect(notificationService.markRead).toHaveBeenCalledTimes(1); - expect(router.navigateByUrl).not.toHaveBeenCalled(); + expect(notificationRoutes.navigate).toHaveBeenCalledWith(null); }); it('says so when a notification could not be marked as read', () => { diff --git a/src/app/common/header/notification-bell/notification-bell.component.ts b/src/app/common/header/notification-bell/notification-bell.component.ts index d8543f848e..3401842586 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.ts +++ b/src/app/common/header/notification-bell/notification-bell.component.ts @@ -4,6 +4,7 @@ import {NavigationEnd, Router} from '@angular/router'; import {Subscription, filter} from 'rxjs'; import {Notification} from 'src/app/api/models/notification'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {NotificationRouteService} from 'src/app/api/services/notification-route.service'; import {NotificationService} from 'src/app/api/services/notification.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {ConfirmationModalService} from '../../modals/confirmation-modal/confirmation-modal.service'; @@ -105,6 +106,7 @@ export class NotificationBellComponent implements OnInit, OnDestroy { private confirmationModal: ConfirmationModalService, private alerts: AlertService, private router: Router, + private notificationRoutes: NotificationRouteService, ) {} ngOnInit(): void { @@ -216,9 +218,7 @@ export class NotificationBellComponent implements OnInit, OnDestroy { }); } - if (notification.link) { - this.router.navigateByUrl(notification.link); - } + void this.notificationRoutes.navigate(notification.link); } /** diff --git a/src/app/common/notifications-page/notifications-page.component.spec.ts b/src/app/common/notifications-page/notifications-page.component.spec.ts index bd2fcb0dac..c70877b145 100644 --- a/src/app/common/notifications-page/notifications-page.component.spec.ts +++ b/src/app/common/notifications-page/notifications-page.component.spec.ts @@ -11,6 +11,7 @@ import {Router} from '@angular/router'; import {Observable, Subject, defer, of, throwError} from 'rxjs'; import {Notification} from 'src/app/api/models/notification'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {NotificationRouteService} from 'src/app/api/services/notification-route.service'; import {NotificationService} from 'src/app/api/services/notification.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {NotificationsPageComponent} from './notifications-page.component'; @@ -40,6 +41,7 @@ describe('NotificationsPageComponent', () => { let authenticationService: {afterAuthCall: ReturnType<typeof vi.fn>}; let alerts: {success: ReturnType<typeof vi.fn>; error: ReturnType<typeof vi.fn>}; let router: {navigateByUrl: ReturnType<typeof vi.fn>}; + let notificationRoutes: {navigate: ReturnType<typeof vi.fn>}; /** * A stand-in that records whether anybody actually subscribed. @@ -92,6 +94,7 @@ describe('NotificationsPageComponent', () => { authenticationService = {afterAuthCall: vi.fn((callback) => callback(true))}; alerts = {success: vi.fn(), error: vi.fn()}; router = {navigateByUrl: vi.fn()}; + notificationRoutes = {navigate: vi.fn().mockResolvedValue(true)}; await TestBed.configureTestingModule({ declarations: [NotificationsPageComponent], @@ -108,6 +111,7 @@ describe('NotificationsPageComponent', () => { {provide: AuthenticationService, useValue: authenticationService}, {provide: AlertService, useValue: alerts}, {provide: Router, useValue: router}, + {provide: NotificationRouteService, useValue: notificationRoutes}, ], }).compileComponents(); @@ -323,7 +327,7 @@ describe('NotificationsPageComponent', () => { expect(notificationService.markRead).toHaveBeenCalledTimes(1); expect(notificationService.markRead.mock.calls[0][0].id).toBe(1); expect(subscribedTo.has('markRead')).toBe(true); - expect(router.navigateByUrl).toHaveBeenCalledWith('/projects/9/dashboard'); + expect(notificationRoutes.navigate).toHaveBeenCalledWith('/projects/9/dashboard'); }); it('does not mark a row read twice', () => { @@ -334,7 +338,7 @@ describe('NotificationsPageComponent', () => { rows()[0].click(); expect(notificationService.markRead).not.toHaveBeenCalled(); - expect(router.navigateByUrl).toHaveBeenCalledTimes(1); + expect(notificationRoutes.navigate).toHaveBeenCalledTimes(1); }); it('marks a row read even when it has nowhere to go', () => { @@ -347,7 +351,7 @@ describe('NotificationsPageComponent', () => { // link is nullable on the api. Refusing to mark it read would leave a // number on the bell that the user has no way to clear. expect(notificationService.markRead).toHaveBeenCalledTimes(1); - expect(router.navigateByUrl).not.toHaveBeenCalled(); + expect(notificationRoutes.navigate).toHaveBeenCalledWith(null); }); it('says so when a notification could not be marked as read', () => { diff --git a/src/app/common/notifications-page/notifications-page.component.ts b/src/app/common/notifications-page/notifications-page.component.ts index 24fce244b1..06fa56cfc3 100644 --- a/src/app/common/notifications-page/notifications-page.component.ts +++ b/src/app/common/notifications-page/notifications-page.component.ts @@ -5,6 +5,7 @@ import {Router} from '@angular/router'; import {Subscription} from 'rxjs'; import {Notification} from 'src/app/api/models/notification'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; +import {NotificationRouteService} from 'src/app/api/services/notification-route.service'; import {NotificationService} from 'src/app/api/services/notification.service'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -75,6 +76,7 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { private authenticationService: AuthenticationService, private alerts: AlertService, private router: Router, + private notificationRoutes: NotificationRouteService, ) {} /** @@ -163,9 +165,7 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { }); } - if (notification.link) { - this.router.navigateByUrl(notification.link); - } + void this.notificationRoutes.navigate(notification.link); } iconFor(notification: Notification): string { From 4677b61f8211f92b0f3da56fa1a5c47788df0143 Mon Sep 17 00:00:00 2001 From: Maple 'Ryan' Fox <s223932052@deakin.edu.au> Date: Fri, 21 Aug 2026 01:26:31 +1000 Subject: [PATCH 1378/1531] docs: add privacy-safe screenshot checklist for Cross-Project Dashboard (CPD-Q06) * docs: add privacy-safe screenshot checklist for Cross-Project Dashboard (CPD-Q06) (cherry picked from commit df15f62bf2ca02465845c96d4bb5be15901ca0a5) * docs: strengthen screenshot redaction guidance (CPD-Q06) --------- Co-authored-by: jmirchh75 <jmirch@live.com> --- ...D-Q06-privacy-safe-screenshot-checklist.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 docs/CPD-Q06-privacy-safe-screenshot-checklist.md diff --git a/docs/CPD-Q06-privacy-safe-screenshot-checklist.md b/docs/CPD-Q06-privacy-safe-screenshot-checklist.md new file mode 100644 index 0000000000..cfa715104c --- /dev/null +++ b/docs/CPD-Q06-privacy-safe-screenshot-checklist.md @@ -0,0 +1,45 @@ +# Cross-Project Dashboard Privacy-Safe Screenshot Checklist + +Use this checklist before sharing a dashboard screenshot in a pull request, Teams message, +report, portfolio, presentation, or handover document. + +## Before sharing + +- [ ] Real student names have been removed or replaced with mock names. +- [ ] Student IDs and email addresses are not visible. +- [ ] Personal account details and profile images are not visible. +- [ ] Unit and project information does not reveal a student's private enrolment details. +- [ ] Task titles do not contain sensitive or personally identifying information. +- [ ] Marks, feedback text, and individual assessment results are removed, permanently + redacted in the final exported image, or replaced with mock data. +- [ ] Extension details and changed due dates do not reveal private student circumstances. +- [ ] Browser tabs, URLs, tokens, local file paths, and account information are cropped out or + permanently redacted in the final exported image. +- [ ] Mock or seeded data has been used wherever possible. +- [ ] The screenshot contains only the area needed to prove the result. +- [ ] The final exported screenshot has been reopened and checked at full size to confirm that + no sensitive data remains. +- [ ] The original unredacted screenshot is not committed to Git, attached to the pull request, + or posted in a shared project channel. + +## Safe example + +A screenshot of the dashboard populated entirely with seeded demo data. For example, students +named "Test Student 1" and "Test Student 2" with placeholder emails, generic task titles, and +sample marks that were never tied to a real person. The screenshot is cropped tightly to the +feature being demonstrated, with no browser chrome, URL bar, or login or account menu visible. + +## Information that must be removed + +A screenshot taken from a real unit that shows an actual student's name, ID, or email next to +their real mark, feedback comment, or an approved extension with a reason attached. This kind +of detail must be cropped out, permanently redacted in the final exported image, or replaced +with mock data before sharing. Do not rely on light blur or pixelation to protect sensitive +information. + +## Recommendation + +The safest default for future contributors is to demonstrate features using mock data rather +than real student or account data, even when it takes a little longer to set up. When redaction +is unavoidable, export a flattened copy, reopen that final file, and check it again before +sharing. From 446d1e10d9a43c0e1857c46660aa6146907a1787 Mon Sep 17 00:00:00 2001 From: Maple 'Ryan' Fox <s223932052@deakin.edu.au> Date: Fri, 21 Aug 2026 01:26:52 +1000 Subject: [PATCH 1379/1531] chore(ci): notify Teams when a pull request opens * Add GitHub Actions workflow to notify Teams on PRs * fix(ci): gate the Teams notifier and harden its payload Adds a job guard so the webhook is unreachable from anonymous fork pull requests on these public repositories, and so the file is inert if it ever travels to thoth-tech or doubtfire-lms. Adds reopened and ready_for_review, which is the transition a reviewer alert exists to catch, and varies the headline per action so it stays accurate. Strips Markdown link and code syntax from the title, author and head label before they reach the channel. Joins on a double newline, which is what Teams renders as a break. Reports the real HTTP status instead of asserting a delivery the workflow never checked. --------- Co-authored-by: Clupai8o0 <clupaio4@gmail.com> --- .github/workflows/notify-teams-pr.yml | 140 ++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 .github/workflows/notify-teams-pr.yml diff --git a/.github/workflows/notify-teams-pr.yml b/.github/workflows/notify-teams-pr.yml new file mode 100644 index 0000000000..507bd01c3d --- /dev/null +++ b/.github/workflows/notify-teams-pr.yml @@ -0,0 +1,140 @@ +# NOTE ON THE BASE BRANCH. GitHub loads a `pull_request_target` workflow from the +# repository DEFAULT branch (11.0.x), not from the pull request's base branch. That +# changed on 2025-12-08. So this file is merged into 11.0.x deliberately, against the +# usual CONTRIBUTING rule, and a copy on feature/notifications would be dead code. +# It fires for pull requests into every base branch, which is what we want. +name: Notify Teams when a pull request opens + +on: + pull_request_target: + types: + - opened + - reopened + - ready_for_review + # - review_requested # matches "reviewer alerts" most directly, but adds one + # # message per requested reviewer. Decide, do not default. + +# Removes all GITHUB_TOKEN scopes, which this workflow does not need. It does NOT +# restrict secrets.* - the webhook is protected by the job guard below, not by this. +permissions: {} + +jobs: + notify-teams: + name: Post pull request notification to Teams + # First clause makes the file inert if it ever travels to thoth-tech or + # doubtfire-lms. Second keeps the webhook out of reach of anonymous fork PRs + # while still notifying teammates who work from their own forks, which + # several doubtfire-web contributors do. + if: >- + github.repository_owner == 'ontrack-features-t2-2026' && + (github.event.pull_request.head.repo.full_name == github.repository || + contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.pull_request.author_association)) + runs-on: ubuntu-latest + timeout-minutes: 2 + + steps: + - name: Build and send Teams notification + shell: bash + env: + TEAMS_WEBHOOK_URL: ${{ secrets.TEAMS_PR_WEBHOOK_URL }} + PAYLOAD_PATH: ${{ runner.temp }}/teams-pr-notification.json + + REPOSITORY: ${{ github.repository }} + PR_ACTION: ${{ github.event.action }} + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_TITLE: ${{ github.event.pull_request.title }} + PR_AUTHOR: ${{ github.event.pull_request.user.login }} + PR_URL: ${{ github.event.pull_request.html_url }} + PR_DRAFT: ${{ github.event.pull_request.draft }} + PR_HEAD: ${{ github.event.pull_request.head.label }} + PR_BASE: ${{ github.event.pull_request.base.ref }} + + run: | + set -euo pipefail + + if [[ -z "${TEAMS_WEBHOOK_URL:-}" ]]; then + echo "::error::The TEAMS_PR_WEBHOOK_URL Actions secret is not configured." + exit 1 + fi + + python3 - <<'PY' + import json + import os + import re + + + def plain(value): + """Teams renders these fields as Markdown, and titles and branch names + come from anyone who can open a pull request. Removing [ ] < > and + backticks stops a title forging a Markdown link or code span. + Parentheses are left alone so `feat(scope): ...` still reads + properly. Note this does NOT stop Teams auto-linking a bare URL in + a title, it only stops the link TEXT being controlled.""" + value = " ".join(value.split()) + return re.sub(r"[\[\]<>`]", " ", value)[:200] + + + headline = { + "opened": "New pull request opened", + "reopened": "Pull request reopened", + "ready_for_review": "Pull request is ready for review", + }.get(os.environ["PR_ACTION"], "Pull request updated") + + status = ( + "Draft" + if os.environ.get("PR_DRAFT", "").lower() == "true" + else "Ready for review" + ) + + # Teams renders a break for "\n\n" and not for a single "\n". + text = "\n\n".join( + [ + headline, + f"Repository: {os.environ['REPOSITORY']}", + f"PR #{os.environ['PR_NUMBER']}: {plain(os.environ['PR_TITLE'])}", + f"Author: {plain(os.environ['PR_AUTHOR'])}", + f"Status: {status}", + f"Branches: {plain(os.environ['PR_HEAD'])} -> {os.environ['PR_BASE']}", + os.environ["PR_URL"], + ] + ) + + with open( + os.environ["PAYLOAD_PATH"], + "w", + encoding="utf-8", + ) as payload_file: + json.dump( + {"text": text}, + payload_file, + ensure_ascii=False, + ) + PY + + http_status="$( + curl \ + --proto '=https' \ + --tlsv1.2 \ + --silent \ + --show-error \ + --connect-timeout 10 \ + --max-time 30 \ + --header 'Content-Type: application/json' \ + --data-binary "@${PAYLOAD_PATH}" \ + --output "${RUNNER_TEMP}/teams-response.txt" \ + --write-out '%{http_code}' \ + --url "${TEAMS_WEBHOOK_URL}" + )" || http_status="000" + + # Uncomment to debug a failing webhook. The body comes from a third party + # and lands in a PUBLIC Actions log, and GitHub only masks an exact + # full-value match of a secret. Read it once, then comment it out again. + # cat "${RUNNER_TEMP}/teams-response.txt" + + if [[ "${http_status}" != 2* ]]; then + echo "::error::Teams webhook returned HTTP ${http_status}." + exit 1 + fi + + echo "Teams webhook returned HTTP ${http_status} for PR #${PR_NUMBER}." + echo "That means the request was accepted. It does not prove the message rendered in the channel." From fa3c6708ac05b6ce434f3f547226a36e55ad1b59 Mon Sep 17 00:00:00 2001 From: Maple 'Ryan' Fox <s223932052@deakin.edu.au> Date: Fri, 21 Aug 2026 11:34:04 +1000 Subject: [PATCH 1380/1531] Refactor Teams notification to use Adaptive Card --- .github/workflows/notify-teams-pr.yml | 75 ++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/.github/workflows/notify-teams-pr.yml b/.github/workflows/notify-teams-pr.yml index 507bd01c3d..5cf0be21f6 100644 --- a/.github/workflows/notify-teams-pr.yml +++ b/.github/workflows/notify-teams-pr.yml @@ -86,18 +86,67 @@ jobs: else "Ready for review" ) - # Teams renders a break for "\n\n" and not for a single "\n". - text = "\n\n".join( - [ - headline, - f"Repository: {os.environ['REPOSITORY']}", - f"PR #{os.environ['PR_NUMBER']}: {plain(os.environ['PR_TITLE'])}", - f"Author: {plain(os.environ['PR_AUTHOR'])}", - f"Status: {status}", - f"Branches: {plain(os.environ['PR_HEAD'])} -> {os.environ['PR_BASE']}", - os.environ["PR_URL"], - ] - ) + card = { + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "version": "1.2", + "body": [ + { + "type": "TextBlock", + "size": "Medium", + "weight": "Bolder", + "wrap": True, + "text": headline, + }, + { + "type": "TextBlock", + "wrap": True, + "text": f"PR #{os.environ['PR_NUMBER']}: {plain(os.environ['PR_TITLE'])}", + }, + { + "type": "FactSet", + "facts": [ + { + "title": "Repository", + "value": plain(os.environ["REPOSITORY"]), + }, + { + "title": "Author", + "value": plain(os.environ["PR_AUTHOR"]), + }, + { + "title": "Status", + "value": status, + }, + { + "title": "Branches", + "value": ( + f"{plain(os.environ['PR_HEAD'])} -> " + f"{plain(os.environ['PR_BASE'])}" + ), + }, + ], + }, + ], + "actions": [ + { + "type": "Action.OpenUrl", + "title": "Open pull request", + "url": os.environ["PR_URL"], + } + ], + } + + payload = { + "type": "message", + "attachments": [ + { + "contentType": "application/vnd.microsoft.card.adaptive", + "contentUrl": None, + "content": card, + } + ], + } with open( os.environ["PAYLOAD_PATH"], @@ -105,7 +154,7 @@ jobs: encoding="utf-8", ) as payload_file: json.dump( - {"text": text}, + payload, payload_file, ensure_ascii=False, ) From 732175876ac452368240005323a4403af6a2e088 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Fri, 21 Aug 2026 12:11:53 +1000 Subject: [PATCH 1381/1531] fix(push): accept bounded notification task routes --- .../api/services/notification-route.service.ts | 16 ++-------------- .../spec/notification-route.service.spec.ts | 16 +++++++++++----- .../notification-bell.component.spec.ts | 2 +- .../notification-bell.component.ts | 4 +++- .../notifications-page.component.spec.ts | 2 +- .../notifications-page.component.ts | 4 +++- 6 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/app/api/services/notification-route.service.ts b/src/app/api/services/notification-route.service.ts index 57a67aed89..607701f903 100644 --- a/src/app/api/services/notification-route.service.ts +++ b/src/app/api/services/notification-route.service.ts @@ -9,10 +9,7 @@ const CONTROL_CHARACTER_MAX = 0x1f; const DELETE_CHARACTER = 0x7f; const FORBIDDEN_ROUTE_TEXT = /[\s\\?#%]/; const PROJECT_ROOT_ROUTE = /^\/projects\/[1-9]\d*\/(?:dashboard|groups)$/; -const PROJECT_TASK_ROUTE = /^\/projects\/[1-9]\d*\/dashboard\/([A-Za-z0-9][A-Za-z0-9._-]{0,31})$/; -const EXPECTED_TASK_ABBREVIATION = - /^(?=.{1,32}$)(?=.*\d)(?=.*(?:\.|[A-Z]))(?:HD|P|C|D|T)?\d+(?:\.\d+)*(?:HD|P|C|D|T)?$/; -const SENSITIVE_TASK_TEXT = /(feedback|token|mark|grade|student|learner|name|comment)/i; +const PROJECT_TASK_ROUTE = /^\/projects\/[1-9]\d*\/dashboard\/[A-Za-z0-9][A-Za-z0-9._-]{0,31}$/; function hasControlCharacters(value: string): boolean { return Array.from(value).some((character) => { @@ -46,16 +43,7 @@ export class NotificationRouteService { return link; } - const taskMatch = PROJECT_TASK_ROUTE.exec(link); - if (!taskMatch) { - return NOTIFICATION_ROUTE_FALLBACK; - } - - const taskAbbreviation = taskMatch[1]; - if ( - !EXPECTED_TASK_ABBREVIATION.test(taskAbbreviation) || - SENSITIVE_TASK_TEXT.test(taskAbbreviation) - ) { + if (!PROJECT_TASK_ROUTE.test(link)) { return NOTIFICATION_ROUTE_FALLBACK; } diff --git a/src/app/api/services/spec/notification-route.service.spec.ts b/src/app/api/services/spec/notification-route.service.spec.ts index 4c9fb1f9b2..6c40ca8780 100644 --- a/src/app/api/services/spec/notification-route.service.spec.ts +++ b/src/app/api/services/spec/notification-route.service.spec.ts @@ -23,6 +23,12 @@ describe('NotificationRouteService', () => { '/projects/23/dashboard/1.1P', '/projects/23/dashboard/T1.1', '/projects/23/dashboard/HD1.2', + '/projects/23/dashboard/10.1H', + '/projects/23/dashboard/A15', + '/projects/23/dashboard/TASK1', + '/projects/23/dashboard/P-2.21', + '/projects/23/dashboard/D-9.568', + '/projects/23/dashboard/C-4.602', ]; for (const route of approved) { @@ -46,6 +52,7 @@ describe('NotificationRouteService', () => { '/projects/1/dashboard/', '/projects/1/dashboard/1.1P/extra', '/projects/1/dashboard/line\nbreak', + `/projects/1/dashboard/${'A1'.repeat(20)}`, ]; for (const value of invalid) { @@ -105,8 +112,8 @@ describe('NotificationRouteService', () => { } }); - it('rejects route segments shaped like marks, names, feedback or tokens', () => { - const invalid = [ + it('accepts bounded task segments without guessing their business format', () => { + const approved = [ '/projects/1/dashboard/85', '/projects/1/dashboard/Alice1', '/projects/1/dashboard/BOB1', @@ -115,11 +122,10 @@ describe('NotificationRouteService', () => { '/projects/1/dashboard/feedback1', '/projects/1/dashboard/token123', '/projects/1/dashboard/mark85', - `/projects/1/dashboard/${'A1'.repeat(20)}`, ]; - for (const value of invalid) { - expect(service.resolve(value)).toBe(NOTIFICATION_ROUTE_FALLBACK); + for (const route of approved) { + expect(service.resolve(route)).toBe(route); } }); diff --git a/src/app/common/header/notification-bell/notification-bell.component.spec.ts b/src/app/common/header/notification-bell/notification-bell.component.spec.ts index b78ea13c22..21cb040f50 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.spec.ts +++ b/src/app/common/header/notification-bell/notification-bell.component.spec.ts @@ -564,7 +564,7 @@ describe('NotificationBellComponent', () => { // link is nullable on the api. Refusing to mark it read would leave a // number on the bell that the user has no way to clear. expect(notificationService.markRead).toHaveBeenCalledTimes(1); - expect(notificationRoutes.navigate).toHaveBeenCalledWith(null); + expect(notificationRoutes.navigate).not.toHaveBeenCalled(); }); it('says so when a notification could not be marked as read', () => { diff --git a/src/app/common/header/notification-bell/notification-bell.component.ts b/src/app/common/header/notification-bell/notification-bell.component.ts index 3401842586..981c84baf9 100644 --- a/src/app/common/header/notification-bell/notification-bell.component.ts +++ b/src/app/common/header/notification-bell/notification-bell.component.ts @@ -218,7 +218,9 @@ export class NotificationBellComponent implements OnInit, OnDestroy { }); } - void this.notificationRoutes.navigate(notification.link); + if (notification.link) { + void this.notificationRoutes.navigate(notification.link); + } } /** diff --git a/src/app/common/notifications-page/notifications-page.component.spec.ts b/src/app/common/notifications-page/notifications-page.component.spec.ts index c70877b145..734286bc46 100644 --- a/src/app/common/notifications-page/notifications-page.component.spec.ts +++ b/src/app/common/notifications-page/notifications-page.component.spec.ts @@ -351,7 +351,7 @@ describe('NotificationsPageComponent', () => { // link is nullable on the api. Refusing to mark it read would leave a // number on the bell that the user has no way to clear. expect(notificationService.markRead).toHaveBeenCalledTimes(1); - expect(notificationRoutes.navigate).toHaveBeenCalledWith(null); + expect(notificationRoutes.navigate).not.toHaveBeenCalled(); }); it('says so when a notification could not be marked as read', () => { diff --git a/src/app/common/notifications-page/notifications-page.component.ts b/src/app/common/notifications-page/notifications-page.component.ts index 06fa56cfc3..bd71ee8839 100644 --- a/src/app/common/notifications-page/notifications-page.component.ts +++ b/src/app/common/notifications-page/notifications-page.component.ts @@ -165,7 +165,9 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { }); } - void this.notificationRoutes.navigate(notification.link); + if (notification.link) { + void this.notificationRoutes.navigate(notification.link); + } } iconFor(notification: Notification): string { From c1a6bc72d745c0454d573cd239d53936b59ee79d Mon Sep 17 00:00:00 2001 From: Thirus224849242 <s224849242@deakin.edu.au> Date: Sat, 22 Aug 2026 13:02:45 +1000 Subject: [PATCH 1382/1531] refactor: replace ng-flex-layout with Tailwind in task-comment-composer --- .../task-comment-composer.component.html | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/app/tasks/task-comment-composer/task-comment-composer.component.html b/src/app/tasks/task-comment-composer/task-comment-composer.component.html index 8455a0b330..13b19b5bda 100644 --- a/src/app/tasks/task-comment-composer/task-comment-composer.component.html +++ b/src/app/tasks/task-comment-composer/task-comment-composer.component.html @@ -51,9 +51,9 @@ > @for (emoji of emojiSearchResults; track emoji) { <mat-list-item (click)="emojiSelected(emoji.native)"> - <div fxLayout="row" fxLayoutAlign="start center"> + <div class="flex flex-row items-center justify-start"> <ngx-emoji set="apple" style="align-items: center" [emoji]="emoji" [size]="20"></ngx-emoji> - <div class="emoji-details" fxLayout="column" fxLayoutAlign="center start"> + <div class="emoji-details flex flex-col items-start justify-center"> <div style="font-weight: 500; font-size: 12px">{{ emoji.name }}</div> <div style="font-size: 10px">{{ emoji.colons }}</div> </div> @@ -77,10 +77,10 @@ (templateSelected)="addFeedback($event)" ></f-task-feedback-templates> } - <div class="composer-container" fxLayout="row" fxLayoutAlign="space-around center"> + <div class="composer-container flex flex-row items-center justify-around"> <div class="composer-action-group" [@shrinkgrow]="$userIsTyping | async"> <!-- if active --> - <div fxLayout="row" fxLayoutAlign="start center"> + <div class="flex flex-row items-center justify-start"> @if ($userIsTyping | async) { <button aria-label="Expand action buttons" @@ -96,20 +96,6 @@ </button> } - <!-- <button - [hidden]="shrinkGrowToggle" - *ngIf="isStaff" - matTooltip="Create a Real Talk discussion" - matTooltipShowDelay="400" - mat-icon-button - class="btn-no-outline" - type="button" - aria-label="launch real talk took" - (click)="openDiscussionComposer()" - > - <mat-icon>crisis_alert</mat-icon> - </button> --> - @if (isStaff) { @if (!isEditing) { <button From 76c68cd1bcacac37732d50aafaaa8d3c48664b9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Aug 2026 03:25:51 +0000 Subject: [PATCH 1383/1531] chore(deps): bump brace-expansion Bumps and [brace-expansion](https://github.com/juliangruber/brace-expansion). These dependencies needed to be updated together. Updates `brace-expansion` from 5.0.6 to 5.0.9 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.6...v5.0.9) Updates `brace-expansion` from 5.0.7 to 5.0.9 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.6...v5.0.9) Updates `brace-expansion` from 2.1.1 to 2.1.4 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.6...v5.0.9) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 5.0.9 dependency-type: indirect - dependency-name: brace-expansion dependency-version: 5.0.9 dependency-type: indirect - dependency-name: brace-expansion dependency-version: 2.1.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> --- package-lock.json | 70 +++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index c97d035b53..70cd595363 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3220,15 +3220,15 @@ } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/@eslint/config-array/node_modules/minimatch": { @@ -4593,16 +4593,16 @@ } }, "node_modules/@npmcli/package-json/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/@npmcli/package-json/node_modules/glob": { @@ -6323,16 +6323,16 @@ } }, "node_modules/@tufjs/models/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/@tufjs/models/node_modules/minimatch": { @@ -6885,15 +6885,15 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", - "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { @@ -7051,15 +7051,15 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { @@ -7784,9 +7784,9 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "dev": true, "license": "MIT", "dependencies": { @@ -7902,16 +7902,16 @@ } }, "node_modules/cacache/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/cacache/node_modules/glob": { @@ -9679,15 +9679,15 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/eslint/node_modules/escape-string-regexp": { @@ -10614,16 +10614,16 @@ } }, "node_modules/ignore-walk/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/ignore-walk/node_modules/minimatch": { From 73eabe9299d759917c7d5b65853df4cb4c3cdb1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Aug 2026 03:25:58 +0000 Subject: [PATCH 1384/1531] chore(deps): bump ip-address from 10.2.0 to 10.5.0 Bumps [ip-address](https://github.com/beaugunderson/ip-address) from 10.2.0 to 10.5.0. - [Release notes](https://github.com/beaugunderson/ip-address/releases) - [Commits](https://github.com/beaugunderson/ip-address/compare/v10.2.0...v10.5.0) --- updated-dependencies: - dependency-name: ip-address dependency-version: 10.5.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c97d035b53..d9f7c5679d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10724,9 +10724,9 @@ "license": "MIT" }, "node_modules/ip-address": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", - "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.5.0.tgz", + "integrity": "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==", "dev": true, "license": "MIT", "engines": { From fee75bc02a7c9a402059617d6e9798a1c558ec24 Mon Sep 17 00:00:00 2001 From: The Herald Sun <samuelryanmason@gmail.com> Date: Sat, 22 Aug 2026 04:36:56 +0000 Subject: [PATCH 1385/1531] feat(notifications): create install prompt --- src/app/doubtfire-angular.module.ts | 2 + .../install-prompt.service.spec.ts | 122 ++++++++++++++++++ .../install-prompt/install-prompt.service.ts | 79 ++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 src/app/sessions/install-prompt/install-prompt.service.spec.ts create mode 100644 src/app/sessions/install-prompt/install-prompt.service.ts diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 6c3c4080c4..9079fae1c0 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -298,6 +298,7 @@ import {TutorialsComponent} from './projects/states/tutorials/tutorials.componen // import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; // import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; import {CheckForUpdateService} from './sessions/service-worker-updater/check-for-update.service'; +import {InstallPromptService} from './sessions/install-prompt/install-prompt.service'; import {SignInComponent} from './sessions/states/sign-in/sign-in.component'; import {FeedbackAppealModalComponent} from './tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component'; import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; @@ -871,6 +872,7 @@ export class DoubtfireAngularModule { private constants: DoubtfireConstants, private title: Title, private updater: CheckForUpdateService, + private installer: InstallPromptService, private matIconRegistry: MatIconRegistry, private domSanitizer: DomSanitizer, ) { diff --git a/src/app/sessions/install-prompt/install-prompt.service.spec.ts b/src/app/sessions/install-prompt/install-prompt.service.spec.ts new file mode 100644 index 0000000000..1106f4a4c7 --- /dev/null +++ b/src/app/sessions/install-prompt/install-prompt.service.spec.ts @@ -0,0 +1,122 @@ +import { TestBed } from '@angular/core/testing'; +import { MatSnackBar, MatSnackBarRef, TextOnlySnackBar } from '@angular/material/snack-bar'; +import { Subject } from 'rxjs'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { InstallPromptService } from './install-prompt.service'; + +describe('InstallPromptService', () => { + let snackBarSpy: { open: ReturnType<typeof vi.fn> }; + let snackBarRefSpy: { onAction: ReturnType<typeof vi.fn>; afterDismissed: ReturnType<typeof vi.fn> }; + let actionSubject: Subject<void>; + let afterDismissedSubject: Subject<void>; + + beforeEach(() => { + actionSubject = new Subject<void>(); + afterDismissedSubject = new Subject<void>(); + + snackBarRefSpy = { + onAction: vi.fn().mockReturnValue(actionSubject.asObservable()), + afterDismissed: vi.fn().mockReturnValue(afterDismissedSubject.asObservable()), + }; + + snackBarSpy = { + open: vi.fn().mockReturnValue(snackBarRefSpy), + }; + + localStorage.clear(); + }); + + function createService(): InstallPromptService { + TestBed.configureTestingModule({ + providers: [ + InstallPromptService, + { provide: MatSnackBar, useValue: snackBarSpy }, + ], + }); + return TestBed.inject(InstallPromptService); + } + + it('should be created', () => { + const service = createService(); + expect(service).toBeTruthy(); + }); + + it('should do nothing if previously dismissed in localStorage', () => { + localStorage.setItem('ontrack_pwa_install_dismissed', 'true'); + createService(); + + expect(snackBarSpy.open).not.toHaveBeenCalled(); + }); + +describe('Non-iOS Flow', () => { + beforeEach(() => { + vi.spyOn(InstallPromptService.prototype as any, 'isIos').mockReturnValue(false); + }); + + it('should open snackbar and trigger prompt on user action', () => { + createService(); + + const mockEvent = new Event('beforeinstallprompt'); + const promptSpy = vi.fn(); + const preventDefaultSpy = vi.spyOn(mockEvent, 'preventDefault'); + (mockEvent as any).prompt = promptSpy; + + window.dispatchEvent(mockEvent); + + expect(preventDefaultSpy).toHaveBeenCalled(); + expect(snackBarSpy.open).toHaveBeenCalledWith( + 'Install OnTrack for a better experience', + 'Install', + { duration: 10000 } + ); + + actionSubject.next(); + expect(promptSpy).toHaveBeenCalled(); + }); + + it('should save dismissal to localStorage when snackbar is dismissed', () => { + createService(); + + const mockEvent = new Event('beforeinstallprompt'); + window.dispatchEvent(mockEvent); + + afterDismissedSubject.next(); + expect(localStorage.getItem('ontrack_pwa_install_dismissed')).toBe('true'); + }); + }); + + describe('iOS Flow', () => { + beforeEach(() => { + vi.spyOn(InstallPromptService.prototype as any, 'isIos').mockReturnValue(true); + }); + + it('should show iOS prompt if not in standalone mode', () => { + vi.spyOn(InstallPromptService.prototype as any, 'isStandalone').mockReturnValue(false); + + createService(); + + expect(snackBarSpy.open).toHaveBeenCalledWith( + 'To install OnTrack: tap Share then "Add to Home Screen"', + 'Got it', + { duration: 10000 } + ); + }); + + it('should not show prompt if already in standalone mode', () => { + vi.spyOn(InstallPromptService.prototype as any, 'isStandalone').mockReturnValue(true); + + createService(); + + expect(snackBarSpy.open).not.toHaveBeenCalled(); + }); + + it('should save dismissal to localStorage when iOS snackbar is dismissed', () => { + vi.spyOn(InstallPromptService.prototype as any, 'isStandalone').mockReturnValue(false); + + createService(); + + afterDismissedSubject.next(); + expect(localStorage.getItem('ontrack_pwa_install_dismissed')).toBe('true'); + }); + }); +}); \ No newline at end of file diff --git a/src/app/sessions/install-prompt/install-prompt.service.ts b/src/app/sessions/install-prompt/install-prompt.service.ts new file mode 100644 index 0000000000..bab65fc7bc --- /dev/null +++ b/src/app/sessions/install-prompt/install-prompt.service.ts @@ -0,0 +1,79 @@ +import { Injectable } from '@angular/core'; +import { MatSnackBar } from '@angular/material/snack-bar'; + + +export interface BeforeInstallPromptEvent extends Event { + readonly platforms: string[]; + readonly userChoice: Promise<{ + outcome: 'accepted' | 'dismissed'; + platform: string; + }>; + prompt(): Promise<void>; +} + +const DISMISSED_KEY = 'ontrack_pwa_install_dismissed'; +const PROMPT_DURATION = 10000 + +@Injectable() +export class InstallPromptService { + private beforeInstallPrompt: BeforeInstallPromptEvent | null = null; + + constructor(private _snackBar: MatSnackBar) { + if (localStorage.getItem(DISMISSED_KEY) === 'true') { + return; + } + + if (this.isIos()) { + if (!this.isStandalone()) { + this.showIosPrompt(); + } + return; + } + + window.addEventListener('beforeinstallprompt', (e: Event) => { + e.preventDefault(); + + this.beforeInstallPrompt = e as BeforeInstallPromptEvent; + + const snackBarRef = this._snackBar.open( + 'Install OnTrack for a better experience', + 'Install', + { duration: PROMPT_DURATION} + ); + + snackBarRef.onAction().subscribe(() => { + if (this.beforeInstallPrompt) { + this.beforeInstallPrompt.prompt(); + } + }); + + snackBarRef.afterDismissed().subscribe(() => { + localStorage.setItem(DISMISSED_KEY, 'true'); + }); + }); + } + + private showIosPrompt(): void { + const snackBarRef = this._snackBar.open( + 'To install OnTrack: tap Share then "Add to Home Screen"', + 'Got it', + { duration: PROMPT_DURATION} + ); + + snackBarRef.afterDismissed().subscribe(() => { + localStorage.setItem(DISMISSED_KEY, 'true'); + }); + } + + private isIos(): boolean { + const userAgent = window.navigator.userAgent.toLowerCase(); + return /iphone|ipad|ipod/.test(userAgent); + } + + private isStandalone(): boolean { + return ( + window.matchMedia('(display-mode: standalone)').matches || + ('standalone' in window.navigator && (window.navigator as unknown as { standalone: boolean }).standalone) + ); + } +} \ No newline at end of file From ccb2c56b4f355943192d07263435e3a0804e812b Mon Sep 17 00:00:00 2001 From: The Herald Sun <samuelryanmason@gmail.com> Date: Sat, 22 Aug 2026 04:54:14 +0000 Subject: [PATCH 1386/1531] fix(notifications): i forgot to lint my changes, whoops --- src/app/doubtfire-angular.module.ts | 2 +- .../install-prompt.service.spec.ts | 64 ++++++++++++------- .../install-prompt/install-prompt.service.ts | 16 ++--- 3 files changed, 51 insertions(+), 31 deletions(-) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 9079fae1c0..60959f626a 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -293,12 +293,12 @@ import {StaffNotesComponent} from './projects/states/staff-notes/staff-notes.com import {TutorDiscussionComponent} from './projects/states/tutor-discussion/tutor-discussion.component'; import {TutorNotesComponent} from './projects/states/tutor-notes/tutor-notes.component'; import {TutorialsComponent} from './projects/states/tutorials/tutorials.component'; +import {InstallPromptService} from './sessions/install-prompt/install-prompt.service'; // import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; // import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; // import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; // import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; import {CheckForUpdateService} from './sessions/service-worker-updater/check-for-update.service'; -import {InstallPromptService} from './sessions/install-prompt/install-prompt.service'; import {SignInComponent} from './sessions/states/sign-in/sign-in.component'; import {FeedbackAppealModalComponent} from './tasks/modals/feedback-appeal-modal/feedback-appeal-modal.component'; import {GradeTaskModalComponent} from './tasks/modals/grade-task-modal/grade-task-modal.component'; diff --git a/src/app/sessions/install-prompt/install-prompt.service.spec.ts b/src/app/sessions/install-prompt/install-prompt.service.spec.ts index 1106f4a4c7..ee96f8048b 100644 --- a/src/app/sessions/install-prompt/install-prompt.service.spec.ts +++ b/src/app/sessions/install-prompt/install-prompt.service.spec.ts @@ -1,12 +1,20 @@ -import { TestBed } from '@angular/core/testing'; -import { MatSnackBar, MatSnackBarRef, TextOnlySnackBar } from '@angular/material/snack-bar'; -import { Subject } from 'rxjs'; -import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { InstallPromptService } from './install-prompt.service'; +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {TestBed} from '@angular/core/testing'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {Subject} from 'rxjs'; +import {BeforeInstallPromptEvent, InstallPromptService} from './install-prompt.service'; + +interface InstallPromptServicePrivate { + isIos(): boolean; + isStandalone(): boolean; +} describe('InstallPromptService', () => { - let snackBarSpy: { open: ReturnType<typeof vi.fn> }; - let snackBarRefSpy: { onAction: ReturnType<typeof vi.fn>; afterDismissed: ReturnType<typeof vi.fn> }; + let snackBarSpy: {open: ReturnType<typeof vi.fn>}; + let snackBarRefSpy: { + onAction: ReturnType<typeof vi.fn>; + afterDismissed: ReturnType<typeof vi.fn>; + }; let actionSubject: Subject<void>; let afterDismissedSubject: Subject<void>; @@ -28,10 +36,7 @@ describe('InstallPromptService', () => { function createService(): InstallPromptService { TestBed.configureTestingModule({ - providers: [ - InstallPromptService, - { provide: MatSnackBar, useValue: snackBarSpy }, - ], + providers: [InstallPromptService, {provide: MatSnackBar, useValue: snackBarSpy}], }); return TestBed.inject(InstallPromptService); } @@ -48,18 +53,21 @@ describe('InstallPromptService', () => { expect(snackBarSpy.open).not.toHaveBeenCalled(); }); -describe('Non-iOS Flow', () => { + describe('Non-iOS Flow', () => { beforeEach(() => { - vi.spyOn(InstallPromptService.prototype as any, 'isIos').mockReturnValue(false); + vi.spyOn( + InstallPromptService.prototype as unknown as InstallPromptServicePrivate, + 'isIos', + ).mockReturnValue(false); }); it('should open snackbar and trigger prompt on user action', () => { createService(); - const mockEvent = new Event('beforeinstallprompt'); + const mockEvent = new Event('beforeinstallprompt') as BeforeInstallPromptEvent; const promptSpy = vi.fn(); const preventDefaultSpy = vi.spyOn(mockEvent, 'preventDefault'); - (mockEvent as any).prompt = promptSpy; + Object.defineProperty(mockEvent, 'prompt', {value: promptSpy}); window.dispatchEvent(mockEvent); @@ -67,7 +75,7 @@ describe('Non-iOS Flow', () => { expect(snackBarSpy.open).toHaveBeenCalledWith( 'Install OnTrack for a better experience', 'Install', - { duration: 10000 } + {duration: 10000}, ); actionSubject.next(); @@ -87,23 +95,32 @@ describe('Non-iOS Flow', () => { describe('iOS Flow', () => { beforeEach(() => { - vi.spyOn(InstallPromptService.prototype as any, 'isIos').mockReturnValue(true); + vi.spyOn( + InstallPromptService.prototype as unknown as InstallPromptServicePrivate, + 'isIos', + ).mockReturnValue(true); }); it('should show iOS prompt if not in standalone mode', () => { - vi.spyOn(InstallPromptService.prototype as any, 'isStandalone').mockReturnValue(false); + vi.spyOn( + InstallPromptService.prototype as unknown as InstallPromptServicePrivate, + 'isStandalone', + ).mockReturnValue(false); createService(); expect(snackBarSpy.open).toHaveBeenCalledWith( 'To install OnTrack: tap Share then "Add to Home Screen"', 'Got it', - { duration: 10000 } + {duration: 10000}, ); }); it('should not show prompt if already in standalone mode', () => { - vi.spyOn(InstallPromptService.prototype as any, 'isStandalone').mockReturnValue(true); + vi.spyOn( + InstallPromptService.prototype as unknown as InstallPromptServicePrivate, + 'isStandalone', + ).mockReturnValue(true); createService(); @@ -111,7 +128,10 @@ describe('Non-iOS Flow', () => { }); it('should save dismissal to localStorage when iOS snackbar is dismissed', () => { - vi.spyOn(InstallPromptService.prototype as any, 'isStandalone').mockReturnValue(false); + vi.spyOn( + InstallPromptService.prototype as unknown as InstallPromptServicePrivate, + 'isStandalone', + ).mockReturnValue(false); createService(); @@ -119,4 +139,4 @@ describe('Non-iOS Flow', () => { expect(localStorage.getItem('ontrack_pwa_install_dismissed')).toBe('true'); }); }); -}); \ No newline at end of file +}); diff --git a/src/app/sessions/install-prompt/install-prompt.service.ts b/src/app/sessions/install-prompt/install-prompt.service.ts index bab65fc7bc..e4a7e03d6d 100644 --- a/src/app/sessions/install-prompt/install-prompt.service.ts +++ b/src/app/sessions/install-prompt/install-prompt.service.ts @@ -1,6 +1,5 @@ -import { Injectable } from '@angular/core'; -import { MatSnackBar } from '@angular/material/snack-bar'; - +import {Injectable} from '@angular/core'; +import {MatSnackBar} from '@angular/material/snack-bar'; export interface BeforeInstallPromptEvent extends Event { readonly platforms: string[]; @@ -12,7 +11,7 @@ export interface BeforeInstallPromptEvent extends Event { } const DISMISSED_KEY = 'ontrack_pwa_install_dismissed'; -const PROMPT_DURATION = 10000 +const PROMPT_DURATION = 10000; @Injectable() export class InstallPromptService { @@ -38,7 +37,7 @@ export class InstallPromptService { const snackBarRef = this._snackBar.open( 'Install OnTrack for a better experience', 'Install', - { duration: PROMPT_DURATION} + {duration: PROMPT_DURATION}, ); snackBarRef.onAction().subscribe(() => { @@ -57,7 +56,7 @@ export class InstallPromptService { const snackBarRef = this._snackBar.open( 'To install OnTrack: tap Share then "Add to Home Screen"', 'Got it', - { duration: PROMPT_DURATION} + {duration: PROMPT_DURATION}, ); snackBarRef.afterDismissed().subscribe(() => { @@ -73,7 +72,8 @@ export class InstallPromptService { private isStandalone(): boolean { return ( window.matchMedia('(display-mode: standalone)').matches || - ('standalone' in window.navigator && (window.navigator as unknown as { standalone: boolean }).standalone) + ('standalone' in window.navigator && + (window.navigator as unknown as {standalone: boolean}).standalone) ); } -} \ No newline at end of file +} From 7b18b320d1ac08cbccd39f50c68e66220f2ba052 Mon Sep 17 00:00:00 2001 From: Maple 'Ryan' Fox <s223932052@deakin.edu.au> Date: Sat, 22 Aug 2026 15:00:44 +1000 Subject: [PATCH 1387/1531] Refactor PR notification condition Simplified the conditional check for PR notifications. --- .github/workflows/notify-teams-pr.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/notify-teams-pr.yml b/.github/workflows/notify-teams-pr.yml index 5cf0be21f6..eb1e03996c 100644 --- a/.github/workflows/notify-teams-pr.yml +++ b/.github/workflows/notify-teams-pr.yml @@ -25,10 +25,7 @@ jobs: # doubtfire-lms. Second keeps the webhook out of reach of anonymous fork PRs # while still notifying teammates who work from their own forks, which # several doubtfire-web contributors do. - if: >- - github.repository_owner == 'ontrack-features-t2-2026' && - (github.event.pull_request.head.repo.full_name == github.repository || - contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.pull_request.author_association)) + if: github.repository_owner == 'ontrack-features-t2-2026' runs-on: ubuntu-latest timeout-minutes: 2 From d2115c2bebe96de9de65c1ce349a853f1e7c53f2 Mon Sep 17 00:00:00 2001 From: Clupai8o0 <clupaio4@gmail.com> Date: Sat, 22 Aug 2026 16:24:16 +1000 Subject: [PATCH 1388/1531] fix(notifications): announce mark all read, guard double delete and manage focus Mark all read had no success handler, so the only feedback was rows losing their bold and a dot going grey. It now announces through AlertService. The button also moved from @if to disabled, but a native disabled attribute does not solve the focus problem it was meant to: a natively disabled button cannot hold focus either, so the browser drops it to the body just the same. disabledInteractive is Material's input for exactly this, buttons that become disabled when activated. It announces via aria-disabled and stays focusable, so markAllRead re-checks hasUnread rather than trusting the binding. The block stays inside an @if on the list length so a greyed control never sits over the loading, failed or empty states. The confirmation dialog closes as soon as it is agreed to and the row is not dropped until the response lands, so the same delete could be confirmed twice and the second request 404s. Ids with a request in the air are held and the button marked disabled, with disabledInteractive again so MatDialog can still restore focus to it. Focus after a removal now lands on the row that took the deleted one's place, clamped to what is on screen so a page collapse does not jump to the top, and only when focus actually went to the body, so a slow delete cannot take it back from wherever the reader moved to. The dialog also now names the notification, which the button's aria-label already did and the modal covering the list dropped. --- node_modules | 1 + .../notifications-page/notifications-page.component.spec.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 120000 node_modules diff --git a/node_modules b/node_modules new file mode 120000 index 0000000000..1d2e552449 --- /dev/null +++ b/node_modules @@ -0,0 +1 @@ +../doubtfire-web/node_modules \ No newline at end of file diff --git a/src/app/common/notifications-page/notifications-page.component.spec.ts b/src/app/common/notifications-page/notifications-page.component.spec.ts index fb36a703c9..cbb6016040 100644 --- a/src/app/common/notifications-page/notifications-page.component.spec.ts +++ b/src/app/common/notifications-page/notifications-page.component.spec.ts @@ -357,7 +357,7 @@ describe('NotificationsPageComponent', () => { // link is nullable on the api. Refusing to mark it read would leave a // number on the bell that the user has no way to clear. expect(notificationService.markRead).toHaveBeenCalledTimes(1); - expect(router.navigateByUrl).not.toHaveBeenCalled(); + expect(notificationRoutes.navigate).not.toHaveBeenCalled(); }); it('says so when a notification could not be marked as read', () => { @@ -499,7 +499,7 @@ describe('NotificationsPageComponent', () => { // would make asking to delete one mark it read and navigate away from the // page it was asked on. expect(notificationService.markRead).not.toHaveBeenCalled(); - expect(router.navigateByUrl).not.toHaveBeenCalled(); + expect(notificationRoutes.navigate).not.toHaveBeenCalled(); }); it('names the notification on its delete button', () => { From 036e3f91dc256dce846b802a09ff71cbada80bad Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sat, 22 Aug 2026 18:39:40 +1000 Subject: [PATCH 1389/1531] feat(CPD): add global dashboard, filters, summaries --- .../f-cross-dashboard.component.html | 97 +++- .../f-cross-dashboard.component.spec.ts | 526 +++++++++++++++++- .../dashboard/f-cross-dashboard.component.ts | 242 ++++++-- .../dashboard-list-item.component.html | 13 +- .../dashboard-list-item.component.spec.ts | 56 ++ .../dashboard-list-item.component.ts | 4 +- 6 files changed, 871 insertions(+), 67 deletions(-) create mode 100644 src/app/dashboard/list-item/dashboard-list-item.component.spec.ts diff --git a/src/app/dashboard/f-cross-dashboard.component.html b/src/app/dashboard/f-cross-dashboard.component.html index d304890cca..ceadf5f613 100644 --- a/src/app/dashboard/f-cross-dashboard.component.html +++ b/src/app/dashboard/f-cross-dashboard.component.html @@ -1,5 +1,9 @@ <div class="panel-full-screen flex h-full flex-col"> - <div class="flex shrink-0 flex-wrap items-end gap-4 px-16 pt-4"> + <div + aria-label="Global dashboard filters" + class="flex shrink-0 flex-wrap items-end gap-4 px-16 pt-4" + role="search" + > <mat-form-field appearance="outline" class="w-full max-w-64"> <mat-label>Unit scope</mat-label> <mat-select [value]="unitScope" (selectionChange)="setUnitScope($event.value)"> @@ -8,6 +12,58 @@ <mat-option value="all">All units</mat-option> </mat-select> </mat-form-field> + + <mat-form-field appearance="outline" class="w-full max-w-96 min-w-64"> + <mat-label>Search all units and tasks</mat-label> + <input + aria-label="Global search" + autocomplete="off" + matInput + type="search" + [value]="globalSearchTerm" + (input)="setGlobalSearch($any($event.target).value)" + /> + <mat-icon matSuffix>search</mat-icon> + </mat-form-field> + + <mat-form-field appearance="outline" class="w-full max-w-64"> + <mat-label>Task statuses</mat-label> + <mat-select + aria-label="Task statuses" + multiple + [value]="selectedStatuses" + (selectionChange)="setStatuses($event.value)" + > + @for (option of statusOptions; track option.value) { + <mat-option [value]="option.value">{{ option.label }}</mat-option> + } + </mat-select> + </mat-form-field> + + <mat-form-field appearance="outline" class="w-full max-w-64"> + <mat-label>Target grades</mat-label> + <mat-select + aria-label="Target grades" + multiple + [value]="selectedGrades" + (selectionChange)="setGrades($event.value)" + > + @for (option of gradeOptions; track option.value) { + <mat-option [value]="option.value">{{ option.label }}</mat-option> + } + </mat-select> + </mat-form-field> + + <button + class="mb-5 h-12" + mat-stroked-button + type="button" + [disabled]="!hasGlobalToolbarChanges" + (click)="clearGlobalFilters()" + > + Clear all + </button> + <div class="flex flex-col gap-1 pb-5"> <label class="font-medium" for="dashboard-start-date">Start date</label> <input @@ -104,6 +160,28 @@ </mat-menu> </div> + @if (unit.gradeSummaries.length > 0) { + <div + class="border-x border-gray-300 bg-gray-50 px-4 py-3" + [attr.aria-label]="'Grade task completion for ' + unit.code" + > + <p class="m-0 text-sm font-semibold">Grade task completion</p> + <div class="mt-1 flex flex-wrap gap-x-4 gap-y-1 text-sm"> + @for (summary of unit.gradeSummaries; track summary.targetGrade) { + <span> + @if (summary.total === 0) { + {{ summary.label }}: 0 tasks + } @else { + {{ summary.label }}: {{ summary.completed }} of {{ summary.total }} complete ({{ + summary.percentage + }}%) + } + </span> + } + </div> + </div> + } + <div class="flex flex-col overflow-y-auto"> @for (task of unit.tasks; track task.abbreviation) { <div class="border-b border-gray-300"> @@ -124,6 +202,20 @@ </div> } + @if ( + hasGlobalTaskCriteria && + displayedUnits.length === 0 && + !loadingPreviousUnits && + !previousUnitsLoadError + ) { + <div + class="flex w-full max-w-2xl shrink-0 items-center self-start rounded border border-gray-300 bg-white p-6" + role="status" + > + <p class="m-0">No tasks match the current global search and filters.</p> + </div> + } + @if (unitScope !== 'active' && loadingPreviousUnits) { <div class="flex w-80 shrink-0 items-center self-start rounded border border-gray-300 p-6"> Loading previous units... @@ -141,7 +233,8 @@ <h3 class="mt-0">Previous units</h3> unitScope !== 'active' && previousUnitsLoaded && !loadingPreviousUnits && - previousUnits.length === 0 + previousUnits.length === 0 && + !hasGlobalTaskCriteria ) { <div class="flex w-96 shrink-0 flex-col self-start overflow-hidden rounded shadow"> <div class="bg-green-600 p-4 text-white"> diff --git a/src/app/dashboard/f-cross-dashboard.component.spec.ts b/src/app/dashboard/f-cross-dashboard.component.spec.ts index 7f227522e1..c34aab2fb5 100644 --- a/src/app/dashboard/f-cross-dashboard.component.spec.ts +++ b/src/app/dashboard/f-cross-dashboard.component.spec.ts @@ -1,11 +1,21 @@ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'; +import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatButtonModule} from '@angular/material/button'; +import {MatButtonHarness} from '@angular/material/button/testing'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatIconModule} from '@angular/material/icon'; +import {MatInputModule} from '@angular/material/input'; import {MatMenuModule} from '@angular/material/menu'; +import {MatSelectModule} from '@angular/material/select'; +import {MatSelectHarness} from '@angular/material/select/testing'; +import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {BehaviorSubject, of, throwError} from 'rxjs'; +import {Grade} from '../api/models/grade'; import {Project} from '../api/models/project'; import {Task} from '../api/models/task'; -import {TaskStatusEnum} from '../api/models/task-status'; +import {TaskStatus, TaskStatusEnum} from '../api/models/task-status'; import {ProjectService} from '../api/services/project.service'; import {GlobalStateService} from '../projects/states/index/global-state.service'; import {CrossDashboardComponent} from './f-cross-dashboard.component'; @@ -30,6 +40,8 @@ describe('CrossDashboardComponent', () => { status: TaskStatusEnum, dueDate: Date | null | undefined, topWeight: number = 0, + targetGrade: number = 0, + targetGradeText: string = Grade.GRADES[targetGrade], ): Task => ({ status, @@ -38,19 +50,26 @@ describe('CrossDashboardComponent', () => { definition: { name, abbreviation, - targetGradeText: 'Pass', + targetGrade, + targetGradeText, description: `${name} description`, targetDate: dueDate, }, }) as unknown as Task; - const makeProject = (id: number, code: string, isActive: boolean, tasks: Task[] = []): Project => + const makeProject = ( + id: number, + code: string, + isActive: boolean, + tasks: Task[] = [], + name: string = `${code} Unit`, + ): Project => ({ id, tasks, unit: { code, - name: `${code} Unit`, + name, isActive, taskDefinitions: [], }, @@ -75,7 +94,15 @@ describe('CrossDashboardComponent', () => { await TestBed.configureTestingModule({ declarations: [CrossDashboardComponent], - imports: [MatMenuModule], + imports: [ + MatButtonModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatMenuModule, + MatSelectModule, + NoopAnimationsModule, + ], providers: [ { provide: GlobalStateService, @@ -110,6 +137,23 @@ describe('CrossDashboardComponent', () => { expect(component.displayedUnits.map((unit) => unit.code)).toEqual(['COS10001']); }); + it('includes authorised tasks above the project target grade', () => { + const passTask = makeTask('Pass Task', 'P1', 'complete', makeDate(10), 0, 0); + const distinctionTask = makeTask('Distinction Task', 'D1', 'redo', makeDate(11), 0, 2); + const project = makeProject(1, 'COS20007', true, [passTask, distinctionTask]); + const targetGradeTasks = vi.fn().mockReturnValue([passTask]); + + project.targetGrade = 0; + project.activeTasks = targetGradeTasks; + projectsSubject.next([project]); + + expect(targetGradeTasks).not.toHaveBeenCalled(); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + 'P1', + 'D1', + ]); + }); + it('loads and displays previous units in Previous units mode', () => { projectServiceQuery.mockReturnValue( of([makeProject(1, 'COS10001', true), makeProject(2, 'COS30046', false)]), @@ -197,7 +241,7 @@ describe('CrossDashboardComponent', () => { expect(component.displayedUnits).toHaveLength(2); const searchInputs = fixture.nativeElement.querySelectorAll( - 'input[type="search"]', + 'input[aria-label^="Search tasks in"]', ) as NodeListOf<HTMLInputElement>; expect(searchInputs).toHaveLength(2); @@ -277,7 +321,7 @@ describe('CrossDashboardComponent', () => { await syncView(); const searchInput = fixture.nativeElement.querySelector( - 'input[type="search"]', + 'input[aria-label^="Search tasks in"]', ) as HTMLInputElement; searchInput.value = 'retro'; @@ -636,4 +680,472 @@ describe('CrossDashboardComponent', () => { expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['MATCH']); }); + + it('renders one labelled global toolbar with canonical status and grade choices', async () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Individual Retrospective', '5.1P', 'not_started', makeDate(12)), + ]), + ]); + + await syncView(); + + expect( + fixture.nativeElement.querySelectorAll('[aria-label="Global dashboard filters"]'), + ).toHaveLength(1); + expect( + fixture.nativeElement.querySelectorAll('input[aria-label="Global search"]'), + ).toHaveLength(1); + expect( + fixture.nativeElement.querySelectorAll('input[aria-label^="Search tasks in"]'), + ).toHaveLength(1); + + expect(component.statusOptions).toEqual( + TaskStatus.STATUS_KEYS.map((value) => ({ + value, + label: TaskStatus.STATUS_LABELS.get(value), + })), + ); + expect(component.statusOptions).toEqual( + expect.arrayContaining([ + {value: 'complete', label: 'Complete'}, + {value: 'not_started', label: 'Not Started'}, + {value: 'redo', label: 'Redo'}, + {value: 'fix_and_resubmit', label: 'Resubmit'}, + ]), + ); + expect(component.gradeOptions).toEqual([ + {value: 0, label: 'Pass'}, + {value: 1, label: 'Credit'}, + {value: 2, label: 'Distinction'}, + {value: 3, label: 'High Distinction'}, + ]); + }); + + it('binds both multiple-select controls and Clear all through the rendered toolbar', async () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Security Pass Task', 'P1', 'complete', makeDate(10), 0, 0), + makeTask('Security Distinction Task', 'D1', 'redo', makeDate(11), 0, 2), + ]), + ]); + await syncView(); + + const loader = TestbedHarnessEnvironment.loader(fixture); + const statusSelect = await loader.getHarness( + MatSelectHarness.with({selector: '[aria-label="Task statuses"]'}), + ); + const gradeSelect = await loader.getHarness( + MatSelectHarness.with({selector: '[aria-label="Target grades"]'}), + ); + + expect(await statusSelect.isMultiple()).toBe(true); + expect(await gradeSelect.isMultiple()).toBe(true); + + await statusSelect.open(); + await statusSelect.clickOptions({text: /^(Redo|Complete)$/}); + await statusSelect.close(); + + await gradeSelect.open(); + await gradeSelect.clickOptions({text: /^(Pass|Distinction)$/}); + await gradeSelect.close(); + + const globalSearch = fixture.nativeElement.querySelector( + 'input[aria-label="Global search"]', + ) as HTMLInputElement; + globalSearch.value = 'security'; + globalSearch.dispatchEvent(new Event('input', {bubbles: true})); + component.setStartDate('2026-08-01'); + await syncView(); + + expect(component.selectedStatuses.slice().sort()).toEqual(['complete', 'redo']); + expect(component.selectedGrades).toEqual([0, 2]); + expect(await statusSelect.getValueText()).toContain('Redo'); + expect(await statusSelect.getValueText()).toContain('Complete'); + expect(await gradeSelect.getValueText()).toContain('Pass'); + expect(await gradeSelect.getValueText()).toContain('Distinction'); + + const clearAll = await loader.getHarness(MatButtonHarness.with({text: 'Clear all'})); + expect(await clearAll.isDisabled()).toBe(false); + await clearAll.click(); + await syncView(); + + expect(component.globalSearchTerm).toBe(''); + expect(component.selectedStatuses).toEqual([]); + expect(component.selectedGrades).toEqual([]); + expect(component.startDate).toBe(''); + expect(globalSearch.value).toBe(''); + expect(await statusSelect.getValueText()).toBe(''); + expect(await gradeSelect.getValueText()).toBe(''); + expect(await clearAll.isDisabled()).toBe(true); + }); + + it('globally searches every required unit and task field case-insensitively', () => { + projectsSubject.next([ + makeProject( + 1, + 'SIT764', + true, + [ + makeTask( + 'Individual Retrospective', + '5.1D', + 'ready_for_feedback', + new Date(2026, 7, 12), + 0, + 2, + ), + ], + 'Human Centred Design', + ), + makeProject( + 2, + 'SIT782', + true, + [makeTask('Network Plan', '2.1P', 'not_started', new Date(2026, 7, 18))], + 'Secure Networks', + ), + ]); + + const matchingQueries = [ + ' sit764 ', + 'HUMAN CENTRED', + 'individual retrospective', + '5.1d', + 'Awaiting Feedback', + 'Distinction', + 'Wednesday 12 August', + '12/08/2026', + '2026-08-12', + ]; + + for (const query of matchingQueries) { + component.setGlobalSearch(query); + + expect(component.displayedUnits.map((unit) => unit.code)).toEqual(['SIT764']); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['5.1D']); + } + + component.setGlobalSearch(' - '); + expect(component.globalSearchTerm).toBe(' - '); + expect(component.hasGlobalTaskCriteria).toBe(false); + expect(component.hasGlobalToolbarChanges).toBe(true); + expect(component.displayedUnits.map((unit) => unit.code)).toEqual(['SIT764', 'SIT782']); + + component.clearGlobalFilters(); + expect(component.globalSearchTerm).toBe(''); + expect(component.hasGlobalToolbarChanges).toBe(false); + }); + + it('filters by every trusted target-grade value and supports multiple grades', () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Pass Task', 'LOOKS-HD', 'not_started', makeDate(10), 0, 0), + makeTask('Credit Task', 'CREDIT', 'not_started', makeDate(11), 0, 1), + makeTask('Distinction Task', 'DISTINCTION', 'not_started', makeDate(12), 0, 2), + makeTask('High Distinction Task', 'LOOKS-P', 'not_started', makeDate(13), 0, 3), + ]), + ]); + + for (const option of component.gradeOptions) { + component.setGrades([option.value]); + + expect(component.displayedUnits[0].tasks).toHaveLength(1); + expect(component.displayedUnits[0].tasks[0].targetGrade).toBe(option.value); + expect(component.displayedUnits[0].tasks[0].targetGradeLabel).toBe(option.label); + } + + component.setGrades([0, 2]); + + expect(component.displayedUnits[0].tasks.map((task) => task.targetGrade)).toEqual([0, 2]); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + 'LOOKS-HD', + 'DISTINCTION', + ]); + }); + + it('filters by every existing task status and supports multiple statuses', () => { + const tasks = TaskStatus.STATUS_KEYS.map((status, index) => + makeTask( + `${TaskStatus.STATUS_LABELS.get(status)} Task`, + `TASK-${index}`, + status, + makeDate(10), + ), + ); + projectsSubject.next([makeProject(1, 'SIT764', true, tasks)]); + + for (const status of TaskStatus.STATUS_KEYS) { + component.setStatuses([status]); + + expect(component.displayedUnits[0].tasks).toHaveLength(1); + expect(component.displayedUnits[0].tasks[0].status).toBe(status); + } + + component.setStatuses(['complete', 'redo', 'fix_and_resubmit']); + + expect(component.displayedUnits[0].tasks.map((task) => task.status).sort()).toEqual([ + 'complete', + 'fix_and_resubmit', + 'redo', + ]); + }); + + it('uses OR within filter groups and AND across search, status and grade groups', () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Security Pass', 'MATCH-P', 'complete', makeDate(10), 0, 0), + makeTask('Security Credit', 'MATCH-C', 'fix_and_resubmit', makeDate(11), 0, 1), + makeTask('Security Distinction', 'GRADE-OUT', 'complete', makeDate(12), 0, 2), + makeTask('Security Redo', 'STATUS-OUT', 'redo', makeDate(13), 0, 0), + makeTask('Calendar Credit', 'SEARCH-OUT', 'complete', makeDate(14), 0, 1), + ]), + ]); + + component.setGlobalSearch('security'); + component.setStatuses(['complete', 'fix_and_resubmit']); + component.setGrades([0, 1]); + + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + 'MATCH-P', + 'MATCH-C', + ]); + }); + + it('applies global criteria in Previous units scope after authorised units load', () => { + projectServiceQuery.mockReturnValue( + of([ + makeProject(2, 'SIT704', false, [ + makeTask('Archived Pass Task', 'OLD-P', 'complete', makeDate(10), 0, 0), + makeTask('Archived Distinction Task', 'OLD-D', 'complete', makeDate(11), 0, 2), + makeTask('Archived Distinction Redo', 'OLD-REDO', 'redo', makeDate(12), 0, 2), + ]), + ]), + ); + + component.setUnitScope('previous'); + component.setGlobalSearch('archived'); + component.setStatuses(['complete']); + component.setGrades([2]); + + expect(component.unitScope).toBe('previous'); + expect(component.displayedUnits.map((unit) => unit.code)).toEqual(['SIT704']); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['OLD-D']); + }); + + it('applies global search before an independent per-unit search', () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Security Report', 'REPORT', 'not_started', makeDate(10)), + makeTask('Security Plan', 'PLAN', 'not_started', makeDate(11)), + ]), + makeProject(2, 'SIT782', true, [ + makeTask('Security Calendar', 'CALENDAR', 'not_started', makeDate(12)), + ]), + ]); + + component.setGlobalSearch('security'); + + expect(component.displayedUnits.map((unit) => unit.code)).toEqual(['SIT764', 'SIT782']); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + 'REPORT', + 'PLAN', + ]); + expect(component.displayedUnits[1].tasks.map((task) => task.abbreviation)).toEqual([ + 'CALENDAR', + ]); + + component.setSearch(1, 'report'); + + expect(component.displayedUnits.map((unit) => unit.code)).toEqual(['SIT764', 'SIT782']); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['REPORT']); + expect(component.displayedUnits[1].tasks.map((task) => task.abbreviation)).toEqual([ + 'CALENDAR', + ]); + + component.setSearch(1, ''); + + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + 'REPORT', + 'PLAN', + ]); + }); + + it('clears global criteria, restores Active units and leaves canonical results', () => { + const activeProject = makeProject(1, 'SIT764', true, [ + makeTask('Active Pass Task', 'ACTIVE-P', 'complete', makeDate(10), 0, 0), + makeTask('Active Credit Task', 'ACTIVE-C', 'not_started', makeDate(11), 0, 1), + ]); + const previousProject = makeProject(2, 'SIT704', false, [ + makeTask('Previous Pass Task', 'PREVIOUS-P', 'complete', makeDate(12), 0, 0), + ]); + + projectsSubject.next([activeProject]); + projectServiceQuery.mockReturnValue(of([activeProject, previousProject])); + + component.setUnitScope('all'); + component.setGlobalSearch('pass'); + component.setStatuses(['complete']); + component.setGrades([0]); + component.setStartDate('2026-08-01'); + component.setEndDate('2026-08-31'); + + expect(component.hasGlobalToolbarChanges).toBe(true); + expect(component.displayedUnits.map((unit) => unit.code)).toEqual(['SIT764', 'SIT704']); + + component.clearGlobalFilters(); + + expect(component.unitScope).toBe('active'); + expect(component.globalSearchTerm).toBe(''); + expect(component.selectedStatuses).toEqual([]); + expect(component.selectedGrades).toEqual([]); + expect(component.startDate).toBe(''); + expect(component.endDate).toBe(''); + expect(component.hasGlobalToolbarChanges).toBe(false); + expect(component.displayedUnits.map((unit) => unit.code)).toEqual(['SIT764']); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + 'ACTIVE-P', + 'ACTIVE-C', + ]); + expect(component.displayedUnits[0].gradeSummaries).toEqual([]); + }); + + it('removes globally empty units and renders the global no-results state', async () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Individual Retrospective', '5.1P', 'not_started', makeDate(12)), + ]), + ]); + + component.setGlobalSearch('not a matching task'); + await syncView(); + + expect(component.displayedUnits).toEqual([]); + expect(fixture.nativeElement.textContent).not.toContain('SIT764'); + expect(fixture.nativeElement.textContent).toContain( + 'No tasks match the current global search and filters.', + ); + expect(fixture.nativeElement.textContent).not.toContain( + 'No tasks match the current search and filters.', + ); + }); + + it('renders the global no-results state when the selected scope contains no units', async () => { + projectsSubject.next([]); + + component.setGlobalSearch('security'); + await syncView(); + + expect(component.displayedUnits).toEqual([]); + expect(fixture.nativeElement.textContent).toContain( + 'No tasks match the current global search and filters.', + ); + }); + + it('keeps grade summaries independent of global and per-unit search and status filters', async () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Completed Pass One', 'P1', 'complete', makeDate(10), 0, 0), + makeTask('Completed Pass Two', 'P2', 'complete', makeDate(11), 0, 0), + makeTask('Open Pass One', 'P3', 'not_started', makeDate(12), 0, 0), + makeTask('Portfolio Pass', 'P4', 'assess_in_portfolio', makeDate(13), 0, 0), + ]), + ]); + + component.setGrades([0]); + component.setStatuses(['not_started']); + component.setGlobalSearch('open'); + component.setSearch(1, 'one'); + await syncView(); + + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual(['P3']); + expect(component.displayedUnits[0].gradeSummaries).toEqual([ + { + targetGrade: 0, + label: 'Pass', + completed: 2, + total: 4, + percentage: 50, + }, + ]); + expect(fixture.nativeElement.textContent).toContain('Pass: 2 of 4 complete (50%)'); + }); + + it('shows a zero-task summary for a selected grade on an otherwise visible unit', async () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Credit Task', 'C1', 'not_started', makeDate(10), 0, 1), + ]), + ]); + + component.setGrades([0, 1]); + await syncView(); + + expect(component.displayedUnits).toHaveLength(1); + expect(component.displayedUnits[0].gradeSummaries).toEqual([ + { + targetGrade: 0, + label: 'Pass', + completed: 0, + total: 0, + percentage: null, + }, + { + targetGrade: 1, + label: 'Credit', + completed: 0, + total: 1, + percentage: 0, + }, + ]); + expect(fixture.nativeElement.textContent).toContain('Pass: 0 tasks'); + expect(fixture.nativeElement.textContent).toContain('Credit: 0 of 1 complete (0%)'); + expect(fixture.nativeElement.textContent).not.toContain('Pass: 0 of 0 complete (0%)'); + }); + + it('calculates summaries independently per unit using trusted task-definition labels', () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Foundation Complete', 'F1', 'complete', makeDate(10), 0, 0, 'Foundation'), + makeTask('Foundation Open', 'F2', 'not_started', makeDate(11), 0, 0, 'Foundation'), + ]), + makeProject(2, 'SIT782', true, [ + makeTask('Entry Complete One', 'E1', 'complete', makeDate(12), 0, 0, 'Entry'), + makeTask('Entry Complete Two', 'E2', 'complete', makeDate(13), 0, 0, 'Entry'), + makeTask('Entry Open', 'E3', 'redo', makeDate(14), 0, 0, 'Entry'), + ]), + ]); + + component.setGrades([0]); + + expect(component.displayedUnits[0].gradeSummaries).toEqual([ + { + targetGrade: 0, + label: 'Foundation', + completed: 1, + total: 2, + percentage: 50, + }, + ]); + expect(component.displayedUnits[1].gradeSummaries).toEqual([ + { + targetGrade: 0, + label: 'Entry', + completed: 2, + total: 3, + percentage: 67, + }, + ]); + }); + + it('hides all grade summaries until a grade filter is selected', async () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [makeTask('Pass Task', 'P1', 'complete', makeDate(10), 0, 0)]), + ]); + + await syncView(); + + expect(component.displayedUnits[0].gradeSummaries).toEqual([]); + expect(fixture.nativeElement.textContent).not.toContain('Grade task completion'); + }); }); diff --git a/src/app/dashboard/f-cross-dashboard.component.ts b/src/app/dashboard/f-cross-dashboard.component.ts index 12e731c56f..2ea5dd01f2 100644 --- a/src/app/dashboard/f-cross-dashboard.component.ts +++ b/src/app/dashboard/f-cross-dashboard.component.ts @@ -1,6 +1,7 @@ import {EntityCache} from 'ngx-entity-service'; import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit} from '@angular/core'; import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; +import {Grade} from '../api/models/grade'; import {Project} from '../api/models/project'; import {Task} from '../api/models/task'; import {TaskStatus, TaskStatusEnum} from '../api/models/task-status'; @@ -32,9 +33,18 @@ type DashboardUnit = { code: string; name: string; tasks: DashboardTask[]; + gradeSummaries: GradeCompletionSummary[]; isPrevious: boolean; }; +type GradeCompletionSummary = { + targetGrade: number; + label: string; + completed: number; + total: number; + percentage: number | null; +}; + @Component({ selector: 'f-cross-dashboard', templateUrl: './f-cross-dashboard.component.html', @@ -47,6 +57,19 @@ export class CrossDashboardComponent implements OnInit { unitScope: UnitScope = 'active'; + globalSearchTerm = ''; + selectedStatuses: TaskStatusEnum[] = []; + selectedGrades: number[] = []; + + readonly statusOptions = TaskStatus.STATUS_KEYS.flatMap((value) => { + const label = TaskStatus.STATUS_LABELS.get(value); + return label ? [{value, label}] : []; + }); + readonly gradeOptions = Grade.PASS_RANGE.map((value) => ({ + value, + label: Grade.GRADES[value], + })); + startDate = ''; endDate = ''; @@ -91,6 +114,25 @@ export class CrossDashboardComponent implements OnInit { return !this.isDateRangeInvalid && (!!this.startDate || !!this.endDate); } + get hasGlobalTaskCriteria(): boolean { + return ( + this.normaliseSearchText(this.globalSearchTerm).length > 0 || + this.selectedStatuses.length > 0 || + this.selectedGrades.length > 0 + ); + } + + get hasGlobalToolbarChanges(): boolean { + return ( + this.unitScope !== 'active' || + this.globalSearchTerm.length > 0 || + this.selectedStatuses.length > 0 || + this.selectedGrades.length > 0 || + !!this.startDate || + !!this.endDate + ); + } + setUnitScope(scope: UnitScope): void { this.unitScope = scope; this.processTasks(); @@ -102,6 +144,36 @@ export class CrossDashboardComponent implements OnInit { } } + setGlobalSearch(value: string): void { + this.globalSearchTerm = value ?? ''; + this.processTasks(); + } + + setStatuses(statuses: readonly TaskStatusEnum[] | null): void { + this.selectedStatuses = [...(statuses ?? [])]; + this.processTasks(); + } + + setGrades(grades: readonly number[] | null): void { + this.selectedGrades = [...(grades ?? [])]; + this.processTasks(); + } + + clearGlobalFilters(): void { + this.globalSearchTerm = ''; + this.selectedStatuses = []; + this.selectedGrades = []; + this.startDate = ''; + this.endDate = ''; + + if (this.unitScope !== 'active') { + this.setUnitScope('active'); + return; + } + + this.processTasks(); + } + setStartDate(value: string): void { this.startDate = value; this.processTasks(); @@ -195,48 +267,88 @@ export class CrossDashboardComponent implements OnInit { private processTasks(): void { const units = this.getUnitsForCurrentScope(); - this.unitsProcessed = units.map((unit) => ({ - ...unit, - tasks: unit.tasks - .filter((task) => { - const filters = this.filters.get(unit.projectId) ?? []; - const isHiddenCompletedTask = - filters.includes(Filter.HideCompleted) && completedTypes.includes(task.status); - - return ( - !isHiddenCompletedTask && - this.taskMatchesDateRange(task) && - this.taskMatchesSearch(task, unit.projectId) - ); - }) - .sort((a, b) => { - const sort = this.sorting.get(unit.projectId) ?? SortMode.Recommended; - - if (completedTypes.includes(a.status) && !completedTypes.includes(b.status)) { - return -1; - } - - if (!completedTypes.includes(a.status) && completedTypes.includes(b.status)) { - return 1; - } - - switch (sort) { - case SortMode.Recommended: - // TODO: Connect to recommender's points. - return 0; - case SortMode.SubmissionDate: - return this.compareDueDates(a.dueDate, b.dueDate); - case SortMode.Default: - return a.weight - b.weight; - } - - return 0; - }), - })); + this.unitsProcessed = units + .map((unit) => ({ + unit, + globallyFilteredTasks: unit.tasks.filter((task) => + this.taskMatchesGlobalCriteria(task, unit), + ), + })) + .filter( + ({globallyFilteredTasks}) => + !this.hasGlobalTaskCriteria || globallyFilteredTasks.length > 0, + ) + .map(({unit, globallyFilteredTasks}) => ({ + ...unit, + gradeSummaries: this.buildGradeSummaries(unit.tasks), + tasks: globallyFilteredTasks + .filter((task) => { + const filters = this.filters.get(unit.projectId) ?? []; + const isHiddenCompletedTask = + filters.includes(Filter.HideCompleted) && completedTypes.includes(task.status); + + return ( + !isHiddenCompletedTask && + this.taskMatchesDateRange(task) && + this.taskMatchesPerUnitSearch(task, unit) + ); + }) + .sort((a, b) => { + const sort = this.sorting.get(unit.projectId) ?? SortMode.Recommended; + + if (completedTypes.includes(a.status) && !completedTypes.includes(b.status)) { + return -1; + } + + if (!completedTypes.includes(a.status) && completedTypes.includes(b.status)) { + return 1; + } + + switch (sort) { + case SortMode.Recommended: + // TODO: Connect to recommender's points. + return 0; + case SortMode.SubmissionDate: + return this.compareDueDates(a.dueDate, b.dueDate); + case SortMode.Default: + return a.weight - b.weight; + } + + return 0; + }), + })); this.changeDetectorRef.markForCheck(); } + private taskMatchesGlobalCriteria(task: DashboardTask, unit: DashboardUnit): boolean { + const matchesStatus = + this.selectedStatuses.length === 0 || this.selectedStatuses.includes(task.status); + const matchesGrade = + this.selectedGrades.length === 0 || this.selectedGrades.includes(task.targetGrade); + + return matchesStatus && matchesGrade && this.taskMatchesGlobalSearch(task, unit); + } + + private buildGradeSummaries(tasks: readonly DashboardTask[]): GradeCompletionSummary[] { + return this.selectedGrades.map((targetGrade) => { + const tasksInGrade = tasks.filter((task) => task.targetGrade === targetGrade); + const completed = tasksInGrade.filter((task) => task.status === 'complete').length; + const total = tasksInGrade.length; + + return { + targetGrade, + label: + tasksInGrade[0]?.targetGradeLabel ?? + this.gradeOptions.find((option) => option.value === targetGrade)?.label ?? + '', + completed, + total, + percentage: total === 0 ? null : Math.round((completed / total) * 100), + }; + }); + } + private taskMatchesDateRange(task: DashboardTask): boolean { if (!this.isDateFilterActive) { return true; @@ -286,8 +398,33 @@ export class CrossDashboardComponent implements OnInit { return firstTime - secondTime; } - private taskMatchesSearch(task: DashboardTask, projectId: number): boolean { - const rawSearchTerm = this.getSearchTerm(projectId); + private taskMatchesGlobalSearch(task: DashboardTask, unit: DashboardUnit): boolean { + return this.taskMatchesSearchText(task, this.globalSearchTerm, [ + unit.code, + unit.name, + task.title, + task.abbreviation, + task.statusLabel, + task.targetGradeLabel, + ]); + } + + private taskMatchesPerUnitSearch(task: DashboardTask, unit: DashboardUnit): boolean { + return this.taskMatchesSearchText(task, this.getSearchTerm(unit.projectId), [ + task.title, + task.subtitle, + task.description, + task.abbreviation, + task.statusLabel, + unit.code, + ]); + } + + private taskMatchesSearchText( + task: DashboardTask, + rawSearchTerm: string, + searchableValues: readonly string[], + ): boolean { const searchTerm = this.normaliseSearchText(rawSearchTerm); if (!searchTerm) { @@ -308,15 +445,7 @@ export class CrossDashboardComponent implements OnInit { } const searchableText = this.normaliseSearchText( - [ - task.title, - task.subtitle, - task.description, - task.abbreviation, - task.statusLabel, - task.unitCode, - this.formatDateForSearch(task.dueDate), - ].join(' '), + [...searchableValues, this.formatDateForSearch(task.dueDate)].join(' '), ); return remainingSearchTerm.split(' ').every((term) => searchableText.includes(term)); @@ -371,13 +500,12 @@ export class CrossDashboardComponent implements OnInit { ); } - private formatDateForSearch(date: Date): string { - const isoDate = this.formatDateAsIso(date); - - if (!isoDate) { + private formatDateForSearch(date: Date | null | undefined): string { + if (!(date instanceof Date) || Number.isNaN(date.getTime())) { return ''; } + const isoDate = this.formatDateAsIso(date); const [year, month, day] = isoDate.split('-'); return [displayedDueDateFormatter.format(date), `${day}/${month}/${year}`, isoDate].join(' '); @@ -404,7 +532,11 @@ export class CrossDashboardComponent implements OnInit { projectId: project.id, code: unit.code, name: unit.name, - tasks: this.mapTasks(project.activeTasks(), project.id, unit.code), + // The cross-unit dashboard is an authorised-task view, not a target-grade plan. + // `activeTasks()` excludes definitions above the student's current target grade, + // even though those tasks are returned by the API and remain available to them. + tasks: this.mapTasks(project.tasks, project.id, unit.code), + gradeSummaries: [], isPrevious: !unit.isActive, }; }); @@ -422,6 +554,8 @@ export class CrossDashboardComponent implements OnInit { color: TaskStatus.STATUS_COLORS.get(task.status), comments: task.numNewComments ?? 0, status: task.status, + targetGrade: def.targetGrade, + targetGradeLabel: def.targetGradeText, weight: task.topWeight, projectId, description: def.description, diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.html b/src/app/dashboard/list-item/dashboard-list-item.component.html index 6498999a9b..935a18ca12 100644 --- a/src/app/dashboard/list-item/dashboard-list-item.component.html +++ b/src/app/dashboard/list-item/dashboard-list-item.component.html @@ -8,6 +8,7 @@ {{ task.title }} </h4> <p class="mb-0">{{ task.subtitle }}</p> + <p class="mt-1 mb-0 text-sm font-medium">Status: {{ task.statusLabel }}</p> </div> <div class="mr-6 ml-2 flex flex-row items-center justify-end gap-4"> @if (!isExpanded && task.comments > 0) { @@ -15,9 +16,15 @@ <span class="m-auto text-xl font-medium text-white">{{ task.comments }}</span> </div> } - <mat-icon class="cursor-pointer" (click)="isExpanded = !isExpanded"> - {{ isExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }} - </mat-icon> + <button + mat-icon-button + type="button" + [attr.aria-expanded]="isExpanded" + [attr.aria-label]="(isExpanded ? 'Collapse ' : 'Expand ') + task.title + ' details'" + (click)="isExpanded = !isExpanded" + > + <mat-icon>{{ isExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</mat-icon> + </button> </div> </div> <div class="flex flex-row"> diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts b/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts new file mode 100644 index 0000000000..876935f265 --- /dev/null +++ b/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts @@ -0,0 +1,56 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatButtonModule} from '@angular/material/button'; +import {MatIconModule} from '@angular/material/icon'; +import {TaskDefinition} from '../../api/models/task-definition'; +import {DashboardListItemComponent, DashboardTask} from './dashboard-list-item.component'; + +describe('DashboardListItemComponent', () => { + let fixture: ComponentFixture<DashboardListItemComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [DashboardListItemComponent], + imports: [MatButtonModule, MatIconModule], + schemas: [NO_ERRORS_SCHEMA], + }).compileComponents(); + + fixture = TestBed.createComponent(DashboardListItemComponent); + fixture.componentInstance.task = { + title: 'Security Review', + subtitle: '1.1P - Pass Task', + statusLabel: 'Resubmit', + abbreviation: '1.1P', + color: '#123456', + comments: 0, + status: 'fix_and_resubmit', + targetGrade: 0, + targetGradeLabel: 'Pass', + weight: 0, + projectId: 1, + description: 'Review the security findings.', + taskDef: {} as TaskDefinition, + unitCode: 'SIT764', + dueDate: new Date(2026, 7, 12), + } satisfies DashboardTask; + fixture.detectChanges(); + }); + + it('shows a textual status without requiring the colour indicator', () => { + expect(fixture.nativeElement.textContent).toContain('Status: Resubmit'); + }); + + it('uses a labelled native button with expanded state for task details', () => { + const button = fixture.nativeElement.querySelector('button') as HTMLButtonElement; + + expect(button.getAttribute('aria-label')).toBe('Expand Security Review details'); + expect(button.getAttribute('aria-expanded')).toBe('false'); + + button.click(); + fixture.detectChanges(); + + expect(button.getAttribute('aria-label')).toBe('Collapse Security Review details'); + expect(button.getAttribute('aria-expanded')).toBe('true'); + }); +}); diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.ts b/src/app/dashboard/list-item/dashboard-list-item.component.ts index 2a28c3ded6..b45332fcd4 100644 --- a/src/app/dashboard/list-item/dashboard-list-item.component.ts +++ b/src/app/dashboard/list-item/dashboard-list-item.component.ts @@ -10,12 +10,14 @@ export type DashboardTask = { color: string; comments: number; status: TaskStatusEnum; + targetGrade: number; + targetGradeLabel: string; weight: number; projectId: number; description: string; taskDef: TaskDefinition; unitCode: string; - dueDate: Date; + dueDate: Date | null | undefined; }; @Component({ From bed1e04646f3958735a512573d5f857ef5edee7c Mon Sep 17 00:00:00 2001 From: Maple 'Ryan' Fox <s223932052@deakin.edu.au> Date: Sat, 22 Aug 2026 19:32:54 +1000 Subject: [PATCH 1390/1531] bugfix(notif): member requirement before secret access --- .github/workflows/notify-teams-pr.yml | 135 +++++++++++++------------- 1 file changed, 68 insertions(+), 67 deletions(-) diff --git a/.github/workflows/notify-teams-pr.yml b/.github/workflows/notify-teams-pr.yml index eb1e03996c..99308ed75f 100644 --- a/.github/workflows/notify-teams-pr.yml +++ b/.github/workflows/notify-teams-pr.yml @@ -15,22 +15,72 @@ on: # # message per requested reviewer. Decide, do not default. # Removes all GITHUB_TOKEN scopes, which this workflow does not need. It does NOT -# restrict secrets.* - the webhook is protected by the job guard below, not by this. +# restrict secrets.* - the webhook is protected by the guards below, not by this. permissions: {} jobs: notify-teams: name: Post pull request notification to Teams - # First clause makes the file inert if it ever travels to thoth-tech or - # doubtfire-lms. Second keeps the webhook out of reach of anonymous fork PRs - # while still notifying teammates who work from their own forks, which - # several doubtfire-web contributors do. + # The job guard makes the file inert if it ever travels to thoth-tech or + # doubtfire-lms. The step below restricts notifications to the two OnTrack + # teams, regardless of which repository or fork the pull request comes from. if: github.repository_owner == 'ontrack-features-t2-2026' runs-on: ubuntu-latest timeout-minutes: 2 steps: + - name: Check pull request author team membership + id: team-membership + shell: bash + env: + TEAM_MEMBERSHIP_TOKEN: ${{ secrets.TEAM_MEMBERSHIP_TOKEN }} + PR_AUTHOR: ${{ github.event.pull_request.user.login }} + run: | + set -euo pipefail + + if [[ -z "${TEAM_MEMBERSHIP_TOKEN:-}" ]]; then + echo "::error::The TEAM_MEMBERSHIP_TOKEN secret is not configured." + exit 1 + fi + + for team in ontrack-contributors ontrack-leads; do + http_status="$( + curl \ + --proto '=https' \ + --tlsv1.2 \ + --silent \ + --show-error \ + --connect-timeout 10 \ + --max-time 30 \ + --header 'Accept: application/vnd.github+json' \ + --header "Authorization: Bearer ${TEAM_MEMBERSHIP_TOKEN}" \ + --header 'X-GitHub-Api-Version: 2022-11-28' \ + --output "${RUNNER_TEMP}/team-membership.json" \ + --write-out '%{http_code}' \ + "https://api.github.com/orgs/ontrack-features-t2-2026/teams/${team}/memberships/${PR_AUTHOR}" \ + )" || http_status="000" + + case "${http_status}" in + 200) + membership_state="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["state"])' \ + < "${RUNNER_TEMP}/team-membership.json")" + if [[ "${membership_state}" == "active" ]]; then + echo "eligible=true" >> "${GITHUB_OUTPUT}" + exit 0 + fi + ;; + 404) ;; + *) + echo "::error::GitHub returned HTTP ${http_status} while checking team membership." + exit 1 + ;; + esac + done + + echo "eligible=false" >> "${GITHUB_OUTPUT}" + - name: Build and send Teams notification + if: steps.team-membership.outputs.eligible == 'true' shell: bash env: TEAMS_WEBHOOK_URL: ${{ secrets.TEAMS_PR_WEBHOOK_URL }} @@ -83,67 +133,18 @@ jobs: else "Ready for review" ) - card = { - "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", - "type": "AdaptiveCard", - "version": "1.2", - "body": [ - { - "type": "TextBlock", - "size": "Medium", - "weight": "Bolder", - "wrap": True, - "text": headline, - }, - { - "type": "TextBlock", - "wrap": True, - "text": f"PR #{os.environ['PR_NUMBER']}: {plain(os.environ['PR_TITLE'])}", - }, - { - "type": "FactSet", - "facts": [ - { - "title": "Repository", - "value": plain(os.environ["REPOSITORY"]), - }, - { - "title": "Author", - "value": plain(os.environ["PR_AUTHOR"]), - }, - { - "title": "Status", - "value": status, - }, - { - "title": "Branches", - "value": ( - f"{plain(os.environ['PR_HEAD'])} -> " - f"{plain(os.environ['PR_BASE'])}" - ), - }, - ], - }, - ], - "actions": [ - { - "type": "Action.OpenUrl", - "title": "Open pull request", - "url": os.environ["PR_URL"], - } - ], - } - - payload = { - "type": "message", - "attachments": [ - { - "contentType": "application/vnd.microsoft.card.adaptive", - "contentUrl": None, - "content": card, - } - ], - } + # Teams renders a break for "\n\n" and not for a single "\n". + text = "\n\n".join( + [ + headline, + f"Repository: {os.environ['REPOSITORY']}", + f"PR #{os.environ['PR_NUMBER']}: {plain(os.environ['PR_TITLE'])}", + f"Author: {plain(os.environ['PR_AUTHOR'])}", + f"Status: {status}", + f"Branches: {plain(os.environ['PR_HEAD'])} -> {os.environ['PR_BASE']}", + os.environ["PR_URL"], + ] + ) with open( os.environ["PAYLOAD_PATH"], @@ -151,7 +152,7 @@ jobs: encoding="utf-8", ) as payload_file: json.dump( - payload, + {"text": text}, payload_file, ensure_ascii=False, ) From 4c6c120945774a023aca70f390ddf2642eb39735 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sat, 22 Aug 2026 21:22:06 +1000 Subject: [PATCH 1391/1531] fix(dashboard): improve task search contrast --- .../dashboard/f-cross-dashboard.component.html | 2 +- .../dashboard/f-cross-dashboard.component.spec.ts | 15 +++++++++++++++ .../unit-task-list/unit-task-list.component.html | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/app/dashboard/f-cross-dashboard.component.html b/src/app/dashboard/f-cross-dashboard.component.html index d304890cca..d700cc46b1 100644 --- a/src/app/dashboard/f-cross-dashboard.component.html +++ b/src/app/dashboard/f-cross-dashboard.component.html @@ -69,7 +69,7 @@ <input autocomplete="off" - class="text-md h-full w-56 rounded-md p-2 px-4" + class="text-md h-full w-56 rounded-md bg-white p-2 px-4 text-gray-900 placeholder:text-gray-600 placeholder:opacity-100 focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-formatif-blue focus:outline-none" placeholder="Search tasks..." type="search" [attr.aria-label]="'Search tasks in ' + unit.code" diff --git a/src/app/dashboard/f-cross-dashboard.component.spec.ts b/src/app/dashboard/f-cross-dashboard.component.spec.ts index 7f227522e1..8068b15f29 100644 --- a/src/app/dashboard/f-cross-dashboard.component.spec.ts +++ b/src/app/dashboard/f-cross-dashboard.component.spec.ts @@ -235,6 +235,21 @@ describe('CrossDashboardComponent', () => { } }); + it('renders per-unit search with an explicit readable surface and placeholder', async () => { + projectsSubject.next([makeProject(1, 'SIT764', true)]); + + await syncView(); + + const searchInput = fixture.nativeElement.querySelector( + 'input[aria-label="Search tasks in SIT764"]', + ) as HTMLInputElement; + + expect(searchInput.classList.contains('bg-white')).toBe(true); + expect(searchInput.classList.contains('text-gray-900')).toBe(true); + expect(searchInput.classList.contains('placeholder:text-gray-600')).toBe(true); + expect(searchInput.classList.contains('placeholder:opacity-100')).toBe(true); + }); + it('does not confuse Australian dates that contain the same numbers in another order', () => { projectsSubject.next([ makeProject(1, 'SIT764', true, [ diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index 3bde7ab01b..df25cd4c2f 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -101,7 +101,7 @@ </button> <input autocomplete="off" - class="search w-full" + class="search w-full text-gray-900 placeholder:text-gray-600 placeholder:opacity-100" placeholder="Search Tasks" spellcheck="false" type="text" From f5223e2c71cb20b73aa5fb58b1ca07be2028a425 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sat, 22 Aug 2026 21:22:41 +1000 Subject: [PATCH 1392/1531] fix(dashboard): scope tasks to target grade --- .../progress-dashboard.component.html | 13 +- .../progress-dashboard.component.spec.ts | 112 ++++++++++++++++++ .../progress-dashboard.component.ts | 31 ++++- .../project-dashboard.component.html | 1 + .../task-planner/task-planner.component.html | 6 +- .../task-planner.component.spec.ts | 51 ++++++++ .../task-planner/task-planner.component.ts | 64 +++++++--- .../unit-task-list.component.html | 6 +- .../unit-task-list.component.spec.ts | 80 ++++++++++++- .../unit-task-list.component.ts | 74 ++++++++---- 10 files changed, 384 insertions(+), 54 deletions(-) create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts create mode 100644 src/app/projects/states/plan/task-planner/task-planner.component.spec.ts diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html index dfc62a5318..82806c09c0 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html @@ -35,8 +35,9 @@ <h4 class="py-3.5 font-semibold text-gray-800"> <mat-form-field appearance="fill" class="w-full"> <mat-label>Select Target Grade</mat-label> <mat-select - disabled - [(value)]="project.targetGrade" + aria-label="Target grade" + [disabled]="isUpdatingTargetGrade" + [value]="project.targetGrade" (selectionChange)="updateTargetGrade($event.value)" > @for (grade of grades.values; track grade) { @@ -46,8 +47,8 @@ <h4 class="py-3.5 font-semibold text-gray-800"> } </mat-select> </mat-form-field> - <div class="ml-0.5 py-1 opacity-70"> - To change your target grade, use the + <div class="ml-0.5 py-1 text-gray-600"> + Plan task dates and prerequisites in the <a class="cursor-pointer underline" [routerLink]="['/projects', project.id, 'plan']"> Task Planner </a> @@ -124,7 +125,9 @@ <h4 class="py-3.5 font-semibold text-gray-800"> <mat-card appearance="outlined" class="max-h-[600px]"> <mat-card-header> <mat-card-title>Task Statuses</mat-card-title> - <mat-card-subtitle>Breakdown summary of each of your task statuses</mat-card-subtitle> + <mat-card-subtitle> + Breakdown of tasks at or below your selected target grade + </mat-card-subtitle> </mat-card-header> <mat-card-content> <f-task-visualisation diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts new file mode 100644 index 0000000000..008e390cb2 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts @@ -0,0 +1,112 @@ +import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'; +import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatCardModule} from '@angular/material/card'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatSelectModule} from '@angular/material/select'; +import {MatSelectHarness} from '@angular/material/select/testing'; +import {NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {of, throwError} from 'rxjs'; +import {Project} from 'src/app/api/models/project'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GradeService} from 'src/app/common/services/grade.service'; +import {ProgressDashboardComponent} from './progress-dashboard.component'; + +describe('ProgressDashboardComponent', () => { + let component: ProgressDashboardComponent; + let fixture: ComponentFixture<ProgressDashboardComponent>; + let project: Project; + let projectServiceUpdate: ReturnType<typeof vi.fn>; + let alertSuccess: ReturnType<typeof vi.fn>; + let alertError: ReturnType<typeof vi.fn>; + + beforeEach(async () => { + project = { + id: 18, + targetGrade: 0, + unit: { + myRole: 'Student', + gradeDefinitions: [ + {value: 0, label: 'Pass'}, + {value: 1, label: 'Credit'}, + ], + }, + activeTasks: vi + .fn() + .mockReturnValue([{status: 'complete'}, {status: 'not_started'}, {status: 'not_started'}]), + refreshBurndownChartData: vi.fn(), + } as unknown as Project; + + projectServiceUpdate = vi.fn().mockReturnValue(of(project)); + alertSuccess = vi.fn(); + alertError = vi.fn(); + + await TestBed.configureTestingModule({ + declarations: [ProgressDashboardComponent], + imports: [MatCardModule, MatFormFieldModule, MatSelectModule, NoopAnimationsModule], + providers: [ + { + provide: GradeService, + useValue: { + grades: {0: 'Pass', 1: 'Credit'}, + gradeValues: [0, 1], + gradeValuesFor: () => [0, 1], + }, + }, + {provide: ProjectService, useValue: {update: projectServiceUpdate}}, + {provide: AlertService, useValue: {success: alertSuccess, error: alertError}}, + {provide: UserService, useValue: {currentUser: {id: 25}}}, + ], + schemas: [NO_ERRORS_SCHEMA], + }).compileComponents(); + + fixture = TestBed.createComponent(ProgressDashboardComponent); + component = fixture.componentInstance; + component.project = project; + fixture.detectChanges(); + await fixture.whenStable(); + vi.clearAllMocks(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('lets the student select a target grade directly from the dashboard', async () => { + const loader = TestbedHarnessEnvironment.loader(fixture); + const select = await loader.getHarness( + MatSelectHarness.with({selector: '[aria-label="Target grade"]'}), + ); + + expect(await select.isDisabled()).toBe(false); + expect(await select.getValueText()).toBe('Pass'); + + await select.open(); + await select.clickOptions({text: 'Credit'}); + + expect(project.targetGrade).toBe(1); + expect(projectServiceUpdate).toHaveBeenCalledWith(project); + expect(alertSuccess).toHaveBeenCalledWith('Updated target grade successfully', 2000); + expect(component.numberOfTasks).toEqual({completed: 1, remaining: 2}); + }); + + it('restores the previous target grade when the update fails', () => { + projectServiceUpdate.mockReturnValueOnce(throwError(() => new Error('update failed'))); + vi.spyOn(console, 'error').mockImplementation(() => undefined); + + component.updateTargetGrade(1); + + expect(project.targetGrade).toBe(0); + expect(component.isUpdatingTargetGrade).toBe(false); + expect(alertError).toHaveBeenCalledWith('Failed to update target grade', 4000); + }); + + it('uses the target-scoped task collection for completion totals', () => { + component.ngOnInit(); + + expect(component.numberOfTasks).toEqual({completed: 1, remaining: 2}); + }); +}); diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts index 7cb2445c90..aaecb0a745 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts @@ -32,6 +32,7 @@ export class ProgressDashboardComponent implements OnInit { completed: 0, remaining: 0, }; + isUpdatingTargetGrade = false; constructor( private gradeService: GradeService, @@ -57,26 +58,44 @@ export class ProgressDashboardComponent implements OnInit { } updateTargetGrade(newGrade: number): void { + if ( + this.isUpdatingTargetGrade || + newGrade === undefined || + newGrade === null || + newGrade === this.project.targetGrade + ) { + return; + } + + const previousTargetGrade = this.project.targetGrade; this.project.targetGrade = newGrade; - this.projectService.update(this.project).subscribe( - (project) => { + this.isUpdatingTargetGrade = true; + + this.projectService.update(this.project).subscribe({ + next: (project) => { + this.isUpdatingTargetGrade = false; project.refreshBurndownChartData(); this.updateTaskCompletionValues(); this.doUpdateTargetGrade.emit(); this.alertService.success('Updated target grade successfully', 2000); }, - (error) => { + error: (error) => { + this.isUpdatingTargetGrade = false; + this.project.targetGrade = previousTargetGrade; + this.updateTaskCompletionValues(); + this.doUpdateTargetGrade.emit(); console.error('Error updating target grade:', error); this.alertService.error('Failed to update target grade', 4000); }, - ); + }); } private updateTaskCompletionValues(): void { - const completedTasks = this.project.numberTasks('complete'); + const activeTasks = this.project.activeTasks(); + const completedTasks = activeTasks.filter((task) => task.status === 'complete').length; this.numberOfTasks = { completed: completedTasks, - remaining: this.project.activeTasks().length - completedTasks, + remaining: activeTasks.length - completedTasks, }; } } diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html index 71f90d18ee..b1651e8154 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.html @@ -50,6 +50,7 @@ [selectedTaskDefinition$]="selectedTaskDefinition$" [selectionUrlBase]="taskSelectionUrlBase" [style.width.px]="leftWidth" + [targetGrade]="project.targetGrade" [taskDefinitions]="taskDefinitionsForProject(project)" [tasks]="project.tasks" ></f-unit-task-list> diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.html b/src/app/projects/states/plan/task-planner/task-planner.component.html index 8e0e9894d4..5aaf830f00 100644 --- a/src/app/projects/states/plan/task-planner/task-planner.component.html +++ b/src/app/projects/states/plan/task-planner/task-planner.component.html @@ -2,10 +2,10 @@ <div class="flex items-center gap-2"> <mat-slide-toggle [(ngModel)]="showDatesColumn">Show Task Dates</mat-slide-toggle> <mat-slide-toggle - [ngModel]="hideTasksAboveTargetGrade" - (ngModelChange)="setHideTasksAboveTargetGrade($event)" + [ngModel]="showTasksAboveTargetGrade" + (ngModelChange)="setShowTasksAboveTargetGrade($event)" > - Hide tasks beyond target grade + Show tasks beyond target grade </mat-slide-toggle> </div> @if (unit.allowFlexibleDates) { diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.spec.ts b/src/app/projects/states/plan/task-planner/task-planner.component.spec.ts new file mode 100644 index 0000000000..185345ccb4 --- /dev/null +++ b/src/app/projects/states/plan/task-planner/task-planner.component.spec.ts @@ -0,0 +1,51 @@ +import {describe, expect, it} from 'vitest'; +import {Project, TaskDefinition} from 'src/app/api/models/doubtfire-model'; +import {TaskPlannerComponent} from './task-planner.component'; + +const taskDefinition = (id: number, targetGrade: number): TaskDefinition => + ({ + id, + targetGrade, + startDate: new Date(2026, 0, id), + }) as TaskDefinition; + +describe('TaskPlannerComponent target-grade filtering', () => { + it('shows tasks beyond the target grade only when the student opts in', () => { + const passTask = taskDefinition(1, 0); + const creditTask = taskDefinition(2, 1); + const component = Object.create(TaskPlannerComponent.prototype) as TaskPlannerComponent; + component.project = { + unit: {taskDefinitions: [passTask, creditTask]}, + findTaskForDefinition: () => null, + } as unknown as Project; + component.targetGrade = 0; + component.showTasksAboveTargetGrade = false; + + expect(component.taskDefs()).toEqual([passTask]); + + component.showTasksAboveTargetGrade = true; + + expect(component.taskDefs()).toEqual([passTask, creditTask]); + }); + + it('reveals an above-target task requested by a direct planner link', () => { + const passTask = taskDefinition(1, 0); + const creditTask = taskDefinition(2, 1); + const component = Object.create(TaskPlannerComponent.prototype) as TaskPlannerComponent; + component.project = { + id: 15, + unit: {taskDefinitions: [passTask, creditTask]}, + findTaskForDefinition: () => null, + } as unknown as Project; + component.targetGrade = 0; + component.showTasksAboveTargetGrade = false; + + const plannerInternals = component as unknown as { + revealRequestedTaskDefinition(taskDefinitionId: string | null): void; + }; + plannerInternals.revealRequestedTaskDefinition('2'); + + expect(component.showTasksAboveTargetGrade).toBe(true); + expect(component.taskDefs()).toEqual([passTask, creditTask]); + }); +}); diff --git a/src/app/projects/states/plan/task-planner/task-planner.component.ts b/src/app/projects/states/plan/task-planner/task-planner.component.ts index d44f3c6b4a..3ae4880e3a 100644 --- a/src/app/projects/states/plan/task-planner/task-planner.component.ts +++ b/src/app/projects/states/plan/task-planner/task-planner.component.ts @@ -71,15 +71,15 @@ export class TaskPlannerComponent implements OnInit, AfterViewInit, OnDestroy { public animateBackground: boolean = false; public showDatesColumn: boolean = false; - public hideTasksAboveTargetGrade: boolean = false; + public showTasksAboveTargetGrade: boolean = false; public overlayLines: boolean = false; public get unit() { return this.project?.unit; } - private get hideTasksAboveTargetGradeStorageKey(): string { - return `ontrack.taskPlanner.${this.project?.id ?? 'unknown'}.hideTasksAboveTargetGrade`; + private get showTasksAboveTargetGradeStorageKey(): string { + return `ontrack.taskPlanner.${this.project?.id ?? 'unknown'}.showTasksAboveTargetGrade`; } constructor( @@ -172,9 +172,12 @@ export class TaskPlannerComponent implements OnInit, AfterViewInit, OnDestroy { this.taskPlannerPrerequisitesModal.show(this.project, td, prereqs); } - setHideTasksAboveTargetGrade(value: boolean) { - this.hideTasksAboveTargetGrade = value; - localStorage.setItem(this.hideTasksAboveTargetGradeStorageKey, JSON.stringify(value)); + setShowTasksAboveTargetGrade(value: boolean) { + this.showTasksAboveTargetGrade = value; + this.preferenceStorage?.setItem( + this.showTasksAboveTargetGradeStorageKey, + JSON.stringify(value), + ); this.refreshItems(false); } @@ -570,7 +573,7 @@ export class TaskPlannerComponent implements OnInit, AfterViewInit, OnDestroy { } ngOnInit(): void { - this.loadHideTasksAboveTargetGradePreference(); + this.loadShowTasksAboveTargetGradePreference(); this.viewOptions = { precisionUnit: 'day', @@ -613,12 +616,12 @@ export class TaskPlannerComponent implements OnInit, AfterViewInit, OnDestroy { }); } - private loadHideTasksAboveTargetGradePreference(): void { - const rawPreference = localStorage.getItem(this.hideTasksAboveTargetGradeStorageKey); + private loadShowTasksAboveTargetGradePreference(): void { + const rawPreference = this.preferenceStorage?.getItem(this.showTasksAboveTargetGradeStorageKey); try { - this.hideTasksAboveTargetGrade = rawPreference ? JSON.parse(rawPreference) === true : false; + this.showTasksAboveTargetGrade = rawPreference ? JSON.parse(rawPreference) === true : false; } catch { - this.hideTasksAboveTargetGrade = false; + this.showTasksAboveTargetGrade = false; } } @@ -701,6 +704,11 @@ export class TaskPlannerComponent implements OnInit, AfterViewInit, OnDestroy { } refreshItems(scroll: boolean = true) { + const requestedTaskDefinitionId = scroll + ? this.route.snapshot.queryParamMap.get('taskDef') + : null; + this.revealRequestedTaskDefinition(requestedTaskDefinitionId); + this.taskPrerequisites = this.allTaskPrerequisites.filter((pre) => this.taskDefs().find((td) => td.id === pre.taskDefinitionId), ); @@ -813,9 +821,8 @@ export class TaskPlannerComponent implements OnInit, AfterViewInit, OnDestroy { this.ganttComponent.scrollToToday(); } - const taskDef = this.route.snapshot.queryParamMap.get('taskDef'); - if (taskDef && scroll) { - const taskItem = this.items.find((item) => item.id === taskDef); + if (requestedTaskDefinitionId) { + const taskItem = this.items.find((item) => item.id === requestedTaskDefinitionId); if (taskItem) { this.ganttComponent.scrollToDate(taskItem.start); taskItem.highlighted = true; @@ -849,7 +856,7 @@ export class TaskPlannerComponent implements OnInit, AfterViewInit, OnDestroy { return this.project.unit.taskDefinitions .filter( - (taskDef) => !this.hideTasksAboveTargetGrade || taskDef.targetGrade <= this.targetGrade, + (taskDef) => this.showTasksAboveTargetGrade || taskDef.targetGrade <= this.targetGrade, ) .sort((a, b) => { const taskA = this.project.findTaskForDefinition(a.id); @@ -861,4 +868,31 @@ export class TaskPlannerComponent implements OnInit, AfterViewInit, OnDestroy { return new Date(dateA).getTime() - new Date(dateB).getTime(); }); } + + private revealRequestedTaskDefinition(taskDefinitionId: string | null): void { + const requestedTaskDefinition = taskDefinitionId + ? this.project.unit.taskDefinitions.find( + (taskDefinition) => taskDefinition.id.toString() === taskDefinitionId, + ) + : null; + + if ( + requestedTaskDefinition?.targetGrade > this.targetGrade && + !this.showTasksAboveTargetGrade + ) { + this.showTasksAboveTargetGrade = true; + this.preferenceStorage?.setItem( + this.showTasksAboveTargetGradeStorageKey, + JSON.stringify(true), + ); + } + } + + private get preferenceStorage(): Storage | null { + try { + return globalThis.localStorage ?? null; + } catch { + return null; + } + } } diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index 3bde7ab01b..3bed31c8fd 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -167,10 +167,10 @@ <mat-checkbox color="primary" [disabled]="!project" - [ngModel]="viewPreferences.hideAboveTargetGrade" - (ngModelChange)="toggleHideAboveTargetGrade($event)" + [ngModel]="viewPreferences.showAboveTargetGrade" + (ngModelChange)="toggleShowAboveTargetGrade($event)" > - Hide tasks beyond target grade + Show tasks beyond target grade </mat-checkbox> </div> diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts index dad93b4165..31bdb21de8 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts @@ -1,8 +1,8 @@ import {beforeEach, describe, expect, it} from 'vitest'; -import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {NO_ERRORS_SCHEMA, SimpleChange} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {ActivatedRoute, Router} from '@angular/router'; -import {Task, TaskDefinition} from 'src/app/api/models/doubtfire-model'; +import {Project, Task, TaskDefinition} from 'src/app/api/models/doubtfire-model'; import {FUnitTaskListComponent} from './unit-task-list.component'; const emptyProvider = {}; @@ -11,6 +11,7 @@ const taskDefinition = ( id: number, abbreviation: string, startDate = new Date(2026, 0, id + 1), + targetGrade = 0, ): TaskDefinition => ({ id, @@ -18,6 +19,7 @@ const taskDefinition = ( abbreviation, name: abbreviation, startDate, + targetGrade, }) as TaskDefinition; const taskForDefinition = (definition: TaskDefinition, topWeight: number): Task => @@ -108,4 +110,78 @@ describe('FUnitTaskListComponent', () => { expect(component.filteredTaskDefinitions).toEqual([firstTask, secondTask, thirdTask]); }); + + it('shows only tasks at or below the project target grade by default', () => { + const passTask = taskDefinition(1, 'P1', undefined, 0); + const creditTask = taskDefinition(2, 'C1', undefined, 1); + const distinctionTask = taskDefinition(3, 'D1', undefined, 2); + component.project = { + id: 10, + targetGrade: 0, + unit: {id: 20}, + } as Project; + component.targetGrade = 0; + component.taskDefinitions = [passTask, creditTask, distinctionTask]; + component.tasks = []; + + component.applyFilters(); + + expect(component.filteredTaskDefinitions).toEqual([passTask]); + expect(component.activeViewPreferenceCount).toBe(0); + }); + + it('reveals tasks beyond the target grade only when explicitly selected', () => { + const passTask = taskDefinition(1, 'P1', undefined, 0); + const creditTask = taskDefinition(2, 'C1', undefined, 1); + component.project = { + id: 10, + targetGrade: 0, + unit: {id: 20}, + } as Project; + component.targetGrade = 0; + component.taskDefinitions = [passTask, creditTask]; + component.tasks = []; + + component.toggleShowAboveTargetGrade(true); + + expect(component.filteredTaskDefinitions).toEqual([passTask, creditTask]); + expect(component.activeViewPreferenceCount).toBe(1); + + component.resetViewPreferences(); + + expect(component.filteredTaskDefinitions).toEqual([passTask]); + expect(component.activeViewPreferenceCount).toBe(0); + }); + + it('reapplies target-grade filtering when the selected target changes', () => { + const passTask = taskDefinition(1, 'P1', undefined, 0); + const creditTask = taskDefinition(2, 'C1', undefined, 1); + component.project = { + id: 10, + targetGrade: 0, + unit: {id: 20}, + } as Project; + component.targetGrade = 0; + component.taskDefinitions = [passTask, creditTask]; + component.tasks = []; + component.applyFilters(); + + component.targetGrade = 1; + component.project.targetGrade = 1; + component.ngOnChanges({targetGrade: new SimpleChange(0, 1, false)}); + + expect(component.filteredTaskDefinitions).toEqual([passTask, creditTask]); + }); + + it('does not grade-filter an all-tasks list without a student project', () => { + const passTask = taskDefinition(1, 'P1', undefined, 0); + const distinctionTask = taskDefinition(2, 'D1', undefined, 2); + component.mode = 'all-tasks'; + component.taskDefinitions = [passTask, distinctionTask]; + component.tasks = []; + + component.applyFilters(); + + expect(component.filteredTaskDefinitions).toEqual([passTask, distinctionTask]); + }); }); diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index bfce70d27d..199223c0ea 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -20,7 +20,7 @@ interface TaskListViewPreferences { sortBy: TaskListSortOption; sortDirection: TaskListSortDirection; hideCompleted: boolean; - hideAboveTargetGrade: boolean; + showAboveTargetGrade: boolean; } interface TaskListSortOptionView { @@ -33,7 +33,7 @@ const DEFAULT_VIEW_PREFERENCES: TaskListViewPreferences = { sortBy: 'default', sortDirection: 'asc', hideCompleted: false, - hideAboveTargetGrade: false, + showAboveTargetGrade: false, }; const START_APPROACHING_DAYS = 7; @@ -48,6 +48,7 @@ const START_APPROACHING_DAYS = 7; export class FUnitTaskListComponent implements OnChanges, OnInit { @Input() mode: 'project' | 'all-tasks'; @Input() project: Project; + @Input() targetGrade: number; @Input() taskDefinitions: readonly TaskDefinition[]; @Input() tasks: readonly Task[]; @Input() isCollapsed = false; @@ -99,6 +100,14 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { this.filteredTaskDefinitions = matchingTaskDefinitions .filter((taskDef) => this.shouldShowTaskDefinition(taskDef)) .sort((a, b) => this.compareTaskDefinitions(a, b)); + + if ( + this.selectedTaskDef && + !this.filteredTaskDefinitions.some((taskDef) => taskDef.id === this.selectedTaskDef.id) + ) { + this.selectedTaskDefinition$?.next(null); + this.replaceSelectionUrl(null); + } } public setSortBy(sortBy: TaskListSortOption): void { @@ -127,10 +136,10 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { this.applyFilters(); } - public toggleHideAboveTargetGrade(value: boolean): void { + public toggleShowAboveTargetGrade(value: boolean): void { this.viewPreferences = { ...this.viewPreferences, - hideAboveTargetGrade: value, + showAboveTargetGrade: value, }; this.persistViewPreferences(); this.applyFilters(); @@ -170,7 +179,7 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { return ( (this.viewPreferences.sortBy !== 'default' ? 1 : 0) + (this.viewPreferences.hideCompleted ? 1 : 0) + - (this.viewPreferences.hideAboveTargetGrade ? 1 : 0) + (this.viewPreferences.showAboveTargetGrade ? 1 : 0) ); } @@ -179,15 +188,13 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { this.loadViewPreferences(); } - if ('project' in changes || 'taskDefinitions' in changes || 'tasks' in changes) { + if ( + 'project' in changes || + 'targetGrade' in changes || + 'taskDefinitions' in changes || + 'tasks' in changes + ) { this.applyFilters(); - - if ( - this.selectedTaskDef && - !this.filteredTaskDefinitions?.some((taskDef) => taskDef.id === this.selectedTaskDef.id) - ) { - this.selectedTaskDefinition$.next(null); - } } } @@ -275,6 +282,12 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { if (param) { const taskDef = this.taskDefinitions.find((t) => t.abbreviation === param); + if (taskDef && this.isTaskDefinitionAboveTargetGrade(taskDef)) { + this.viewPreferences = {...this.viewPreferences, showAboveTargetGrade: true}; + this.persistViewPreferences(); + this.applyFilters(); + } + if (taskDef !== current) { this.selectedTaskDefinition$.next(taskDef); } @@ -354,10 +367,18 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { } return !( - this.viewPreferences.hideAboveTargetGrade && - this.project?.targetGrade !== undefined && - this.project?.targetGrade !== null && - taskDef.targetGrade > this.project.targetGrade + !this.viewPreferences.showAboveTargetGrade && this.isTaskDefinitionAboveTargetGrade(taskDef) + ); + } + + private isTaskDefinitionAboveTargetGrade(taskDef: TaskDefinition): boolean { + const targetGrade = this.targetGrade ?? this.project?.targetGrade; + + return ( + !!this.project && + targetGrade !== undefined && + targetGrade !== null && + taskDef.targetGrade > targetGrade ); } @@ -434,7 +455,7 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { } private loadViewPreferences(): void { - const rawPreferences = localStorage.getItem(this.viewPreferencesStorageKey); + const rawPreferences = this.viewPreferencesStorage?.getItem(this.viewPreferencesStorageKey); if (!rawPreferences) { this.viewPreferences = {...DEFAULT_VIEW_PREFERENCES}; @@ -450,7 +471,9 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { ? parsedPreferences.sortDirection : migratedSort.sortDirection, hideCompleted: !!parsedPreferences.hideCompleted, - hideAboveTargetGrade: !!parsedPreferences.hideAboveTargetGrade, + // The legacy preference was named `hideAboveTargetGrade` and defaulted to false, + // which made higher-grade tasks visible. Treat legacy records as the new default. + showAboveTargetGrade: parsedPreferences.showAboveTargetGrade === true, }; } catch { this.viewPreferences = {...DEFAULT_VIEW_PREFERENCES}; @@ -458,7 +481,10 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { } private persistViewPreferences(): void { - localStorage.setItem(this.viewPreferencesStorageKey, JSON.stringify(this.viewPreferences)); + this.viewPreferencesStorage?.setItem( + this.viewPreferencesStorageKey, + JSON.stringify(this.viewPreferences), + ); } private isSortOption(value: unknown): value is TaskListSortOption { @@ -502,4 +528,12 @@ export class FUnitTaskListComponent implements OnChanges, OnInit { const unitId = this.project?.unit?.id ?? this.taskDefinitions?.[0]?.unit?.id ?? 'unknown'; return `ontrack.unitTaskList.${unitId}.viewPreferences`; } + + private get viewPreferencesStorage(): Storage | null { + try { + return globalThis.localStorage ?? null; + } catch { + return null; + } + } } From 27a07c4e255d1e81035f67aff068834b5084333f Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sat, 22 Aug 2026 21:24:14 +1000 Subject: [PATCH 1393/1531] fix(dashboard): refresh reused project routes --- .../progress-dashboard.component.spec.ts | 50 +++++ .../progress-dashboard.component.ts | 18 +- .../project-dashboard.component.spec.ts | 183 ++++++++++++++++++ .../project-dashboard.component.ts | 90 ++++++--- .../project-root-state.component.spec.ts | 24 +++ .../states/project-root-state.component.ts | 9 +- .../progress-burndown-chart.component.spec.ts | 23 +++ .../progress-burndown-chart.component.ts | 6 +- .../task-visualisation.component.spec.ts | 27 +++ .../task-visualisation.component.ts | 5 +- 10 files changed, 407 insertions(+), 28 deletions(-) create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts create mode 100644 src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts create mode 100644 src/app/projects/states/project-root-state.component.spec.ts create mode 100644 src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts create mode 100644 src/app/visualisations/task-visualisation/task-visualisation.component.spec.ts diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts new file mode 100644 index 0000000000..100d101440 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts @@ -0,0 +1,50 @@ +import {describe, expect, it, vi} from 'vitest'; +import {SimpleChange} from '@angular/core'; +import {Project} from 'src/app/api/models/project'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GradeService} from 'src/app/common/services/grade.service'; +import {ProgressDashboardComponent} from './progress-dashboard.component'; + +describe('ProgressDashboardComponent route reuse', () => { + it('refreshes summary data when the active project changes', () => { + const gradeValuesFor = vi.fn(() => [0]); + const component = new ProgressDashboardComponent( + { + grades: {0: 'Pass'}, + gradeValues: [0], + gradeValuesFor, + } as unknown as GradeService, + {} as ProjectService, + {} as AlertService, + {} as UserService, + ); + const firstProject = { + id: 2, + targetGrade: 0, + unit: {gradeDefinitions: [{value: 0, label: 'Pass'}]}, + numberTasks: vi.fn(() => 1), + activeTasks: vi.fn(() => [{}, {}, {}]), + refreshBurndownChartData: vi.fn(), + } as unknown as Project; + const nextProject = { + id: 18, + targetGrade: 0, + unit: {gradeDefinitions: [{value: 0, label: 'Pass'}]}, + numberTasks: vi.fn(() => 2), + activeTasks: vi.fn(() => [{}, {}, {}, {}]), + refreshBurndownChartData: vi.fn(), + } as unknown as Project; + component.project = firstProject; + component.ngOnInit(); + vi.clearAllMocks(); + + component.project = nextProject; + component.ngOnChanges({project: new SimpleChange(firstProject, nextProject, false)}); + + expect(gradeValuesFor).toHaveBeenCalledWith(nextProject.unit); + expect(component.numberOfTasks).toEqual({completed: 2, remaining: 2}); + expect(nextProject.refreshBurndownChartData).toHaveBeenCalled(); + }); +}); diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts index 7cb2445c90..4ddfc832d5 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts @@ -3,8 +3,10 @@ import { Component, EventEmitter, Input, + OnChanges, OnInit, Output, + SimpleChanges, } from '@angular/core'; import {Project} from 'src/app/api/models/project'; import {ProjectService} from 'src/app/api/services/project.service'; @@ -19,7 +21,7 @@ import {GradeService} from 'src/app/common/services/grade.service'; changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) -export class ProgressDashboardComponent implements OnInit { +export class ProgressDashboardComponent implements OnChanges, OnInit { @Input() project: Project; @Input() showSubmittedGrade?: boolean = false; @Output() doUpdateTargetGrade: EventEmitter<void> = new EventEmitter(); @@ -41,6 +43,20 @@ export class ProgressDashboardComponent implements OnInit { ) {} ngOnInit(): void { + this.refreshProjectSummary(); + } + + ngOnChanges(changes: SimpleChanges): void { + if ('project' in changes && !changes.project.firstChange) { + this.refreshProjectSummary(); + } + } + + private refreshProjectSummary(): void { + if (!this.project?.unit) { + return; + } + this.grades.values = this.gradeService.gradeValuesFor(this.project.unit); this.grades.names = Object.fromEntries( this.project.unit.gradeDefinitions.map((definition) => [definition.value, definition.label]), diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts new file mode 100644 index 0000000000..004fb35a74 --- /dev/null +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts @@ -0,0 +1,183 @@ +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {BreakpointObserver} from '@angular/cdk/layout'; +import {ActivatedRoute, convertToParamMap} from '@angular/router'; +import {BehaviorSubject, Subject, of, tap} from 'rxjs'; +import {Project, TaskDefinition, Unit} from 'src/app/api/models/doubtfire-model'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {UnitService} from 'src/app/api/services/unit.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {GlobalStateService, ViewType} from '../../index/global-state.service'; +import {ProjectDashboardComponent} from './project-dashboard.component'; + +describe('ProjectDashboardComponent route reuse', () => { + let firstProject: Project; + let secondProject: Project; + let firstUnit: Unit; + let secondUnit: Unit; + + beforeEach(() => { + firstUnit = { + id: 101, + taskDefinitions: [], + studentCache: {add: vi.fn()}, + } as unknown as Unit; + secondUnit = { + id: 202, + taskDefinitions: [], + studentCache: {add: vi.fn()}, + } as unknown as Unit; + firstProject = {id: 2, targetGrade: 0, unit: firstUnit} as Project; + secondProject = {id: 18, targetGrade: 0, unit: secondUnit} as Project; + }); + + it('loads and displays each project emitted by a reused parent route', () => { + const routeProjects: BehaviorSubject<Project> = new BehaviorSubject(firstProject); + const loadedProjects = new Map([ + [firstProject.id, firstProject], + [secondProject.id, secondProject], + ]); + const loadedUnits = new Map([ + [firstUnit.id, firstUnit], + [secondUnit.id, secondUnit], + ]); + const projectGet = vi.fn( + (params: {id: number}, options: {mappingCompleteCallback: (project: Project) => void}) => { + const project = loadedProjects.get(params.id); + options.mappingCompleteCallback(project); + return of(project); + }, + ); + const unitGet = vi.fn((id: number) => of(loadedUnits.get(id))); + const setView = vi.fn(); + const component = new ProjectDashboardComponent( + {} as UserService, + {get: projectGet} as unknown as ProjectService, + {get: unitGet} as unknown as UnitService, + {setView} as unknown as GlobalStateService, + { + parent: { + data: of({project: firstProject}), + snapshot: {paramMap: convertToParamMap({projectId: firstProject.id})}, + }, + } as unknown as ActivatedRoute, + {observe: () => of({matches: false, breakpoints: {}})} as unknown as BreakpointObserver, + ); + component.project$ = routeProjects.asObservable(); + + component.ngOnInit(); + component.selectedTaskDefinition$.next({id: 999} as TaskDefinition); + routeProjects.next(secondProject); + + let displayedProject: Project; + component.project$.subscribe((project) => (displayedProject = project)); + + expect(projectGet.mock.calls.map(([params]) => params.id)).toEqual([2, 18]); + expect(unitGet.mock.calls.map(([id]) => id)).toEqual([101, 202]); + expect(displayedProject.id).toBe(18); + expect(component.selectedTaskDefinition$.value).toBeNull(); + expect(setView).toHaveBeenLastCalledWith(ViewType.PROJECT, secondProject); + + component.ngOnDestroy(); + }); + + it('ignores a delayed response from an earlier visit to the same project', () => { + const routeProjects: BehaviorSubject<Project> = new BehaviorSubject(firstProject); + const projectResponses: Subject<Project>[] = []; + const projectGet = vi.fn( + (_params: {id: number}, options: {mappingCompleteCallback: (project: Project) => void}) => { + const response: Subject<Project> = new Subject(); + projectResponses.push(response); + return response.pipe(tap((project) => options.mappingCompleteCallback(project))); + }, + ); + const oldUnit = {...firstUnit, id: 301} as Unit; + const latestUnit = {...firstUnit, id: 303} as Unit; + const oldProject = {id: firstProject.id, targetGrade: 0, unit: oldUnit} as Project; + const latestProject = {id: firstProject.id, targetGrade: 0, unit: latestUnit} as Project; + const unitGet = vi.fn((id: number) => of(id === latestUnit.id ? latestUnit : oldUnit)); + const component = new ProjectDashboardComponent( + {} as UserService, + {get: projectGet} as unknown as ProjectService, + {get: unitGet} as unknown as UnitService, + {setView: vi.fn()} as unknown as GlobalStateService, + { + parent: { + data: of({project: firstProject}), + snapshot: {paramMap: convertToParamMap({projectId: firstProject.id})}, + }, + } as unknown as ActivatedRoute, + {observe: () => of({matches: false, breakpoints: {}})} as unknown as BreakpointObserver, + ); + component.project$ = routeProjects.asObservable(); + + component.ngOnInit(); + routeProjects.next(secondProject); + routeProjects.next({...firstProject} as Project); + projectResponses[2].next(latestProject); + projectResponses[0].next(oldProject); + + let displayedProject: Project; + component.project$.subscribe((project) => (displayedProject = project)); + + expect(displayedProject).toBe(latestProject); + expect(unitGet).toHaveBeenCalledTimes(1); + expect(unitGet).toHaveBeenCalledWith(latestUnit.id); + + component.ngOnDestroy(); + }); + + it('cancels a pending unit load when a reused route changes projects', () => { + const routeProjects: BehaviorSubject<Project> = new BehaviorSubject(firstProject); + const oldUnitResponse: Subject<Unit> = new Subject(); + const delayedOldUnit = { + ...firstUnit, + studentCache: {add: vi.fn()}, + } as unknown as Unit; + const latestUnit = {...firstUnit, id: 303} as Unit; + const oldProject = {id: firstProject.id, targetGrade: 0, unit: firstUnit} as Project; + const latestProject = {id: firstProject.id, targetGrade: 0, unit: latestUnit} as Project; + const loadedProjects = [oldProject, secondProject, latestProject]; + let projectLoad = 0; + const projectGet = vi.fn( + (_params: {id: number}, options: {mappingCompleteCallback: (project: Project) => void}) => { + const project = loadedProjects[projectLoad++]; + options.mappingCompleteCallback(project); + return of(project); + }, + ); + const unitGet = vi.fn((id: number) => { + if (id === firstUnit.id) { + return oldUnitResponse; + } + return of(id === secondUnit.id ? secondUnit : latestUnit); + }); + const component = new ProjectDashboardComponent( + {} as UserService, + {get: projectGet} as unknown as ProjectService, + {get: unitGet} as unknown as UnitService, + {setView: vi.fn()} as unknown as GlobalStateService, + { + parent: { + data: of({project: firstProject}), + snapshot: {paramMap: convertToParamMap({projectId: firstProject.id})}, + }, + } as unknown as ActivatedRoute, + {observe: () => of({matches: false, breakpoints: {}})} as unknown as BreakpointObserver, + ); + component.project$ = routeProjects.asObservable(); + + component.ngOnInit(); + routeProjects.next(secondProject); + routeProjects.next({...firstProject} as Project); + oldUnitResponse.next(delayedOldUnit); + + let displayedProject: Project; + component.project$.subscribe((project) => (displayedProject = project)); + + expect(displayedProject).toBe(latestProject); + expect(oldProject.unit).toBe(firstUnit); + expect(delayedOldUnit.studentCache.add).not.toHaveBeenCalled(); + + component.ngOnDestroy(); + }); +}); diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts index 2a1fd23b73..03f2a15341 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts @@ -11,7 +11,7 @@ import { Output, } from '@angular/core'; import {ActivatedRoute} from '@angular/router'; -import {BehaviorSubject, Observable, Subject, first, of, takeUntil} from 'rxjs'; +import {BehaviorSubject, Observable, Subject, filter, map, of, takeUntil} from 'rxjs'; import {Project, TaskDefinition} from 'src/app/api/models/doubtfire-model'; import {ProjectService} from 'src/app/api/services/project.service'; import {UnitService} from 'src/app/api/services/unit.service'; @@ -50,7 +50,10 @@ export class ProjectDashboardComponent implements OnInit, OnDestroy { private readonly projectSubject: BehaviorSubject<Project> = new BehaviorSubject(null); private readonly destroy$: Subject<void> = new Subject(); + private readonly projectLoadCancel$: Subject<void> = new Subject(); private projectReady = false; + private activeProjectId: number | null = null; + private projectActivation = 0; projectTasks = []; @@ -154,20 +157,28 @@ export class ProjectDashboardComponent implements OnInit, OnDestroy { } const initialProject$ = - this.project$ ?? of(this.route.parent?.snapshot.data.project as Project); + this.project$ ?? + this.route.parent.data.pipe( + map((data) => data.project as Project), + filter((project): project is Project => !!project), + ); this.project$ = this.projectSubject.asObservable(); - initialProject$.pipe(first()).subscribe((project) => { - this.projectSubject.next(project); - this.loadProject( - project?.id ?? Number(this.route.parent?.snapshot.paramMap.get('projectId')), + initialProject$ + .pipe(takeUntil(this.destroy$)) + .subscribe((project) => + this.activateProject( + project, + project?.id ?? Number(this.route.parent?.snapshot.paramMap.get('projectId')), + ), ); - }); window.dispatchEvent(new Event('resize')); } ngOnDestroy(): void { document.body.classList.remove('split-pane-resizing'); + this.projectLoadCancel$.next(); + this.projectLoadCancel$.complete(); this.destroy$.next(); this.destroy$.complete(); } @@ -177,7 +188,26 @@ export class ProjectDashboardComponent implements OnInit, OnDestroy { window.dispatchEvent(new Event('resize')); } - private loadProject(projectId: number): void { + private activateProject(project: Project, projectId: number): void { + if (!projectId) { + return; + } + + this.projectLoadCancel$.next(); + const activation = ++this.projectActivation; + this.activeProjectId = projectId; + this.projectReady = false; + this.selectedTaskDefinition$.next(null); + this.projectSubject.next(project); + + if (project?.unit?.id) { + this.globalStateService.setView(ViewType.PROJECT, project); + } + + this.loadProject(projectId, activation); + } + + private loadProject(projectId: number, activation: number): void { if (!projectId) { return; } @@ -187,32 +217,48 @@ export class ProjectDashboardComponent implements OnInit, OnDestroy { {id: projectId}, { cacheBehaviourOnGet: 'cacheQuery', - mappingCompleteCallback: (project: Project) => this.loadUnit(project), + mappingCompleteCallback: (project: Project) => { + if (activation === this.projectActivation && project.id === this.activeProjectId) { + this.loadUnit(project, activation); + } + }, }, ) + .pipe(takeUntil(this.projectLoadCancel$), takeUntil(this.destroy$)) .subscribe(); } - private loadUnit(project: Project): void { + private loadUnit(project: Project, activation: number): void { const unitId = project.unit?.id; if (!unitId) { - this.showLoadedProject(project); + this.showLoadedProject(project, activation); return; } - this.unitService.get(unitId).subscribe({ - next: (unit) => { - project.unit = unit; - unit.studentCache.add(project); - this.showLoadedProject(project); - }, - error: () => { - this.showLoadedProject(project); - }, - }); + this.unitService + .get(unitId) + .pipe(takeUntil(this.projectLoadCancel$), takeUntil(this.destroy$)) + .subscribe({ + next: (unit) => { + if (activation !== this.projectActivation || project.id !== this.activeProjectId) { + return; + } + + project.unit = unit; + unit.studentCache.add(project); + this.showLoadedProject(project, activation); + }, + error: () => { + this.showLoadedProject(project, activation); + }, + }); } - private showLoadedProject(project: Project): void { + private showLoadedProject(project: Project, activation: number): void { + if (activation !== this.projectActivation || project.id !== this.activeProjectId) { + return; + } + this.projectReady = true; this.globalStateService.setView(ViewType.PROJECT, project); this.projectSubject.next(project); diff --git a/src/app/projects/states/project-root-state.component.spec.ts b/src/app/projects/states/project-root-state.component.spec.ts new file mode 100644 index 0000000000..d31cfd7740 --- /dev/null +++ b/src/app/projects/states/project-root-state.component.spec.ts @@ -0,0 +1,24 @@ +import {describe, expect, it} from 'vitest'; +import {ActivatedRoute, Data} from '@angular/router'; +import {BehaviorSubject} from 'rxjs'; +import {Project} from 'src/app/api/models/doubtfire-model'; +import {ProjectRootStateComponent} from './project-root-state.component'; + +describe('ProjectRootStateComponent', () => { + it('passes project resolver updates to a reused child route', () => { + const firstProject = {id: 2} as Project; + const secondProject = {id: 18} as Project; + const routeData: BehaviorSubject<Data> = new BehaviorSubject({project: firstProject}); + const component = new ProjectRootStateComponent({ + data: routeData.asObservable(), + } as ActivatedRoute); + const child: {project$?: typeof component.project$} = {project$: undefined}; + const projectIds: number[] = []; + + component.onActivate(child); + child.project$.subscribe((project) => projectIds.push(project.id)); + routeData.next({project: secondProject}); + + expect(projectIds).toEqual([2, 18]); + }); +}); diff --git a/src/app/projects/states/project-root-state.component.ts b/src/app/projects/states/project-root-state.component.ts index a9d436dde3..908cfd6f21 100644 --- a/src/app/projects/states/project-root-state.component.ts +++ b/src/app/projects/states/project-root-state.component.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; -import {Observable, Subscription, of} from 'rxjs'; +import {Observable, Subscription, filter, map, shareReplay} from 'rxjs'; import {Project} from 'src/app/api/models/doubtfire-model'; interface ProjectRouteChild { @@ -25,8 +25,11 @@ export class ProjectRootStateComponent implements OnDestroy { private taskListWidthSub?: Subscription; constructor(private activatedRoute: ActivatedRoute) { - const project = this.activatedRoute.snapshot.data.project as Project; - this.project$ = this.project$ ?? (project ? of(project) : undefined); + this.project$ = this.activatedRoute.data.pipe( + map((data) => data.project as Project), + filter((project): project is Project => !!project), + shareReplay({bufferSize: 1, refCount: true}), + ); } onActivate(component: ProjectRouteChild): void { diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts new file mode 100644 index 0000000000..d7a0f864cb --- /dev/null +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts @@ -0,0 +1,23 @@ +import {describe, expect, it, vi} from 'vitest'; +import {SimpleChange} from '@angular/core'; +import {Project} from 'src/app/api/models/doubtfire-model'; +import {ProgressBurndownChartComponent} from './progress-burndown-chart.component'; + +describe('ProgressBurndownChartComponent route reuse', () => { + it('refreshes chart data for a different project at the same grade', () => { + const previousProject = {id: 2} as Project; + const refreshBurndownChartData = vi.fn(); + const nextProject = {id: 18, refreshBurndownChartData} as unknown as Project; + const component = Object.create( + ProgressBurndownChartComponent.prototype, + ) as ProgressBurndownChartComponent; + component.project = nextProject; + component.grade = 0; + const updateData = vi.spyOn(component, 'updateData').mockImplementation(() => undefined); + + component.ngOnChanges({project: new SimpleChange(previousProject, nextProject, false)}); + + expect(refreshBurndownChartData).toHaveBeenCalled(); + expect(updateData).toHaveBeenCalled(); + }); +}); diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts index ef0f238404..ed0bfb1947 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts @@ -79,7 +79,11 @@ export class ProgressBurndownChartComponent } ngOnChanges(changes: SimpleChanges): void { - if ('grade' in changes && changes.grade.currentValue !== undefined) { + const projectChanged = 'project' in changes && !changes.project.firstChange; + const unitChanged = 'unit' in changes && !changes.unit.firstChange; + const gradeChanged = 'grade' in changes && changes.grade.currentValue !== undefined; + + if (this.project && (projectChanged || unitChanged || gradeChanged)) { this.project.refreshBurndownChartData(); this.updateData(); } diff --git a/src/app/visualisations/task-visualisation/task-visualisation.component.spec.ts b/src/app/visualisations/task-visualisation/task-visualisation.component.spec.ts new file mode 100644 index 0000000000..cf6d89f9dc --- /dev/null +++ b/src/app/visualisations/task-visualisation/task-visualisation.component.spec.ts @@ -0,0 +1,27 @@ +import {describe, expect, it} from 'vitest'; +import {SimpleChange} from '@angular/core'; +import {Project} from 'src/app/api/models/doubtfire-model'; +import {TaskVisualisationComponent} from './task-visualisation.component'; + +describe('TaskVisualisationComponent route reuse', () => { + it('updates counts for a different project at the same grade', () => { + const firstProject = { + id: 2, + activeTasks: () => [{status: 'complete'}], + } as unknown as Project; + const nextProject = { + id: 18, + activeTasks: () => [{status: 'ready_for_feedback'}], + } as unknown as Project; + const component = new TaskVisualisationComponent(); + component.project = firstProject; + component.grade = 0; + component.ngOnInit(); + + component.project = nextProject; + component.ngOnChanges({project: new SimpleChange(firstProject, nextProject, false)}); + + expect(component.data.find(({name}) => name === 'Awaiting Feedback')?.value).toBe(1); + expect(component.data.find(({name}) => name === 'Complete')?.value).toBe(0); + }); +}); diff --git a/src/app/visualisations/task-visualisation/task-visualisation.component.ts b/src/app/visualisations/task-visualisation/task-visualisation.component.ts index ba1dc1a54e..45effd1829 100644 --- a/src/app/visualisations/task-visualisation/task-visualisation.component.ts +++ b/src/app/visualisations/task-visualisation/task-visualisation.component.ts @@ -31,7 +31,10 @@ export class TaskVisualisationComponent implements OnChanges, OnInit { } ngOnChanges(changes: SimpleChanges): void { - if ('grade' in changes && changes.grade.currentValue !== undefined) { + const projectChanged = 'project' in changes && !changes.project.firstChange; + const gradeChanged = 'grade' in changes && changes.grade.currentValue !== undefined; + + if (projectChanged || gradeChanged) { this.updateData(); } } From 4e2afc876db90c8da0895fc36c0f02b7349e8a96 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sat, 22 Aug 2026 21:25:04 +1000 Subject: [PATCH 1394/1531] fix(dashboard): prevent visualisation clipping --- .../progress-dashboard.component.html | 11 ++-- .../progress-dashboard.component.spec.ts | 63 ++++++++++++++++++ .../progress-burndown-chart.component.html | 24 ++++++- .../progress-burndown-chart.component.scss | 52 +++++++++++++++ .../progress-burndown-chart.component.spec.ts | 41 ++++++++++++ .../progress-burndown-chart.component.ts | 44 +++++++------ .../task-visualisation.component.html | 21 ++++-- .../task-visualisation.component.scss | 27 ++++++++ .../task-visualisation.component.spec.ts | 33 ++++++++++ .../task-visualisation.component.ts | 65 +++++++++++-------- 10 files changed, 320 insertions(+), 61 deletions(-) create mode 100644 src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts create mode 100644 src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts create mode 100644 src/app/visualisations/task-visualisation/task-visualisation.component.spec.ts diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html index dfc62a5318..29d404168b 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html @@ -97,16 +97,16 @@ <h4 class="py-3.5 font-semibold text-gray-800"> </div> <div class="grid grid-cols-1 items-stretch gap-3.5 xl:col-span-2 xl:grid-cols-2"> - <mat-card appearance="outlined" class="max-h-[600px]"> + <mat-card appearance="outlined" class="h-full min-w-0"> <mat-card-header> <mat-card-title>Progress Burndown</mat-card-title> <mat-card-subtitle> The burndown chart shows how much work remains for you to achieve your target grade. </mat-card-subtitle> </mat-card-header> - <mat-card-content class="overflow-hidden"> + <mat-card-content class="min-w-0"> <f-progress-burndown-chart - class="block" + class="block min-w-0" [grade]="project.targetGrade" [project]="project" [unit]="project.unit" @@ -121,13 +121,14 @@ <h4 class="py-3.5 font-semibold text-gray-800"> </mat-card-content> </mat-card> - <mat-card appearance="outlined" class="max-h-[600px]"> + <mat-card appearance="outlined" class="h-full min-w-0"> <mat-card-header> <mat-card-title>Task Statuses</mat-card-title> <mat-card-subtitle>Breakdown summary of each of your task statuses</mat-card-subtitle> </mat-card-header> - <mat-card-content> + <mat-card-content class="min-w-0"> <f-task-visualisation + class="block min-w-0" [grade]="project.targetGrade" [project]="project" ></f-task-visualisation> diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts new file mode 100644 index 0000000000..d44793ce09 --- /dev/null +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts @@ -0,0 +1,63 @@ +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {Project} from 'src/app/api/models/project'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GradeService} from 'src/app/common/services/grade.service'; +import {ProgressDashboardComponent} from './progress-dashboard.component'; + +describe('ProgressDashboardComponent', () => { + let fixture: ComponentFixture<ProgressDashboardComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ProgressDashboardComponent], + providers: [ + { + provide: GradeService, + useValue: { + grades: {0: 'Pass'}, + gradeValues: [0], + gradeValuesFor: () => [0], + }, + }, + {provide: ProjectService, useValue: {update: vi.fn()}}, + {provide: AlertService, useValue: {success: vi.fn(), error: vi.fn()}}, + {provide: UserService, useValue: {currentUser: {id: 25}}}, + ], + schemas: [NO_ERRORS_SCHEMA], + }).compileComponents(); + + fixture = TestBed.createComponent(ProgressDashboardComponent); + fixture.componentInstance.project = { + id: 18, + targetGrade: 0, + unit: { + myRole: 'Student', + gradeDefinitions: [{value: 0, label: 'Pass'}], + }, + numberTasks: vi.fn().mockReturnValue(0), + activeTasks: vi.fn().mockReturnValue([]), + refreshBurndownChartData: vi.fn(), + } as unknown as Project; + fixture.detectChanges(); + }); + + it('does not cap or clip the burndown and status cards', () => { + const host = fixture.nativeElement as HTMLElement; + const cardTitles = Array.from(host.querySelectorAll<HTMLElement>('mat-card-title')); + const burndownCard = cardTitles + .find((title) => title.textContent.trim() === 'Progress Burndown') + ?.closest('mat-card'); + const statusCard = cardTitles + .find((title) => title.textContent.trim() === 'Task Statuses') + ?.closest('mat-card'); + const burndownContent = burndownCard?.querySelector('mat-card-content'); + + expect(burndownCard?.classList.contains('max-h-[600px]')).toBe(false); + expect(statusCard?.classList.contains('max-h-[600px]')).toBe(false); + expect(burndownContent?.classList.contains('overflow-hidden')).toBe(false); + }); +}); diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index e13b7c4048..a72d4a8e08 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -1,9 +1,7 @@ -<div class="chart-container flex h-full min-h-[320px] pb-6"> +<div class="chart-container flex min-w-0"> <ngx-charts-line-chart class="progress-burndown-chart h-full flex-1" [legend]="legend" - [legendPosition]="legendPosition" - [legendTitle]="''" [results]="data" [scheme]="colorScheme" [showXAxisLabel]="showXAxisLabel" @@ -21,3 +19,23 @@ > </ngx-charts-line-chart> </div> + +@if (temp.length > 0) { + <div aria-label="Burndown chart series" class="burndown-legend" role="group"> + @for (series of temp; track series.name; let index = $index) { + <button + class="burndown-legend-button" + type="button" + [attr.aria-pressed]="isDataShown(series.name)" + (click)="toggleSeries(series.name)" + > + <span + aria-hidden="true" + class="burndown-legend-swatch" + [style.background-color]="seriesColor(index)" + ></span> + <span>{{ series.name }}</span> + </button> + } + </div> +} diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.scss b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.scss index e69de29bb2..1a4ae267c4 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.scss +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.scss @@ -0,0 +1,52 @@ +:host { + display: block; + min-width: 0; +} + +.chart-container { + height: clamp(24rem, 40vw, 32rem); + min-width: 0; +} + +.burndown-legend { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.5rem; + padding: 0.75rem 0.5rem 0.5rem; +} + +.burndown-legend-button { + display: inline-flex; + align-items: center; + gap: 0.5rem; + border: 1px solid #d1d5db; + border-radius: 9999px; + background: #ffffff; + color: #374151; + cursor: pointer; + font: inherit; + padding: 0.375rem 0.75rem; +} + +.burndown-legend-button:hover { + background: #f9fafb; +} + +.burndown-legend-button:focus-visible { + outline: 2px solid #3b82f6; + outline-offset: 2px; +} + +.burndown-legend-button[aria-pressed='false'] { + opacity: 0.55; + text-decoration: line-through; +} + +.burndown-legend-swatch { + width: 0.75rem; + height: 0.75rem; + flex: 0 0 auto; + border: 1px solid rgb(17 24 39 / 20%); + border-radius: 9999px; +} diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts new file mode 100644 index 0000000000..471478878a --- /dev/null +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts @@ -0,0 +1,41 @@ +import {describe, expect, it, vi} from 'vitest'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {TestBed} from '@angular/core/testing'; +import {Project, Unit} from 'src/app/api/models/doubtfire-model'; +import {ProgressBurndownChartComponent} from './progress-burndown-chart.component'; + +describe('ProgressBurndownChartComponent', () => { + it('renders keyboard-accessible series controls outside the measured chart area', async () => { + await TestBed.configureTestingModule({ + declarations: [ProgressBurndownChartComponent], + schemas: [NO_ERRORS_SCHEMA], + }).compileComponents(); + const fixture = TestBed.createComponent(ProgressBurndownChartComponent); + const component = fixture.componentInstance; + const series = {name: 'Complete', series: [{name: '1 Jan', value: 50}]}; + component.project = {refreshBurndownChartData: vi.fn()} as unknown as Project; + component.unit = {} as Unit; + component.data = [series]; + component.temp = [series]; + vi.spyOn(component, 'updateData').mockImplementation(() => undefined); + + fixture.detectChanges(); + + const host = fixture.nativeElement as HTMLElement; + const chart = host.querySelector('.chart-container') as HTMLElement; + const legend = host.querySelector('.burndown-legend') as HTMLElement; + const button = legend.querySelector('button') as HTMLButtonElement; + + expect(legend).not.toBeNull(); + expect(chart.contains(legend)).toBe(false); + expect(button.type).toBe('button'); + expect(button.textContent).toContain('Complete'); + expect(button.getAttribute('aria-pressed')).toBe('true'); + + button.click(); + fixture.detectChanges(); + + expect(button.getAttribute('aria-pressed')).toBe('false'); + expect(component.data[0].series[0].value).toBe(0); + }); +}); diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts index ef0f238404..cc50f2dc77 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts @@ -1,4 +1,4 @@ -import {Color, LegendPosition, ScaleType} from '@swimlane/ngx-charts'; +import {Color, ScaleType} from '@swimlane/ngx-charts'; import {formatDate} from '@angular/common'; import { ChangeDetectionStrategy, @@ -43,7 +43,7 @@ export class ProgressBurndownChartComponent temp: BurndownSeries[] = []; // options - legend: boolean = true; + legend: boolean = false; showLabels: boolean = true; animations: boolean = true; xAxis: boolean = true; @@ -52,7 +52,6 @@ export class ProgressBurndownChartComponent showXAxisLabel: boolean = true; xAxisLabel: string = 'Time'; yAxisLabel: string = 'Tasks Remaining'; - legendPosition: LegendPosition = LegendPosition.Below; colorScheme: Color = { name: 'Burndown', selectable: true, @@ -132,35 +131,40 @@ export class ProgressBurndownChartComponent this.temp = JSON.parse(JSON.stringify(formattedData)); this.data = formattedData; + this.seriesVisibility = Object.fromEntries(formattedData.map((series) => [series.name, true])); } onSelect(event: string | BurndownPoint): void { if (this.isLegend(event)) { - const tempData = JSON.parse(JSON.stringify(this.data)); - if (this.isDataShown(event)) { - tempData.forEach((series) => { - if (series.name === event) { - series.series.forEach((point) => (point.value = 0)); - } - }); - } else { - const originalSeries = this.temp.find((series) => series.name === event); - const seriesIndex = tempData.findIndex((series) => series.name === event); - if (seriesIndex >= 0) { - tempData[seriesIndex] = JSON.parse(JSON.stringify(originalSeries)); - } - } - this.data = tempData; + this.toggleSeries(event); } } + toggleSeries(name: string): void { + if (!this.temp.some((series) => series.name === name)) { + return; + } + + this.seriesVisibility[name] = !this.isDataShown(name); + this.data = this.temp.map((series) => ({ + name: series.name, + series: series.series.map((point) => ({ + ...point, + value: this.seriesVisibility[series.name] === false ? 0 : point.value, + })), + })); + } + isLegend(event: string | BurndownPoint): event is string { return typeof event === 'string'; } isDataShown(name: string): boolean { - const series = this.data.find((series) => series.name === name); - return series && series.series.some((point) => point.value !== 0); + return this.seriesVisibility[name] !== false; + } + + seriesColor(index: number): string { + return this.colorScheme.domain[index % this.colorScheme.domain.length] as string; } public formatPerc(input: number) { diff --git a/src/app/visualisations/task-visualisation/task-visualisation.component.html b/src/app/visualisations/task-visualisation/task-visualisation.component.html index b5311d2fab..34665575a8 100644 --- a/src/app/visualisations/task-visualisation/task-visualisation.component.html +++ b/src/app/visualisations/task-visualisation/task-visualisation.component.html @@ -1,7 +1,14 @@ -<ngx-charts-number-card - [customColors]="colors" - [results]="data" - [textColor]="textColor" - (select)="onSelect($event)" -> -</ngx-charts-number-card> +<div aria-label="Task status summary" class="task-status-grid" role="list"> + @for (status of data; track status.status) { + <div + class="task-status-card" + role="listitem" + [attr.aria-label]="status.name + ': ' + status.value" + [style.background-color]="status.color" + [style.color]="status.textColor" + > + <span class="task-status-value">{{ status.value }}</span> + <span class="task-status-label">{{ status.name }}</span> + </div> + } +</div> diff --git a/src/app/visualisations/task-visualisation/task-visualisation.component.scss b/src/app/visualisations/task-visualisation/task-visualisation.component.scss index e69de29bb2..f9e62b8980 100644 --- a/src/app/visualisations/task-visualisation/task-visualisation.component.scss +++ b/src/app/visualisations/task-visualisation/task-visualisation.component.scss @@ -0,0 +1,27 @@ +.task-status-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); + gap: 1rem; +} + +.task-status-card { + display: flex; + min-height: 10rem; + flex-direction: column; + justify-content: center; + border-radius: 0.25rem; + padding: 1.5rem; +} + +.task-status-value { + font-size: clamp(2.5rem, 4vw, 4rem); + line-height: 1; +} + +.task-status-label { + margin-top: 1.25rem; + overflow-wrap: anywhere; + font-size: 1rem; + font-weight: 500; + line-height: 1.35; +} diff --git a/src/app/visualisations/task-visualisation/task-visualisation.component.spec.ts b/src/app/visualisations/task-visualisation/task-visualisation.component.spec.ts new file mode 100644 index 0000000000..50e9325c28 --- /dev/null +++ b/src/app/visualisations/task-visualisation/task-visualisation.component.spec.ts @@ -0,0 +1,33 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {Project} from 'src/app/api/models/doubtfire-model'; +import {TaskVisualisationComponent} from './task-visualisation.component'; + +describe('TaskVisualisationComponent', () => { + let fixture: ComponentFixture<TaskVisualisationComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [TaskVisualisationComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(TaskVisualisationComponent); + fixture.componentInstance.project = { + activeTasks: () => [{status: 'complete'}, {status: 'not_started'}], + } as unknown as Project; + fixture.detectChanges(); + }); + + it('renders complete status labels without chart ellipsis or a false click affordance', () => { + const host = fixture.nativeElement as HTMLElement; + const cards = Array.from(host.querySelectorAll<HTMLElement>('[role="listitem"]')); + const awaitingFeedback = cards.find((card) => card.textContent.includes('Awaiting Feedback')); + + expect(awaitingFeedback).toBeTruthy(); + expect(awaitingFeedback?.textContent).not.toContain('...'); + expect(awaitingFeedback?.getAttribute('aria-label')).toBe('Awaiting Feedback: 0'); + expect(awaitingFeedback?.tagName).toBe('DIV'); + expect(host.querySelector('ngx-charts-number-card')).toBeNull(); + expect(host.querySelector('button')).toBeNull(); + }); +}); diff --git a/src/app/visualisations/task-visualisation/task-visualisation.component.ts b/src/app/visualisations/task-visualisation/task-visualisation.component.ts index ba1dc1a54e..2d9a377faf 100644 --- a/src/app/visualisations/task-visualisation/task-visualisation.component.ts +++ b/src/app/visualisations/task-visualisation/task-visualisation.component.ts @@ -6,7 +6,15 @@ import { OnInit, SimpleChanges, } from '@angular/core'; -import {Project, TaskStatus} from 'src/app/api/models/doubtfire-model'; +import {Project, TaskStatus, TaskStatusEnum} from 'src/app/api/models/doubtfire-model'; + +interface TaskStatusSummary { + status: TaskStatusEnum; + name: string; + value: number; + color: string; + textColor: string; +} @Component({ selector: 'f-task-visualisation', @@ -19,12 +27,7 @@ export class TaskVisualisationComponent implements OnChanges, OnInit { @Input() project: Project; @Input() grade: number; - data: {name: string; value: number}[] = []; - colors: {name: string; value: string}[]; - view: number[] = [700, 400]; - - // options - textColor: string = '#F5F5F5'; + data: TaskStatusSummary[] = []; ngOnInit(): void { this.updateData(); @@ -46,42 +49,52 @@ export class TaskVisualisationComponent implements OnChanges, OnInit { } }); - const sortOrder = [ - 'Complete', - 'Discuss', - 'Awaiting Feedback', - 'Working On It', - 'Not Started', + const sortOrder: TaskStatusEnum[] = [ + 'complete', + 'discuss', + 'ready_for_feedback', + 'working_on_it', + 'not_started', ]; this.data = Array.from(taskCounts) .map(([status, count]) => { + const color = TaskStatus.STATUS_COLORS.get(status) ?? '#64748b'; return { - name: TaskStatus.STATUS_LABELS.get(status), + status, + name: TaskStatus.STATUS_LABELS.get(status) ?? status, value: count, + color, + textColor: this.contrastingTextColor(color), }; }) - .filter((task) => task.value > 0 || sortOrder.includes(task.name)) + .filter((task) => task.value > 0 || sortOrder.includes(task.status)) .sort((a, b) => { - let aIndex = sortOrder.indexOf(a.name); - let bIndex = sortOrder.indexOf(b.name); + let aIndex = sortOrder.indexOf(a.status); + let bIndex = sortOrder.indexOf(b.status); aIndex = aIndex === -1 ? sortOrder.length : aIndex; bIndex = bIndex === -1 ? sortOrder.length : bIndex; return aIndex - bIndex; }); - - this.colors = Array.from(TaskStatus.STATUS_COLORS).map(([status, color]) => { - return {name: TaskStatus.STATUS_LABELS.get(status), value: color}; - }); - - // console.log('Data:', this.data); - // console.log('Colors:', this.colors); } } - onSelect(event) { - console.log(event); + private contrastingTextColor(color: string): string { + const hex = color.replace('#', ''); + if (!/^[0-9a-f]{6}$/i.test(hex)) { + return '#ffffff'; + } + + const channels = [0, 2, 4].map((index) => parseInt(hex.slice(index, index + 2), 16) / 255); + const [red, green, blue] = channels.map((channel) => + channel <= 0.03928 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4, + ); + const luminance = 0.2126 * red + 0.7152 * green + 0.0722 * blue; + const whiteContrast = 1.05 / (luminance + 0.05); + const darkContrast = (luminance + 0.05) / 0.057; + + return whiteContrast >= darkContrast ? '#ffffff' : '#111827'; } } From 3078c7a151aaa6a3fd7b5b2035ba0f9377b99657 Mon Sep 17 00:00:00 2001 From: Reem-997 <s224722416@deakin.edu.au> Date: Sat, 22 Aug 2026 22:36:22 +1000 Subject: [PATCH 1395/1531] docs: add English-only submission notice --- docs/english-only-submission-notice.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docs/english-only-submission-notice.md diff --git a/docs/english-only-submission-notice.md b/docs/english-only-submission-notice.md new file mode 100644 index 0000000000..68169dd27a --- /dev/null +++ b/docs/english-only-submission-notice.md @@ -0,0 +1,21 @@ +# English-Only Assessment Submission Notice + +## Proposed Notice + +All assessment submissions must be written and submitted in English. Translation tools may be used to help understand the assessment instructions, but the final submitted work must remain in English. + +## Recommended Placement + +The notice should appear in the following locations: + +1. **Assessment task details page** — near the assessment requirements. +2. **Submission upload page** — above the upload or submit button. +3. **Final submission confirmation window** — before the student confirms the submission. + +## Behaviour When Translation Is Enabled + +The notice should remain visible in English when the language or translation option is active. Translation must not hide or change the requirement that the final assessment submission must be in English. + +## Scope + +This document provides the proposed wording and recommended placement only. No application or interface changes have been implemented. From 7af3807b104d67e086ebd038f1921bbf63827e57 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 02:06:57 +1000 Subject: [PATCH 1396/1531] fix(pwa): make the install prompt reliable --- .../install-prompt.service.spec.ts | 40 ++++++++-- .../install-prompt/install-prompt.service.ts | 73 ++++++++++++------- 2 files changed, 79 insertions(+), 34 deletions(-) diff --git a/src/app/sessions/install-prompt/install-prompt.service.spec.ts b/src/app/sessions/install-prompt/install-prompt.service.spec.ts index ee96f8048b..6257ead951 100644 --- a/src/app/sessions/install-prompt/install-prompt.service.spec.ts +++ b/src/app/sessions/install-prompt/install-prompt.service.spec.ts @@ -1,4 +1,4 @@ -import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'; import {TestBed} from '@angular/core/testing'; import {MatSnackBar} from '@angular/material/snack-bar'; import {Subject} from 'rxjs'; @@ -17,6 +17,7 @@ describe('InstallPromptService', () => { }; let actionSubject: Subject<void>; let afterDismissedSubject: Subject<void>; + let localStorageMock: Storage; beforeEach(() => { actionSubject = new Subject<void>(); @@ -31,7 +32,26 @@ describe('InstallPromptService', () => { open: vi.fn().mockReturnValue(snackBarRefSpy), }; - localStorage.clear(); + const storedValues: Map<string, string> = new Map(); + localStorageMock = { + get length() { + return storedValues.size; + }, + clear: vi.fn(() => storedValues.clear()), + getItem: vi.fn((key: string) => storedValues.get(key) ?? null), + key: vi.fn((index: number) => [...storedValues.keys()][index] ?? null), + removeItem: vi.fn((key: string) => storedValues.delete(key)), + setItem: vi.fn((key: string, value: string) => storedValues.set(key, value)), + }; + Object.defineProperty(window, 'localStorage', { + configurable: true, + value: localStorageMock, + }); + }); + + afterEach(() => { + TestBed.resetTestingModule(); + vi.restoreAllMocks(); }); function createService(): InstallPromptService { @@ -47,7 +67,7 @@ describe('InstallPromptService', () => { }); it('should do nothing if previously dismissed in localStorage', () => { - localStorage.setItem('ontrack_pwa_install_dismissed', 'true'); + localStorageMock.setItem('ontrack_pwa_install_dismissed', 'true'); createService(); expect(snackBarSpy.open).not.toHaveBeenCalled(); @@ -61,24 +81,28 @@ describe('InstallPromptService', () => { ).mockReturnValue(false); }); - it('should open snackbar and trigger prompt on user action', () => { + it('should open snackbar and trigger prompt on user action', async () => { createService(); const mockEvent = new Event('beforeinstallprompt') as BeforeInstallPromptEvent; - const promptSpy = vi.fn(); + const promptSpy = vi.fn().mockResolvedValue(undefined); const preventDefaultSpy = vi.spyOn(mockEvent, 'preventDefault'); Object.defineProperty(mockEvent, 'prompt', {value: promptSpy}); + Object.defineProperty(mockEvent, 'userChoice', { + value: Promise.resolve({outcome: 'accepted', platform: 'web'}), + }); window.dispatchEvent(mockEvent); expect(preventDefaultSpy).toHaveBeenCalled(); expect(snackBarSpy.open).toHaveBeenCalledWith( - 'Install OnTrack for a better experience', + 'Install OnTrack for quicker access and notifications', 'Install', {duration: 10000}, ); actionSubject.next(); + await Promise.resolve(); expect(promptSpy).toHaveBeenCalled(); }); @@ -89,7 +113,7 @@ describe('InstallPromptService', () => { window.dispatchEvent(mockEvent); afterDismissedSubject.next(); - expect(localStorage.getItem('ontrack_pwa_install_dismissed')).toBe('true'); + expect(localStorageMock.getItem('ontrack_pwa_install_dismissed')).toBe('true'); }); }); @@ -136,7 +160,7 @@ describe('InstallPromptService', () => { createService(); afterDismissedSubject.next(); - expect(localStorage.getItem('ontrack_pwa_install_dismissed')).toBe('true'); + expect(localStorageMock.getItem('ontrack_pwa_install_dismissed')).toBe('true'); }); }); }); diff --git a/src/app/sessions/install-prompt/install-prompt.service.ts b/src/app/sessions/install-prompt/install-prompt.service.ts index e4a7e03d6d..88b90e6b04 100644 --- a/src/app/sessions/install-prompt/install-prompt.service.ts +++ b/src/app/sessions/install-prompt/install-prompt.service.ts @@ -1,4 +1,4 @@ -import {Injectable} from '@angular/core'; +import {Injectable, OnDestroy} from '@angular/core'; import {MatSnackBar} from '@angular/material/snack-bar'; export interface BeforeInstallPromptEvent extends Event { @@ -14,42 +14,55 @@ const DISMISSED_KEY = 'ontrack_pwa_install_dismissed'; const PROMPT_DURATION = 10000; @Injectable() -export class InstallPromptService { +export class InstallPromptService implements OnDestroy { private beforeInstallPrompt: BeforeInstallPromptEvent | null = null; + private readonly handleBeforeInstallPrompt = (event: Event): void => { + event.preventDefault(); + + this.beforeInstallPrompt = event as BeforeInstallPromptEvent; + + const snackBarRef = this._snackBar.open( + 'Install OnTrack for quicker access and notifications', + 'Install', + {duration: PROMPT_DURATION}, + ); + + snackBarRef.onAction().subscribe(() => { + void this.showInstallPrompt(); + }); + + snackBarRef.afterDismissed().subscribe(() => { + this.rememberDismissal(); + }); + }; constructor(private _snackBar: MatSnackBar) { - if (localStorage.getItem(DISMISSED_KEY) === 'true') { + if (window.localStorage.getItem(DISMISSED_KEY) === 'true' || this.isStandalone()) { return; } if (this.isIos()) { - if (!this.isStandalone()) { - this.showIosPrompt(); - } + this.showIosPrompt(); return; } - window.addEventListener('beforeinstallprompt', (e: Event) => { - e.preventDefault(); + window.addEventListener('beforeinstallprompt', this.handleBeforeInstallPrompt); + } - this.beforeInstallPrompt = e as BeforeInstallPromptEvent; + public ngOnDestroy(): void { + window.removeEventListener('beforeinstallprompt', this.handleBeforeInstallPrompt); + } - const snackBarRef = this._snackBar.open( - 'Install OnTrack for a better experience', - 'Install', - {duration: PROMPT_DURATION}, - ); + private async showInstallPrompt(): Promise<void> { + const prompt = this.beforeInstallPrompt; + this.beforeInstallPrompt = null; - snackBarRef.onAction().subscribe(() => { - if (this.beforeInstallPrompt) { - this.beforeInstallPrompt.prompt(); - } - }); + if (!prompt) { + return; + } - snackBarRef.afterDismissed().subscribe(() => { - localStorage.setItem(DISMISSED_KEY, 'true'); - }); - }); + await prompt.prompt(); + await prompt.userChoice; } private showIosPrompt(): void { @@ -60,18 +73,26 @@ export class InstallPromptService { ); snackBarRef.afterDismissed().subscribe(() => { - localStorage.setItem(DISMISSED_KEY, 'true'); + this.rememberDismissal(); }); } + private rememberDismissal(): void { + window.localStorage.setItem(DISMISSED_KEY, 'true'); + } + private isIos(): boolean { const userAgent = window.navigator.userAgent.toLowerCase(); - return /iphone|ipad|ipod/.test(userAgent); + return ( + /iphone|ipad|ipod/.test(userAgent) || + (userAgent.includes('macintosh') && window.navigator.maxTouchPoints > 1) + ); } private isStandalone(): boolean { return ( - window.matchMedia('(display-mode: standalone)').matches || + (typeof window.matchMedia === 'function' && + window.matchMedia('(display-mode: standalone)').matches) || ('standalone' in window.navigator && (window.navigator as unknown as {standalone: boolean}).standalone) ); From d397d675e7cecd1ac3a8c5a3c37f94e21e7a7c4c Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 02:07:49 +1000 Subject: [PATCH 1397/1531] fix(notifications): re-subscribe on push subscription rotation --- docs/service-worker.md | 17 +++ .../api/services/push-notification.service.ts | 106 +++++++++++--- .../spec/push-notification.service.spec.ts | 137 +++++++++++++++++- src/app/app.component.spec.ts | 15 +- src/app/app.component.ts | 4 + 5 files changed, 247 insertions(+), 32 deletions(-) diff --git a/docs/service-worker.md b/docs/service-worker.md index 5de7e1afee..818a6c5579 100644 --- a/docs/service-worker.md +++ b/docs/service-worker.md @@ -95,6 +95,23 @@ The cost to watch for is stale app code, not stale data — API responses are no cached. If something you just changed is not showing up, clear the worker before assuming the change is wrong. +## Push subscription rotation + +Angular 22's worker handles the browser's `pushsubscriptionchange` event and +forwards it through `SwPush.pushSubscriptionChanges`. The app starts that +listener with its other push lifecycle services. When the browser supplies a +replacement, the app POSTs it to `/api/push_subscriptions` first and removes the +old endpoint only after the replacement is stored. A keys-only rotation keeps +the same endpoint and updates the existing api row in place. + +The focused service tests simulate this event because browsers do not provide a +reliable way to force a real rotation. They verify the POST-before-DELETE order, +keys-only updates, teardown, and that one failed api request does not stop later +rotations. A change event with no replacement cannot be repaired automatically: +creating a fresh subscription may require a user gesture, so the user must use +the existing opt-in control again; the api removes the dead row after a failed +delivery. + ## Clearing a stuck service worker Fastest, in the browser console: diff --git a/src/app/api/services/push-notification.service.ts b/src/app/api/services/push-notification.service.ts index 24e4d2bcca..00bf17167c 100644 --- a/src/app/api/services/push-notification.service.ts +++ b/src/app/api/services/push-notification.service.ts @@ -1,7 +1,17 @@ import {HttpClient} from '@angular/common/http'; import {Injectable} from '@angular/core'; import {SwPush} from '@angular/service-worker'; -import {Observable, catchError, from, map, of, switchMap, take} from 'rxjs'; +import { + Observable, + Subscription, + catchError, + concatMap, + from, + map, + of, + switchMap, + take, +} from 'rxjs'; import API_URL from 'src/app/config/constants/apiUrl'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; @@ -83,6 +93,7 @@ export const PERMISSION_DENIED_INSTRUCTIONS: Record<SupportedBrowser, string[]> @Injectable({providedIn: 'root'}) export class PushNotificationService { private readonly endpoint = `${API_URL}/push_subscriptions`; + private subscriptionChangeSubscription: Subscription | null = null; constructor( private http: HttpClient, @@ -145,6 +156,52 @@ export class PushNotificationService { return PERMISSION_DENIED_INSTRUCTIONS[this.browser]; } + /** + * Keep the api registration in step with browser-driven subscription changes. + * + * Angular 22 forwards the service worker's `pushsubscriptionchange` event as + * `pushSubscriptionChanges`. Register the replacement before removing the old + * endpoint so a transient api failure cannot throw away the last server row. + */ + public start(): void { + if (this.subscriptionChangeSubscription) { + return; + } + + this.subscriptionChangeSubscription = this.swPush.pushSubscriptionChanges + .pipe( + concatMap(({oldSubscription, newSubscription}) => { + if (!newSubscription) { + // Some browsers can report invalidation without a replacement. A + // fresh subscribe needs a user gesture, so leave recovery to the + // existing opt-in control and let server delivery remove the dead row. + return of(void 0); + } + + return this.registerSubscription(newSubscription).pipe( + switchMap(() => { + if (!oldSubscription || oldSubscription.endpoint === newSubscription.endpoint) { + return of(void 0); + } + + return this.removeServerSubscription(oldSubscription.endpoint); + }), + // One failed sync must not terminate the long-lived rotation stream. + catchError((error) => { + console.error('Could not update the rotated push subscription', error); + return of(void 0); + }), + ); + }), + ) + .subscribe(); + } + + public stop(): void { + this.subscriptionChangeSubscription?.unsubscribe(); + this.subscriptionChangeSubscription = null; + } + /** * Ask the browser for permission, then store the resulting registration * against the signed in user. @@ -158,16 +215,7 @@ export class PushNotificationService { this.swPush.requestSubscription({ serverPublicKey: this.constants.VapidPublicKey.value, }), - ).pipe( - switchMap((subscription) => { - const keys = subscription.toJSON().keys ?? {}; - return this.http.post<void>(this.endpoint, { - endpoint: subscription.endpoint, - p256dh: keys.p256dh, - auth: keys.auth, - }); - }), - ); + ).pipe(switchMap((subscription) => this.registerSubscription(subscription))); } /** @@ -193,18 +241,16 @@ export class PushNotificationService { return of(void 0); } - return this.http - .delete<void>(this.endpoint, {params: {endpoint: subscription.endpoint}}) - .pipe( - // Server cleanup failing must not leave the browser subscribed. If - // the delete fails we still unsubscribe locally: the browser stops - // receiving immediately, and the row left behind is removed the - // first time the push service answers 410 for it, which deliver_to - // in PushNotificationService already handles. - catchError(() => of(void 0)), - switchMap(() => from(this.swPush.unsubscribe())), - map(() => void 0), - ); + return this.removeServerSubscription(subscription.endpoint).pipe( + // Server cleanup failing must not leave the browser subscribed. If + // the delete fails we still unsubscribe locally: the browser stops + // receiving immediately, and the row left behind is removed the + // first time the push service answers 410 for it, which deliver_to + // in PushNotificationService already handles. + catchError(() => of(void 0)), + switchMap(() => from(this.swPush.unsubscribe())), + map(() => void 0), + ); }), ); } @@ -219,4 +265,18 @@ export class PushNotificationService { public unsubscribeQuietly(): Observable<void> { return this.unsubscribe().pipe(catchError(() => of(void 0))); } + + private registerSubscription(subscription: PushSubscription): Observable<void> { + const keys = subscription.toJSON().keys ?? {}; + + return this.http.post<void>(this.endpoint, { + endpoint: subscription.endpoint, + p256dh: keys.p256dh, + auth: keys.auth, + }); + } + + private removeServerSubscription(endpoint: string): Observable<void> { + return this.http.delete<void>(this.endpoint, {params: {endpoint}}); + } } diff --git a/src/app/api/services/spec/push-notification.service.spec.ts b/src/app/api/services/spec/push-notification.service.spec.ts index e1b8068741..71526017bf 100644 --- a/src/app/api/services/spec/push-notification.service.spec.ts +++ b/src/app/api/services/spec/push-notification.service.spec.ts @@ -3,7 +3,7 @@ import {provideHttpClient, withInterceptorsFromDi, withXhr} from '@angular/commo import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; import {TestBed} from '@angular/core/testing'; import {SwPush} from '@angular/service-worker'; -import {BehaviorSubject, NEVER, Observable} from 'rxjs'; +import {BehaviorSubject, NEVER, Observable, Subject} from 'rxjs'; import API_URL from 'src/app/config/constants/apiUrl'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import { @@ -29,12 +29,16 @@ function flushMicrotasks(): Promise<void> { * Enough of a PushSubscription for the service. The real one comes from the * browser and cannot be constructed in a test environment. */ -function fakeSubscription() { +function fakeSubscription( + endpoint: string = ENDPOINT, + p256dh: string = 'BFakePublicKey', + auth: string = 'FakeAuthSecret', +) { return { - endpoint: ENDPOINT, + endpoint, toJSON: () => ({ - endpoint: ENDPOINT, - keys: {p256dh: 'BFakePublicKey', auth: 'FakeAuthSecret'}, + endpoint, + keys: {p256dh, auth}, }), } as unknown as PushSubscription; } @@ -43,9 +47,17 @@ describe('PushNotificationService', () => { let service: PushNotificationService; let httpMock: HttpTestingController; let subscriptionSubject: BehaviorSubject<PushSubscription | null>; + let subscriptionChangeSubject: Subject<{ + oldSubscription: PushSubscription | null; + newSubscription: PushSubscription | null; + }>; let swPush: { isEnabled: boolean; subscription: Observable<PushSubscription | null>; + pushSubscriptionChanges: Observable<{ + oldSubscription: PushSubscription | null; + newSubscription: PushSubscription | null; + }>; requestSubscription: ReturnType<typeof vi.fn>; unsubscribe: ReturnType<typeof vi.fn>; }; @@ -53,10 +65,12 @@ describe('PushNotificationService', () => { beforeEach(() => { subscriptionSubject = new BehaviorSubject<PushSubscription | null>(null); + subscriptionChangeSubject = new Subject(); swPush = { isEnabled: true, subscription: subscriptionSubject, + pushSubscriptionChanges: subscriptionChangeSubject, requestSubscription: vi.fn().mockResolvedValue(fakeSubscription()), unsubscribe: vi.fn().mockResolvedValue(undefined), }; @@ -117,6 +131,119 @@ describe('PushNotificationService', () => { }); }); + it('stores a rotated registration before deleting the old endpoint', () => { + const oldSubscription = fakeSubscription(`${ENDPOINT}-old`); + const newSubscription = fakeSubscription( + `${ENDPOINT}-new`, + 'BRotatedPublicKey', + 'RotatedAuthSecret', + ); + + service.start(); + subscriptionChangeSubject.next({oldSubscription, newSubscription}); + + const post = httpMock.expectOne( + (request) => request.url === `${API_URL}/push_subscriptions` && request.method === 'POST', + ); + expect(post.request.body).toEqual({ + endpoint: `${ENDPOINT}-new`, + p256dh: 'BRotatedPublicKey', + auth: 'RotatedAuthSecret', + }); + httpMock.expectNone( + (request) => request.url === `${API_URL}/push_subscriptions` && request.method === 'DELETE', + ); + + post.flush(null); + + const removeOld = httpMock.expectOne( + (request) => request.url === `${API_URL}/push_subscriptions` && request.method === 'DELETE', + ); + expect(removeOld.request.params.get('endpoint')).toBe(`${ENDPOINT}-old`); + removeOld.flush(null); + }); + + it('updates keys in place when rotation keeps the same endpoint', () => { + const oldSubscription = fakeSubscription(); + const newSubscription = fakeSubscription(ENDPOINT, 'BRotatedPublicKey', 'RotatedAuthSecret'); + + service.start(); + subscriptionChangeSubject.next({oldSubscription, newSubscription}); + + const post = httpMock.expectOne( + (request) => request.url === `${API_URL}/push_subscriptions` && request.method === 'POST', + ); + expect(post.request.body).toEqual({ + endpoint: ENDPOINT, + p256dh: 'BRotatedPublicKey', + auth: 'RotatedAuthSecret', + }); + post.flush(null); + + httpMock.expectNone( + (request) => request.url === `${API_URL}/push_subscriptions` && request.method === 'DELETE', + ); + }); + + it('keeps listening after one rotated registration fails to reach the api', () => { + const consoleError = vi.spyOn(console, 'error').mockImplementation(() => undefined); + + service.start(); + subscriptionChangeSubject.next({ + oldSubscription: fakeSubscription(`${ENDPOINT}-old`), + newSubscription: fakeSubscription(`${ENDPOINT}-failed`), + }); + + httpMock + .expectOne( + (request) => request.url === `${API_URL}/push_subscriptions` && request.method === 'POST', + ) + .flush('nope', {status: 500, statusText: 'Server Error'}); + + subscriptionChangeSubject.next({ + oldSubscription: null, + newSubscription: fakeSubscription(`${ENDPOINT}-later`), + }); + + const later = httpMock.expectOne( + (request) => request.url === `${API_URL}/push_subscriptions` && request.method === 'POST', + ); + expect(later.request.body['endpoint']).toBe(`${ENDPOINT}-later`); + later.flush(null); + + expect(consoleError).toHaveBeenCalledOnce(); + }); + + it('ignores an invalidation when the browser supplies no replacement', () => { + service.start(); + subscriptionChangeSubject.next({ + oldSubscription: fakeSubscription(), + newSubscription: null, + }); + + httpMock.expectNone(`${API_URL}/push_subscriptions`); + }); + + it('starts the rotation listener only once and stops it on teardown', () => { + service.start(); + service.start(); + + subscriptionChangeSubject.next({ + oldSubscription: null, + newSubscription: fakeSubscription(`${ENDPOINT}-once`), + }); + + httpMock.expectOne(`${API_URL}/push_subscriptions`).flush(null); + service.stop(); + + subscriptionChangeSubject.next({ + oldSubscription: null, + newSubscription: fakeSubscription(`${ENDPOINT}-stopped`), + }); + + httpMock.expectNone(`${API_URL}/push_subscriptions`); + }); + it('deletes on the api before unsubscribing in the browser', () => { subscriptionSubject.next(fakeSubscription()); diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 2f03f0aab6..e88ba1499a 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,13 +1,14 @@ -// MN-C03 targeted startup and teardown test. +// MN-C03 and MN-C05 targeted startup and teardown test. import {describe, expect, it, vi} from 'vitest'; import {Renderer2} from '@angular/core'; import {Router} from '@angular/router'; import {Subject} from 'rxjs'; import {PushNotificationClickService} from 'src/app/api/services/push-notification-click.service'; +import {PushNotificationService} from 'src/app/api/services/push-notification.service'; import {AppComponent} from './app.component'; -describe('AppComponent notification-click lifecycle', () => { - it('starts click routing at app startup and stops it at teardown', () => { +describe('AppComponent push lifecycle', () => { + it('starts push listeners at app startup and stops them at teardown', () => { const events: Subject<unknown> = new Subject(); const router = { url: '/home', @@ -20,14 +21,20 @@ describe('AppComponent notification-click lifecycle', () => { start: vi.fn(), stop: vi.fn(), } as unknown as PushNotificationClickService; + const pushNotifications = { + start: vi.fn(), + stop: vi.fn(), + } as unknown as PushNotificationService; - const component = new AppComponent(router, renderer, clickRouting); + const component = new AppComponent(router, renderer, clickRouting, pushNotifications); component.ngOnInit(); expect(clickRouting.start).toHaveBeenCalledOnce(); + expect(pushNotifications.start).toHaveBeenCalledOnce(); component.ngOnDestroy(); expect(clickRouting.stop).toHaveBeenCalledOnce(); + expect(pushNotifications.stop).toHaveBeenCalledOnce(); }); }); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 6cf98f030f..25b944278d 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -2,6 +2,7 @@ import {ChangeDetectionStrategy, Component, OnDestroy, OnInit, Renderer2} from ' import {NavigationEnd, Router} from '@angular/router'; import {Subscription, filter} from 'rxjs'; import {PushNotificationClickService} from 'src/app/api/services/push-notification-click.service'; +import {PushNotificationService} from 'src/app/api/services/push-notification.service'; @Component({ selector: 'app-root', @@ -16,10 +17,12 @@ export class AppComponent implements OnInit, OnDestroy { private router: Router, private renderer: Renderer2, private pushNotificationClicks: PushNotificationClickService, + private pushNotifications: PushNotificationService, ) {} ngOnInit(): void { this.pushNotificationClicks.start(); + this.pushNotifications.start(); this.setBodyBackground(this.router.url); this.routerSub = this.router.events .pipe(filter((event) => event instanceof NavigationEnd)) @@ -28,6 +31,7 @@ export class AppComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.pushNotificationClicks.stop(); + this.pushNotifications.stop(); this.routerSub?.unsubscribe(); } From 6c0274268f332b464632852c43ebc72b985c7579 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 02:08:16 +1000 Subject: [PATCH 1398/1531] feat(pwa): improve update available prompt --- .../check-for-update.service.spec.ts | 152 ++++++++++++++++++ .../check-for-update.service.ts | 79 ++++++--- 2 files changed, 205 insertions(+), 26 deletions(-) create mode 100644 src/app/sessions/service-worker-updater/check-for-update.service.spec.ts diff --git a/src/app/sessions/service-worker-updater/check-for-update.service.spec.ts b/src/app/sessions/service-worker-updater/check-for-update.service.spec.ts new file mode 100644 index 0000000000..6ffeac7e92 --- /dev/null +++ b/src/app/sessions/service-worker-updater/check-for-update.service.spec.ts @@ -0,0 +1,152 @@ +import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'; +import {ApplicationRef} from '@angular/core'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {SwUpdate, UnrecoverableStateEvent, VersionEvent} from '@angular/service-worker'; +import {Subject} from 'rxjs'; +import {CheckForUpdateService} from './check-for-update.service'; + +const APP_STABILITY_DELAY_MS = 10 * 1000; +const UPDATE_CHECK_INTERVAL_MS = 4 * 60 * 60 * 1000; + +describe('CheckForUpdateService', () => { + let service: CheckForUpdateService; + let appIsStable: Subject<boolean>; + let versionUpdates: Subject<VersionEvent>; + let unrecoverable: Subject<UnrecoverableStateEvent>; + let updateActions: Subject<void>[]; + let reload: ReturnType<typeof vi.fn>; + let updates: { + isEnabled: boolean; + versionUpdates: Subject<VersionEvent>; + unrecoverable: Subject<UnrecoverableStateEvent>; + checkForUpdate: ReturnType<typeof vi.fn>; + activateUpdate: ReturnType<typeof vi.fn>; + }; + let snackBar: {open: ReturnType<typeof vi.fn>}; + + beforeEach(() => { + vi.useFakeTimers(); + appIsStable = new Subject<boolean>(); + versionUpdates = new Subject<VersionEvent>(); + unrecoverable = new Subject<UnrecoverableStateEvent>(); + updateActions = []; + reload = vi.fn(); + updates = { + isEnabled: true, + versionUpdates, + unrecoverable, + checkForUpdate: vi.fn().mockResolvedValue(false), + activateUpdate: vi.fn().mockResolvedValue(true), + }; + snackBar = { + open: vi.fn(() => { + const action: Subject<void> = new Subject(); + updateActions.push(action); + return {onAction: () => action}; + }), + }; + + service = new CheckForUpdateService( + {isStable: appIsStable} as unknown as ApplicationRef, + updates as unknown as SwUpdate, + snackBar as unknown as MatSnackBar, + {location: {reload}} as unknown as Document, + ); + }); + + afterEach(() => { + service.ngOnDestroy(); + vi.useRealTimers(); + }); + + it('checks after the app is stable for ten seconds and then every four hours', async () => { + appIsStable.next(false); + await vi.advanceTimersByTimeAsync(APP_STABILITY_DELAY_MS); + expect(updates.checkForUpdate).not.toHaveBeenCalled(); + + appIsStable.next(true); + await vi.advanceTimersByTimeAsync(APP_STABILITY_DELAY_MS - 1); + expect(updates.checkForUpdate).not.toHaveBeenCalled(); + + await vi.advanceTimersByTimeAsync(1); + expect(updates.checkForUpdate).toHaveBeenCalledTimes(1); + + await vi.advanceTimersByTimeAsync(UPDATE_CHECK_INTERVAL_MS); + expect(updates.checkForUpdate).toHaveBeenCalledTimes(2); + }); + + it('does not poll after the service is destroyed', async () => { + appIsStable.next(true); + await vi.advanceTimersByTimeAsync(APP_STABILITY_DELAY_MS); + expect(updates.checkForUpdate).toHaveBeenCalledTimes(1); + + service.ngOnDestroy(); + await vi.advanceTimersByTimeAsync(UPDATE_CHECK_INTERVAL_MS * 2); + + expect(updates.checkForUpdate).toHaveBeenCalledTimes(1); + }); + + it('does not check for updates when the service worker is disabled', async () => { + updates.isEnabled = false; + appIsStable.next(true); + + await vi.advanceTimersByTimeAsync(APP_STABILITY_DELAY_MS + UPDATE_CHECK_INTERVAL_MS); + + expect(updates.checkForUpdate).not.toHaveBeenCalled(); + }); + + it('offers a reload for a ready version and reloads only after activation', async () => { + let finishActivation: (activated: boolean) => void; + updates.activateUpdate.mockReturnValue( + new Promise<boolean>((resolve) => { + finishActivation = resolve; + }), + ); + + versionUpdates.next({ + type: 'VERSION_READY', + currentVersion: {hash: 'old'}, + latestVersion: {hash: 'new'}, + }); + + expect(snackBar.open).toHaveBeenCalledWith( + 'A new version of OnTrack is ready. Reload to update now.', + 'Reload', + ); + + updateActions[0].next(); + expect(updates.activateUpdate).toHaveBeenCalledTimes(1); + expect(reload).not.toHaveBeenCalled(); + + finishActivation(true); + await Promise.resolve(); + + expect(reload).toHaveBeenCalledTimes(1); + }); + + it('ignores version events that are not ready to activate', () => { + versionUpdates.next({type: 'VERSION_DETECTED', version: {hash: 'new'}}); + versionUpdates.next({type: 'NO_NEW_VERSION_DETECTED', version: {hash: 'current'}}); + versionUpdates.next({ + type: 'VERSION_INSTALLATION_FAILED', + version: {hash: 'broken'}, + error: 'Download failed', + }); + + expect(snackBar.open).not.toHaveBeenCalled(); + }); + + it('offers a direct reload when the current version is unrecoverable', () => { + unrecoverable.next({type: 'UNRECOVERABLE_STATE', reason: 'Cache is corrupt'}); + + expect(snackBar.open).toHaveBeenCalledWith( + 'This version of OnTrack can no longer run safely. Reload to recover.', + 'Reload', + ); + + updateActions[0].next(); + + expect(updates.activateUpdate).not.toHaveBeenCalled(); + expect(reload).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/app/sessions/service-worker-updater/check-for-update.service.ts b/src/app/sessions/service-worker-updater/check-for-update.service.ts index 302af93ef1..8bdfeb84e4 100644 --- a/src/app/sessions/service-worker-updater/check-for-update.service.ts +++ b/src/app/sessions/service-worker-updater/check-for-update.service.ts @@ -1,44 +1,71 @@ -import {ApplicationRef, Injectable} from '@angular/core'; +import {DOCUMENT} from '@angular/common'; +import {ApplicationRef, Inject, Injectable, OnDestroy} from '@angular/core'; import {MatSnackBar} from '@angular/material/snack-bar'; import {SwUpdate} from '@angular/service-worker'; +import {Subject, concat, delay, filter, from, interval, of, switchMap, take, takeUntil} from 'rxjs'; + +const APP_STABILITY_DELAY_MS = 10 * 1000; +const UPDATE_CHECK_INTERVAL_MS = 4 * 60 * 60 * 1000; @Injectable() -export class CheckForUpdateService { +export class CheckForUpdateService implements OnDestroy { + private readonly destroy$: Subject<void> = new Subject(); + constructor( appRef: ApplicationRef, private updates: SwUpdate, - private _snackBar: MatSnackBar, + private snackBar: MatSnackBar, + @Inject(DOCUMENT) private document: Document, ) { - // Allow the app to stabilize first, before starting polling for updates with `interval()`. - // const appIsStable$ = appRef.isStable.pipe(delay(10000)); - - // Checks every 4 hours - // const updateInterval$ = interval(4 * 60 * 60 * 1000); - // const updateIntervalOnceAppIsStable$ = concat(appIsStable$, updateInterval$); - - // updateIntervalOnceAppIsStable$.subscribe((() => { - // this.checkForUpdate(); - // }).bind(this)); - this.updates.versionUpdates.subscribe((updateEvent) => { - if (updateEvent.type === 'VERSION_READY') { - const snackBarRef = _snackBar.open( - 'An update to the app has been found, would you like to refresh now?', - 'refresh', - ); - snackBarRef.onAction().subscribe((_result) => { - updates.activateUpdate().then(() => document.location.reload()); - }); + appRef.isStable + .pipe( + filter((isStable) => isStable), + take(1), + delay(APP_STABILITY_DELAY_MS), + switchMap(() => concat(of(0), interval(UPDATE_CHECK_INTERVAL_MS))), + takeUntil(this.destroy$), + ) + .subscribe(() => this.checkForUpdate()); + + this.updates.versionUpdates.pipe(takeUntil(this.destroy$)).subscribe((updateEvent) => { + if (updateEvent.type !== 'VERSION_READY') { + return; } + + const snackBarRef = this.snackBar.open( + 'A new version of OnTrack is ready. Reload to update now.', + 'Reload', + ); + snackBarRef + .onAction() + .pipe( + take(1), + switchMap(() => from(this.updates.activateUpdate())), + takeUntil(this.destroy$), + ) + .subscribe(() => this.document.location.reload()); }); - this.updates.unrecoverable.subscribe((_event) => { - _snackBar.open('An error occurred during update, please refresh the page'); + this.updates.unrecoverable.pipe(takeUntil(this.destroy$)).subscribe(() => { + const snackBarRef = this.snackBar.open( + 'This version of OnTrack can no longer run safely. Reload to recover.', + 'Reload', + ); + snackBarRef + .onAction() + .pipe(take(1), takeUntil(this.destroy$)) + .subscribe(() => this.document.location.reload()); }); } - public checkForUpdate() { + public ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + + public checkForUpdate(): void { if (this.updates.isEnabled) { - this.updates.checkForUpdate(); + void this.updates.checkForUpdate(); } } } From 72ef984c0bc2118a02267f805458dc9bec1aab00 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 12:45:04 +1000 Subject: [PATCH 1399/1531] docs: clarify dashboard sample data semantics --- DASHBOARD-SAMPLE-DATA.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/DASHBOARD-SAMPLE-DATA.md b/DASHBOARD-SAMPLE-DATA.md index d5594c8cab..2befa99d66 100644 --- a/DASHBOARD-SAMPLE-DATA.md +++ b/DASHBOARD-SAMPLE-DATA.md @@ -1,8 +1,10 @@ +# Cross-unit dashboard sample data -| Unit | Due Date | Progress | Status | -| -------- | ---------- | -------- | ------------- | -| COS10001 | 17/10/2026 | 10% | not_started | -| COS20007 | 19/08/2026 | 100% | complete | -| COS30046 | 25/08/2026 | 90% | working_on_it | - +These values are entirely synthetic and are intended only as a visual reference for dashboard +mockups. They are not an API schema or an automated-test fixture. Dates use `DD/MM/YYYY`. +| Unit code | Example task due date | Unit completion | Example task status | +| --------- | --------------------- | --------------- | ------------------- | +| COS10001 | 17/10/2026 | 10% | `not_started` | +| COS20007 | 19/08/2026 | 100% | `complete` | +| COS30046 | 25/08/2026 | 90% | `working_on_it` | From b0d45a4deb55a5a74df49f648a0ff5f1689835b1 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 13:04:57 +1000 Subject: [PATCH 1400/1531] fix: harden notification page actions --- node_modules | 1 - .../notifications-page.component.html | 13 ++- .../notifications-page.component.spec.ts | 89 ++++++++++++++++--- .../notifications-page.component.ts | 66 +++++++++++++- 4 files changed, 150 insertions(+), 19 deletions(-) delete mode 120000 node_modules diff --git a/node_modules b/node_modules deleted file mode 120000 index 1d2e552449..0000000000 --- a/node_modules +++ /dev/null @@ -1 +0,0 @@ -../doubtfire-web/node_modules \ No newline at end of file diff --git a/src/app/common/notifications-page/notifications-page.component.html b/src/app/common/notifications-page/notifications-page.component.html index c50b514750..42e545f6c1 100644 --- a/src/app/common/notifications-page/notifications-page.component.html +++ b/src/app/common/notifications-page/notifications-page.component.html @@ -3,11 +3,12 @@ <h1 class="text-2xl">Notifications</h1> <!-- - Only when it has something to do, the same reason the badge on the bell - disappears at zero rather than showing one. hasUnread reads the rows this - page is holding and not the shared unread count, see the note on it. + Keep the control rendered once the list is visible, even after the last + unread row changes. Removing a focused button would drop keyboard focus to + the document body. disabledInteractive keeps it focusable while the guard + in markAllRead prevents another request. --> - @if (hasUnread) { + @if (!loading && !loadFailed && notifications.length) { <!-- The label is hidden below sm and the icon carries it there, so the aria-label is not a duplicate of visible text, it is the only wording @@ -17,6 +18,8 @@ <h1 class="text-2xl">Notifications</h1> aria-label="Mark all read" class="notification-mark-all" mat-stroked-button + [disabled]="!hasUnread || markAllReadPending" + [disabledInteractive]="true" (click)="markAllRead()" > <mat-icon>done_all</mat-icon> @@ -103,6 +106,8 @@ <h1 class="text-2xl">Notifications</h1> mat-icon-button matTooltip="Delete" [attr.aria-label]="deleteLabel(notification)" + [disabled]="isDeleting(notification)" + [disabledInteractive]="true" (click)="confirmDelete(notification)" > <mat-icon>close</mat-icon> diff --git a/src/app/common/notifications-page/notifications-page.component.spec.ts b/src/app/common/notifications-page/notifications-page.component.spec.ts index cbb6016040..0194c99350 100644 --- a/src/app/common/notifications-page/notifications-page.component.spec.ts +++ b/src/app/common/notifications-page/notifications-page.component.spec.ts @@ -357,7 +357,7 @@ describe('NotificationsPageComponent', () => { // link is nullable on the api. Refusing to mark it read would leave a // number on the bell that the user has no way to clear. expect(notificationService.markRead).toHaveBeenCalledTimes(1); - expect(notificationRoutes.navigate).not.toHaveBeenCalled(); + expect(router.navigateByUrl).not.toHaveBeenCalled(); }); it('says so when a notification could not be marked as read', () => { @@ -412,21 +412,57 @@ describe('NotificationsPageComponent', () => { }); it('marks everything read without asking first', () => { - markAllButton().click(); + component.markAllRead(); expect(notificationService.markAllRead).toHaveBeenCalledTimes(1); expect(subscribedTo.has('markAllRead')).toBe(true); expect(confirmationModal.show).not.toHaveBeenCalled(); + expect(alerts.success).toHaveBeenCalledWith('All notifications marked as read'); }); - it('does not offer to mark all read when nothing is unread', () => { + it('keeps the focused action available but disabled when nothing is unread', () => { const refresh = reloadWith(); refresh.next([read(2), read(1)]); fixture.detectChanges(); - // Same reason the badge on the bell disappears at zero rather than showing - // one. An action that cannot do anything should not be sitting there. - expect(markAllButton()).toBeNull(); + expect(markAllButton()).not.toBeNull(); + expect(markAllButton().getAttribute('aria-disabled')).toBe('true'); + + component.markAllRead(); + + expect(notificationService.markAllRead).not.toHaveBeenCalled(); + }); + + it('does not send mark all read twice while the request is pending', () => { + const pending: Subject<void> = new Subject(); + notificationService.markAllRead.mockReturnValue(pending); + + component.markAllRead(); + component.markAllRead(); + + expect(notificationService.markAllRead).toHaveBeenCalledTimes(1); + expect(component.markAllReadPending).toBe(true); + + pending.next(); + + expect(component.markAllReadPending).toBe(false); + }); + + it('keeps focus on mark all read after the rows become read', () => { + notificationService.markAllRead.mockImplementation(() => + defer(() => { + component.notifications.forEach((row) => (row.readAt = new Date())); + return of(undefined); + }), + ); + + const button = markAllButton(); + button.focus(); + button.click(); + fixture.detectChanges(); + + expect(document.activeElement).toBe(button); + expect(button.getAttribute('aria-disabled')).toBe('true'); }); it('offers it on a phone, where nothing refreshes the shared unread count', () => { @@ -454,6 +490,7 @@ describe('NotificationsPageComponent', () => { expect(confirmationModal.show).toHaveBeenCalledTimes(1); expect(notificationService.remove).not.toHaveBeenCalled(); + expect(confirmationModal.show.mock.calls[0][1]).toContain('notification 2'); }); it('deletes only once the dialog is agreed to', () => { @@ -468,6 +505,35 @@ describe('NotificationsPageComponent', () => { expect(rowText()).toEqual(['notification 1']); }); + it('does not delete the same notification twice while the first request is pending', () => { + const pending: Subject<void> = new Subject(); + notificationService.remove.mockReturnValue(pending); + + deleteButtons()[0].click(); + confirmed(); + confirmed(); + fixture.detectChanges(); + + expect(notificationService.remove).toHaveBeenCalledTimes(1); + expect(deleteButtons()[0].getAttribute('aria-disabled')).toBe('true'); + + pending.next(); + fixture.detectChanges(); + + expect(component.isDeleting(notificationService.remove.mock.calls[0][0])).toBe(false); + }); + + it('moves focus to the row that replaces a deleted row', () => { + const button = deleteButtons()[0]; + button.click(); + button.focus(); + + confirmed(); + + expect(rowText()).toEqual(['notification 1']); + expect(document.activeElement).toBe(rows()[0]); + }); + it('leaves the notification alone when the dialog is cancelled', () => { deleteButtons()[0].click(); cancelled(); @@ -480,7 +546,9 @@ describe('NotificationsPageComponent', () => { it('keeps the row when the delete fails', () => { notificationService.remove.mockReturnValue(throwError(() => new Error('DELETE failed'))); - deleteButtons()[0].click(); + const lastPageDelete = deleteButtons()[0]; + lastPageDelete.click(); + lastPageDelete.focus(); confirmed(); fixture.detectChanges(); @@ -499,7 +567,7 @@ describe('NotificationsPageComponent', () => { // would make asking to delete one mark it read and navigate away from the // page it was asked on. expect(notificationService.markRead).not.toHaveBeenCalled(); - expect(notificationRoutes.navigate).not.toHaveBeenCalled(); + expect(router.navigateByUrl).not.toHaveBeenCalled(); }); it('names the notification on its delete button', () => { @@ -528,6 +596,7 @@ describe('NotificationsPageComponent', () => { // either, because there are still twenty notifications. expect(component.pageIndex).toBe(0); expect(rows()).toHaveLength(20); + expect(document.activeElement).toBe(rows()[0]); }); it('shows the empty state once the last one is deleted', () => { @@ -547,7 +616,7 @@ describe('NotificationsPageComponent', () => { const refresh = reloadWith(); expect(refresh.observed).toBe(true); - markAllButton().click(); + component.markAllRead(); // That response was worked out before the click, and NotificationService // writes list responses into the shared entity cache, so letting it land @@ -578,7 +647,7 @@ describe('NotificationsPageComponent', () => { reloadWith(); expect(pageText()).toContain('Loading your notifications'); - markAllButton().click(); + component.markAllRead(); fixture.detectChanges(); // Cancelling the request without clearing the flag sits a spinner over a diff --git a/src/app/common/notifications-page/notifications-page.component.ts b/src/app/common/notifications-page/notifications-page.component.ts index da71e08634..09e51094e7 100644 --- a/src/app/common/notifications-page/notifications-page.component.ts +++ b/src/app/common/notifications-page/notifications-page.component.ts @@ -1,5 +1,12 @@ import moment from 'moment'; -import {ChangeDetectionStrategy, Component, OnDestroy, OnInit} from '@angular/core'; +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ElementRef, + OnDestroy, + OnInit, +} from '@angular/core'; import {PageEvent} from '@angular/material/paginator'; import {Router} from '@angular/router'; import {Subscription} from 'rxjs'; @@ -70,6 +77,8 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { pageSize = 20; private listSubscription: Subscription | null = null; + private readonly deletingNotificationIds: Set<number> = new Set(); + markAllReadPending = false; constructor( private notificationService: NotificationService, @@ -77,6 +86,8 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { private confirmationModal: ConfirmationModalService, private alerts: AlertService, private router: Router, + private changeDetectorRef: ChangeDetectorRef, + private elementRef: ElementRef<HTMLElement>, ) {} /** @@ -207,13 +218,26 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { * ever come to disagree with it. */ markAllRead(): void { + if (!this.hasUnread || this.markAllReadPending) { + return; + } + + this.markAllReadPending = true; + // A list read raised before this is out of date now, and its response goes // straight into the shared cache, so landing late would draw every row // unread again. this.cancelPendingList(); this.notificationService.markAllRead().subscribe({ - error: () => this.alerts.error('Your notifications could not be marked as read'), + next: () => { + this.markAllReadPending = false; + this.alerts.success('All notifications marked as read'); + }, + error: () => { + this.markAllReadPending = false; + this.alerts.error('Your notifications could not be marked as read'); + }, }); } @@ -230,9 +254,13 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { * noise. */ confirmDelete(notification: Notification): void { + if (this.isDeleting(notification)) { + return; + } + this.confirmationModal.show( 'Delete notification', - 'This removes the notification. You will not be able to get it back.', + `Delete "${notification.message}"? This removes the notification permanently.`, () => this.remove(notification), () => undefined, 'Delete', @@ -273,6 +301,10 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { return `Delete: ${notification.message}`; } + isDeleting(notification: Notification): boolean { + return this.deletingNotificationIds.has(notification.id); + } + timeAgo(notification: Notification): string { return moment(notification.createdAt).fromNow(); } @@ -313,10 +345,18 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { * something, which is a worse story than it not having worked. */ private remove(notification: Notification): void { + if (this.isDeleting(notification)) { + return; + } + + this.deletingNotificationIds.add(notification.id); this.cancelPendingList(); + const visibleIndex = this.visible.indexOf(notification); + this.notificationService.remove(notification).subscribe({ next: () => { + this.deletingNotificationIds.delete(notification.id); this.notifications = this.notifications.filter((row) => row !== notification); // Deleting the only row on the last page leaves the reader on a page @@ -325,11 +365,29 @@ export class NotificationsPageComponent implements OnInit, OnDestroy { this.pageIndex = Math.min(this.pageIndex, this.lastPageIndex()); this.updateVisible(); this.alerts.success('Notification deleted'); + this.changeDetectorRef.detectChanges(); + this.restoreFocusAfterDelete(visibleIndex); + }, + error: () => { + this.deletingNotificationIds.delete(notification.id); + this.alerts.error('That notification could not be deleted'); }, - error: () => this.alerts.error('That notification could not be deleted'), }); } + private restoreFocusAfterDelete(previousIndex: number): void { + if (document.activeElement !== document.body) { + return; + } + + const rows = Array.from( + this.elementRef.nativeElement.querySelectorAll<HTMLElement>('.notification-row'), + ); + const nextIndex = Math.min(Math.max(previousIndex, 0), rows.length - 1); + + rows[nextIndex]?.focus(); + } + private updateVisible(): void { const start = this.pageIndex * this.pageSize; this.visible = this.notifications.slice(start, start + this.pageSize); From ef16e33ff65965c61225c5f6d5033d15102ade4d Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 13:20:28 +1000 Subject: [PATCH 1401/1531] fix: wait for authenticated settings readiness --- .../api/services/authentication.service.ts | 160 ++++++++++-- .../spec/authentication.service.spec.ts | 241 +++++++++++++++++- .../constants/doubtfire-constants.spec.ts | 25 +- .../config/constants/doubtfire-constants.ts | 15 ++ .../accept-eula/accept-eula.component.spec.ts | 71 +++++- .../eula/accept-eula/accept-eula.component.ts | 23 +- 6 files changed, 482 insertions(+), 53 deletions(-) diff --git a/src/app/api/services/authentication.service.ts b/src/app/api/services/authentication.service.ts index 6574c4bccf..e896b77561 100644 --- a/src/app/api/services/authentication.service.ts +++ b/src/app/api/services/authentication.service.ts @@ -1,7 +1,20 @@ import {HttpClient} from '@angular/common/http'; import {Injectable} from '@angular/core'; import {Router} from '@angular/router'; -import {AsyncSubject, Observable, catchError, map, throwError} from 'rxjs'; +import { + AsyncSubject, + EMPTY, + Observable, + Subject, + Subscription, + catchError, + map, + of, + switchMap, + takeUntil, + tap, + throwError, +} from 'rxjs'; import {User, UserService} from 'src/app/api/models/doubtfire-model'; import {NotificationService} from 'src/app/api/services/notification.service'; import {PushNotificationService} from 'src/app/api/services/push-notification.service'; @@ -46,6 +59,25 @@ export class AuthenticationService { */ private authComplete$: AsyncSubject<boolean> = new AsyncSubject<boolean>(); + /** + * Cancels a protected settings request as soon as sign out starts. A plain + * Subject is intentional: requests created by a later session must not see a + * previous session's cancellation event. + */ + private authenticatedSettingsCancellation$: Subject<void> = new Subject<void>(); + + /** + * Changes on sign out so a response belonging to an earlier session cannot + * publish settings or complete authentication for the current session. + */ + private authenticationGeneration = 0; + + /** + * Only the newest settings response for the current session may update the + * singleton constants. Token refresh can legitimately overlap a prior read. + */ + private authenticatedSettingsRequestId = 0; + constructor( private httpClient: HttpClient, private userService: UserService, @@ -80,18 +112,33 @@ export class AuthenticationService { return; } + const authenticationGeneration = this.authenticationGeneration; + // Attempt to get an access token using the refresh token cookie this.httpClient.post(this.AUTH_URL + '/access-token', {}).subscribe({ next: (response: AuthResponse | null) => { + if (authenticationGeneration !== this.authenticationGeneration) { + return; + } + if (response && response.auth_token) { - this.setupUserFromResponse(response, firstTime); - loginResultCallback(true); + this.setupUserFromResponse(response, firstTime, authenticationGeneration).subscribe({ + next: () => loginResultCallback(true), + error: () => { + this.actionAuthFailed(); + loginResultCallback(false); + }, + }); } else { this.actionAuthFailed(); loginResultCallback(false); } }, error: (_error) => { + if (authenticationGeneration !== this.authenticationGeneration) { + return; + } + // Will occur on 404 when the refresh token cookie is not present this.actionAuthFailed(); loginResultCallback(false); @@ -165,13 +212,54 @@ export class AuthenticationService { ); } - private loadAuthenticatedSettings(): void { + private isCurrentAuthentication(userId: number, authenticationGeneration: number): boolean { + return ( + authenticationGeneration === this.authenticationGeneration && + userId === this.userService.currentUser.id && + !!this.userService.currentUser.authenticationToken + ); + } + + private loadAuthenticatedSettings( + userId: number, + authenticationGeneration: number, + ): Observable<void> { const url: string = `${this.doubtfireConstants.API_URL}/settings`; + const requestId = ++this.authenticatedSettingsRequestId; + + return this.httpClient.get<AuthenticatedSettingsResponseFormat>(url).pipe( + takeUntil(this.authenticatedSettingsCancellation$), + switchMap((settings) => { + if ( + !this.isCurrentAuthentication(userId, authenticationGeneration) || + requestId !== this.authenticatedSettingsRequestId + ) { + return EMPTY; + } - this.httpClient.get<AuthenticatedSettingsResponseFormat>(url).subscribe({ - next: (settings) => this.doubtfireConstants.applyAuthenticatedSettings(settings), - error: (error) => console.error('Unable to load authenticated settings', error), - }); + this.doubtfireConstants.applyAuthenticatedSettings(settings); + + return of(void 0); + }), + catchError((error) => { + if ( + !this.isCurrentAuthentication(userId, authenticationGeneration) || + requestId !== this.authenticatedSettingsRequestId + ) { + return EMPTY; + } + + // A failed settings read must not leave a previous session's feature + // flags or VAPID key active. Stale overlapping requests return above and + // cannot reset or publish authentication readiness. + this.doubtfireConstants.resetAuthenticatedSettings(); + console.error('Unable to load authenticated settings', error); + + // Settings are fail closed, but their availability must not turn valid + // credentials into a failed sign in. + return of(void 0); + }), + ); } /** @@ -180,7 +268,11 @@ export class AuthenticationService { * * @param response the response from the authentication API */ - private setupUserFromResponse(response: AuthResponse, firstTime: boolean = true): void { + private setupUserFromResponse( + response: AuthResponse, + firstTime: boolean = true, + authenticationGeneration: number = this.authenticationGeneration, + ): Observable<void> { // Extract relevant data from response and construct user object to store in cache. const user: User = this.userService.cache.getOrCreate( response.user['id'], @@ -195,19 +287,23 @@ export class AuthenticationService { // Record the current user this.userService.currentUser = user; - // Load feature flags using the newly issued authentication token. - this.loadAuthenticatedSettings(); - - if (firstTime) { - // Load everything! - AppInjector.get(GlobalStateService).loadGlobals(); - // Update token in one hour - setTimeout(() => this.cycleAccessToken(), 1000 * 60 * 60); - } + // Feature flags are part of authentication readiness. Consumers use their + // current values synchronously, so do not load globals, publish authComplete + // or complete signIn until this authenticated request has settled. + return this.loadAuthenticatedSettings(user.id, authenticationGeneration).pipe( + tap(() => { + if (firstTime) { + // Load everything! + AppInjector.get(GlobalStateService).loadGlobals(); + // Update token in one hour + setTimeout(() => this.cycleAccessToken(), 1000 * 60 * 60); + } - // Inidcate that the authentication was successful - this.authComplete$.next(true); - this.authComplete$.complete(); + // Indicate that authentication and its protected settings are ready. + this.authComplete$.next(true); + this.authComplete$.complete(); + }), + ); } /** @@ -218,8 +314,8 @@ export class AuthenticationService { * * @param callback the callback function to call */ - public afterAuthCall(callback: (result: boolean) => void): void { - this.authComplete$.subscribe({ + public afterAuthCall(callback: (result: boolean) => void): Subscription { + return this.authComplete$.subscribe({ next: (result) => { callback(result); }, @@ -239,10 +335,14 @@ export class AuthenticationService { remember: boolean; }, ): Observable<void> { + const authenticationGeneration = this.authenticationGeneration; + return this.httpClient.post(this.AUTH_URL, userCredentials).pipe( - map((response: AuthResponse) => { - this.setupUserFromResponse(response); - }), + switchMap((response: AuthResponse) => + authenticationGeneration === this.authenticationGeneration + ? this.setupUserFromResponse(response, true, authenticationGeneration) + : EMPTY, + ), catchError((error) => { // this.authComplete$.next(false); // this.authComplete$.complete(); @@ -269,6 +369,14 @@ export class AuthenticationService { } public signOut(ssoSignOut = true): void { + // Invalidate authentication work before the asynchronous push and token + // teardown. This prevents a late /settings response from restoring values + // after sign out or completing an obsolete sign-in observable. + this.authenticationGeneration += 1; + this.authenticatedSettingsRequestId += 1; + this.authenticatedSettingsCancellation$.next(); + this.doubtfireConstants.resetAuthenticatedSettings(); + // This function is called after the token is deleted... const doSignOut = () => { // Setup ability to auth again diff --git a/src/app/api/services/spec/authentication.service.spec.ts b/src/app/api/services/spec/authentication.service.spec.ts index ae718e722b..0e450b95d5 100644 --- a/src/app/api/services/spec/authentication.service.spec.ts +++ b/src/app/api/services/spec/authentication.service.spec.ts @@ -5,7 +5,7 @@ import {Injector} from '@angular/core'; import {TestBed} from '@angular/core/testing'; import {Router} from '@angular/router'; import {Subject, of, throwError} from 'rxjs'; -import {UserService} from 'src/app/api/models/doubtfire-model'; +import {User, UserService} from 'src/app/api/models/doubtfire-model'; import {AppInjector, setAppInjector} from 'src/app/app-injector'; import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; @@ -29,7 +29,7 @@ const AUTH_URL = `${API_URL}/auth`; * push-notification.service.spec.ts. Here PushNotificationService is a mock so * these tests only describe what AuthenticationService.signOut does with it. */ -describe('AuthenticationService sign out', () => { +describe('AuthenticationService', () => { let service: AuthenticationService; let httpMock: HttpTestingController; @@ -42,11 +42,20 @@ describe('AuthenticationService sign out', () => { loadGlobals: ReturnType<typeof vi.fn>; }; let userService: { - currentUser: {authenticationToken?: string}; - anonymousUser: {authenticationToken?: string}; - cache: {clear: ReturnType<typeof vi.fn>}; + currentUser: Partial<User>; + anonymousUser: Partial<User>; + cache: { + clear: ReturnType<typeof vi.fn>; + getOrCreate: ReturnType<typeof vi.fn>; + }; }; let router: {navigateByUrl: ReturnType<typeof vi.fn>}; + let constants: { + API_URL: string; + SignoutURL: string | undefined; + applyAuthenticatedSettings: ReturnType<typeof vi.fn>; + resetAuthenticatedSettings: ReturnType<typeof vi.fn>; + }; // signOut resolves PushNotificationService, GlobalStateService and // NotificationService through AppInjector rather than the constructor (its @@ -85,13 +94,25 @@ describe('AuthenticationService sign out', () => { loadGlobals: vi.fn(), }; - const anonymousUser = {authenticationToken: undefined}; + const anonymousUser: Partial<User> = {authenticationToken: undefined}; userService = { - currentUser: {authenticationToken: 'token-for-user-a'}, + currentUser: {id: 1, username: 'user-a', authenticationToken: 'token-for-user-a'}, anonymousUser, - cache: {clear: vi.fn()}, + cache: { + clear: vi.fn(), + getOrCreate: vi.fn((id: number, _service: UserService, data: object) => ({ + ...data, + id, + })), + }, }; router = {navigateByUrl: vi.fn()}; + constants = { + API_URL, + SignoutURL: undefined, + applyAuthenticatedSettings: vi.fn(), + resetAuthenticatedSettings: vi.fn(), + }; if (!AppInjector) { setAppInjector(injectorStub); @@ -103,7 +124,7 @@ describe('AuthenticationService sign out', () => { {provide: UserService, useValue: userService as unknown as UserService}, {provide: Router, useValue: router}, {provide: AlertService, useValue: {error: vi.fn()}}, - {provide: DoubtfireConstants, useValue: {API_URL, SignoutURL: undefined}}, + {provide: DoubtfireConstants, useValue: constants}, provideHttpClient(withXhr(), withInterceptorsFromDi()), provideHttpClientTesting(), ], @@ -115,8 +136,28 @@ describe('AuthenticationService sign out', () => { afterEach(() => { httpMock.verify(); + vi.restoreAllMocks(); }); + const authResponse = (id: number, token: string) => ({ + user: { + id, + username: `user-${id}`, + systemRole: 'Student', + hasRunFirstTimeSetup: true, + }, + auth_token: token, + auth_token_expiry: '2099-01-01T00:00:00Z', + }); + + const authenticatedSettings = { + overseerEnabled: true, + tiiEnabled: true, + d2lEnabled: false, + pushEnabled: true, + vapidPublicKey: 'BCurrentVapidKey', + }; + // The shared computer case. The push registration belongs to whoever enabled // it and the browser keeps it across sign out, so it has to be dropped while // the token is still valid. DELETE /push_subscriptions needs that token, which @@ -129,6 +170,7 @@ describe('AuthenticationService sign out', () => { service.signOut(); expect(pushService.unsubscribeQuietly).toHaveBeenCalledTimes(1); + expect(constants.resetAuthenticatedSettings).toHaveBeenCalledTimes(1); // The token is still needed for the push delete, so it must not be gone yet. httpMock.expectNone((r) => r.url === AUTH_URL && r.method === 'DELETE'); @@ -173,7 +215,188 @@ describe('AuthenticationService sign out', () => { service.signOut(); expect(pushService.unsubscribeQuietly).not.toHaveBeenCalled(); + expect(constants.resetAuthenticatedSettings).toHaveBeenCalledTimes(1); httpMock.expectNone((r) => r.url === AUTH_URL && r.method === 'DELETE'); expect(userService.currentUser).toBe(userService.anonymousUser); }); + + it('does not complete sign in until authenticated settings are applied', () => { + const afterAuth = vi.fn(); + const signInNext = vi.fn(); + service.afterAuthCall(afterAuth); + + service + .signIn({username: 'user-1', password: 'password', remember: false}) + .subscribe(signInNext); + + httpMock + .expectOne((r) => r.url === AUTH_URL && r.method === 'POST') + .flush(authResponse(1, 't1')); + + const settingsRequest = httpMock.expectOne(`${API_URL}/settings`); + expect(constants.applyAuthenticatedSettings).not.toHaveBeenCalled(); + expect(globalState.loadGlobals).not.toHaveBeenCalled(); + expect(afterAuth).not.toHaveBeenCalled(); + expect(signInNext).not.toHaveBeenCalled(); + + settingsRequest.flush(authenticatedSettings); + + expect(constants.applyAuthenticatedSettings).toHaveBeenCalledWith(authenticatedSettings); + expect(constants.applyAuthenticatedSettings.mock.invocationCallOrder[0]).toBeLessThan( + globalState.loadGlobals.mock.invocationCallOrder[0], + ); + expect(afterAuth).toHaveBeenCalledWith(true); + expect(signInNext).toHaveBeenCalledTimes(1); + }); + + it('waits for authenticated settings before reporting a restored session', () => { + const loginResult = vi.fn(); + + service.attemptLoginUsingRefreshToken(loginResult); + + httpMock + .expectOne((r) => r.url === `${AUTH_URL}/access-token` && r.method === 'POST') + .flush(authResponse(1, 'refreshed-token')); + + const settingsRequest = httpMock.expectOne(`${API_URL}/settings`); + expect(loginResult).not.toHaveBeenCalled(); + + settingsRequest.flush(authenticatedSettings); + + expect(loginResult).toHaveBeenCalledWith(true); + }); + + it('fails settings closed without rejecting valid credentials', () => { + const consoleError = vi.spyOn(console, 'error').mockImplementation(() => undefined); + const afterAuth = vi.fn(); + const signInNext = vi.fn(); + service.afterAuthCall(afterAuth); + + service + .signIn({username: 'user-1', password: 'password', remember: false}) + .subscribe(signInNext); + + httpMock + .expectOne((r) => r.url === AUTH_URL && r.method === 'POST') + .flush(authResponse(1, 't1')); + httpMock.expectOne(`${API_URL}/settings`).flush( + {error: 'unavailable'}, + { + status: 500, + statusText: 'Server Error', + }, + ); + + expect(constants.resetAuthenticatedSettings).toHaveBeenCalledTimes(1); + expect(constants.applyAuthenticatedSettings).not.toHaveBeenCalled(); + expect(globalState.loadGlobals).toHaveBeenCalledTimes(1); + expect(afterAuth).toHaveBeenCalledWith(true); + expect(signInNext).toHaveBeenCalledTimes(1); + expect(consoleError).toHaveBeenCalled(); + }); + + it('cancels pending settings and authentication completion when sign out starts', () => { + const afterAuth = vi.fn(); + const signInNext = vi.fn(); + service.afterAuthCall(afterAuth); + + service + .signIn({username: 'user-1', password: 'password', remember: false}) + .subscribe(signInNext); + + httpMock + .expectOne((r) => r.url === AUTH_URL && r.method === 'POST') + .flush(authResponse(1, 't1')); + const settingsRequest = httpMock.expectOne(`${API_URL}/settings`); + + service.signOut(false); + + expect(settingsRequest.cancelled).toBe(true); + expect(constants.resetAuthenticatedSettings).toHaveBeenCalledTimes(1); + expect(constants.applyAuthenticatedSettings).not.toHaveBeenCalled(); + expect(globalState.loadGlobals).not.toHaveBeenCalled(); + expect(afterAuth).not.toHaveBeenCalled(); + expect(signInNext).not.toHaveBeenCalled(); + + httpMock.expectOne((r) => r.url === AUTH_URL && r.method === 'DELETE').flush(null); + }); + + it('does not complete from an older settings response for the same user', () => { + const afterAuth = vi.fn(); + const firstSignInNext = vi.fn(); + const secondSignInNext = vi.fn(); + service.afterAuthCall(afterAuth); + + service + .signIn({username: 'user-1', password: 'password', remember: false}) + .subscribe(firstSignInNext); + httpMock + .expectOne((r) => r.url === AUTH_URL && r.method === 'POST') + .flush(authResponse(1, 't1')); + const firstSettingsRequest = httpMock.expectOne(`${API_URL}/settings`); + + service + .signIn({username: 'user-1', password: 'password', remember: false}) + .subscribe(secondSignInNext); + httpMock + .expectOne((r) => r.url === AUTH_URL && r.method === 'POST') + .flush(authResponse(1, 't2')); + const secondSettingsRequest = httpMock.expectOne(`${API_URL}/settings`); + + firstSettingsRequest.flush({...authenticatedSettings, vapidPublicKey: 'BStaleKey'}); + + expect(constants.applyAuthenticatedSettings).not.toHaveBeenCalled(); + expect(globalState.loadGlobals).not.toHaveBeenCalled(); + expect(afterAuth).not.toHaveBeenCalled(); + expect(firstSignInNext).not.toHaveBeenCalled(); + + secondSettingsRequest.flush(authenticatedSettings); + + expect(constants.applyAuthenticatedSettings).toHaveBeenCalledOnce(); + expect(constants.applyAuthenticatedSettings).toHaveBeenCalledWith(authenticatedSettings); + expect(afterAuth).toHaveBeenCalledWith(true); + expect(secondSignInNext).toHaveBeenCalledTimes(1); + }); + + it('does not reset or complete from an older settings failure for the same user', () => { + const afterAuth = vi.fn(); + const firstSignInNext = vi.fn(); + const secondSignInNext = vi.fn(); + service.afterAuthCall(afterAuth); + + service + .signIn({username: 'user-1', password: 'password', remember: false}) + .subscribe(firstSignInNext); + httpMock + .expectOne((r) => r.url === AUTH_URL && r.method === 'POST') + .flush(authResponse(1, 't1')); + const firstSettingsRequest = httpMock.expectOne(`${API_URL}/settings`); + + service + .signIn({username: 'user-1', password: 'password', remember: false}) + .subscribe(secondSignInNext); + httpMock + .expectOne((r) => r.url === AUTH_URL && r.method === 'POST') + .flush(authResponse(1, 't2')); + const secondSettingsRequest = httpMock.expectOne(`${API_URL}/settings`); + + firstSettingsRequest.flush( + {error: 'stale failure'}, + { + status: 500, + statusText: 'Server Error', + }, + ); + + expect(constants.resetAuthenticatedSettings).not.toHaveBeenCalled(); + expect(globalState.loadGlobals).not.toHaveBeenCalled(); + expect(afterAuth).not.toHaveBeenCalled(); + expect(firstSignInNext).not.toHaveBeenCalled(); + + secondSettingsRequest.flush(authenticatedSettings); + + expect(constants.applyAuthenticatedSettings).toHaveBeenCalledWith(authenticatedSettings); + expect(afterAuth).toHaveBeenCalledWith(true); + expect(secondSignInNext).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/app/config/constants/doubtfire-constants.spec.ts b/src/app/config/constants/doubtfire-constants.spec.ts index 09c8c67e09..3a87a6e08c 100644 --- a/src/app/config/constants/doubtfire-constants.spec.ts +++ b/src/app/config/constants/doubtfire-constants.spec.ts @@ -199,9 +199,8 @@ describe('DoubtfireConstants', () => { * and neither push field. The assertion is what makes the ?? in * applyAuthenticatedSettings load bearing rather than decoration. * - * The cast is deliberate. AuthenticatedSettingsResponseFormat declares both - * push fields as required, which is the right contract for the current api, so - * an object without them is only reachable in a test by asserting past it. + * AuthenticatedSettingsResponseFormat keeps the two push fields optional for + * this staged-deployment case. */ it('leaves push disabled when the api omits the push fields entirely', () => { const service = bootstrap(); @@ -247,4 +246,24 @@ describe('DoubtfireConstants', () => { expect(service.IsPushEnabled.value).toBe(false); expect(service.VapidPublicKey.value).toBe(''); }); + + it('resets every authenticated setting to its signed-out default', () => { + const service = bootstrap(); + + service.applyAuthenticatedSettings({ + overseerEnabled: true, + tiiEnabled: true, + d2lEnabled: true, + pushEnabled: true, + vapidPublicKey: 'BPreviousSessionKey', + }); + + service.resetAuthenticatedSettings(); + + expect(service.IsOverseerEnabled.value).toBe(false); + expect(service.IsTiiEnabled.value).toBe(false); + expect(service.IsD2LEnabled.value).toBe(false); + expect(service.IsPushEnabled.value).toBe(false); + expect(service.VapidPublicKey.value).toBe(''); + }); }); diff --git a/src/app/config/constants/doubtfire-constants.ts b/src/app/config/constants/doubtfire-constants.ts index 7f04049682..794efa4a98 100644 --- a/src/app/config/constants/doubtfire-constants.ts +++ b/src/app/config/constants/doubtfire-constants.ts @@ -149,4 +149,19 @@ export class DoubtfireConstants { this.IsPushEnabled.next(result.pushEnabled ?? false); this.VapidPublicKey.next(result.vapidPublicKey ?? ''); } + + /** + * Remove configuration that may only be used by an authenticated session. + * + * DoubtfireConstants is a root singleton, so these subjects otherwise retain + * the previous session's values after sign out. Keep the defaults fail closed + * while signed out and when the authenticated settings request fails. + */ + public resetAuthenticatedSettings(): void { + this.IsOverseerEnabled.next(false); + this.IsTiiEnabled.next(false); + this.IsD2LEnabled.next(false); + this.IsPushEnabled.next(false); + this.VapidPublicKey.next(''); + } } diff --git a/src/app/eula/accept-eula/accept-eula.component.spec.ts b/src/app/eula/accept-eula/accept-eula.component.spec.ts index 9912d785e5..90b765c3fa 100644 --- a/src/app/eula/accept-eula/accept-eula.component.spec.ts +++ b/src/app/eula/accept-eula/accept-eula.component.spec.ts @@ -1,33 +1,56 @@ -import {beforeEach, describe, expect, it} from 'vitest'; +import {beforeEach, describe, expect, it, vi} from 'vitest'; import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {Router} from '@angular/router'; -import {EMPTY} from 'rxjs'; +import {BehaviorSubject, Subscription, of} from 'rxjs'; import {UserService} from 'src/app/api/models/doubtfire-model'; +import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {TiiService} from 'src/app/api/services/tii.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {AcceptEulaComponent} from './accept-eula.component'; -const constantsStub = { - ExternalName: EMPTY, - IsTiiEnabled: EMPTY, -}; const emptyProvider = {}; describe('AcceptEulaComponent', () => { let component: AcceptEulaComponent; let fixture: ComponentFixture<AcceptEulaComponent>; + let afterAuthCallback: ((authenticated: boolean) => void) | undefined; + let authenticationSubscription: Subscription; + let tiiEnabled: BehaviorSubject<boolean>; + let tiiService: {getTiiEula: ReturnType<typeof vi.fn>}; + let router: {navigateByUrl: ReturnType<typeof vi.fn>}; beforeEach(async () => { + afterAuthCallback = undefined; + authenticationSubscription = new Subscription(); + tiiEnabled = new BehaviorSubject<boolean>(false); + tiiService = {getTiiEula: vi.fn().mockReturnValue(of('<p>EULA</p>'))}; + router = {navigateByUrl: vi.fn()}; + await TestBed.configureTestingModule({ declarations: [AcceptEulaComponent], providers: [ - {provide: DoubtfireConstants, useValue: constantsStub}, - {provide: TiiService, useValue: emptyProvider}, + { + provide: DoubtfireConstants, + useValue: { + ExternalName: of('OnTrack'), + IsTiiEnabled: tiiEnabled, + }, + }, + { + provide: AuthenticationService, + useValue: { + afterAuthCall: vi.fn((callback: (authenticated: boolean) => void) => { + afterAuthCallback = callback; + return authenticationSubscription; + }), + }, + }, + {provide: TiiService, useValue: tiiService}, {provide: UserService, useValue: emptyProvider}, {provide: AlertService, useValue: emptyProvider}, - {provide: Router, useValue: emptyProvider}, + {provide: Router, useValue: router}, ], schemas: [NO_ERRORS_SCHEMA], }) @@ -43,4 +66,34 @@ describe('AcceptEulaComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('does not treat the pre-authentication TurnItIn default as a disabled feature', () => { + expect(afterAuthCallback).toBeDefined(); + expect(router.navigateByUrl).not.toHaveBeenCalled(); + expect(tiiService.getTiiEula).not.toHaveBeenCalled(); + }); + + it('loads the EULA after authenticated settings enable TurnItIn', () => { + tiiEnabled.next(true); + + afterAuthCallback?.(true); + + expect(tiiService.getTiiEula).toHaveBeenCalledTimes(1); + expect(router.navigateByUrl).not.toHaveBeenCalled(); + }); + + it('redirects after authenticated settings disable TurnItIn', () => { + afterAuthCallback?.(true); + + expect(tiiService.getTiiEula).not.toHaveBeenCalled(); + expect(router.navigateByUrl).toHaveBeenCalledWith('/home'); + }); + + it('stops waiting for authentication when the component is destroyed', () => { + const unsubscribe = vi.spyOn(authenticationSubscription, 'unsubscribe'); + + fixture.destroy(); + + expect(unsubscribe).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/app/eula/accept-eula/accept-eula.component.ts b/src/app/eula/accept-eula/accept-eula.component.ts index a8c0ede0e0..cd59a8ee4e 100644 --- a/src/app/eula/accept-eula/accept-eula.component.ts +++ b/src/app/eula/accept-eula/accept-eula.component.ts @@ -1,7 +1,8 @@ -import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component, OnDestroy} from '@angular/core'; import {Router} from '@angular/router'; -import {Observable, ReplaySubject, take} from 'rxjs'; +import {Observable, ReplaySubject, Subscription, take} from 'rxjs'; import {UserService} from 'src/app/api/models/doubtfire-model'; +import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {TiiService} from 'src/app/api/services/tii.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; @@ -13,21 +14,27 @@ import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; changeDetection: ChangeDetectionStrategy.Eager, standalone: false, }) -export class AcceptEulaComponent { +export class AcceptEulaComponent implements OnDestroy { public toolName: Observable<string>; public eulaHtml: string; public iframeDoc$: ReplaySubject<Document> = new ReplaySubject(1); + private authenticationSubscription: Subscription; + constructor( private constants: DoubtfireConstants, + private authenticationService: AuthenticationService, private tiiService: TiiService, private userService: UserService, private alertService: AlertService, private router: Router, ) { - this.constants.IsTiiEnabled.subscribe((enabled) => { - if (enabled) { + // Auth completion now includes the protected settings request. Do not react + // to IsTiiEnabled's pre-authentication false default: on a cold /eula load + // that used to redirect before a remembered session could be restored. + this.authenticationSubscription = this.authenticationService.afterAuthCall((authenticated) => { + if (authenticated && this.constants.IsTiiEnabled.value) { this.getEulaHtml(); } else { this.router.navigateByUrl('/home'); @@ -37,7 +44,11 @@ export class AcceptEulaComponent { this.toolName = constants.ExternalName; } - public getEulaHtml() { + public ngOnDestroy(): void { + this.authenticationSubscription.unsubscribe(); + } + + public getEulaHtml(): void { this.tiiService.getTiiEula().subscribe((eulaHtml) => { this.eulaHtml = eulaHtml; this.updateHtmlEulaInIFrame(); From 2f0ca9418c61936b38bdc3bb02da578d4619cf44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 04:27:16 +0000 Subject: [PATCH 1402/1531] chore(deps): bump fast-uri from 3.1.2 to 3.1.6 Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.2 to 3.1.6. - [Release notes](https://github.com/fastify/fast-uri/releases) - [Commits](https://github.com/fastify/fast-uri/compare/v3.1.2...v3.1.6) --- updated-dependencies: - dependency-name: fast-uri dependency-version: 3.1.6 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d9f7c5679d..8b92b921e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9998,9 +9998,9 @@ } }, "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.6.tgz", + "integrity": "sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==", "dev": true, "funding": [ { From f727f7945a7eab29fa2939f5c7596fa9ab883faf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 04:27:18 +0000 Subject: [PATCH 1403/1531] chore(deps-dev): bump js-yaml from 4.2.0 to 4.3.1 Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.2.0 to 4.3.1. - [Changelog](https://github.com/nodeca/js-yaml/blob/4.3.1/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.2.0...4.3.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.3.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d9f7c5679d..c49f6345a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10897,9 +10897,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, "funding": [ { From a02e90fd9b97e8d6a7563e2c86ed054fd2ab9dba Mon Sep 17 00:00:00 2001 From: The Herald Sun <samuelryanmason@gmail.com> Date: Sun, 23 Aug 2026 05:24:52 +0000 Subject: [PATCH 1404/1531] fix: accidentaly messed up the providers last commit --- src/app/doubtfire-angular.module.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 60959f626a..c147d9abd8 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -756,6 +756,7 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { StaffNoteService, SidekiqJobService, LtiService, + InstallPromptService, TaskPrerequisiteService, MarkingSessionService, DiscussionPromptService, From e69e5d457fd6423ef771837d5a26b9a18a55d083 Mon Sep 17 00:00:00 2001 From: The Herald Sun <samuelryanmason@gmail.com> Date: Sun, 23 Aug 2026 05:43:00 +0000 Subject: [PATCH 1405/1531] fix(pwa): add InstallPromptService to the providers --- src/app/doubtfire-angular.module.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index c147d9abd8..35516567e0 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -714,6 +714,7 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { EmojiService, FileDownloaderService, CheckForUpdateService, + InstallPromptService, TaskOutcomeAlignmentService, // rootScopeProvider, {provide: MAT_DATE_LOCALE, useValue: enAU}, From 533235220cf7516c3d1df3fb6b9fce44b554dc82 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 21:14:57 +1000 Subject: [PATCH 1406/1531] fix(pwa): remove duplicate install prompt provider --- src/app/doubtfire-angular.module.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 35516567e0..6de63d3cfb 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -757,7 +757,6 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { StaffNoteService, SidekiqJobService, LtiService, - InstallPromptService, TaskPrerequisiteService, MarkingSessionService, DiscussionPromptService, From 2959671bab42f9552a8192ed1414adfa900d261e Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 22:18:28 +1000 Subject: [PATCH 1407/1531] fix(integration): remove non-portable node_modules symlink --- node_modules | 1 - 1 file changed, 1 deletion(-) delete mode 120000 node_modules diff --git a/node_modules b/node_modules deleted file mode 120000 index a13f6c1984..0000000000 --- a/node_modules +++ /dev/null @@ -1 +0,0 @@ -/Users/clupa/Documents/uni/sit374/ontrack/doubtfire-web/node_modules \ No newline at end of file From f2802bc7b0c3ecd90fed7b877892164c3f46223e Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 13:04:02 +1000 Subject: [PATCH 1408/1531] fix: show due date warnings on student dashboard --- .../f-cross-dashboard.component.spec.ts | 18 +++ .../dashboard/f-cross-dashboard.component.ts | 3 +- .../dashboard-list-item.component.html | 18 ++- .../dashboard-list-item.component.spec.ts | 112 +++++++++++++++++- .../dashboard-list-item.component.ts | 43 +++++++ .../unit-task-editor.component.html | 96 ++------------- .../unit-task-editor.component.ts | 90 +++----------- 7 files changed, 218 insertions(+), 162 deletions(-) diff --git a/src/app/dashboard/f-cross-dashboard.component.spec.ts b/src/app/dashboard/f-cross-dashboard.component.spec.ts index 7e372675d7..8dc2e37c30 100644 --- a/src/app/dashboard/f-cross-dashboard.component.spec.ts +++ b/src/app/dashboard/f-cross-dashboard.component.spec.ts @@ -47,6 +47,8 @@ describe('CrossDashboardComponent', () => { status, topWeight, numNewComments: 0, + localDueDate: vi.fn().mockReturnValue(dueDate), + inSubmittedState: vi.fn().mockReturnValue(TaskStatus.SUBMITTED_STATUSES.includes(status)), definition: { name, abbreviation, @@ -154,6 +156,22 @@ describe('CrossDashboardComponent', () => { ]); }); + it('maps each task using its effective due date and submitted state', () => { + const targetDate = makeDate(30); + const effectiveDate = makeDate(23); + const activeTask = makeTask('Active task', '1.1P', 'working_on_it', targetDate); + const submittedTask = makeTask('Submitted task', '1.2P', 'ready_for_feedback', targetDate); + + vi.mocked(activeTask.localDueDate).mockReturnValue(effectiveDate); + projectsSubject.next([makeProject(1, 'COS10001', true, [activeTask, submittedTask])]); + + expect(component.activeUnits[0].tasks[0]).toMatchObject({ + dueDate: effectiveDate, + showDueWarning: true, + }); + expect(component.activeUnits[0].tasks[1].showDueWarning).toBe(false); + }); + it('loads and displays previous units in Previous units mode', () => { projectServiceQuery.mockReturnValue( of([makeProject(1, 'COS10001', true), makeProject(2, 'COS30046', false)]), diff --git a/src/app/dashboard/f-cross-dashboard.component.ts b/src/app/dashboard/f-cross-dashboard.component.ts index 2ea5dd01f2..cd6bd40b6b 100644 --- a/src/app/dashboard/f-cross-dashboard.component.ts +++ b/src/app/dashboard/f-cross-dashboard.component.ts @@ -561,7 +561,8 @@ export class CrossDashboardComponent implements OnInit { description: def.description, taskDef: def, unitCode, - dueDate: def.targetDate, + dueDate: task.localDueDate(), + showDueWarning: !task.inSubmittedState(), }; }); } diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.html b/src/app/dashboard/list-item/dashboard-list-item.component.html index 935a18ca12..6e77d556a9 100644 --- a/src/app/dashboard/list-item/dashboard-list-item.component.html +++ b/src/app/dashboard/list-item/dashboard-list-item.component.html @@ -7,7 +7,23 @@ > {{ task.title }} </h4> - <p class="mb-0">{{ task.subtitle }}</p> + <div class="flex flex-wrap items-center gap-2"> + <p class="mb-0">{{ task.subtitle }}</p> + @if (dueDateWarning; as warning) { + <span + class="inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium whitespace-nowrap" + [ngClass]="{ + 'bg-red-100 text-red-800': warning.state === 'overdue', + 'bg-orange-100 text-orange-800': warning.state === 'within24Hours', + 'bg-yellow-100 text-yellow-900': warning.state === 'within3Days', + 'bg-blue-100 text-blue-800': warning.state === 'within7Days', + }" + > + <mat-icon aria-hidden="true" class="!size-3.5 !text-sm">{{ warning.icon }}</mat-icon> + <span>{{ warning.label }}</span> + </span> + } + </div> <p class="mt-1 mb-0 text-sm font-medium">Status: {{ task.statusLabel }}</p> </div> <div class="mr-6 ml-2 flex flex-row items-center justify-end gap-4"> diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts b/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts index 876935f265..ac80323d60 100644 --- a/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts +++ b/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts @@ -4,9 +4,80 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; import {MatButtonModule} from '@angular/material/button'; import {MatIconModule} from '@angular/material/icon'; import {TaskDefinition} from '../../api/models/task-definition'; -import {DashboardListItemComponent, DashboardTask} from './dashboard-list-item.component'; +import { + DashboardListItemComponent, + DashboardTask, + getDueDateWarning, +} from './dashboard-list-item.component'; + +describe('getDueDateWarning', () => { + const now = new Date('2026-08-23T00:00:00.000Z'); + const day = 24 * 60 * 60 * 1000; + + it.each([ + {offset: -1, state: 'overdue', label: 'Overdue', icon: 'error'}, + { + offset: day, + state: 'within24Hours', + label: 'Due within 24 hours', + icon: 'schedule', + }, + { + offset: day + 1, + state: 'within3Days', + label: 'Due within 3 days', + icon: 'warning', + }, + { + offset: 3 * day, + state: 'within3Days', + label: 'Due within 3 days', + icon: 'warning', + }, + { + offset: 3 * day + 1, + state: 'within7Days', + label: 'Due within 7 days', + icon: 'event', + }, + { + offset: 7 * day, + state: 'within7Days', + label: 'Due within 7 days', + icon: 'event', + }, + ])('returns $state at the expected boundary', ({offset, state, label, icon}) => { + const dueDate = new Date(now.getTime() + offset); + + expect(getDueDateWarning(dueDate, true, now)).toEqual({state, label, icon}); + }); + + it('treats a task due now as due within 24 hours', () => { + expect(getDueDateWarning(now, true, now)?.state).toBe('within24Hours'); + }); + + it('does not warn more than seven days before the due date', () => { + const dueDate = new Date(now.getTime() + 7 * day + 1); + + expect(getDueDateWarning(dueDate, true, now)).toBeNull(); + }); + + it('does not warn for a submitted task', () => { + const overdueDate = new Date(now.getTime() - day); + + expect(getDueDateWarning(overdueDate, false, now)).toBeNull(); + }); + + it.each([null, undefined, new Date('invalid')])( + 'ignores a missing or invalid date', + (dueDate) => { + expect(getDueDateWarning(dueDate, true, now)).toBeNull(); + }, + ); +}); describe('DashboardListItemComponent', () => { + let component: DashboardListItemComponent; let fixture: ComponentFixture<DashboardListItemComponent>; beforeEach(async () => { @@ -17,7 +88,8 @@ describe('DashboardListItemComponent', () => { }).compileComponents(); fixture = TestBed.createComponent(DashboardListItemComponent); - fixture.componentInstance.task = { + component = fixture.componentInstance; + component.task = { title: 'Security Review', subtitle: '1.1P - Pass Task', statusLabel: 'Resubmit', @@ -33,6 +105,7 @@ describe('DashboardListItemComponent', () => { taskDef: {} as TaskDefinition, unitCode: 'SIT764', dueDate: new Date(2026, 7, 12), + showDueWarning: false, } satisfies DashboardTask; fixture.detectChanges(); }); @@ -53,4 +126,39 @@ describe('DashboardListItemComponent', () => { expect(button.getAttribute('aria-label')).toBe('Collapse Security Review details'); expect(button.getAttribute('aria-expanded')).toBe('true'); }); + + it('renders warning text and an icon alongside the separate status colour', () => { + fixture.componentRef.setInput('task', { + title: 'Accessible task', + subtitle: '1.1P - Pass Task', + statusLabel: 'Not Started', + abbreviation: '1.1P', + color: '#123456', + comments: 0, + status: 'not_started', + targetGrade: 0, + targetGradeLabel: 'Pass', + weight: 0, + projectId: 1, + description: 'Description', + taskDef: {} as DashboardTask['taskDef'], + unitCode: 'COS10001', + dueDate: new Date(Date.now() + 12 * 60 * 60 * 1000), + showDueWarning: true, + } satisfies DashboardTask); + + fixture.detectChanges(); + + expect(component.dueDateWarning?.state).toBe('within24Hours'); + + const badge = fixture.nativeElement.querySelector('.bg-orange-100') as HTMLElement; + const icon = badge.querySelector('mat-icon') as HTMLElement; + const statusStrip = fixture.nativeElement.firstElementChild.firstElementChild as HTMLElement; + + expect(badge.textContent).toContain('Due within 24 hours'); + expect(icon.textContent.trim()).toBe('schedule'); + expect(icon.getAttribute('aria-hidden')).toBe('true'); + expect(statusStrip.style.backgroundColor).toBe('rgb(18, 52, 86)'); + expect(fixture.nativeElement.textContent).toContain('Status: Not Started'); + }); }); diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.ts b/src/app/dashboard/list-item/dashboard-list-item.component.ts index b45332fcd4..04d128cf9a 100644 --- a/src/app/dashboard/list-item/dashboard-list-item.component.ts +++ b/src/app/dashboard/list-item/dashboard-list-item.component.ts @@ -2,6 +2,44 @@ import {Component, Input} from '@angular/core'; import {TaskDefinition} from '../../api/models/task-definition'; import {TaskStatusEnum} from '../../api/models/task-status'; +export type DueDateWarning = { + state: 'overdue' | 'within24Hours' | 'within3Days' | 'within7Days'; + label: string; + icon: string; +}; + +const DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000; + +export function getDueDateWarning( + dueDate: Date | null | undefined, + showWarning: boolean, + now: Date = new Date(), +): DueDateWarning | null { + if (!showWarning || !(dueDate instanceof Date) || Number.isNaN(dueDate.getTime())) { + return null; + } + + const millisecondsUntilDue = dueDate.getTime() - now.getTime(); + + if (millisecondsUntilDue < 0) { + return {state: 'overdue', label: 'Overdue', icon: 'error'}; + } + + if (millisecondsUntilDue <= DAY_IN_MILLISECONDS) { + return {state: 'within24Hours', label: 'Due within 24 hours', icon: 'schedule'}; + } + + if (millisecondsUntilDue <= 3 * DAY_IN_MILLISECONDS) { + return {state: 'within3Days', label: 'Due within 3 days', icon: 'warning'}; + } + + if (millisecondsUntilDue <= 7 * DAY_IN_MILLISECONDS) { + return {state: 'within7Days', label: 'Due within 7 days', icon: 'event'}; + } + + return null; +} + export type DashboardTask = { title: string; subtitle: string; @@ -18,6 +56,7 @@ export type DashboardTask = { taskDef: TaskDefinition; unitCode: string; dueDate: Date | null | undefined; + showDueWarning: boolean; }; @Component({ @@ -29,4 +68,8 @@ export class DashboardListItemComponent { @Input() task: DashboardTask; isExpanded = false; + + get dueDateWarning(): DueDateWarning | null { + return getDueDateWarning(this.task?.dueDate, this.task?.showDueWarning ?? false); + } } diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html index 0d95db5031..a239a50f97 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html @@ -4,30 +4,24 @@ <h3>Task List</h3> <p>Plan the list of tasks for students to complete.</p> </div> - <div class="flex flex-wrap items-center gap-3 md:justify-end"> <div class="flex items-center"> <label>Definitions CSV</label> - <div class="flex items-center"> <button mat-icon-button (click)="unit.downloadTaskDefinitionsCsv()"> <mat-icon>download</mat-icon> </button> - <button mat-icon-button (click)="uploadTaskDefinitionsCsv()"> <mat-icon>upload_file</mat-icon> </button> </div> </div> - <div class="flex items-center"> <label>Resources as Zip</label> - <div class="flex items-center"> <button mat-icon-button (click)="unit.downloadAllTaskResourcesZip()"> <mat-icon>download</mat-icon> </button> - <button mat-icon-button (click)="uploadTaskResourcesZip()"> <mat-icon>upload_file</mat-icon> </button> @@ -35,17 +29,11 @@ <h3>Task List</h3> </div> </div> </div> - <div class="my-2 flex w-full items-center justify-end gap-2"> @if (unit.allowFlexibleDates) { - <button mat-raised-button (click)="manageDueDates = !manageDueDates"> - Manage Due Dates - </button> + <button mat-raised-button (click)="manageDueDates = !manageDueDates">Manage Due Dates</button> } - - <button color="primary" mat-raised-button (click)="createTaskDefinition()"> - Add Task - </button> + <button color="primary" mat-raised-button (click)="createTaskDefinition()">Add Task</button> </div> @if (unit.allowFlexibleDates) { @@ -53,17 +41,14 @@ <h3>Task List</h3> <br /> <mat-divider class="my-3"></mat-divider> <br /> - <div> <h3>Manage Target Dates</h3> <p>Modify or add target dates for each target grade</p> </div> - <div class="mt-3.5"> <table class="mat-elevation-z0 w-full" mat-table [dataSource]="taskDefinitionSource"> <ng-container matColumnDef="taskDefinition"> <th *matHeaderCellDef mat-header-cell>Task</th> - <td *matCellDef="let td" class="w-fit whitespace-nowrap" mat-cell> {{ td.abbreviation }} {{ td.name }} </td> @@ -76,7 +61,6 @@ <h3>Manage Target Dates</h3> <f-grade-icon [grade]="grade.value" [unit]="unit"></f-grade-icon> </div> </th> - <td *matCellDef="let td" mat-cell> <div class="flex flex-col gap-1"> <mat-form-field @@ -86,8 +70,7 @@ <h3>Manage Target Dates</h3> 'date-error': isStartAfterTarget(td, grade), }" > - <mat-label>Start Date</mat-label> - + <mat-label> Start Date </mat-label> <input matInput placeholder="Select date" @@ -98,11 +81,9 @@ <h3>Manage Target Dates</h3> [ngModel]="getGradeStartDate(td, grade)" (ngModelChange)="setGradeStartDate(td, grade, $event)" /> - <mat-datepicker-toggle matSuffix [for]="dpStart"></mat-datepicker-toggle> <mat-datepicker #dpStart></mat-datepicker> </mat-form-field> - <mat-form-field appearance="outline" class="flex w-[250px] items-center justify-center" @@ -110,8 +91,7 @@ <h3>Manage Target Dates</h3> 'date-error': isStartAfterTarget(td, grade), }" > - <mat-label>Target Date</mat-label> - + <mat-label> Target Date </mat-label> <input matInput placeholder="Select date" @@ -122,13 +102,11 @@ <h3>Manage Target Dates</h3> [ngModel]="getGradeDueDate(td, grade)" (ngModelChange)="setGradeDueDate(td, grade, $event)" /> - @if (isStartAfterTarget(td, grade)) { <mat-hint class="text-red-500"> Target date must be after start date </mat-hint> } - <mat-datepicker-toggle matSuffix [for]="dpTarget"></mat-datepicker-toggle> <mat-datepicker #dpTarget></mat-datepicker> </mat-form-field> @@ -160,25 +138,17 @@ <h3>Manage Target Dates</h3> 'px-0': isTaskListCollapsed, }" > - <div - class="flex items-center" - [ngClass]="{ - 'justify-center': isTaskListCollapsed, - }" - > + <div class="flex items-center" [ngClass]="{'justify-center': isTaskListCollapsed}"> <button class="flex flex-none items-center" mat-icon-button - [attr.aria-label]=" - isTaskListCollapsed ? 'Expand task list' : 'Collapse task list' - " + [attr.aria-label]="isTaskListCollapsed ? 'Expand task list' : 'Collapse task list'" (click)="toggleTaskListCollapsed()" > <mat-icon class="flex items-center"> {{ isTaskListCollapsed ? 'chevron_right' : 'chevron_left' }} </mat-icon> </button> - @if (!isTaskListCollapsed) { <button aria-label="Search Icon" @@ -188,7 +158,6 @@ <h3>Manage Target Dates</h3> > <mat-icon class="flex items-center">search</mat-icon> </button> - <div class="grow pr-1"> <input autocomplete="off" @@ -207,11 +176,8 @@ <h3>Manage Target Dates</h3> <div class="h-[560px] overflow-auto md:h-auto md:flex-1"> <mat-selection-list [multiple]="false"> @if ((taskDefinitionSource?.filteredData ?? []).length === 0) { - <div class="text-muted p-2 text-center"> - No task definitions to display - </div> + <div class="text-muted p-2 text-center">No task definitions to display</div> } - @for ( taskDefinition of taskDefinitionSource?.filteredData ?? []; track taskDefinition @@ -231,11 +197,8 @@ <h3>Manage Target Dates</h3> <div class="flex w-full items-center px-[6px]"> <div class="flex w-full items-center" - [ngClass]="{ - 'justify-center': isTaskListCollapsed, - }" + [ngClass]="{'justify-center': isTaskListCollapsed}" > - <!-- Existing task status badge - unchanged --> <f-task-badge [highlight]="isSelectedTaskDefinition(taskDefinition)" [taskDef]="taskDefinition" @@ -243,39 +206,9 @@ <h3>Manage Target Dates</h3> @if (!isTaskListCollapsed) { <div class="ml-2.5 min-w-0 flex-1 flex-col"> - <div class="flex min-w-0 items-center gap-2"> - <h4 class="mt-[8px] mb-[-2px] line-clamp-1 text-[15px]"> - {{ taskDefinition.name }} - </h4> - - <!-- Accessible due-date warning --> - @if (getDueDateWarning(taskDefinition); as warning) { - <span - class="inline-flex shrink-0 items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium" - [attr.aria-label]="warning.label" - [ngClass]="{ - 'bg-red-100 text-red-800': - warning.state === 'overdue', - 'bg-orange-100 text-orange-800': - warning.state === 'within24Hours', - 'bg-yellow-100 text-yellow-900': - warning.state === 'within3Days', - 'bg-blue-100 text-blue-800': - warning.state === 'within7Days', - }" - > - <mat-icon - aria-hidden="true" - class="!h-3.5 !w-3.5 !text-[14px]" - > - {{ warning.icon }} - </mat-icon> - - <span>{{ warning.label }}</span> - </span> - } - </div> - + <h4 class="mt-[8px] mb-[-2px] line-clamp-1 text-[15px]"> + {{ taskDefinition.name }} + </h4> <div class="mb-0 text-[12px]"> {{ gradeNames[taskDefinition.targetGrade] }} Task </div> @@ -295,7 +228,6 @@ <h4 class="mt-[8px] mb-[-2px] line-clamp-1 text-[15px]"> <mat-icon>save</mat-icon> </button> } - <button aria-label="delete task definition" color="warn" @@ -323,13 +255,11 @@ <h4 class="mt-[8px] mb-[-2px] line-clamp-1 text-[15px]"> [unit]="unit" ></f-task-definition-editor> } @else { - <div - class="rounded-xl border border-dashed border-gray-300 bg-gray-50 p-5 text-gray-600" - > + <div class="rounded-xl border border-dashed border-gray-300 bg-gray-50 p-5 text-gray-600"> <h4>Select a task definition</h4> <p>Pick a task from the left list to edit its details.</p> </div> } </div> </div> -</div> \ No newline at end of file +</div> diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts index 39830be3ec..fb571c5ea7 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts @@ -1,18 +1,18 @@ -import { addWeeks } from 'date-fns'; -import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { MatTableDataSource } from '@angular/material/table'; -import { Subscription } from 'rxjs'; -import { TaskDefinition } from 'src/app/api/models/task-definition'; -import { GradeDefinition, Unit } from 'src/app/api/models/unit'; -import { FeedbackTemplateService } from 'src/app/api/services/feedback-template.service'; -import { TaskDefinitionService } from 'src/app/api/services/task-definition.service'; -import { ConfirmationModalService } from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {addWeeks} from 'date-fns'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {MatTableDataSource} from '@angular/material/table'; +import {Subscription} from 'rxjs'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {GradeDefinition, Unit} from 'src/app/api/models/unit'; +import {FeedbackTemplateService} from 'src/app/api/services/feedback-template.service'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; import { CsvResult, CsvResultModalService, } from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; -import { CsvUploadModalService } from 'src/app/common/modals/csv-upload-modal/csv-upload-modal.service'; -import { AlertService } from 'src/app/common/services/alert.service'; +import {CsvUploadModalService} from 'src/app/common/modals/csv-upload-modal/csv-upload-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; @Component({ selector: 'f-unit-task-editor', @@ -57,11 +57,9 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { isStartAfterTarget(td: TaskDefinition, grade: GradeDefinition): boolean { const start = this.getGradeStartDate(td, grade); const target = this.getGradeDueDate(td, grade); - if (!start || !target) { return false; } - return new Date(start).getTime() > new Date(target).getTime(); } @@ -86,60 +84,6 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { return grade.value !== 0 && !td.gradeTargetDate(grade.value); } - getDueDateWarning(taskDefinition: TaskDefinition): { - state: 'overdue' | 'within24Hours' | 'within3Days' | 'within7Days'; - label: string; - icon: string; - } | null { - const dueDate = taskDefinition.targetDate; - - if (!dueDate || Number.isNaN(new Date(dueDate).getTime())) { - return null; - } - - const now = new Date(); - const due = new Date(dueDate); - const difference = due.getTime() - now.getTime(); - - const hours24 = 24 * 60 * 60 * 1000; - const days3 = 3 * 24 * 60 * 60 * 1000; - const days7 = 7 * 24 * 60 * 60 * 1000; - - if (difference < 0) { - return { - state: 'overdue', - label: 'Overdue', - icon: 'error', - }; - } - - if (difference <= hours24) { - return { - state: 'within24Hours', - label: 'Due within 24 hours', - icon: 'schedule', - }; - } - - if (difference <= days3) { - return { - state: 'within3Days', - label: 'Due within 3 days', - icon: 'warning', - }; - } - - if (difference <= days7) { - return { - state: 'within7Days', - label: 'Due within 7 days', - icon: 'event', - }; - } - - return null; - } - setGradeDueDate(td: TaskDefinition, grade: GradeDefinition, value: Date | null): void { td.setGradeTargetDate(grade.value, value); this.saveTaskDefinition(td); @@ -178,7 +122,6 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { } private subscriptions: Subscription[] = []; - ngOnDestroy(): void { this.subscriptions.forEach((s) => s.unsubscribe()); } @@ -196,7 +139,7 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { } this.feedbackTemplateService - .query({ contextType: 'task_definitions', contextId: this.selectedTaskDefinition.id }, {}) + .query({contextType: 'task_definitions', contextId: this.selectedTaskDefinition.id}, {}) .subscribe({ error: () => this.alerts.error('Error loading task feedback templates.'), }); @@ -227,7 +170,6 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { const lastAbbr = this.unit.taskDefinitions[this.unit.taskDefinitions.length - 1].abbreviation; const regex = /(.*)(\d+)(\D*)/; const match = regex.exec(lastAbbr); - if (match) { return `${match[1]}${parseInt(match[2]) + 1}${match[3]}`; } else { @@ -255,12 +197,11 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { this.csvUploadModal.show( 'Upload Task Definitions as CSV', 'Upload a CSV of task definitions.', - { file: { name: 'Task Definition CSV Data', type: 'csv' } }, + {file: {name: 'Task Definition CSV Data', type: 'csv'}}, this.unit.getTaskDefinitionBatchUploadUrl(), (response: CsvResult) => { // at least one student? this.csvResultModalService.show('Task Definition Import Results', response); - if (response.success.length > 0) { this.unit.refresh(); } @@ -272,12 +213,11 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { this.csvUploadModal.show( 'Upload Task Sheets and Resources as Zip', 'Upload a ZIP of task sheets and resources.', - { file: { name: 'Task Sheets and Resources', type: 'zip' } }, + {file: {name: 'Task Sheets and Resources', type: 'zip'}}, this.unit.taskUploadUrl, (response: CsvResult) => { // at least one student? this.csvResultModalService.show('Task Sheet and Resources Import Results', response); - if (response.success.length > 0) { this.unit.refresh(); } @@ -305,4 +245,4 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { this.selectedTaskDefinition = task; } -} \ No newline at end of file +} From 03978fe76b926ce5f3fb485bf929743f13adc341 Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 22:24:54 +1000 Subject: [PATCH 1409/1531] test(cpd): align route reuse with target-grade scope --- .../progress-dashboard.component.spec.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts index 02a00a39f9..384a02fdbb 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts @@ -153,7 +153,12 @@ describe('ProgressDashboardComponent route reuse', () => { targetGrade: 0, unit: {gradeDefinitions: [{value: 0, label: 'Pass'}]}, numberTasks: vi.fn(() => 2), - activeTasks: vi.fn(() => [{}, {}, {}, {}]), + activeTasks: vi.fn(() => [ + {status: 'complete'}, + {status: 'complete'}, + {status: 'not_started'}, + {status: 'not_started'}, + ]), refreshBurndownChartData: vi.fn(), } as unknown as Project; component.project = firstProject; From 99c9cb6718b9d828477ff238c3623575e368e5cf Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 22:24:56 +1000 Subject: [PATCH 1410/1531] test(cpd): port PR 9 storage isolation --- .../unit-task-list/unit-task-list.component.spec.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts index 31bdb21de8..75c8c62298 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts @@ -1,4 +1,4 @@ -import {beforeEach, describe, expect, it} from 'vitest'; +import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'; import {NO_ERRORS_SCHEMA, SimpleChange} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {ActivatedRoute, Router} from '@angular/router'; @@ -33,6 +33,11 @@ describe('FUnitTaskListComponent', () => { let fixture: ComponentFixture<FUnitTaskListComponent>; beforeEach(async () => { + vi.stubGlobal('localStorage', { + getItem: vi.fn(() => null), + setItem: vi.fn(), + }); + await TestBed.configureTestingModule({ declarations: [FUnitTaskListComponent], providers: [ @@ -50,6 +55,10 @@ describe('FUnitTaskListComponent', () => { component = fixture.componentInstance; }); + afterEach(() => { + vi.unstubAllGlobals(); + }); + it('should create', () => { expect(component).toBeTruthy(); }); From 2559e9760acde4b8cbf1178ed5c7577c98125b6c Mon Sep 17 00:00:00 2001 From: maplefoxgit <s223932052@deakin.edu.au> Date: Sun, 23 Aug 2026 22:27:44 +1000 Subject: [PATCH 1411/1531] docs(cpd): document sizing investigation --- docs/cpd-sizing-investigation.md | 173 ++++++ .../01-current-v11-1440x900.jpg | Bin 0 -> 75492 bytes .../02-legacy-v10-feature-1440x900.jpg | Bin 0 -> 59240 bytes .../03-current-v11-640x800.jpg | Bin 0 -> 40545 bytes .../04-legacy-v10-feature-640x800.jpg | Bin 0 -> 31180 bytes ...-current-v11-390x844-mobile-limitation.jpg | Bin 0 -> 34050 bytes .../06-v11-before-sizing-fix-640x800.jpg | Bin 0 -> 40815 bytes .../07-current-v11-480x800.jpg | Bin 0 -> 35494 bytes .../08-legacy-v10-feature-480x800.jpg | Bin 0 -> 27898 bytes .../cpd-sizing-investigation/README.md | 69 +++ .../cpd-sizing-investigation/SHA256SUMS | 22 + .../after-1024x900.png | Bin 0 -> 29688 bytes .../after-1280x900.png | Bin 0 -> 24966 bytes .../after-1440x900.png | Bin 0 -> 23143 bytes .../after-390x900.png | Bin 0 -> 30728 bytes .../after-768x900.png | Bin 0 -> 27219 bytes .../before-1024x900.png | Bin 0 -> 27650 bytes .../before-1280x900.png | Bin 0 -> 24138 bytes .../before-1440x900.png | Bin 0 -> 28427 bytes .../before-390x900.png | Bin 0 -> 30296 bytes .../before-768x900.png | Bin 0 -> 26800 bytes .../cpd-sizing-investigation/measurements.txt | 61 +++ .../source-comparison.txt | 67 +++ .../synthetic-cpd-comparison.html | 500 ++++++++++++++++++ .../cpd-sizing-investigation/verification.txt | 28 + 25 files changed, 920 insertions(+) create mode 100644 docs/cpd-sizing-investigation.md create mode 100644 docs/evidence/cpd-sizing-investigation/01-current-v11-1440x900.jpg create mode 100644 docs/evidence/cpd-sizing-investigation/02-legacy-v10-feature-1440x900.jpg create mode 100644 docs/evidence/cpd-sizing-investigation/03-current-v11-640x800.jpg create mode 100644 docs/evidence/cpd-sizing-investigation/04-legacy-v10-feature-640x800.jpg create mode 100644 docs/evidence/cpd-sizing-investigation/05-current-v11-390x844-mobile-limitation.jpg create mode 100644 docs/evidence/cpd-sizing-investigation/06-v11-before-sizing-fix-640x800.jpg create mode 100644 docs/evidence/cpd-sizing-investigation/07-current-v11-480x800.jpg create mode 100644 docs/evidence/cpd-sizing-investigation/08-legacy-v10-feature-480x800.jpg create mode 100644 docs/evidence/cpd-sizing-investigation/README.md create mode 100644 docs/evidence/cpd-sizing-investigation/SHA256SUMS create mode 100644 docs/evidence/cpd-sizing-investigation/after-1024x900.png create mode 100644 docs/evidence/cpd-sizing-investigation/after-1280x900.png create mode 100644 docs/evidence/cpd-sizing-investigation/after-1440x900.png create mode 100644 docs/evidence/cpd-sizing-investigation/after-390x900.png create mode 100644 docs/evidence/cpd-sizing-investigation/after-768x900.png create mode 100644 docs/evidence/cpd-sizing-investigation/before-1024x900.png create mode 100644 docs/evidence/cpd-sizing-investigation/before-1280x900.png create mode 100644 docs/evidence/cpd-sizing-investigation/before-1440x900.png create mode 100644 docs/evidence/cpd-sizing-investigation/before-390x900.png create mode 100644 docs/evidence/cpd-sizing-investigation/before-768x900.png create mode 100644 docs/evidence/cpd-sizing-investigation/measurements.txt create mode 100644 docs/evidence/cpd-sizing-investigation/source-comparison.txt create mode 100644 docs/evidence/cpd-sizing-investigation/synthetic-cpd-comparison.html create mode 100644 docs/evidence/cpd-sizing-investigation/verification.txt diff --git a/docs/cpd-sizing-investigation.md b/docs/cpd-sizing-investigation.md new file mode 100644 index 0000000000..3c28d96413 --- /dev/null +++ b/docs/cpd-sizing-investigation.md @@ -0,0 +1,173 @@ +# CPD sizing investigation + +Ticket: [CPD - Investigate sizing issue](https://teams.microsoft.com/l/entity/com.microsoft.teamspace.tab.planner/planner.v1.df787fb0-1a0b-4bb5-9bc9-9b92a428eb13_p_KuipOoIL0E-7orl64gLd0cgAGv3z?tenantId=d02378ec-1688-46d5-8540-1c28b5f470f6&webUrl=https%3A%2F%2Ftasks.teams.microsoft.com%2Fteamsui%2FpersonalApp%2Falltasklists&context=%7B%22subEntityId%22%3A%22%2Fv1%2Fplan%2FKuipOoIL0E-7orl64gLd0cgAGv3z%2Fview%2Fboard%2Ftask%2FhHsrVI-btk62f51L1DisTMgAOioK%22%2C%22channelId%22%3A%2219%3Abd20175d09414f079490a2403f7fca74%40thread.tacv2%22%7D) + +Status: Investigation complete. An initial responsive sizing adjustment was implemented by CPD-Q04 in [PR #34](https://github.com/ontrack-features-t2-2026/doubtfire-web/pull/34). This ticket adds the investigation and handover without changing CPD behavior. + +## Scope + +This report explains why the Cross-Project Dashboard (CPD) became noticeably larger when its 10.x feature implementation was moved to the 11.x codebase. It records the reproduction, affected dimensions, source and dependency history, existing remediation, remaining limitations, and implementation guidance. + +This investigation does not change CPD production code, dashboard behavior, or the implementation completed by CPD-Q04. Two unit-task editor files receive mechanical, behavior-neutral formatting because the target branch's existing warnings prevented the required lint check from passing. + +## Finding + +The primary cause was a missed rem-unit migration: + +1. The original CPD feature ran on an OnTrack 10.x baseline that loaded Bootstrap 3 after the application styles. Bootstrap 3 set the root font size to 10 px. +2. Commit [`a8ba06c01`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/a8ba06c01cd47937249d5780face427143b7dac4) removed Bootstrap. Its commit notes explicitly state that Tailwind spacing, sizing, and font utilities would otherwise render 60 percent larger, so 138 files were rescaled. +3. CPD was still on the separate `Feature/Cross-Unit` history and was not present in that migration. +4. Commit [`2c6d2786e`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/2c6d2786e) later reintroduced the legacy CPD template onto the 11.x base with the same rem-based width and spacing classes. With the browser default 16 px root, those values rendered 60 percent larger. + +For example, the legacy `w-[34rem]` card was 340 px under the 10 px root. The same 34 rem value became 544 px under the 16 px root. This is a 204 px, or 60 percent, increase before CPD-Q04. + +The Angular Material upgrade and later toolbar controls increased the amount of space needed inside the card header, but they did not cause the uniform 60 percent increase. Tailwind also did not redefine 34 rem: the root font-size context changed. + +A secondary height issue has the same migration boundary. Commit [`edab0928c`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/edab0928c3419cb7babb3363cc1c2046decb3c0b) deleted the `.panel-full-screen` rule, including its viewport-height constraint. CPD still applies that class, so it is now a no-op. The remaining `h-full` has no explicitly sized route parent and does not reliably constrain the task list to the viewport. This can make the dashboard feel vertically oversized, although it is separate from the uniform width and spacing increase. + +## Baselines and ownership + +| Baseline | Commit | Package context | Purpose | +| --- | --- | --- | --- | +| Plain 10.0.x | [`c57c1c320`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/c57c1c3206073f7b45fba69eefe9875985a4bee9) | 10.x | Does not contain CPD and cannot be used as a visual CPD baseline. | +| 10.x CPD feature | [`187902747`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/187902747adb3a851bd3294b97b2a9d4a6e8ca95) | `10.0.1-29`, Bootstrap 3.4, Angular Material 17.3.10, Tailwind 3.3 | Valid legacy CPD baseline. Its merge base with 10.0.x is `c57c1c320`. | +| 11.x CPD reintroduction | [`2c6d2786e`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/2c6d2786e) | `11.0.0-45`, no Bootstrap, Angular Material 22.0.2, Tailwind 4.3.1 | Reintroduced the legacy class values after the repository-wide rescaling. | +| 11.x before CPD-Q04 | [`b9386055`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/b9386055) | 11.x | Reproduction baseline immediately before the responsive sizing adjustment. | +| CPD-Q04 implementation | [`854f9ce9b`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/854f9ce9ba5f100b0425996c3f5d7e248faa6b32) | 11.x | Existing production remediation by SandilBandara in PR #34. | +| Current shared feature | [`53f1c5532`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/53f1c5532eefc75cadf7834748a5a85c2bc6b3e8) | 11.x | Investigation target and PR base, `feature/cross-unit`. | + +## Reproduction + +1. Check out `187902747` in an isolated worktree and inspect `angular.json`, `package.json`, and `src/app/dashboard/f-cross-dashboard.component.html`. +2. Confirm that Bootstrap 3.4 is loaded after `src/styles.scss`, the CPD card uses `w-[34rem]`, the search field uses `w-64`, and the dashboard strip uses `gap-8 px-16`. +3. Check out `b9386055` in a second isolated worktree. Confirm that Bootstrap is absent and that the corresponding pre-fix values are `w-136`, `w-64`, `gap-8`, and `px-16`. +4. Render the dashboard with the same synthetic units and tasks at 100 percent browser zoom. Record computed styles at 1440 x 900, 1280 x 900, 1024 x 900, 768 x 900, 640 x 800, and 390 x 844. +5. Repeat against `854f9ce9b` or the current `feature/cross-unit` branch to verify the CPD-Q04 adjustment. + +The included standalone evidence harness reconstructs only the relevant CPD dimensions and uses synthetic data. It makes no network or API requests. The application-level images from PR #34 use the same privacy-safe principle. A live application render additionally requires a compatible local API and an authenticated synthetic student session. + +## Measurements + +The values below assume the original 10 px root and the current browser-default 16 px root documented above. + +| Element or utility | 10.x CPD feature | 11.x before CPD-Q04 | Difference | Current after CPD-Q04 | +| --- | ---: | ---: | ---: | ---: | +| Unit card | `34rem` = 340 px | `34rem` = 544 px | +204 px, +60% | `32rem` = 512 px | +| Search field | `16rem` = 160 px | `16rem` = 256 px | +96 px, +60% | `14rem` = 224 px | +| Side padding, each side | `4rem` = 40 px | `4rem` = 64 px | +24 px, +60% | 64 px | +| Gap between cards | `2rem` = 20 px | `2rem` = 32 px | +12 px, +60% | 32 px | +| Card-header padding | `1rem` = 10 px | `1rem` = 16 px | +6 px, +60% | 16 px | +| `text-xl` reference size | `1.25rem` = 12.5 px | `1.25rem` = 20 px | +7.5 px, +60% | 20 px | + +The same unconverted scale remains in the task rows and expanded details: + +| Legacy-derived utility | 10.x rendering | Current rendering | Increase | +| --- | ---: | ---: | ---: | +| `w-4` task rail | 10 px | 16 px | +60% | +| `mr-6` task margin | 15 px | 24 px | +60% | +| `py-4` row padding, each side | 10 px | 16 px | +60% | +| `size-8` comment badge | 20 px | 32 px | +60% | +| `text-xl` badge text | 12.5 px | 20 px | +60% | +| `gap-2` and `pt-2` expanded spacing | 5 px | 8 px | +60% | + +Containment thresholds for one card are: + +- 10.x CPD feature: 40 + 340 + 40 = 420 px. +- 11.x before CPD-Q04: 64 + 544 + 64 = 672 px. +- Current after CPD-Q04: 64 + 512 + 64 = 640 px. + +At a 640 px viewport, the legacy layout had 220 px of spare horizontal space, the 11.x pre-fix layout overflowed by 32 px, and the current layout fits exactly. At 390 px, the current fixed-width card still overflows by 250 px. That remaining horizontal scrolling is intentional in the current multi-card dashboard design and was outside CPD-Q04. + +CPD-Q04 reduced the pre-fix card by 32 px (5.9 percent) and the search field by 32 px (12.5 percent). It also changed the unit-scope selector from fixed `w-64` to `w-full max-w-64`, allowing the selector to shrink while retaining its 256 px maximum. + +## Visual evidence + +### True 10.x and 11.x scale comparison + +The following privacy-safe reconstructions use the exact root-size context and component utility values from each source baseline. + +![10.x CPD feature at 1440 x 900](evidence/cpd-sizing-investigation/02-legacy-v10-feature-1440x900.jpg) + +![Current 11.x CPD after CPD-Q04 at 1440 x 900](evidence/cpd-sizing-investigation/01-current-v11-1440x900.jpg) + +### Narrow viewport threshold + +![10.x CPD feature at 640 x 800](evidence/cpd-sizing-investigation/04-legacy-v10-feature-640x800.jpg) + +![11.x CPD before CPD-Q04 at 640 x 800](evidence/cpd-sizing-investigation/06-v11-before-sizing-fix-640x800.jpg) + +![Current 11.x CPD after CPD-Q04 at 640 x 800](evidence/cpd-sizing-investigation/03-current-v11-640x800.jpg) + +![Current 11.x CPD at 390 x 844](evidence/cpd-sizing-investigation/05-current-v11-390x844-mobile-limitation.jpg) + +At 480 x 800, the legacy one-card footprint fits while the current one-card footprint overflows by 160 px: + +![10.x CPD feature at 480 x 800](evidence/cpd-sizing-investigation/08-legacy-v10-feature-480x800.jpg) + +![Current 11.x CPD at 480 x 800](evidence/cpd-sizing-investigation/07-current-v11-480x800.jpg) + +The complete application-level CPD-Q04 before and after capture set is also stored in [`docs/evidence/cpd-sizing-investigation`](evidence/cpd-sizing-investigation/README.md) for the 1440, 1280, 1024, 768, and 390 px viewport widths. + +## Affected source and dependencies + +The affected legacy-derived sizing values span three CPD templates. + +[`f-cross-dashboard.component.html`](../src/app/dashboard/f-cross-dashboard.component.html): + +- Line 3: fluid unit-scope selector with a 256 px maximum. +- Line 50: fixed horizontal card strip with 32 px gaps, 64 px side padding, and intentional horizontal scrolling. +- Line 52: 512 px fixed unit card. +- Line 72: 224 px search field. +- Lines 80 and 91: Angular Material icon buttons. Their larger accessible control footprints are a secondary header-space constraint and should not be globally reduced to solve this local issue. + +[`dashboard-list-item.component.html`](../src/app/dashboard/list-item/dashboard-list-item.component.html): + +- Lines 2 and 12: `mr-6`, `ml-2`, and `gap-4` row spacing. +- Lines 2 and 3: `w-4` task rail and `py-4` row padding. +- Lines 14 and 15: `size-8` comment badge and `text-xl` badge text. + +[`expanded-list-item.component.html`](../src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.html): + +- Lines 2, 3, 5, and 10: `mr-6`, `w-4`, `pb-4`, `pt-2`, and `gap-2` expanded-row spacing. + +Related history and context: + +- `angular.json` at the 10.x feature baseline loaded Bootstrap CSS after the application styles. +- `package.json` moved from Bootstrap 3.4, Angular Material 17.3.10, and Tailwind 3.3 to no Bootstrap, Angular Material 22.0.2, and Tailwind 4.3.1. +- Commit [`edab0928c`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/edab0928c3419cb7babb3363cc1c2046decb3c0b) removed the old `.panel-full-screen` height rule. The `$main-view-max-height` token still exists in `styles.scss`, and the current inbox applies the equivalent calculated height directly. + +## Recommendation and handover + +SandilBandara's CPD-Q04 change in PR #34 safely addressed the immediate 11.x overflow threshold without changing behavior: + +- Keep the unit-scope selector fluid up to its existing maximum. +- Keep the local card and search reductions from `w-136` to `w-128` and `w-64` to `w-56`. +- Preserve the horizontal card strip, search behavior, grade and date filtering, warning states, and Material touch targets. +- Do not apply a global root-font, Tailwind scale, or Angular Material density override for this local dashboard issue. + +The investigation shows that PR #34 was a partial remediation rather than a restoration of the 10.x visual scale. If parity with 10.x is still required, hand CPD-Q04 or a follow-up ticket these scoped implementation options: + +1. Apply the repository's 0.625 conversion to legacy-derived CPD spacing in all three templates. Examples include `gap-8` to `gap-5`, `px-16` to `px-10`, `gap-4` and `p-4` to `gap-2.5` and `p-2.5`, `mr-6` to `mr-3.5`, `w-4` to `w-2.5`, and `size-8` to `size-5`. +2. Decide the card target explicitly. Exact historic parity is 340 px for the card and 160 px for search. Preserving the relative CPD-Q04 reductions under the corrected scale produces 320 px and 140 px. Either compact target requires the header to reflow because the new Material icon buttons must retain their accessible touch targets. +3. Replace the dead `panel-full-screen h-full` assumption with an explicit viewport-bounded height such as the calculated height already used by the inbox, together with `min-h-0 overflow-hidden`. +4. Preserve the horizontal card strip, search behavior, grade and date filtering, warning states, and Material touch targets. +5. Add a privacy-safe visual regression fixture before making phone-width full-card containment a requirement. A fluid phone layout changes the current horizontal multi-unit navigation model and needs product and accessibility review. + +No further production change is made by this investigation branch. Any follow-up should preserve the authorship and implementation history in PR #34. + +## Risks + +- Reducing the card further can crowd the unit title, search field, and two Material icon buttons. +- Making cards fluid on phones changes the current horizontal multi-unit navigation model and needs product and accessibility review. +- Changing the global rem baseline or Material density would affect unrelated screens and touch targets. +- Removing horizontal overflow without a replacement layout could make additional units inaccessible. +- Removing `.panel-full-screen` without checking the older project dashboard could introduce a vertical layout regression. + +## Verification completed + +- Compared the 10.x feature, 11.x reintroduction, pre-fix, production fix, and current shared branch histories. +- Verified the Bootstrap removal commit and its explicit 60 percent rescaling rationale. +- Calculated the relevant rem-to-pixel values and one-card containment thresholds. +- Reviewed privacy-safe evidence at the specified desktop, tablet, and phone widths. +- Confirmed that this branch changes no CPD behavior; its only source changes are the formatter's mechanical lint cleanup in two unit-task editor files. +- Ran the repository lint, typecheck, full test, and production build checks recorded in the PR. diff --git a/docs/evidence/cpd-sizing-investigation/01-current-v11-1440x900.jpg b/docs/evidence/cpd-sizing-investigation/01-current-v11-1440x900.jpg new file mode 100644 index 0000000000000000000000000000000000000000..37d22cc965d7dfb0313d1452fbfa4489c39992b9 GIT binary patch literal 75492 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�Fz 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 literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/02-legacy-v10-feature-1440x900.jpg b/docs/evidence/cpd-sizing-investigation/02-legacy-v10-feature-1440x900.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b91ae46fae61aa680718618b21a6c7fae617f5a7 GIT binary patch literal 59240 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%0A}eWRrqFaua0p+TI1j*OEV8iCPXG@!os@Hj~8G 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 R4EmBM2l`8b-p-G${{z1)(s}>@ literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/03-current-v11-640x800.jpg b/docs/evidence/cpd-sizing-investigation/03-current-v11-640x800.jpg new file mode 100644 index 0000000000000000000000000000000000000000..46ad7138227154b47c13f2e419039c4cc2c1c575 GIT binary patch literal 40545 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 MWYnP)gg>VL7kE~VL;wH) literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/04-legacy-v10-feature-640x800.jpg b/docs/evidence/cpd-sizing-investigation/04-legacy-v10-feature-640x800.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3127af3fe9cb97aba781f632adef9456e128115a GIT binary patch literal 31180 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 QP0;9Pevb34-M{qxA6kPC{Qv*} literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/05-current-v11-390x844-mobile-limitation.jpg b/docs/evidence/cpd-sizing-investigation/05-current-v11-390x844-mobile-limitation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cf85864ea26b658e04c8b393b4c9565870affce5 GIT binary patch literal 34050 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 Nn)nP)%lBvge*roc#6JK4 literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/06-v11-before-sizing-fix-640x800.jpg b/docs/evidence/cpd-sizing-investigation/06-v11-before-sizing-fix-640x800.jpg new file mode 100644 index 0000000000000000000000000000000000000000..21b9d961fa4aaad2537f165d918ce3bd3b238f93 GIT binary patch literal 40815 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 HeoX%#<x}=o literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/07-current-v11-480x800.jpg b/docs/evidence/cpd-sizing-investigation/07-current-v11-480x800.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0dd58231b34dc497b7d5828b53ce4b9316ebce1c GIT binary patch literal 35494 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 I#h=sv1Ir>;1poj5 literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/08-legacy-v10-feature-480x800.jpg b/docs/evidence/cpd-sizing-investigation/08-legacy-v10-feature-480x800.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7363d1197235b5ee32e1a385f2dd7c81c3fc2c2e GIT binary patch literal 27898 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 YoU!0r^vDp$&jwGHceAS%wZQuR6(_fTDgXcg literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/README.md b/docs/evidence/cpd-sizing-investigation/README.md new file mode 100644 index 0000000000..be6c419054 --- /dev/null +++ b/docs/evidence/cpd-sizing-investigation/README.md @@ -0,0 +1,69 @@ +# CPD sizing investigation evidence + +Date: 2026-08-23 + +Report: [`docs/cpd-sizing-investigation.md`](../../cpd-sizing-investigation.md) + +This folder contains the evidence for `CPD - Investigate sizing issue`. All visible unit codes, task names, dates, and statuses are synthetic. No production system, live account, student record, token, or secret was used. + +## Source baselines + +- 10.x CPD feature: `187902747adb3a851bd3294b97b2a9d4a6e8ca95`. +- Bootstrap removal and repository utility rescaling: `a8ba06c01cd47937249d5780face427143b7dac4`. +- CPD reintroduction on 11.x: `2c6d2786e9484c57436099d25281aa45fa89453c`. +- 11.x before the responsive adjustment: `b9386055`. +- CPD-Q04 responsive adjustment: `854f9ce9ba5f100b0425996c3f5d7e248faa6b32`. +- Current `feature/cross-unit` baseline: `53f1c5532eefc75cadf7834748a5a85c2bc6b3e8`. + +## Deterministic comparison set + +The numbered JPG files were captured from `synthetic-cpd-comparison.html`. The local-only harness reconstructs the source-derived card, search, padding, gap, and root-font dimensions. It does not load the Angular application or make network requests. + +| File | Evidence | +| --- | --- | +| `01-current-v11-1440x900.jpg` | Current 11.x, three cards, 1440 x 900. | +| `02-legacy-v10-feature-1440x900.jpg` | Legacy 10.x-root rendering, three cards, 1440 x 900. | +| `03-current-v11-640x800.jpg` | Current one-card containment threshold at 640 x 800. | +| `04-legacy-v10-feature-640x800.jpg` | Legacy one-card rendering at 640 x 800. | +| `05-current-v11-390x844-mobile-limitation.jpg` | Current phone-width overflow at 390 x 844. | +| `06-v11-before-sizing-fix-640x800.jpg` | 11.x immediately before CPD-Q04 at 640 x 800. | +| `07-current-v11-480x800.jpg` | Current one-card overflow at 480 x 800. | +| `08-legacy-v10-feature-480x800.jpg` | Legacy one-card fit at 480 x 800. | + +Supporting files: + +- `measurements.txt` records measured widths and overflow results. +- `source-comparison.txt` records the exact commits, utility classes, and rendered values. +- `synthetic-cpd-comparison.html` is the reproducible standalone harness. +- `verification.txt` records the passing repository checks. +- `SHA256SUMS` provides integrity checks for every evidence artifact. + +The harness images are deterministic layout reconstructions, not signed-in application screenshots. This limitation is intentional so the root-scale comparison is repeatable and privacy-safe. + +## CPD-Q04 application capture set + +The `before-*.png` and `after-*.png` files preserve the application-level evidence supplied with [PR #34](https://github.com/ontrack-features-t2-2026/doubtfire-web/pull/34). They compare the 11.x state immediately before and after its local responsive adjustment at these viewport widths: + +- 1440 x 900 +- 1280 x 900 +- 1024 x 900 +- 768 x 900 +- 390 x 900 + +These images show that CPD-Q04 changed the card from 544 px to 512 px, the search field from 256 px to 224 px, and the unit-scope selector from fixed width to fluid with a 256 px maximum. They do not represent the original 10.x 10 px root scale; use the numbered comparison set for that question. + +## Reproduction + +Serve this folder locally: + +```sh +python3 -m http.server 8765 --bind 127.0.0.1 +``` + +Then open one of these URLs and set the viewport to the size in the filename: + +```text +http://127.0.0.1:8765/synthetic-cpd-comparison.html?mode=legacy +http://127.0.0.1:8765/synthetic-cpd-comparison.html?mode=pre-fix +http://127.0.0.1:8765/synthetic-cpd-comparison.html?mode=current +``` diff --git a/docs/evidence/cpd-sizing-investigation/SHA256SUMS b/docs/evidence/cpd-sizing-investigation/SHA256SUMS new file mode 100644 index 0000000000..8874c85089 --- /dev/null +++ b/docs/evidence/cpd-sizing-investigation/SHA256SUMS @@ -0,0 +1,22 @@ +3541c299daf8de7adb99565754859d8bc2cd9ec256c054c17bfc89636333bfde 01-current-v11-1440x900.jpg +ee0a1143926d4b9a3579de9d476da072d128cc2293f9dce97b2dae91151ae0c9 02-legacy-v10-feature-1440x900.jpg +60cbac1d7fe742399002be8d6ab877b1e1230d53ce862e0a9a2c6c16cb4039cd 03-current-v11-640x800.jpg +8fe839a0a89510f446754632f86a87e60b4beff899ac2d043e817c15784ba43c 04-legacy-v10-feature-640x800.jpg +db8327cec1b67dc6d2c16d6524177a2595594562b8e24af1d64a784353e3d49d 05-current-v11-390x844-mobile-limitation.jpg +35ae6b3d9d02346e79c7dcaed04cc76c97a2e6d6c36672f9290e8b2d00e8786a 06-v11-before-sizing-fix-640x800.jpg +e9971bcfb40e114a1f5b6668baa12dcf76ec90d7228586b88a445170dd1edd94 07-current-v11-480x800.jpg +21273f22f715109381eb79da8987e2bea31481050be72c36f0f3364bec90056f 08-legacy-v10-feature-480x800.jpg +55f5c273610ea0352af980b2c38ee356cba0c0ff201899243c7b5f86b58b71ff after-1440x900.png +a7c5db0c304b0266e40c2f3212b706d96f326700ad4007d131e0e90b318698ac after-1280x900.png +49b5f9c62579e1f139977ea01c9a4ba37d51cc228c80abf9d66c9e04005ce8f8 after-1024x900.png +228ed36601f465011c4d4939edca751fcb1612ecc47856a3a335f01f556f031d after-768x900.png +da166e582fc08c6dec2c9c8fdadf8fed457e1821b2aed39f6236d0229ab5ba28 after-390x900.png +0ce6e03138edcba5f8bf2eb5f9b1f556a867ef094bcd9f85aa8946d7d34c41ea before-1440x900.png +4a8c27f19f5cf2aaba354001860ea103b4d2f26be000dd87cdf82eae094cab00 before-1280x900.png +16965adb873827e5d9b30b46340237ef146e74b5efd973add35cd93a93a4ebc2 before-1024x900.png +96e810d2ff565123384a962e61be7f462204bedb107951c97a29a64ffd9fe920 before-768x900.png +4b3fdcd12b68fc6a44798f4f58a17881d6c4d30a6c060faec2a46c7bab93486b before-390x900.png +14f2b26c5c0d5dfc9a1a528fdbdaa5c404c68fe5b8b18f76c70c5d734136120e measurements.txt +7a391e9326ed30e25654752199168107eb1bdb202afe56459f8b830ba91abea9 source-comparison.txt +ae8ccfaf88912e57259eac2fbe9236382b559493625ad0a63e654917d7e04744 synthetic-cpd-comparison.html +56995cda119a5e7886c92abaed7dab320be719cd1af4fd3cfcde4281eb71d2ed verification.txt diff --git a/docs/evidence/cpd-sizing-investigation/after-1024x900.png b/docs/evidence/cpd-sizing-investigation/after-1024x900.png new file mode 100644 index 0000000000000000000000000000000000000000..8fa3057acca2d7723ff3bb4bf916b2c7913e1110 GIT binary patch literal 29688 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 R!=oc)FDYKkmb`ZRzW^4u+NS^j literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/after-1280x900.png b/docs/evidence/cpd-sizing-investigation/after-1280x900.png new file mode 100644 index 0000000000000000000000000000000000000000..44bbba2e4504ba5b606ad830e804e00d4bef4d11 GIT binary patch literal 24966 zcmb@uc|6qb|1Ydn<%3ERLc0(uBxEmZDEqF>I<_#jF=$l@Wz9}@W8V!!ktJemGsD<Y z7-kGvW+pRc+}C`*_kBOkIgfMy?sFcG^G7ku`~AM&*Y&zyuh(;Vdwb7Vm-~p&5e^Ox zZhgJmrW_o5ao}Ibp@ZNZ=TE0Q!H+%urn*`j6@#aj!HfN_nns!&9My4LI}Z<l*N1)e zZ2UPmjt8*+?U`{A3+CW>D6D^5(>&ObJRK5dj+xutr9GLo*?acP(L=C~OK*;9o`@bZ zO?f9J^Tzs)w3GVQ<LWwW!D{=4yCL%dKjk<6UHwViqXUx9yAG{t98$R*_(A$fy5}b2 zx636tMY#m>T`X>M{S)U8CBjUzoWK7f9GwB{`Iwrz{4O@u(%wD;42nbE-rCyw)925h zR~FbWi4s??UpGB=>=@OL{gQG*r;2@lKYX7!J2!W9c9It~YTvzib1yi!3B2MzdGb<J z=h>*vhd$t2L!V#1di83eKhouxsA$Fbxb?+Lmn3CmjE9GZ!6AQMLO3`glV#oyJzqQt zK5uHe+11k{b^Ut$8Ey^^Tj|&3!)2fI^7zHX(E9Zp963g3?DK5E2_@9j9Kji=lHh2| zXy2Gi0>_T!{{0*L^qe#Yha2P&&W%0XchS*^%~s;ZhM!WVF~5KSqPV!%UrIvazKu<) zq?8mn8r+1uaL>!beD+kWGbg6ZG(EVm{QUgjGc$Mh5>#L1pFh5L?%a{MetpCdtkzKe zsb-yow=pr?LS+szDFy}x=3t%(56VlgI@;TpJ%7G8DJ5kRA>6g_Yn+dRV@zaD$mpE1 zvhvbt(z|!>LZdud`uYsO`M)m*;1NRK7W@vVo&rOtI&Xh|9!%T|NB;cQR(mjA-HRqI z1UJQ#UxmO~1m=X!3S6<aGB+;<<9D2Lb9Q#t*?WV7Lj(SjwmQwwggq<<Q{w*P)3rV{ z+Gh;6Yb0^y%3TzUhFu;lvfJ93tg5=oefs7-?I<41gll&B`tKfuQ+qgZtR&$G7niE0 z+@(u8ID7vX<-nEVwKm3Jo6v9eGV<{~mQ5}#bU4A!k6DJsfc3StO=ExO`Sa(>F@9E- zmVI-+`!i$ra&SB_O>mIDaO;-6;&ed5>wg44(`F-_5LT59itZmnX{+UJa0c<)TRwc9 zyIH1|gPEa;369^&J~uJ(1T3j1#VNd`aW>peHFRr8BxouZ40D;*zKcSoKCP~<-c$MO zzNzW)tuqLJ!eH7BuQZ+ar*dT+kimUm1!6^13b}=EEDb2mj=kj*4@<5!)YH3XeadMB z#KjOK{v!!2;Iv=Aw2-{phra&)dcOsOOl4@_OxYdw8mGuOB!2jilb?S<M9J^lOukJf z6l;@q?eXj5$B&!a+Lof#7<a|O{yb~j*)UvKSSTqj*8BebI}w9O(TNi+PY^fp`1$3T z<mJov0s|Z1(C!0BExkK;UV*S!=@QM;jl(i&vz2@H9dsiMX4=*~d23l_ovQ%BE|DtR zEpZhN3f@yUnLjzzhrsLv{Q0TLki2CtWA!CcY-m0kGAHYUZJMW1)*GpPL+R_2UC2%G zee*jwSNz50j$OxMCr7z&{$eiNs729%tmNEc1t-B!xHt*RsK70KQlNVjp$7Z^K%i(Z zGYo0o)=Sy5(o?f=s+3WYUM4CHSJ{(u;7~|Y?ECj)CJ}Tq%G#_G2rApw;OdQyjg<l0 zvYMLfBC4V05)u*yU_zsKL;|*!hLw$+57mSFS?U({0fGPNhWAu)SF`}+cXy0(_)b%- zn0f`AL6r~}*M;CJEWjONT7rDofft{4!Cv?F?aPvqeU4Z3C8eb;z%-$(OOIgN|8~g+ z(6`)G|9sg;C#dh1Fc~z`(r}(~=vFaxZMM=xZTq%U_;x`}O-;bp0|IX7EY&^x0-c=; z&YeHce7zGnQX6pJMIdR#E6Z2)(a1%j$R_HB)vM)j8v%*DP6;$K`TLPXb<t7no?6B4 z{-=}|ET@B}<DfGkgb?o+dtVNIZ=5b76(J{MHiZ|<&V*@}ll%~dzQ%&ej@t2tb+UTt zbbZ{?W~e^ng-<$?8}s+8NPq`qfH3iSOSpV9w3`@gIBU$|wnvNZ5c1?nz6(05Je)}{ zsjI8Q9Dpbmjh6VdZR>!EC5~6;fv_E38U3fDqa&b;-|8~hph`+gp$kb?d$Ue01t?Sc zq$=IOZqBL+Juq<a$PJv*P{0Qem;<SDJ$z;015%0M-Mi+G9(^XTvQ%MPU-t19=j3Rp zGbYes#Fe{FyU6mEKkWh@>mAu7E!dr-+LeL@=CIuS@9_MUC^2lOMPp-wQj#)NZCbet zyV}4=OlorQ3Bl{{lWEb#@l<-tZKc5iw!iRUNOnQJYsgY=%uv>_pLajj0LIV3arS7< z%TxUP1rxQdQqs~!1qB76i>a=*&Q*a@GBVWtD`228r>>oI3;w76toG~6N=h~d4jc$2 z*W*?&@%bPvGynFeV-qFJ<emFYh^PeqFvFcVzxK>A`++7c-caWL-MjCz!s+fH;>L=+ zXIev$jMWx+ACH(?nQJ!O5+niS)`%gT*qW4-G!gw^?1?k?R)oc;B(xfV&r^}<mD(Vn zUjn~mCBV~enTJ%Whj)?i^P@7h`?{MaZQ`D~W#Z_`>P0J^ro<|U!kELN*WY`TSbt)R zJ<WCx$D#5MFG<D4m#4!SWCKG(GkyKHSs{yp*~faZrC`6$hBL|~B_$IR6Z7XfqomHA z>zFCif8yd|U?DDfQ0RcDl3)Iy`fiv*@Z2lppAIgNKU_nIX}`Yx(8yyvD|~VDG>=in z&HJ-(T4o!I4uRDt%Q%!47^dK(DP00iOGCNZX*Zuf`f_YrBkr)=YezYQlBn7wha!o6 z>03<q+4x-TP$}e+iWmN;15!Vos#M?&SFnjM+_EU;ai{sM-5BXpjmmGD5h5ydkZ*)c zaoiDO8B{XL1VHk;7G8fesA?7DstfEL$;orNN|DQrK_#n=3Z!Y7n#L<bi6^dpnz(r3 z0(-sU*}Kr>r?)}S)YGVu(NW4qzbs_*(r%vL`ue&uA;W)1trD!98%{>9)^MNx-Md?i z@vg3}aNT&u)^c8tScLs9SmUk5bRRt81(HQ4LD#zkNLjGe!@*~)DiN>mvYJmiDp-rF zXO?q1Q6<}#HKo;xTC6my8+PCoEbGUEU;j~U3T_Rv^@f}I?^bpAWb%|_RyZBkr!qnE z6PkS(J(I!EEiX<heCoV*3#CN+)D4q`*bSQcGcj=vWOhoF;_R{%IN>v#zGkT2=26vZ zfXIG4UXJwfEafSOS))TZr{-|Pto~3^OHg>xT91Vh`7fMuD8NV?N}f(Z(ApZeTH3uf zro?=e?ReE8u(L%VU3LeKP#=&)!^>BjJtK|B8x0enB)CmHs<jm5nt^g_si9FUv0wQ5 z!ka?Pr_!GPQWaVoqXvZ&_{R_pDualw8#MpY@Rb$g8B%q5CkqcnI9kQvY&ObpFuD=t zF%mN+!@u3;o#4}AV$+B1gwcs@)g|#fA*w-)$EQuH$`S}7{HMkNj^}dWTEBZgo>vIp z2}UzP*`$zgm4l6AW9H>{jf1Y4xyh-iCEnA>lE*!<P-It^MTEy4U0p;~)jiNmsFD7u z_eZN*y?y)Ew$VEiq-pO;P}j9q@b!i&L91m?5#$Z%rTxe@C}@jjKW>6@<gxR2-L~E% zX%^z^6t><)oNaG!@R{|lGzAq?K6J|s&e|sIsa!fPC}>0TB@<qD3${CysYKm&>z^eo z&4|z97;EjagfG$ZPk${a_cKb*B}7!bYCm0I9EJ6uPR9{JVZ<>m?vt;WJO<A|849py z14NWpZ20<{`dFIbLAQ<Z`$)GOv)#T1p5UFVp-*@R!Iaw`ohwdD!yNs~g`D+&2miU_ z2_j{cnc&J4Fv=+I?+L&%EQH+;kP>W3jyQ%fcdx<lM*&u`di!o$#y)YW^WjA^8UB^5 zEmr&1gbYpJ>#*b>C4Hab3e>|^<&|)gXm#b!Tf>ABtF5PA>uR~fE*oC83g<#wW?-v% zr8gvmLI;mtJk8XC_<I_5@s2f>^0D59W)(RWOl~cvG`#5OEb05>zwvVjQZe>veA;$h zVDfvCy51;_B#IStvd?3e{ou6{r0;{e{JoWYLgJ*F=)SsNZ`DZy3YIO!Uj^L0EooYa z>x7CN-C4g_Zd0oRF{a+r!JVf|65fFM9m^s}Fvnq`J7^!ejV|SIj7X?c&L=O&$uW3F z_xq+Vv?l`+jl?$6>&t$Vc3G5ir3vldJ#n}LFY@ZTnaI1%cg^}O%^Pj_3N#aR-QHWJ z|9hv8-gS2^5ZBe)@)cIeg6tUgdie+?cHX6~LM&af<T;<vo*W+HCwZcGf3h^b(I=Y_ zZfqP2x|sWfNwC0cwQYq}5S$F?j4<1aszKXZ%cDle&B;?K)u0QjvZ@b#w)f9AA-j@G zrs<30m5_n6ymg*=MyzI?0_^Dm$MvXYTbLd(ypS>9&PCab=9I#!eQw=|3$5~)5AG6M zq{qIl+{tTGzR(r;N3froXKlw~<=lcmWpOY!%H!+_)Z%4IpSs6t5of{JeR>FHYhhL7 zQGs?#DXxH@{(B$xa)?HM_Gl+BBeswS<x+akttEN;eFmNzQy(;2#8|EM&ND_8M3M8* zns=mzXH(;EWGaWCkrm1xpUz&Y>=7)5L>2Tklclo>Rm(o@n{t`X1zELTzx&V){Uyf4 z>-O=cNvFg`@W1QjJcAw36HZZ`6KZ*VSY=ZTj<ElSn|t=IS80}^BZ{n+Hzw?eTf>UP zBV$U{*8R8r8$PZi_023M9&h<OXc(uGTj@D_!g|y#tkDJx*lsdoW`Ki3^OVUsuy@%l z83C~kx(fHs*W9*kVIi5`xml$@(ccrq>s`@V%G2zwi$_FRFMeZlv;JY{!FIFLT4b;~ zDHqUN>Bx6+aaNvXYbmT;)7gYe)0`3|CC?JfbD-3vVeR<6vA-0tuR2Fh*ku$MDHKNN zRjw#s?kaR&dZM2YB`IyG+|;jT(YdO{44Zo-?dUn(U1UJ~aC(P$I$U)3XUQXph8GG4 zo^0GJ=sGFo^CJ7r&W4PLdD+NoyExxJ=GBSHj$FGcOXm+NE?7FK-BS}kOK;S#+-;+K zob8vlpiKv5uQqqDNxTWa38jBPl@;=dw>EUlzJ1T?D?P2uf995PGsgd(@2vB_6Xe76 zr~ss%fd~nvz^9V^M_OOF4fj@vbFXHDgv@YS*0Cp(^<j-X61J$Qzin9wJ_xm(=CB6= z6y(%9<9?cRW?9?xj%RJY(ZJP64vzAqb>H&R`xZ3)_t&mnL;j9cdCm%b0GWdy&r`AH zY}vSTd0}zUAYLa%i2sl6NFXSFX>zWytl3>gL^we!{p96CoI(z))s{8$d-rm#J?<Vy zJomeKT1d|2y>X`U!e;qfhn$}B=v5J7u!f%wXIH6p5p`0kbl@);%wSl-NE^(o))kFi znW(LA;F+tobPcE)NaFDX;qE~#;^bFZGLZU-+pK|&JegL$VKL~{PgLa$8l4R<0^J+G z>eYVb`_%>koa&qwC2ukQc?D^CmGSbe(aIC=cCvcioUE>PR$^3X(?yK#PzRkqndH*g zpV&Rx)HyfqrXNSDpz79ck)fW9A;{`5oMtglLPhR8<SuG&9B`=IR^H1&tekVtJ2{gw z8yy`zni({+yvc_xk5RFXii(m_S8um5ezesPvgwj}^QqS1!-tW?Qp5^I;bl}5r2D-f zaik#HI9pBR>ff|^AIJLV_Ma<jYD@tHv;-}?!lQ48VD;<?qNS+zycf)47cSd+$)B45 ze?rFgbbU4JqMqBOW}6NrE2<W+mvrGbXcG#?S3T?SqLZr&oQMvlt;l<kGARM|VnOPS zJx!IMS^Tp>{5Z`hHSUcT&gq97PRHsM!`|J&V6=Dk6LK?^^_6qi6vuV^Pz9GH@vZ?X zUk<J0jylfW{FIBNYC%H3bvlaQq}Ogt5J_ITysh@M=|y<cgGg9FbH$|Ej;)c%sd8<S zXhn#hn^&n0W)DXUUkwPHNL29pBl1+U83+vI=Aa6u#Ec{?yxvwp0UMG+Zk#>%PplC@ zE2f4iGD-alBcNtOf5#}&Gu)QT0VqO}Dq0e=vMShYfYaN&+`S@U`;Xw_w?I7gEe8+> zRo2R`sm`M#ShcJjf;uCyps<kGFzIdf^l5dnwB4c^L3;c#w(H$vaYRx0_z%4`M^)#? z3)eEY(!%d6$|X9Uzji~Ts;5oDVVeIz-y6r_7ZJ0cA3@D)vIzuqVLNkBPLc@kSF?vY zzl#!U7+_EqMAG>G_=RFy-9=`~lj3hIgcDrbYUG<uO6Q@1?YX%3rXItA&XbjO)pM}S zKXUMn&71Y7l=Fjr4nL-~K2hg9RL@mov^u;HIl0<)`(dQSdDG17Y}e9g8l?wuclGfj z&I6Iuv-xwj7FMtSw(m03$>Y`9pbPnT;;J9(!fH?Ui<ET&MD*+1VXyJ3+=&<Uli)tL z0Qv{u-mo)@7l)$FAPi+u<^UJsBKPc*2bkF*f=NkJ^vMd{TFQ-&KaQdk5enfM7tQy+ zB2`sYMLtwiS9dZ|r6k73$8UY(Gx=*DvN&G-Sk1o_4H|XT^>2J2DdKinYrDiP_sOmV z)NLIdd^C};z*$edS9Z{;e#qZ6r?dijO|9PAZYC)EpTF-!%hJ5(<g!CH(3GDMPSy&@ z72!zN9c-XY+d;0KaW3?7#jo<+t&I0dzZ=`~#sqjw%*u?3))uJQ7jH|qd!9vb566Ml zQ<UMhnrH_Ni4lA8y&?SSVh2&|g<$A_Irkftd{5e;mDe~5=Ai_1r5rP=51{&$Y_aV1 zpmTZY&__;NU;5!$FDN%>$fY_X(>R<Z<&AIscO-@oGST6ydWScIC>I3V@JfMbWSC8= z`?qUJQS32GO=!iv?1V5g>R+mpjoRloKoID?glb#=FecqkyH+?w^na_tq2b$I=`W%O zxI34Dw1Q{*I6byE7Hq3KW)Io+kJh@HfL7B)+&E*X&?w#ZZWR?<WFqDO#aL((>V2k~ z?yt3O#?HF)=bl)y#Q~%%DZ_K??c7Q&8VmAA$<mUW*JOiHx}pzub-INgP;_c=`sMTI zwV8Cvzd$RLC;<mJfoc&92rSHQspOste}~`rA?4!wT2#f)Im`Mms9~j4%y>l-{LknF zK4}%^K>C7frlLOUQZ7<j8*;lJ+r`Z>Z@KI=5HIu*Pc{&q=7zWZG2o81AcL>{+CJ=$ zPP(yU?>`Y<?#c_ZTZ712rH7@{C^`F_6p@Q`X)4J|r4d!&oMua@C9d|=dKnG}qUyEM zh|O6IOxq!Bl4fbqqy0_Yffga+Gz;}xlZ>R}vb7F&c(i}z(-`jvTxUc5I&J3`xR@gJ z$vcV~>~x?LZ#v0-pN50HO_QZXui&*uFWa^k(<A*K+ob^}4ob#b=*FIQAD%pY@?;@^ z%WmJ^93u|pz5tArYRcgqBBC<juWt+_M&a%F_;_SqH-OTbyq56^2~Y~g3NqF7RKXY@ zpqxqH8a1H+yoC*Y_2I!}WWz-_xBVPBhvnUybQpYqN(HbRR(+ua5Q>1or2Y~Dj0vXF zNga(*0~e|XKtb7|<l?z==YHC6Y1qr8%nk?E`R<7*ImQuLsNJN~3&5QOK)a4tEMhcN zGNDKwEtJw}9zf125|4)g(vqS{)aX6Hg$69_+4P!Y!or4ZPT1(({Id^$W<4ZSWrThk zc=NQTZvP$*4y{*!qMZv+-shNRVzEc%(xq-kdmlDI8y6>Ty^kZ(MYBmKK|)4`C$uXG zU~zy+<=sxG0FDG;e?a0smOKPl-5dEw<x~6m`f_j$$yR#CfS0;^_wE<5^!pZ*y}f#1 zyb3oH_i=E1`i9XOng=&_LRi?YvVYpb(vto@Gz!EQBxLk?%olJuDqxIV=0tOOZd?Z} z^AP^3^!|a*AZde!OSAGE;4_EtM=OTQGK`BreIji^*gUZ`Aae&QK7ZB%vnhGyin)!A z;AZL`4h_VeCY|W}_wVQa`t>MN4Q>lQ_EXN3l$EV~di^}$Xbrm#$AH5l&%U<@gX4I8 zv;xcrhxQ>L6M#3_^f$+sqa6z1$Ad$2fbQkE`qCE+isRI;Pdl9w_Jn`miWK|EK59n~ z5T_LmEh}A`*QEFVH{aE2V)OC;oc(VufiD51423*t1y&l9ub+?z5F$Gy<i_?{ae<S$ zMFA>G9!?L4IjuBOG_~Nj+_Kg-3V2w=%8DnTu^D5H;@r))dckWmD6u+$y&Se#-x8m_ zBaN9|(=W-g(`P+|$w60?I*N>L2Rt{3HXcvk<3<2+bi)gu&qktljoyCE_V@;`bigGi zrKOc>zBtIHsQ+aOPb)ogYIRrw1hjERvD5DNUImUi--pMp2|+1hNgu9%aV&@vFm4c7 z-f5O1-%*AKBidMu2t>`4d*$AtK@f)1!M|gKZg_s8u1+IdvqE%05Q4xMng5=!;Cpjx zE=tT}p)U<?XlIrE@n3EygpdiQU&Aov(}<J%V;^((xx<-iNQa9>yfE*m8xd|k6|pEC zdfj2JI8*zgEae6%yTRvc<bgePj~_mKXrQk@40xzQQPt4mh+P&N46`<~ciF5i9tCSW z$Ssur{{257cHF@`R15iZ5RDFS3WnVvjg{LedQH^akx7}j_M86RK4^8y=EXtobL_zg zOs@Y^;Iea1Hz@40(b{yScDnl3)XsW^dfm2mSI{!zWd$=JxWAoge16Z68rXOw>ZA`Y zE_~}e=n6c($6qusGQt#PhZ9o|`tAIE3g2Ex5mF7UW3%tmEkUHe>%XZM3eoKR0*L;1 z@86rpiK^BGtvRw;wwbc~M81mXcki|U3$;J{<aO7<(=lS|Gmd5T5S+*G=Q~*poI_Bi zO!Iua(1LVV{6)h$SF|XTXw_b0RewlOP!I_c8o4VJ<nDUV5yGw!AFy_|*^3SMEuvZ5 zgRgthyP%7N?lNhNF_ZKgMm9D!S&Yra0WRBF{A^yToU5dq+^Bzh8yeTP=Hlv#3m&jL z!thVZCc~F<qrlFU(g$=s<QmhaC+ocYM&B%HXmJ5wvlB!m+Hz<4#hJ<#E~P83VZXy? z@d)7`%+Lv%umwC^?>b9pFk9UT5Y{80Yj{%Wah>brm7yBv{yGng<N)~O>C>kQ^!Q}Y z!3-rp-2VyTM$zEg+mmhv)bO5iiH7g95Hqn{{F?UJYuE0B&Cp_MYHDt3`uWqRQveqb zldK%qVS9g9J?xZ!-2Kl2fk0aC5u;5OmT;fCs?j(dm`-5*>WT)*l_&c~j77FPILkHV z-|yu-+E0KhR~MQ9(4)#&sTEQWZ_NtZ&^JlPIl_!ai%fi~RYn1Pw)3o_Qh!CudH@oX z-QxK9`RyF^-mmDtcvsrGN&|=wRLOx1rBQ-{n&12z(a@!{CQSC;PD)yEPe@2GgTNu- zaV~=yC0kno+3<=sGz}C8OQ23H4x|@3_a{q8Nf{<wGTLw-HN60MKXLJ%%`n11I$={& zHG&n!7D3EXl9LO;^3coj3f{ffH#Mc5efP$=&Pw5MP|j5^AmFGmo)oKY4QT@@#<tvf zCM)>YTTA{jrcKp@XQ0XnquX}D_$4JIz5|{VNN$Xs^0vRfqS?E1XM2-u^rDo^gj6aA zEahY~S6so?y6^2>AqwBR4+oG?==zg4?9sn@bBJ*c-}E%k&)+}kKg{bSBE5@Bo@5I+ zWWZaAh5yZ6f8gNcn(_3tcRQ1c@2sCLwLq}*87Ll0GqAOKtInge`~HU9l13MmmGO=z zhU(l$*-0>DbFrkUY22|q#WD1|>lh_3PR-QQv+Vly>lgG>Q&U0MZPtY>7o>n7B!%#H z$BG~_GEQgHfBpJpIr+4xs0e~7wa8*n;S~)86|gRBI-BpFRk>|JYip}eUZ?aOEv@GO zi<7%dG5*HJ##F&Gy@P|6p`l2Vme-}|aC@<1!-s`Jzxyb#s0BjMfnARd5g&=iL=>3j zDn;&8a4|ry*E8BA$F%Bsjlk9cl}(K^4Kz{Se|o)&J!e{Nz&<jwx3@<qEh!AltN8++ zT@p~ZAt51bJ%JsrY*l8L#RRI?y)Ti>?A;yRcs6YZv#8zv)5%K#okQcB1nD?H9q>z8 z7B5O!=>j6qywQ957A@t9&1c#S%%l=UO><4_g{`5A3}u>c$KM*g&W>1i_p%{}`liO+ zg;LW;f^T9#iW5-_vj(zV(gn6?6f_M@DPn@gom7&L&nEB@mgOS}CTb<1pC=9Lic!Ww ze4;$#7JL{M3VT-<y?-x;%gDC=c@Fq~PtW|FKXb(GkN%54?gO=vz`9jg`AFO-Ex*L9 zD0H=@T`gV7ztGgotRD20Iin&gPN{_X`M&`btCf$;%*<5tI#~E7(vDH{pJbrxu}ROv zho5O{Xlg!F+n(oB%7nHczm60bYSWV*`uWvh%k2nef%Cl|UBu?xi-9zq%`~(?_n_i1 z)G%;1=+e;HZ2CS<9yg%!sX3Qxf&l@+anY>7x&LIllM#%oD|`hFG7udl+53fS)ifpC zGCRc6s^NGGw`t!OeLo9JNt#m}4DV&bYB^{mUJ|{t6Sgov?>3UJuf_>sjbYKjo2w=# zuUO}R8om5hJnN6$8cH<C=~HHAd0E+&?1k2pkMpVcx#<WOXJ_`-1vM3uqxmANZ;Fg+ zW>~NFRMC>CEUcXwS$n2cJ;)^E=A4|!H!+4h_Zm87Yimmgj-u5GGRCSOtc5tR>E4o( zk}SrvhJjfaapn@kwS*R+xQ6RSc{2iT`pl4kw)^SGks~WcV0-gof@4}0C~8Lq1%aL= z-)t|###vd*BLBDc6ENx3=suLA3Di=Z7>RR0S4g-3kOJBaJH_7IpjNt(u;ry?Wp!4H zC4Az>ZU9tJ#F_&qLB%w=NpS^jY*xtyIDKmv6qhZaO1smymTg-C%S}E6azbcZd_h$d zQSPVeSuIAO<56|e9ZZ$e1+ZartlXgmTbnV>CEJ<<IvAli=rk0!UFYw!3-Tv)Yw5l! ztBLYZ!F}X{gWvayq0|XiRW!Oz$$xPPfWR#ECGgwjvuD3<@~6_Q{(?%DrVK45kQf3^ zVZ*KtY;|`yFUobIwe?nZr7ht{>TfyK2Ot^u{rFLKP5A>zA5aq3-4Syl^2d+6=;BIP zRvK&@zbM|UawJ0JBk`V3$Iq`XEbQ%9LSoeEOXtC4g=8hbo?w}K&Q5-fEp3pqj&d^v zh1jE2+<UapXcXMImuy86ZBI?9a)<@ltaM?!yQ>Rx>ag0=UoSz*3G1_c2Rsn~S-F3G ze!vzaS+pV#AYT-y^%`P@Gai#B5QNYBH%qq*{y}OCK7UMKc_m!8KF!$ba&kq~{dtMx zW<Bf3OIsDdPR(xY$E#b!g?E!dq_Gui*U-qIDk@H3LU$0TLrb+&+Ptdsqq@>|4R_6o zj47v2{6NsV`&9>)*&ObD7hdeM@kZHCc<M(yQJ9?s+2I0$_ug-X0RQ&nRYF2iQUPd$ z%AMM02$Sj|F)v}9Bv5m<TM04S4YIPbXaa}CP{TIN1jX>9T?gtXl8T3*L~~acf28IC zO#_W=@S0rY!&}tP*4LpsfdmZ)s|VP%G_dC%J$iHtdhz1F3tI0ptHv#O{kGyva9&48 zY2Ksz_dkM+%P%TAbB<1Di>8?>R<$kzBeD_Oh8Hj0K#$#Q1mu%@U!nvzFAlnnwe!)p zh-lS~6U7YY>8j>+g0aNotcLP*Vn#r|BiK;uagL+lBj}(KA-E3!5V%e@ZDk@)Zt$jd zsj}bt%=$@b+xf=x0Z~uaJ}$6JIE=b747!3=TT7qz3m`WQ@ZClRt;txZ%F^0b^QLWT zT@-@H=%5%=!~Tff^!>7#`{CoqT(GgSc?H%axK_!2QO^d_6&de;o&+`Xbd0QRU2km} zY`U_Yg)DO1({>yU%2LQ6C<Q{df~)4mGsc{soVyowtavJ4-(vGEiuMs44VkEM&Z3=F zRh=d%_;{b!jWu_1af#V3UmZ@8L*E)LYP|tUgqm0(2)s=dD^z*YE{g#PJEXX%JtIBD z5-Ofb9FJAKpuf$jSaM;OelWLg>E#Bmcl?DeXdS(~Fg`Pr?Ei&auExCU@Rt+~<iq*V z#p$3~%FZlP4Mux`(7GA(y$xP}xUO=)q~ZYlj2x6`4!V|{ZrIW^FVblZpaOSLx!7TY ze#ZRrY@h1Gjptl4_kgB=hI~j!c)T@Pt}%JC7xXG{>OR_@=jwn&!?cEM?ufcECX0ad zMBL;a2UXnM+<a^$JBsbF0Dh4<xtwOtiR)g|NDEaMbqsKDj^`h=6uo)!<cS*~Ce`*Z zUht|7z2ldf_q}<`d7!`~TP<r(_F$$80{lk3WK;@#C2Z+dSfC=B`2#{(WO7<qTNkr) z3v@L{NLU!bu78HfSJtOi&i|%nB7p3^zK&h`0UC!=0LIv@xPnd&3Y3f7ZnumJ<k|Mw zS{cPPvO4fY5O{|~c0fse6fn~an^$6Qf+D?Xkyk3gEk53eRvpoun7zOdG!cDEOlKMi z-4sMYCu^JyV|aR4bOC<;kitV{c8$iMEm51a5TM3(hO3_dJWL^|hS<OFg22W}lXs67 zj|60D-x{ZpzfFT@YE5lzQgZU*;qlc6nJFnnpcR-DILz+pl|jqs8o|zQ|C&7T`4$LE zLFR|XwMHr<_nsdy=Ym8D<KCSvyRX+J+Y;iDc4oidnTY&x7xP$s@DwyecmxrH9(%=v zQdXm<TE&2m>ib${zsODBGZ$uWO*B@@tT5g)!;70=JTb<+?WgWTM~Q~^j#_=|?hfT~ zVQ+0EjlSOAd+fqn=_G5xjcigEm{MGOk-EJ}V2n+O$sL7J57l`+0}B_7Zz(DpYs}`Y zGl8``>Feto7#mk?5<W9k8)tor0ef6fRK$2m0>&;Ba0c`Z3}6IZGjb=rTZ{k_&!PiX zP<8W%99y!wE++?PRkZ*8#U<_3HYGl)kOG2a36u&`%!zvN>v+1n1TBMfFp30Z&l_~^ zMt_sqKW!m#=D2RyyB<)RRxmoCz&NC-!I7_dL~J2Bm9n(^^+ES!8Zwp0A{-XbEwxIb zRO127wwX;!9O(wOtF*N8CurR39(;WsnmJ6Ke)efe?>T6xV|8LrFK^<Ton2h$@3ort zjUN!O|GBI|K7WpSjB(En8Bikr0G+Kq%U32GT99=o`eX>T0Q@fjsudxB@Btd<l(P&F z^X!Y}<X)J8;j`>zRSL7ptB+|N-)FD^4PbcO5x+nxBb|hNIS{lAeoBF5<nh^V?90rB zhegc5X$}{~#c?IOnnp$_-tA3*kR()8Cgr}!fnq6L<zVzpWeOOp#^e;9{Q3D+ZB)>L zLVn5g?^ngIu%`TGiGG83K?hV6SK>9flL}I@H|X~xM=u-o_xF#sp7CELYgO|$@m^60 zSo&$^=;&Bs<rs3Oxw)Bbmjcchhw~5G!CC=M0APU)L6o-yTd?w-(?T(+ll0MS*8E}o zK*4?g3U;>#JYd9Hv|6o|f;E6mA1et{DF?0qr-@2w7yz?E&onJkOx%0#kArmtDwt@D zu;QR2=JIUVW(<LHGYqh2AzsgZAcVF>RRYV3eyGVxo<HB|f88zz+Cn&w!vSQN59)pO z%qSOVcj_K>9XT(ee@4!A&|FJPYlzSAxl-VYb<B1Ea6cKT;adWhP0_8Lk0ukdyL&<W z0*fReC$E7(QgiROW0&%b`EgTFnL?<Fj9bPQOzv?LzcQm@>hD-p-6cR^C<OPZsx8=A zvF__OR$7{exn^G5F}>3jgdHX$>fxAOdY$mC1<_3PpaNy;={YlRJjj2l;)<bi)95j) z@bET(Kv%lhyLO#cS`8opCW`jO5G(}P#9_}XnUk+UuaXHWrO-{^9QH1gkOhXcI8p4@ zMLvLOZf#Cj^mx@88W~vx1_plF^AdRk?5Q=^XVez_rx{LQ;kumCzrdF<J+%i08aCo| zOQXq`*f(#6ViadCM|I|cvZBcN{`}cIfdB!(OJQ)22M>3aKOF3dWuQ!q;_D%*n?*+B z&HhE*abjzu5-lcY%A!FPZPbYZ4nv7-#)c3-)sY6aP!S-1*=?Ys^uCr=B+26k49dAF z;250iI4RN#x^mDqm4WUoc(H!M1nKM334pCfSmq*AR}i8yyab|^^4=J@gV;Dn0h<Y$ z4dAZoF1m7xK^i`q+ja&X8X6jda0&+DxVcU2pZ?f_<{bx&1bWZUAE|N{plCeae`}1L zJ?lylb|5PWg^(>22(t{;O7eCEXj)to{Xl09JV1!iosPofk00kYm5tKmzY|bUG-ivX z^1ZL`2(o?uaUyfvuDMo2X*bLolAT&u$qGziZEh{}Z4){Nu6vLd!*@}<KZNk;u?2&Z z&^aC_D*O!aOo_p_J{J9$ZM??n(<+ys<+_g+V*c)&0s)Ga7g~#4s%%&C{TWFhUY^lZ zEFxZynIUBZgdKw>B0qr?Pe9UV;ND<$*O;3;J6{`|0TQ=8`oJTH;XlEUdkhMJ8Uq0{ zpPdcFbkD2ZGd2Asc)4nqyASg2P0*Lvw{M5R6sTq^K({S(o8Jq{>BzbK7_xEAbguO9 zgJ$`Q0H`a+O9xi0;jN=P5B{xe0C}<(c=MJeJVdqy)X2!mn-J_3(Ebh(l$vEHt*n5- zfObVpOl<aN!l@TFz%5erIP}+BaWK*Ia_ZzS&xlG%Ggg{<dU}6CR(oPa%m6Mfa%|v( zt@!%@JL}KpjQb8Dm9y}`U_(A|eWiyzj71*v=#$c>nwpw1gt-}6HkXu2t;tC>4&KUo zOjbMm9mW#~|4~N&DnbLKnzPzkh!;A@A9FZo6*mU&N=tSF?FCrB&07MrhS1%C*@#`H z+NL&H?3c8SjeZ;GWh|R(L)wo+H)%+P{OqS<TUUw+=5i6M?YrRx`T1kxoUKJyn|Ln^ z1RIraT49qjZa(cGY(55!H=8O7(`n*Oo`Ql_xp>{H6U1whJ#^rS4*<6t8Mjs(!vT&A zr}4J1VWbxT6&^7q=b;lf7z`Q^_vl*(pcBa&fGjx-TDTBwL8+#Y&t_@(htg&yV|F*W z)YuzH!bK=NUsa>$#OE0lj07kQHr5OH`{$vwZC&w1k=_20_J{~JvB+jVE1DP64rZS5 z8euURlpk{F{kz-#b>VVexCeJg3vHg(SzfXAD!yyLcsL`j@EPh>q8`DMLumrWIyM*E z(V?Zf(R*Gk?>AUj3~&jv?OvqU!ru2>Fma_QK-h4nU7s|cQvbe61sgA<?W25wntH_Q z$(fd*HBRy?Hx*FJN?yL)kFJ!=rLgI6kfmZsrG&*rNkE)UHh7JKalwg0H*R-{BN#(s z7R>fqc6w{x=IV!c5BzZ-ttK2|C&6biyNR_wi&09Efe(Pg0l48l1HU(PwVB`nOee~4 zdR-`mSOCOT1dvaOGpH8F(B+F>KzI_1*r^6<O-8uiH_o`33kWYLaZFz&aAjy?p?|?I zRYY!eti&u+mg6HJkbqJf_mR{P`w@~u;fj7UY=cuTZ!$)$ScFG3ukSP~L>z2d`Wr<5 zRj*=hGxOIec;ApRfNt*8l?gzcCITI|FG;FCY}*fbjeq!W{8F3^%WG#*DyerS%K@pY zd*_b(>Qpn}^4+-4edbFXs$VqWVF))<gDgHg&r?aK+}7og);2d!^hPdULPJ?nQc@PC zrstwM=akMSL^_nK&Dq8SeDkj)KsGWkcvpd<+GalO77VX^$XrNq!v3|uP>b8<Y>%@A zf*jTUA3w%GXpGfEtN`o042mFqKEcGpo|&%-h-DxIyq3RUkJ}Lizj0{1_@4?6K!lgO znR^U;;p&%b!FmVhkgt?rKWyUjDcKPZD?J48j7{DoI*_%!*04hhk=<@f;a0N?#7R-; z=!_GN%G$B3sqM)q0EmAw`o$w#AkX}d^2Pr|lK5XyJ^qgzcJm<bci#!N$`MIjUAgA! z4u}KlubflO|EeTUfeMj_iLr07FZWIW-@z+@M-^l}_=zfh<WE;0?$rl|SB@%u6O+oI zCYS%*njYc^?k*==H9_IElOYy!$ofIx3E<FR^!iE5*f&O<XUjByJ){Jyx?VzPTzJt~ zH}J;K{>(jguwI_E=@!}xYRBTy(tFeR*)w2R$&x3wrB9GNi`lpoFm+&bwv>Xu9$bUc z%LDA|MC1KLA)6_`{G0976r(ziZGoXj4%HB383S3fc;rbr=?h2K6u+`uFuJf{IdDXp z7ToWXYWqa3gCX{V`&sG0c|2pOQ05^%-26#9`25R1u)&(y=j($|sQWBl{(A<*3UeYB z>D&J0D;`I^wBPO|81SOPrEJW_-4KLHgXjC#KbpPc-OoZpHfCf?+o`OXt3h^a!r)tJ zQK~5i`dp}fL6gYWD|n)jdvD!`53%;Rh2jns`N_$HN5;HaL{cXUJj=rI$N9R?wq1&9 z+=2erfza=1F~h%fDj=|$XF3S7Y-`I5<4w2NS|F8u-XB$jGNenz1M-wJH8jF&`Z*?b z=)*^ni%Rabp{jPKTi3&um(hw0;rZ#oa1iE^g47IWv_19xqK^^`rCJ$6Xu;;&bkx(h z)*M_Sv|Ib9_P%mgVF<Gqy>{<{G)!j`H|W&cKtN(oRcR|rf6LbRiXWJbURvW`KUr3B zqkMS)NPlhy+ymBMlQ&aHdy_(TA-fS~ZtT0u8gc_gi@}9i-9RRW_=_C?Q+j60qu-HL zW0!M%`+L+gP}a|i%iox&I~pPT2K7VD)=SoZQ)bi3C*r+^A{fGcSF{PMCb9jCot>k9 z%7lM<P-=V6pT>&heEq^#<4%_&oT&on@Y(c!(o*lNGOAz1k&j4jM0zayoCARd$0%@3 zY$mi{;lKPM1P7aKRBvc!u<#5iu7Z;)(%)Fm4<5m?R$=Wn_2oT-PM3Mc*vt79BW}0d z?@ql!$fWEnXhhJaou7%~@?YQOx^~@9WaTj4=>vVLvHjVM*Xf45OKT0Q*VjV9VV@qO zZKzjV(C$>~j2CLxX%g;3Wq5zBafi!4naB5LknlIu?!j{&c<r{Mezc&1Qc+Wm0&Xhc z$a^ZV!Xt^zt)!`i)$1w|+p^ZM1K*Rq>oHNLc}1_9o}U&RC$&0VT@&bMgllT%7M%vi zkae}RTFnhD>s<Shi$ky3v#k?FdeEAk$UJcPL>*|+7Xp$mD=Om5*ju2%M^C2^)mtp{ zJ(GM#Q{jTWaO%llCRKR{BEBl$vjeBgsXt`XL|v4<%PGYPUfSjXdpB~wGb2p!-w(O; zo07BLMX3^J{@u?ScEHv{wwx>u@S=dvH6X)3eMK&x;8giIJkVCgXhX3_=w>8zx&p#A zG~<ze@E2H7_Ic}0a`WJz$2>3KMe+sf!N@f1j*a+|<5cg;c>wt~vZ2GRiK;k@Y>+s+ z!Pf+WB@)}~)>I+eArB75$GaTHQA^HHBmVQjwTB)1A9wc5jB2$OJs)#^iAQ;Y*~u6@ z4m2lxIyfNba8jbVTUQ#B9y<C|<d*3LePY(}BDttQ>?=MrkinbaA9V!dKf23aFE#XY zh26imyu57N9*#oYEWX5rd#2S81k`JA8fR<d6_Z^W-je@h(j?-7{`%8n$OWWk+6{#P zN6Z7Sv-VM8wr|=sMD*bJ8{Ndr5dw@{051O_{}p;+={v!H??H&Z<P}L=0-E49=dVO9 z4V2EGQyxF<0sFv%#U>_njTluL(ss<!Hk0K^J|nBYsg~eyGR}!rZRQj4!Bv)LiOjpP zl@hU1C(vkjmK(<!H*xfQcaMy{W~rQ~O<`tqj#R3jc>s2|-pDiUJE5#fJ91Y&`v>&r z2L<sKY2Y(6%=FReglfO2fuESHn{Fu}WH+*Q$K&$F{wc1Qg#LK&rNUQo_vNS~US2Yz z5A9Rf16IeYgCQlX=F@Pkzu{tc2h?F-O^^!XIyX1r>&lEYb5U`GOZMf>2Ww%DwS~K; zaneoNDfY}#k5xx8$m$(5L!xmKVdbh?=(!f}TI9Ccj#!;nt&|9gSh29{O3jNXS3Acf zTpOT6$Z_mvp=jHRvoMzWgS(|V&_>oQ+^w{mf?!$2k5wWr@x*M_(Ht98<xW-z_lwpU z`Ert`Tgn-^|BS<|+Rq!o^h|D1pU;G`t{3Rx*Xi~S5tJk(>#gSk%yv<V@s<Q#z~CUO zB$W&LDvs^iR*v^Et0cv`r3A&TFRE+AVjP`JWl{DFL_DdeXk9t3`ls4VIV&#$-lD(O zw)0vooM@~{sShH>DJZHsEUPs(Z}1HR2ZKs-Bdw0GtKJ-#$Rg37=s!iyEq+8U=#G3t z$WhYM4;sW*G>0}VI!+I))sSuUI_leVRw}O~_Vwqt!3%Unt65Mki!ZCtQ7+`-PkRTY z_2UC@cvOb&?9k&00k=6b6G-gI<>nX*?)JZ^lU=*EChGO~2s?~xD8{sK=oyB1=%$zt zaoK%X`TCN_G=43NNe@aXMUbzBop3=s`Jshsp0^~!W$j9RJ!aopJA{(AiRznZ`b6qX z3>w$r&{7u~9-(i#yNv+KwN~cZG_Xa~!4~)(L&~o@73jMQVNlue7H6cC1(tG@mrqhK zsdL8U5^r*gr^?BA-|49~^()ME#gV?obeRWY)2-S}m-ZY*Tx(JG{H+{C>U@7lXk{CH zM{0pLJ2!etzxhka&I=_vakFx4Zo@8V?njE8vTc0gSZ#Z#%`W9w!kESO9gEG9O%p&_ zVRz48=(<=!bSw{@Zm>sKm18$1LnjbmKO|0lS9z1TjQFMJpekovkluHzU^37!wcX(U z7|YDji`?JfBz?|)G9tLJI{DUl`1;$eskQu|U7?!~DjguqS*I`IrKJ@W@fnD%&E;D8 z-S&#H$DEZ|-X8mMJ2Q36ENk<bqs>l9ERyd}vpU9Ed}f$)cRT$gs!e-%Uj;Vf4MCoS z^M@{EDArk_<UKlEq(gr_M%R6)NSP^Tp`A)>+OrU(h+1uR)WbyF`N@CObyas+ku&3- zl~r2?=Yd;?WA`=pI`d=F?`%tt2cfChV3VToYff(kKjK-Rtx~g{C#4>@4=u4?-J$JT zL}jbd8t*=Qct0;9cU=Hy2tzE|(1=n4@Y}?R#>LYsoT4AX|8^1=!kN#u*2vi1mTtqf zSyKm)VTZ8g%$+x@@EtDL)683RM6G=I-FK)aM_Zz-eBkm(mm~kZ=u^!%yjCuhm<hOd z@FHH+o2x#D&%GLv4L|Gbye&fmDIr=ef9uI|%}`q-n0D#Gzt<%CgdBDwGZd5yhQA`~ z-vFO$)6?H4`1pQH2m|ezuxoVP&tdXV!#{ECK04=NY?xD7Gp!P_8P~C;7c<%s)h$_I zScWQ{vF+@o0A?C^3_t%rk1MjDOBD8Q(gg8Rdc$*k=+=2${Q)m<UHP~~nQD4A1C4$2 z9{*zL&HF+2iyOzw?6??fHDjmjy#X#+YnX9<G|$e_UBN-yLG+)qjKmgZzRC87JtCAm zv8}NJvrtB&q9x>1b1bkg0<EF$>2DqIsI5Uf+kjGTSDqas&K~rc;^!THB5EE+e9Kq` z<HPI6sF!r=Ui&(vyQH23*(nlx{;Zl7lYXJZDLene0aC;B|G16*tG;_cv|?M6T|Vph z!LRI+^<N%!n(xxxtA5QqDg74##My4Y01P`O%`^+m6)zNtiz|8_lymSz5_p&k$b<9m zKzGAI{?aR_I}!b!7(X@Pc)}cr<$xlt1Z3nmVz0;W91_^B080+I!~LG%>NkGO`MQlQ z)vk2u)RTNsz<{E|9u@xMvGeFU0YS`aXFUxG&N|fK%p>9gYNA6FX==(on+o1@o4kHK z3LpLcU!asTed<3&Q=&s5<rkQ||K39NzlB$#w49p_49Kt8*B~9jaR-D^guJR*MGA=W zUHt_~*%b3|`yS(Dh%U8Ac@=dpq`7Z;xAKZrNI_AD?Vvx76l=n6pz5B)9_G8$wDO93 z&aas*SnQ@;0Fx*Yl(G#WIXGEcUnr`*4M^22s`T(W1`;se`c|myw{0!`%_W`z9K%V6 z`2H7DvL&b80Q;(Br8k9mYg;li_4rv4+q_196+~@cz~W_hO3{cQUN%O!@Hb>*to-*e z@-mf=GQ0hb8l-O4#pn;1`KD*mvYH@c>G2*e1qOwWJu8?>J(q{P5Y!-WAPM-F|AYI^ z*>m0l#y4PJVR$xPV8ibX;fgr7fw{M7#R|5g(s%HQpHFz1_J#0aY~l@Q5av5ixPYRm z`f8v?c2Iip+wbwQ<<-gk<DV4}h?HTXg7S!h6QrT1)XB5@dM&v6=lK9-z}wB&8eQ#~ z^Sum+g}J#o_9Nd%AH9UgQood0idF#chaGtIu*1=w+*=eXXGcs4&|tJMtp$P@tvXG{ zQVcyt)b4FU{%t)@H4H-~Au(XSYUEN7R)^6GCHz*NB8e+M{>_D-g;c$3Un`65K0$J7 z_(%fU;~n4%ZajDpL!SYL!4GHbVbz>2^&7q@D9MsrNWRzcw4a@2Wr-+Rr`D~4CJKON zh4f2^v76^Zx@)F3+Y0Gca0n-T_qO><6dN6v@Bi=2egD;Vdr8vyj*E?J9~nLZ3o+7F z4>$1fY)H8=G8{)4BPmhA-x%PK=j(tz_JkQnXE9LWyVX9`o44CC;`33VtW`q2l_{<) zn^>cvPPa;|+&Kq($iZ*CK(K>Y;jS>ZM(!@p`YX_89Vz0aM6hXw@(<x+s(xpy$ZzG^ z6*SIJUM^d$HEBnyh3oR#??zgB(rweJ-XlH2aUN^^?PCbW2BkYfHD~3BJ}B@aH0S>9 z^?gXz$DpnCUn=snfjo>98s_MqJq;<ROf-k8nb7~P8p_jT*Oq?owrJNnj!P||N}X5> z!V6(-CJZ$+Hg-)NyJIId+9Rf3XwyDWfxoo#TWq)Zsnq4mRf=Foy2*DyUo0$T4rnJO zC6@SisE<V5iEj&b%+8{HSZ&+UQC;uzfzA!dDb(TaWvZ7!FxT~wo*Tzdo7DjU6Gg-b zXas5#hf;RcdiR+#CV8_n=t<YI29o$3QGqQ`&(6)y$h2_&-gkP`Ott4pNkoR(McoYL zq|m&RgJ{z_uVpInom9mTP}}Ofr<K{Ze?n$Z7I-*(WdJOKP>k>NJ*U>(N>iBoEWt@4 z)VED7m{xouGvAHoTP^3bIw3ssxoGg-Ruq~P!;K1<sJhVg?PAI9r~5(*i`P}R#$$*J z-ltM7WcJY<to04v)$)f#GjdP1twS=iKa@9H?K-NgP{`wDHnsA>e;y2^DHu8+1FEgS zq@2=h^3GWSUbxTM4y9to%-rzcp3?<ac2i<`T5JhnH>_&IRjqKdNIexv(=m0rQ|Ql1 zM{$wYuFEy~cjy6s|Djmbg$F-==a|YU4&UvypWe;FH9>J#VrFhSfg_zv%Il&$(^=X{ z?SHSqTbYjsvbPOU)f<LNx-k_z#1Ex=Z+r!X>Sg@nj+cjJU=OvM>}5cTNAF(zKIa?U zH|@;AhvEcIp8URig>CLCg8Ppnp@@UrM*<F>!(X3)0Ro}t!~46ikM|woRVJgK8vs)) zokAi5Q>)*<&e#8PbNqiBX0@7lz@z-PffPgi<w6KhCf~VQT+p@#N-Fdx0ZnoT@&@(u zCEyaM0NmtcGzflMRKuT5!oMEex<df{$o>DBYX9qs;N-TI2PzdvQhkHTGa<TkqEt!F zmzg6Pb{{{Si4nT!5SW^nWHHStzn{rD)HW3H3Hs|o`_T9zm_Lx_F00suvO?Sk(x{D( z_mPb>pHUiFJDa9~4U|0u)id|3w!}0T+PiyHI_kwh=?o=^ln8R7_sGAPvWL_a*VK$S zTDY>ma(j1=BKS%akJ1*#3M31%=Hp%JvU(&HQ60h967$+OhmRXG7jWw0Ae;Y>pMX{U zf9=QryNht4HE3;y7tbXO{wTy>l#gs<O2}?|S=n8F{ss0ER7GVa;2xJ2QqHe*g*!Xz z;~b?j;SB-A#4RQb1C@{%Sx7NVu|EeTOD-(vJ3C`2DUOm3AqDcmRdqhu;ExTU>@Aal z_!;mg$Kr-ZVgQq3>Qd-qr?0$rYZ*z(cSPkow3LdSzt|<&{&O#IK8HHQ%RhNjKiFrm zJpY~O$1!50n8bc~+h^7yeQ{NN3f^Vost*hjyYQYa8?tQk?IXO6Sc2s&YazqGtbxg} zYupN;AOBLWKof&A4CGw&2w8S=ihoI5=7v~boU5~bNy*3z3bU|Ep)8*lQ8q_$U%VJm z;eBE+kSnR5bAUM_A3U)FxKY2mpRRs&mi0UYRJMta_A-zpo~TZ<Rhdm3wxzAAO3&E! zEigH%lGEe+7ve{k#|{X58%KnF>(Xy$)z|wcrWihah>hxxzc^BhHc;Qm4d@X8&)~+7 zO5D-4Q~AA*S1*d!FizbYo|BYpaQ{9w>gVG)o7^CJfRuH_`l|q(!$_IU2)CkjoUo{j zh{`2t>od--hVAsEfZ;pX8@F`~U{ve4;pW<UxC2s;pC4OO*)D@(Hpsii%0K-)@2eNF z9lbT>uV%vSMpL5~-v%yg3d`5?FtcYs(Jo?=C(7LZ3UiKkq`_-Mo7d)SQ`y~jZ$4O- zeGm=Ff5`0j2?zEkoBo%tZ2E^&IFhmWh=4U2;Q2JY`+h#wlYQzAu4jzr8aBTtToH}5 zxv27=DAzdXQCa<3S3AywGAZ?K02))sGt!wiQ*BVbhXV9hJ!Owbs;WAGho2h-IJ@dT z97O&)0@+%uMdyp{TBj+QDf@oGm!NN%As2-pMetvTmpRoxIKl>$@##vVM;cO7N20`R zp%L^1OyJZ_2<KGYcY0(({tT)>!Yn^ex4_Q(<4Ngw<$$Wdjj}85JHZl)IAvv^&lF^- z7Kkx>l_kmJ!yXa+(%20F`!f!~x!`Y#)CHEW-M<o9$XCkxy;587yQjQ;yGN{1Ywgpu zkuCu{`1jdeZwh~Nvn9h&*2{Vq{3Q}#Qpb9YUIK~X$R7?ZS#zeYZ5n@M#5$KdD-3cW zWWM(&Tr;O^xTUeae6-L8KD7QDGnt+0?nNpzvYf38u7)1H>S+y4$Hw|jYwSB{tqT_m zJHyX!qiYv;>zpdHZY(cqtUSH$Y2Fr#VaZ5wtZAd_nKZVwNk~+)ZY~Za`1zHIP)mx+ z?&mAcRK;ptBuU|7Mao6OY2NPB%2L6!RcQ)IysO(_ve9nx4+V$Sv#?FGh}g)l-&~!M z_L}x6C;ZeT@%o@evy1lS9DY^0+eDICE=814{;zhfGpfmKUB^xl5K%!88Hyq(pwa|s zgF*-(NDrY&QG)?wgosiMBOpp0MT#g*Kxv^Fibxqjl%f(4LRCaXN(_#WfCNI$o9Nti z*W6ii=C1SS{Fop4k^SxO+kNkMzwh%r_-U_r*DURm4Bq^F`{BDX)X_9CYDBFxD|R?P z72~!S<|8Q>kJkz(^V+e$^x9Ca1_hF~{__4^$&}n<CQO4|0-<<DUcbWlX~X>-f$cJ_ z&zy!qG$k3;$g&S!cs;E_lpL%3S^GRGfn<?Uq}=%;*}jz2D1I$rK7)X^^;-9_d_R>+ z(O-VdSEtXsPG6p*^cRLL+1CWc##A;o<IAXzK9>kj6zsvB4tkik99mpjJHYJNtwAYL zQK+bHcM%nKPhNv{&6&|xZX8J0ymcEFR{r!UQ_mH3jd9k;r-dn6)1E{WS|qTF>oyu- zqw3hT<J)jvi%)p>?%zP=zkD*jxU}+PNE5@J5uW2E`SsZov}~VQs_D{#lXU11>3j7B zC2wrr92(Rn;aA>haqU_~qlMP{xaqp*<~Za&rK%KO{s#$aDz(3ApOZLrypB0NJ@5A{ z(djU*#*f01K2pLE-C~=iMt*pP36d;*1Y3CvH1dk9F&aOk|Mc?ZqOEJN8abah^%oD* zK5vexB{NUxo_m7P(;7UJbkmC!LdQZgF2-XBi}{S71+u*(E7`~GYBSY4`Fb7Pe3kAa zxKr=JeF!-B2?<D?iu&~A=+yi$@nlCQ(OXHS$yv8q?}S0$deW*$>UvDm8}YG+@A#&c z=ZLbT;<A*32lK`|iDkwIRrB3edWNP>Jug51yi334qcRW&C@+U|k&Jep@$q?N#m<Q~ zVJhxcKv&gA6a0*i<gS?!Z(3eUv{TJoS51OgKtR6a;S&9Dc<#4-J4NaPVa1cMHXHwN zQU(|K@s%ZO6h?lC<drk6uiP}E?Y=lrF`X14S6s%!pS0V&oEc-4Thiz`Sb2q^;?XNk z+`>Y>UGW?<#4X}VE1G{Yk5k{==zipF;}6Fv1NDR224y9rdshP|Ppn%eso@^l+%K8^ zF`^{EXonzf?IYsbGtwG(T_*=SWK6%?S(=)1DkFJ1$r6)$2+oCo35=A-*chdMcW0^- z;|Be0M9)A4#jz6hE?K?#G=}@3U{WBP1#I_6GevrHn!8%hEWOa|VJ`#1_=-fH#92}T z&tAoni;0Q4r{a&Y-icD$c?6>wtAN@?L2bMdNF`FF$fGOU>Qt9qO5ygK&&MB|Y}@qU zUiUfO#XS72niC@qb-c-Ltd4Z~$*z#kj`DNr#syvT4p*6pS?v0cA#<(pNz_a+e`K`T zeM_^l#xpLw+0v{|BT+}$<Aa0tSB2Iw6RWSS$d<#QXl;|vW~xv>AfsEfP2B1S#2p2D zMSD}!M>0cum>-{qRsG`RS0TtVLS6c#TCAd=ct*m3U)p)N_w<AYF#d>1*AjMA^!En7 z)S`6fvhuIRK3Kij7}h6i=Xc}^dhWI!tG7m{*VIg?s9@5`$oRaS<Df8pa=)V>GOxig zW6PG%oPvU#F)`C)Hm;72fWA9>Gwslu`y-_!dN{naM>;2ErzA0^Nyytqs^i#~F|1)2 zQ^?MxrTVlbP7!H!{jAFoX6o@Awn0HRp|^?6LlI4TF3!Cr?rX+BvPXX<Hn)gu5qV{q zoNN&lWmHh^A93fUj?vLTdyjV)v@#yq*^*H1?gvaw#By!!+qaKhJ?`O=!pBExA1|`? zcy~xE<Kj8(g^qDWJCAp3;q2}I+TO)RuUqE^=s|BqrPsx?vm!AGGe9g5R@{TWKRf$A zCPw?n_3MR-O1jwv1*#tcXROW5-L`HCRVp+@p^~=j%*2j{t{wY)1hrm2ZMuUc0K_f| zD;G(`X~F7jILWF?5qee~vyw}@%jSt&X)&yw_Yit6<6MJNcDTjI-(>aEmu;=j60L1* zgSKw<wGLgr1>#B|q$9;?(#d?A)>fx2JKy}6pFdi7Bw7jpZ}^ya$?V^Lle4o=DX6^= zd-rbe9vvO4s3<oDg{e>!0Fu0+a-bxzyRfnn4d5EZeajeL-qX|cDW6@t6CBX!xQ>p5 zqU^T;QPDxit$U6_sW)1LOViR;&K;5&_m3Rblp;QXdF6&OrP!{wnIkOv`?%7juzYkW zB^xK6{yXHWzwA-b2az`6=^@5?JKH<QFD@=*3gy(+n!_g{R?oI~9Q-jVs?|<utG#+n z<;Yyl$v!O|&D2h6u%2B<XCi>#2oTu^w1KI+`%k8(>2mi~%Zf&rgMeUCNbLl6n|n;$ zr+YAbMWkM84SE%chc1P{s5Yw`f|8xVvjnBSFYnJ5*DvQm<J-p-9jv;IGqkI$l^w1% zH@~xWy<})Hp`3LxH+M-vpY55U^AP@9WNDujMAky-MI?H8p1)ScXkq<wt>RvO{OpHl zMHPL8XjxN1BuM3zl!aJkxfVA!m)Y6UiO!|xpe1|s*&@j)GsG_{%OSJv)2h_h@@<IS z-2{>gbc|5iHjkG6g9g;c{dEX&80nJ`NAImE!%NSDEZQ-D2UmsH0g3o|rSL0@{Y@oQ zCCf~onTQI7ZUW*(^h%5C8XLH|s|DPn-yTKx6G~ouz9j!TtcJmcV|U-UvdbqTf+Py< z=X`lw##yuZ7io&h#<00~2F~OS@@G*OFV;|Za}<S5SoWkge~Q@PB<k7K`QVa~_rQMY zGqI6N%brvB^{ZA0eRe%ImX4|X9UEyia)@*>)`svaciGrMD1HB_IL51-Vh1x63XoIw zi>;z&`b)PMBH7V`j_l9fEzE~qEzv|NZ!w(#=JuXRELA>Q-n@L}P-$&*-KHg_8k2q( zdEXH%YqiMXL*!~Q0fF7aOiY1mHBU>l+0ug9=X%*Nb^`;4EMoTM*6RR8qGTA%N*1Hc z+PlyeJsEPHNnmv{72Z{N5+!w{e`L-(QDv5HYk&(I3^N8&?Ys};90H@s6ha6XvAZjU zOC_*$toN@7@7_J$<EGx^AE>x=F#i%H!E!4ezO>}~B1`=IUd74;IaO7nY&WQAq^P8B z79lc#3`bAOLK6`3mP4uQ$>J~w+`1-$73TTOw6&GupqwOc21YwRFlc3wV&$2oN4Zts z5Ml;f`->315Blti#?0*pnzb=EOJsX=L-Mw(=CMDs!5+(t*g!K|jg6nwN2tM3)ro|= zy=vFZYTpM5OgV+aPGHkAi%v~h7v>$skW7M^-qg4eaQ9{e%z8~-M~3z%XDE$Nm<bD0 zmK9LJOTJTaswD)%!eMF~oh&^%jv!h5J_+6<y?o4FpM<q-qK-b*N$$=qZmL^FR>L$W z8bH?*MOeu9zsVltQPiyYau`r28kZyy7^&}FSO4$%s(*c9)NgLS;21t%av;pWGi4o_ zseVrg`@9mX#c>t`R70Y9{2a%7u%d$czxSitUo<uMDk|CnJ`fypAzQ;WltGRXsKI<f zLNyM3yl|Vo)J;%(qxD{X;153Jvnqly{<P@M@!3IF1TD5@>^Hg<!-&0#be1j^pQII- z*3h<xOTHb7|K{UNmvL5o$O-WNPQ(4)EboedQub_W(}kfm2uuQS1BPP}zh150KT+3u zg$fkZr>}M*$mi|^y}39qgV=xBpVqoFt*_0W1>A`c?kfP63K8abZaDk+8L!%p)*Kc! z&5XM>ay*1$f8BwQ<Ij1*|Gf5hut(%G^iPAYT=PhzH}iK-9pUh$4PyHnLV{d^UI!i% z({}}o{S6>4TL-ekn!0~;Z~64%wgA^<tMuk^#D=~mH+@htG$`#bMOmMl@Iv+6I-Ti_ zdmZ|pu8aSQVGZ9_=1`WI$$r+_in<YFW-5mQlq0=YU6Z>sF!i&ue6)dwHUR5eh@1uw z7pe!e@O+536aS_MP#0P`)cEH?1a8plkE`u}6WRaT=l1WTS6uhrKT8MPo&WSCtor{T z#K#E`{(b$1fA;0SvoHU*&q=kAT2L{8GabSRc4y|f+YM>!|94MG-{m~lasa-8jRh&( zN6yM2*SF+xp=I&#pEIv$tG>kt^NavLO5gO+0}`{<al+hGEWhFAQdYdd(q2y1p&I~c zyYfRQCr1?kiKyZU4a0+}V?7*$0{bE^3a2i!WB7;${3DBR7w88L!rSjiGi5+)q5Z29 z?Kj}~;W24FK(J;-?nV?^a-nniyccWF^Q#>^md!aHorD1zr=s?#^D+nOiXhsxHRJcs zCvB&(0Y`u!T0MxwX&M)EVu&eX0{w!~xlbn_fT0zM4asmSpW^hG0nS~`xj#zRM0FQO zt;E;Jqy=Ao9UGKZ9nAqoWLKT>uPyB|3GlT!BG$kyk__-WY~J8#J?`*QWt=OgiAq?= zR6Mjg;5$MOYUL}{P;Du|t8t9;Rct(T4)vfoO|ppE!@)dbryzm09FP7V1Yi{PguDim zzwhTEZq1`O$5y;))nnrf8h!@hEA-~g0taTePl?gXY3c4idYbztuTu>kV^$fGmLvT> z*F{EN$l?g0XIEhZYwacP1+FcsvE;4T;KxZ*Kd`wpBFZDgCELKaNeEI%8pZ%PTbsVq zqe%*TQvy=3Q!wbmEu^M{#wDEY6BF4T*S|}Yjb5{!UgMyCYd0?p$~{)Ha5?AcriskM zKTc!?WxmvzGiOW>cDlayO5f+)X_;1?y7(xDV>)hn{&2#Ad{IOm?#AXoj~Qz8eAIwS z^6v2`VpdmkF^oJ<ca}JmIp%^Y_~30QLa3i_b2$JP$=l@Q<%eU_kCwUW-lkQo%GUbI zPYId-0GSGn*@m8;YtwNoR>gb0g;m*AlOXcumw7SC!_$*yckFI$Et-F2Vqx9`fejD` zI7_RF+IpMeEkaA7fP|-M<3A1fJjUFxxTE8(vN~Kt9$h{I(kVcT^>fQ>SEII7X@0iy z0pteh6eyxtUqG8YQ(gwH?W?KFtAWhf2ZHOq#=eiWaU*C@Z*Tarph=6>Xm7(OMN*m0 z>p(nxYT%0qlnp%`P_>Ra_wsguYB2pcXhZM3NI$Uj&R5>KUsSdqfq4LO5&}E+{|X`d z)?K@X9tD+w#skd`L7whYM<33xAi6#<&I+r3*~kax4#{|7bU`A-Dk*q!4Ef0jK`vUy zPg%2mBl*d-35s}0-_fzUDfxA)4J0&97!Z61YP(%W<OFvd8t_RJK;&3Em6vv2#oK(d zX_R`tewo1bEKY0?py<{Gl?9Za;sAUQH2dJu#!C@Za`D>(Qi20Nm-h5n6Bj=uVIuH0 z-Ur6gK|2a;{o!;=y>8C0gFvu-zrll#pKlkcxWB~e{QPM>{ENcYWBg;>D@4IDP}t*$ z+XL-*7~nFguMDSybpa=XAh`i8zu2MNPf^M51Lh7Hrb_rGY+D;XOqhe0Au9t-poZx! z4OtCveKJTcwCCef5aWS|aevpc6))_X%rg15BktfDjK2#Rz3o6YezWA_@sx3)=@+AM z-!{AWs*?;h%A5nxM~Iib{pxy+yRW8k&GJ7zpbcbci?hC{9=1?Iu~Fv_`P(MpRRqe& L;%KSiiOc^2L<>Rb literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/after-1440x900.png b/docs/evidence/cpd-sizing-investigation/after-1440x900.png new file mode 100644 index 0000000000000000000000000000000000000000..39b14e7d6f86b6996fde692c9798b50570f64c34 GIT binary patch literal 23143 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%0A|){Ax_e+ zjqn4c<`sd`Lf#(FeW+MZJdZrj5-b?JO;73wIU_fsnR?^P_2N;iwRN-$eb%@KcU$MT z;pJRpvILF-Lar}x#)V?H&Kh8lzQPM#Fetw1h%}Q7WCa_(Zrd>*SvX{$=9eIbYd*Q{ zzWSMAK-fv#G2Q@uHVOkH!J^l`v7v6DIo4uRk`FJ*b-*nsf#Wd|48yjxBv+(0&jWlS z<p_zPwp-x}M3YoJjAIi{i22&pOOGQ|5u>o#edD3r>kHZ^dfGmH8yW-`v3CL;V%2+Z zrEU=tu8j%Msla?j$kL7cG=SGoMvk6A?1il4Zk?fJJ4K|GJRn_Y*%*{nx2(6Z^?NFp zo2hNX*W-wUa@R@9cH+vG>;e9~rU56%LS1B9XJZg1#OhO=;e&`DRL08}mnbH)4+|sL zzv-j{pKE~L!IyH&lDpgbE(X>RIt$n1cd{^okx%k=9z*w2W?(*0*Sn{vT(KT!{Doh; z{Yt`kD=;k7nSDdXJqo@CiS6;oT{ei|CH%rP0Sp%kLTn2K^~YOG3Ks0mULgyBerH=g zy9;M+3*6TzQQ33O{k{YV;v1z`l-8+KnjADzW9n7smh9Cs`jarYH-d2G=>{P&3SHX~ zxIjAM!K^pXMyVbi6a2$&o7BwaW{d4oslSYYkz#GcE$~juvyNa~xrq-A<f}0>HYTh( zY(Yu4W!vUZpsJ6UvJMZQ3xD5k-dnh*)hW-EKeTqEOJyu;WwPzNl8-31I9L(cjA-nj zTOO$DtjuO1)XUMI>_WlRixq>S+R1C4D+NMu7u~}K*yj6G&c`3=tL8YdtRFdlQ}>7# zrSzcbEx(b6gn}f|_$Wgau`SCmdrFDngIh7gYzE~Z_(m?;gTsXGwf6z>N+o5zdFDNd zJ~J9XZo|ZMc1nUS2a5Y+%5^Htz@DE;J6bl7L<k^lqa+=10DdSA+#wI@5;~I5Pb|n9 zWup=cP}K!N``jJdvE0K3<?y<(9$MG>m2lf$9}U!mSnc<&A*~*NLSYz3NT^{Iua<tN z=r^z*E4*n_duI-g+rrewb_}kqiiJOnA6Z-)6X1}x;QeP0jpjaFU!Y|R6Tg_-(X0ZZ z`q7R@+RYWOO*tJ2nN#&>PRy+Qbmi@uqw<hJIjaF)?-W7c-BI5lTurYDJA}E4?Eq7@ zgl7{b;2Mb~)2vc|c>g|!oSD%Sr>>%6QU;DQ-D&QN;}S%^8XIJHR+f!NhfgJsDWk?E zLy0pCxEhoh_f^A-!z*+N%O^qILe69|?;L-EaRC1XOvqfqL0z}YDdr`IjSme$>ow6p z9M5`bIOwI}Ck;x_<xlf3Sq&(*`itO+bagwLp2_sjDHZSEH90<3x>R?wmDrV_4v|1K zFGqyg4a%RL4thJ7UK133FS4rF%hde@$e=t#Vt?AGA#dmm>oE~=4Fr3t@b8~tfon|D zDdo-@l(!-KbpL?canWQ|(B;`E0yLmCx(J|vmd90mdwV-lFotF7cW_h}Hw(t0iki~J zIz2Jw3CXwz2)<LJ3|9n!5{PhRE&Q#&AQl+5_y3LqLVuC#h#9ZHtd$oq05U#GOy#+C zj7Q@(cuRnzE{I-URW{Q_4H1YR1)36{)6E2pf7#KO51mI&l8TMK(8=Ko{{w$)4e^B! bTwZHVxz)7a?u7*m4TUv5ag1^F?2Uf_(hg`^ literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/after-390x900.png b/docs/evidence/cpd-sizing-investigation/after-390x900.png new file mode 100644 index 0000000000000000000000000000000000000000..83b8569b5ade484d5b39f50e46baca62f3827209 GIT binary patch literal 30728 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 bG|UP1y~6@kXFkJlV^CGnxRQP8&g1_BpZ#(U literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/after-768x900.png b/docs/evidence/cpd-sizing-investigation/after-768x900.png new file mode 100644 index 0000000000000000000000000000000000000000..62a0638f43ede34b0858f645413d114e9af27061 GIT binary patch literal 27219 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 literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/before-1024x900.png b/docs/evidence/cpd-sizing-investigation/before-1024x900.png new file mode 100644 index 0000000000000000000000000000000000000000..b9538ee4c7c04a8aac80d9aabc6a98acba883d98 GIT binary patch literal 27650 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 literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/before-1280x900.png b/docs/evidence/cpd-sizing-investigation/before-1280x900.png new file mode 100644 index 0000000000000000000000000000000000000000..9a94b5e3fb138258ccc623abb4bac0352e1cfc6f GIT binary patch literal 24138 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%0D)Cc1S82U+z7D;gfSqMq7&-WFOz+ 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 literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/before-1440x900.png b/docs/evidence/cpd-sizing-investigation/before-1440x900.png new file mode 100644 index 0000000000000000000000000000000000000000..9049d7c61e68bed804cbd1b912e6d69ca59c3edc GIT binary patch literal 28427 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 literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/before-390x900.png b/docs/evidence/cpd-sizing-investigation/before-390x900.png new file mode 100644 index 0000000000000000000000000000000000000000..dfceffdef7e5425d01ade130ebdf0d22d3fc99ab GIT binary patch literal 30296 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 IN;dcY2UveeRsaA1 literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/before-768x900.png b/docs/evidence/cpd-sizing-investigation/before-768x900.png new file mode 100644 index 0000000000000000000000000000000000000000..661fd7bd2b0e3cec60ff23587a5c43d7d4eba6f3 GIT binary patch literal 26800 zcmcG$2T+sU_bwVl6h#E}Q<SQrC|#s?5CH+{y{kwKy%S21s?r1nq=WPtkX|Dopp?*y zv`B}94xt1{?#}o7-!tdVoICeFXYOIhB=4KI?04_A*Lt33t(^}VYKqjC=`TYd5Nf3t z&$S?sb8X<YMR@`2ak`t$2j0lsv=pB~%214JVB@^Ctg0*oQV~OS`kDf4Uvhq7=mvpY zcPG8bX02GfArKpRrRTCb-ewy!K7L<DvxqxeFP{lLGk6C6zodnzYVgt0RejSP{HPr9 z&vUz*+~e5hgoLqM?4{h?<LHg*s&CcGI~?2`9*Dq?RJ1!q^0Yzg*Ph=Ed-yiRe(z-A zH-D1P)6bHx<Mw=zW_v-RD~48V{42*OACy~Xd~EDo{DZ`v+=7C~^78WRPoIJZg2*T? z>v>Q{fB2wjV#0XuHrS)!Jatcmjjhx0BG_;@*aU|^djdX2E<}I)=$b$VJ~E}J@U?>X zC$Uq8;0^NiM|^zzlE<xc*4l61=9us#-oJl;(Y4-B7y=1QcpmelEof>(&)vOhet!NR zCZ<wS1D-$swc&XqhzufAe3x>e#I<qeBWQ!YeF@?bXhbGAZHUX*bI?j5A-!wYuAw-< zmGl&86;j;5fl*Pq`D$sYy5P<ZVRs{iZr-_5`1R}U`k5vi1oGpLJiTnnhsa1BcX#*T zE;4;Ry`rWj6XqDj+}zw2V?)Cv4h{|-UEL)UFhZHFlx;RQ9BYlKk8idY6>)&aC<Lv$ zyRWCGhj;W8;bCXjw6!e+XQZZp2QQ$Lz3uR=CH)m*y!iX~r}1CD6f`wW8!~BGTITZp z1MVbN432tspE7$C^zf)CTU}9+GPrHj<sWJXLfzfn|F&5+RPB)rm2=~a2kNS(p<!WM zT-+^&EhtS2c%A|p+1sT>WiG9rypAfx1qFAnkV67t^7~t8cx+|4VBL(PsdFm@$K%H~ z!ug09$6Ea17J}az^$Uv=D{c>)+8FzEPfp;?PfAnoxzJ=0mv0xYG8SykG=eL=c=+&P zTn^|a|C1@SUajNIeg~boi16?{ra=aU#dR<22&{TUfo?N0N^bDL=C!r8UBEHx>+1eq za^10Df<W#*01v2lrj(NeM%R7Hq1N_jdk%&h)yHi%Zi&%dQaL+09IszVFaG>U9aGsa z1=WB+q2w2?45$jv<SZ_}wT|!aVu6>?nfqz_<M#(=ywIiDiZPhEa28LVvH5S=*<cvg zxDp<KF(CDvVhnS#m`9O940CC^q%Xd^*$lC}w^!{jB_v5a-4pZKeftBZR#8#m5v>lU z<FXx&dG7stO8+fi^zcBIoUW#3mN42+J6}D+ljl}KcTdk~rL}rTR~P5Kd$L_IEM7dW zdTDUNak3yZVSZsjS5GgGM(Rk0c)B8u+v#HA6c*O+=;%;>`BKNuuBbDLAzwRR&Gy%) zdmLO`I-Z_2Zf@K>BQLM%>gsx2HN7qDn0kxHq@XqUA{5=?Z&Ym;KZY<z9M1Zx6Y=B7 zFJHdoMDR4c&^K`jy~-k0f@r~a*MERywRykzyfw}$eVqREhWS`nDXM!+_#{!?W;QBV z7vFEc@mb(FJZAL~TIp~`v4>vN|J`Q2Psq2~<AP8#^zY<Gn><uZfFjFib?YF1)!$8M zyr*k+4U3yzSZwjK-C(a%fm5Bd8pI|@kGd^Q%wvejYdT9d_(CC=3NexgUtQhY(jr1j zcXwTvmX_E>MGbd$b}*CG#k;$^^zLHFYHDT)17KHQfJGf_OyMRhVr)+iHpE=!L)215 zvf9IGpk2{SlU25#f$@$Y;c)6ZPoKw4KA==oPzbw{39fn1cf1R98w+7OT+D4blG$%t zw)tQZir?+wjZaL>Z)%e8KVC|N5zh|)?Qed5?L_l{`m4+mx1U}CMpp>>TbA7C1^J`Z zlsifslJ1^C+h2PS`oyn@>TI#2tEt<nmhO@pjV$RU+g>xF{_#lLMnCgAh~#2<e#Ee4 zqUmxYHPtoRNByQbN#lQdO#cz^Hq62?;2e9#K7E>kzD*eNO~7a{^$4J3(%^<g?sc18 zd0#ZU>1TB*8ttU}%b%|LnI_O@-<TtakY!#n+DLT)9>;y$)XVnok9QoLoKUZO6U#f^ zRUTM9@HoZBwT|?Xuzf@6(M``rk6~5e-y5E!9x|$T&HWe=krtse8UtVIju&(O8;B^; z%qstYnN%#eckR-pOUc4c>AdGz#N2=BkLRk;d8`d}coF}$2E(>nFX|c?6tJBBy-4Pv zcKTOg;U!^?6*eDxBKXHpGdy;<i=)HvvF&dC(6W3)RRR8>Z6#Ovw@FUDzGy;9<BJ>D z4^}DAu0wwr=xjPylPwk0%rjHM(u@9>9Smkp74d0hYgy>vkJ(Dy^vECsMzSIt9LioZ z9*ILkLpoqKEcGPT_R!jMva|1m&V_`Wk7Aa@mzaeJ`W-nxWMeBTFW2aoIw`3%iW{kS zvo`hJs7{vf`Oc=EUUGWsXKre|Zxasl$KVGe*tPQ>v#}|}NZ|{BZJom`_h%qZwvf`9 z>k}0gu+yEcn+y!aSOiik6J>6C@?7O>$p<-$)X=ybkDkPfAp;x5X2a=k*q2O@UnOB- zoq1pE`X{ZcBwy9vrbbmIRvx$rOgZ^N6QO&W?3VjiqN;jMqnL9?>a>_9ZJlmH0%f?F zL$bep6Y$zJ0dBaks!FFPk(Xxm4-^4L1-F);QS|-078nG2K|7sa+Qd?BR#v&97D}Fx zD~uMMk%PdF@;DJqTKZ-_xhQEOc(8)km$=z=Vw?;78%=mjU4K8s&qwg?Bj9H}hNXhg zF`K?*LDU=n{Xs=B*nR;|{bJmwlLwTwWu(DcTD5YJ!jxRHYTUhiPDLRvpCj++Q;k2y zyuozpYP>Q#c}e<O@rB3oiq-H^;?to9a>d*_ov2-`XpJh0vE*xZ#%faF#yN;aw!C#z zxtufbOAl;;iHW%`zIUtmbg=&ChVx}4_k#xy3VaVY@5z19_Va7He&fbNC2LgbPUu37 z`{9fi^hY2W9&1i40)y9U$gO)wss8oJz16+RMlZy{7J7@zQPai6MfPxG$2;h%uE<KN z+kOiARDri?J18Aa@Uiwtv+Dhtg)M7Tlg1CmJPTN}8(F_b@?yhb*pWQ(s%>`U?i3yN z!w3J<%OB$_@n(`H*rpSE?tuF$WGb6RrM^U{>42DjwWimpU+C86y17(VNtvjT|5m$^ zzNF4;Bce%Zi?F#N0V_6EIWim2*8(Nke6kQ%Sze}yVzGIAS&EQJK(1i_prC%lQ*Czv z-`Iqc@IjIX?9^excU@ny)T41aGF9z&bYK-+P!wjz4Nw_<w`<%Y{0-_es+!(;W=1-* z(N^7bidj;Q%8{`|8`YId@~1(ITnMw-aky!dVhT;JUE6^6WK%(2?H~HEIdqR{ktESz zp022vr4}8bi?2URwL54o3@3UrPC2)D23V-rHKXF38VPb5b_ce_XLUM^M-8g!U=~&x zMqIrz@U8bBCB?J!MmHA4YEk24jWe&mDindydGCH_zE+54T%&3&+N`hgeZb(F^3+oK z$H8P<rfje~N_6EhH+QM5u=x36*mM!`tmgU+3nl|Bp6}zgZ}&^hk!IMj(qa$j25pHL zEJTjFXLYu@@xj{a;NO{#z*VJ{)i2XqS3EdwvG>4^^%;)7u_EqXlH{vMan(a-iEoxW z7JDhR=SyaF)ShsQ90y45K2N~=RS(uqGZnkJcb5_73~aUggf<P*vgc<FVT<9o$X`(m zWwz>91_%vfjs6ws-uG2zJWH=mw1lY+-$15r824Uo&953XTaF&>7Ui~`X>T};7O#To zSKN%;s+04YzQ(mWrC`^o8=Tv34t17EmN;ai9%F94MLU}_G%U;GDFIU;+u9Clnj||J zmOw+XPK)~$%Ive*s)X0OMfFBHOv(Nh31DoVmA+>BEXarZ<kYnL4LHAJo5%}jky_Yv zmAQ9q;&E5HQ4H%tx7e~#=)D?ER$P%hy>n)|%ZPs8=r{QrBO7~k=MD<9glz{+klbd1 znuXz~35HdMiVGL8Y(&ck?5|61r8XjANf=rQSlBI*!&q+BUsr_i3=pxfThwiho*P4R z?cx51Uh5NCIPAFa(E+9yalszJy^cnj*Vormw;ab*OS&z;Y~GuwxgZYd>gp0No@~}= zu1PfYOyWVFx>{E((v``T7K@$p4u08UZs9w=d1iWOerUI#ua&X4PSwMPC1AriQGc`> zH(zs?Y{rtlym0Uo;cJlL_prl*dX@F+Hv`dPy6#$C-(~_U^uXUNW3m~EWgcrziGI=C zg&|<LM)IMl`=f+p2ir7eLjC9o<Iv=iQPtz}MAyZAXmHr13~7D{-g8=CqpSM$r`S0E zwui0ERqR+h{EIVA-Zi}Dc*8o!DpE~zZH4!|MEFK=!udNx6>2?9F)pSD%<)AjaSAG0 zP97gVM>B8xc1Zav^rRu$2m8pHtH*@21n&NwZ@ImuvE8M^e^9?%adDpzfR9Xg%M!2E zIcB0$=UJZ}?wuy&Z^rTP0Y!9nw0N#MqvZCOM%<6ClIk8@+e#MFnOw$~PE1rlR#P*U z*>{}}y|(s_{G#1djYBo;f!xgGxBQ{CkwR@T@9kH?j*rw*HO9+KA1YB$P)yc182`FM zYcxD=4(C=PYu=(B1R<)Uvr{a>Sl%Ky|19+W!-wveOVxc+{w1_N^FJ?H$Ez1GW5T{l zaHzU;)K4-$U@x11KmVvQ{OfldTa1oTs{31{TV2rb+Zp1o8?gCH*o0AIt?{2mlA&Zl z>%?DcZ`jL<1+To>eUaO7lhe!i)5YVF04B}UAq7KU5!VI-*8?`;F<m#0VGRnCzqh76 zCHESW@17=?0b`7)dIcNknF@M5nq(wfU8DWzlv%z!VlgOQ_XOkqKGSP-Iyrri;UZ@z zT{m(l=?(iserG+Z{J_kT<XP;G0kbZPkJxXsMJE-|jQ}RyNUdRV^Zws%P_w<1u+9<t z9z8#WcmCU-1@AumWsy*I7E*}-HXIFXxM;JqiuY5*hYutaZn}a<ucjl={rYoHWWr#) z=F{iTtV;Cap7y^oo_J!W>noT0Qu5&^wQ#83WBUS)EI}Q_1_1F{ZEep;Tm)4lRu4iU z_$20!cmMH+GJjcOMaq<1u`g_-ws>BrWY}Dc)2^4W1bXg+t@6n?tE0BgyV>XHOP%z) zCT0i5&c>S?EQYUjP^Vah?kK3mv#E|v_x=+v^yWo~!%5LY*xa60$Cb3(<^5mF$oTr= zhH|aA5IT+e+Hnexev95^Ta|Z3IgEnf&uvikBI4;;UcgBgGx9aPUR`aNm;sKO=0J7e zeV3Fg{v5ZFj^u?2rviCy)N3|bGeyV~*=?PnmjvxR0QJ|>eK#*1B~2f6UTp=06EG|h zPP$*mQ}u57YUvV%M@QZ>u07l+j1eF|0?;uo-1;AF5LhqW(K6O5@DI7%2DktWMA%V; zxpWk>X=BR9{@SoCJa#*Xibq3P`J<5i1g&cZPhzp5?9s2azitBKyGypC^@|%3@uQ7k zE^ifh>=;#!);i_q-_pCd6D4+C*km}}pd?xIr$^<=mFPP#ZPl2yZ<vVY`3u-QSWwnz zyA2J0LAw0?7r&VPWT)h4cb|+5%3*kOBi@{YMak{ki*+%Czm4*Z7Hz1vTDPafCQL2Z z#26t$-54F+{xsK6`>$tPuTEz1i6u7|9E67BF7b`gL&O^X7Uob)NPnwvLQ8pUP8%Lh zyTxn;6&(D8&;A9Nd~H}=np%{?z__reXb6y}MI21fs`qwZs;IV$OX~?a-~;Yk&4+dX zXB3r`*zZSPQN4+Ycvf(iONkeG`dxxKW)o0EBe@5J{e0;)bvRyI#t`(*X49S;VAHF( zadVo2JvuwJg)pN;c#+jnaQix$zg-x2NzXVt@*X8MzcIO8ZX;U(6kSWB!4i5~DC?$C zotR<=ChzCn;tQ4jqj7-{d$bTsX?oVH!TVhzqcQ|C{mX(B0G8=19zxS{HpFQt?wE6` zN(syFrogy?^?VOD+qieW<!r>_EzEA!%+Qz7;nNdyq!{z(87RYU#nf;&xXnGmqvPW+ z-=qF56NlaUtZ+^;l6Q))3Iq)5Y>5{>INR(y3gG*UTfbx}%o46rDOV1-)9=rZ0AsDG zWDas5#SQS~BOo1UW-F|{yU08Mo)!T(neF!9)`rz@5ds#SSNbxf%>g?mi4N%j_%$PG zok62#I8?*T=BL)G%uE^h=>kjqr%#y=RT6CGe|~6bI6XZL<oiL2ED2nO-%x4dSQ_|I zFe+7aq1estz^`AOd!!RFFW@)H+CqhT06hpTneFKI8EqM`551*FBT9K2E`A)qO_*E6 zm`(jC7duIeE*web+HYY=no#U$G{c#$0#f>}8TnZ;mt8IYi@7O_z>$7TBJ~-kqike) z76r;|sCXHZXCxh2@f*JrS!@?@+X4g_L6OY@p()9f45@7OXl3@KfJz<{LH!%&0^YMu z$h!(*zg2wA5~h&22$d%E=pJfJ?a>wI<yUvU?W6WKi~c+Lf=>=XeH$v_v#CnYs9z-c z=YX?Ht*6*GjT|<q*gtTNc#mVWxq<My=3tM?vN8R5zu?Q$d(JHSebisas3Bs>x6%|v zz5qF(FNt4KF6_!65HzX+&R{F|Ul*Dq1L#GZGf9&gfM72BXXQvYl&E6uw5v+mLV2wd zx-8KQ#=bfbH1>}j&)mn4mwhCdtt<LN>C6gzH|rG#2L~sceQP~8rwhq1UVRKiGysyL zhlYm*o&U<jCnR8E;HTMA_*K>wHos{{uLWM(D||7|rS)DO&l$G1Q+~JVH3#&?1@Nnh zEZ>*<zIJtkg;vDLdDSO`+}g7s=|bNY-^gTbH4Slv?<8@QZgrGv&YStO2a$DHKtc`I z&$`}q$p5?L4qZ^MEjCqUysN&1I9(&i){o0@65elWs;+f%LD87tkEvj)<9bB*%4X>< z3jm<##+1kL%bcF5YG@y=CO_l7pNyTOOEc?#So~rRZ+O%X@_9LZS}}uOU3|4iEuL`c z;M8xA@*;zjOFYi&K-8{ZxL2YLB9<p~sjcYh1EAWBjg=b99o!0IsGTa!$$7ve9UxJ{ zQV9%xd#+s&wr}IHF$w&kZcE{e)bZjCCUMW+dgYY&(a~4`Fc@oTX|2#j{QUV`HAP63 z&eUDAl<J%$bBvJFY{^OnyaknXU#H(frc2BE2RY>Kdm*Z}C+eon6+jj8Al!Xl3VaZ0 z_?+xrbamqoHfN?X?}!7J>?bW1bd_h3x0eh;OAjP84mLKn#jk(AfB&wR7GAF@U3>)y zm~zT8#eloJ-8u%!V)bNsC{V*l(q_R8C9={Y@P{%(kKJxJ*5?%fa%0rpNIjC`wG!$A z2ECf+J@g~6D1alblT^!K+K@pu31;;)ekXU#h!PN@R547RK%9(@c8s5+ZOwy|1D#Z^ zC-1`D5O8I&E~*~hfzFN&b`FjrRJtjUVSoL4(ed-AfT)b{bJIDXuT?qq(!cvx%Pc4; zP{379wsSO@A%K{=1@x@}#(m0cRb3sOf~u-26kofVW9`)8aIa%+3N3gtqw_$QECX62 z(D*!1Y(Rq?n51kIfda)*M@#Elcek?jO(69avjU|RG)4<}7iDE-9Zk*F4qG6C_R)r1 zy9M?y?s)5%m~h2(Wdm^&NMc~uM`zOIDJm6!Hu>YlJ|%dlA1}_o23xm3+y!4jSg(bE z+r4@a^shwxoEEe-FqRU?<d7$ESO$GnE9QR>4rdtwy8>fx(}Sb`*C*8(Tm=`G0c@Nk zySci42WqkV>5&VQgtrDzQ&IBbT%?->zMgih%~Q`P<Fn{I|HZf2%zvkY4!=LF9-o$0 z`tjq(Kzwu<XxWBF;^MuJ?>|yM7WX(B4m^n)DMhaap4?1-c5``y>M{8%HZTNR0f&u% z`hNla?71~t3Pehety$AJcl^F>^U-_+e!a3kwb=7EcwQUD=~zB`@eSn742cQDT(1Bk zwRJ2{<Cdy*EQ;~Ogb3S|*43SJ(Ia~j*|Rj%o5U~Zy7+=g%>4z>8}xzl{gj^{7v<z9 z$CIc69WNVAaT;?}5es@xI6L8Wy>$-Krk%JbtIQy+Z7KiAgUu;Mxu0=wCVJBZYhp5^ z)pee0A^N?R$zeb@I)ht%ZXDG?cKhdsCnu2YSp2r%;rG|FNnvClQ+Be>B^&5<`M@>V ztPW%;tE(r1N!j8*=O#o_)RKi9k{#=pZs9PaDj*)kjZYo5n1W8NVy&3Lb38obSlaM6 z&uIRxq3BhHn+e)MNH@5ZiXBSm?<kRb*pC}?aEmOPFb3We^V%$_cU!>#Z6FU!=PJ8V zj@+Cao4w^ev4GRM2Wvk++`u0##0WZ0i%_#jnOwZeIPl@dqtp~J&M+F5GH6-70+1xN zGNk<7R|oC^u~3w*SpQenHE{kgI5n+<BrGOy8!tD)v8A<k-Cx+NyW2a8bc@}$|H_^% zK9Y9P3k}`hcb^G3*+9LK#EocA0+?2L8~0Vxx8~{7r>PxUpT^zShH_hoE6d9ln&2w{ z!B$lXC}{-*w16-<UyP-^#buBQd=UH3y*)SqOdF#*=hxYo_76n2>SH8bYDVk&x_zl( zWv3S!es;XKa?;(O;CQA0?d_w%uA)39t2ez+7#MZRDQj+y`q<dY7L8b5UE%uSPatKL zQ8NggA5l#c(*+um?atxv^*@#IadBGMv#Epx9#f1j%JXEw9@;ht=!@XnU!MZUQAD@W zyBlwejhnnH-dK=#wbsh}-dL};jU0m^Yjb!^8*DbG>y_2i^uWY@^XAQ$&!4m7IrT3z zi#RU+iX}<dmoHx?2{ml1PaPacXkrf~?tjPvSkuN#qwuSwumU&cxwyFNsu@x<UcNwd z6Lgt>F1h=QwZ$^s|G*IJJ}U_@z&r)Wqnx^xkPgGJlYq$HO8<B?lXy^=#fVeK$D1wV zgG5|!UmrE4)In>HSts#K-1or#;iE?<7#;t>)yJeR1zCen{r$(M5fKs9uUdmHjEASx z)zt+eai_<7<j=Y{YSCq&V@VfBAPEg%RtVY-Jt)N2i<uWYkF&GMUTO~KeA*CES)@9F zFjYwb34mL?X6syzg1|P4arHEM%l(e<Hp%lBE#P5i(vRkT5bP&w7rJ7gV6>xP8KZ|@ z{HlNm;(}RDWq$wu-TnLbpd5{44sXlRGay=zgOMO*8BFA-YMu1e)S|Cnzb;@m^4J<@ zSYh4I+<d&8GKqvE$I48na%fBNLFL0?)C>ZE)_}wT79cifz3k8ugNkQ%9puV&5z*0} zw**yy;5{2~;($H_BX9QS&!1{osXZy{0V1UTVXgh2>jNr7>ACs&oP2zIcaM;#yFFz6 zysWIOf2)0f03QGKYr+2h{)N%-l!*xgCh=Q-ls`!3l9926C7UgO9Snqef9sndMd7jd z>spsl-|*0ulkr>kCWV*Bp=>DA><Tm?`1>Xyd<fwq6Fazrk~da$bS%?3Yxw3-)p^q8 zNOwA=r1bhvYqkBKr<T^%*kov#i=KxK_puid<<*i6rohtjvK^47Ik>q;En+0|08H1C z3%^QzCrsFJ`mqu{NN!YON(>u4OPPVLX=VCL|0GH1M~nZ-NU=UI`b@W2Z!KQmY!D=T zunZhK-JA#;Fkj;q8IreuvBo@RXIHxX^k<vsKkc*W4<xsLkYh%R6M;?TU1L>v5eF1u z5?jD0!2iCx=;sl)51a<HJ&YQ*7^~>MKEWrsKOom4M(n!R)e<BbpnJ$QwQgyD;O4XY z`;iCGk8fe$9Y}kNs~aA}jWYynwPdniWlUD9Gi=T_8z&_twZK+{{a2iW0Q@*=t1I%o z9L+3Q^ySMxX!iM6JrCH}#wKf!fY+J&?R0#Mq49sk!^JfMq-oxme9JPc3`t+l(%HX1 zfBp>AMzgJfR)dInuA7AWK*}SK*Nh-LUbY2xZ@IA)wKU^GfCF4z9n2=PRE%aE1X;Ko z%%KJFaOW^`w#A2sh3y#^(wN@-S~@IRktwF`LuZuoG>38c{CeP1T=ZqH)5))A!|1S) zjk?gL0Jx7;Fie^-7%Xk;qIKg<`}fg(aPRJ+Toouc79A#v1zw~GOe1p!n_5keYF|Qo z9%&DF&huQ*#N*m`yS{1%QmGEsBGoYjhs-mtA}s$p<FmIkDdicJZX)l`rZ>ia!M_IY zIgJ=V$4Yk6>MN%16E{w1GAIvfO)B1m=BcI8JDcpYTwfwiPV`TSzU?+IcM#MuCeDa^ zU~+&b^=USfJlh{`xp&pl($c8KubxEUsF}ocDy{m81Ygbr7#NoW<QjZ8s;11eu}D2b z3V*uS4<O-EiQ^{)9OcwiMiE-t2f_7#_xQE51ErI()TmmS6wXMo9Y8~h5Hs=fQ*uw% zX)*9uHHX%`pTB%r6d&btnw6kt6dBO3wH;<d!_?HJj&nfNx7)yu89PxMpaM>Z^VRju z%+dq)7_c%=fp<|&dMY0yO{m*CuCDUgTV|J*MvoWtrU<Kplvj(koVe%ucG~@y>gtDr z&qxkWTV3*Ic`29|xV7P~T1W8rW32<6XA3ATS$;YQFLt=qw{PFt^dxX61Fj~*%Gy3o zE&`f`UR!9GU|9ybh;{r(AU^NcuU`Ye)cp>_sTuM>TBI*s(pV*t2RC!-Fw-FTDrjeC zq3fc3cIm&lTHxs_4T_|`3JVncNwwHK?P>7ZGUI%#qUGXJLHg+AUsr+7u0;nlZaHnB z-I(a;@`HlTAq8_lwv~g2N3BRo{00jP%fA1-4*I0F1;6}0a`W3_R$`C#R|HM^X;}^O z)Xjgt*OY@(tkA5zOyjwZ^$JI+6_{+@{r%&BiEfqbCW(32$uuspFa{fbfBWHkWu-0v zk0AJ640%l4nF5`o4}wqW0Vh8{|0`)+wXdgfQc6lODLRHpi1g66Ava1?{I_E8m=sd( zt6@1AYS-*p)5D9D_`3zDQ67LGcHo8_?CgW(uiO24CYi3X1RQ1QFlilbq0O;Q1B}PV z$1SKV(s4l9ZrPxtqdTc#!E6b={Y8u3J@{0Rmpb}guAIm>A^p#IehU)nkBibZGb<yd zZUM5YwC>k?`7#nw2J$?l5hrC^fm91!?oD!SguZzLx)KD+f397dgR=JLfut5tzx<Q= zt)l|~t1eba%%i>t)uMHLPa@e`9@$_2lczLC6f<$GX97DhXx{DSZ1KndArpWW+qRHP zE#FDbz-%V?B2AGKx<v~oe2ysm`@3aNQ2IfQ^lgG<4Jk_ovYG|4tcrMU!@Z-2wuhTD zE$QVzFHi}Pe8V7Qzm2o+PvX!2-P}sJh+$QXKBC71Yy;9&6auH5dL<g5CW1{hdC}Lz z(`FV3nLldBNcT)XwCqVZ9;>cBt3{sm=_4>sl_2U+KJEeW*&9WmHuv-M3zp8wk{ZeC zPO-p@6oO$!;LKjUe0k;Q&D^PLxm6$i1{#SzJbcW>Wxp+p5KQ%&_37^IEx8#+f=iK+ zkw(bNI&>#aD{xx7O)~b>jp_Q~L$CBLVL}Vv#U>y?oM-%jy^ir`ENaUA=~>xw<)$Al zNtvpIdGq`HXO5%p<nz*HDWiHdH+}0O_avbV{8o{`q{v~kDPlkK0BQWY2du}q*sBj2 zUdFd!rn2oMj=h2Lzh2bzuoT2tbxGV8FxjdAjx&Ncf`_FzZ3e**h#z;ANI`mw>thkJ zX(~+=;96afwEBTA$PG^ckd5tcT`kCf8Euh0B3cy9@ZdAnYW_I9D42b<;_I`5N{iYQ zxr95U)}6h*&>1xhOn_<N_y~_hVE6i^^^pN*AXzwV^m>AsEjB&9%&^jmB4iFu*vl|N z1~daQhFG^31&rShzQQaCTTOLCx$q3#RlVBQ3JX0whHpoF{CF;)cCxHe&Jv7U-pizK zAV3~FqL{5$7_vapG)>&NnUO|v{}UKP0Go@9BpV40o*VS;C4WKwdu=MAkGPW|;?g#5 zVHLg)POV-Qu|1i33%rm_d4=>>LUSTPQrmN@2gHKlfX}=<Jf61-b8?=~G<qGTv3aFm zo~nlGmzv3~V9iZT)}iMC{+NeKFti=ddCoeqlavrp43gGS-NM*(b}$7BX>d$|bX*3s zv|p&GsHXPsGv#+N`@RH83^LFG9G?NB0wVfMy>c3<zF~235yU;5f4ca`o1A)&rKQd3 z%)GNIi#kNm{iu`Dto?ocxSWt#)_+F-V3J}m)25f2OXuD^%s2K-b@N|;LR)0b1*&-f z@3{PUYEAfO9$%`1$?MmzOKIJA7nRUNhT+ZXkWRu(+7{i)+1T4~smAb;<A*-8O+GE2 ztlZpvhhp%fxo|S`Hy5tl{tNZJasB!iz~7xucUi9U+YaRfHgr~16Rh1p?7~bbSXo&G z!?@@Gb~Jt@BvhkhT^-b%m}Z?s-*)T;x`G4)sBb^HdzVsQN5=+WTL2U_LG6aeN}3la z_UYC)H!>;$DR3+ZWZl1hQHnI~4JxwO&NO(CC2iV^dT(a}g^g7gxqOj^*_~tnm)lm- zeH|-_B5DU3<ir#>jkEu0xM+z{b+_Tnx6S55Gk~#8SrsA+g#CmQm<CSeO8vzKd@9=; zW-Khj2g6L>uE1Z}kch((Y>K{{C^vhZ#q-h0h)IFd4q=`A4Z^Hh0E9B2Q&XH@0-av~ zK(!u?lCe>ZeG=~#UW4)<bU_Ter$L5w&RJXjRbXxdor2_RNp&&<PiR530C8f>7|ncy z96v=4{P{P!m<Z}Yk;t@e6{;__E2i>Yk1(gkEW>|$wnmR@rSb|;GbGMev|Y7H2sQ+$ z005w%09nPEN&MMD)$8^PB;uv4qOuoi+?d_&DC}Cy8>!>Lkerc$c-<bxE-7gWL=iHF z&yrlNKA+J$?Ja`t-4!6Nnx|C0YCRWqhrhEn3g5XpIX49tkr#2lP}PZ^NvEj;^q6ev z=FOX=(g{~r*DuM*MU9&c#d^2RKobB_2b_T%7TPW^EBh{hc!I`)Dy9+QX+QDknTv%W zK1nrMKne8oz(p3nza@76x@W3u$=&JQB%R8}X=80TKlngse`Bgv3GGON8o+g9zD0m? zAi*9IWJh#WSah9(abn*Hs{vkd7%z&vITbYmc0P0TohW~;YWEMlxL+oi%Ghy)Q!Gv6 zXUSU=>;{OKv(w--Zpudh6=*9deYjqXIB>9|^dyxqZDm@)>vxGyEs@qB3!vfT?@P<V zvW2av;C;J04hocv=mrWe@!zW&J83jV4mPZ}2n*Wp#+>VxhVLQcNdx1tnbneArmwTY z+dc3^)b_rtZFjrbyQ<}j}T$H1g9OAjubNpjidLduL5%1bsWM%pU1zNNX<v(nT{ zXbUMYL5!@2Qkyp$y|zd-V(xRHbQeMv0fYej?IPEd$$^J}XUb<Vp`MI%90$08aV;JV z6N{muzPa8!J%JTEt=>obgA$-!STotZajWpTerci!sQ99xY>$nNO%`>_1I`hk<3Ed3 zgGR<+aD*HtM{>-(jkANcOKWF~#J8HXQ-mCLqYfP|fy<D1KKa$MgAQBjogd^hBNz%v zQufII7*~ULIss5_6nNQekhVVNzB38VH^REdGJVVN+x@K|xv4Q$VwfF=aY;Q8-q`Y6 z5hv@Jh<QDfqf`y!IFptkS>45L5*w=@t$e&bU9S!NS#?cXQqr9#{s#W32t|vkv7G6w zw#c*8Gv4lcz{va&A7;w&NGlLZ9GtgYp`@CeHx?HDbRR^Bo2q<Z=2==<U3i(Yc>2`i z3^#sp|6p97MU8}#x5WUe6aVXEn=w>96{GZ-jU6QH#}XR=r(^RsbSgdcdIBV;4eyP_ z$tu4hspFI8$)nY%$(>2wer2a}hhPgau_<77P}9^!v=GG&jQw*9!KxX~D^GvkH!y_S z6(6bt7EtQx2g*Ch<X)U2B_<rcAx#@S+4=Z1+1c62Hs1Mn{)V5dt*u27-q;$Kzj_z< z`7^Xn>~;9ytBlcCaABhJrr#!EsCXrfW^{HFjg)>x`DrFhKv9J-qoShXpY{xO*mN4E zbQC@Z#-4;wZEbD44^zyZGLlkyByE9I_+qUaJbEX@!oq^Qb3+Z_>0#r!E`Da%>OKF1 zKi2=M4JUS7M32LbDY{)g6cF8;VYtiQY6m({YLe7|#;1vUIqp)pdi(*DmUo@Y@cVP% z%g7cAPFIBbdVBZdL6ZEU#34v#80j~Q^QKomdR*%iCAqXY9U$^TP3`J2^<V%Y%d9e# zijI_8YQgtnI8ps<M7~y)1TM`oi(Y37F5m<Yr`HS9Pus)yaP00TTn6U;BBG=^!Ik!O z_8&EFD{9RIJeCAY{Se`9%QtmdWH910^gO`->1>ax>3S!7CYR?@KqJP1d9AOn2S$W| zs2I!xozn1^9R?9s4#hL5L2Y}u&a0$yR)(b18@om_FVJITh^{~~a=-R})_DaE(8Yl6 zkTtg)2!Vpdn{;&gSZ^^TEa8&x6bZgNDSW^m!2=QjVIv9Y^ir{=l9IFk#&b}SDBRfm zz4lKk_JLlBLDuxN3A&~;hQ%C8w4O3{YJR9|E;0`Ci`Lb=SGFdr|1G#Ar;*6ak_*Rx zYAO&63_pi6R@IQiKp>&fi@N5toNYJ>AHNy@BwZ1C;N*Gx^z?D^R$1fb5U4M)V=CBi zZUVkq!Td@10jCN4%^jJe1|s1Eh*jS}fyo(0A9;Dzqh+h*#C^H<&KV8?AN4|>m|DJl z`xw+m0)VFTIV`H?=81KN0|2TvLw|n%m!SF0;x<5gK(z2jUI;#5zkmN3$jev5)}&9j z<!~EQ`oIxfo^o2Z@zG4XG3xtMxR{8Ro54pN%mh(Px$z|5EPq)WkbQHsK0MkUuA1H^ zu`&-4%LI9}wKx?XO`xXov>d(J0384lu$rI_s%0n2iKH|%`yP$~Xj0{W;@J!oFp|{o z$X1dn;iCnhu?E21)qqHq8rQ0sIW3%cu3g*wv3l)-7_-;gNL0p7!F)r$SaA?xe%kVI zl(059f5Ut=+j>h+SAGv(cv<G;6Cf}k5UBv=GHx6T6x^0V;GS%O0M|mbP~$jLWS#EQ zS#KAvKzkw3lkKUP*^W{*d|ALC#<~2@y~}$CX`>OVkW?m3P0falnkhf&KrLO}+@T>Y zkUU3s6y$}z{#V?V1=AOow&kY?d@Z$@;x?$5HNlS4iF5q>Z59B;0`99CK(7P^hFBmo zlL{!IeOHDw|0BcaOrFh=bat};DDc;1|1Idg{~y_&1ZG_-7{T|E3-m$~k|jagp>(Od zO89M}l&fAAnfKXb%rc=gxv|B_hCxPg_<BafvSW5VHhW{c)-JvB49_QU4xFs;UzhuD zW&!@6ZTSD~r1A2(H8bmbpgjYFgRK8%BI>RBlI3H{Wt+?h(-4S2LeG-xtt@h9pism{ zg5zE>hW#gtasIX3lLzM@fy;9SlRLB_)U6Y25J+;kg>9D{?WW98-epij-pW_!f1lC| zau6QlR0ILzcEI;lX1e7G^!&5=_A8LpU#l|bWG6Imp(gYfA%T}fn3JQju7z!b;3%Bf zqq{;4f!q*@fumCPjy^<(GS6M@C6Z62I`>>;fege}jqp{7PRV*_D%O$j62~S#F`KQ_ znu2ozqksCOy3Jzd;U*5hb}60qDZ@pba8JU*%B3ScxXsZQYsx&xAgcw*ZhrQ^cE-&u zqBm?z&(B@WY@vBoPUBT>8O#kD!%h#gzfzM*?<}EkbdNH;FwD<*pXe->Sh^L=P}0Je zdIHjFjMa-fJQFpkUF{9geQMOAW7!_pLZ%8e&|+yULwKnlLMxu9qt(n1$cCzRjE@JC zcG}bxk5mQkxi|Hmk4M6Lj=4vcz8-XBm^wMN!$to`)0y{DyMDdGiel5cREP_lZFI7A zX*<ME_(W0ZCW2*+M(g<R<GBlvOxDXDO>WGr!Q6CQwBj+vA#>YZ1MfW_=up;Bocy5R z+_Mf}&a=V5Ku(Op+S{R^Av&rxy4WNBI8hk4lZm4ZnfmaG<-T>&o*ct^Fk?w?M&i2@ z2&8?)Yn{q-{fchh-L4f4OOcb?^n+K=pKOct1o=~W1jwXWwqnvwC_Ts_nUc=T$RMVk zpwMA_bfRa{Ufr7cEqj*Mn$XH{=D8;;ry3NTZUF<BhArxy((!sVl{s=6hz)hAN6F<H z)0K*0AA4#~bJ^(etZwH6+K~3tz4nz;$fyUh46<(0&u$P%UCjl0PSzsYp*8w5%A$~1 zAvED4GU4CIH4-pbL)m6+Xv%V7B|M++FxY?M<{LPnXH54ZSc#!IzQbdXR@poD<;i-} zmd-d~;QMV>zl7041sdJ0Q`%#AU~uU8tDciY(VjGqEM~AiV<U9$>n+UJ6?5yvDND81 zXru=>LM(ct29FtZUA-n1(d6N`;5K#)uRE1CARJOrMffd&e4j%{msbKtR8Kr+gSwB* zhUxs=lO-aVbAb1=(D}Bu`#uu6fDY}%lR*M&_#`CT4M)Dg*bba;WhLFFzZQnU-@46p zKHTUQm{M8SLfTEr{~GIyf(`nxyNp)!*X`04B1p5+8(ejf5%ZVvLhC0=;F6YEDZ?x9 zFkfsjXt#{b`MJuwI)SCw`=TjsrY9|xB)8<jN|`}{3pIt~s6)$pf<{5A@UB3R^Vg!{ z@bRn7`xij+QGiLdj>+YMIV>1_nH+tWku4~Srp(D8Bq+oJTtVOpu(<n2z)cCzfKM)0 z!<`9K;O1dqB4oX4ZuX#lN2y0jQ8oZ`f2YyheEt>K$Rjna^ZZOF7dRFY<UDbCl&a)z zR&ALj8RSW8IynVwqfZWouW$bM1wK!@W&WtYO-ow!BCr4E_I8F;9|1`mu|+*4m3Msm z_U1ob=%Pms8MxQHjgf7xI-v63vCOJe2G#OTO^$U%NXLdvMr+*&hV=9~E;~)h8@?hD z124gh|B!cp3A@}0mfpPeJ)pDMj1gL+QQy3BC+Oi?1TPgX{E?R(*k{`x0DFJ!{awZj z^z>F|iEd@XBX?)CgqS}`Nv(5HKr)vcrhJ|qa-YgH9;AEfg;qhgY-eh>$-&+>LyF*Q zA>t70$Brsa8?lZjDegqhAxUUX<M<1wO&1;th)j=&OLuk$(W&_3N6u7T90y0)z&x>5 z_mP@Us_v72WJP+<Q&qQiw{=YU=9+dvH{q@Zu)i5Y3>hc9q?5h(5u$kf^TNuy))pzv zB1K|%wLm$@mOpSpI-H#h2<H}ui9vHOjw>UEP$0KF0Q%R6xOvUmCA$=UNXf4(bDy#n zPT*Iqimyc{1RU_&E+}9L^Tj#PaPh>rfO<2SOL%3~@nuiMSi7`oCIu4qY-=%0syY4; z#e(bd+D+|<(u0coY^}z?y%l9^O-`eko94#5ub!1dAgcQZ3Pjq}yoWuA5f-PIz4%@e zzfiri2dWMHD%gaW(Q40*RX#kn(h%>3jzc-L>YRTq@R2F#Ar?&|T}41{E3e`2R(75) zbFYPNpoXj_&dT#%PGye#ImBMn_ugM&Shn#Pc+L^O8KA_w;n=%Y>E(_NJlT)Vt{U_F zc!<dzKj2tRSa|BuHIzipz|92n`_3jE@T>kjB=ZBIS`xjLZmjuHWAeS*sBxUY3p(89 zgN}yW$F*N*5fQw#35>ozO|YKQ$H;2(S_<uJA%m|7_YC5?yGu@p_(TulJI)*i#gUPz zfLdAniJrCX4W{42Srwn%ai1RKS`lQ_TMi2xSML@6y&)+9ZR%9Njo2AKGx|fYZsOS6 z-#z<W+MwhG#Yq+0Z>Z<noO(B|e@ahx%P<@3X>e*o#BbEXUO3I<|0WVLH(MN=E?h}3 zF^4b4eklz{1Q`5bfS0BaeGvzQ!@lIbNd7A<LpStk1_H^doz7cBC`-o#Y?t!m83s*< zVJgY#IRy*(x_YL#(RZ%6^iLe@nrMu6p=9*5G1U0UbzoYd$+x(5e4q`B*VpDF$a^kR z<%Uw_GL6dJy=B5PBf;T(M+pz#QtJ1c=W+;&*c#7fSI5TjEeI~1&|uR(4}OgPbU?6t z=Q;h|%vi{25dX)w`Y*4qf3dfjd4VN6sP9jywdo<MjIt21mN%PPG^EGQU`{=^9DLpe zdD`#UEPqCh;~LD6=u>UW3+n<^&DKx%r}S%Wh}|zGo4a|Xtj~1%iCuT8@i8m7#Yi2Z z?t@%RwD19Th9da1`@&j2!vS<A4F$YL&3v4)qEfunZx86tY8U+Md&;E%JzZ^_Zu({4 z+||iJTa0N!elVe!V&>M%=d_O2ldfFl4hv$1O)o!2e!0aR*BL`o(%)a(w!JdSFW-xN zi9h)I!}7seY}Amsv}=Np*7LYBJdSe`zvBzroqgNv-TsecEGLsxlfHQR*X)%1nG(_B zt19w>3lF2=)#_d2k_DuFDe%vwHvP6se%0!Urm&=M4{aA;p3N%|HH=~|BguZue2%}X z<gYb4L74(uX}~;@cp*JguI7~^nh1d$MMOk7-zwbRIM)$#yR<?x6egMZ*$W}{c(nwY z*Hvf_Rb6?{JyG+DIp_&yAH%Um6OltSx|=5Yu%lBMc@!$(Y5&*N+}|>Ek^CaCSDz08 z?G=#^&TK396EQ9ws<DT)q7BD`Oj^&Y;uK~xl`IbJw#eAQLM@9eZ-stDfLTA$<wHVm z$seDW&*B=)Dt{LF&LeRVEVG$pmz25*`W|#1n>~0O`kDD?qSzBtUr=C?g+T>3W6g%L zdMl!?wzTHV)~lTyg5`#p_wa{NUbmDon1`a(W^QIQ8l!H+s5{|ooYAh$hpE~3M`~U% z20eMUtEbdY?7$PpXmTFz<sxE~FJ02RjdC_&OibYfyr=KXw=&0Y;WV*a;;cev^k?)& z4zvYP0d*YP-dPX~==GK?dDyV<#&#WkYGw-OH`BK29XKk6monWP6vR&NQuR%HS9bP) z&0<gN9Z)ehv_un;qV)W)n>we<Uz+kieLy`@w>O5_RHC^kl&8-%#=lZJws;L(_|#d| z&@CzbH0CZl`kv1(gEYbxd&3FKy|QI;h(Naw>y5KbrU5u%>eiX*F@BWBY}}#eW3GP9 zYE9_H9Lue>8q2u!p0ULw<9#nB72<{@H+4Pt*KX2+yPq$D66SF*sA}*sShu-^%Fy$S zrm4XKIeTg63&*2;OSWy?7v;(#L|t`mI_JzGXCb;?k9S)=;Qq#}sW!T?cE62^0DaL@ znVV1GEniP-%$-nsXBjoW^XrCf6pbT)Jo8QOZ}A%Z+BA?%>J3qiOpx%A^s?qZJD%gB zmJ)6?oaSmD4t|+267*kCWA&QCi$T7jS4hLVr*h>*a$EBqL)#e9kcIgiQ8&AU+P=Oo zo43tx_;npXttb<6R)wy%#{DBpc_FaUcDw#k!|sq2YF?ocym2!J4N48NGG1t_Ry2sa zOqEmmN6WqBi<BOQ@y(0T*=8*wLF)_gLDbds%WDQ%BgmA>3ji;Of(R%MuPgj5T{&H; z7|BdTe83ErT2Y#+WGU92WhvhF_^AHrds!S$-2-=Ud)Z(N>HbVgU}>;`dW_?s(NTuQ zh$zpHp)LaD5=+`LdU!q?Pztb|)6-H1MspUhBTp|>P+ZB8^E$Wza~Q!pRNxNN)eI(8 zRZXU~l3%Yn^}2y`avQ>?UM_{Bz0amn-MNV~ Sz)V(_YCerz~4d(W1Ykz3uHGrrk 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℘Vj9~6YbXtUye@DLC<Z6c}@+p@~B9UNL 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 literal 0 HcmV?d00001 diff --git a/docs/evidence/cpd-sizing-investigation/measurements.txt b/docs/evidence/cpd-sizing-investigation/measurements.txt new file mode 100644 index 0000000000..e78613a02f --- /dev/null +++ b/docs/evidence/cpd-sizing-investigation/measurements.txt @@ -0,0 +1,61 @@ +CPD sizing evidence measurements +Captured 2026-08-23 + +Current v11, 1440 x 900, three units +card: 512 px +strip client: 1440 px +strip scroll: 1728 px +horizontal overflow: yes (expected because three fixed cards require horizontal scrolling) + +Legacy v10 feature, 1440 x 900, three units +card: 340 px +strip client: 1440 px +strip scroll: 1440 px +horizontal overflow: no + +Current v11, 640 x 800, one unit +card: 512 px +strip client: 640 px +strip scroll: 640 px +horizontal overflow: no + +Legacy v10 feature, 640 x 800, one unit +card: 340 px +strip client: 640 px +strip scroll: 640 px +horizontal overflow: no + +V11 before sizing fix, 640 x 800, one unit +card: 544 px +strip client: 640 px +strip scroll: 672 px +horizontal overflow: yes + +Current v11, 390 x 844, one unit +card: 512 px +strip client: 390 px +strip scroll: 640 px +horizontal overflow: yes + +Current v11, 480 x 800, one unit +card: 512 px +strip client: 480 px +strip scroll: 640 px +horizontal overflow: yes + +Legacy v10 feature, 480 x 800, one unit +card: 340 px +strip client: 480 px +strip scroll: 480 px +horizontal overflow: no + +Derived one-card containment thresholds +legacy: 40 + 340 + 40 = 420 px +v11 pre-fix: 64 + 544 + 64 = 672 px +current: 64 + 512 + 64 = 640 px +current versus v11 pre-fix improvement: 32 px +current versus legacy increase: 220 px (52.4 percent larger footprint) + +Derived three-card footprint +legacy: 40 + (3 x 340) + (2 x 20) + 40 = 1140 px +current: 64 + (3 x 512) + (2 x 32) + 64 = 1728 px diff --git a/docs/evidence/cpd-sizing-investigation/source-comparison.txt b/docs/evidence/cpd-sizing-investigation/source-comparison.txt new file mode 100644 index 0000000000..9fb3ccbb0a --- /dev/null +++ b/docs/evidence/cpd-sizing-investigation/source-comparison.txt @@ -0,0 +1,67 @@ +CPD sizing source comparison + +Plain 10.0.x +commit: c57c1c3206073f7b45fba69eefe9875985a4bee9 +result: src/app/dashboard/f-cross-dashboard.component.html does not exist + +Legacy Feature/Cross-Unit based on 10.0.x +commit: 187902747adb3a851bd3294b97b2a9d4a6e8ca95 +package version: 10.0.1-29 +component classes: + dashboard strip: panel-full-screen flex flex-row gap-8 px-16 overflow-x-auto + unit card: flex flex-col h-full w-[34rem] shadow + search: h-full w-64 p-2 px-4 text-md rounded-md +rendering context: + Bootstrap 3.4 sets html font-size to 10px +rendered sizes: + px-16 = 40 px each side + gap-8 = 20 px + w-[34rem] = 340 px + w-64 = 160 px + +Bootstrap removal +commit: a8ba06c01cd47937249d5780face427143b7dac4 +message: refactor: remove bootstrap and grunt packages +recorded migration rule: Tailwind spacing, sizing, and font classes render 60 percent larger after + Bootstrap removal, so existing utilities were reduced to 0.625 of their old scale + +CPD skeleton reintroduction +commit: 2c6d2786e9484c57436099d25281aa45fa89453c +finding: copied the legacy CPD utility classes after Bootstrap had been removed, reintroducing the + unscaled w-[34rem], w-64, px-16, gap-8, gap-4, and p-4 values + +Current feature/cross-unit +commit: 53f1c5532eefc75cadf7834748a5a85c2bc6b3e8 +package version: 11.0.0-45 +component classes: + dashboard strip: flex min-h-0 flex-1 flex-row gap-8 overflow-x-auto px-16 pb-4 + unit card: flex h-full w-128 shrink-0 flex-col shadow + search: text-md h-full w-56 rounded-md p-2 px-4 + unit scope: w-full max-w-64 +rendering context: + browser default html font-size is 16 px +rendered sizes: + px-16 = 64 px each side + gap-8 = 32 px + w-128 = 512 px + w-56 = 224 px + +Responsive sizing fix +commit: 854f9ce9ba5f100b0425996c3f5d7e248faa6b32 +changes: + unit scope: w-64 -> w-full max-w-64 + unit card: w-136 -> w-128 + search: w-64 -> w-56 +rendered effect at 16 px root: + card: 544 px -> 512 px + search: 256 px -> 224 px + +Comparison to legacy rendered values + card: 340 px -> 512 px (+172 px, +50.6 percent) + search: 160 px -> 224 px (+64 px, +40 percent) + side padding: 40 px -> 64 px (+60 percent) + inter-card gap: 20 px -> 32 px (+60 percent) + +Sizing fix conflict resolution +commit: 09b3d248f48b92b7b4a5cb58434eb9c3d0944017 +result: retained w-full max-w-64, w-128, and w-56 while integrating date controls diff --git a/docs/evidence/cpd-sizing-investigation/synthetic-cpd-comparison.html b/docs/evidence/cpd-sizing-investigation/synthetic-cpd-comparison.html new file mode 100644 index 0000000000..482a360bd1 --- /dev/null +++ b/docs/evidence/cpd-sizing-investigation/synthetic-cpd-comparison.html @@ -0,0 +1,500 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <title>CPD sizing investigation - synthetic comparison + + + +
        +

        Cross-project dashboard sizing evidence

        +

        Repository sample data only

        +
        + +
        +
        +
        + + +
        +
        + + +
        +
        + + +
        + +
        + +
        +
        +
        +
        +

        COS10001

        +

        Active

        +
        + + + +
        +
        +
        +
        +
        +

        Getting started reflection

        +

        1.1P - Pass Task

        +
        + +
        +
        +
        +
        +

        Professional practice plan

        +

        2.1P - Pass Task

        +
        + +
        +
        +
        +
        +

        Evidence portfolio

        +

        3.1C - Credit Task

        +
        + +
        +
        +
        + +
        +
        +
        +

        COS20007

        +

        Active

        +
        + + + +
        +
        +
        +
        +
        +

        Communication report

        +

        4.1P - Pass Task

        +
        + +
        +
        +
        +
        +

        Team contribution review

        +

        5.1P - Pass Task

        +
        + +
        +
        +
        + +
        +
        +
        +

        COS30046

        +

        Active

        +
        + + + +
        +
        +
        +
        +
        +

        Capstone project proposal

        +

        6.1D - Distinction Task

        +
        + +
        +
        +
        +
        +
        + + + + + + diff --git a/docs/evidence/cpd-sizing-investigation/verification.txt b/docs/evidence/cpd-sizing-investigation/verification.txt new file mode 100644 index 0000000000..70f71c5ca6 --- /dev/null +++ b/docs/evidence/cpd-sizing-investigation/verification.txt @@ -0,0 +1,28 @@ +CPD sizing investigation verification +Date: 2026-08-23 +Branch: docs/cpd-sizing-investigation +Target: feature/cross-unit + +1. npm run lint + Result: PASS + Detail: All files pass linting. + +2. npm run typecheck + Result: PASS + Detail: Angular compiler typecheck exited with code 0. + +3. npm run test:ci + Result: PASS + Detail: 60 test files passed. 119 tests passed and 1 existing test is marked todo. + +4. CI=true npm run build -- --no-progress + Result: PASS + Detail: Application bundle generation completed successfully. + +5. git diff --check + Result: PASS + Detail: No whitespace errors. + +The initial lint run exposed 25 Prettier warnings already present on the shared target branch in +unit-task-editor.component.html and unit-task-editor.component.ts. The formatter made mechanical +style-only changes to those two files. No behavior was changed. From 4007ce827511139e8bc3e77eba3248bcf6f72e50 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Sun, 23 Aug 2026 22:27:48 +1000 Subject: [PATCH 1412/1531] chore: format unit task editor --- .../unit-task-editor.component.html | 36 ++++++------------- .../unit-task-editor.component.ts | 30 ++++++++-------- 2 files changed, 25 insertions(+), 41 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html index 0d95db5031..f9265f7169 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html @@ -38,14 +38,10 @@

        Task List

        @if (unit.allowFlexibleDates) { - + } - +
        @if (unit.allowFlexibleDates) { @@ -169,9 +165,7 @@

        Manage Target Dates

        \ No newline at end of file +
        diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts index 39830be3ec..0077c64900 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts @@ -1,18 +1,18 @@ -import { addWeeks } from 'date-fns'; -import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { MatTableDataSource } from '@angular/material/table'; -import { Subscription } from 'rxjs'; -import { TaskDefinition } from 'src/app/api/models/task-definition'; -import { GradeDefinition, Unit } from 'src/app/api/models/unit'; -import { FeedbackTemplateService } from 'src/app/api/services/feedback-template.service'; -import { TaskDefinitionService } from 'src/app/api/services/task-definition.service'; -import { ConfirmationModalService } from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {addWeeks} from 'date-fns'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {MatTableDataSource} from '@angular/material/table'; +import {Subscription} from 'rxjs'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {GradeDefinition, Unit} from 'src/app/api/models/unit'; +import {FeedbackTemplateService} from 'src/app/api/services/feedback-template.service'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; import { CsvResult, CsvResultModalService, } from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; -import { CsvUploadModalService } from 'src/app/common/modals/csv-upload-modal/csv-upload-modal.service'; -import { AlertService } from 'src/app/common/services/alert.service'; +import {CsvUploadModalService} from 'src/app/common/modals/csv-upload-modal/csv-upload-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; @Component({ selector: 'f-unit-task-editor', @@ -196,7 +196,7 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { } this.feedbackTemplateService - .query({ contextType: 'task_definitions', contextId: this.selectedTaskDefinition.id }, {}) + .query({contextType: 'task_definitions', contextId: this.selectedTaskDefinition.id}, {}) .subscribe({ error: () => this.alerts.error('Error loading task feedback templates.'), }); @@ -255,7 +255,7 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { this.csvUploadModal.show( 'Upload Task Definitions as CSV', 'Upload a CSV of task definitions.', - { file: { name: 'Task Definition CSV Data', type: 'csv' } }, + {file: {name: 'Task Definition CSV Data', type: 'csv'}}, this.unit.getTaskDefinitionBatchUploadUrl(), (response: CsvResult) => { // at least one student? @@ -272,7 +272,7 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { this.csvUploadModal.show( 'Upload Task Sheets and Resources as Zip', 'Upload a ZIP of task sheets and resources.', - { file: { name: 'Task Sheets and Resources', type: 'zip' } }, + {file: {name: 'Task Sheets and Resources', type: 'zip'}}, this.unit.taskUploadUrl, (response: CsvResult) => { // at least one student? @@ -305,4 +305,4 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { this.selectedTaskDefinition = task; } -} \ No newline at end of file +} From 5d2aad3b82f283e6e06898ecb146c4668c7e24fb Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Sun, 23 Aug 2026 22:33:13 +1000 Subject: [PATCH 1413/1531] chore(node): remove node_modules from ppi --- node_modules | 1 - 1 file changed, 1 deletion(-) delete mode 120000 node_modules diff --git a/node_modules b/node_modules deleted file mode 120000 index a13f6c1984..0000000000 --- a/node_modules +++ /dev/null @@ -1 +0,0 @@ -/Users/clupa/Documents/uni/sit374/ontrack/doubtfire-web/node_modules \ No newline at end of file From 4b32ad89329dedeeeeab8019cd01797ef40f3388 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Sun, 23 Aug 2026 22:52:21 +1000 Subject: [PATCH 1414/1531] style(ppi): format accessibility changes --- .../ppi-widget/ppi-widget.component.html | 5 ++- .../ppi-widget/ppi-widget.component.spec.ts | 40 +++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.html index 91bdcc3916..aabd7239af 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.html @@ -45,8 +45,9 @@ } @case ('success') {
        - {{ view.data?.submittedPercentage }}% of peers at your target grade have submitted + {{ view.data?.submittedPercentage }}% of peers at your target grade have submitted
        } } - diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts index 6dd594dbb2..ef56a44633 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts @@ -1,13 +1,13 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { SimpleChange } from '@angular/core'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatButtonModule } from '@angular/material/button'; -import { MatIconModule } from '@angular/material/icon'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; -import { Observable, Subject, of, throwError } from 'rxjs'; -import { PeerProgressIndicator } from 'src/app/api/models/peer-progress-indicator'; -import { Task } from 'src/app/api/models/task'; -import { TaskDefinition } from 'src/app/api/models/task-definition'; +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {SimpleChange} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatButtonModule} from '@angular/material/button'; +import {MatIconModule} from '@angular/material/icon'; +import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; +import {Observable, Subject, of, throwError} from 'rxjs'; +import {PeerProgressIndicator} from 'src/app/api/models/peer-progress-indicator'; +import {Task} from 'src/app/api/models/task'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; import { DISABLED_STATE, NORMAL_STATE, @@ -16,16 +16,16 @@ import { UNAVAILABLE_STATE, ZERO_PERCENT_STATE, } from 'src/app/api/services/mock'; -import { PeerProgressIndicatorService } from 'src/app/api/services/peer-progress-indicator.service'; -import { PpiWidgetComponent } from './ppi-widget.component'; +import {PeerProgressIndicatorService} from 'src/app/api/services/peer-progress-indicator.service'; +import {PpiWidgetComponent} from './ppi-widget.component'; describe('PpiWidgetComponent', () => { let component: PpiWidgetComponent; let fixture: ComponentFixture; let getIndicator: ReturnType; - const mockTask = { project: { unit: { id: 1 }, targetGrade: 2 } } as unknown as Task; - const mockTaskDef = { id: 99 } as unknown as TaskDefinition; + const mockTask = {project: {unit: {id: 1}, targetGrade: 2}} as unknown as Task; + const mockTaskDef = {id: 99} as unknown as TaskDefinition; beforeEach(async () => { getIndicator = vi.fn(); @@ -33,7 +33,7 @@ describe('PpiWidgetComponent', () => { await TestBed.configureTestingModule({ declarations: [PpiWidgetComponent], imports: [MatIconModule, MatProgressSpinnerModule, MatButtonModule], - providers: [{ provide: PeerProgressIndicatorService, useValue: { getIndicator } }], + providers: [{provide: PeerProgressIndicatorService, useValue: {getIndicator}}], }).compileComponents(); fixture = TestBed.createComponent(PpiWidgetComponent); @@ -44,7 +44,7 @@ describe('PpiWidgetComponent', () => { function load(response$: Observable) { getIndicator.mockReturnValue(response$); - component.ngOnChanges({ task: new SimpleChange(null, mockTask, true) }); + component.ngOnChanges({task: new SimpleChange(null, mockTask, true)}); fixture.detectChanges(); } @@ -97,7 +97,7 @@ describe('PpiWidgetComponent', () => { const subject: Subject = new Subject(); getIndicator.mockReturnValue(subject.asObservable()); - component.ngOnChanges({ task: new SimpleChange(null, mockTask, true) }); + component.ngOnChanges({task: new SimpleChange(null, mockTask, true)}); expect(component.view.state).toBe('loading'); subject.next(NORMAL_STATE); @@ -108,7 +108,7 @@ describe('PpiWidgetComponent', () => { const subject: Subject = new Subject(); getIndicator.mockReturnValue(subject.asObservable()); - component.ngOnChanges({ task: new SimpleChange(null, mockTask, true) }); + component.ngOnChanges({task: new SimpleChange(null, mockTask, true)}); expect(component.view.state).toBe('loading'); subject.error(new Error('network down')); @@ -133,8 +133,8 @@ describe('PpiWidgetComponent', () => { .mockReturnValueOnce(first.asObservable()) .mockReturnValueOnce(second.asObservable()); - component.ngOnChanges({ task: new SimpleChange(null, mockTask, true) }); - component.ngOnChanges({ task: new SimpleChange(null, mockTask, true) }); + component.ngOnChanges({task: new SimpleChange(null, mockTask, true)}); + component.ngOnChanges({task: new SimpleChange(null, mockTask, true)}); first.next(NORMAL_STATE); expect(component.view.state).toBe('loading'); From 574ede8e467ba3314e28381d94e3a57ba40075e4 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 00:08:12 +1000 Subject: [PATCH 1415/1531] fix(pwa): use OnTrack install branding --- src/manifest.webmanifest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/manifest.webmanifest b/src/manifest.webmanifest index 6aa76a0c12..c6df094d7f 100644 --- a/src/manifest.webmanifest +++ b/src/manifest.webmanifest @@ -1,6 +1,6 @@ { - "name": "formatif learning and feedback", - "short_name": "formatif", + "name": "OnTrack learning and feedback", + "short_name": "OnTrack", "icons": [ { "src": "/assets/icons/android-chrome-192x192.png", From 3173a4db570306a6da4462f6c1c0ba37be7665cd Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 01:12:51 +1000 Subject: [PATCH 1416/1531] style(docs): remove PPI trailing whitespace --- docs/ppi-help-text-pack.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ppi-help-text-pack.md b/docs/ppi-help-text-pack.md index 58c2482d18..abae2371de 100644 --- a/docs/ppi-help-text-pack.md +++ b/docs/ppi-help-text-pack.md @@ -1,7 +1,7 @@ # PPI-D01: Peer Progress Help Text and Privacy Copy -**Ticket:** PPI-D01 - Write the peer-comparison explanation, privacy limits and help text -**Branch:** `docs/ppi-help-privacy` +**Ticket:** PPI-D01 - Write the peer-comparison explanation, privacy limits and help text +**Branch:** `docs/ppi-help-privacy` **Scope:** Documentation and copy specification only. No production widget logic, API behaviour or data flow is changed by this document. From 73f9613ad806b6931c0c13529382598973140792 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 01:17:52 +1000 Subject: [PATCH 1417/1531] fix(integration): align merged feature regressions --- .../progress-dashboard/progress-dashboard.component.spec.ts | 2 ++ .../directives/unit-task-list/unit-task-list.component.ts | 5 +---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts index 384a02fdbb..d5e1ca888a 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts @@ -9,6 +9,7 @@ import {MatSelectHarness} from '@angular/material/select/testing'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {of, throwError} from 'rxjs'; import {Project} from 'src/app/api/models/project'; +import {PeerProgressIndicatorService} from 'src/app/api/services/peer-progress-indicator.service'; import {ProjectService} from 'src/app/api/services/project.service'; import {UserService} from 'src/app/api/services/user.service'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -136,6 +137,7 @@ describe('ProgressDashboardComponent route reuse', () => { gradeValues: [0], gradeValuesFor, } as unknown as GradeService, + new PeerProgressIndicatorService(), {} as ProjectService, {} as AlertService, {} as UserService, diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index ec543b2d64..20400dded7 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -300,10 +300,7 @@ export class FUnitTaskListComponent implements OnChanges, OnInit, OnDestroy { ) ?? null) : null; - if ( - nextTaskDefinition && - this.isTaskDefinitionAboveTargetGrade(nextTaskDefinition) - ) { + if (nextTaskDefinition && this.isTaskDefinitionAboveTargetGrade(nextTaskDefinition)) { this.viewPreferences = {...this.viewPreferences, showAboveTargetGrade: true}; this.persistViewPreferences(); this.applyFilters(); From e800116179e4baf853f27c3f9329f30184186343 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 01:31:20 +1000 Subject: [PATCH 1418/1531] fix(test): isolate browser globals across suites --- .../api/services/authentication.service.ts | 17 ++++++++++++--- .../unit-task-list.component.spec.ts | 8 +++---- .../progress-burndown-chart.component.spec.ts | 21 +++---------------- .../progress-burndown-chart.component.ts | 5 +++-- 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/app/api/services/authentication.service.ts b/src/app/api/services/authentication.service.ts index e896b77561..f8cfc99c8e 100644 --- a/src/app/api/services/authentication.service.ts +++ b/src/app/api/services/authentication.service.ts @@ -87,7 +87,7 @@ export class AuthenticationService { ) { this.AUTH_URL = `${this.doubtfireConstants.API_URL}/auth`; // Ensure any only user data is removed from local storage - localStorage.removeItem(this.USERNAME_KEY); + this.browserStorage?.removeItem(this.USERNAME_KEY); } private actionAuthFailed() { @@ -159,11 +159,22 @@ export class AuthenticationService { } public get rememberMe(): boolean { - return localStorage.getItem(this.REMEMBER_DOUBTFIRE_CREDENTIALS_TOKEN) !== 'false'; + return this.browserStorage?.getItem(this.REMEMBER_DOUBTFIRE_CREDENTIALS_TOKEN) !== 'false'; } public set rememberMe(remember: boolean) { - localStorage.setItem(this.REMEMBER_DOUBTFIRE_CREDENTIALS_TOKEN, remember ? 'true' : 'false'); + this.browserStorage?.setItem( + this.REMEMBER_DOUBTFIRE_CREDENTIALS_TOKEN, + remember ? 'true' : 'false', + ); + } + + private get browserStorage(): Storage | null { + try { + return globalThis.localStorage ?? null; + } catch { + return null; + } } /** diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts index feae0a45c2..69cb4a8e05 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts @@ -39,10 +39,8 @@ describe('FUnitTaskListComponent', () => { let routeParamMap$: Subject>; beforeEach(async () => { - vi.stubGlobal('localStorage', { - getItem: vi.fn(() => null), - setItem: vi.fn(), - }); + vi.spyOn(Storage.prototype, 'getItem').mockReturnValue(null); + vi.spyOn(Storage.prototype, 'setItem').mockImplementation(() => undefined); routeParamMap$ = new Subject>(); await TestBed.configureTestingModule({ @@ -69,7 +67,7 @@ describe('FUnitTaskListComponent', () => { }); afterEach(() => { - vi.unstubAllGlobals(); + vi.restoreAllMocks(); }); it('should create', () => { diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts index 5fd6fd5fdd..64d6c9abbf 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts @@ -1,5 +1,5 @@ -import {beforeAll, describe, expect, it, vi} from 'vitest'; -import {Injector, LOCALE_ID, SimpleChange, ViewContainerRef} from '@angular/core'; +import {describe, expect, it, vi} from 'vitest'; +import {SimpleChange, ViewContainerRef} from '@angular/core'; import {Subject, of, throwError} from 'rxjs'; import { PeerProgressResponse, @@ -7,27 +7,11 @@ import { PeerProgressState, Project, } from 'src/app/api/models/doubtfire-model'; -import {AppInjector, setAppInjector} from 'src/app/app-injector'; import {ProgressBurndownChartComponent} from './progress-burndown-chart.component'; describe('ProgressBurndownChartComponent peer comparison', () => { const EXISTING_SERIES = ['Target', 'Projected', 'To Submit', 'To Complete']; - beforeAll(() => { - if (!AppInjector) { - setAppInjector( - Injector.create({ - providers: [ - { - provide: LOCALE_ID, - useValue: 'en-US', - }, - ], - }), - ); - } - }); - function makeProject(): Project { const startDate = new Date(2026, 6, 1); const endDate = new Date(2026, 7, 31); @@ -109,6 +93,7 @@ describe('ProgressBurndownChartComponent peer comparison', () => { { getCohortMedian, } as unknown as PeerProgressService, + 'en-US', ); component.project = project; diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts index 1ca9323e91..160b6a6d84 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts @@ -4,6 +4,7 @@ import { ChangeDetectionStrategy, Component, HostListener, + Inject, Input, LOCALE_ID, OnChanges, @@ -21,7 +22,6 @@ import { Project, Unit, } from 'src/app/api/models/doubtfire-model'; -import {AppInjector} from 'src/app/app-injector'; import {ChartBaseComponent} from 'src/app/common/chart-base/chart-base-component/chart-base-component.component'; interface BurndownPoint { @@ -89,6 +89,7 @@ export class ProgressBurndownChartComponent constructor( public viewContainerRef: ViewContainerRef, private peerProgressService: PeerProgressService, + @Inject(LOCALE_ID) private locale: string, ) { super(viewContainerRef); this.data = []; @@ -231,7 +232,7 @@ export class ProgressBurndownChartComponent updateData(): void { const chartData = this.project?.burndownChartData; - const locale: string = AppInjector.get(LOCALE_ID); + const locale = this.locale; const startDate: Date = this.project.unit.startDate; const endDate: Date = this.project.unit.endDate; From b61a668aad2d4f765c3a0c37b844e2b279369c21 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 01:31:29 +1000 Subject: [PATCH 1419/1531] feat(ppi): connect task widget to live API --- docs/ppi-f02-unit-summary-handover.md | 14 +- docs/ppi-help-text-pack.md | 26 ++-- .../peer-progress-indicator.fixtures.spec.ts | 6 +- .../peer-progress-indicator-state.spec.ts | 12 +- src/app/api/models/peer-progress-indicator.ts | 4 +- .../peer-progress-indicator.service.ts | 48 ++++--- .../peer-progress-indicator.service.spec.ts | 133 ++++++++---------- .../progress-dashboard.component.spec.ts | 8 +- .../ppi-widget/ppi-widget.component.html | 4 +- .../ppi-widget/ppi-widget.component.spec.ts | 46 ++++-- .../ppi-widget/ppi-widget.component.ts | 21 +-- 11 files changed, 171 insertions(+), 151 deletions(-) diff --git a/docs/ppi-f02-unit-summary-handover.md b/docs/ppi-f02-unit-summary-handover.md index c0fede4536..a19a8dd04a 100644 --- a/docs/ppi-f02-unit-summary-handover.md +++ b/docs/ppi-f02-unit-summary-handover.md @@ -81,19 +81,19 @@ The future frontend adapter can replace the mock call inside `ProgressDashboardComponent.loadPeerProgressUnitSummary()` without redesigning the presentational component. -### Nullability the frontend types do not yet allow +### Task-level adapter nullability doubtfire-api#16 returns `null` for `last_updated_at` and `target_grade` in -several documented states. Before the adapter lands, `PeerProgressIndicator` -needs `lastUpdatedAt: string | null` and `targetGrade: number | null`. +several documented states. The task-level live adapter now maps those values to +`PeerProgressIndicator.lastUpdatedAt: string | null` and +`PeerProgressIndicator.targetGrade: number | null`. ### The mock must not reach a production build -Both PPI surfaces render a fixture today: this component and the already-merged -`f-ppi-widget` on the task sheet. Both are now gated on +The unit-level summary in this document remains mock-backed and is gated on `environment.production`, so a built application shows the unavailable state -rather than a fabricated percentage. Remove both guards in the same change that -lands the live adapter, and not before. +rather than a fabricated percentage. The task-sheet `f-ppi-widget` now uses the +authorised project/task API route and does not render a fixture in production. ## Validation diff --git a/docs/ppi-help-text-pack.md b/docs/ppi-help-text-pack.md index abae2371de..4d388814e0 100644 --- a/docs/ppi-help-text-pack.md +++ b/docs/ppi-help-text-pack.md @@ -33,8 +33,8 @@ These rules apply to both views: 1. A group result is shown as one combined percentage. 2. It must not display names, student IDs, project IDs, individual results, individual task statuses, marks, feedback, raw group size or rankings. -3. A genuine `0%` is a real value. It must not be presented as missing, suppressed or - unavailable data. +3. A displayed `0%` is a real privacy-bucket value. It must not be presented as missing, + suppressed or unavailable data, but it may represent a small percentage that rounds to zero. 4. A suppressed result explains that the group value is hidden for privacy without revealing the exact group size. 5. Unavailable and stale states describe a data or timing condition. They must not sound @@ -124,16 +124,16 @@ Suggested accessible name: same target grade. It does not show names, individual results, raw group size or rankings. It does not assess your own work or predict your grade. -### 3.2 Genuine zero result +### 3.2 Rounded zero result **Template state:** `@case ('no-data')` - **Label:** Peer task progress -- **Tooltip or short help text:** The group percentage is currently 0%. This is a real - result, not missing data. -- **Expanded explanation:** No students in the privacy-protected group have submitted - this task yet. This is not feedback about your own progress. The percentage may change - as submissions are made. +- **Tooltip or short help text:** The privacy-protected group percentage currently rounds + to 0%. This is a displayed value, not missing data. +- **Expanded explanation:** The API rounds percentages into privacy-safe bands, so 0% may + include a small number of submissions. It is not feedback about your own progress. The + displayed percentage may change as submissions are made. ### 3.3 Small-group suppression @@ -204,14 +204,14 @@ claim that live unit-level data has been delivered. and does not show names, individual results, raw group size, marks, feedback or rankings. -### 4.2 Genuine zero group result +### 4.2 Rounded zero group result - **Label:** Unit progress overview -- **Tooltip or short help text:** Anonymous group progress is currently 0%. This is a real - value, not missing data. +- **Tooltip or short help text:** Anonymous group progress currently rounds to 0%. This is + a displayed value, not missing data. - **Expanded explanation:** Your own progress remains separate from the group result. A - group value of 0% only describes the current aggregate. It is not feedback about your - work and does not predict your grade. + displayed group value of 0% may include a small value that rounds to zero. It is not + feedback about your work and does not predict your grade. ### 4.3 Small-group suppression diff --git a/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts b/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts index d302c9bdd7..b4c3f8cc9b 100644 --- a/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts +++ b/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts @@ -13,7 +13,7 @@ import { const assertContractShape = (fixture: PeerProgressIndicator) => { expect(typeof fixture.taskDefinitionId).toBe('number'); expect(typeof fixture.unitId).toBe('number'); - expect(typeof fixture.targetGrade).toBe('number'); + expect(fixture.targetGrade === null || typeof fixture.targetGrade === 'number').toBe(true); // submittedPercentage can be number or null expect( @@ -24,7 +24,7 @@ const assertContractShape = (fixture: PeerProgressIndicator) => { expect(typeof fixture.isStale).toBe('boolean'); expect(typeof fixture.isFeatureEnabled).toBe('boolean'); - expect(typeof fixture.lastUpdatedAt).toBe('string'); + expect(fixture.lastUpdatedAt === null || typeof fixture.lastUpdatedAt === 'string').toBe(true); expect(typeof fixture.unavailableMessage).toBe('string'); }; @@ -61,7 +61,7 @@ describe('PeerProgressIndicator Fixture Regression Tests', () => { expect(FIXTURE_NORMAL.isFeatureEnabled).toBe(true); }); - it('ZERO_PERCENT fixture correctly represents genuine 0%', () => { + it('ZERO_PERCENT fixture keeps a displayed 0% distinct from unavailable data', () => { expect(FIXTURE_ZERO_PERCENT.submittedPercentage).toBe(0); expect(FIXTURE_ZERO_PERCENT.isSuppressed).toBe(false); }); diff --git a/src/app/api/models/peer-progress-indicator-state.spec.ts b/src/app/api/models/peer-progress-indicator-state.spec.ts index df17d4085e..5d7a2d9d35 100644 --- a/src/app/api/models/peer-progress-indicator-state.spec.ts +++ b/src/app/api/models/peer-progress-indicator-state.spec.ts @@ -28,7 +28,7 @@ describe('resolvePeerProgressState', () => { expect(result.data).toEqual(NORMAL_STATE); }); - it('returns no-data when nobody has submitted yet', () => { + it('keeps a rounded zero distinct from unavailable data', () => { const result = resolvePeerProgressState(false, null, ZERO_PERCENT_STATE); expect(result.state).toBe('no-data'); }); @@ -39,6 +39,16 @@ describe('resolvePeerProgressState', () => { expect(result.message).toBe(SUPPRESSED_STATE.unavailableMessage); }); + it('prioritises privacy suppression when a response is also stale', () => { + const result = resolvePeerProgressState(false, null, { + ...STALE_STATE, + isSuppressed: true, + }); + + expect(result.state).toBe('hidden'); + expect(result.data?.submittedPercentage).toBeNull(); + }); + it('returns unavailable for a generically unavailable response', () => { const result = resolvePeerProgressState(false, null, UNAVAILABLE_STATE); expect(result.state).toBe('unavailable'); diff --git a/src/app/api/models/peer-progress-indicator.ts b/src/app/api/models/peer-progress-indicator.ts index 2a201b5237..d354ae7e97 100644 --- a/src/app/api/models/peer-progress-indicator.ts +++ b/src/app/api/models/peer-progress-indicator.ts @@ -1,13 +1,13 @@ export interface PeerProgressIndicator { taskDefinitionId: number; // ID of the task definition unitId: number; // ID of the unit - targetGrade: number; // Student’s selected target grade (0–3) + targetGrade: number | null; // Valid server-side target grade, or null when unavailable submittedPercentage: number | null; // null when suppressed/unavailable/disabled isSuppressed: boolean; // true when cohort too small isStale: boolean; // true when data is outdated isFeatureEnabled: boolean; // false when unit disables PPI - lastUpdatedAt: string; // ISO timestamp + lastUpdatedAt: string | null; // ISO timestamp, or null when no snapshot was used unavailableMessage: string; // safe message for suppressed/unavailable/stale/disabled } diff --git a/src/app/api/services/peer-progress-indicator.service.ts b/src/app/api/services/peer-progress-indicator.service.ts index 7bbf160a46..54c6fa5f7c 100644 --- a/src/app/api/services/peer-progress-indicator.service.ts +++ b/src/app/api/services/peer-progress-indicator.service.ts @@ -1,5 +1,7 @@ +import {HttpClient} from '@angular/common/http'; import {Injectable} from '@angular/core'; -import {Observable, of} from 'rxjs'; +import {Observable, map, of} from 'rxjs'; +import API_URL from 'src/app/config/constants/apiUrl'; import {PeerProgressIndicator} from '../models/peer-progress-indicator'; import {PeerProgressUnitSummary} from '../models/peer-progress-unit-summary'; import { @@ -11,28 +13,40 @@ import { ZERO_PERCENT_STATE, } from './mock/peer-progress-indicator.mock'; +interface PeerProgressIndicatorResponse { + task_definition_id: number; + unit_id: number; + target_grade: number | null; + submitted_percentage: number | null; + is_suppressed: boolean; + is_stale: boolean; + is_feature_enabled: boolean; + last_updated_at: string | null; + unavailable_message: string; +} + @Injectable({ providedIn: 'root', }) export class PeerProgressIndicatorService { - constructor() {} - - // At the moment, it returns mock PPI data for the given state. In future, this will call the real backend API. + constructor(private httpClient: HttpClient) {} - getIndicator( - taskDefinitionId: number, - unitId: number, - targetGrade: number, - state: 'normal' | 'zero' | 'suppressed' | 'unavailable' | 'stale' | 'disabled', - ): Observable { - const base = this.resolveState(state); + getIndicator(projectId: number, taskDefinitionId: number): Observable { + const url = `${API_URL}/projects/${projectId}/task_def_id/${taskDefinitionId}/peer_progress`; - return of({ - ...base, - taskDefinitionId, - unitId, - targetGrade, - }); + return this.httpClient.get(url).pipe( + map((response) => ({ + taskDefinitionId: response.task_definition_id, + unitId: response.unit_id, + targetGrade: response.target_grade, + submittedPercentage: response.submitted_percentage, + isSuppressed: response.is_suppressed, + isStale: response.is_stale, + isFeatureEnabled: response.is_feature_enabled, + lastUpdatedAt: response.last_updated_at, + unavailableMessage: response.unavailable_message, + })), + ); } /** diff --git a/src/app/api/services/spec/peer-progress-indicator.service.spec.ts b/src/app/api/services/spec/peer-progress-indicator.service.spec.ts index 9a8863738e..8c0c9adafd 100644 --- a/src/app/api/services/spec/peer-progress-indicator.service.spec.ts +++ b/src/app/api/services/spec/peer-progress-indicator.service.spec.ts @@ -1,106 +1,93 @@ -import {beforeEach, describe, expect, it} from 'vitest'; +import {afterEach, beforeEach, describe, expect, it} from 'vitest'; +import {provideHttpClient, withInterceptorsFromDi, withXhr} from '@angular/common/http'; +import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; import {TestBed} from '@angular/core/testing'; -import { - DISABLED_STATE, - NORMAL_STATE, - STALE_STATE, - SUPPRESSED_STATE, - UNAVAILABLE_STATE, - ZERO_PERCENT_STATE, -} from '../mock/peer-progress-indicator.mock'; +import {PeerProgressIndicator} from 'src/app/api/models/peer-progress-indicator'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {DISABLED_STATE, NORMAL_STATE, SUPPRESSED_STATE} from '../mock/peer-progress-indicator.mock'; import {PeerProgressIndicatorService} from '../peer-progress-indicator.service'; describe('PeerProgressIndicatorService', () => { let service: PeerProgressIndicatorService; + let httpMock: HttpTestingController; beforeEach(() => { TestBed.configureTestingModule({ - providers: [PeerProgressIndicatorService], + providers: [ + PeerProgressIndicatorService, + provideHttpClient(withXhr(), withInterceptorsFromDi()), + provideHttpClientTesting(), + ], }); service = TestBed.inject(PeerProgressIndicatorService); + httpMock = TestBed.inject(HttpTestingController); }); - it('should return normal state', () => { - service.getIndicator(1, 10, 2, 'normal').subscribe((result) => { - expect(result.submittedPercentage).toBe(NORMAL_STATE.submittedPercentage); - expect(result.isSuppressed).toBe(NORMAL_STATE.isSuppressed); - expect(result.isFeatureEnabled).toBe(NORMAL_STATE.isFeatureEnabled); - - // overwritten fields - expect(result.taskDefinitionId).toBe(1); - expect(result.unitId).toBe(10); - expect(result.targetGrade).toBe(2); - }); + afterEach(() => { + httpMock.verify({ignoreCancelled: true}); }); - it('should return zero percent state', () => { - service.getIndicator(2, 20, 1, 'zero').subscribe((result) => { - expect(result.submittedPercentage).toBe(ZERO_PERCENT_STATE.submittedPercentage); - expect(result.isSuppressed).toBe(ZERO_PERCENT_STATE.isSuppressed); + it('requests the authorised project/task route without client-supplied cohort parameters', () => { + service.getIndicator(7, 99).subscribe(); - expect(result.taskDefinitionId).toBe(2); - expect(result.unitId).toBe(20); - expect(result.targetGrade).toBe(1); - }); - }); + const request = httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`); - it('should return suppressed state', () => { - service.getIndicator(3, 30, 0, 'suppressed').subscribe((result) => { - expect(result.submittedPercentage).toBe(SUPPRESSED_STATE.submittedPercentage); - expect(result.isSuppressed).toBe(true); - expect(result.unavailableMessage).toBe(SUPPRESSED_STATE.unavailableMessage); + expect(request.request.method).toBe('GET'); + expect(request.request.params.keys()).toEqual([]); - expect(result.taskDefinitionId).toBe(3); - expect(result.unitId).toBe(30); - expect(result.targetGrade).toBe(0); + request.flush({ + task_definition_id: 99, + unit_id: 1, + target_grade: 2, + submitted_percentage: 40, + is_suppressed: false, + is_stale: false, + is_feature_enabled: true, + last_updated_at: '2026-08-23T00:00:00Z', + unavailable_message: '', }); }); - it('should return unavailable state', () => { - service.getIndicator(4, 40, 3, 'unavailable').subscribe((result) => { - expect(result.submittedPercentage).toBe(UNAVAILABLE_STATE.submittedPercentage); - expect(result.unavailableMessage).toBe(UNAVAILABLE_STATE.unavailableMessage); + it('maps the complete snake-case response and preserves nullable fields', () => { + let result: PeerProgressIndicator | undefined; - expect(result.taskDefinitionId).toBe(4); - expect(result.unitId).toBe(40); - expect(result.targetGrade).toBe(3); + service.getIndicator(7, 99).subscribe((value) => { + result = value; }); - }); - it('should return stale state', () => { - service.getIndicator(5, 50, 2, 'stale').subscribe((result) => { - expect(result.submittedPercentage).toBe(STALE_STATE.submittedPercentage); - expect(result.isStale).toBe(true); - expect(result.unavailableMessage).toBe(STALE_STATE.unavailableMessage); - - expect(result.taskDefinitionId).toBe(5); - expect(result.unitId).toBe(50); - expect(result.targetGrade).toBe(2); + httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`).flush({ + task_definition_id: 99, + unit_id: 1, + target_grade: null, + submitted_percentage: null, + is_suppressed: false, + is_stale: false, + is_feature_enabled: true, + last_updated_at: null, + unavailable_message: 'Peer progress is currently unavailable.', }); - }); - - it('should return disabled state', () => { - service.getIndicator(6, 60, 1, 'disabled').subscribe((result) => { - expect(result.submittedPercentage).toBe(DISABLED_STATE.submittedPercentage); - expect(result.isFeatureEnabled).toBe(false); - expect(result.unavailableMessage).toBe(DISABLED_STATE.unavailableMessage); - expect(result.taskDefinitionId).toBe(6); - expect(result.unitId).toBe(60); - expect(result.targetGrade).toBe(1); + expect(result).toEqual({ + taskDefinitionId: 99, + unitId: 1, + targetGrade: null, + submittedPercentage: null, + isSuppressed: false, + isStale: false, + isFeatureEnabled: true, + lastUpdatedAt: null, + unavailableMessage: 'Peer progress is currently unavailable.', }); }); - it('should fall back to unavailable state for unknown keys', () => { - service.getIndicator(99, 99, 0, 'unknown' as 'normal').subscribe((result) => { - expect(result.unavailableMessage).toBe(UNAVAILABLE_STATE.unavailableMessage); - expect(result.submittedPercentage).toBeNull(); + it('cancels the live HTTP request when the caller unsubscribes', () => { + const subscription = service.getIndicator(7, 99).subscribe(); + const request = httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`); - expect(result.taskDefinitionId).toBe(99); - expect(result.unitId).toBe(99); - expect(result.targetGrade).toBe(0); - }); + subscription.unsubscribe(); + + expect(request.cancelled).toBe(true); }); describe('getMockUnitSummary', () => { diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts index d5e1ca888a..954d6b6635 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts @@ -57,6 +57,10 @@ describe('ProgressDashboardComponent', () => { gradeValuesFor: () => [0, 1], }, }, + { + provide: PeerProgressIndicatorService, + useValue: {getMockUnitSummary: vi.fn().mockReturnValue(of(null))}, + }, {provide: ProjectService, useValue: {update: projectServiceUpdate}}, {provide: AlertService, useValue: {success: alertSuccess, error: alertError}}, {provide: UserService, useValue: {currentUser: {id: 25}}}, @@ -137,7 +141,9 @@ describe('ProgressDashboardComponent route reuse', () => { gradeValues: [0], gradeValuesFor, } as unknown as GradeService, - new PeerProgressIndicatorService(), + { + getMockUnitSummary: vi.fn().mockReturnValue(of(null)), + } as unknown as PeerProgressIndicatorService, {} as ProjectService, {} as AlertService, {} as UserService, diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.html index aabd7239af..f806af991b 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.html @@ -33,7 +33,9 @@ @case ('no-data') {
        hourglass_empty - No peer submissions yet + + Peer submission progress rounds to 0% for your target grade +
        } @case ('stale') { diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts index ef56a44633..2a3d901d08 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts @@ -1,4 +1,5 @@ import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {HttpErrorResponse} from '@angular/common/http'; import {SimpleChange} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {MatButtonModule} from '@angular/material/button'; @@ -24,7 +25,7 @@ describe('PpiWidgetComponent', () => { let fixture: ComponentFixture; let getIndicator: ReturnType; - const mockTask = {project: {unit: {id: 1}, targetGrade: 2}} as unknown as Task; + const mockTask = {project: {id: 7, unit: {id: 1}, targetGrade: 2}} as unknown as Task; const mockTaskDef = {id: 99} as unknown as TaskDefinition; beforeEach(async () => { @@ -55,14 +56,17 @@ describe('PpiWidgetComponent', () => { it('shows the peer percentage on a normal response', () => { load(of(NORMAL_STATE)); + expect(getIndicator).toHaveBeenCalledWith(7, 99); expect(component.view.state).toBe('success'); expect(fixture.nativeElement.textContent).toContain('42%'); }); - it('shows no-data when nobody has submitted yet', () => { + it('shows a rounded zero as data rather than unavailable', () => { load(of(ZERO_PERCENT_STATE)); expect(component.view.state).toBe('no-data'); - expect(fixture.nativeElement.textContent).toContain('No peer submissions yet'); + expect(fixture.nativeElement.textContent).toContain( + 'Peer submission progress rounds to 0% for your target grade', + ); }); it('shows the API-provided hidden message for a suppressed response', () => { @@ -104,17 +108,31 @@ describe('PpiWidgetComponent', () => { expect(component.view.state).toBe('success'); }); - it('transitions from loading to error on failure, with no stale data shown', () => { - const subject: Subject = new Subject(); - getIndicator.mockReturnValue(subject.asObservable()); - - component.ngOnChanges({task: new SimpleChange(null, mockTask, true)}); - expect(component.view.state).toBe('loading'); - - subject.error(new Error('network down')); - expect(component.view.state).toBe('error'); - expect(component.view.data).toBeNull(); - }); + it.each([404, 503])( + 'shows a generic error for HTTP %s without leaking server details', + (status) => { + const subject: Subject = new Subject(); + getIndicator.mockReturnValue(subject.asObservable()); + + component.ngOnChanges({task: new SimpleChange(null, mockTask, true)}); + expect(component.view.state).toBe('loading'); + + subject.error( + new HttpErrorResponse({ + status, + error: {error: 'Peer progress is unavailable for this project or task.'}, + }), + ); + fixture.detectChanges(); + + expect(component.view.state).toBe('error'); + expect(component.view.data).toBeNull(); + expect(fixture.nativeElement.textContent).toContain('Could not load peer progress.'); + expect(fixture.nativeElement.textContent).not.toContain( + 'unavailable for this project or task', + ); + }, + ); it('does not render a stale value if a request fails after a new one has already started', () => { load(of(NORMAL_STATE)); diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.ts index 48f71a14a7..a88f2a02ef 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.ts @@ -1,4 +1,3 @@ -import {environment} from 'src/environments/environment'; import { ChangeDetectorRef, Component, @@ -27,12 +26,6 @@ export class PpiWidgetComponent implements OnChanges, OnDestroy { @Input({required: true}) task: Task; @Input({required: true}) taskDef: TaskDefinition; - // Optional mock-state override for local previewing/screenshots. - // Only used while the mock service is in place; once the real backend - // lands, this input and the 4th argument to getIndicator() both go away. - @Input() mockState: 'normal' | 'zero' | 'suppressed' | 'unavailable' | 'stale' | 'disabled' = - 'normal'; - view: PeerProgressViewModel = {state: 'loading', data: null, message: null}; private activeRequest?: Subscription; @@ -43,7 +36,7 @@ export class PpiWidgetComponent implements OnChanges, OnDestroy { ) {} ngOnChanges(changes: SimpleChanges): void { - if (changes.task || changes.taskDef || changes.mockState) { + if (changes.task || changes.taskDef) { this.load(); } } @@ -66,22 +59,12 @@ export class PpiWidgetComponent implements OnChanges, OnDestroy { return; } - // The indicator is still a fixture. Never show a fabricated percentage in a - // production build - a student cannot tell it from a real one. Remove this - // guard when the live PPI-F01 adapter replaces getIndicator's mock states. - if (environment.production) { - this.setView(resolvePeerProgressState(false, null, null)); - return; - } - // Cancel the previous request first -- otherwise a late response could overwrite our new loading state with old data. this.activeRequest?.unsubscribe(); this.setView(resolvePeerProgressState(true, null, null)); - const {unit, targetGrade} = this.task.project; - this.activeRequest = this.ppiService - .getIndicator(this.taskDef.id, unit.id, targetGrade, this.mockState) + .getIndicator(this.task.project.id, this.taskDef.id) .subscribe({ next: (data) => this.setView(resolvePeerProgressState(false, null, data)), error: (err) => this.setView(resolvePeerProgressState(false, err, null)), From a2448feb4815627891f78fd53cadaa03dc7c772f Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 01:35:26 +1000 Subject: [PATCH 1420/1531] test(ci): allow Angular suites time under load --- src/vitest-setup.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/vitest-setup.ts b/src/vitest-setup.ts index 9ee7140bc8..e2b9a2ab21 100644 --- a/src/vitest-setup.ts +++ b/src/vitest-setup.ts @@ -1 +1,10 @@ +import {vi} from 'vitest'; import 'zone.js/plugins/vitest-patch'; + +// The full Angular suite compiles and instantiates many large TestBed modules in +// parallel. Give those hooks enough headroom under CI load while keeping a +// finite timeout so genuine hangs still fail the run. +vi.setConfig({ + hookTimeout: 30_000, + testTimeout: 30_000, +}); From 7be242e2c854d8437f1a74938b17f0c680de3348 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 01:42:13 +1000 Subject: [PATCH 1421/1531] fix(cpd): keep completed tasks at bottom --- .../f-cross-dashboard.component.spec.ts | 33 ++++++++++++++++--- .../dashboard/f-cross-dashboard.component.ts | 4 +-- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/app/dashboard/f-cross-dashboard.component.spec.ts b/src/app/dashboard/f-cross-dashboard.component.spec.ts index 8dc2e37c30..257179892a 100644 --- a/src/app/dashboard/f-cross-dashboard.component.spec.ts +++ b/src/app/dashboard/f-cross-dashboard.component.spec.ts @@ -151,8 +151,8 @@ describe('CrossDashboardComponent', () => { expect(targetGradeTasks).not.toHaveBeenCalled(); expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ - 'P1', 'D1', + 'P1', ]); }); @@ -407,8 +407,8 @@ describe('CrossDashboardComponent', () => { component.setSearch(1, 'security'); expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ - '1.1P', '1.2P', + '1.1P', ]); component.toggleFilter(1, component.filterOptions[0]); @@ -445,6 +445,31 @@ describe('CrossDashboardComponent', () => { ]); }); + it('keeps completed tasks below open tasks in every sort mode', () => { + projectsSubject.next([ + makeProject(1, 'SIT764', true, [ + makeTask('Completed First', 'DONE-FIRST', 'complete', makeDate(3), 0), + makeTask('Open Later', 'OPEN-LATE', 'not_started', makeDate(20), 4), + makeTask('Completed Later', 'DONE-LATE', 'complete', makeDate(25), 5), + makeTask('Open Earlier', 'OPEN-EARLY', 'working_on_it', makeDate(10), 1), + ]), + ]); + + const expectedByMode: Record = { + Recommended: ['OPEN-LATE', 'OPEN-EARLY', 'DONE-FIRST', 'DONE-LATE'], + 'Due Date': ['OPEN-EARLY', 'OPEN-LATE', 'DONE-FIRST', 'DONE-LATE'], + Default: ['OPEN-EARLY', 'OPEN-LATE', 'DONE-FIRST', 'DONE-LATE'], + }; + + component.sortOptions.forEach((mode) => { + component.setSort(1, mode); + + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual( + expectedByMode[mode], + ); + }); + }); + it('applies separate search state in All and Previous unit scopes', () => { projectsSubject.next([ makeProject(1, 'SIT764', true, [ @@ -940,8 +965,8 @@ describe('CrossDashboardComponent', () => { component.setGrades([0, 1]); expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ - 'MATCH-P', 'MATCH-C', + 'MATCH-P', ]); }); @@ -1037,8 +1062,8 @@ describe('CrossDashboardComponent', () => { expect(component.hasGlobalToolbarChanges).toBe(false); expect(component.displayedUnits.map((unit) => unit.code)).toEqual(['SIT764']); expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ - 'ACTIVE-P', 'ACTIVE-C', + 'ACTIVE-P', ]); expect(component.displayedUnits[0].gradeSummaries).toEqual([]); }); diff --git a/src/app/dashboard/f-cross-dashboard.component.ts b/src/app/dashboard/f-cross-dashboard.component.ts index cd6bd40b6b..ebabfef7c5 100644 --- a/src/app/dashboard/f-cross-dashboard.component.ts +++ b/src/app/dashboard/f-cross-dashboard.component.ts @@ -297,11 +297,11 @@ export class CrossDashboardComponent implements OnInit { const sort = this.sorting.get(unit.projectId) ?? SortMode.Recommended; if (completedTypes.includes(a.status) && !completedTypes.includes(b.status)) { - return -1; + return 1; } if (!completedTypes.includes(a.status) && completedTypes.includes(b.status)) { - return 1; + return -1; } switch (sort) { From 3de977864affb13a7cddb7a44f7efd2357d2b052 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 02:00:04 +1000 Subject: [PATCH 1422/1531] chore(toolchain): align nvm with Angular Node support --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 6276cf12fb..6bb900519d 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v16.14.2 +v22.22.3 From ffae98e4b729b3cfe80cd6ea1be33cb4ce5be945 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 07:13:36 +1000 Subject: [PATCH 1423/1531] fix(cpd): centre deadline warning icons --- .../dashboard/list-item/dashboard-list-item.component.html | 4 +++- .../dashboard/list-item/dashboard-list-item.component.spec.ts | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.html b/src/app/dashboard/list-item/dashboard-list-item.component.html index 6e77d556a9..d262d37c19 100644 --- a/src/app/dashboard/list-item/dashboard-list-item.component.html +++ b/src/app/dashboard/list-item/dashboard-list-item.component.html @@ -19,7 +19,9 @@ 'bg-blue-100 text-blue-800': warning.state === 'within7Days', }" > - + {{ warning.label }} } diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts b/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts index ac80323d60..9a299e0d7a 100644 --- a/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts +++ b/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts @@ -158,6 +158,7 @@ describe('DashboardListItemComponent', () => { expect(badge.textContent).toContain('Due within 24 hours'); expect(icon.textContent.trim()).toBe('schedule'); expect(icon.getAttribute('aria-hidden')).toBe('true'); + expect(icon.classList).toContain('!leading-none'); expect(statusStrip.style.backgroundColor).toBe('rgb(18, 52, 86)'); expect(fixture.nativeElement.textContent).toContain('Status: Not Started'); }); From fdddd220237f3bccb4292924135b26605cfc4b2d Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 07:24:02 +1000 Subject: [PATCH 1424/1531] fix(ppi): stop demo median at current date --- src/app/api/services/peer-progress.service.ts | 16 ++++++--- .../spec/peer-progress.service.spec.ts | 33 ++++++++++++++++++- .../progress-burndown-chart.component.html | 4 ++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/app/api/services/peer-progress.service.ts b/src/app/api/services/peer-progress.service.ts index 9183204be9..c4a37f601b 100644 --- a/src/app/api/services/peer-progress.service.ts +++ b/src/app/api/services/peer-progress.service.ts @@ -40,15 +40,23 @@ export class PeerProgressService { } private sampleProfile(project: Project, profile: number[]): PeerMedianPoint[] { + const asOf = Date.now(); const weeks = MappingFunctions.step( project.unit.startDate.getTime(), project.unit.endDate.getTime(), MappingFunctions.weeksMs(1), ); - return weeks.map((time, week) => ({ - date: new Date(time).toISOString(), - remaining: profile[Math.round((week / Math.max(weeks.length - 1, 1)) * (profile.length - 1))], - })); + // Map against the whole unit before removing future points. Mapping only + // the elapsed weeks would incorrectly stretch the sample to 100% complete + // at today's date and make the demo look like the cohort has finished every + // task. + return weeks + .map((time, week) => ({ + date: new Date(time).toISOString(), + remaining: + profile[Math.round((week / Math.max(weeks.length - 1, 1)) * (profile.length - 1))], + })) + .filter((point) => new Date(point.date).getTime() <= asOf); } } diff --git a/src/app/api/services/spec/peer-progress.service.spec.ts b/src/app/api/services/spec/peer-progress.service.spec.ts index 64fccf0687..c49b353dc7 100644 --- a/src/app/api/services/spec/peer-progress.service.spec.ts +++ b/src/app/api/services/spec/peer-progress.service.spec.ts @@ -1,9 +1,13 @@ -import {describe, expect, it} from 'vitest'; +import {afterEach, describe, expect, it, vi} from 'vitest'; import {firstValueFrom} from 'rxjs'; import {Project} from '../../models/project'; import {PeerProgressService} from '../peer-progress.service'; describe('PeerProgressService', () => { + afterEach(() => { + vi.useRealTimers(); + }); + it('returns a safe demo state without exposing raw cohort size', async () => { const project = { id: 42, @@ -32,4 +36,31 @@ describe('PeerProgressService', () => { response.median_burndown.every((point) => point.remaining >= 0 && point.remaining <= 1), ).toBe(true); }); + + it('shows the demo curve only through today without remapping its future values', async () => { + vi.useFakeTimers(); + vi.setSystemTime(new Date('2026-08-23T00:00:00.000Z')); + + const project = { + id: 42, + targetGrade: 0, + unit: { + startDate: new Date('2026-07-12T00:00:00.000Z'), + endDate: new Date('2026-10-11T00:00:00.000Z'), + }, + } as unknown as Project; + + const response = await firstValueFrom(new PeerProgressService().getCohortMedian(project)); + const lastPoint = response.median_burndown.at(-1); + + expect(lastPoint).toEqual({ + date: '2026-08-23T00:00:00.000Z', + remaining: 0.58, + }); + expect(response.median_burndown.every((point) => new Date(point.date) <= new Date())).toBe( + true, + ); + expect(Math.round((1 - lastPoint!.remaining) * 100)).toBe(42); + expect(lastPoint?.remaining).not.toBe(0); + }); }); diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index f19cd9753b..837687865c 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -54,7 +54,9 @@
        - Demo peer median: anonymous aggregate sample data, not live cohort data. + + Demo peer median through today: anonymous aggregate sample data, not live cohort data. +
        } @else {
        From 02ac2e203a0a7410f37f6ae5f93f5a6b029f2231 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 07:24:02 +1000 Subject: [PATCH 1425/1531] fix(ppi): stop demo median at current date --- src/app/api/services/peer-progress.service.ts | 16 ++++++--- .../spec/peer-progress.service.spec.ts | 33 ++++++++++++++++++- .../progress-burndown-chart.component.html | 4 ++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/app/api/services/peer-progress.service.ts b/src/app/api/services/peer-progress.service.ts index 9183204be9..c4a37f601b 100644 --- a/src/app/api/services/peer-progress.service.ts +++ b/src/app/api/services/peer-progress.service.ts @@ -40,15 +40,23 @@ export class PeerProgressService { } private sampleProfile(project: Project, profile: number[]): PeerMedianPoint[] { + const asOf = Date.now(); const weeks = MappingFunctions.step( project.unit.startDate.getTime(), project.unit.endDate.getTime(), MappingFunctions.weeksMs(1), ); - return weeks.map((time, week) => ({ - date: new Date(time).toISOString(), - remaining: profile[Math.round((week / Math.max(weeks.length - 1, 1)) * (profile.length - 1))], - })); + // Map against the whole unit before removing future points. Mapping only + // the elapsed weeks would incorrectly stretch the sample to 100% complete + // at today's date and make the demo look like the cohort has finished every + // task. + return weeks + .map((time, week) => ({ + date: new Date(time).toISOString(), + remaining: + profile[Math.round((week / Math.max(weeks.length - 1, 1)) * (profile.length - 1))], + })) + .filter((point) => new Date(point.date).getTime() <= asOf); } } diff --git a/src/app/api/services/spec/peer-progress.service.spec.ts b/src/app/api/services/spec/peer-progress.service.spec.ts index 64fccf0687..c49b353dc7 100644 --- a/src/app/api/services/spec/peer-progress.service.spec.ts +++ b/src/app/api/services/spec/peer-progress.service.spec.ts @@ -1,9 +1,13 @@ -import {describe, expect, it} from 'vitest'; +import {afterEach, describe, expect, it, vi} from 'vitest'; import {firstValueFrom} from 'rxjs'; import {Project} from '../../models/project'; import {PeerProgressService} from '../peer-progress.service'; describe('PeerProgressService', () => { + afterEach(() => { + vi.useRealTimers(); + }); + it('returns a safe demo state without exposing raw cohort size', async () => { const project = { id: 42, @@ -32,4 +36,31 @@ describe('PeerProgressService', () => { response.median_burndown.every((point) => point.remaining >= 0 && point.remaining <= 1), ).toBe(true); }); + + it('shows the demo curve only through today without remapping its future values', async () => { + vi.useFakeTimers(); + vi.setSystemTime(new Date('2026-08-23T00:00:00.000Z')); + + const project = { + id: 42, + targetGrade: 0, + unit: { + startDate: new Date('2026-07-12T00:00:00.000Z'), + endDate: new Date('2026-10-11T00:00:00.000Z'), + }, + } as unknown as Project; + + const response = await firstValueFrom(new PeerProgressService().getCohortMedian(project)); + const lastPoint = response.median_burndown.at(-1); + + expect(lastPoint).toEqual({ + date: '2026-08-23T00:00:00.000Z', + remaining: 0.58, + }); + expect(response.median_burndown.every((point) => new Date(point.date) <= new Date())).toBe( + true, + ); + expect(Math.round((1 - lastPoint!.remaining) * 100)).toBe(42); + expect(lastPoint?.remaining).not.toBe(0); + }); }); diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index f19cd9753b..837687865c 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -54,7 +54,9 @@
        - Demo peer median: anonymous aggregate sample data, not live cohort data. + + Demo peer median through today: anonymous aggregate sample data, not live cohort data. +
        } @else {
        From 27f1012bf7cd01f81a4fe5725a3be545288a03cd Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 02:00:04 +1000 Subject: [PATCH 1426/1531] chore(toolchain): align nvm with Angular Node support --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 6276cf12fb..6bb900519d 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v16.14.2 +v22.22.3 From e513ca336a869beeb42bcfb510a84d76fee35b6a Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 01:35:26 +1000 Subject: [PATCH 1427/1531] test(ci): allow Angular suites time under load --- src/vitest-setup.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/vitest-setup.ts b/src/vitest-setup.ts index 9ee7140bc8..e2b9a2ab21 100644 --- a/src/vitest-setup.ts +++ b/src/vitest-setup.ts @@ -1 +1,10 @@ +import {vi} from 'vitest'; import 'zone.js/plugins/vitest-patch'; + +// The full Angular suite compiles and instantiates many large TestBed modules in +// parallel. Give those hooks enough headroom under CI load while keeping a +// finite timeout so genuine hangs still fail the run. +vi.setConfig({ + hookTimeout: 30_000, + testTimeout: 30_000, +}); From a4814bf2fb3047407fc12cb7fea1f8639fdcc65c Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 08:40:24 +1000 Subject: [PATCH 1428/1531] fix(deps): resolve inherited npm audit findings --- env.config.js | 14 +- package-lock.json | 525 +++++++++--------- package.json | 16 +- .../unit-task-list.component.spec.ts | 8 +- 4 files changed, 298 insertions(+), 265 deletions(-) diff --git a/env.config.js b/env.config.js index 60f507f0f5..cd7528500b 100644 --- a/env.config.js +++ b/env.config.js @@ -1,3 +1,15 @@ +const {networkInterfaces} = require('node:os'); + +function localIpv4Address() { + for (const addresses of Object.values(networkInterfaces())) { + const address = addresses?.find(({family, internal}) => family === 'IPv4' && !internal); + + if (address) return address.address; + } + + return '127.0.0.1'; +} + module.exports = { env: { options: { @@ -9,7 +21,7 @@ module.exports = { // Use the computer's IP address -- if using localhost then // testing on mobile devices will fail as it cannot point to // localhost (this would be the device itself!) - API_URL: 'http://' + require('ip').address() + ':3000/api', + API_URL: 'http://' + localIpv4Address() + ':3000/api', }, production: { diff --git a/package-lock.json b/package-lock.json index 121c278ad5..b196f0fe62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,7 @@ "canvas-confetti": "^1.9", "d3": "^7.9.0", "date-fns": "^4.4.0", - "dompurify": "^3.4.11", + "dompurify": "^3.4.14", "html2canvas": "^1.0.0-rc.7", "html5-qrcode": "^2.3.8", "jszip": "^3.10.1", @@ -47,7 +47,7 @@ "ng2-pdf-viewer": "10.4.0", "ngx-entity-service": "^0.0.44", "ngx-lottie": "^22.0.0", - "ngx-monaco-editor-v2-alternative": "^22.0.0", + "ngx-monaco-editor-v2-alternative": "22.0.0", "ngx-skeleton-loader": "^13.0.0", "qrcode": "^1.5.4", "rxjs": "~7.8.2", @@ -61,8 +61,8 @@ "@angular-eslint/eslint-plugin-template": "^22.0.0", "@angular-eslint/schematics": "^22.0.0", "@angular-eslint/template-parser": "^22.0.0", - "@angular/build": "^22.0.4", - "@angular/cli": "^22.0.4", + "@angular/build": "22.0.9", + "@angular/cli": "22.0.9", "@angular/compiler-cli": "^22.0.3", "@angular/language-service": "^22.0.3", "@commitlint/cli": "^21.1.0", @@ -76,13 +76,12 @@ "@typescript-eslint/parser": "^8.62.1", "angular-eslint": "^22.0.0", "autoprefixer": "^10.5.2", - "concurrently": "^10.0.3", + "concurrently": "^10.0.5", "eslint": "^10.6.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.5.6", "eslint-plugin-tailwindcss": "^4.0.4", "husky": "^9.1.7", - "ip": "^2.0.1", "jsdom": "^29.1.1", "npm-run-all2": "^9.0.2", "postcss": "^8.5.26", @@ -343,13 +342,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.2200.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2200.4.tgz", - "integrity": "sha512-X/iEQiZ0pRmpjUt11jCM+mtOLRl4XxI9hnM0IC9aAcsm5AzRBb9WY6QIEqOSficjxC/+MI7MGwrerrcP6QN8UA==", + "version": "0.2200.9", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2200.9.tgz", + "integrity": "sha512-kwiyEFfJsnJ4o7ondW8KswwJbp+qri5yWLS0wMMG+uBwOolZfrQReorqsQNCALhwmojhDNZc0wEWXEHEhKnotw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "22.0.4", + "@angular-devkit/core": "22.0.9", "rxjs": "7.8.2" }, "bin": { @@ -362,9 +361,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "22.0.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.0.4.tgz", - "integrity": "sha512-zA2UJSMAU3su5uJTOn5ul/gCLRcw6/uIQ6EC5v/Ju/ePjgDIw9R3y3MAvWQ4Ibi/fXiq0FVxpF8hE7RUclYmJA==", + "version": "22.0.9", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.0.9.tgz", + "integrity": "sha512-u53kltrh1ZKHSqGfEDbPW2RzSC1WBPpan3LN61TuzjAkiHqqaQXrN6EmUvYkX3CIT5PKhO6RPRsptMH9y7hs0w==", "dev": true, "license": "MIT", "dependencies": { @@ -390,13 +389,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "22.0.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-22.0.4.tgz", - "integrity": "sha512-VRxL1hD/Q3TQglM6EfQ0ksAW4OIvtKyZgtaUpyGsJRfD6tGmLFn7MDnmyyq1ceLX/Clq+3tzH/wN0tF6rcE0jA==", + "version": "22.0.9", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-22.0.9.tgz", + "integrity": "sha512-r7tPuiXI7pnwcaLQY4hQLOM9R5rkKRc1mKhQQb074Shh8XzTcTaw2ktDXLeiJm/SUUWQPhaxClnjjO3qU8AJRw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "22.0.4", + "@angular-devkit/core": "22.0.9", "jsonc-parser": "3.3.1", "magic-string": "0.30.21", "ora": "9.4.0", @@ -547,16 +546,16 @@ } }, "node_modules/@angular/build": { - "version": "22.0.4", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-22.0.4.tgz", - "integrity": "sha512-hst/KhP5mMPajY32l7qmyW/5fuqrMHCjHEeNhMMNqP82+j8jPBFfMEL26AH9w2kIIdKGpC3WKN5JgLotyFD7tQ==", + "version": "22.0.9", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-22.0.9.tgz", + "integrity": "sha512-j5eYaMTGFXdPVSX0xtWRRWHE2Ezz2CFiBPsAKrWHitvzccv95nURQYk5jbB+FHCYuN60zJNoTZMIlT7rXYAvag==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2200.4", - "@babel/core": "7.29.0", - "@babel/helper-annotate-as-pure": "7.27.3", + "@angular-devkit/architect": "0.2200.9", + "@babel/core": "7.29.7", + "@babel/helper-annotate-as-pure": "7.29.7", "@babel/helper-split-export-declaration": "7.24.7", "@inquirer/confirm": "6.0.12", "@vitejs/plugin-basic-ssl": "2.3.0", @@ -576,7 +575,7 @@ "semver": "7.7.4", "source-map-support": "0.5.21", "tinyglobby": "0.2.16", - "vite": "7.3.5", + "vite": "7.3.6", "watchpack": "2.5.1" }, "engines": { @@ -595,7 +594,7 @@ "@angular/platform-browser": "^22.0.0", "@angular/platform-server": "^22.0.0", "@angular/service-worker": "^22.0.0", - "@angular/ssr": "^22.0.4", + "@angular/ssr": "^22.0.9", "istanbul-lib-instrument": "^6.0.0", "karma": "^6.4.0", "less": "^4.2.0", @@ -1602,19 +1601,19 @@ } }, "node_modules/@angular/cli": { - "version": "22.0.4", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-22.0.4.tgz", - "integrity": "sha512-3eJy6VoNlgskKFzvqy3AJsYXFRhSBLLGObF2iTpJymsukuxWUen7hlVVVWrO5++bW1LEgd6PTCCD5fdT2UuRiA==", + "version": "22.0.9", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-22.0.9.tgz", + "integrity": "sha512-nkdz9sc9OjTLBG2QwPH8HuFc4fOl489AzrKInM2y+Q0u1+/HFt9QpSeupPnDJeOYGImDIP0B2VJJ3teDRM1DGg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.2200.4", - "@angular-devkit/core": "22.0.4", - "@angular-devkit/schematics": "22.0.4", + "@angular-devkit/architect": "0.2200.9", + "@angular-devkit/core": "22.0.9", + "@angular-devkit/schematics": "22.0.9", "@inquirer/prompts": "8.4.2", "@listr2/prompt-adapter-inquirer": "4.2.3", "@modelcontextprotocol/sdk": "1.29.0", - "@schematics/angular": "22.0.4", + "@schematics/angular": "22.0.9", "@yarnpkg/lockfile": "1.1.0", "algoliasearch": "5.52.0", "ini": "6.0.0", @@ -1697,54 +1696,6 @@ } } }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", - "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.7", - "@babel/helper-compilation-targets": "^7.29.7", - "@babel/helper-module-transforms": "^7.29.7", - "@babel/helpers": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/template": "^7.29.7", - "@babel/traverse": "^7.29.7", - "@babel/types": "^7.29.7", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@angular/core": { "version": "22.0.3", "resolved": "https://registry.npmjs.org/@angular/core/-/core-22.0.3.tgz", @@ -1986,21 +1937,21 @@ } }, "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -2051,13 +2002,13 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2728,9 +2679,9 @@ "peer": true }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ "ppc64" ], @@ -2745,9 +2696,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ "arm" ], @@ -2762,9 +2713,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", "cpu": [ "arm64" ], @@ -2779,9 +2730,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", "cpu": [ "x64" ], @@ -2796,9 +2747,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", "cpu": [ "arm64" ], @@ -2813,9 +2764,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", "cpu": [ "x64" ], @@ -2830,9 +2781,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", "cpu": [ "arm64" ], @@ -2847,9 +2798,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", "cpu": [ "x64" ], @@ -2864,9 +2815,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", "cpu": [ "arm" ], @@ -2881,9 +2832,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", "cpu": [ "arm64" ], @@ -2898,9 +2849,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", "cpu": [ "ia32" ], @@ -2915,9 +2866,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", "cpu": [ "loong64" ], @@ -2932,9 +2883,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", "cpu": [ "mips64el" ], @@ -2949,9 +2900,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", "cpu": [ "ppc64" ], @@ -2966,9 +2917,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", "cpu": [ "riscv64" ], @@ -2983,9 +2934,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", "cpu": [ "s390x" ], @@ -3000,9 +2951,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", "cpu": [ "x64" ], @@ -3017,9 +2968,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", "cpu": [ "arm64" ], @@ -3034,9 +2985,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", "cpu": [ "x64" ], @@ -3051,9 +3002,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", "cpu": [ "arm64" ], @@ -3068,9 +3019,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", "cpu": [ "x64" ], @@ -3085,9 +3036,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", "cpu": [ "arm64" ], @@ -3102,9 +3053,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", "cpu": [ "x64" ], @@ -3119,9 +3070,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", "cpu": [ "arm64" ], @@ -3136,9 +3087,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", "cpu": [ "ia32" ], @@ -3153,9 +3104,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", "cpu": [ "x64" ], @@ -3200,6 +3151,7 @@ "version": "0.23.5", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^3.0.5", @@ -3214,6 +3166,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, "license": "MIT", "engines": { "node": "18 || 20 || >=22" @@ -3223,6 +3176,7 @@ "version": "5.0.9", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -3235,6 +3189,7 @@ "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.5" @@ -3250,6 +3205,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz", "integrity": "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/core": "^1.2.1" @@ -3262,6 +3218,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -3294,6 +3251,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" @@ -3303,6 +3261,7 @@ "version": "0.7.2", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/core": "^1.2.1", @@ -3349,9 +3308,9 @@ "optional": true }, "node_modules/@hono/node-server": { - "version": "1.19.14", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", - "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", + "version": "1.19.17", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.17.tgz", + "integrity": "sha512-dSneS5qhiauZWGDCeK4o695Xd9nUNjviSZCMQrj10eetr8Uln1ucn6bbphOM6UynAMMtNIzZNSpL9vnASJwrPQ==", "dev": true, "license": "MIT", "engines": { @@ -3365,6 +3324,7 @@ "version": "0.19.2", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@humanfs/types": "^0.15.0" @@ -3377,6 +3337,7 @@ "version": "0.16.8", "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.2", @@ -3391,6 +3352,7 @@ "version": "0.15.0", "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18.0" @@ -3400,6 +3362,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.22" @@ -3413,6 +3376,7 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18" @@ -5457,14 +5421,14 @@ "license": "Apache-2.0" }, "node_modules/@schematics/angular": { - "version": "22.0.4", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-22.0.4.tgz", - "integrity": "sha512-P3V3tkqIR+n0GJSv0ibf34/zMtKbFp6kaTjBe5cm/RyXuHbmdaPYjk8PNphkGMypDtWCof1RtNnW/hl832Wnew==", + "version": "22.0.9", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-22.0.9.tgz", + "integrity": "sha512-moQI3UnqUt6GZ81ykxJRUbf+IpM6SDFRyMMj6A2VNSiUGVpSAETNFIuTk/6YDzNG8yhMN9zOICeBwvvPH0ylbA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "22.0.4", - "@angular-devkit/schematics": "22.0.4", + "@angular-devkit/core": "22.0.9", + "@angular-devkit/schematics": "22.0.9", "jsonc-parser": "3.3.1", "typescript": "6.0.3" }, @@ -6674,12 +6638,14 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, "license": "MIT" }, "node_modules/@types/geojson": { @@ -6693,6 +6659,7 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, "license": "MIT" }, "node_modules/@types/node": { @@ -6744,6 +6711,7 @@ "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.62.1.tgz", "integrity": "sha512-sPhE4iHuJDSvoAiec+Ro8JyXw8f0ql13HFR82P99nCm9GwTEKG0KYLvDe6REk8BCXuit6vJAv/Yxg5ABaNS2rA==", + "dev": true, "license": "MIT", "dependencies": { "@typescript-eslint/scope-manager": "8.62.1", @@ -6768,6 +6736,7 @@ "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.62.1.tgz", "integrity": "sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==", + "dev": true, "license": "MIT", "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.62.1", @@ -6789,6 +6758,7 @@ "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.62.1.tgz", "integrity": "sha512-r4d249KbQ1SFdpeStvob8Ih6aPPIzfqllPVOtvhve6ZcpuVcYo5/7zUWckKpHE7StASX4kTKZTLf0WQm/wPkcg==", + "dev": true, "license": "MIT", "dependencies": { "@typescript-eslint/types": "8.62.1", @@ -6806,6 +6776,7 @@ "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.1.tgz", "integrity": "sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==", + "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6822,6 +6793,7 @@ "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.1.tgz", "integrity": "sha512-ooCzJFaf+Hg+uG6fA3NRFGuFjlfNlDhBthbv4ZPU/0elCAFUfnyXUvf/WOpHz/jYwSmvU2GkR2LtyUfy1AxZ1Q==", + "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6835,6 +6807,7 @@ "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.1.tgz", "integrity": "sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==", + "dev": true, "license": "MIT", "dependencies": { "@typescript-eslint/project-service": "8.62.1", @@ -6862,6 +6835,7 @@ "version": "8.62.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.62.1.tgz", "integrity": "sha512-4g3BLxfdTMy8iZG0MaBkadnlRrCJ74cQiFbyEVMrkwIoqdyaXXQM22cotDvrl4x28wgIZ9rEJRoM+mmhSJpJ1g==", + "dev": true, "license": "MIT", "dependencies": { "@typescript-eslint/types": "8.62.1", @@ -6879,6 +6853,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, "license": "MIT", "engines": { "node": "18 || 20 || >=22" @@ -6888,6 +6863,7 @@ "version": "5.0.9", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -6900,6 +6876,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" @@ -6912,6 +6889,7 @@ "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.5" @@ -7314,6 +7292,7 @@ "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -7326,6 +7305,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -8287,15 +8267,15 @@ } }, "node_modules/concurrently": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-10.0.3.tgz", - "integrity": "sha512-hc3LH4UaKWd/bbyDK/IGVa4RB6PtQ3CUYwtrkzqHn+wIG3Hr5fhpRlk0L/gCa8ZE1L/Ufj50Zho69cI5w8SQBA==", + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-10.0.5.tgz", + "integrity": "sha512-JaP/CoftUrCcAFW/g//RbgEGwlelnEae6cfBLgH6ZdO6s8jPkn6p9SB9u6pdVxYXoiSnFqseOlHfrEfF82TVOg==", "dev": true, "license": "MIT", "dependencies": { "chalk": "5.6.2", "rxjs": "7.8.2", - "shell-quote": "1.8.4", + "shell-quote": "1.9.0", "supports-color": "10.2.2", "tree-kill": "1.2.2", "yargs": "18.0.0" @@ -8492,6 +8472,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -9141,6 +9122,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, "license": "MIT" }, "node_modules/delaunator": { @@ -9232,9 +9214,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.11", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.11.tgz", - "integrity": "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.14.tgz", + "integrity": "sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -9435,9 +9417,9 @@ ] }, "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -9448,32 +9430,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" } }, "node_modules/escalade": { @@ -9497,6 +9479,7 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.6.0.tgz", "integrity": "sha512-6lVbcqSodALYo+4ELD0heG6lFiFxnLMuLkiMi2qV8LMp54N8tE8FT1GMH+ev4Ti00nFjNze2+Su6DsV5OQW3Dg==", + "dev": true, "license": "MIT", "workspaces": [ "packages/*" @@ -9627,6 +9610,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "@types/esrecurse": "^4.3.1", @@ -9657,6 +9641,7 @@ "version": "6.15.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -9673,6 +9658,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, "license": "MIT", "engines": { "node": "18 || 20 || >=22" @@ -9682,6 +9668,7 @@ "version": "5.0.9", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -9694,6 +9681,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -9706,6 +9694,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" @@ -9718,6 +9707,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -9727,12 +9717,14 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, "license": "MIT" }, "node_modules/eslint/node_modules/minimatch": { "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.5" @@ -9748,6 +9740,7 @@ "version": "11.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.16.0", @@ -9765,6 +9758,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" @@ -9777,6 +9771,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" @@ -9789,6 +9784,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" @@ -9801,6 +9797,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -9820,6 +9817,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -9959,6 +9957,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, "license": "MIT" }, "node_modules/fast-diff": { @@ -9972,12 +9971,14 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, "license": "MIT" }, "node_modules/fast-string-truncated-width": { @@ -10045,6 +10046,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" @@ -10079,6 +10081,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "license": "MIT", "dependencies": { "locate-path": "^6.0.0", @@ -10095,6 +10098,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", @@ -10108,6 +10112,7 @@ "version": "3.4.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, "license": "ISC" }, "node_modules/forwarded": { @@ -10288,6 +10293,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -10365,9 +10371,9 @@ } }, "node_modules/hono": { - "version": "4.12.26", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.26.tgz", - "integrity": "sha512-uyZtpnYxM9CmQ7QsQknM4zN8EftNqhON1qYeIKM0Se67CCEe2c44xyGURwB0axX2fBDu1dqHrHAc1hmNT8ITkw==", + "version": "4.13.3", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.3.tgz", + "integrity": "sha512-r8AO2mYHoLxSHkgafNeC/BXyb2vWRxD3jem4Ts+ptav8oTG5FIRifAjuJEmZI4bSvvc2ns0GxmIYiZnHqN3mMw==", "dev": true, "license": "MIT", "engines": { @@ -10649,9 +10655,9 @@ "license": "MIT" }, "node_modules/immutable": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.6.tgz", - "integrity": "sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.9.tgz", + "integrity": "sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==", "dev": true, "license": "MIT" }, @@ -10686,6 +10692,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -10716,13 +10723,6 @@ "node": ">=12" } }, - "node_modules/ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "dev": true, - "license": "MIT" - }, "node_modules/ip-address": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.5.0.tgz", @@ -10754,6 +10754,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10779,6 +10780,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -10873,7 +10875,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -10984,9 +10986,9 @@ } }, "node_modules/jsdom/node_modules/undici": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", - "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", "dev": true, "license": "MIT", "engines": { @@ -11010,6 +11012,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { @@ -11040,6 +11043,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, "license": "MIT" }, "node_modules/json5": { @@ -11088,6 +11092,7 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" @@ -11097,6 +11102,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", @@ -11477,6 +11483,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "license": "MIT", "dependencies": { "p-locate": "^5.0.0" @@ -12005,15 +12012,6 @@ "marked": "14.0.0" } }, - "node_modules/monaco-editor/node_modules/dompurify": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", - "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, "node_modules/monaco-editor/node_modules/marked": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", @@ -12581,6 +12579,7 @@ "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, "license": "MIT", "dependencies": { "deep-is": "^0.1.3", @@ -12629,6 +12628,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -12644,6 +12644,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "license": "MIT", "dependencies": { "p-limit": "^3.0.2" @@ -12859,6 +12860,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -13181,6 +13183,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" @@ -13895,6 +13898,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -13907,15 +13911,16 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shell-quote": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz", - "integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.9.0.tgz", + "integrity": "sha512-Iov+JwFv/2HcTpcwNMKd8+IWNb8tboQJNQTkAY/LLVK7gGH9jy+LGkVqPxfekHl+yMmiqXszdGWXgkfml7hjqA==", "dev": true, "license": "MIT", "engines": { @@ -14411,9 +14416,9 @@ } }, "node_modules/tar": { - "version": "7.5.16", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz", - "integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==", + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -14696,6 +14701,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" @@ -14741,6 +14747,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -14805,9 +14812,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "6.27.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz", - "integrity": "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", "license": "MIT", "engines": { "node": ">=18.17" @@ -14865,6 +14872,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -14874,6 +14882,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -14913,13 +14922,13 @@ } }, "node_modules/vite": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.5.tgz", - "integrity": "sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", + "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", @@ -15189,6 +15198,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -15393,6 +15403,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" diff --git a/package.json b/package.json index b3b4d379dc..439817c39b 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "canvas-confetti": "^1.9", "d3": "^7.9.0", "date-fns": "^4.4.0", - "dompurify": "^3.4.11", + "dompurify": "^3.4.14", "html2canvas": "^1.0.0-rc.7", "html5-qrcode": "^2.3.8", "jszip": "^3.10.1", @@ -66,7 +66,7 @@ "ng2-pdf-viewer": "10.4.0", "ngx-entity-service": "^0.0.44", "ngx-lottie": "^22.0.0", - "ngx-monaco-editor-v2-alternative": "^22.0.0", + "ngx-monaco-editor-v2-alternative": "22.0.0", "ngx-skeleton-loader": "^13.0.0", "qrcode": "^1.5.4", "rxjs": "~7.8.2", @@ -80,8 +80,8 @@ "@angular-eslint/eslint-plugin-template": "^22.0.0", "@angular-eslint/schematics": "^22.0.0", "@angular-eslint/template-parser": "^22.0.0", - "@angular/build": "^22.0.4", - "@angular/cli": "^22.0.4", + "@angular/build": "22.0.9", + "@angular/cli": "22.0.9", "@angular/compiler-cli": "^22.0.3", "@angular/language-service": "^22.0.3", "@commitlint/cli": "^21.1.0", @@ -95,13 +95,12 @@ "@typescript-eslint/parser": "^8.62.1", "angular-eslint": "^22.0.0", "autoprefixer": "^10.5.2", - "concurrently": "^10.0.3", + "concurrently": "^10.0.5", "eslint": "^10.6.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.5.6", "eslint-plugin-tailwindcss": "^4.0.4", "husky": "^9.1.7", - "ip": "^2.0.1", "jsdom": "^29.1.1", "npm-run-all2": "^9.0.2", "postcss": "^8.5.26", @@ -121,5 +120,10 @@ "@nx/nx-win32-x64-msvc": "^23.0.1", "@rollup/rollup-linux-arm64-gnu": "^4.62.2", "@rollup/rollup-linux-x64-gnu": "^4.62.2" + }, + "overrides": { + "monaco-editor": { + "dompurify": "3.4.14" + } } } diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts index dad93b4165..9685a3ac6b 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts @@ -1,4 +1,4 @@ -import {beforeEach, describe, expect, it} from 'vitest'; +import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'; import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {ActivatedRoute, Router} from '@angular/router'; @@ -44,10 +44,16 @@ describe('FUnitTaskListComponent', () => { }); beforeEach(() => { + vi.stubGlobal('localStorage', { + getItem: vi.fn(() => null), + setItem: vi.fn(), + }); fixture = TestBed.createComponent(FUnitTaskListComponent); component = fixture.componentInstance; }); + afterEach(() => vi.unstubAllGlobals()); + it('should create', () => { expect(component).toBeTruthy(); }); From 0abb1ce00398743fca631eb81b9ad1b96905affa Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 11:36:26 +1000 Subject: [PATCH 1429/1531] fix(cpd): align recommendation lifecycle --- .../spec/task-recommendation.service.spec.ts | 71 ++++++++ .../services/task-recommendation.service.ts | 53 ++++++ .../f-cross-dashboard.component.spec.ts | 163 +++++++++++++++++- .../dashboard/f-cross-dashboard.component.ts | 107 ++++++++++-- .../dashboard/f-cross-dashboard.route.spec.ts | 12 +- .../dashboard-list-item.component.spec.ts | 2 + .../dashboard-list-item.component.ts | 1 + 7 files changed, 391 insertions(+), 18 deletions(-) create mode 100644 src/app/api/services/spec/task-recommendation.service.spec.ts create mode 100644 src/app/api/services/task-recommendation.service.ts diff --git a/src/app/api/services/spec/task-recommendation.service.spec.ts b/src/app/api/services/spec/task-recommendation.service.spec.ts new file mode 100644 index 0000000000..cf1d4dde8d --- /dev/null +++ b/src/app/api/services/spec/task-recommendation.service.spec.ts @@ -0,0 +1,71 @@ +import {provideHttpClient, withInterceptorsFromDi, withXhr} from '@angular/common/http'; +import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; +import {TestBed} from '@angular/core/testing'; +import API_URL from 'src/app/config/constants/apiUrl'; +import {TaskRecommendation, TaskRecommendationService} from '../task-recommendation.service'; + +describe('TaskRecommendationService', () => { + let httpTestingController: HttpTestingController; + let service: TaskRecommendationService; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + TaskRecommendationService, + provideHttpClient(withXhr(), withInterceptorsFromDi()), + provideHttpClientTesting(), + ], + }); + + httpTestingController = TestBed.inject(HttpTestingController); + service = TestBed.inject(TaskRecommendationService); + }); + + afterEach(() => { + httpTestingController.verify(); + }); + + it('loads and combines every recommendation page', () => { + let recommendations: TaskRecommendation[] | undefined; + + service.getAll().subscribe((result) => { + recommendations = result; + }); + + const firstRequest = httpTestingController.expectOne( + (request) => + request.url === `${API_URL}/tasks/recommended` && + request.params.get('page') === '1' && + request.params.get('per_page') === '50', + ); + firstRequest.flush({ + data: [makeRecommendation(1, 80)], + meta: {page: 1, per_page: 50, total_count: 2, total_pages: 2}, + }); + + const secondRequest = httpTestingController.expectOne( + (request) => + request.url === `${API_URL}/tasks/recommended` && + request.params.get('page') === '2' && + request.params.get('per_page') === '50', + ); + secondRequest.flush({ + data: [makeRecommendation(2, 60)], + meta: {page: 2, per_page: 50, total_count: 2, total_pages: 2}, + }); + + expect(recommendations).toEqual([makeRecommendation(1, 80), makeRecommendation(2, 60)]); + }); + + const makeRecommendation = ( + taskDefinitionId: number, + priorityScore: number, + ): TaskRecommendation => ({ + task_id: null, + task_definition_id: taskDefinitionId, + task_name: `Task ${taskDefinitionId}`, + project_id: 10, + unit_id: 20, + priority_score: priorityScore, + }); +}); diff --git a/src/app/api/services/task-recommendation.service.ts b/src/app/api/services/task-recommendation.service.ts new file mode 100644 index 0000000000..475a990f66 --- /dev/null +++ b/src/app/api/services/task-recommendation.service.ts @@ -0,0 +1,53 @@ +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {EMPTY, Observable, expand, reduce} from 'rxjs'; +import API_URL from 'src/app/config/constants/apiUrl'; + +export type TaskRecommendation = { + task_id: number | null; + task_definition_id: number; + task_name: string; + project_id: number; + unit_id: number; + priority_score: number; +}; + +export type TaskRecommendationPage = { + data: TaskRecommendation[]; + meta: { + page: number; + per_page: number; + total_count: number; + total_pages: number; + }; +}; + +@Injectable({providedIn: 'root'}) +export class TaskRecommendationService { + private static readonly PAGE_SIZE = 50; + + constructor(private httpClient: HttpClient) {} + + getAll(): Observable { + return this.getPage(1).pipe( + expand((response) => + response.meta.page < response.meta.total_pages + ? this.getPage(response.meta.page + 1) + : EMPTY, + ), + reduce( + (recommendations, response) => recommendations.concat(response.data), + [] as TaskRecommendation[], + ), + ); + } + + private getPage(page: number): Observable { + return this.httpClient.get(`${API_URL}/tasks/recommended`, { + params: { + page, + per_page: TaskRecommendationService.PAGE_SIZE, + }, + }); + } +} diff --git a/src/app/dashboard/f-cross-dashboard.component.spec.ts b/src/app/dashboard/f-cross-dashboard.component.spec.ts index 257179892a..c89303d80a 100644 --- a/src/app/dashboard/f-cross-dashboard.component.spec.ts +++ b/src/app/dashboard/f-cross-dashboard.component.spec.ts @@ -11,12 +11,17 @@ import {MatMenuModule} from '@angular/material/menu'; import {MatSelectModule} from '@angular/material/select'; import {MatSelectHarness} from '@angular/material/select/testing'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; -import {BehaviorSubject, of, throwError} from 'rxjs'; +import {BehaviorSubject, Observable, ReplaySubject, Subject, of, throwError} from 'rxjs'; import {Grade} from '../api/models/grade'; import {Project} from '../api/models/project'; import {Task} from '../api/models/task'; import {TaskStatus, TaskStatusEnum} from '../api/models/task-status'; import {ProjectService} from '../api/services/project.service'; +import { + TaskRecommendation, + TaskRecommendationService, +} from '../api/services/task-recommendation.service'; +import {TaskService} from '../api/services/task.service'; import {GlobalStateService} from '../projects/states/index/global-state.service'; import {CrossDashboardComponent} from './f-cross-dashboard.component'; @@ -25,6 +30,10 @@ describe('CrossDashboardComponent', () => { let fixture: ComponentFixture; let projectsSubject: BehaviorSubject; let projectServiceQuery: ReturnType; + let recommendationsSubject: ReplaySubject; + let recommendationServiceGetAll: ReturnType; + let taskStatusSubject: Subject; + let nextTaskDefinitionId: number; const syncView = async (): Promise => { fixture.detectChanges(); @@ -50,6 +59,7 @@ describe('CrossDashboardComponent', () => { localDueDate: vi.fn().mockReturnValue(dueDate), inSubmittedState: vi.fn().mockReturnValue(TaskStatus.SUBMITTED_STATUSES.includes(status)), definition: { + id: nextTaskDefinitionId++, name, abbreviation, targetGrade, @@ -65,8 +75,8 @@ describe('CrossDashboardComponent', () => { isActive: boolean, tasks: Task[] = [], name: string = `${code} Unit`, - ): Project => - ({ + ): Project => { + const project = { id, tasks, unit: { @@ -77,16 +87,28 @@ describe('CrossDashboardComponent', () => { }, calcTopTasks: vi.fn(), activeTasks: vi.fn().mockReturnValue(tasks), - }) as unknown as Project; + } as unknown as Project; + + tasks.forEach((task) => (task.project = project)); + return project; + }; beforeEach(async () => { projectsSubject = new BehaviorSubject([]); projectServiceQuery = vi.fn().mockReturnValue(of([])); + recommendationsSubject = new ReplaySubject(1); + recommendationsSubject.next([]); + recommendationServiceGetAll = vi.fn().mockReturnValue(recommendationsSubject.asObservable()); + taskStatusSubject = new Subject(); + nextTaskDefinitionId = 100; const globalStateServiceStub = { onLoad: (callback: () => void): void => callback(), currentUserProjects: { values: projectsSubject.asObservable(), + get currentValues(): Project[] { + return projectsSubject.value; + }, }, }; @@ -114,6 +136,14 @@ describe('CrossDashboardComponent', () => { provide: ProjectService, useValue: projectServiceStub, }, + { + provide: TaskRecommendationService, + useValue: {getAll: recommendationServiceGetAll}, + }, + { + provide: TaskService, + useValue: {taskStatusUpdated$: taskStatusSubject.asObservable()}, + }, ], schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); @@ -125,6 +155,17 @@ describe('CrossDashboardComponent', () => { afterEach(() => { projectsSubject.complete(); + recommendationsSubject.complete(); + taskStatusSubject.complete(); + }); + + const recommendationFor = (task: Task, projectId: number, score: number): TaskRecommendation => ({ + task_id: null, + task_definition_id: task.definition.id, + task_name: task.definition.name, + project_id: projectId, + unit_id: 20, + priority_score: score, }); it('uses Active units as the default scope', () => { @@ -445,18 +486,126 @@ describe('CrossDashboardComponent', () => { ]); }); - it('keeps completed tasks below open tasks in every sort mode', () => { + it('sorts recommendations by project and task-definition id, including virtual tasks', () => { + const lowerPriority = makeTask('Lower priority', 'LOW', 'not_started', makeDate(10), 1); + const recommended = makeTask('Recommended next', 'NEXT', 'not_started', makeDate(20), 4); + const project = makeProject(7, 'DEMO20007', true, [lowerPriority, recommended]); + + projectsSubject.next([project]); + recommendationsSubject.next([recommendationFor(recommended, project.id, 95)]); + + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + 'NEXT', + 'LOW', + ]); + }); + + it('refreshes recommendations after a status change in an active project', async () => { + const task = makeTask('Current task', 'CURRENT', 'working_on_it', makeDate(10)); + const project = makeProject(7, 'DEMO20007', true, [task]); + + projectsSubject.next([project]); + const callsBeforeStatusChange = recommendationServiceGetAll.mock.calls.length; + taskStatusSubject.next(task); + + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(recommendationServiceGetAll).toHaveBeenCalledTimes(callsBeforeStatusChange + 1); + }); + + it('refreshes recommendation scores whenever the active project cache changes', () => { + const callsBeforeProjectChanges = recommendationServiceGetAll.mock.calls.length; + + projectsSubject.next([makeProject(1, 'COS10001', true)]); + projectsSubject.next([makeProject(1, 'COS10001', true), makeProject(2, 'COS30046', true)]); + + expect(recommendationServiceGetAll).toHaveBeenCalledTimes(callsBeforeProjectChanges + 2); + }); + + it('does not refresh recommendations for task changes in an inactive project', async () => { + const task = makeTask('Previous task', 'PREVIOUS', 'working_on_it', makeDate(10)); + const project = makeProject(8, 'COS30046', false, [task]); + + projectsSubject.next([project]); + const callsBeforeStatusChange = recommendationServiceGetAll.mock.calls.length; + taskStatusSubject.next(task); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(recommendationServiceGetAll).toHaveBeenCalledTimes(callsBeforeStatusChange); + }); + + it('cancels a recommendation request superseded by a newer project snapshot', () => { + const cancelled = vi.fn(); + const pendingRequest: Observable = new Observable(() => cancelled); + + recommendationServiceGetAll.mockImplementationOnce(() => pendingRequest); + recommendationServiceGetAll.mockImplementation(() => of([])); + + projectsSubject.next([makeProject(1, 'COS10001', true)]); + expect(cancelled).not.toHaveBeenCalled(); + + projectsSubject.next([makeProject(1, 'COS10001', true), makeProject(2, 'COS20007', true)]); + + expect(cancelled).toHaveBeenCalledOnce(); + }); + + it('retries after a recommendation error on the next active task status change', async () => { + const lowerPriority = makeTask('Lower priority', 'LOW', 'working_on_it', makeDate(10), 0); + const higherPriority = makeTask('Higher priority', 'HIGH', 'working_on_it', makeDate(20), 5); + const project = makeProject(1, 'COS10001', true, [lowerPriority, higherPriority]); + + recommendationServiceGetAll.mockImplementationOnce(() => + throwError(() => new Error('Recommendations unavailable')), + ); + recommendationServiceGetAll.mockImplementation(() => + of([ + recommendationFor(lowerPriority, project.id, 25), + recommendationFor(higherPriority, project.id, 90), + ]), + ); + + projectsSubject.next([project]); + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + 'LOW', + 'HIGH', + ]); + + taskStatusSubject.next(lowerPriority); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(component.displayedUnits[0].tasks.map((task) => task.abbreviation)).toEqual([ + 'HIGH', + 'LOW', + ]); + }); + + it('stops project and task-status refreshes after destruction', async () => { + const task = makeTask('Current task', 'CURRENT', 'working_on_it', makeDate(10)); + const project = makeProject(1, 'COS10001', true, [task]); + + projectsSubject.next([project]); + const callsBeforeDestruction = recommendationServiceGetAll.mock.calls.length; + fixture.destroy(); + + projectsSubject.next([project, makeProject(2, 'COS20007', true)]); + taskStatusSubject.next(task); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(recommendationServiceGetAll).toHaveBeenCalledTimes(callsBeforeDestruction); + }); + + it('keeps final-state tasks below open tasks in every sort mode', () => { projectsSubject.next([ makeProject(1, 'SIT764', true, [ makeTask('Completed First', 'DONE-FIRST', 'complete', makeDate(3), 0), makeTask('Open Later', 'OPEN-LATE', 'not_started', makeDate(20), 4), - makeTask('Completed Later', 'DONE-LATE', 'complete', makeDate(25), 5), + makeTask('Final Later', 'DONE-LATE', 'fail', makeDate(25), 5), makeTask('Open Earlier', 'OPEN-EARLY', 'working_on_it', makeDate(10), 1), ]), ]); const expectedByMode: Record = { - Recommended: ['OPEN-LATE', 'OPEN-EARLY', 'DONE-FIRST', 'DONE-LATE'], + Recommended: ['OPEN-EARLY', 'OPEN-LATE', 'DONE-FIRST', 'DONE-LATE'], 'Due Date': ['OPEN-EARLY', 'OPEN-LATE', 'DONE-FIRST', 'DONE-LATE'], Default: ['OPEN-EARLY', 'OPEN-LATE', 'DONE-FIRST', 'DONE-LATE'], }; diff --git a/src/app/dashboard/f-cross-dashboard.component.ts b/src/app/dashboard/f-cross-dashboard.component.ts index ebabfef7c5..42b0626620 100644 --- a/src/app/dashboard/f-cross-dashboard.component.ts +++ b/src/app/dashboard/f-cross-dashboard.component.ts @@ -1,11 +1,24 @@ import {EntityCache} from 'ngx-entity-service'; -import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit} from '@angular/core'; +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + DestroyRef, + OnInit, +} from '@angular/core'; +import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; +import {catchError, debounceTime, filter, map, merge, of, switchMap, tap} from 'rxjs'; import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; import {Grade} from '../api/models/grade'; import {Project} from '../api/models/project'; import {Task} from '../api/models/task'; import {TaskStatus, TaskStatusEnum} from '../api/models/task-status'; import {ProjectService} from '../api/services/project.service'; +import { + TaskRecommendation, + TaskRecommendationService, +} from '../api/services/task-recommendation.service'; +import {TaskService} from '../api/services/task.service'; import {DashboardTask} from './list-item/dashboard-list-item.component'; type UnitScope = 'active' | 'previous' | 'all'; @@ -21,6 +34,7 @@ enum SortMode { } const completedTypes: readonly TaskStatusEnum[] = ['complete']; +const finalTypes: readonly TaskStatusEnum[] = TaskStatus.FINAL_STATUSES; const displayedDueDateFormatter = new Intl.DateTimeFormat('en-AU', { weekday: 'long', @@ -85,23 +99,58 @@ export class CrossDashboardComponent implements OnInit { private filters: Map = new Map(); private sorting: Map = new Map(); private searchTerms: Map = new Map(); + private recommendationScores: Map = new Map(); constructor( private globalStateService: GlobalStateService, private projectService: ProjectService, + private taskRecommendationService: TaskRecommendationService, + private taskService: TaskService, private changeDetectorRef: ChangeDetectorRef, + private destroyRef: DestroyRef, ) {} ngOnInit(): void { this.globalStateService.onLoad(() => { - this.globalStateService.currentUserProjects.values.subscribe((projects) => { - const activeProjects = projects.filter((project) => project.unit.isActive); - this.activeUnits = this.mapProjects(activeProjects); - this.processTasks(); - }); + const projectChanges = this.globalStateService.currentUserProjects.values.pipe( + tap((projects) => this.refreshActiveUnits(projects)), + map(() => undefined), + ); + const activeTaskStatusChanges = this.taskService.taskStatusUpdated$.pipe( + filter((task) => this.isTaskInActiveProject(task)), + debounceTime(0), + tap(() => + this.refreshActiveUnits(this.globalStateService.currentUserProjects.currentValues), + ), + map(() => undefined), + ); + + merge(projectChanges, activeTaskStatusChanges) + .pipe( + switchMap(() => this.taskRecommendationService.getAll().pipe(catchError(() => of([])))), + takeUntilDestroyed(this.destroyRef), + ) + .subscribe((recommendations) => { + this.setRecommendationScores(recommendations); + this.processTasks(); + }); }); } + private refreshActiveUnits(projects: readonly Project[]): void { + const activeProjects = projects.filter((project) => project.unit.isActive); + this.activeUnits = this.mapProjects(activeProjects); + this.processTasks(); + } + + private isTaskInActiveProject(task: Task): boolean { + const projectId = task.project?.id; + + return this.globalStateService.currentUserProjects.currentValues.some( + (project) => project.id === projectId && project.unit.isActive, + ); + } + get displayedUnits(): DashboardUnit[] { return this.unitsProcessed; } @@ -296,18 +345,17 @@ export class CrossDashboardComponent implements OnInit { .sort((a, b) => { const sort = this.sorting.get(unit.projectId) ?? SortMode.Recommended; - if (completedTypes.includes(a.status) && !completedTypes.includes(b.status)) { + if (finalTypes.includes(a.status) && !finalTypes.includes(b.status)) { return 1; } - if (!completedTypes.includes(a.status) && completedTypes.includes(b.status)) { + if (!finalTypes.includes(a.status) && finalTypes.includes(b.status)) { return -1; } switch (sort) { case SortMode.Recommended: - // TODO: Connect to recommender's points. - return 0; + return this.compareRecommendations(a, b); case SortMode.SubmissionDate: return this.compareDueDates(a.dueDate, b.dueDate); case SortMode.Default: @@ -321,6 +369,44 @@ export class CrossDashboardComponent implements OnInit { this.changeDetectorRef.markForCheck(); } + private setRecommendationScores(recommendations: readonly TaskRecommendation[]): void { + this.recommendationScores = new Map( + recommendations + .filter((recommendation) => Number.isFinite(recommendation.priority_score)) + .map((recommendation) => [ + this.recommendationKey(recommendation.project_id, recommendation.task_definition_id), + recommendation.priority_score, + ]), + ); + } + + private compareRecommendations(first: DashboardTask, second: DashboardTask): number { + const firstScore = this.recommendationScores.get( + this.recommendationKey(first.projectId, first.taskDefinitionId), + ); + const secondScore = this.recommendationScores.get( + this.recommendationKey(second.projectId, second.taskDefinitionId), + ); + + if (firstScore !== undefined && secondScore !== undefined) { + return secondScore - firstScore || first.weight - second.weight; + } + + if (firstScore !== undefined) { + return -1; + } + + if (secondScore !== undefined) { + return 1; + } + + return first.weight - second.weight; + } + + private recommendationKey(projectId: number, taskDefinitionId: number): string { + return `${projectId}:${taskDefinitionId}`; + } + private taskMatchesGlobalCriteria(task: DashboardTask, unit: DashboardUnit): boolean { const matchesStatus = this.selectedStatuses.length === 0 || this.selectedStatuses.includes(task.status); @@ -547,6 +633,7 @@ export class CrossDashboardComponent implements OnInit { const def = task.definition; return { + taskDefinitionId: def.id, title: def.name, subtitle: `${def.abbreviation} - ${def.targetGradeText} Task`, statusLabel: TaskStatus.STATUS_LABELS.get(task.status), diff --git a/src/app/dashboard/f-cross-dashboard.route.spec.ts b/src/app/dashboard/f-cross-dashboard.route.spec.ts index eda2482605..6804789525 100644 --- a/src/app/dashboard/f-cross-dashboard.route.spec.ts +++ b/src/app/dashboard/f-cross-dashboard.route.spec.ts @@ -2,9 +2,11 @@ import {beforeEach, describe, expect, it, vi} from 'vitest'; import {TestBed} from '@angular/core/testing'; import {Router, provideRouter} from '@angular/router'; import {RouterTestingHarness} from '@angular/router/testing'; -import {BehaviorSubject, of} from 'rxjs'; +import {BehaviorSubject, EMPTY, of} from 'rxjs'; import {AuthenticationService} from '../api/services/authentication.service'; import {ProjectService} from '../api/services/project.service'; +import {TaskRecommendationService} from '../api/services/task-recommendation.service'; +import {TaskService} from '../api/services/task.service'; import {UserService} from '../api/services/user.service'; import {routes} from '../app.routes'; import {GlobalStateService} from '../projects/states/index/global-state.service'; @@ -53,6 +55,14 @@ describe('Cross-Project Dashboard route (/dashboard)', () => { provide: ProjectService, useValue: projectServiceMock, }, + { + provide: TaskRecommendationService, + useValue: {getAll: () => of([])}, + }, + { + provide: TaskService, + useValue: {taskStatusUpdated$: EMPTY}, + }, ], }); }); diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts b/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts index 9a299e0d7a..c5d73dd5b6 100644 --- a/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts +++ b/src/app/dashboard/list-item/dashboard-list-item.component.spec.ts @@ -90,6 +90,7 @@ describe('DashboardListItemComponent', () => { fixture = TestBed.createComponent(DashboardListItemComponent); component = fixture.componentInstance; component.task = { + taskDefinitionId: 10, title: 'Security Review', subtitle: '1.1P - Pass Task', statusLabel: 'Resubmit', @@ -129,6 +130,7 @@ describe('DashboardListItemComponent', () => { it('renders warning text and an icon alongside the separate status colour', () => { fixture.componentRef.setInput('task', { + taskDefinitionId: 10, title: 'Accessible task', subtitle: '1.1P - Pass Task', statusLabel: 'Not Started', diff --git a/src/app/dashboard/list-item/dashboard-list-item.component.ts b/src/app/dashboard/list-item/dashboard-list-item.component.ts index 04d128cf9a..9fcc96888f 100644 --- a/src/app/dashboard/list-item/dashboard-list-item.component.ts +++ b/src/app/dashboard/list-item/dashboard-list-item.component.ts @@ -41,6 +41,7 @@ export function getDueDateWarning( } export type DashboardTask = { + taskDefinitionId: number; title: string; subtitle: string; statusLabel: string; From dc6a0bfbba33c63a00ef857803665935997faa69 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 11:36:36 +1000 Subject: [PATCH 1430/1531] feat(demo): centralize local walkthrough mode --- docs/ppi-f02-unit-summary-handover.md | 2 +- .../peer-progress-indicator-state.spec.ts | 2 +- .../peer-progress-unit-summary-state.spec.ts | 2 +- .../api/services/authentication.service.ts | 4 + src/app/api/services/mock/index.ts | 1 - .../mock/peer-progress-indicator.mock.ts | 73 ------------ .../peer-progress-indicator.service.ts | 60 +++------- src/app/api/services/peer-progress.service.ts | 22 ++-- .../spec/authentication.service.spec.ts | 5 + .../peer-progress-indicator.service.spec.ts | 56 +++++++-- src/app/app.component.html | 1 + src/app/app.routes.ts | 8 ++ src/app/common/header/header.component.html | 6 + src/app/common/header/header.component.ts | 2 + src/app/demo/README.md | 25 ++++ .../demo-controls.component.html | 78 +++++++++++++ .../demo-controls.component.scss | 69 +++++++++++ .../demo-controls.component.spec.ts | 97 +++++++++++++++ .../demo-controls/demo-controls.component.ts | 41 +++++++ .../demo/demo-data-mask.interceptor.spec.ts | 91 +++++++++++++++ src/app/demo/demo-data-mask.interceptor.ts | 78 +++++++++++++ .../demo-mode-banner.component.html | 8 ++ .../demo-mode-banner.component.scss | 16 +++ .../demo-mode-banner.component.spec.ts | 46 ++++++++ .../demo-mode-banner.component.ts | 22 ++++ src/app/demo/demo-mode.store.spec.ts | 46 ++++++++ src/app/demo/demo-mode.store.ts | 87 ++++++++++++++ src/app/demo/demo-tools.guard.ts | 8 ++ src/app/demo/demo-tools.module.ts | 32 +++++ .../fixtures/peer-progress-demo.fixtures.ts | 110 ++++++++++++++++++ src/app/demo/fixtures/push-preview.fixture.ts | 6 + src/app/doubtfire-angular.module.ts | 2 + .../progress-dashboard.component.html | 2 +- .../progress-dashboard.component.spec.ts | 16 ++- .../progress-dashboard.component.ts | 19 ++- .../ppi-widget/ppi-widget.component.spec.ts | 4 +- .../progress-burndown-chart.component.html | 68 +++++------ .../progress-burndown-chart.component.spec.ts | 18 ++- .../progress-burndown-chart.component.ts | 16 ++- src/environments/environment.prod.ts | 3 + src/environments/environment.ts | 4 + 41 files changed, 1062 insertions(+), 194 deletions(-) delete mode 100644 src/app/api/services/mock/index.ts delete mode 100644 src/app/api/services/mock/peer-progress-indicator.mock.ts create mode 100644 src/app/demo/README.md create mode 100644 src/app/demo/demo-controls/demo-controls.component.html create mode 100644 src/app/demo/demo-controls/demo-controls.component.scss create mode 100644 src/app/demo/demo-controls/demo-controls.component.spec.ts create mode 100644 src/app/demo/demo-controls/demo-controls.component.ts create mode 100644 src/app/demo/demo-data-mask.interceptor.spec.ts create mode 100644 src/app/demo/demo-data-mask.interceptor.ts create mode 100644 src/app/demo/demo-mode-banner/demo-mode-banner.component.html create mode 100644 src/app/demo/demo-mode-banner/demo-mode-banner.component.scss create mode 100644 src/app/demo/demo-mode-banner/demo-mode-banner.component.spec.ts create mode 100644 src/app/demo/demo-mode-banner/demo-mode-banner.component.ts create mode 100644 src/app/demo/demo-mode.store.spec.ts create mode 100644 src/app/demo/demo-mode.store.ts create mode 100644 src/app/demo/demo-tools.guard.ts create mode 100644 src/app/demo/demo-tools.module.ts create mode 100644 src/app/demo/fixtures/peer-progress-demo.fixtures.ts create mode 100644 src/app/demo/fixtures/push-preview.fixture.ts diff --git a/docs/ppi-f02-unit-summary-handover.md b/docs/ppi-f02-unit-summary-handover.md index a19a8dd04a..d459b84df0 100644 --- a/docs/ppi-f02-unit-summary-handover.md +++ b/docs/ppi-f02-unit-summary-handover.md @@ -28,7 +28,7 @@ This implementation reuses: - `PeerProgressUnitSummary`; - `PeerProgressUnitSummaryViewModel`; - `resolvePeerProgressUnitSummaryState`; -- `PeerProgressIndicatorService.getMockUnitSummary`; +- `PeerProgressIndicatorService.getDemoUnitSummary` (only while the local demo-mode switch is on); - `calculateCompletionPercentage`. The existing task-sheet PPI widget and Progress Burndown implementation were diff --git a/src/app/api/models/peer-progress-indicator-state.spec.ts b/src/app/api/models/peer-progress-indicator-state.spec.ts index 5d7a2d9d35..b289ea5783 100644 --- a/src/app/api/models/peer-progress-indicator-state.spec.ts +++ b/src/app/api/models/peer-progress-indicator-state.spec.ts @@ -6,7 +6,7 @@ import { SUPPRESSED_STATE, UNAVAILABLE_STATE, ZERO_PERCENT_STATE, -} from '../services/mock'; +} from 'src/app/demo/fixtures/peer-progress-demo.fixtures'; import {resolvePeerProgressState} from './peer-progress-indicator-state'; describe('resolvePeerProgressState', () => { diff --git a/src/app/api/models/peer-progress-unit-summary-state.spec.ts b/src/app/api/models/peer-progress-unit-summary-state.spec.ts index d7cdf6ab9e..ec0ad7d4c5 100644 --- a/src/app/api/models/peer-progress-unit-summary-state.spec.ts +++ b/src/app/api/models/peer-progress-unit-summary-state.spec.ts @@ -6,7 +6,7 @@ import { SUPPRESSED_STATE, UNAVAILABLE_STATE, ZERO_PERCENT_STATE, -} from '../services/mock'; +} from 'src/app/demo/fixtures/peer-progress-demo.fixtures'; import {PeerProgressUnitSummary} from './peer-progress-unit-summary'; import {resolvePeerProgressUnitSummaryState} from './peer-progress-unit-summary-state'; diff --git a/src/app/api/services/authentication.service.ts b/src/app/api/services/authentication.service.ts index f8cfc99c8e..b83991fd14 100644 --- a/src/app/api/services/authentication.service.ts +++ b/src/app/api/services/authentication.service.ts @@ -24,6 +24,7 @@ import { type AuthenticatedSettingsResponseFormat, DoubtfireConstants, } from 'src/app/config/constants/doubtfire-constants'; +import {DemoModeStore} from 'src/app/demo/demo-mode.store'; import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; /** @@ -84,6 +85,7 @@ export class AuthenticationService { private alertService: AlertService, private angularRouter: Router, private doubtfireConstants: DoubtfireConstants, + private demoMode: DemoModeStore, ) { this.AUTH_URL = `${this.doubtfireConstants.API_URL}/auth`; // Ensure any only user data is removed from local storage @@ -380,6 +382,8 @@ export class AuthenticationService { } public signOut(ssoSignOut = true): void { + this.demoMode.reset(); + // Invalidate authentication work before the asynchronous push and token // teardown. This prevents a late /settings response from restoring values // after sign out or completing an obsolete sign-in observable. diff --git a/src/app/api/services/mock/index.ts b/src/app/api/services/mock/index.ts deleted file mode 100644 index b0da6ff8ad..0000000000 --- a/src/app/api/services/mock/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './peer-progress-indicator.mock'; diff --git a/src/app/api/services/mock/peer-progress-indicator.mock.ts b/src/app/api/services/mock/peer-progress-indicator.mock.ts deleted file mode 100644 index 554f53bd74..0000000000 --- a/src/app/api/services/mock/peer-progress-indicator.mock.ts +++ /dev/null @@ -1,73 +0,0 @@ -import {PeerProgressIndicator} from '../../models/peer-progress-indicator'; - -export const NORMAL_STATE: PeerProgressIndicator = { - taskDefinitionId: 0, - unitId: 0, - targetGrade: 0, - submittedPercentage: 42, - isSuppressed: false, - isStale: false, - isFeatureEnabled: true, - lastUpdatedAt: new Date().toISOString(), - unavailableMessage: '', -}; - -export const ZERO_PERCENT_STATE: PeerProgressIndicator = { - taskDefinitionId: 0, - unitId: 0, - targetGrade: 0, - submittedPercentage: 0, - isSuppressed: false, - isStale: false, - isFeatureEnabled: true, - lastUpdatedAt: new Date().toISOString(), - unavailableMessage: '', -}; - -export const SUPPRESSED_STATE: PeerProgressIndicator = { - taskDefinitionId: 0, - unitId: 0, - targetGrade: 0, - submittedPercentage: null, - isSuppressed: true, - isStale: false, - isFeatureEnabled: true, - lastUpdatedAt: new Date().toISOString(), - unavailableMessage: 'Not enough students to show progress.', -}; - -export const UNAVAILABLE_STATE: PeerProgressIndicator = { - taskDefinitionId: 0, - unitId: 0, - targetGrade: 0, - submittedPercentage: null, - isSuppressed: false, - isStale: false, - isFeatureEnabled: true, - lastUpdatedAt: new Date().toISOString(), - unavailableMessage: 'Progress unavailable.', -}; - -export const STALE_STATE: PeerProgressIndicator = { - taskDefinitionId: 0, - unitId: 0, - targetGrade: 0, - submittedPercentage: null, - isSuppressed: false, - isStale: true, - isFeatureEnabled: true, - lastUpdatedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 3).toISOString(), - unavailableMessage: 'Peer progress is currently unavailable.', -}; - -export const DISABLED_STATE: PeerProgressIndicator = { - taskDefinitionId: 0, - unitId: 0, - targetGrade: 0, - submittedPercentage: null, - isSuppressed: false, - isStale: false, - isFeatureEnabled: false, - lastUpdatedAt: new Date().toISOString(), - unavailableMessage: 'Peer Progress Indicator is disabled for this unit.', -}; diff --git a/src/app/api/services/peer-progress-indicator.service.ts b/src/app/api/services/peer-progress-indicator.service.ts index 54c6fa5f7c..230353969e 100644 --- a/src/app/api/services/peer-progress-indicator.service.ts +++ b/src/app/api/services/peer-progress-indicator.service.ts @@ -2,16 +2,14 @@ import {HttpClient} from '@angular/common/http'; import {Injectable} from '@angular/core'; import {Observable, map, of} from 'rxjs'; import API_URL from 'src/app/config/constants/apiUrl'; +import {DemoModeStore} from 'src/app/demo/demo-mode.store'; +import { + DemoPeerProgressState, + createDemoUnitSummary, + createMaskedPeerProgressIndicator, +} from 'src/app/demo/fixtures/peer-progress-demo.fixtures'; import {PeerProgressIndicator} from '../models/peer-progress-indicator'; import {PeerProgressUnitSummary} from '../models/peer-progress-unit-summary'; -import { - DISABLED_STATE, - NORMAL_STATE, - STALE_STATE, - SUPPRESSED_STATE, - UNAVAILABLE_STATE, - ZERO_PERCENT_STATE, -} from './mock/peer-progress-indicator.mock'; interface PeerProgressIndicatorResponse { task_definition_id: number; @@ -29,9 +27,16 @@ interface PeerProgressIndicatorResponse { providedIn: 'root', }) export class PeerProgressIndicatorService { - constructor(private httpClient: HttpClient) {} + constructor( + private httpClient: HttpClient, + private demoMode: DemoModeStore, + ) {} getIndicator(projectId: number, taskDefinitionId: number): Observable { + if (this.demoMode.shouldMaskApiData) { + return of(createMaskedPeerProgressIndicator(taskDefinitionId)); + } + const url = `${API_URL}/projects/${projectId}/task_def_id/${taskDefinitionId}/peer_progress`; return this.httpClient.get(url).pipe( @@ -56,43 +61,12 @@ export class PeerProgressIndicatorService { * adapter, and the caller-supplied target grade must never become the design * of a future live endpoint. */ - getMockUnitSummary( + getDemoUnitSummary( unitId: number, targetGrade: number, studentPercentage: number | null, - state: 'normal' | 'zero' | 'suppressed' | 'unavailable' | 'stale' | 'disabled', + state: DemoPeerProgressState, ): Observable { - const cohort = this.resolveState(state); - - return of({ - unitId, - targetGrade, - studentPercentage, - submittedPercentage: cohort.submittedPercentage, - isSuppressed: cohort.isSuppressed, - isStale: cohort.isStale, - isFeatureEnabled: cohort.isFeatureEnabled, - lastUpdatedAt: cohort.lastUpdatedAt, - unavailableMessage: cohort.unavailableMessage, - }); - } - - private resolveState(state: string): PeerProgressIndicator { - switch (state) { - case 'normal': - return NORMAL_STATE; - case 'zero': - return ZERO_PERCENT_STATE; - case 'suppressed': - return SUPPRESSED_STATE; - case 'unavailable': - return UNAVAILABLE_STATE; - case 'stale': - return STALE_STATE; - case 'disabled': - return DISABLED_STATE; - default: - return UNAVAILABLE_STATE; - } + return of(createDemoUnitSummary(unitId, targetGrade, studentPercentage, state)); } } diff --git a/src/app/api/services/peer-progress.service.ts b/src/app/api/services/peer-progress.service.ts index c4a37f601b..2d4b84932f 100644 --- a/src/app/api/services/peer-progress.service.ts +++ b/src/app/api/services/peer-progress.service.ts @@ -1,6 +1,10 @@ import {Injectable} from '@angular/core'; import {Observable, of} from 'rxjs'; -import {PeerMedianPoint, PeerProgressResponse, PeerProgressState} from '../models/peer-progress'; +import { + DEMO_PEER_MEDIAN_STATE, + DEMO_WEEKLY_REMAINING, +} from 'src/app/demo/fixtures/peer-progress-demo.fixtures'; +import {PeerMedianPoint, PeerProgressResponse} from '../models/peer-progress'; import {Project} from '../models/project'; import {MappingFunctions} from './mapping-fn'; @@ -8,11 +12,6 @@ import {MappingFunctions} from './mapping-fn'; providedIn: 'root', }) export class PeerProgressService { - private static readonly MOCK_WEEKLY_REMAINING = [ - 1.0, 0.98, 0.93, 0.88, 0.8, 0.73, 0.66, 0.58, 0.51, 0.44, 0.36, 0.28, 0.2, 0.13, 0.07, 0.02, - 0.0, - ]; - /** * Temporary proof-of-concept state. * @@ -20,26 +19,21 @@ export class PeerProgressService { * suppressed, unavailable or disabled. It must not send the raw cohort size * to the browser. */ - private static readonly MOCK_STATE: PeerProgressState = 'ready'; - public getCohortMedian( project: Project, targetGrade: number = project.targetGrade, ): Observable { - const state = PeerProgressService.MOCK_STATE; + const state = DEMO_PEER_MEDIAN_STATE; return of({ project_id: project.id, target_grade: targetGrade, state, - median_burndown: - state === 'ready' - ? this.sampleProfile(project, PeerProgressService.MOCK_WEEKLY_REMAINING) - : [], + median_burndown: state === 'ready' ? this.sampleProfile(project, DEMO_WEEKLY_REMAINING) : [], }); } - private sampleProfile(project: Project, profile: number[]): PeerMedianPoint[] { + private sampleProfile(project: Project, profile: readonly number[]): PeerMedianPoint[] { const asOf = Date.now(); const weeks = MappingFunctions.step( project.unit.startDate.getTime(), diff --git a/src/app/api/services/spec/authentication.service.spec.ts b/src/app/api/services/spec/authentication.service.spec.ts index 0e450b95d5..cc2cb97f6d 100644 --- a/src/app/api/services/spec/authentication.service.spec.ts +++ b/src/app/api/services/spec/authentication.service.spec.ts @@ -9,6 +9,7 @@ import {User, UserService} from 'src/app/api/models/doubtfire-model'; import {AppInjector, setAppInjector} from 'src/app/app-injector'; import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {DemoModeStore} from 'src/app/demo/demo-mode.store'; import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; import {AuthenticationService} from '../authentication.service'; import {NotificationService} from '../notification.service'; @@ -35,6 +36,7 @@ describe('AuthenticationService', () => { let pushService: {unsubscribeQuietly: ReturnType}; let notificationService: {reset: ReturnType}; + let demoMode: {reset: ReturnType}; let globalState: { clearUnitsAndProjects: ReturnType; hideHeader: ReturnType; @@ -87,6 +89,7 @@ describe('AuthenticationService', () => { beforeEach(() => { pushService = {unsubscribeQuietly: vi.fn().mockReturnValue(of(void 0))}; notificationService = {reset: vi.fn()}; + demoMode = {reset: vi.fn()}; globalState = { clearUnitsAndProjects: vi.fn(), hideHeader: vi.fn(), @@ -125,6 +128,7 @@ describe('AuthenticationService', () => { {provide: Router, useValue: router}, {provide: AlertService, useValue: {error: vi.fn()}}, {provide: DoubtfireConstants, useValue: constants}, + {provide: DemoModeStore, useValue: demoMode}, provideHttpClient(withXhr(), withInterceptorsFromDi()), provideHttpClientTesting(), ], @@ -189,6 +193,7 @@ describe('AuthenticationService', () => { // gone but NotificationService is a root singleton, so its cache and unread // count would otherwise survive into the next person's session. expect(notificationService.reset).toHaveBeenCalledTimes(1); + expect(demoMode.reset).toHaveBeenCalledTimes(1); }); // unsubscribeQuietly is the "never throw" variant, and sign out is also wired diff --git a/src/app/api/services/spec/peer-progress-indicator.service.spec.ts b/src/app/api/services/spec/peer-progress-indicator.service.spec.ts index 8c0c9adafd..7df95a6ae9 100644 --- a/src/app/api/services/spec/peer-progress-indicator.service.spec.ts +++ b/src/app/api/services/spec/peer-progress-indicator.service.spec.ts @@ -4,17 +4,25 @@ import {HttpTestingController, provideHttpClientTesting} from '@angular/common/h import {TestBed} from '@angular/core/testing'; import {PeerProgressIndicator} from 'src/app/api/models/peer-progress-indicator'; import API_URL from 'src/app/config/constants/apiUrl'; -import {DISABLED_STATE, NORMAL_STATE, SUPPRESSED_STATE} from '../mock/peer-progress-indicator.mock'; +import {DemoModeStore} from 'src/app/demo/demo-mode.store'; +import { + DISABLED_STATE, + NORMAL_STATE, + SUPPRESSED_STATE, +} from 'src/app/demo/fixtures/peer-progress-demo.fixtures'; import {PeerProgressIndicatorService} from '../peer-progress-indicator.service'; describe('PeerProgressIndicatorService', () => { let service: PeerProgressIndicatorService; let httpMock: HttpTestingController; + let demoMode: {shouldMaskApiData: boolean}; beforeEach(() => { + demoMode = {shouldMaskApiData: false}; TestBed.configureTestingModule({ providers: [ PeerProgressIndicatorService, + {provide: DemoModeStore, useValue: demoMode}, provideHttpClient(withXhr(), withInterceptorsFromDi()), provideHttpClientTesting(), ], @@ -90,9 +98,43 @@ describe('PeerProgressIndicatorService', () => { expect(request.cancelled).toBe(true); }); - describe('getMockUnitSummary', () => { + it('masks task peer comparison without calling the API while local demo mode is off', () => { + demoMode.shouldMaskApiData = true; + let result: PeerProgressIndicator | undefined; + + service.getIndicator(7, 99).subscribe((value) => { + result = value; + }); + + httpMock.expectNone(`${API_URL}/projects/7/task_def_id/99/peer_progress`); + expect(result).toMatchObject({ + taskDefinitionId: 99, + submittedPercentage: null, + isFeatureEnabled: false, + unavailableMessage: 'Enable demo mode to show live peer comparison data.', + }); + }); + + it('keeps the genuine API path when masking is unavailable in production', () => { + demoMode.shouldMaskApiData = false; + service.getIndicator(7, 99).subscribe(); + + httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`).flush({ + task_definition_id: 99, + unit_id: 1, + target_grade: 2, + submitted_percentage: 40, + is_suppressed: false, + is_stale: false, + is_feature_enabled: true, + last_updated_at: '2026-08-23T00:00:00Z', + unavailable_message: '', + }); + }); + + describe('getDemoUnitSummary', () => { it('should keep the student and cohort percentages separate for a normal response', () => { - service.getMockUnitSummary(10, 2, 30, 'normal').subscribe((result) => { + service.getDemoUnitSummary(10, 2, 30, 'normal').subscribe((result) => { expect(result.studentPercentage).toBe(30); expect(result.submittedPercentage).toBe(NORMAL_STATE.submittedPercentage); expect(result.isSuppressed).toBe(NORMAL_STATE.isSuppressed); @@ -103,13 +145,13 @@ describe('PeerProgressIndicatorService', () => { }); it('should not expose a task definition id -- a unit summary is not task-scoped', () => { - service.getMockUnitSummary(10, 2, 30, 'normal').subscribe((result) => { + service.getDemoUnitSummary(10, 2, 30, 'normal').subscribe((result) => { expect((result as unknown as {taskDefinitionId?: number}).taskDefinitionId).toBeUndefined(); }); }); it('should return suppressed state with the safe message and no cohort percentage', () => { - service.getMockUnitSummary(30, 0, 30, 'suppressed').subscribe((result) => { + service.getDemoUnitSummary(30, 0, 30, 'suppressed').subscribe((result) => { expect(result.submittedPercentage).toBe(SUPPRESSED_STATE.submittedPercentage); expect(result.isSuppressed).toBe(true); expect(result.unavailableMessage).toBe(SUPPRESSED_STATE.unavailableMessage); @@ -118,14 +160,14 @@ describe('PeerProgressIndicatorService', () => { }); it('should return disabled state when the unit has PPI turned off', () => { - service.getMockUnitSummary(60, 1, 30, 'disabled').subscribe((result) => { + service.getDemoUnitSummary(60, 1, 30, 'disabled').subscribe((result) => { expect(result.isFeatureEnabled).toBe(false); expect(result.unavailableMessage).toBe(DISABLED_STATE.unavailableMessage); }); }); it('should preserve a null studentPercentage rather than substituting a default', () => { - service.getMockUnitSummary(10, 2, null, 'normal').subscribe((result) => { + service.getDemoUnitSummary(10, 2, null, 'normal').subscribe((result) => { expect(result.studentPercentage).toBeNull(); }); }); diff --git a/src/app/app.component.html b/src/app/app.component.html index 53e25cc7c8..346e6f06df 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,3 +1,4 @@ + diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index f16c0f363a..415e2c58a7 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -9,6 +9,8 @@ import {ScormPlayerComponent} from './common/scorm-player/scorm-player.component import {SubmissionFilesDownloadComponent} from './common/submission-files-download/submission-files-download.component'; import {SuccessCloseComponent} from './common/success-close/success-close.component'; import {CrossDashboardComponent} from './dashboard/f-cross-dashboard.component'; +import {DemoControlsComponent} from './demo/demo-controls/demo-controls.component'; +import {demoToolsGuard} from './demo/demo-tools.guard'; import {TimeoutComponent} from './errors/states/timeout/timeout.component'; import {UnauthorisedComponent} from './errors/states/unauthorised/unauthorised.component'; import {AcceptEulaComponent} from './eula/accept-eula/accept-eula.component'; @@ -47,6 +49,12 @@ export const routes: Routes = [ {path: 'success-close', component: SuccessCloseComponent}, {path: 'edit_profile', component: EditProfileComponent}, {path: 'notifications', component: NotificationsPageComponent}, + { + path: 'demo-controls', + component: DemoControlsComponent, + canActivate: [demoToolsGuard], + data: {pageTitle: 'Demo controls'}, + }, {path: 'eula', component: AcceptEulaComponent}, {path: 'lti', component: LtiDashboardComponent}, {path: 'lti/link', component: LtiUnitLinkComponent}, diff --git a/src/app/common/header/header.component.html b/src/app/common/header/header.component.html index 29ac6fd43e..f35c30e454 100644 --- a/src/app/common/header/header.component.html +++ b/src/app/common/header/header.component.html @@ -118,6 +118,12 @@ } } + @if (demoMode.available) { + + } + +} diff --git a/src/app/demo/demo-mode-banner/demo-mode-banner.component.scss b/src/app/demo/demo-mode-banner/demo-mode-banner.component.scss new file mode 100644 index 0000000000..7247eb0865 --- /dev/null +++ b/src/app/demo/demo-mode-banner/demo-mode-banner.component.scss @@ -0,0 +1,16 @@ +.demo-mode-banner { + align-items: center; + background: #fff4cc; + border-bottom: 1px solid #9a6700; + color: #5f3b00; + display: flex; + flex-wrap: wrap; + gap: 0.75rem; + justify-content: center; + padding: 0.5rem 1rem; +} + +.demo-mode-banner a, +.demo-mode-banner button { + color: inherit; +} diff --git a/src/app/demo/demo-mode-banner/demo-mode-banner.component.spec.ts b/src/app/demo/demo-mode-banner/demo-mode-banner.component.spec.ts new file mode 100644 index 0000000000..d0871ff50d --- /dev/null +++ b/src/app/demo/demo-mode-banner/demo-mode-banner.component.spec.ts @@ -0,0 +1,46 @@ +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {provideRouter} from '@angular/router'; +import {BehaviorSubject} from 'rxjs'; +import {DEMO_RELOAD} from '../demo-controls/demo-controls.component'; +import {DemoModeStore} from '../demo-mode.store'; +import {DemoToolsModule} from '../demo-tools.module'; +import {DemoModeBannerComponent} from './demo-mode-banner.component'; + +describe('DemoModeBannerComponent', () => { + let fixture: ComponentFixture; + let enabled: BehaviorSubject; + let reset: ReturnType; + let reload: ReturnType; + + beforeEach(async () => { + enabled = new BehaviorSubject(true); + reset = vi.fn(() => enabled.next(false)); + reload = vi.fn(); + + await TestBed.configureTestingModule({ + imports: [DemoToolsModule, NoopAnimationsModule], + providers: [ + {provide: DemoModeStore, useValue: {enabled$: enabled.asObservable(), reset}}, + {provide: DEMO_RELOAD, useValue: reload}, + provideRouter([]), + ], + }).compileComponents(); + + fixture = TestBed.createComponent(DemoModeBannerComponent); + fixture.detectChanges(); + }); + + it('stays visible across routes while demo mode is active', () => { + expect(fixture.nativeElement.textContent).toContain('Demo mode:'); + expect(fixture.nativeElement.textContent).toContain('Exit demo'); + }); + + it('exits demo mode and reloads the application', () => { + fixture.componentInstance.exitDemo(); + + expect(reset).toHaveBeenCalledOnce(); + expect(reload).toHaveBeenCalledOnce(); + }); +}); diff --git a/src/app/demo/demo-mode-banner/demo-mode-banner.component.ts b/src/app/demo/demo-mode-banner/demo-mode-banner.component.ts new file mode 100644 index 0000000000..0d71af378b --- /dev/null +++ b/src/app/demo/demo-mode-banner/demo-mode-banner.component.ts @@ -0,0 +1,22 @@ +import {ChangeDetectionStrategy, Component, Inject} from '@angular/core'; +import {DEMO_RELOAD} from '../demo-controls/demo-controls.component'; +import {DemoModeStore} from '../demo-mode.store'; + +@Component({ + selector: 'f-demo-mode-banner', + templateUrl: './demo-mode-banner.component.html', + styleUrls: ['./demo-mode-banner.component.scss'], + changeDetection: ChangeDetectionStrategy.Eager, + standalone: false, +}) +export class DemoModeBannerComponent { + constructor( + readonly demoMode: DemoModeStore, + @Inject(DEMO_RELOAD) private reload: () => void, + ) {} + + exitDemo(): void { + this.demoMode.reset(); + this.reload(); + } +} diff --git a/src/app/demo/demo-mode.store.spec.ts b/src/app/demo/demo-mode.store.spec.ts new file mode 100644 index 0000000000..a547ee6bf9 --- /dev/null +++ b/src/app/demo/demo-mode.store.spec.ts @@ -0,0 +1,46 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {DEMO_MODE_STORAGE_KEY, DemoModeStore} from './demo-mode.store'; + +describe('DemoModeStore', () => { + beforeEach(() => { + sessionStorage.clear(); + }); + + it('is available but defaults off in a development demo build', () => { + const store = new DemoModeStore(true); + + expect(store.available).toBe(true); + expect(store.enabled).toBe(false); + expect(store.shouldMaskApiData).toBe(true); + }); + + it('persists the enabled state in session storage', () => { + const firstStore = new DemoModeStore(true); + firstStore.setEnabled(true); + + expect(sessionStorage.getItem(DEMO_MODE_STORAGE_KEY)).toBe('true'); + expect(new DemoModeStore(true).enabled).toBe(true); + }); + + it('reset fails closed and removes the stored state', () => { + const store = new DemoModeStore(true); + store.setEnabled(true); + + store.reset(); + + expect(store.enabled).toBe(false); + expect(sessionStorage.getItem(DEMO_MODE_STORAGE_KEY)).toBeNull(); + }); + + it('cannot enable in production and leaves genuine API data unmasked', () => { + sessionStorage.setItem(DEMO_MODE_STORAGE_KEY, 'true'); + const store = new DemoModeStore(false); + + store.setEnabled(true); + + expect(store.available).toBe(false); + expect(store.enabled).toBe(false); + expect(store.shouldMaskApiData).toBe(false); + expect(sessionStorage.getItem(DEMO_MODE_STORAGE_KEY)).toBeNull(); + }); +}); diff --git a/src/app/demo/demo-mode.store.ts b/src/app/demo/demo-mode.store.ts new file mode 100644 index 0000000000..465c48173a --- /dev/null +++ b/src/app/demo/demo-mode.store.ts @@ -0,0 +1,87 @@ +import {environment} from 'src/environments/environment'; +import {Inject, Injectable, InjectionToken} from '@angular/core'; +import {BehaviorSubject, Observable, distinctUntilChanged} from 'rxjs'; + +export const DEMO_MODE_STORAGE_KEY = 'ontrack_demo_mode_enabled'; + +export const DEMO_TOOLS_AVAILABLE: InjectionToken = new InjectionToken( + 'DEMO_TOOLS_AVAILABLE', + { + providedIn: 'root', + factory: () => environment.enableDemoTools === true && environment.production === false, + }, +); + +@Injectable({providedIn: 'root'}) +export class DemoModeStore { + private readonly enabledSubject: BehaviorSubject; + + readonly enabled$: Observable; + + constructor(@Inject(DEMO_TOOLS_AVAILABLE) readonly available: boolean) { + const enabled = available && this.readStoredValue(); + + if (!available) { + this.removeStoredValue(); + } + + this.enabledSubject = new BehaviorSubject(enabled); + this.enabled$ = this.enabledSubject.asObservable().pipe(distinctUntilChanged()); + } + + get enabled(): boolean { + return this.available && this.enabledSubject.value; + } + + /** + * Local development starts in the intentionally quiet state. Production and + * builds without demo tools must always pass API data through unchanged. + */ + get shouldMaskApiData(): boolean { + return this.available && !this.enabled; + } + + setEnabled(enabled: boolean): void { + if (!this.available) { + this.reset(); + return; + } + + if (enabled) { + this.writeStoredValue(); + } else { + this.removeStoredValue(); + } + + this.enabledSubject.next(enabled); + } + + reset(): void { + this.removeStoredValue(); + this.enabledSubject.next(false); + } + + private readStoredValue(): boolean { + try { + return globalThis.sessionStorage?.getItem(DEMO_MODE_STORAGE_KEY) === 'true'; + } catch { + return false; + } + } + + private writeStoredValue(): void { + try { + globalThis.sessionStorage?.setItem(DEMO_MODE_STORAGE_KEY, 'true'); + } catch { + // Storage can be unavailable in private or hardened browser contexts. + } + } + + private removeStoredValue(): void { + try { + globalThis.sessionStorage?.removeItem(DEMO_MODE_STORAGE_KEY); + } catch { + // The in-memory state still fails closed when storage is unavailable. + } + } +} diff --git a/src/app/demo/demo-tools.guard.ts b/src/app/demo/demo-tools.guard.ts new file mode 100644 index 0000000000..bbc49aa88b --- /dev/null +++ b/src/app/demo/demo-tools.guard.ts @@ -0,0 +1,8 @@ +import {inject} from '@angular/core'; +import {CanActivateFn, Router} from '@angular/router'; +import {DemoModeStore} from './demo-mode.store'; + +export const demoToolsGuard: CanActivateFn = () => { + const demoMode = inject(DemoModeStore); + return demoMode.available ? true : inject(Router).createUrlTree(['/home']); +}; diff --git a/src/app/demo/demo-tools.module.ts b/src/app/demo/demo-tools.module.ts new file mode 100644 index 0000000000..8fc0dbebff --- /dev/null +++ b/src/app/demo/demo-tools.module.ts @@ -0,0 +1,32 @@ +import {CommonModule} from '@angular/common'; +import {HTTP_INTERCEPTORS} from '@angular/common/http'; +import {NgModule} from '@angular/core'; +import {MatButtonModule} from '@angular/material/button'; +import {MatCardModule} from '@angular/material/card'; +import {MatIconModule} from '@angular/material/icon'; +import {MatSlideToggleModule} from '@angular/material/slide-toggle'; +import {RouterModule} from '@angular/router'; +import {DemoControlsComponent} from './demo-controls/demo-controls.component'; +import {DemoDataMaskInterceptor} from './demo-data-mask.interceptor'; +import {DemoModeBannerComponent} from './demo-mode-banner/demo-mode-banner.component'; + +@NgModule({ + declarations: [DemoControlsComponent, DemoModeBannerComponent], + imports: [ + CommonModule, + RouterModule, + MatButtonModule, + MatCardModule, + MatIconModule, + MatSlideToggleModule, + ], + exports: [DemoModeBannerComponent], + providers: [ + { + provide: HTTP_INTERCEPTORS, + useClass: DemoDataMaskInterceptor, + multi: true, + }, + ], +}) +export class DemoToolsModule {} diff --git a/src/app/demo/fixtures/peer-progress-demo.fixtures.ts b/src/app/demo/fixtures/peer-progress-demo.fixtures.ts new file mode 100644 index 0000000000..fc9527c187 --- /dev/null +++ b/src/app/demo/fixtures/peer-progress-demo.fixtures.ts @@ -0,0 +1,110 @@ +import {PeerProgressState} from 'src/app/api/models/peer-progress'; +import {PeerProgressIndicator} from 'src/app/api/models/peer-progress-indicator'; +import {PeerProgressUnitSummary} from 'src/app/api/models/peer-progress-unit-summary'; + +export type DemoPeerProgressState = + | 'normal' + | 'zero' + | 'suppressed' + | 'unavailable' + | 'stale' + | 'disabled'; + +const currentTimestamp = (): string => new Date().toISOString(); + +export const NORMAL_STATE: PeerProgressIndicator = { + taskDefinitionId: 0, + unitId: 0, + targetGrade: 0, + submittedPercentage: 42, + isSuppressed: false, + isStale: false, + isFeatureEnabled: true, + lastUpdatedAt: currentTimestamp(), + unavailableMessage: '', +}; + +export const ZERO_PERCENT_STATE: PeerProgressIndicator = { + ...NORMAL_STATE, + submittedPercentage: 0, +}; + +export const SUPPRESSED_STATE: PeerProgressIndicator = { + ...NORMAL_STATE, + submittedPercentage: null, + isSuppressed: true, + unavailableMessage: 'Not enough students to show progress.', +}; + +export const UNAVAILABLE_STATE: PeerProgressIndicator = { + ...NORMAL_STATE, + submittedPercentage: null, + unavailableMessage: 'Progress unavailable.', +}; + +export const STALE_STATE: PeerProgressIndicator = { + ...NORMAL_STATE, + submittedPercentage: null, + isStale: true, + lastUpdatedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 3).toISOString(), + unavailableMessage: 'Peer progress is currently unavailable.', +}; + +export const DISABLED_STATE: PeerProgressIndicator = { + ...NORMAL_STATE, + submittedPercentage: null, + isFeatureEnabled: false, + unavailableMessage: 'Peer Progress Indicator is disabled for this unit.', +}; + +export const DEMO_WEEKLY_REMAINING: readonly number[] = [ + 1.0, 0.98, 0.93, 0.88, 0.8, 0.73, 0.66, 0.58, 0.51, 0.44, 0.36, 0.28, 0.2, 0.13, 0.07, 0.02, 0.0, +]; + +export const DEMO_PEER_MEDIAN_STATE: PeerProgressState = 'ready'; + +export function createDemoUnitSummary( + unitId: number, + targetGrade: number, + studentPercentage: number | null, + state: DemoPeerProgressState = 'normal', +): PeerProgressUnitSummary { + const cohort = demoPeerProgressState(state); + + return { + unitId, + targetGrade, + studentPercentage, + submittedPercentage: cohort.submittedPercentage, + isSuppressed: cohort.isSuppressed, + isStale: cohort.isStale, + isFeatureEnabled: cohort.isFeatureEnabled, + lastUpdatedAt: cohort.lastUpdatedAt, + unavailableMessage: cohort.unavailableMessage, + }; +} + +export function createMaskedPeerProgressIndicator(taskDefinitionId: number): PeerProgressIndicator { + return { + ...DISABLED_STATE, + taskDefinitionId, + unavailableMessage: 'Enable demo mode to show live peer comparison data.', + }; +} + +function demoPeerProgressState(state: DemoPeerProgressState): PeerProgressIndicator { + switch (state) { + case 'normal': + return NORMAL_STATE; + case 'zero': + return ZERO_PERCENT_STATE; + case 'suppressed': + return SUPPRESSED_STATE; + case 'unavailable': + return UNAVAILABLE_STATE; + case 'stale': + return STALE_STATE; + case 'disabled': + return DISABLED_STATE; + } +} diff --git a/src/app/demo/fixtures/push-preview.fixture.ts b/src/app/demo/fixtures/push-preview.fixture.ts new file mode 100644 index 0000000000..d7a388e97f --- /dev/null +++ b/src/app/demo/fixtures/push-preview.fixture.ts @@ -0,0 +1,6 @@ +export const DEMO_PUSH_PREVIEW = { + appName: 'OnTrack demo', + title: 'Feedback is ready', + message: 'New feedback is available for Demo Task 2.1P.', + destination: 'Demo task dashboard', +} as const; diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index ce8b8a93f7..e5dae86a39 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -238,6 +238,7 @@ import {PrivacyPolicy} from './config/privacy-policy/privacy-policy'; import {CrossDashboardComponent} from './dashboard/f-cross-dashboard.component'; import {DashboardListItemComponent} from './dashboard/list-item/dashboard-list-item.component'; import {DashboardExpandedListItemComponent} from './dashboard/list-item/expanded-list-item/expanded-list-item.component'; +import {DemoToolsModule} from './demo/demo-tools.module'; import {TimeoutComponent} from './errors/states/timeout/timeout.component'; import {UnauthorisedComponent} from './errors/states/unauthorised/unauthorised.component'; import {UnavailableCardComponent} from './errors/unavailable-card/unavailable-card.component'; @@ -805,6 +806,7 @@ const DEFAULT_TOOLTIP_OPTIONS: MatTooltipDefaultOptions = { FlexLayoutModule, BrowserModule, BrowserAnimationsModule, + DemoToolsModule, RouterModule.forRoot(routes, { initialNavigation: 'enabledNonBlocking', }), diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html index 189f316e12..199a65492e 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html @@ -97,7 +97,7 @@

        - @if (!viewingOtherStudentProject) { + @if (showDemoPeerProgress) {
        diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts index 954d6b6635..9664b38441 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts @@ -14,6 +14,7 @@ import {ProjectService} from 'src/app/api/services/project.service'; import {UserService} from 'src/app/api/services/user.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {GradeService} from 'src/app/common/services/grade.service'; +import {DemoModeStore} from 'src/app/demo/demo-mode.store'; import {ProgressDashboardComponent} from './progress-dashboard.component'; describe('ProgressDashboardComponent', () => { @@ -59,8 +60,9 @@ describe('ProgressDashboardComponent', () => { }, { provide: PeerProgressIndicatorService, - useValue: {getMockUnitSummary: vi.fn().mockReturnValue(of(null))}, + useValue: {getDemoUnitSummary: vi.fn().mockReturnValue(of(null))}, }, + {provide: DemoModeStore, useValue: {enabled: true}}, {provide: ProjectService, useValue: {update: projectServiceUpdate}}, {provide: AlertService, useValue: {success: alertSuccess, error: alertError}}, {provide: UserService, useValue: {currentUser: {id: 25}}}, @@ -130,6 +132,15 @@ describe('ProgressDashboardComponent', () => { expect(statusCard?.classList.contains('max-h-[600px]')).toBe(false); expect(burndownContent?.classList.contains('overflow-hidden')).toBe(false); }); + + it('renders fabricated unit peer progress only while demo mode is enabled', () => { + expect(fixture.nativeElement.querySelector('f-peer-progress-unit-summary')).toBeTruthy(); + + (component.demoMode as {enabled: boolean}).enabled = false; + fixture.detectChanges(); + + expect(fixture.nativeElement.querySelector('f-peer-progress-unit-summary')).toBeNull(); + }); }); describe('ProgressDashboardComponent route reuse', () => { @@ -142,11 +153,12 @@ describe('ProgressDashboardComponent route reuse', () => { gradeValuesFor, } as unknown as GradeService, { - getMockUnitSummary: vi.fn().mockReturnValue(of(null)), + getDemoUnitSummary: vi.fn().mockReturnValue(of(null)), } as unknown as PeerProgressIndicatorService, {} as ProjectService, {} as AlertService, {} as UserService, + {enabled: true} as DemoModeStore, ); const firstProject = { id: 2, diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts index dec132e7f8..4d617675e4 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.ts @@ -1,4 +1,3 @@ -import {environment} from 'src/environments/environment'; import { ChangeDetectionStrategy, Component, @@ -21,6 +20,7 @@ import {UserService} from 'src/app/api/services/user.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {GradeService} from 'src/app/common/services/grade.service'; import {calculateCompletionPercentage} from 'src/app/common/services/ppi-progress-calculation.service'; +import {DemoModeStore} from 'src/app/demo/demo-mode.store'; @Component({ selector: 'f-progress-dashboard', @@ -56,6 +56,7 @@ export class ProgressDashboardComponent implements OnChanges, OnInit { private projectService: ProjectService, private alertService: AlertService, private userService: UserService, + readonly demoMode: DemoModeStore, ) {} ngOnInit(): void { @@ -89,6 +90,10 @@ export class ProgressDashboardComponent implements OnChanges, OnInit { return !!role && role !== 'Student' && this.project?.student?.id !== currentUser?.id; } + public get showDemoPeerProgress(): boolean { + return this.demoMode.enabled && !this.viewingOtherStudentProject; + } + updateTargetGrade(newGrade: number): void { if ( this.isUpdatingTargetGrade || @@ -125,7 +130,7 @@ export class ProgressDashboardComponent implements OnChanges, OnInit { } private loadPeerProgressUnitSummary(): void { - if (this.viewingOtherStudentProject) { + if (!this.showDemoPeerProgress) { return; } @@ -136,20 +141,12 @@ export class ProgressDashboardComponent implements OnChanges, OnInit { availableTasks, ); - // The cohort figure is still a fixture. Never show a fabricated percentage - // in a production build - a student cannot tell it from a real one. Remove - // this guard when the live PPI-F01 adapter replaces getMockUnitSummary. - if (environment.production) { - this.peerProgressView = resolvePeerProgressUnitSummaryState(false, null, null); - return; - } - this.peerProgressView = resolvePeerProgressUnitSummaryState(true, null, null); // PPI-F02 demonstration only. // A live authorised unit-level API remains future work. this.peerProgressService - .getMockUnitSummary( + .getDemoUnitSummary( this.project.unit.id, this.project.targetGrade, studentPercentage, diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts index 2a3d901d08..c7587139d9 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-description-card/ppi-widget/ppi-widget.component.spec.ts @@ -9,6 +9,7 @@ import {Observable, Subject, of, throwError} from 'rxjs'; import {PeerProgressIndicator} from 'src/app/api/models/peer-progress-indicator'; import {Task} from 'src/app/api/models/task'; import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {PeerProgressIndicatorService} from 'src/app/api/services/peer-progress-indicator.service'; import { DISABLED_STATE, NORMAL_STATE, @@ -16,8 +17,7 @@ import { SUPPRESSED_STATE, UNAVAILABLE_STATE, ZERO_PERCENT_STATE, -} from 'src/app/api/services/mock'; -import {PeerProgressIndicatorService} from 'src/app/api/services/peer-progress-indicator.service'; +} from 'src/app/demo/fixtures/peer-progress-demo.fixtures'; import {PpiWidgetComponent} from './ppi-widget.component'; describe('PpiWidgetComponent', () => { diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index 837687865c..f445e22ef7 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -50,44 +50,46 @@
        } - @if (peerMedianState === 'ready') { -
        - + @if (demoMode.enabled) { + @if (peerMedianState === 'ready') { +
        + - - Demo peer median through today: anonymous aggregate sample data, not live cohort data. - -
        - } @else { -
        - @switch (peerMedianState) { - @case ('loading') { - - Loading peer comparison… - } + + Demo peer median through today: anonymous aggregate sample data, not live cohort data. + +
        + } @else { +
        + @switch (peerMedianState) { + @case ('loading') { + + Loading peer comparison… + } - @case ('suppressed') { - - - Peer comparison is hidden because the anonymous cohort threshold was not met. - - } + @case ('suppressed') { + + + Peer comparison is hidden because the anonymous cohort threshold was not met. + + } - @case ('unavailable') { - - Peer median is unavailable right now. - } + @case ('unavailable') { + + Peer median is unavailable right now. + } - @case ('disabled') { - - Peer comparison is disabled for this unit. - } + @case ('disabled') { + + Peer comparison is disabled for this unit. + } - @case ('error') { - - Peer median could not be loaded. Please try again later. + @case ('error') { + + Peer median could not be loaded. Please try again later. + } } - } -
        +
        + } }
        diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts index 64d6c9abbf..4a65a0e503 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.spec.ts @@ -7,6 +7,7 @@ import { PeerProgressState, Project, } from 'src/app/api/models/doubtfire-model'; +import {DemoModeStore} from 'src/app/demo/demo-mode.store'; import {ProgressBurndownChartComponent} from './progress-burndown-chart.component'; describe('ProgressBurndownChartComponent peer comparison', () => { @@ -82,7 +83,10 @@ describe('ProgressBurndownChartComponent peer comparison', () => { }; } - function makeHarness(getCohortMedian: ReturnType): { + function makeHarness( + getCohortMedian: ReturnType, + demoEnabled = true, + ): { component: ProgressBurndownChartComponent; project: Project; } { @@ -93,6 +97,7 @@ describe('ProgressBurndownChartComponent peer comparison', () => { { getCohortMedian, } as unknown as PeerProgressService, + {enabled: demoEnabled} as DemoModeStore, 'en-US', ); @@ -119,6 +124,17 @@ describe('ProgressBurndownChartComponent peer comparison', () => { return component.data.map((series) => series.name); } + it('does not request or render synthetic peer data when demo mode is off', () => { + const getCohortMedian = vi.fn(); + const {component} = makeHarness(getCohortMedian, false); + + initialise(component); + + expect(getCohortMedian).not.toHaveBeenCalled(); + expect(seriesNames(component)).toEqual(EXISTING_SERIES); + expect(component.peerMedianState).toBe('disabled'); + }); + function expectOnlyExistingSeries(component: ProgressBurndownChartComponent): void { expect(seriesNames(component)).toEqual(EXISTING_SERIES); } diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts index 160b6a6d84..2aff507f6d 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.ts @@ -23,6 +23,7 @@ import { Unit, } from 'src/app/api/models/doubtfire-model'; import {ChartBaseComponent} from 'src/app/common/chart-base/chart-base-component/chart-base-component.component'; +import {DemoModeStore} from 'src/app/demo/demo-mode.store'; interface BurndownPoint { name: string; @@ -78,7 +79,7 @@ export class ProgressBurndownChartComponent yScaleMax: number = 100; /** Drives the privacy-safe status message below the chart. */ - peerMedianState: PeerMedianState = 'loading'; + peerMedianState: PeerMedianState = 'disabled'; private seriesVisibility: Record = {}; private peerMedian: PeerMedianPoint[] = []; @@ -89,6 +90,7 @@ export class ProgressBurndownChartComponent constructor( public viewContainerRef: ViewContainerRef, private peerProgressService: PeerProgressService, + readonly demoMode: DemoModeStore, @Inject(LOCALE_ID) private locale: string, ) { super(viewContainerRef); @@ -107,7 +109,9 @@ export class ProgressBurndownChartComponent this.seriesVisibility[item.name] = true; }); - this.loadPeerMedian(); + if (this.demoMode.enabled) { + this.loadPeerMedian(); + } } ngOnChanges(changes: SimpleChanges): void { @@ -137,7 +141,13 @@ export class ProgressBurndownChartComponent this.updateData(); // The comparison cohort changes with the project, unit, or target grade. - this.loadPeerMedian(); + if (this.demoMode.enabled) { + this.loadPeerMedian(); + } else { + this.peerMedianState = 'disabled'; + this.peerMedian = []; + this.updateData(); + } } @HostListener('window:resize') diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 5a15ec8f62..2e2458489c 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -5,6 +5,9 @@ export const environment = { // worker. Present so both environment files have the same shape. enableServiceWorker: false, + // Demo mode must never be enabled by a production build. + enableDemoTools: false, + sentryDsn: '${SENTRY_DSN}', sentryRelease: '${SENTRY_RELEASE}', sentryDist: '${SENTRY_DIST}', diff --git a/src/environments/environment.ts b/src/environments/environment.ts index cfcbe0bb80..fec5e071b0 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -14,6 +14,10 @@ export const environment = { // See docs/service-worker.md. enableServiceWorker: true, + // Makes the local-only demo controls available. The mode itself still starts + // off and is stored only for the current browser tab. + enableDemoTools: true, + sentryDsn: '', sentryRelease: '', sentryDist: '', From 08b0b9d0dbfb5c05f0cac77cb87c71bb0083029d Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 12:57:58 +1000 Subject: [PATCH 1431/1531] fix(auth): scrub callback credentials before telemetry --- .../api/services/authentication.service.ts | 12 +- .../lti-dashboard/lti-dashboard.component.ts | 9 +- .../lti-unit-link/lti-unit-link.component.ts | 7 +- src/app/security/auth-callback.spec.ts | 100 ++++++++++++ src/app/security/auth-callback.ts | 150 ++++++++++++++++++ .../states/sign-in/sign-in.component.spec.ts | 3 +- .../states/sign-in/sign-in.component.ts | 46 ++---- src/index.html | 12 +- src/main.ts | 23 ++- 9 files changed, 303 insertions(+), 59 deletions(-) create mode 100644 src/app/security/auth-callback.spec.ts create mode 100644 src/app/security/auth-callback.ts diff --git a/src/app/api/services/authentication.service.ts b/src/app/api/services/authentication.service.ts index 46c6f89aa0..c01664073b 100644 --- a/src/app/api/services/authentication.service.ts +++ b/src/app/api/services/authentication.service.ts @@ -10,6 +10,7 @@ import { DoubtfireConstants, } from 'src/app/config/constants/doubtfire-constants'; import {GlobalStateService, ViewType} from 'src/app/projects/states/index/global-state.service'; +import {buildAuthCallbackFragment} from 'src/app/security/auth-callback'; /** * The format for the data returned from the auth api. @@ -253,11 +254,14 @@ export class AuthenticationService { public signInWithLti(userCredentials: {ltik: string; lti_token: string}): Observable { return this.httpClient.post(`${this.AUTH_URL}/lti`, userCredentials).pipe( map((response: AuthResponse) => { - const username = encodeURIComponent(response.user['username']); - const authToken = encodeURIComponent(response.auth_token); - const ltik = encodeURIComponent(userCredentials.ltik); + const fragment = buildAuthCallbackFragment({ + username: response.user['username'], + authToken: response.auth_token, + ltik: userCredentials.ltik, + isLtiLogin: true, + }); setTimeout(() => { - window.location.href = `/sign_in?username=${username}&authToken=${authToken}<ik=${ltik}&isLtiLogin=true`; + window.location.href = `/sign_in#${fragment}`; }); }), catchError((error) => { diff --git a/src/app/home/states/lti-dashboard/lti-dashboard.component.ts b/src/app/home/states/lti-dashboard/lti-dashboard.component.ts index dd775f824d..4cdcaf7df9 100644 --- a/src/app/home/states/lti-dashboard/lti-dashboard.component.ts +++ b/src/app/home/states/lti-dashboard/lti-dashboard.component.ts @@ -1,5 +1,5 @@ import {AfterViewInit, ChangeDetectionStrategy, Component, Input} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; +import {Router} from '@angular/router'; import {ProjectService, User} from 'src/app/api/models/doubtfire-model'; import {Unit} from 'src/app/api/models/unit'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; @@ -21,7 +21,6 @@ import {AlertService} from 'src/app/common/services/alert.service'; export class LtiDashboardComponent implements AfterViewInit { constructor( private router: Router, - private route: ActivatedRoute, private ltiService: LtiService, private userService: UserService, private authenticationService: AuthenticationService, @@ -47,7 +46,7 @@ export class LtiDashboardComponent implements AfterViewInit { isSyncingEnrolments: boolean; ngAfterViewInit(): void { - this.ltik = this.ltik ?? this.route.snapshot.queryParamMap.get('ltik'); + this.ltik = this.ltik ?? this.userService.currentUser.ltik; // Scroll to the bottom of the page in case the header is visible // Ensures our action buttons are centered @@ -101,7 +100,7 @@ export class LtiDashboardComponent implements AfterViewInit { } goToLinkUnit(): void { - this.router.navigate(['/lti/link'], {queryParams: {ltik: this.ltik}}); + this.router.navigateByUrl('/lti/link'); } removeLink(): void { @@ -213,6 +212,6 @@ export class LtiDashboardComponent implements AfterViewInit { ); } public launchApplication(): void { - window.open('http://localhost:4200/home', '_blank'); + window.open('/home', '_blank'); } } diff --git a/src/app/home/states/lti-unit-link/lti-unit-link.component.ts b/src/app/home/states/lti-unit-link/lti-unit-link.component.ts index 74f4c8bbb3..e2cff995e4 100644 --- a/src/app/home/states/lti-unit-link/lti-unit-link.component.ts +++ b/src/app/home/states/lti-unit-link/lti-unit-link.component.ts @@ -1,5 +1,5 @@ import {AfterViewInit, ChangeDetectionStrategy, Component, Input} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; +import {Router} from '@angular/router'; import {CreateNewUnitModal} from 'src/app/admin/modals/create-new-unit-modal/create-new-unit-modal.component'; import {Unit} from 'src/app/api/models/unit'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; @@ -26,7 +26,6 @@ export class LtiUnitLinkComponent implements AfterViewInit { private ltiService: LtiService, private userService: UserService, private router: Router, - private route: ActivatedRoute, ) {} @Input() ltik: string; @@ -39,7 +38,7 @@ export class LtiUnitLinkComponent implements AfterViewInit { public loadingUnits: boolean; ngAfterViewInit(): void { - this.ltik = this.ltik ?? this.route.snapshot.queryParamMap.get('ltik'); + this.ltik = this.ltik ?? this.userService.currentUser.ltik; this.loadingUnits = true; // Scroll to the bottom of the page in case the header is visible @@ -93,7 +92,7 @@ export class LtiUnitLinkComponent implements AfterViewInit { this.alertsService.success(`Successfully linked ${unit.code}`, 5000); - this.router.navigate(['/lti'], {queryParams: {ltik: this.ltik}}); + this.router.navigateByUrl('/lti'); }, error: (error) => { console.log(error); diff --git a/src/app/security/auth-callback.spec.ts b/src/app/security/auth-callback.spec.ts new file mode 100644 index 0000000000..c49487e218 --- /dev/null +++ b/src/app/security/auth-callback.spec.ts @@ -0,0 +1,100 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import { + buildAuthCallbackFragment, + captureAndScrubAuthCallback, + consumeAuthCallback, + redactAuthCallbackFromUrl, + resetAuthCallbackForTest, +} from './auth-callback'; + +const SENTINEL = 'SECRET_CALLBACK_SENTINEL_7f91'; + +describe('authentication callback security', () => { + beforeEach(() => resetAuthCallbackForTest()); + + it('captures a fragment callback and removes credentials before startup', () => { + let cleanUrl = ''; + + const safe = captureAndScrubAuthCallback( + `https://ontrack.example/sign_in#authToken=${SENTINEL}&username=student%40example.edu`, + (_data, _unused, url) => { + cleanUrl = String(url); + }, + ); + + expect(safe).toBe(true); + expect(cleanUrl).toBe('/sign_in'); + expect(cleanUrl).not.toContain(SENTINEL); + expect(consumeAuthCallback()).toEqual({ + username: 'student@example.edu', + authToken: SENTINEL, + ltiToken: undefined, + ltik: undefined, + isLtiLogin: false, + }); + expect(consumeAuthCallback()).toBeUndefined(); + }); + + it('supports and scrubs a legacy LTI query while preserving unrelated values', () => { + let cleanUrl = ''; + + captureAndScrubAuthCallback( + `https://ontrack.example/sign_in?theme=dark<iToken=${SENTINEL}<ik=launch-token&isLtiLogin=true#panel=help`, + (_data, _unused, url) => { + cleanUrl = String(url); + }, + ); + + expect(cleanUrl).toBe('/sign_in?theme=dark#panel=help'); + expect(consumeAuthCallback()).toMatchObject({ + ltiToken: SENTINEL, + ltik: 'launch-token', + isLtiLogin: true, + }); + }); + + it('disables telemetry and drops the callback when history cannot be scrubbed', () => { + const safe = captureAndScrubAuthCallback( + `https://ontrack.example/sign_in#authToken=${SENTINEL}`, + () => { + throw new Error('history unavailable'); + }, + ); + + expect(safe).toBe(false); + expect(consumeAuthCallback()).toBeUndefined(); + }); + + it('encodes fragment callbacks without putting values in a query', () => { + const fragment = buildAuthCallbackFragment({ + username: 'student+alias@example.edu', + authToken: `${SENTINEL}+/=`, + isLtiLogin: true, + }); + const values = new URLSearchParams(fragment); + + expect(fragment).not.toContain('?'); + expect(values.get('username')).toBe('student+alias@example.edu'); + expect(values.get('authToken')).toBe(`${SENTINEL}+/=`); + expect(values.get('isLtiLogin')).toBe('true'); + }); + + it('redacts callback secrets from telemetry URLs', () => { + const redacted = redactAuthCallbackFromUrl( + `https://ontrack.example/sign_in?authToken=${SENTINEL}#ltik=${SENTINEL}`, + ); + + expect(redacted).not.toContain(SENTINEL); + expect(redacted).toContain('%5BFiltered%5D'); + }); + + it('redacts inherited SCORM path credentials from telemetry URLs', () => { + const redacted = redactAuthCallbackFromUrl( + `https://ontrack.example/api/scorm/42/student/${SENTINEL}/index.html`, + ); + + expect(redacted).not.toContain('student'); + expect(redacted).not.toContain(SENTINEL); + expect(redacted).toContain('/api/scorm/42/[Filtered]/[Filtered]/index.html'); + }); +}); diff --git a/src/app/security/auth-callback.ts b/src/app/security/auth-callback.ts new file mode 100644 index 0000000000..450aa0e0d5 --- /dev/null +++ b/src/app/security/auth-callback.ts @@ -0,0 +1,150 @@ +export interface AuthCallbackParameters { + username?: string; + authToken?: string; + ltiToken?: string; + ltik?: string; + isLtiLogin?: boolean; +} + +type ReplaceState = (data: unknown, unused: string, url?: string | URL | null) => void; + +const CALLBACK_KEYS = [ + 'username', + 'authToken', + 'auth_token', + 'ltiToken', + 'lti_token', + 'ltik', + 'isLtiLogin', +] as const; +const SECRET_KEYS = ['authToken', 'auth_token', 'ltiToken', 'lti_token', 'ltik'] as const; + +let pendingCallback: AuthCallbackParameters | undefined; + +const firstValue = ( + fragment: URLSearchParams, + query: URLSearchParams, + ...keys: string[] +): string | undefined => { + for (const key of keys) { + const value = fragment.get(key) ?? query.get(key); + if (value !== null) { + return value; + } + } + + return undefined; +}; + +const callbackFragment = (hash: string): URLSearchParams => + new URLSearchParams(hash.replace(/^#\??/, '')); + +/** + * Capture a one-time authentication callback in module memory and remove it + * from the address bar before telemetry or Angular start. No callback value is + * persisted in browser storage or exposed on window. + */ +export const captureAndScrubAuthCallback = ( + href: string = globalThis.location.href, + replaceState: ReplaceState = (data, unused, url) => + globalThis.history.replaceState(data, unused, url), +): boolean => { + try { + const url = new URL(href); + const fragment = callbackFragment(url.hash); + const containsSecret = SECRET_KEYS.some( + (key) => fragment.has(key) || url.searchParams.has(key), + ); + + if (!containsSecret) { + return true; + } + + const callback: AuthCallbackParameters = { + username: firstValue(fragment, url.searchParams, 'username'), + authToken: firstValue(fragment, url.searchParams, 'authToken', 'auth_token'), + ltiToken: firstValue(fragment, url.searchParams, 'ltiToken', 'lti_token'), + ltik: firstValue(fragment, url.searchParams, 'ltik'), + isLtiLogin: firstValue(fragment, url.searchParams, 'isLtiLogin')?.toLowerCase() === 'true', + }; + + for (const key of CALLBACK_KEYS) { + fragment.delete(key); + url.searchParams.delete(key); + } + + const remainingFragment = fragment.toString(); + url.hash = remainingFragment ? `#${remainingFragment}` : ''; + replaceState(globalThis.history?.state ?? null, '', `${url.pathname}${url.search}${url.hash}`); + pendingCallback = callback; + return true; + } catch { + // If the browser cannot remove the credential from the address bar, keep + // telemetry disabled and force the user through a fresh sign-in. + pendingCallback = undefined; + return false; + } +}; + +export const consumeAuthCallback = (): AuthCallbackParameters | undefined => { + const callback = pendingCallback; + pendingCallback = undefined; + return callback; +}; + +export const buildAuthCallbackFragment = (callback: AuthCallbackParameters): string => { + const params = new URLSearchParams(); + + if (callback.username) { + params.set('username', callback.username); + } + if (callback.authToken) { + params.set('authToken', callback.authToken); + } + if (callback.ltiToken) { + params.set('ltiToken', callback.ltiToken); + } + if (callback.ltik) { + params.set('ltik', callback.ltik); + } + if (callback.isLtiLogin) { + params.set('isLtiLogin', 'true'); + } + + return params.toString(); +}; + +/** Replace credentials defensively if an error SDK later receives a URL. */ +export const redactAuthCallbackFromUrl = (value: string): string => { + try { + const url = new URL(value, globalThis.location?.origin ?? 'https://invalid.local'); + const fragment = callbackFragment(url.hash); + + // The inherited SCORM launch endpoint embeds username/token path segments. + // Redact them from browser telemetry until that endpoint is replaced by a + // cookie/header-backed launch exchange. + url.pathname = url.pathname.replace( + /(\/scorm\/[^/]+\/)[^/]+\/[^/]+(?=\/|$)/, + '$1[Filtered]/[Filtered]', + ); + + for (const key of SECRET_KEYS) { + if (url.searchParams.has(key)) { + url.searchParams.set(key, '[Filtered]'); + } + if (fragment.has(key)) { + fragment.set(key, '[Filtered]'); + } + } + + const redactedFragment = fragment.toString(); + url.hash = redactedFragment ? `#${redactedFragment}` : ''; + return url.toString(); + } catch { + return '[Filtered URL]'; + } +}; + +export const resetAuthCallbackForTest = (): void => { + pendingCallback = undefined; +}; diff --git a/src/app/sessions/states/sign-in/sign-in.component.spec.ts b/src/app/sessions/states/sign-in/sign-in.component.spec.ts index f80e7c1961..351eb579a0 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.spec.ts +++ b/src/app/sessions/states/sign-in/sign-in.component.spec.ts @@ -2,7 +2,7 @@ import {beforeEach, describe, expect, it} from 'vitest'; import {HttpClient} from '@angular/common/http'; import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; -import {ActivatedRoute, Router} from '@angular/router'; +import {Router} from '@angular/router'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {UserService} from 'src/app/api/services/user.service'; import {AlertService} from 'src/app/common/services/alert.service'; @@ -23,7 +23,6 @@ describe('SignInComponent', () => { {provide: AuthenticationService, useValue: emptyProvider}, {provide: UserService, useValue: emptyProvider}, {provide: Router, useValue: emptyProvider}, - {provide: ActivatedRoute, useValue: emptyProvider}, {provide: DoubtfireConstants, useValue: emptyProvider}, {provide: HttpClient, useValue: emptyProvider}, {provide: GlobalStateService, useValue: emptyProvider}, diff --git a/src/app/sessions/states/sign-in/sign-in.component.ts b/src/app/sessions/states/sign-in/sign-in.component.ts index 4e1905a484..f55dbbb2d5 100644 --- a/src/app/sessions/states/sign-in/sign-in.component.ts +++ b/src/app/sessions/states/sign-in/sign-in.component.ts @@ -1,24 +1,13 @@ import {HttpClient} from '@angular/common/http'; import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; +import {Router} from '@angular/router'; import {BehaviorSubject} from 'rxjs'; import {AuthenticationService} from 'src/app/api/services/authentication.service'; import {UserService} from 'src/app/api/services/user.service'; import {AlertService} from 'src/app/common/services/alert.service'; import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; import {GlobalStateService} from 'src/app/projects/states/index/global-state.service'; - -// Add fallback to check url for query parameters -type IParams = Record; - -const paramReducer = (params: IParams, pair: string): IParams => { - const [key, value] = `${pair}=`.split('=').map(decodeURIComponent); - - return key.length > 0 ? {...params, [key]: value} : params; -}; - -const getUrlParams = (search: string): IParams => - `${search}?`.split('?')[1].split('&').reduce(paramReducer, {}); +import {consumeAuthCallback} from 'src/app/security/auth-callback'; type signInData = | { @@ -67,7 +56,6 @@ export class SignInComponent implements OnInit { public authService: AuthenticationService, private userService: UserService, private router: Router, - private route: ActivatedRoute, private constants: DoubtfireConstants, private http: HttpClient, private globalState: GlobalStateService, @@ -75,15 +63,21 @@ export class SignInComponent implements OnInit { ) {} ngOnInit(): void { + const callback = consumeAuthCallback(); + this.username = callback?.username ?? this.username; + this.authToken = callback?.authToken ?? this.authToken; + this.ltiToken = callback?.ltiToken ?? this.ltiToken; + this.ltik = callback?.ltik ?? this.ltik; + this.isLtiLogin = callback?.isLtiLogin ?? this.isLtiLogin; + this.authService.afterAuthCall((result) => { if (result) { - const params = getUrlParams(document.location.href); this.isLoading = false; - if (params.isLtiLogin && params.ltik) { + if (this.isLtiLogin && this.ltik) { this.globalState.hideHeader(); - this.userService.currentUser.ltik = params.ltik; - return this.router.navigate(['/lti'], {queryParams: {ltik: params.ltik}}); + this.userService.currentUser.ltik = this.ltik; + return this.router.navigateByUrl('/lti'); } else if (this.userService.currentUser.hasRunFirstTimeSetup === false) { return this.router.navigateByUrl('/welcome'); } else { @@ -114,18 +108,6 @@ export class SignInComponent implements OnInit { this.api = this.constants.API_URL; this.externalName = this.constants.ExternalName; - const queryParams = this.route.snapshot.queryParams; - const params = getUrlParams(document.location.href); - if (!this.username) { - this.username = queryParams.username || params.username; - this.authToken = queryParams.authToken || params.authToken; - } - - this.ltiToken = queryParams.ltiToken || params.ltiToken || undefined; - this.ltik = queryParams.ltik || params.ltik || undefined; - this.isLtiLogin = - (queryParams.isLtiLogin || params.isLtiLogin)?.toLowerCase() === 'true' ? true : false; - // wait 2 seconds with rxjs const wait = new Promise((resolve) => setTimeout(resolve, 3000)); this.http.get(`${this.constants.API_URL}/auth/method`).subscribe({ @@ -253,8 +235,8 @@ export class SignInComponent implements OnInit { this.authService.signIn(signInCredentials).subscribe({ next: () => { if (this.isLtiLogin) { - const params = getUrlParams(document.location.href); - this.router.navigate(['/lti'], {queryParams: {ltik: params.ltik}}); + this.userService.currentUser.ltik = this.ltik; + this.router.navigateByUrl('/lti'); } else { this.actionSignInSuccess(); } diff --git a/src/index.html b/src/index.html index f2d5aa9c95..e1ac26e210 100644 --- a/src/index.html +++ b/src/index.html @@ -2,17 +2,7 @@ - - - + Date: Mon, 24 Aug 2026 13:00:59 +1000 Subject: [PATCH 1432/1531] chore(deploy): harden the production web artifact --- .github/workflows/deployment.yml | 4 +- .github/workflows/nodejs-ci.yml | 3 + README.md | 146 +++++++++++++--------- deploy.Dockerfile | 7 +- nginx.conf | 43 +++++++ package.json | 1 + scripts/verify-deployment-config.js | 75 +++++++++++ src/environments/environment.prod.spec.ts | 12 ++ src/environments/environment.prod.ts | 14 ++- 9 files changed, 238 insertions(+), 67 deletions(-) create mode 100644 scripts/verify-deployment-config.js create mode 100644 src/environments/environment.prod.spec.ts diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 6c986fcff7..642900037c 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -41,7 +41,7 @@ jobs: # context: . # push: ${{ github.event_name != 'pull_request' }} # tags: ${{ steps.docker_meta.outputs.tags }} - # labels: ${{ steps.meta.outputs.labels }} + # labels: ${{ steps.docker_meta.outputs.labels }} # - name: Image digest # run: echo ${{ steps.docker_build.outputs.digest }} docker-web-server: @@ -80,6 +80,6 @@ jobs: context: . push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.docker_meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + labels: ${{ steps.docker_meta.outputs.labels }} - name: Image digest run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/.github/workflows/nodejs-ci.yml b/.github/workflows/nodejs-ci.yml index df3f516514..72086ff3e9 100644 --- a/.github/workflows/nodejs-ci.yml +++ b/.github/workflows/nodejs-ci.yml @@ -16,10 +16,13 @@ jobs: node-version: [22] steps: - uses: actions/checkout@v6 + with: + submodules: recursive - uses: browser-actions/setup-chrome@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v5 with: node-version: ${{ matrix.node-version }} - run: npm ci + - run: npm run verify:deployment-config - run: npm run build --if-present diff --git a/README.md b/README.md index b050cbf4a6..c0780a02c2 100644 --- a/README.md +++ b/README.md @@ -2,110 +2,140 @@ OnTrack logo

        -# OnTrack Web [![CI](https://img.shields.io/github/workflow/status/doubtfire-lms/doubtfire-web/Node.js%20CI?label=CI&logo=GitHub)](https://github.com/doubtfire-lms/doubtfire-web/actions/workflows/nodejs-ci.yml) +# OnTrack Web [![CI](https://github.com/doubtfire-lms/doubtfire-web/actions/workflows/nodejs-ci.yml/badge.svg)](https://github.com/doubtfire-lms/doubtfire-web/actions/workflows/nodejs-ci.yml) A modern, lightweight learning management system. ## Table of Contents -- [Doubtfire Web ![CI](https://github.com/doubtfire-lms/doubtfire-web/actions/workflows/nodejs-ci.yml)](#doubtfire-web-) - - [Table of Contents](#table-of-contents) - - [Getting Started](#getting-started) - - [Deployment](#deployment) - - [Resources](#resources) - - [Contributing](#contributing) - - [License](#license) +- [Getting Started](#getting-started) +- [Checks](#checks) +- [Production build and handover](#production-build-and-handover) +- [Demo and live feature boundaries](#demo-and-live-feature-boundaries) +- [Resources](#resources) +- [Contributing](#contributing) +- [License](#license) ## Getting Started -If you will be using [Docker](https://github.com/doubtfire-lms/doubtfire-api/#getting-started-via-docker), follow the instructions there. - -Before you get started, make sure you have the [Doubtfire API](https://github.com/doubtfire-lms/doubtfire-api) up and running. You will need to do this before continuing. - -First, clone the web repository, and change to the root directory: +OnTrack Web requires Node.js 22.22.3 or newer. The exact handover version is in +`.nvmrc`. Clone recursively because the JPlag report viewer is a production +asset supplied by a git submodule: ```sh -git clone https://github.com/doubtfire-lms/doubtfire-web.git -cd ./doubtfire-web +git clone --recurse-submodules https://github.com/doubtfire-lms/doubtfire-web.git +cd doubtfire-web +git submodule update --init --recursive +nvm install +nvm use +npm ci ``` -You can automate the installation process by running the automated setup script: +Run the [Doubtfire API](https://github.com/doubtfire-lms/doubtfire-api) on +`http://localhost:3000`, then start the Angular development server: ```sh -./setup.sh +npm start ``` -Or, you can continue following the below steps to manually install `doubtfire-web`. - -Install [Node.js](http://nodejs.org/) either by [downloading it](http://nodejs.org/download/) and installing it manually, or via [Homebrew](http://brew.sh) on OS X: +Open . `proxy.conf.json` forwards `/api` to the local API. +It also forwards `/lti/api` to the optional local LTI service on port 3001; LTI +requests will fail if that service is not running. -```sh -brew install node -``` +## Checks -_or_ by using `apt-get` on Linux: +Run the same checks required for a release before handing the branch over: ```sh -curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - -sudo apt-get install nodejs +npm run verify:deployment-config +npm run lint +npm run typecheck +npm run test:ci +npm run deploy ``` -Install Ruby [SASS](http://sass-lang.com): +## Production build and handover -```sh -gem install sass -``` +The production application deliberately uses the browser origin for both API +contracts: -If `gem` fails, you should read the Doubtfire API README to install ruby. If you are _not_ using `rbenv`, e.g., using Docker instead, you may need to prepend `sudo` to the above commands to have root write access. +- `/api` must be reverse-proxied to Doubtfire API. +- `/lti/api` must be reverse-proxied to the LTI service when LTI is enabled. -If using `rbenv`, rehash to ensure each of the gems are on your `PATH`: +`DF_API_URL` is not a runtime switch for the Angular production build. Hosting +the API on another origin requires an explicit web configuration and matching +CORS policy. Production must use HTTPS for service workers, installation, and +Web Push. + +Build the static production bundle directly with: ```sh -rbenv rehash +npm ci +git submodule update --init --recursive +npm run deploy ``` -Install all node dependencies using `npm`, as well as [grunt-cli](http://gruntjs.com/using-the-cli) globally: +Or build the production Nginx image, which is the release artifact used by the +deployment repository: ```sh -npm install +docker build -f deploy.Dockerfile -t doubtfire-web:handover . +docker run --rm -p 8080:80 doubtfire-web:handover ``` -**Note:** You may need to install `grunt-cli` globally in Linux using `sudo`. +The Dockerfile pins its Node and Nginx base images by multi-architecture digest +and performs the build as the unprivileged `node` user. Refresh those digests +deliberately as part of a reviewed dependency update; do not replace them with +floating tags for a release. + +Sentry is optional. Direct production builds leave it disabled. The image build +can substitute `SENTRY_DSN`, `SENTRY_RELEASE`, and `SENTRY_DIST`; source-map +upload additionally requires the documented Sentry build arguments and a +BuildKit `sentry_auth_token` secret. -Lastly, to compile and run a watch server and web server, use `npm start`: +Before publishing, verify the generated service-worker files and JPlag assets: ```sh -npm start +test -f dist/browser/index.html +test -f dist/browser/ngsw.json +test -f dist/browser/ngsw-worker.js +test -f dist/browser/manifest.webmanifest +test -n "$(find dist/browser/JPlag -mindepth 1 -maxdepth 1 -print -quit)" ``` -This will automatically run the angular 1 `grunt watch`, and the angular 7 `ng serve`. +Against the running image, confirm application routes fall back to `index.html`, +each named control-file URL returns 404 rather than HTML if its build output is +missing, and these files return `Cache-Control: no-store, no-cache` when present: -You can then navigate to the Doubtfire web interface at **http://localhost:8000**. +- `/index.html` +- `/ngsw.json` +- `/ngsw-worker.js` +- `/safety-worker.js` +- `/worker-basic.min.js` +- `/manifest.webmanifest` -## Deployment +The external proxy or CDN must preserve that cache policy. Pin the tested image +digest in `doubtfire-deploy`, then smoke-test sign-in, API routing, service-worker +registration/update, and any enabled LTI or Web Push integration. -To compile the front-end, ensure `doubtfire-api` is placed as a sibling directory to `doubtfire-web`, then run: +## Demo and live feature boundaries -```sh -cd /path/to/repos -ls -doubtfire-api doubtfire-web -cd ./doubtfire-api -grunt deploy -``` - -You may prefix this command with the following environment variables: +Demo source, fixtures, controls, and evidence remain in the repository for local +demonstrations. Production builds set `production: true` and +`enableDemoTools: false`; `/demo-controls` is unavailable and genuine API data +passes through unchanged. Do not change that flag from deployment tooling. -- `DF_API_URL` - the URL of the API (e.g., `https://doubtfire.com/api`). This will default to `window.location.host` if not set and dynamically generate a URL. -- `DF_EXTERNAL_NAME` - a new name that removes references to the _Doubtfire_ name should you so want to not use such its original name (😢). +Task-level peer progress is live when the matching API feature and privacy +configuration are enabled. The unit summary and burndown peer-median displays +are explicitly demo-only fixtures. The push-notification demo preview is visual +only; real Web Push requires API VAPID configuration, HTTPS, a running worker, +and browser permission. ## Resources -Doubtfire Web is an [Angular](https://angular.dev) application built using [Material UI]https://material.angular.dev). It uses many Open Source libraries, which you can read up on: - -- [Lodash](http://lodash.com/docs) -- [Moment.js](http://momentjs.com) -- [NVD3 Charts](http://krispo.github.io/angular-nvd3/#/) +Doubtfire Web is an [Angular](https://angular.dev) application using +[Angular Material](https://material.angular.dev/). Production is served as a +static progressive web application by Nginx. ## Contributing diff --git a/deploy.Dockerfile b/deploy.Dockerfile index ce51c53b13..3a1f5b0993 100644 --- a/deploy.Dockerfile +++ b/deploy.Dockerfile @@ -1,5 +1,5 @@ ### STAGE 1: Build ### -FROM node:22 AS build +FROM node:22.22.3-bookworm-slim@sha256:e21fc383b50d5347dc7a9f1cae45b8f4e2f0d39f7ade28e4eef7d2934522b752 AS build RUN apt-get update && apt-get install -y --no-install-recommends \ gettext-base \ @@ -11,10 +11,9 @@ USER node # Copy in doubtfire-web code WORKDIR /doubtfire-web COPY package.json package-lock.json ./ -RUN npm ci --force --include=optional +RUN npm ci --include=optional COPY --chown=node:node . . -RUN chmod 777 src ARG SENTRY_DSN ARG SENTRY_ORG @@ -42,7 +41,7 @@ RUN --mount=type=secret,id=sentry_auth_token,uid=1000 \ ## STAGE 2: Host ### -FROM nginx:1.29.0-alpine +FROM nginx:1.30.4-alpine@sha256:97d490c12ba55b4946b01546d1c3ed324e8d41ab1c9fcb2a616aa470620e5b46 # Remove the default Nginx configuration file RUN rm -v /etc/nginx/nginx.conf diff --git a/nginx.conf b/nginx.conf index 0914d0a344..889b629cc0 100644 --- a/nginx.conf +++ b/nginx.conf @@ -5,6 +5,20 @@ events { } http { include /etc/nginx/mime.types; + # The Angular app shell and service-worker control files must always be + # revalidated. `$uri` excludes query parameters, so cache-busting query + # strings cannot bypass this policy. An empty value is not emitted for + # fingerprinted bundles and other static assets. + map $uri $ontrack_control_file_cache_control { + default ""; + /index.html "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; + /ngsw.json "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; + /ngsw-worker.js "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; + /safety-worker.js "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; + /worker-basic.min.js "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; + /manifest.webmanifest "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; + } + sendfile on; server { root /usr/share/nginx/html/; @@ -13,6 +27,35 @@ http { add_header Content-Security-Policy "default-src https: 'unsafe-inline' 'unsafe-eval' blob: data: ws:; worker-src 'self' blob:; child-src 'self' blob:" always; add_header Permissions-Policy "microphone=(self),fullscreen=(self),payment=()" always; + add_header Cache-Control $ontrack_control_file_cache_control always; + + # Do not serve the SPA fallback under a service-worker or manifest URL. + # A missing control file must be a real 404, otherwise browsers can try + # to execute index.html as JavaScript. Internal SPA fallback redirects + # still resolve through the exact /index.html location below. + location = /index.html { + try_files $uri =404; + } + + location = /ngsw.json { + try_files $uri =404; + } + + location = /ngsw-worker.js { + try_files $uri =404; + } + + location = /safety-worker.js { + try_files $uri =404; + } + + location = /worker-basic.min.js { + try_files $uri =404; + } + + location = /manifest.webmanifest { + try_files $uri =404; + } location / { try_files $uri $uri/ $uri/index.html /index.html; diff --git a/package.json b/package.json index b3b4d379dc..9325d66d1c 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "deploy:build2api": "ng build --delete-output-path=true --optimization=true --configuration production --output-path dist", "deploy:build2api:sourcemaps": "ng build --delete-output-path=true --optimization=true --configuration production --source-map=true --output-path dist", "sentry:sourcemaps": "node scripts/upload-sentry-sourcemaps.js", + "verify:deployment-config": "node scripts/verify-deployment-config.js", "deploy": "run-s -l deploy:build2api", "prepare": "husky install", "test": "ng test", diff --git a/scripts/verify-deployment-config.js b/scripts/verify-deployment-config.js new file mode 100644 index 0000000000..430345279c --- /dev/null +++ b/scripts/verify-deployment-config.js @@ -0,0 +1,75 @@ +const assert = require('node:assert/strict'); +const {readFileSync} = require('node:fs'); +const {resolve} = require('node:path'); + +const root = resolve(__dirname, '..'); +const nginx = readFileSync(resolve(root, 'nginx.conf'), 'utf8'); +const dockerfile = readFileSync(resolve(root, 'deploy.Dockerfile'), 'utf8'); +const deploymentWorkflow = readFileSync(resolve(root, '.github/workflows/deployment.yml'), 'utf8'); +const productionEnvironment = readFileSync( + resolve(root, 'src/environments/environment.prod.ts'), + 'utf8', +); + +const controlFiles = [ + '/index.html', + '/ngsw.json', + '/ngsw-worker.js', + '/safety-worker.js', + '/worker-basic.min.js', + '/manifest.webmanifest', +]; +const noStorePolicy = 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; + +const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + +for (const path of controlFiles) { + const escapedPath = escapeRegExp(path); + + assert.match( + nginx, + new RegExp(`^\\s*${escapedPath}\\s+"${noStorePolicy}";`, 'm'), + `${path} must map to the no-store cache policy`, + ); + assert.match( + nginx, + new RegExp(`location = ${escapedPath} \\{\\s*try_files \\$uri =404;\\s*\\}`, 'm'), + `${path} must use an exact location and return 404 when absent`, + ); +} + +assert.match( + nginx, + /add_header Cache-Control \$ontrack_control_file_cache_control always;/, + 'the mapped cache policy must be added to responses', +); +assert.match( + nginx, + /try_files \$uri \$uri\/ \$uri\/index\.html \/index\.html;/, + 'SPA routes must continue to fall back to /index.html', +); +assert.doesNotMatch( + deploymentWorkflow, + /steps\.meta\.outputs\.labels/, + 'deployment metadata labels must reference the declared docker_meta step', +); +assert.match(deploymentWorkflow, /steps\.docker_meta\.outputs\.labels/); +assert.match( + dockerfile, + /^FROM node:22\.22\.3-bookworm-slim@sha256:[0-9a-f]{64} AS build$/m, + 'the release build must pin the supported Node image digest', +); +assert.match( + dockerfile, + /^FROM nginx:1\.30\.4-alpine@sha256:[0-9a-f]{64}$/m, + 'the release runtime must pin the Nginx image digest', +); +assert.doesNotMatch(dockerfile, /npm ci[^\n]*--force/, 'the release build must not force npm resolution'); +assert.doesNotMatch(dockerfile, /chmod\s+777/, 'the release build must not create world-writable source'); +assert.match( + productionEnvironment, + /enableDemoTools:\s*false/, + 'production must keep demo tools disabled', +); + +console.log('Deployment configuration checks passed.'); diff --git a/src/environments/environment.prod.spec.ts b/src/environments/environment.prod.spec.ts new file mode 100644 index 0000000000..5b0dc75d17 --- /dev/null +++ b/src/environments/environment.prod.spec.ts @@ -0,0 +1,12 @@ +import {describe, expect, it} from 'vitest'; +import {environment} from './environment.prod'; + +describe('production environment', () => { + it('fails closed for demos and unresolved optional telemetry settings', () => { + expect(environment.production).toBe(true); + expect(environment.enableDemoTools).toBe(false); + expect(environment.sentryDsn).toBe(''); + expect(environment.sentryRelease).toBe(''); + expect(environment.sentryDist).toBe(''); + }); +}); diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 2e2458489c..21dbe97419 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,3 +1,11 @@ +/** + * Docker replaces optional build values before Angular compiles this file. + * A direct production build leaves the `${...}` marker intact; normalising + * unresolved markers to an empty string keeps optional telemetry disabled. + */ +const optionalBuildValue = (value: string): string => + value.startsWith('${') && value.endsWith('}') ? '' : value; + export const environment = { production: true, @@ -8,7 +16,7 @@ export const environment = { // Demo mode must never be enabled by a production build. enableDemoTools: false, - sentryDsn: '${SENTRY_DSN}', - sentryRelease: '${SENTRY_RELEASE}', - sentryDist: '${SENTRY_DIST}', + sentryDsn: optionalBuildValue('${SENTRY_DSN}'), + sentryRelease: optionalBuildValue('${SENTRY_RELEASE}'), + sentryDist: optionalBuildValue('${SENTRY_DIST}'), }; From 8ef1be045fbd153ee9a33320bff07bda0e54b82b Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 13:27:23 +1000 Subject: [PATCH 1433/1531] fix(security): remove credential-bearing telemetry paths --- .env.example | 14 +++++++ .gitignore | 1 + README.md | 6 +++ docker-compose.yml | 21 +++++----- scripts/verify-deployment-config.js | 38 ++++++++++++++++++- .../scorm-player/scorm-player.component.html | 2 +- src/app/security/auth-callback.spec.ts | 5 ++- src/app/security/auth-callback.ts | 3 +- src/main.ts | 8 ++-- 9 files changed, 79 insertions(+), 19 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000..af8ec52c7f --- /dev/null +++ b/.env.example @@ -0,0 +1,14 @@ +# Optional values for development through the legacy root docker-compose.yml. +# Copy this file to .env. Database authentication remains the safe default. +# Never commit an institution credential or a populated .env file. +DF_AUTH_METHOD=database + +# To exercise AAF locally, obtain a dedicated non-production registration from +# the identity owner, change DF_AUTH_METHOD to aaf, and fill every field below. +DF_AAF_ISSUER_URL= +DF_AAF_AUDIENCE_URL=http://localhost:4200 +DF_AAF_CALLBACK_URL=http://localhost:4200/api/auth/jwt +DF_AAF_IDENTITY_PROVIDER_URL= +DF_AAF_UNIQUE_URL= +DF_AAF_AUTH_SIGNOUT_URL= +DF_SECRET_KEY_AAF= diff --git a/.gitignore b/.gitignore index 9912f41615..65909d007d 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ vendor/ tmp.scss .tscache a.env +.env dist/ .angulardoc.json .nx diff --git a/README.md b/README.md index c0780a02c2..b8971c9688 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,12 @@ Open . `proxy.conf.json` forwards `/api` to the local API It also forwards `/lti/api` to the optional local LTI service on port 3001; LTI requests will fail if that service is not running. +The legacy root `docker-compose.yml` also defaults to local database +authentication. Optional AAF development must use a dedicated non-production +registration supplied through an ignored `.env` file copied from +`.env.example`. Any AAF secret ever committed to Git must be treated as +compromised and rotated by its identity owner. + ## Checks Run the same checks required for a release before handing the branch over: diff --git a/docker-compose.yml b/docker-compose.yml index ee16895e5d..e478833212 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3' services: doubtfire-api: container_name: web-doubtfire-api @@ -21,15 +20,17 @@ services: DF_SECRET_KEY_ATTR: test-secret-key-test-secret-key! DF_SECRET_KEY_DEVISE: test-secret-key-test-secret-key! - # Authentication method - can set to AAF or ldap - DF_AUTH_METHOD: database - DF_AAF_ISSUER_URL: https://rapid.test.aaf.edu.au - DF_AAF_AUDIENCE_URL: http://localhost:4200 - DF_AAF_CALLBACK_URL: http://localhost:4200/api/auth/jwt - DF_AAF_IDENTITY_PROVIDER_URL: https://signon-uat.deakin.edu.au/idp/shibboleth - DF_AAF_UNIQUE_URL: https://rapid.test.aaf.edu.au/jwt/authnrequest/research/Ag4EJJhjf0zXHqlKvKZEbg - DF_AAF_AUTH_SIGNOUT_URL: https://sync-uat.deakin.edu.au/auth/logout - DF_SECRET_KEY_AAF: v4~LMFLzzwRGZdju\5QBa@FiHIN9 + # Database authentication is the safe local default. Optional AAF + # development values must come from an ignored .env file; never commit an + # institution credential or registration URL here. + DF_AUTH_METHOD: ${DF_AUTH_METHOD:-database} + DF_AAF_ISSUER_URL: ${DF_AAF_ISSUER_URL:-} + DF_AAF_AUDIENCE_URL: ${DF_AAF_AUDIENCE_URL:-http://localhost:4200} + DF_AAF_CALLBACK_URL: ${DF_AAF_CALLBACK_URL:-http://localhost:4200/api/auth/jwt} + DF_AAF_IDENTITY_PROVIDER_URL: ${DF_AAF_IDENTITY_PROVIDER_URL:-} + DF_AAF_UNIQUE_URL: ${DF_AAF_UNIQUE_URL:-} + DF_AAF_AUTH_SIGNOUT_URL: ${DF_AAF_AUTH_SIGNOUT_URL:-} + DF_SECRET_KEY_AAF: ${DF_SECRET_KEY_AAF:-} # Database settings - for development env DF_DEV_DB_ADAPTER: mysql2 diff --git a/scripts/verify-deployment-config.js b/scripts/verify-deployment-config.js index 430345279c..36011a45e2 100644 --- a/scripts/verify-deployment-config.js +++ b/scripts/verify-deployment-config.js @@ -5,7 +5,13 @@ const {resolve} = require('node:path'); const root = resolve(__dirname, '..'); const nginx = readFileSync(resolve(root, 'nginx.conf'), 'utf8'); const dockerfile = readFileSync(resolve(root, 'deploy.Dockerfile'), 'utf8'); +const developmentCompose = readFileSync(resolve(root, 'docker-compose.yml'), 'utf8'); const deploymentWorkflow = readFileSync(resolve(root, '.github/workflows/deployment.yml'), 'utf8'); +const applicationBootstrap = readFileSync(resolve(root, 'src/main.ts'), 'utf8'); +const scormPlayerTemplate = readFileSync( + resolve(root, 'src/app/common/scorm-player/scorm-player.component.html'), + 'utf8', +); const productionEnvironment = readFileSync( resolve(root, 'src/environments/environment.prod.ts'), 'utf8', @@ -64,8 +70,36 @@ assert.match( /^FROM nginx:1\.30\.4-alpine@sha256:[0-9a-f]{64}$/m, 'the release runtime must pin the Nginx image digest', ); -assert.doesNotMatch(dockerfile, /npm ci[^\n]*--force/, 'the release build must not force npm resolution'); -assert.doesNotMatch(dockerfile, /chmod\s+777/, 'the release build must not create world-writable source'); +assert.doesNotMatch( + dockerfile, + /npm ci[^\n]*--force/, + 'the release build must not force npm resolution', +); +assert.doesNotMatch( + dockerfile, + /chmod\s+777/, + 'the release build must not create world-writable source', +); +assert.match( + developmentCompose, + /DF_SECRET_KEY_AAF:\s*\$\{DF_SECRET_KEY_AAF:-\}/, + 'optional development AAF credentials must come from the ignored environment', +); +assert.doesNotMatch( + developmentCompose, + /https?:\/\/[^\s$]*(?:aaf\.edu\.au|deakin\.edu\.au)/i, + 'institution-specific AAF endpoints must not be committed in development Compose', +); +assert.doesNotMatch( + applicationBootstrap, + /(?:browserTracingIntegration|replayIntegration|tracesSampleRate|replaysSessionSampleRate|replaysOnErrorSampleRate)/, + 'tracing and replay must stay disabled while SCORM uses credential-bearing paths', +); +assert.match( + scormPlayerTemplate, + /]*data-sentry-block[^>]*referrerpolicy="no-referrer"/, + 'the SCORM iframe must suppress referrers and remain blocked from any future replay integration', +); assert.match( productionEnvironment, /enableDemoTools:\s*false/, diff --git a/src/app/common/scorm-player/scorm-player.component.html b/src/app/common/scorm-player/scorm-player.component.html index 0e36d95f4f..0214ecc7ab 100644 --- a/src/app/common/scorm-player/scorm-player.component.html +++ b/src/app/common/scorm-player/scorm-player.component.html @@ -1,3 +1,3 @@ @if (iframeSrc) { - + } diff --git a/src/app/security/auth-callback.spec.ts b/src/app/security/auth-callback.spec.ts index c49487e218..c55b1d1b33 100644 --- a/src/app/security/auth-callback.spec.ts +++ b/src/app/security/auth-callback.spec.ts @@ -80,11 +80,14 @@ describe('authentication callback security', () => { }); it('redacts callback secrets from telemetry URLs', () => { + const callbackUsername = 'student.person@example.edu'; const redacted = redactAuthCallbackFromUrl( - `https://ontrack.example/sign_in?authToken=${SENTINEL}#ltik=${SENTINEL}`, + `https://ontrack.example/sign_in?authToken=${SENTINEL}&username=${encodeURIComponent(callbackUsername)}#ltik=${SENTINEL}&user_name=${encodeURIComponent(callbackUsername)}`, ); expect(redacted).not.toContain(SENTINEL); + expect(redacted).not.toContain('student.person'); + expect(redacted).not.toContain(encodeURIComponent(callbackUsername)); expect(redacted).toContain('%5BFiltered%5D'); }); diff --git a/src/app/security/auth-callback.ts b/src/app/security/auth-callback.ts index 450aa0e0d5..6cc54adab4 100644 --- a/src/app/security/auth-callback.ts +++ b/src/app/security/auth-callback.ts @@ -18,6 +18,7 @@ const CALLBACK_KEYS = [ 'isLtiLogin', ] as const; const SECRET_KEYS = ['authToken', 'auth_token', 'ltiToken', 'lti_token', 'ltik'] as const; +const TELEMETRY_KEYS = [...SECRET_KEYS, 'username', 'user_name'] as const; let pendingCallback: AuthCallbackParameters | undefined; @@ -128,7 +129,7 @@ export const redactAuthCallbackFromUrl = (value: string): string => { '$1[Filtered]/[Filtered]', ); - for (const key of SECRET_KEYS) { + for (const key of TELEMETRY_KEYS) { if (url.searchParams.has(key)) { url.searchParams.set(key, '[Filtered]'); } diff --git a/src/main.ts b/src/main.ts index afefa0af4d..9ddbad48fd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -18,10 +18,10 @@ if (environment.sentryDsn && telemetrySafe) { tunnel: '/api/client-reports', release: environment.sentryRelease || undefined, dist: environment.sentryDist || undefined, - integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()], - tracesSampleRate: 1, - replaysSessionSampleRate: 0.1, - replaysOnErrorSampleRate: 1, + // Keep telemetry to redacted error events for this release. Browser tracing + // and Session Replay can observe iframe/resource URLs outside beforeSend; + // legacy SCORM URLs still contain a reusable credential in their path. + // They must stay disabled until that launch protocol is redesigned. enableLogs: true, sendDefaultPii: false, beforeSend(event) { From 6e014cb3d487b4221e1886cd1dab3624bfddbaf3 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 13:51:50 +1000 Subject: [PATCH 1434/1531] ci(deploy): harden image publication workflows --- .github/workflows/deployment-institution.yml | 12 ++++--- .github/workflows/deployment.yml | 12 ++++--- scripts/verify-deployment-config.js | 35 ++++++++++++++++---- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/.github/workflows/deployment-institution.yml b/.github/workflows/deployment-institution.yml index d9f6075048..7bb05d76f0 100644 --- a/.github/workflows/deployment-institution.yml +++ b/.github/workflows/deployment-institution.yml @@ -11,11 +11,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 with: submodules: recursive - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4 - name: Check custom institution deployment secrets id: custom_config env: @@ -30,14 +30,14 @@ jobs: echo "Skipping custom institution Docker publish because one or more institution secrets are not set." fi - name: Login to DockerHub - uses: docker/login-action@v4 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4 if: github.event_name != 'pull_request' && steps.custom_config.outputs.enabled == 'true' with: username: ${{ secrets.INSTITUTION_DOCKERHUB_USERNAME }} password: ${{ secrets.INSTITUTION_DOCKERHUB_TOKEN }} - name: Setup meta for custom institution web server id: docker_meta - uses: docker/metadata-action@v6 + uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6 if: steps.custom_config.outputs.enabled == 'true' with: images: ${{ secrets.INSTITUTION_DOCKERHUB_USERNAME }}/${{ secrets.INSTITUTION }} @@ -49,7 +49,7 @@ jobs: type=semver,pattern=prod-{{major}} - name: Build and push custom web server id: docker_build - uses: docker/build-push-action@v7 + uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7 if: steps.custom_config.outputs.enabled == 'true' with: file: deploy.Dockerfile @@ -57,6 +57,8 @@ jobs: push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} + sbom: true + provenance: mode=max build-args: | SENTRY_DSN=${{ secrets.SENTRY_DSN }} SENTRY_ORG=${{ secrets.SENTRY_ORG }} diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 642900037c..507dfb6c2a 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -50,20 +50,20 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 with: submodules: recursive - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4 - name: Login to DockerHub - uses: docker/login-action@v4 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4 if: github.event_name != 'pull_request' with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Setup meta for web server id: docker_meta - uses: docker/metadata-action@v6 + uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6 with: images: lmsdoubtfire/doubtfire-web tags: | @@ -74,12 +74,14 @@ jobs: type=semver,pattern=prod-{{major}} - name: Build and push web server id: docker_build - uses: docker/build-push-action@v7 + uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7 with: file: deploy.Dockerfile context: . push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} + sbom: true + provenance: mode=max - name: Image digest run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/scripts/verify-deployment-config.js b/scripts/verify-deployment-config.js index 36011a45e2..2755991193 100644 --- a/scripts/verify-deployment-config.js +++ b/scripts/verify-deployment-config.js @@ -6,7 +6,13 @@ const root = resolve(__dirname, '..'); const nginx = readFileSync(resolve(root, 'nginx.conf'), 'utf8'); const dockerfile = readFileSync(resolve(root, 'deploy.Dockerfile'), 'utf8'); const developmentCompose = readFileSync(resolve(root, 'docker-compose.yml'), 'utf8'); -const deploymentWorkflow = readFileSync(resolve(root, '.github/workflows/deployment.yml'), 'utf8'); +const deploymentWorkflows = [ + ['default', readFileSync(resolve(root, '.github/workflows/deployment.yml'), 'utf8')], + [ + 'institution', + readFileSync(resolve(root, '.github/workflows/deployment-institution.yml'), 'utf8'), + ], +]; const applicationBootstrap = readFileSync(resolve(root, 'src/main.ts'), 'utf8'); const scormPlayerTemplate = readFileSync( resolve(root, 'src/app/common/scorm-player/scorm-player.component.html'), @@ -54,12 +60,27 @@ assert.match( /try_files \$uri \$uri\/ \$uri\/index\.html \/index\.html;/, 'SPA routes must continue to fall back to /index.html', ); -assert.doesNotMatch( - deploymentWorkflow, - /steps\.meta\.outputs\.labels/, - 'deployment metadata labels must reference the declared docker_meta step', -); -assert.match(deploymentWorkflow, /steps\.docker_meta\.outputs\.labels/); +for (const [name, workflow] of deploymentWorkflows) { + assert.doesNotMatch( + workflow, + /steps\.meta\.outputs\.labels/, + `${name} deployment metadata labels must reference the declared docker_meta step`, + ); + assert.match(workflow, /steps\.docker_meta\.outputs\.labels/); + + for (const line of workflow.split('\n')) { + if (/^\s*uses:/.test(line)) { + assert.match( + line, + /@[0-9a-f]{40}(?:\s+#.*)?$/, + `${name} production image workflow actions must be pinned to immutable commits`, + ); + } + } + + assert.match(workflow, /^\s*sbom:\s*true$/m); + assert.match(workflow, /^\s*provenance:\s*mode=max$/m); +} assert.match( dockerfile, /^FROM node:22\.22\.3-bookworm-slim@sha256:[0-9a-f]{64} AS build$/m, From 5083dbd43811a8308db409e50d462d5822338921 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 18:38:42 +1000 Subject: [PATCH 1435/1531] ci: enforce OnTrack review policy --- .github/CODEOWNERS | 5 + .github/review-policy/README.md | 48 ++ .github/review-policy/evaluate.mjs | 530 ++++++++++++++++++ .github/review-policy/evaluate.test.mjs | 221 ++++++++ .../ontrack-review-policy-signal.yml | 32 ++ .github/workflows/ontrack-review-policy.yml | 56 ++ 6 files changed, 892 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/review-policy/README.md create mode 100644 .github/review-policy/evaluate.mjs create mode 100644 .github/review-policy/evaluate.test.mjs create mode 100644 .github/workflows/ontrack-review-policy-signal.yml create mode 100644 .github/workflows/ontrack-review-policy.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..1cc4d7d71b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# The App key is available only to the default-branch policy job. Keep every +# workflow and the evaluator itself under lead review. +/.github/workflows/ @ontrack-features-t2-2026/ontrack-leads +/.github/review-policy/ @ontrack-features-t2-2026/ontrack-leads +/.github/CODEOWNERS @ontrack-features-t2-2026/ontrack-leads diff --git a/.github/review-policy/README.md b/.github/review-policy/README.md new file mode 100644 index 0000000000..9fa7103867 --- /dev/null +++ b/.github/review-policy/README.md @@ -0,0 +1,48 @@ +# OnTrack pull-request review policy + +The required status context `ontrack/review-policy` passes when the current pull +request head has either: + +- one approval from a current `ontrack-leads` member; or +- two approvals from distinct current `ontrack-contributors` members. + +Approvals from the pull-request author, bots, stale commits, dismissed reviews, +or reviewers whose latest actionable review requests changes do not count. + +## Security model + +`ontrack-review-policy-signal.yml` is unprivileged and never checks out pull-request +code. A completed signal wakes `ontrack-review-policy.yml` through `workflow_run`. +The evaluator workflow checks out only this directory from the protected default +branch, then mints a short-lived token for the organization-owned GitHub App. + +The App is installed only on the three OnTrack Doubtfire repositories and has: + +- organization Members: read; +- repository Metadata: read (mandatory); +- repository Pull requests: read; and +- repository Commit statuses: write. + +The App has no contents, workflow, administration, merge, or webhook permission. +Its private key is held in `ONTRACK_REVIEW_APP_PRIVATE_KEY` in the +`ontrack-review-policy` environment, which only permits the protected `11.0.x` +branch. Its numeric App ID is held in `ONTRACK_REVIEW_APP_ID`. + +The evaluator reports on GitHub's per-PR test merge commit when available, so two +pull requests that share a head commit cannot accidentally share a passing result. +A five-minute reconciliation covers team membership and base-branch changes that +do not emit a pull-request review event. Unchanged results are not republished, +which avoids GitHub's per-commit status limit. + +## Ruleset integration + +Keep the native one-overall-approval rule, stale-review dismissal, and conversation +resolution. Require `ontrack/review-policy` with the OnTrack Review Policy App as +its expected source. Remove the native `ontrack-leads` required-reviewer entry only +after the App status has been observed and made required; otherwise GitHub combines +the native team rules with AND semantics. + +Changes to any workflow, the evaluator, or CODEOWNERS should continue to require +one `ontrack-leads` approval through a path-specific native reviewer rule. This is +necessary because any default-branch workflow could otherwise reference the App's +environment secret. diff --git a/.github/review-policy/evaluate.mjs b/.github/review-policy/evaluate.mjs new file mode 100644 index 0000000000..badebd8a4b --- /dev/null +++ b/.github/review-policy/evaluate.mjs @@ -0,0 +1,530 @@ +import { createSign } from 'node:crypto'; +import { readFile } from 'node:fs/promises'; +import { pathToFileURL } from 'node:url'; + +const API_VERSION = '2022-11-28'; +const POLICY_CONTEXT = 'ontrack/review-policy'; +const APP_BOT_LOGIN = 'ontrack-review-policy-t2-2026[bot]'; +const PAGE_SIZE = 100; +const MAX_PAGES = 50; +const ALLOWED_REPOSITORIES = new Set([ + 'doubtfire-deploy', + 'doubtfire-api', + 'doubtfire-web', +]); + +function normalizeLogin(login) { + return String(login || '').toLowerCase(); +} + +function encodeJson(value) { + return Buffer.from(JSON.stringify(value)).toString('base64url'); +} + +export function createAppJwt(appId, privateKey, nowSeconds = Math.floor(Date.now() / 1000)) { + if (!/^\d+$/.test(String(appId))) { + throw new Error('ONTRACK_REVIEW_APP_ID must be a numeric GitHub App ID.'); + } + if (!String(privateKey).includes('PRIVATE KEY')) { + throw new Error('ONTRACK_REVIEW_APP_PRIVATE_KEY is missing or invalid.'); + } + + const header = encodeJson({ alg: 'RS256', typ: 'JWT' }); + const payload = encodeJson({ + iat: nowSeconds - 60, + exp: nowSeconds + 540, + iss: String(appId), + }); + const unsigned = `${header}.${payload}`; + const signer = createSign('RSA-SHA256'); + signer.update(unsigned); + signer.end(); + const signature = signer.sign(privateKey).toString('base64url'); + return `${unsigned}.${signature}`; +} + +export function approvedReviewers(reviews, headSha, authorLogin) { + const author = normalizeLogin(authorLogin); + const latestActionableReview = new Map(); + const actionableStates = new Set(['APPROVED', 'CHANGES_REQUESTED', 'DISMISSED']); + + const ordered = [...reviews].sort((left, right) => { + const leftTime = Date.parse(left.submitted_at || 0) || 0; + const rightTime = Date.parse(right.submitted_at || 0) || 0; + return leftTime - rightTime || Number(left.id || 0) - Number(right.id || 0); + }); + + for (const review of ordered) { + const login = normalizeLogin(review.user?.login); + const state = String(review.state || '').toUpperCase(); + if (!login || login === author || review.user?.type === 'Bot') { + continue; + } + // A comment after an approval does not revoke the approval. + if (!actionableStates.has(state)) { + continue; + } + latestActionableReview.set(login, review); + } + + return new Set( + [...latestActionableReview.entries()] + .filter(([, review]) => ( + String(review.state || '').toUpperCase() === 'APPROVED' + && review.commit_id === headSha + )) + .map(([login]) => login), + ); +} + +export function evaluatePolicy(approved, leadMembers, contributorMembers) { + const leads = new Set([...leadMembers].map(normalizeLogin)); + const contributors = new Set([...contributorMembers].map(normalizeLogin)); + let leadApprovals = 0; + let contributorApprovals = 0; + + for (const login of approved) { + const normalized = normalizeLogin(login); + if (leads.has(normalized)) { + leadApprovals += 1; + } + if (contributors.has(normalized)) { + contributorApprovals += 1; + } + } + + return { + leadApprovals, + contributorApprovals, + passes: leadApprovals >= 1 || contributorApprovals >= 2, + }; +} + +export function pullRequestNumbersFromWorkflowRun(workflowRun) { + const numbers = new Set(); + for (const pullRequest of workflowRun?.pull_requests || []) { + const number = Number(pullRequest?.number); + if (Number.isSafeInteger(number) && number > 0) { + numbers.add(number); + } + } + + const title = String(workflowRun?.display_title || ''); + const titleMatch = title.match(/\bPR #([1-9]\d{0,9})\b/); + if (titleMatch) { + const number = Number(titleMatch[1]); + if (Number.isSafeInteger(number)) { + numbers.add(number); + } + } + return [...numbers]; +} + +function safeError(error) { + return String(error?.message || error || 'Unknown error') + .replace(/gh[opsu]_[A-Za-z0-9_]+/g, '[redacted token]') + .replace( + /-----BEGIN [^-]*PRIVATE KEY-----[\s\S]*?-----END [^-]*PRIVATE KEY-----/g, + '[redacted private key]', + ) + .slice(0, 500); +} + +function repositoryParts(repository) { + const match = String(repository || '').match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/); + if (!match) { + throw new Error('GITHUB_REPOSITORY is invalid.'); + } + return { owner: match[1], repo: match[2] }; +} + +class GitHubApi { + constructor(apiUrl, token) { + this.apiUrl = String(apiUrl || 'https://api.github.com').replace(/\/$/, ''); + this.token = token; + } + + async request(path, { method = 'GET', body, expected = [200] } = {}) { + const response = await fetch(`${this.apiUrl}${path}`, { + method, + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${this.token}`, + 'User-Agent': 'ontrack-review-policy', + 'X-GitHub-Api-Version': API_VERSION, + }, + body: body === undefined ? undefined : JSON.stringify(body), + }); + + if (!expected.includes(response.status)) { + const requestId = response.headers.get('x-github-request-id'); + throw new Error( + `GitHub API ${method} ${path} returned ${response.status}` + + (requestId ? ` (request ${requestId})` : ''), + ); + } + + if (response.status === 204) { + return null; + } + const text = await response.text(); + return text ? JSON.parse(text) : null; + } + + async paginate(path) { + const items = []; + const separator = path.includes('?') ? '&' : '?'; + for (let page = 1; page <= MAX_PAGES; page += 1) { + const batch = await this.request( + `${path}${separator}per_page=${PAGE_SIZE}&page=${page}`, + ); + if (!Array.isArray(batch)) { + throw new Error(`Expected a list from GitHub API path ${path}.`); + } + items.push(...batch); + if (batch.length < PAGE_SIZE) { + return items; + } + } + throw new Error(`GitHub API pagination exceeded ${MAX_PAGES} pages for ${path}.`); + } +} + +async function mintInstallationToken({ apiUrl, owner, repo, appId, privateKey }) { + const appJwt = createAppJwt(appId, privateKey); + const appApi = new GitHubApi(apiUrl, appJwt); + const installation = await appApi.request( + `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/installation`, + ); + const tokenResponse = await appApi.request( + `/app/installations/${installation.id}/access_tokens`, + { + method: 'POST', + expected: [201], + body: { + repositories: [repo], + permissions: { + members: 'read', + pull_requests: 'read', + statuses: 'write', + }, + }, + }, + ); + + if (!tokenResponse?.token) { + throw new Error('GitHub did not return an installation access token.'); + } + // Generated tokens are not repository secrets, so mask them explicitly. + console.log(`::add-mask::${tokenResponse.token}`); + return tokenResponse.token; +} + +async function teamMembers(api, owner, teamSlug) { + const members = await api.paginate( + `/orgs/${encodeURIComponent(owner)}/teams/${encodeURIComponent(teamSlug)}/members`, + ); + return new Set(members.map((member) => normalizeLogin(member.login))); +} + +async function openPullRequests(api, owner, repo) { + return api.paginate( + `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls?state=open`, + ); +} + +async function pullRequest(api, owner, repo, number) { + return api.request( + `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${number}`, + ); +} + +async function reviewsForPullRequest(api, owner, repo, number) { + return api.paginate( + `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${number}/reviews`, + ); +} + +function runUrl(repository, runId) { + return `https://github.com/${repository}/actions/runs/${runId}`; +} + +async function setPolicyStatus(api, owner, repo, sha, state, description, targetUrl) { + if (!/^[0-9a-f]{40}$/i.test(String(sha || ''))) { + throw new Error('Cannot publish the review policy without a valid commit SHA.'); + } + const clippedDescription = description.slice(0, 140); + try { + const statuses = await api.paginate( + `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}` + + `/commits/${encodeURIComponent(sha)}/statuses`, + ); + const latest = statuses.find((status) => ( + status.context === POLICY_CONTEXT + && normalizeLogin(status.creator?.login) === APP_BOT_LOGIN + )); + if (latest?.state === state && latest?.description === clippedDescription) { + return false; + } + } catch (error) { + // Deduplication is only an optimization. Always attempt the fail-closed write + // when status history cannot be read but the status endpoint may still work. + console.warn(`::warning::Status deduplication failed: ${safeError(error)}`); + } + + await api.request( + `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/statuses/${sha}`, + { + method: 'POST', + expected: [201], + body: { + state, + context: POLICY_CONTEXT, + description: clippedDescription, + target_url: targetUrl, + }, + }, + ); + return true; +} + +export { setPolicyStatus }; + +async function statusShaForPullRequest(api, owner, repo, initialPullRequest) { + let current = initialPullRequest; + if (!current.merge_commit_sha && current.state === 'open') { + await new Promise((resolve) => setTimeout(resolve, 1000)); + current = await pullRequest(api, owner, repo, current.number); + } + return current.merge_commit_sha || current.head?.sha; +} + +function reviewDigest(reviews) { + return reviews + .map((review) => ( + `${review.id}:${review.state}:${review.commit_id}:` + + `${review.submitted_at}:${review.user?.id}:${review.user?.login}` + )) + .sort() + .join('|'); +} + +function samePullRequestVersion(left, right) { + return ( + left.state === right.state + && left.draft === right.draft + && left.head?.sha === right.head?.sha + && left.base?.ref === right.base?.ref + && left.base?.sha === right.base?.sha + && left.merge_commit_sha === right.merge_commit_sha + && left.mergeable === right.mergeable + ); +} + +async function evaluatePullRequest({ + api, + owner, + repo, + pullRequest: current, + leads, + contributors, + targetUrl, + attempt = 0, +}) { + // Re-fetch before evaluating so a delayed workflow_run never trusts its event's + // old head or merge SHA. + current = await pullRequest(api, owner, repo, current.number); + if (current.state !== 'open') { + return; + } + + const statusSha = await statusShaForPullRequest(api, owner, repo, current); + if (current.draft) { + await setPolicyStatus( + api, + owner, + repo, + statusSha, + 'pending', + 'Waiting for the pull request to be marked ready for review', + targetUrl, + ); + console.log(`PR #${current.number}: draft`); + return; + } + + const firstReviews = await reviewsForPullRequest(api, owner, repo, current.number); + const checked = await pullRequest(api, owner, repo, current.number); + const secondReviews = await reviewsForPullRequest(api, owner, repo, current.number); + const live = await pullRequest(api, owner, repo, current.number); + if (checked.state !== 'open' || live.state !== 'open') { + return; + } + const liveStatusSha = await statusShaForPullRequest(api, owner, repo, live); + if ( + !samePullRequestVersion(current, checked) + || !samePullRequestVersion(checked, live) + || reviewDigest(firstReviews) !== reviewDigest(secondReviews) + || liveStatusSha !== statusSha + ) { + if (attempt >= 1) { + throw new Error('Pull request changed repeatedly during evaluation.'); + } + console.log(`PR #${current.number}: changed during evaluation; retrying once`); + return evaluatePullRequest({ + api, + owner, + repo, + pullRequest: live, + leads, + contributors, + targetUrl, + attempt: attempt + 1, + }); + } + + const approved = approvedReviewers( + secondReviews, + live.head.sha, + live.user?.login, + ); + const result = evaluatePolicy(approved, leads, contributors); + const state = result.passes ? 'success' : 'pending'; + const description = result.passes + ? `Passed: ${result.leadApprovals}/1 lead or ${result.contributorApprovals}/2 contributors` + : `Waiting: ${result.leadApprovals}/1 lead or ${result.contributorApprovals}/2 contributors`; + + await setPolicyStatus(api, owner, repo, liveStatusSha, state, description, targetUrl); + console.log( + `PR #${current.number}: lead=${result.leadApprovals}, ` + + `contributors=${result.contributorApprovals}, status=${state}`, + ); +} + +async function eventPayload() { + const payloadPath = process.env.GITHUB_EVENT_PATH; + if (!payloadPath) { + return {}; + } + return JSON.parse(await readFile(payloadPath, 'utf8')); +} + +async function pullRequestsToEvaluate(api, owner, repo, eventName, payload) { + const open = await openPullRequests(api, owner, repo); + if (eventName === 'workflow_run') { + // Treat workflow_run fields only as untrusted locators. Match them against + // live open PRs fetched with the App token before evaluating anything. + const numbers = new Set(pullRequestNumbersFromWorkflowRun(payload.workflow_run)); + const headSha = payload.workflow_run?.head_sha; + const linked = open.filter((candidate) => ( + numbers.has(candidate.number) + || candidate.head?.sha === headSha + || candidate.merge_commit_sha === headSha + )); + return linked.length > 0 ? linked : open; + } + return open; +} + +export async function main() { + const repository = process.env.GITHUB_REPOSITORY; + const { owner, repo } = repositoryParts(repository); + if (owner !== 'ontrack-features-t2-2026' || !ALLOWED_REPOSITORIES.has(repo)) { + throw new Error('This evaluator only runs for the three approved OnTrack repositories.'); + } + + const appId = process.env.ONTRACK_REVIEW_APP_ID; + const privateKey = process.env.ONTRACK_REVIEW_APP_PRIVATE_KEY; + const apiUrl = process.env.GITHUB_API_URL || 'https://api.github.com'; + const token = await mintInstallationToken({ + apiUrl, + owner, + repo, + appId, + privateKey, + }); + const api = new GitHubApi(apiUrl, token); + const payload = await eventPayload(); + const eventName = process.env.GITHUB_EVENT_NAME || ''; + const pullRequests = await pullRequestsToEvaluate(api, owner, repo, eventName, payload); + + if (pullRequests.length === 0) { + console.log('No open pull requests require review-policy evaluation.'); + return; + } + + const leadTeam = process.env.ONTRACK_LEAD_TEAM || 'ontrack-leads'; + const contributorTeam = process.env.ONTRACK_CONTRIBUTOR_TEAM || 'ontrack-contributors'; + let leads; + let contributors; + try { + [leads, contributors] = await Promise.all([ + teamMembers(api, owner, leadTeam), + teamMembers(api, owner, contributorTeam), + ]); + } catch (error) { + const targetUrl = runUrl(repository, process.env.GITHUB_RUN_ID); + for (const current of pullRequests) { + try { + const sha = await statusShaForPullRequest(api, owner, repo, current); + await setPolicyStatus( + api, + owner, + repo, + sha, + 'error', + 'OnTrack team membership could not be verified', + targetUrl, + ); + } catch (statusError) { + console.error(`::error::${safeError(statusError)}`); + } + } + throw error; + } + + const targetUrl = runUrl(repository, process.env.GITHUB_RUN_ID); + const failures = []; + for (const current of pullRequests) { + try { + await evaluatePullRequest({ + api, + owner, + repo, + pullRequest: current, + leads, + contributors, + targetUrl, + }); + } catch (error) { + failures.push(error); + try { + const sha = await statusShaForPullRequest(api, owner, repo, current); + await setPolicyStatus( + api, + owner, + repo, + sha, + 'error', + 'OnTrack review policy evaluation failed', + targetUrl, + ); + } catch (statusError) { + console.error(`::error::${safeError(statusError)}`); + } + console.error(`::error::PR #${current.number}: ${safeError(error)}`); + } + } + + if (failures.length > 0) { + throw new Error(`${failures.length} pull-request evaluation(s) failed.`); + } +} + +const invokedPath = process.argv[1] ? pathToFileURL(process.argv[1]).href : ''; +if (import.meta.url === invokedPath) { + main().catch((error) => { + console.error(`::error::${safeError(error)}`); + process.exitCode = 1; + }); +} diff --git a/.github/review-policy/evaluate.test.mjs b/.github/review-policy/evaluate.test.mjs new file mode 100644 index 0000000000..868bb827b0 --- /dev/null +++ b/.github/review-policy/evaluate.test.mjs @@ -0,0 +1,221 @@ +import assert from 'node:assert/strict'; +import { generateKeyPairSync, verify } from 'node:crypto'; +import { test } from 'node:test'; + +import { + approvedReviewers, + createAppJwt, + evaluatePolicy, + pullRequestNumbersFromWorkflowRun, + setPolicyStatus, +} from './evaluate.mjs'; + +function review({ + id, + login, + state = 'APPROVED', + commit = 'head', + submitted = `2026-08-24T00:00:${String(id).padStart(2, '0')}Z`, + type = 'User', +}) { + return { + id, + state, + commit_id: commit, + submitted_at: submitted, + user: { login, type }, + }; +} + +test('one lead approval passes', () => { + const result = evaluatePolicy( + new Set(['lead']), + new Set(['lead']), + new Set(['lead', 'contributor']), + ); + assert.equal(result.passes, true); + assert.equal(result.leadApprovals, 1); +}); + +test('two distinct contributor approvals pass', () => { + const result = evaluatePolicy( + new Set(['contributor-a', 'contributor-b']), + new Set(['lead']), + new Set(['lead', 'contributor-a', 'contributor-b']), + ); + assert.equal(result.passes, true); + assert.equal(result.contributorApprovals, 2); +}); + +test('one contributor approval does not pass', () => { + const result = evaluatePolicy( + new Set(['contributor-a']), + new Set(['lead']), + new Set(['lead', 'contributor-a']), + ); + assert.equal(result.passes, false); +}); + +test('duplicate approvals from one reviewer count once', () => { + const approved = approvedReviewers([ + review({ id: 1, login: 'Contributor-A' }), + review({ id: 2, login: 'contributor-a' }), + ], 'head', 'author'); + assert.deepEqual([...approved], ['contributor-a']); +}); + +test('a later comment does not revoke an approval', () => { + const approved = approvedReviewers([ + review({ id: 1, login: 'contributor-a' }), + review({ id: 2, login: 'contributor-a', state: 'COMMENTED' }), + ], 'head', 'author'); + assert.deepEqual([...approved], ['contributor-a']); +}); + +test('a later changes-requested review revokes an approval', () => { + const approved = approvedReviewers([ + review({ id: 1, login: 'contributor-a' }), + review({ id: 2, login: 'contributor-a', state: 'CHANGES_REQUESTED' }), + ], 'head', 'author'); + assert.deepEqual([...approved], []); +}); + +test('stale, author, and bot approvals are ignored', () => { + const approved = approvedReviewers([ + review({ id: 1, login: 'stale', commit: 'old-head' }), + review({ id: 2, login: 'author' }), + review({ id: 3, login: 'review-bot[bot]', type: 'Bot' }), + ], 'head', 'author'); + assert.deepEqual([...approved], []); +}); + +test('workflow run PR numbers are deduplicated and validated', () => { + assert.deepEqual( + pullRequestNumbersFromWorkflowRun({ + display_title: 'OnTrack review policy signal for PR #42', + pull_requests: [{ number: 42 }, { number: 17 }, { number: 0 }], + }), + [42, 17], + ); +}); + +test('workflow run ignores unsafe or implausibly large PR numbers', () => { + assert.deepEqual( + pullRequestNumbersFromWorkflowRun({ + display_title: 'OnTrack review policy signal for PR #12345678901', + pull_requests: [{ number: Number.MAX_SAFE_INTEGER + 1 }, { number: -4 }], + }), + [], + ); +}); + +test('GitHub App JWT has a valid RSA signature and bounded lifetime', () => { + const { privateKey, publicKey } = generateKeyPairSync('rsa', { modulusLength: 2048 }); + const privateKeyPem = privateKey.export({ type: 'pkcs8', format: 'pem' }); + const now = 1_800_000_000; + const jwt = createAppJwt('4699573', privateKeyPem, now); + const [header, payload, signature] = jwt.split('.'); + assert.equal( + verify( + 'RSA-SHA256', + Buffer.from(`${header}.${payload}`), + publicKey, + Buffer.from(signature, 'base64url'), + ), + true, + ); + const claims = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8')); + assert.equal(claims.iss, '4699573'); + assert.equal(claims.iat, now - 60); + assert.equal(claims.exp, now + 540); +}); + +test('unchanged App status is not republished and spoofed sources are ignored', async () => { + const posts = []; + const api = { + async paginate() { + return [ + { + context: 'ontrack/review-policy', + state: 'success', + description: 'Passed', + creator: { login: 'not-the-policy-app[bot]' }, + }, + { + context: 'ontrack/review-policy', + state: 'pending', + description: 'Waiting', + creator: { login: 'ontrack-review-policy-t2-2026[bot]' }, + }, + ]; + }, + async request(path, options) { + posts.push({ path, options }); + return {}; + }, + }; + + assert.equal( + await setPolicyStatus( + api, + 'owner', + 'repo', + 'a'.repeat(40), + 'pending', + 'Waiting', + 'https://example.test/run', + ), + false, + ); + assert.equal(posts.length, 0); + + assert.equal( + await setPolicyStatus( + api, + 'owner', + 'repo', + 'a'.repeat(40), + 'success', + 'Passed', + 'https://example.test/run', + ), + true, + ); + assert.equal(posts.length, 1); +}); + +test('status-history failure does not suppress a fail-closed write', async () => { + const posts = []; + const warnings = []; + const originalWarn = console.warn; + console.warn = (message) => warnings.push(message); + const api = { + async paginate() { + throw new Error('history unavailable'); + }, + async request(path, options) { + posts.push({ path, options }); + return {}; + }, + }; + + try { + assert.equal( + await setPolicyStatus( + api, + 'owner', + 'repo', + 'b'.repeat(40), + 'error', + 'Evaluation failed', + 'https://example.test/run', + ), + true, + ); + assert.equal(posts.length, 1); + assert.equal(posts[0].options.body.state, 'error'); + assert.equal(warnings.length, 1); + } finally { + console.warn = originalWarn; + } +}); diff --git a/.github/workflows/ontrack-review-policy-signal.yml b/.github/workflows/ontrack-review-policy-signal.yml new file mode 100644 index 0000000000..d87949cbbc --- /dev/null +++ b/.github/workflows/ontrack-review-policy-signal.yml @@ -0,0 +1,32 @@ +name: OnTrack review policy signal +run-name: "OnTrack review policy signal for PR #${{ github.event.pull_request.number || 'all' }}" + +on: + pull_request_target: + types: + - opened + - reopened + - synchronize + - edited + - ready_for_review + - converted_to_draft + pull_request_review: + types: + - submitted + - edited + - dismissed + workflow_dispatch: + +# This workflow deliberately has no permissions and never checks out pull-request +# code or secrets. Its completion wakes the trusted evaluator on the default +# branch; manual runs safely reconcile every open pull request. +permissions: {} + +jobs: + signal: + if: github.repository_owner == 'ontrack-features-t2-2026' + runs-on: ubuntu-24.04 + timeout-minutes: 1 + steps: + - name: Signal policy evaluation + run: ':' diff --git a/.github/workflows/ontrack-review-policy.yml b/.github/workflows/ontrack-review-policy.yml new file mode 100644 index 0000000000..61c194b103 --- /dev/null +++ b/.github/workflows/ontrack-review-policy.yml @@ -0,0 +1,56 @@ +name: OnTrack review policy evaluator + +on: + workflow_run: + workflows: + - OnTrack review policy signal + types: + - completed + push: + branches: + - 11.0.x + schedule: + # Reconcile team membership and base-branch changes even when no PR event fires. + - cron: '3-58/5 * * * *' + +# The repository token is used only to check out the trusted evaluator from the +# default branch. The GitHub App token is separately scoped to member/PR reads and +# commit-status writes. +permissions: + contents: read + +concurrency: + # Serialize signals for the same PR without allowing unrelated PR activity to + # replace a queued revocation. Scheduled and base-push reconciliations share a + # separate group. Every run re-reads authoritative GitHub state. + group: ontrack-review-policy-${{ github.repository }}-${{ github.event.workflow_run.pull_requests[0].number || github.event.workflow_run.display_title || 'reconcile' }} + cancel-in-progress: false + +jobs: + evaluate: + if: github.repository_owner == 'ontrack-features-t2-2026' + runs-on: ubuntu-24.04 + timeout-minutes: 5 + environment: + name: ontrack-review-policy + deployment: false + + steps: + - name: Check out the trusted policy evaluator + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + ref: refs/heads/11.0.x + fetch-depth: 1 + persist-credentials: false + sparse-checkout: .github/review-policy + + - name: Verify policy logic + run: node --test .github/review-policy/evaluate.test.mjs + + - name: Evaluate current pull-request approvals + env: + ONTRACK_REVIEW_APP_ID: ${{ vars.ONTRACK_REVIEW_APP_ID }} + ONTRACK_REVIEW_APP_PRIVATE_KEY: ${{ secrets.ONTRACK_REVIEW_APP_PRIVATE_KEY }} + ONTRACK_CONTRIBUTOR_TEAM: ontrack-contributors + ONTRACK_LEAD_TEAM: ontrack-leads + run: node .github/review-policy/evaluate.mjs From cf0ef3396cd07791301f898ee285dd26d06d97b3 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Mon, 24 Aug 2026 18:56:30 +1000 Subject: [PATCH 1436/1531] feat(peer-progress): deliver compact and advanced indicator --- .../peer-progress-indicator.fixtures.spec.ts | 33 ++ .../peer-progress-indicator.fixtures.ts | 78 ++- .../peer-progress-indicator-state.spec.ts | 21 + .../models/peer-progress-indicator-state.ts | 15 +- src/app/api/models/peer-progress-indicator.ts | 27 + .../api/models/peer-progress-unit-summary.ts | 11 +- src/app/api/models/task-status.ts | 20 + src/app/api/models/user/user.ts | 1 + .../peer-progress-indicator.service.ts | 140 +++++- .../peer-progress-indicator.service.spec.ts | 216 ++++++++ .../api/services/spec/user.service.spec.ts | 17 + src/app/api/services/user.service.ts | 1 + .../edit-profile-form.component.html | 21 + .../edit-profile-form.component.scss | 16 + .../edit-profile-form.component.spec.ts | 19 + .../edit-profile-form.component.ts | 7 + .../demo-controls.component.html | 175 ++++++- .../demo-controls.component.scss | 319 ++++++++++++ .../demo-controls.component.spec.ts | 54 +- .../demo-controls/demo-controls.component.ts | 95 +++- .../fixtures/peer-progress-demo.fixtures.ts | 99 +++- .../ppi-widget/ppi-widget.component.html | 298 +++++++++-- .../ppi-widget/ppi-widget.component.scss | 470 +++++++++++++++++- .../ppi-widget/ppi-widget.component.spec.ts | 120 ++++- .../ppi-widget/ppi-widget.component.ts | 134 ++++- .../task-description-card.component.html | 4 - .../task-description-card.component.ts | 1 - .../task-dashboard.component.html | 4 +- .../task-dashboard.component.spec.ts | 147 +++++- .../task-dashboard.component.ts | 19 +- 30 files changed, 2460 insertions(+), 122 deletions(-) diff --git a/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts b/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts index b4c3f8cc9b..1e6f5cb0d3 100644 --- a/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts +++ b/src/app/api/fixtures/peer-progress-indicator.fixtures.spec.ts @@ -19,6 +19,12 @@ const assertContractShape = (fixture: PeerProgressIndicator) => { expect( fixture.submittedPercentage === null || typeof fixture.submittedPercentage === 'number', ).toBe(true); + expect( + fixture.completedPercentage === null || typeof fixture.completedPercentage === 'number', + ).toBe(true); + expect(typeof fixture.distributionAvailable).toBe('boolean'); + expect(Array.isArray(fixture.statusDistribution)).toBe(true); + expect(typeof fixture.isUserEnabled).toBe('boolean'); expect(typeof fixture.isSuppressed).toBe('boolean'); expect(typeof fixture.isStale).toBe('boolean'); @@ -26,6 +32,13 @@ const assertContractShape = (fixture: PeerProgressIndicator) => { expect(fixture.lastUpdatedAt === null || typeof fixture.lastUpdatedAt === 'string').toBe(true); expect(typeof fixture.unavailableMessage).toBe('string'); + expect(fixture.unavailableReason === null || typeof fixture.unavailableReason === 'string').toBe( + true, + ); + expect( + fixture.distributionUnavailableReason === null || + typeof fixture.distributionUnavailableReason === 'string', + ).toBe(true); }; describe('PeerProgressIndicator Fixture Regression Tests', () => { @@ -61,6 +74,22 @@ describe('PeerProgressIndicator Fixture Regression Tests', () => { expect(FIXTURE_NORMAL.isFeatureEnabled).toBe(true); }); + it('NORMAL fixture contains the complete, 10-point-quantised canonical status vector', () => { + expect(FIXTURE_NORMAL.statusDistribution).toHaveLength(15); + expect(new Set(FIXTURE_NORMAL.statusDistribution.map((entry) => entry.status)).size).toBe(15); + expect(FIXTURE_NORMAL.statusDistribution.every((entry) => entry.percentage % 10 === 0)).toBe( + true, + ); + expect(FIXTURE_NORMAL.statusDistribution).toContainEqual({ + status: 'fix_and_resubmit', + percentage: 10, + }); + expect(FIXTURE_NORMAL.statusDistribution).toContainEqual({ + status: 'redo', + percentage: 10, + }); + }); + it('ZERO_PERCENT fixture keeps a displayed 0% distinct from unavailable data', () => { expect(FIXTURE_ZERO_PERCENT.submittedPercentage).toBe(0); expect(FIXTURE_ZERO_PERCENT.isSuppressed).toBe(false); @@ -104,6 +133,9 @@ describe('PeerProgressIndicator Fixture Regression Tests', () => { expect(f).not.toHaveProperty('cohortCount'); expect(f).not.toHaveProperty('marks'); expect(f).not.toHaveProperty('feedback'); + expect(f.statusDistribution).not.toContainEqual( + expect.objectContaining({studentId: expect.anything()}), + ); }); }); @@ -114,6 +146,7 @@ describe('PeerProgressIndicator Fixture Regression Tests', () => { // invalid numeric values expect(malformed.submittedPercentage).toBeNaN(); expect(Number.isFinite(malformed.submittedPercentage as number)).toBe(false); + expect(typeof malformed.distributionAvailable).not.toBe('boolean'); // invalid ranges // expect((malformed.submittedPercentage as number) < 0).toBe(true); diff --git a/src/app/api/fixtures/peer-progress-indicator.fixtures.ts b/src/app/api/fixtures/peer-progress-indicator.fixtures.ts index fba256c6bc..17c525f52e 100644 --- a/src/app/api/fixtures/peer-progress-indicator.fixtures.ts +++ b/src/app/api/fixtures/peer-progress-indicator.fixtures.ts @@ -4,12 +4,34 @@ export const FIXTURE_NORMAL: PeerProgressIndicator = { taskDefinitionId: 12, unitId: 5, targetGrade: 2, - submittedPercentage: 62.5, + submittedPercentage: 60, + completedPercentage: 10, + distributionAvailable: true, + statusDistribution: [ + {status: 'not_started', percentage: 20}, + {status: 'feedback_exceeded', percentage: 0}, + {status: 'redo', percentage: 10}, + {status: 'need_help', percentage: 0}, + {status: 'working_on_it', percentage: 20}, + {status: 'fix_and_resubmit', percentage: 10}, + {status: 'ready_for_feedback', percentage: 20}, + {status: 'discuss', percentage: 0}, + {status: 'demonstrate', percentage: 0}, + {status: 'complete', percentage: 10}, + {status: 'fail', percentage: 10}, + {status: 'time_exceeded', percentage: 0}, + {status: 'assess_in_portfolio', percentage: 0}, + {status: 'attention_required', percentage: 0}, + {status: 'rediscuss', percentage: 0}, + ], + isUserEnabled: true, isSuppressed: false, isStale: false, isFeatureEnabled: true, lastUpdatedAt: '2026-08-14T03:15:00Z', unavailableMessage: '', + unavailableReason: null, + distributionUnavailableReason: null, }; export const FIXTURE_ZERO_PERCENT: PeerProgressIndicator = { @@ -17,11 +39,33 @@ export const FIXTURE_ZERO_PERCENT: PeerProgressIndicator = { unitId: 5, targetGrade: 2, submittedPercentage: 0, + completedPercentage: 0, + distributionAvailable: true, + statusDistribution: [ + {status: 'not_started', percentage: 50}, + {status: 'feedback_exceeded', percentage: 0}, + {status: 'redo', percentage: 0}, + {status: 'need_help', percentage: 10}, + {status: 'working_on_it', percentage: 30}, + {status: 'fix_and_resubmit', percentage: 10}, + {status: 'ready_for_feedback', percentage: 0}, + {status: 'discuss', percentage: 0}, + {status: 'demonstrate', percentage: 0}, + {status: 'complete', percentage: 0}, + {status: 'fail', percentage: 0}, + {status: 'time_exceeded', percentage: 0}, + {status: 'assess_in_portfolio', percentage: 0}, + {status: 'attention_required', percentage: 0}, + {status: 'rediscuss', percentage: 0}, + ], + isUserEnabled: true, isSuppressed: false, isStale: false, isFeatureEnabled: true, lastUpdatedAt: '2026-08-14T03:15:00Z', unavailableMessage: '', + unavailableReason: null, + distributionUnavailableReason: null, }; export const FIXTURE_SUPPRESSED: PeerProgressIndicator = { @@ -29,11 +73,17 @@ export const FIXTURE_SUPPRESSED: PeerProgressIndicator = { unitId: 5, targetGrade: 2, submittedPercentage: null, + completedPercentage: null, + distributionAvailable: false, + statusDistribution: [], + isUserEnabled: true, isSuppressed: true, isStale: false, isFeatureEnabled: true, lastUpdatedAt: '2026-08-14T03:15:00Z', unavailableMessage: 'Not enough students to show progress.', + unavailableReason: 'insufficient_cohort', + distributionUnavailableReason: 'insufficient_cohort', }; export const FIXTURE_UNAVAILABLE: PeerProgressIndicator = { @@ -41,11 +91,17 @@ export const FIXTURE_UNAVAILABLE: PeerProgressIndicator = { unitId: 5, targetGrade: 2, submittedPercentage: null, + completedPercentage: null, + distributionAvailable: false, + statusDistribution: [], + isUserEnabled: true, isSuppressed: false, isStale: false, isFeatureEnabled: true, lastUpdatedAt: '2026-08-14T03:15:00Z', unavailableMessage: 'Progress unavailable.', + unavailableReason: 'snapshot_unavailable', + distributionUnavailableReason: 'snapshot_unavailable', }; export const FIXTURE_DISABLED: PeerProgressIndicator = { @@ -53,23 +109,35 @@ export const FIXTURE_DISABLED: PeerProgressIndicator = { unitId: 5, targetGrade: 2, submittedPercentage: null, + completedPercentage: null, + distributionAvailable: false, + statusDistribution: [], + isUserEnabled: true, isSuppressed: false, isStale: false, isFeatureEnabled: false, lastUpdatedAt: '2026-08-14T03:15:00Z', unavailableMessage: 'Peer Progress Indicator is disabled for this unit.', + unavailableReason: 'feature_disabled', + distributionUnavailableReason: 'feature_disabled', }; export const FIXTURE_STALE: PeerProgressIndicator = { taskDefinitionId: 12, unitId: 5, targetGrade: 2, - submittedPercentage: 55, + submittedPercentage: null, + completedPercentage: null, + distributionAvailable: false, + statusDistribution: [], + isUserEnabled: true, isSuppressed: false, isStale: true, isFeatureEnabled: true, lastUpdatedAt: '2026-08-14T03:15:00Z', unavailableMessage: 'Progress data is stale.', + unavailableReason: 'stale', + distributionUnavailableReason: 'stale', }; // Malformed fixture for safe-failure tests @@ -78,9 +146,15 @@ export const FIXTURE_MALFORMED: unknown = { unitId: undefined, targetGrade: 'wrong-type', submittedPercentage: NaN, + completedPercentage: -1, + distributionAvailable: 'yes', + statusDistribution: [{status: 'not_real', percentage: 200}], + isUserEnabled: 'yes', isSuppressed: 'nope', isStale: 123, isFeatureEnabled: 'false', lastUpdatedAt: 'not-a-date', unavailableMessage: 999, + unavailableReason: 'raw server detail', + distributionUnavailableReason: 'raw server detail', }; diff --git a/src/app/api/models/peer-progress-indicator-state.spec.ts b/src/app/api/models/peer-progress-indicator-state.spec.ts index b289ea5783..65ea141544 100644 --- a/src/app/api/models/peer-progress-indicator-state.spec.ts +++ b/src/app/api/models/peer-progress-indicator-state.spec.ts @@ -5,6 +5,7 @@ import { STALE_STATE, SUPPRESSED_STATE, UNAVAILABLE_STATE, + USER_DISABLED_STATE, ZERO_PERCENT_STATE, } from 'src/app/demo/fixtures/peer-progress-demo.fixtures'; import {resolvePeerProgressState} from './peer-progress-indicator-state'; @@ -60,6 +61,26 @@ describe('resolvePeerProgressState', () => { expect(result.message).toBe(DISABLED_STATE.unavailableMessage); }); + it('returns preference-disabled without compact or detailed values when the user opts out', () => { + const result = resolvePeerProgressState(false, null, USER_DISABLED_STATE); + + expect(result.state).toBe('preference-disabled'); + expect(result.data?.completedPercentage).toBeNull(); + expect(result.data?.submittedPercentage).toBeNull(); + expect(result.data?.statusDistribution).toEqual([]); + expect(result.message).toContain('profile settings'); + }); + + it('keeps an old API response usable as submission progress when completion is absent', () => { + const result = resolvePeerProgressState(false, null, { + ...NORMAL_STATE, + completedPercentage: null, + }); + + expect(result.state).toBe('success'); + expect(result.data?.submittedPercentage).toBe(60); + }); + it('returns stale without exposing a percentage when data is outdated', () => { const result = resolvePeerProgressState(false, null, STALE_STATE); diff --git a/src/app/api/models/peer-progress-indicator-state.ts b/src/app/api/models/peer-progress-indicator-state.ts index 40a5b9d1eb..2f29e3b4fe 100644 --- a/src/app/api/models/peer-progress-indicator-state.ts +++ b/src/app/api/models/peer-progress-indicator-state.ts @@ -5,6 +5,7 @@ export type PeerProgressUiState = | 'success' | 'no-data' | 'hidden' + | 'preference-disabled' | 'unavailable' | 'disabled' | 'stale' @@ -32,6 +33,14 @@ export function resolvePeerProgressState( return {state: 'error', data: null, message: GENERIC_ERROR_MESSAGE}; } + if (!data.isUserEnabled) { + return { + state: 'preference-disabled', + data, + message: 'Peer progress is turned off in your profile settings.', + }; + } + if (!data.isFeatureEnabled) { return {state: 'disabled', data, message: data.unavailableMessage}; } @@ -44,11 +53,13 @@ export function resolvePeerProgressState( return {state: 'stale', data, message: data.unavailableMessage}; } - if (data.submittedPercentage === null) { + const compactPercentage = data.completedPercentage ?? data.submittedPercentage; + + if (compactPercentage === null) { return {state: 'unavailable', data, message: data.unavailableMessage}; } - if (data.submittedPercentage === 0) { + if (compactPercentage === 0) { return {state: 'no-data', data, message: null}; } diff --git a/src/app/api/models/peer-progress-indicator.ts b/src/app/api/models/peer-progress-indicator.ts index d354ae7e97..6f0bfc0f26 100644 --- a/src/app/api/models/peer-progress-indicator.ts +++ b/src/app/api/models/peer-progress-indicator.ts @@ -1,13 +1,40 @@ +import {TaskStatusEnum} from './task-status'; + +export interface PeerProgressStatusDistributionEntry { + status: TaskStatusEnum; + percentage: number; +} + +export type PeerProgressUnavailableReason = + | 'user_disabled' + | 'feature_disabled' + | 'target_grade_unavailable' + | 'snapshot_unavailable' + | 'insufficient_cohort' + | 'aggregation_incomplete' + | 'stale'; + +export type PeerProgressDistributionUnavailableReason = + | 'detailed_data_unavailable' + | 'privacy_protection' + | PeerProgressUnavailableReason; + export interface PeerProgressIndicator { taskDefinitionId: number; // ID of the task definition unitId: number; // ID of the unit targetGrade: number | null; // Valid server-side target grade, or null when unavailable submittedPercentage: number | null; // null when suppressed/unavailable/disabled + completedPercentage: number | null; // null when suppressed/unavailable/disabled + distributionAvailable: boolean; // false when a detailed vector cannot be shown safely + statusDistribution: PeerProgressStatusDistributionEntry[]; // privacy-safe, quantised values only + isUserEnabled: boolean; // false when the student's profile preference disables PPI isSuppressed: boolean; // true when cohort too small isStale: boolean; // true when data is outdated isFeatureEnabled: boolean; // false when unit disables PPI lastUpdatedAt: string | null; // ISO timestamp, or null when no snapshot was used unavailableMessage: string; // safe message for suppressed/unavailable/stale/disabled + unavailableReason: PeerProgressUnavailableReason | null; + distributionUnavailableReason: PeerProgressDistributionUnavailableReason | null; } diff --git a/src/app/api/models/peer-progress-unit-summary.ts b/src/app/api/models/peer-progress-unit-summary.ts index d7abdd3242..8e408c8de3 100644 --- a/src/app/api/models/peer-progress-unit-summary.ts +++ b/src/app/api/models/peer-progress-unit-summary.ts @@ -14,6 +14,15 @@ import {PeerProgressIndicator} from './peer-progress-indicator'; * * `taskDefinitionId` is omitted because this summary is not scoped to one task. */ -export interface PeerProgressUnitSummary extends Omit { +export interface PeerProgressUnitSummary extends Omit< + PeerProgressIndicator, + | 'taskDefinitionId' + | 'completedPercentage' + | 'distributionAvailable' + | 'statusDistribution' + | 'isUserEnabled' + | 'unavailableReason' + | 'distributionUnavailableReason' +> { studentPercentage: number | null; } diff --git a/src/app/api/models/task-status.ts b/src/app/api/models/task-status.ts index 5544f5ea8f..aa164b6301 100644 --- a/src/app/api/models/task-status.ts +++ b/src/app/api/models/task-status.ts @@ -45,6 +45,26 @@ export class TaskStatus { 'rediscuss', ]; + // Student-facing lifecycle order for an anonymous peer distribution. This + // differs from persistence/API order, which is not intended as presentation. + public static readonly PEER_PROGRESS_DISPLAY_ORDER: TaskStatusEnum[] = [ + 'not_started', + 'working_on_it', + 'need_help', + 'ready_for_feedback', + 'fix_and_resubmit', + 'redo', + 'attention_required', + 'discuss', + 'rediscuss', + 'demonstrate', + 'assess_in_portfolio', + 'complete', + 'feedback_exceeded', + 'time_exceeded', + 'fail', + ]; + public static readonly VALID_TOP_TASKS: TaskStatusEnum[] = [ 'not_started', 'redo', diff --git a/src/app/api/models/user/user.ts b/src/app/api/models/user/user.ts index 5a98e22551..ae6441051b 100644 --- a/src/app/api/models/user/user.ts +++ b/src/app/api/models/user/user.ts @@ -19,6 +19,7 @@ export class User extends Entity { public receiveTaskNotifications: boolean; public receivePortfolioNotifications: boolean; public receiveFeedbackNotifications: boolean; + public displayPeerProgress: boolean; public hasRunFirstTimeSetup: boolean; public authenticationToken: string; public authenticationTokenExpiry: string; diff --git a/src/app/api/services/peer-progress-indicator.service.ts b/src/app/api/services/peer-progress-indicator.service.ts index 230353969e..2333533928 100644 --- a/src/app/api/services/peer-progress-indicator.service.ts +++ b/src/app/api/services/peer-progress-indicator.service.ts @@ -8,14 +8,30 @@ import { createDemoUnitSummary, createMaskedPeerProgressIndicator, } from 'src/app/demo/fixtures/peer-progress-demo.fixtures'; -import {PeerProgressIndicator} from '../models/peer-progress-indicator'; +import { + PeerProgressDistributionUnavailableReason, + PeerProgressIndicator, + PeerProgressUnavailableReason, +} from '../models/peer-progress-indicator'; import {PeerProgressUnitSummary} from '../models/peer-progress-unit-summary'; +import {TaskStatus, TaskStatusEnum} from '../models/task-status'; + +interface PeerProgressStatusDistributionResponse { + status: string; + percentage: number; +} interface PeerProgressIndicatorResponse { task_definition_id: number; unit_id: number; target_grade: number | null; submitted_percentage: number | null; + completed_percentage?: number | null; + distribution_available?: boolean; + status_distribution?: PeerProgressStatusDistributionResponse[] | null; + is_user_enabled?: boolean; + unavailable_reason?: string | null; + distribution_unavailable_reason?: string | null; is_suppressed: boolean; is_stale: boolean; is_feature_enabled: boolean; @@ -27,6 +43,19 @@ interface PeerProgressIndicatorResponse { providedIn: 'root', }) export class PeerProgressIndicatorService { + private readonly knownStatuses: Set = new Set(TaskStatus.STATUS_KEYS); + private readonly unavailableReasons: Set = new Set([ + 'user_disabled', + 'feature_disabled', + 'target_grade_unavailable', + 'snapshot_unavailable', + 'insufficient_cohort', + 'aggregation_incomplete', + 'stale', + ]); + private readonly distributionUnavailableReasons: Set = + new Set(['detailed_data_unavailable', 'privacy_protection', ...this.unavailableReasons]); + constructor( private httpClient: HttpClient, private demoMode: DemoModeStore, @@ -40,20 +69,107 @@ export class PeerProgressIndicatorService { const url = `${API_URL}/projects/${projectId}/task_def_id/${taskDefinitionId}/peer_progress`; return this.httpClient.get(url).pipe( - map((response) => ({ - taskDefinitionId: response.task_definition_id, - unitId: response.unit_id, - targetGrade: response.target_grade, - submittedPercentage: response.submitted_percentage, - isSuppressed: response.is_suppressed, - isStale: response.is_stale, - isFeatureEnabled: response.is_feature_enabled, - lastUpdatedAt: response.last_updated_at, - unavailableMessage: response.unavailable_message, - })), + map((response) => { + const isUserEnabled = response.is_user_enabled !== false; + const mayExposeCompact = + isUserEnabled && + response.is_feature_enabled && + !response.is_suppressed && + !response.is_stale; + const mayExposeDistribution = mayExposeCompact && response.distribution_available === true; + const statusDistribution = mayExposeDistribution + ? this.mapStatusDistribution(response.status_distribution) + : null; + const distributionAvailable = statusDistribution !== null; + + return { + taskDefinitionId: response.task_definition_id, + unitId: response.unit_id, + targetGrade: response.target_grade, + submittedPercentage: mayExposeCompact + ? this.mapCompactPercentage(response.submitted_percentage) + : null, + completedPercentage: mayExposeCompact + ? this.mapCompactPercentage(response.completed_percentage) + : null, + distributionAvailable, + statusDistribution: statusDistribution ?? [], + isUserEnabled, + isSuppressed: response.is_suppressed, + isStale: response.is_stale, + isFeatureEnabled: response.is_feature_enabled, + lastUpdatedAt: response.last_updated_at, + unavailableMessage: response.unavailable_message, + unavailableReason: this.mapUnavailableReason(response.unavailable_reason), + distributionUnavailableReason: this.mapDistributionUnavailableReason( + response.distribution_unavailable_reason, + ), + }; + }), ); } + private mapUnavailableReason( + reason: string | null | undefined, + ): PeerProgressUnavailableReason | null { + return this.unavailableReasons.has(reason as PeerProgressUnavailableReason) + ? (reason as PeerProgressUnavailableReason) + : null; + } + + private mapDistributionUnavailableReason( + reason: string | null | undefined, + ): PeerProgressDistributionUnavailableReason | null { + return this.distributionUnavailableReasons.has( + reason as PeerProgressDistributionUnavailableReason, + ) + ? (reason as PeerProgressDistributionUnavailableReason) + : null; + } + + private mapStatusDistribution( + distribution: PeerProgressStatusDistributionResponse[] | null | undefined, + ): PeerProgressIndicator['statusDistribution'] | null { + if (!Array.isArray(distribution) || distribution.length !== this.knownStatuses.size) { + return null; + } + + const seen: Set = new Set(); + const result: PeerProgressIndicator['statusDistribution'] = []; + + for (const entry of distribution) { + const status = entry?.status as TaskStatusEnum; + const percentage = entry?.percentage; + + if ( + !this.knownStatuses.has(status) || + seen.has(status) || + typeof percentage !== 'number' || + !Number.isFinite(percentage) || + percentage < 0 || + percentage > 100 || + percentage % 10 !== 0 + ) { + return null; + } + + seen.add(status); + result.push({status, percentage}); + } + + return seen.size === this.knownStatuses.size ? result : null; + } + + private mapCompactPercentage(value: unknown): number | null { + return typeof value === 'number' && + Number.isFinite(value) && + value >= 0 && + value <= 100 && + value % 10 === 0 + ? value + : null; + } + /** * Builds a privacy-safe unit-summary fixture for PPI-F02 tests and demos. * diff --git a/src/app/api/services/spec/peer-progress-indicator.service.spec.ts b/src/app/api/services/spec/peer-progress-indicator.service.spec.ts index 7df95a6ae9..15d8b03515 100644 --- a/src/app/api/services/spec/peer-progress-indicator.service.spec.ts +++ b/src/app/api/services/spec/peer-progress-indicator.service.spec.ts @@ -6,6 +6,7 @@ import {PeerProgressIndicator} from 'src/app/api/models/peer-progress-indicator' import API_URL from 'src/app/config/constants/apiUrl'; import {DemoModeStore} from 'src/app/demo/demo-mode.store'; import { + DEMO_STATUS_DISTRIBUTION, DISABLED_STATE, NORMAL_STATE, SUPPRESSED_STATE, @@ -81,14 +82,229 @@ describe('PeerProgressIndicatorService', () => { unitId: 1, targetGrade: null, submittedPercentage: null, + completedPercentage: null, + distributionAvailable: false, + statusDistribution: [], + isUserEnabled: true, isSuppressed: false, isStale: false, isFeatureEnabled: true, lastUpdatedAt: null, unavailableMessage: 'Peer progress is currently unavailable.', + unavailableReason: null, + distributionUnavailableReason: null, }); }); + it('maps the full quantised status distribution and compact completion metric', () => { + let result: PeerProgressIndicator | undefined; + + service.getIndicator(7, 99).subscribe((value) => { + result = value; + }); + + httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`).flush({ + task_definition_id: 99, + unit_id: 1, + target_grade: 2, + submitted_percentage: 60, + completed_percentage: 10, + distribution_available: true, + status_distribution: DEMO_STATUS_DISTRIBUTION, + is_user_enabled: true, + is_suppressed: false, + is_stale: false, + is_feature_enabled: true, + last_updated_at: '2026-08-23T00:00:00Z', + unavailable_message: '', + unavailable_reason: null, + distribution_unavailable_reason: null, + }); + + expect(result).toMatchObject({ + submittedPercentage: 60, + completedPercentage: 10, + distributionAvailable: true, + statusDistribution: DEMO_STATUS_DISTRIBUTION, + isUserEnabled: true, + }); + }); + + it.each([ + ['a missing canonical status', DEMO_STATUS_DISTRIBUTION.slice(0, -1)], + ['a duplicate status', [...DEMO_STATUS_DISTRIBUTION.slice(0, -1), DEMO_STATUS_DISTRIBUTION[0]]], + [ + 'an unknown status', + [...DEMO_STATUS_DISTRIBUTION.slice(0, -1), {status: 'unknown_status', percentage: 0}], + ], + [ + 'a non-quantised percentage', + DEMO_STATUS_DISTRIBUTION.map((entry, index) => + index === 0 ? {...entry, percentage: 15} : entry, + ), + ], + ])('fails the entire detailed vector closed for %s', (_label, statusDistribution) => { + let result: PeerProgressIndicator | undefined; + + service.getIndicator(7, 99).subscribe((value) => { + result = value; + }); + + httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`).flush({ + task_definition_id: 99, + unit_id: 1, + target_grade: 2, + submitted_percentage: 60, + completed_percentage: 10, + distribution_available: true, + status_distribution: statusDistribution, + is_user_enabled: true, + is_suppressed: false, + is_stale: false, + is_feature_enabled: true, + last_updated_at: '2026-08-23T00:00:00Z', + unavailable_message: '', + distribution_unavailable_reason: 'detailed_data_unavailable', + }); + + expect(result?.distributionAvailable).toBe(false); + expect(result?.statusDistribution).toEqual([]); + expect(result?.completedPercentage).toBe(10); + }); + + it('scrubs every compact and detailed value when the server reports the user preference off', () => { + let result: PeerProgressIndicator | undefined; + + service.getIndicator(7, 99).subscribe((value) => { + result = value; + }); + + httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`).flush({ + task_definition_id: 99, + unit_id: 1, + target_grade: 2, + submitted_percentage: 60, + completed_percentage: 10, + distribution_available: true, + status_distribution: DEMO_STATUS_DISTRIBUTION, + is_user_enabled: false, + is_suppressed: false, + is_stale: false, + is_feature_enabled: true, + last_updated_at: '2026-08-23T00:00:00Z', + unavailable_message: 'server-provided preference detail', + unavailable_reason: 'user_disabled', + distribution_unavailable_reason: 'user_disabled', + }); + + expect(result).toMatchObject({ + submittedPercentage: null, + completedPercentage: null, + distributionAvailable: false, + statusDistribution: [], + isUserEnabled: false, + unavailableReason: 'user_disabled', + }); + }); + + it('scrubs compact and detailed values from a suppressed response even if the payload is malformed', () => { + let result: PeerProgressIndicator | undefined; + + service.getIndicator(7, 99).subscribe((value) => { + result = value; + }); + + httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`).flush({ + task_definition_id: 99, + unit_id: 1, + target_grade: 2, + submitted_percentage: 60, + completed_percentage: 10, + distribution_available: true, + status_distribution: DEMO_STATUS_DISTRIBUTION, + is_user_enabled: true, + is_suppressed: true, + is_stale: false, + is_feature_enabled: true, + last_updated_at: '2026-08-23T00:00:00Z', + unavailable_message: 'Not enough students to show progress.', + unavailable_reason: 'insufficient_cohort', + distribution_unavailable_reason: 'insufficient_cohort', + }); + + expect(result).toMatchObject({ + submittedPercentage: null, + completedPercentage: null, + distributionAvailable: false, + statusDistribution: [], + isSuppressed: true, + }); + }); + + it('does not retain unrecognised reason strings from the API', () => { + let result: PeerProgressIndicator | undefined; + + service.getIndicator(7, 99).subscribe((value) => { + result = value; + }); + + httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`).flush({ + task_definition_id: 99, + unit_id: 1, + target_grade: 2, + submitted_percentage: 60, + completed_percentage: 10, + distribution_available: false, + status_distribution: null, + is_user_enabled: true, + is_suppressed: false, + is_stale: false, + is_feature_enabled: true, + last_updated_at: '2026-08-23T00:00:00Z', + unavailable_message: '', + unavailable_reason: 'sensitive-internal-reason', + distribution_unavailable_reason: 'sensitive-internal-detail', + }); + + expect(result?.unavailableReason).toBeNull(); + expect(result?.distributionUnavailableReason).toBeNull(); + }); + + it.each([ + ['not finite', Number.NaN, Number.POSITIVE_INFINITY], + ['negative', -10, -20], + ['over 100', 110, 120], + ['not quantised', 15, 25], + ])( + 'fails malformed compact percentages closed when they are %s', + (_label, submitted, completed) => { + let result: PeerProgressIndicator | undefined; + + service.getIndicator(7, 99).subscribe((value) => { + result = value; + }); + + httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`).flush({ + task_definition_id: 99, + unit_id: 1, + target_grade: 2, + submitted_percentage: submitted, + completed_percentage: completed, + distribution_available: false, + status_distribution: null, + is_user_enabled: true, + is_suppressed: false, + is_stale: false, + is_feature_enabled: true, + last_updated_at: '2026-08-23T00:00:00Z', + unavailable_message: '', + }); + + expect(result?.submittedPercentage).toBeNull(); + expect(result?.completedPercentage).toBeNull(); + }, + ); + it('cancels the live HTTP request when the caller unsubscribes', () => { const subscription = service.getIndicator(7, 99).subscribe(); const request = httpMock.expectOne(`${API_URL}/projects/7/task_def_id/99/peer_progress`); diff --git a/src/app/api/services/spec/user.service.spec.ts b/src/app/api/services/spec/user.service.spec.ts index 2e03e7e9c4..5dfc671571 100644 --- a/src/app/api/services/spec/user.service.spec.ts +++ b/src/app/api/services/spec/user.service.spec.ts @@ -53,6 +53,7 @@ describe('UserService', () => { firstName: 'Jake', lastName: 'renzella', email: 'jake@jake.jake', + displayPeerProgress: false, }); }); @@ -74,9 +75,25 @@ describe('UserService', () => { receive_portfolio_notifications: false, receive_feedback_notifications: false, receive_task_notifications: false, + display_peer_progress: false, }); }); + it('serialises the peer progress display preference when updating a profile', () => { + const user = new User(); + user.id = 1; + user.displayPeerProgress = false; + + userService.update(user).subscribe(); + + const req = httpMock.expectOne('http://localhost:3000/api/users/1'); + expect(req.request.method).toBe('PUT'); + expect(req.request.body).toMatchObject({ + user: {display_peer_progress: false}, + }); + req.flush({id: 1, display_peer_progress: false}); + }); + it('should create a new user', () => { const user = new User(); user.lastName = 'renzella'; diff --git a/src/app/api/services/user.service.ts b/src/app/api/services/user.service.ts index c63e903b2b..075cf921b0 100644 --- a/src/app/api/services/user.service.ts +++ b/src/app/api/services/user.service.ts @@ -31,6 +31,7 @@ export class UserService extends CachedEntityService { 'receiveTaskNotifications', 'receivePortfolioNotifications', 'receiveFeedbackNotifications', + 'displayPeerProgress', 'hasRunFirstTimeSetup', 'pronouns', 'acceptedTiiEula', diff --git a/src/app/common/edit-profile-form/edit-profile-form.component.html b/src/app/common/edit-profile-form/edit-profile-form.component.html index c1dcd7c77b..5465ccdf80 100644 --- a/src/app/common/edit-profile-form/edit-profile-form.component.html +++ b/src/app/common/edit-profile-form/edit-profile-form.component.html @@ -92,6 +92,27 @@

        {{ user?.firstName }}

        +
        +

        Peer progress

        + + Display anonymous peer progress statistics + + + This controls whether you see the privacy-protected widget below your submission details. + It does not opt your anonymous task status out of authorised cohort aggregation. + +
        + -
        +
        @if ($userIsTyping | async) {
        From deedb28ea295a90b8539bdb373b450a084971114 Mon Sep 17 00:00:00 2001 From: owensmac Date: Thu, 20 Aug 2026 15:19:52 +1000 Subject: [PATCH 1460/1531] fix: changed the waveform ui/ux for accurate audio displaying (cherry picked from commit 3e3a1229f258c212f490b454355170f6fc158bd6) --- .../audio-comment-recorder.html | 23 +++++++------ .../audio-comment-recorder.ts | 5 +++ .../audio/base-audio-recorder.ts | 32 +++++++++---------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html b/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html index 736059be22..dc55b8b008 100644 --- a/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html +++ b/src/app/common/audio-recorder/audio/audio-comment-recorder/audio-comment-recorder.html @@ -1,4 +1,4 @@ -
        +

        Audio recording
        only supported in modern versions of Chrome, Firefox and Safari. @@ -11,13 +11,13 @@ >

        - +
        + +
        Date: Wed, 26 Aug 2026 05:18:06 +1000 Subject: [PATCH 1474/1531] chore: format unit task editor --- .../unit-task-editor.component.html | 36 ++++++------------- .../unit-task-editor.component.ts | 30 ++++++++-------- 2 files changed, 25 insertions(+), 41 deletions(-) diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html index 0d95db5031..f9265f7169 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.html @@ -38,14 +38,10 @@

        Task List

        @if (unit.allowFlexibleDates) { - + } - +
        @if (unit.allowFlexibleDates) { @@ -169,9 +165,7 @@

        Manage Target Dates

        \ No newline at end of file +
        diff --git a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts index 39830be3ec..0077c64900 100644 --- a/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts +++ b/src/app/units/states/edit/directives/unit-tasks-editor/unit-task-editor.component.ts @@ -1,18 +1,18 @@ -import { addWeeks } from 'date-fns'; -import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { MatTableDataSource } from '@angular/material/table'; -import { Subscription } from 'rxjs'; -import { TaskDefinition } from 'src/app/api/models/task-definition'; -import { GradeDefinition, Unit } from 'src/app/api/models/unit'; -import { FeedbackTemplateService } from 'src/app/api/services/feedback-template.service'; -import { TaskDefinitionService } from 'src/app/api/services/task-definition.service'; -import { ConfirmationModalService } from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; +import {addWeeks} from 'date-fns'; +import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {MatTableDataSource} from '@angular/material/table'; +import {Subscription} from 'rxjs'; +import {TaskDefinition} from 'src/app/api/models/task-definition'; +import {GradeDefinition, Unit} from 'src/app/api/models/unit'; +import {FeedbackTemplateService} from 'src/app/api/services/feedback-template.service'; +import {TaskDefinitionService} from 'src/app/api/services/task-definition.service'; +import {ConfirmationModalService} from 'src/app/common/modals/confirmation-modal/confirmation-modal.service'; import { CsvResult, CsvResultModalService, } from 'src/app/common/modals/csv-result-modal/csv-result-modal.service'; -import { CsvUploadModalService } from 'src/app/common/modals/csv-upload-modal/csv-upload-modal.service'; -import { AlertService } from 'src/app/common/services/alert.service'; +import {CsvUploadModalService} from 'src/app/common/modals/csv-upload-modal/csv-upload-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; @Component({ selector: 'f-unit-task-editor', @@ -196,7 +196,7 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { } this.feedbackTemplateService - .query({ contextType: 'task_definitions', contextId: this.selectedTaskDefinition.id }, {}) + .query({contextType: 'task_definitions', contextId: this.selectedTaskDefinition.id}, {}) .subscribe({ error: () => this.alerts.error('Error loading task feedback templates.'), }); @@ -255,7 +255,7 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { this.csvUploadModal.show( 'Upload Task Definitions as CSV', 'Upload a CSV of task definitions.', - { file: { name: 'Task Definition CSV Data', type: 'csv' } }, + {file: {name: 'Task Definition CSV Data', type: 'csv'}}, this.unit.getTaskDefinitionBatchUploadUrl(), (response: CsvResult) => { // at least one student? @@ -272,7 +272,7 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { this.csvUploadModal.show( 'Upload Task Sheets and Resources as Zip', 'Upload a ZIP of task sheets and resources.', - { file: { name: 'Task Sheets and Resources', type: 'zip' } }, + {file: {name: 'Task Sheets and Resources', type: 'zip'}}, this.unit.taskUploadUrl, (response: CsvResult) => { // at least one student? @@ -305,4 +305,4 @@ export class UnitTaskEditorComponent implements OnInit, OnDestroy { this.selectedTaskDefinition = task; } -} \ No newline at end of file +} From 33211392e00027eb3175a694f0bddf3ab6730b44 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Wed, 26 Aug 2026 05:11:23 +1000 Subject: [PATCH 1475/1531] fix: use valid 960px Tailwind variants --- src/app/welcome/welcome.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/welcome/welcome.component.html b/src/app/welcome/welcome.component.html index 87f311bd9a..40bc7d8228 100644 --- a/src/app/welcome/welcome.component.html +++ b/src/app/welcome/welcome.component.html @@ -1,7 +1,7 @@
        - + -
        +
        From 1326ade155a9026dbfeb4ee6a424bfe272e44010 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Wed, 26 Aug 2026 06:19:16 +1000 Subject: [PATCH 1476/1531] fix: scope dashboard reset to completed submissions --- src/app/api/models/task.ts | 18 +++- .../api/services/spec/task.service.spec.ts | 59 ++++++++++++ src/app/api/services/task.service.ts | 8 ++ .../project-dashboard.component.spec.ts | 92 +++++++++++++++++++ .../project-dashboard.component.ts | 8 +- .../upload-submission-modal.component.ts | 2 +- 6 files changed, 180 insertions(+), 7 deletions(-) create mode 100644 src/app/api/services/spec/task.service.spec.ts create mode 100644 src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts diff --git a/src/app/api/models/task.ts b/src/app/api/models/task.ts index bac5be4451..3f27f45158 100644 --- a/src/app/api/models/task.ts +++ b/src/app/api/models/task.ts @@ -905,7 +905,11 @@ export class Task extends Entity { ); } - public processTaskStatusChange(expectedStatus: TaskStatusEnum, alerts: AlertService) { + public processTaskStatusChange( + expectedStatus: TaskStatusEnum, + alerts: AlertService, + submissionCompleted: boolean = false, + ) { if (this.inTimeExceeded() && !this.isPastDeadline()) { alerts.message( 'You have submitted after the deadline for feedback. Your task will not be reviewed by a tutor. It is now your responsibility to ensure this task meets the required standard.', @@ -920,7 +924,7 @@ export class Task extends Entity { } this.getSubmissionDetails().subscribe(); const taskService: TaskService = AppInjector.get(TaskService); - taskService.notifyStatusChange(this); + taskService.notifyTransitionComplete(this, submissionCompleted); } public async markAsDiscussed(reasonText?: string) { @@ -994,6 +998,7 @@ export class Task extends Entity { status: TaskStatusEnum, markAsDiscussed?: boolean, triggerRecursiveFix?: boolean, + submissionCompleted: boolean = false, ) { const oldStatus = this.status; const oldGrade = this.grade; @@ -1043,7 +1048,7 @@ export class Task extends Entity { this.project.taskCache.delete(this.definition.abbreviation); this.project.taskCache.add(this); } - this.processTaskStatusChange(status, alerts); + this.processTaskStatusChange(status, alerts, submissionCompleted); taskService.notifyStatusChange(this); }, error: (error) => { @@ -1093,7 +1098,12 @@ export class Task extends Entity { } else if (requiresFileUpload && !this.isReadyForUpload) { alerts.error('Complete Knowledge Check first to submit files', 6000); } else { - await this.updateTaskStatus(status); + await this.updateTaskStatus( + status, + undefined, + undefined, + TaskStatus.SUBMITTABLE_STATUSES.includes(status), + ); } } diff --git a/src/app/api/services/spec/task.service.spec.ts b/src/app/api/services/spec/task.service.spec.ts new file mode 100644 index 0000000000..0e8f4428c4 --- /dev/null +++ b/src/app/api/services/spec/task.service.spec.ts @@ -0,0 +1,59 @@ +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {provideHttpClient} from '@angular/common/http'; +import {TestBed} from '@angular/core/testing'; +import {Task} from 'src/app/api/models/task'; +import {TaskService} from '../task.service'; + +describe('TaskService status events', () => { + let service: TaskService; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [TaskService, provideHttpClient()], + }); + service = TestBed.inject(TaskService); + }); + + it('keeps general status changes separate from completed submissions', () => { + const task = {} as Task; + const statusUpdated = vi.fn(); + const submissionCompleted = vi.fn(); + service.taskStatusUpdated$.subscribe(statusUpdated); + service.taskSubmissionCompleted$.subscribe(submissionCompleted); + + service.notifyStatusChange(task); + + expect(statusUpdated).toHaveBeenCalledOnce(); + expect(statusUpdated).toHaveBeenCalledWith(task); + expect(submissionCompleted).not.toHaveBeenCalled(); + }); + + it('broadcasts both events when a submission completes', () => { + const task = {} as Task; + const statusUpdated = vi.fn(); + const submissionCompleted = vi.fn(); + service.taskStatusUpdated$.subscribe(statusUpdated); + service.taskSubmissionCompleted$.subscribe(submissionCompleted); + + service.notifyTransitionComplete(task, true); + + expect(statusUpdated).toHaveBeenCalledOnce(); + expect(statusUpdated).toHaveBeenCalledWith(task); + expect(submissionCompleted).toHaveBeenCalledOnce(); + expect(submissionCompleted).toHaveBeenCalledWith(task); + }); + + it('does not treat a non-submission transition as a completed submission', () => { + const task = {} as Task; + const statusUpdated = vi.fn(); + const submissionCompleted = vi.fn(); + service.taskStatusUpdated$.subscribe(statusUpdated); + service.taskSubmissionCompleted$.subscribe(submissionCompleted); + + service.notifyTransitionComplete(task, false); + + expect(statusUpdated).toHaveBeenCalledOnce(); + expect(statusUpdated).toHaveBeenCalledWith(task); + expect(submissionCompleted).not.toHaveBeenCalled(); + }); +}); diff --git a/src/app/api/services/task.service.ts b/src/app/api/services/task.service.ts index e82b781f12..cd51c0c5fb 100644 --- a/src/app/api/services/task.service.ts +++ b/src/app/api/services/task.service.ts @@ -17,6 +17,7 @@ import {MappingFunctions} from './mapping-fn'; @Injectable() export class TaskService extends CachedEntityService { public readonly taskStatusUpdated$: EventEmitter = new EventEmitter(); + public readonly taskSubmissionCompleted$: EventEmitter = new EventEmitter(); protected readonly endpointFormat = '/projects/:projectId:/task_def_id/:taskDefId:'; @@ -243,6 +244,13 @@ export class TaskService extends CachedEntityService { this.taskStatusUpdated$.emit(task); } + public notifyTransitionComplete(task: Task, submissionCompleted: boolean): void { + this.notifyStatusChange(task); + if (submissionCompleted) { + this.taskSubmissionCompleted$.emit(task); + } + } + public readonly statusColors: Map = TaskStatus.STATUS_COLORS; public readonly switchableStates = TaskStatus.SWITCHABLE_STATES; diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts new file mode 100644 index 0000000000..9e9ce52eb3 --- /dev/null +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts @@ -0,0 +1,92 @@ +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {BreakpointObserver} from '@angular/cdk/layout'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {ActivatedRoute} from '@angular/router'; +import {EMPTY, Subject, of} from 'rxjs'; +import {Project, Task, TaskDefinition} from 'src/app/api/models/doubtfire-model'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {TaskService} from 'src/app/api/services/task.service'; +import {UnitService} from 'src/app/api/services/unit.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {GlobalStateService} from '../../index/global-state.service'; +import {ProjectDashboardComponent} from './project-dashboard.component'; + +describe('ProjectDashboardComponent task selection', () => { + let component: ProjectDashboardComponent; + let fixture: ComponentFixture; + let taskStatusUpdated$: Subject; + let taskSubmissionCompleted$: Subject; + + const project = {id: 7} as Project; + const selectedTaskDefinition = {id: 42} as TaskDefinition; + + beforeEach(async () => { + taskStatusUpdated$ = new Subject(); + taskSubmissionCompleted$ = new Subject(); + + await TestBed.configureTestingModule({ + declarations: [ProjectDashboardComponent], + providers: [ + {provide: UserService, useValue: {}}, + {provide: ProjectService, useValue: {get: () => EMPTY}}, + { + provide: TaskService, + useValue: {taskStatusUpdated$, taskSubmissionCompleted$}, + }, + {provide: UnitService, useValue: {}}, + {provide: GlobalStateService, useValue: {setView: vi.fn()}}, + { + provide: ActivatedRoute, + useValue: { + parent: { + snapshot: { + data: {project}, + paramMap: {get: () => String(project.id)}, + }, + }, + }, + }, + { + provide: BreakpointObserver, + useValue: {observe: () => of({matches: false, breakpoints: {}})}, + }, + ], + schemas: [NO_ERRORS_SCHEMA], + }) + .overrideComponent(ProjectDashboardComponent, {set: {template: ''}}) + .compileComponents(); + + fixture = TestBed.createComponent(ProjectDashboardComponent); + component = fixture.componentInstance; + component.project$ = of(project); + fixture.detectChanges(); + component.selectedTaskDefinition$.next(selectedTaskDefinition); + }); + + it('keeps the selected task when an unrelated status-change event is emitted', () => { + taskStatusUpdated$.next({project, definition: selectedTaskDefinition} as Task); + + expect(component.selectedTaskDefinition$.value).toBe(selectedTaskDefinition); + }); + + it('returns to the dashboard after the selected task submission completes', () => { + taskSubmissionCompleted$.next({project, definition: selectedTaskDefinition} as Task); + + expect(component.selectedTaskDefinition$.value).toBeNull(); + }); + + it('ignores submission events from another project or task definition', () => { + taskSubmissionCompleted$.next({ + project: {id: project.id + 1}, + definition: selectedTaskDefinition, + } as Task); + expect(component.selectedTaskDefinition$.value).toBe(selectedTaskDefinition); + + taskSubmissionCompleted$.next({ + project, + definition: {id: selectedTaskDefinition.id + 1}, + } as Task); + expect(component.selectedTaskDefinition$.value).toBe(selectedTaskDefinition); + }); +}); diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts index d5cb1cf35b..b0b9ab0409 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts @@ -155,9 +155,13 @@ export class ProjectDashboardComponent implements OnInit, OnDestroy { this.leftWidth = this.taskListCollapsedWidth; } - this.taskService.taskStatusUpdated$.pipe(takeUntil(this.destroy$)).subscribe((task) => { + this.taskService.taskSubmissionCompleted$.pipe(takeUntil(this.destroy$)).subscribe((task) => { + const activeProject = this.projectSubject.value; const selectedTaskDefinition = this.selectedTaskDefinition$.value; - if (selectedTaskDefinition && task.definition?.id === selectedTaskDefinition.id) { + if ( + activeProject?.id === task.project?.id && + selectedTaskDefinition?.id === task.definition?.id + ) { this.selectedTaskDefinition$.next(null); } }); diff --git a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.component.ts b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.component.ts index 5107f3f584..f5f6d42b6d 100644 --- a/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.component.ts +++ b/src/app/tasks/modals/upload-submission-modal/upload-submission-modal.component.ts @@ -298,7 +298,7 @@ export class UploadSubmissionModalComponent implements OnInit { : response.status; this.task.updateFromJson(response, this.taskService.mapping); - this.task.processTaskStatusChange(expectedStatus as TaskStatusEnum, this.alertService); + this.task.processTaskStatusChange(expectedStatus as TaskStatusEnum, this.alertService, true); }, 1500); }; From 39ec6a8e8760d81b80ebc72f2c54a69fa84fd493 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Wed, 26 Aug 2026 20:14:17 +1000 Subject: [PATCH 1477/1531] ci: add weekly integration PR workflow --- .github/workflows/weekly-integration-prs.yml | 90 ++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 .github/workflows/weekly-integration-prs.yml diff --git a/.github/workflows/weekly-integration-prs.yml b/.github/workflows/weekly-integration-prs.yml new file mode 100644 index 0000000000..56c7a60760 --- /dev/null +++ b/.github/workflows/weekly-integration-prs.yml @@ -0,0 +1,90 @@ +name: Weekly integration PRs + +on: + schedule: + - cron: "17 9 * * 1" + timezone: Australia/Melbourne + workflow_dispatch: + +permissions: + contents: read + +jobs: + ensure-pr: + if: github.repository_owner == 'ontrack-features-t2-2026' + name: ${{ matrix.source }} -> ${{ matrix.target }} + runs-on: ubuntu-24.04 + timeout-minutes: 10 + + strategy: + fail-fast: false + max-parallel: 4 + matrix: + include: + - source: feature/cross-unit + target: 11.0.x + - source: feature/notifications + target: 11.0.x + - source: feature/peer-progress-indicator + target: 11.0.x + - source: feature/calendar-integration + target: 11.0.x + + concurrency: + group: ${{ github.workflow }}-${{ matrix.target }}-${{ matrix.source }} + cancel-in-progress: false + + steps: + - name: Ensure pull request exists + shell: bash + env: + GH_TOKEN: ${{ secrets.INTEGRATION_BOT_TOKEN }} + SOURCE_BRANCH: ${{ matrix.source }} + TARGET_BRANCH: ${{ matrix.target }} + run: | + set -euo pipefail + + if [[ -z "${GH_TOKEN:-}" ]]; then + echo "::error::INTEGRATION_BOT_TOKEN is not configured." + exit 1 + fi + + existing="$( + gh api --method GET "repos/$GITHUB_REPOSITORY/pulls" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2026-03-10" \ + -f state=open \ + -f head="${GITHUB_REPOSITORY_OWNER}:${SOURCE_BRANCH}" \ + -f base="$TARGET_BRANCH" \ + -F per_page=1 \ + --jq '.[0].html_url // empty' + )" + + if [[ -n "$existing" ]]; then + echo "Pull request already open: $existing" + exit 0 + fi + + target_ref="$(jq -rn --arg ref "$TARGET_BRANCH" '$ref | @uri')" + source_ref="$(jq -rn --arg ref "$SOURCE_BRANCH" '$ref | @uri')" + comparison="$( + gh api "repos/$GITHUB_REPOSITORY/compare/${target_ref}...${source_ref}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2026-03-10" \ + --jq '[.ahead_by, (.files | length)] | @tsv' + )" + read -r ahead changed_files <<< "$comparison" + + if [[ "$ahead" == "0" || "$changed_files" == "0" ]]; then + echo "Nothing to merge from $SOURCE_BRANCH into $TARGET_BRANCH." + exit 0 + fi + + gh api --method POST "repos/$GITHUB_REPOSITORY/pulls" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2026-03-10" \ + -f title="Integration: $SOURCE_BRANCH into $TARGET_BRANCH" \ + -f head="$SOURCE_BRANCH" \ + -f base="$TARGET_BRANCH" \ + -f body="Created by the scheduled integration workflow. The source branch is intentionally retained after merge." \ + --jq '.html_url' From 832d5e47eb26ff2e21ce25e576daa13b3054cc3e Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Wed, 26 Aug 2026 21:55:16 +1000 Subject: [PATCH 1478/1531] test: restore project dashboard constructor coverage --- .../project-dashboard/project-dashboard.component.spec.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts index 004fb35a74..c8f9c21479 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts @@ -4,6 +4,7 @@ import {ActivatedRoute, convertToParamMap} from '@angular/router'; import {BehaviorSubject, Subject, of, tap} from 'rxjs'; import {Project, TaskDefinition, Unit} from 'src/app/api/models/doubtfire-model'; import {ProjectService} from 'src/app/api/services/project.service'; +import {TaskService} from 'src/app/api/services/task.service'; import {UnitService} from 'src/app/api/services/unit.service'; import {UserService} from 'src/app/api/services/user.service'; import {GlobalStateService, ViewType} from '../../index/global-state.service'; @@ -52,6 +53,7 @@ describe('ProjectDashboardComponent route reuse', () => { const component = new ProjectDashboardComponent( {} as UserService, {get: projectGet} as unknown as ProjectService, + {} as TaskService, {get: unitGet} as unknown as UnitService, {setView} as unknown as GlobalStateService, { @@ -98,6 +100,7 @@ describe('ProjectDashboardComponent route reuse', () => { const component = new ProjectDashboardComponent( {} as UserService, {get: projectGet} as unknown as ProjectService, + {} as TaskService, {get: unitGet} as unknown as UnitService, {setView: vi.fn()} as unknown as GlobalStateService, { @@ -154,6 +157,7 @@ describe('ProjectDashboardComponent route reuse', () => { const component = new ProjectDashboardComponent( {} as UserService, {get: projectGet} as unknown as ProjectService, + {} as TaskService, {get: unitGet} as unknown as UnitService, {setView: vi.fn()} as unknown as GlobalStateService, { From 739c872be12e81b70126eb13e3e3193249629f43 Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Thu, 27 Aug 2026 11:45:36 +1000 Subject: [PATCH 1479/1531] ci: skip integration PR when a matrix branch is gone The compare call 404s once a source or target branch is deleted, and with set -euo pipefail that fails the whole weekly job instead of skipping the entry. Check both refs exist first and exit 0 when either is missing. --- .github/workflows/weekly-integration-prs.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/weekly-integration-prs.yml b/.github/workflows/weekly-integration-prs.yml index 56c7a60760..59eefb3cf4 100644 --- a/.github/workflows/weekly-integration-prs.yml +++ b/.github/workflows/weekly-integration-prs.yml @@ -67,6 +67,16 @@ jobs: target_ref="$(jq -rn --arg ref "$TARGET_BRANCH" '$ref | @uri')" source_ref="$(jq -rn --arg ref "$SOURCE_BRANCH" '$ref | @uri')" + + for ref in "$target_ref" "$source_ref"; do + if ! gh api "repos/$GITHUB_REPOSITORY/branches/${ref}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2026-03-10" \ + --silent >/dev/null 2>&1; then + echo "Branch $ref no longer exists in $GITHUB_REPOSITORY; skipping." + exit 0 + fi + done comparison="$( gh api "repos/$GITHUB_REPOSITORY/compare/${target_ref}...${source_ref}" \ -H "Accept: application/vnd.github+json" \ From d1352b22fccabc8ed1707f64a59b73fed85ad20b Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Thu, 27 Aug 2026 11:54:05 +1000 Subject: [PATCH 1480/1531] fix(deps): keep the caret on the build toolchain @angular/build, @angular/cli and ngx-monaco-editor-v2-alternative were pinned to exact versions. In a change whose purpose is remediating audit findings that is the wrong direction: it stops the next patch release arriving and stops a later npm audit fix from taking it, and @angular/build is one of the packages carrying an advisory on the base branch. Restored as ^22.0.9, ^22.0.9 and ^22.0.0. The resolved versions in the lockfile are unchanged and still satisfy the ranges, so nothing is upgraded here. The root declaration in package-lock.json is updated to match, which is what npm ci compares against. The exact dompurify pin inside overrides is deliberate and is left alone. npm audit on origin/11.0.x: 12 total, 4 high, 5 moderate, 3 low. npm audit with this branch: 0. --- package-lock.json | 6 +++--- package.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index b196f0fe62..57ca0548b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,7 +47,7 @@ "ng2-pdf-viewer": "10.4.0", "ngx-entity-service": "^0.0.44", "ngx-lottie": "^22.0.0", - "ngx-monaco-editor-v2-alternative": "22.0.0", + "ngx-monaco-editor-v2-alternative": "^22.0.0", "ngx-skeleton-loader": "^13.0.0", "qrcode": "^1.5.4", "rxjs": "~7.8.2", @@ -61,8 +61,8 @@ "@angular-eslint/eslint-plugin-template": "^22.0.0", "@angular-eslint/schematics": "^22.0.0", "@angular-eslint/template-parser": "^22.0.0", - "@angular/build": "22.0.9", - "@angular/cli": "22.0.9", + "@angular/build": "^22.0.9", + "@angular/cli": "^22.0.9", "@angular/compiler-cli": "^22.0.3", "@angular/language-service": "^22.0.3", "@commitlint/cli": "^21.1.0", diff --git a/package.json b/package.json index 439817c39b..20c3655142 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "ng2-pdf-viewer": "10.4.0", "ngx-entity-service": "^0.0.44", "ngx-lottie": "^22.0.0", - "ngx-monaco-editor-v2-alternative": "22.0.0", + "ngx-monaco-editor-v2-alternative": "^22.0.0", "ngx-skeleton-loader": "^13.0.0", "qrcode": "^1.5.4", "rxjs": "~7.8.2", @@ -80,8 +80,8 @@ "@angular-eslint/eslint-plugin-template": "^22.0.0", "@angular-eslint/schematics": "^22.0.0", "@angular-eslint/template-parser": "^22.0.0", - "@angular/build": "22.0.9", - "@angular/cli": "22.0.9", + "@angular/build": "^22.0.9", + "@angular/cli": "^22.0.9", "@angular/compiler-cli": "^22.0.3", "@angular/language-service": "^22.0.3", "@commitlint/cli": "^21.1.0", From 1ff6351333b73c82884cdb09b22f84897d3ce75c Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Wed, 26 Aug 2026 01:26:54 +1000 Subject: [PATCH 1481/1531] fix(dashboard): keep the target grade read only for staff The target grade selector lost its static disabled attribute, so it was live for anyone viewing the dashboard, staff included, and the API permits the change because tutors hold :change on a project. The component already computes viewingOtherStudentProject, so the guard uses that. The Task Planner carried the same unguarded selector and now matches. Deselecting had moved into applyFilters, which is bound to the search box, so every keystroke closed the open task and rewrote the URL, losing an unsent comment with it. It now only deselects when the open task has gone or a view filter hides it. Hiding tasks above the target grade is counted by the filter badge, and a task with unread comments stays visible the way the hide-completed filter already allows, so tutor feedback cannot disappear behind the new default. --- .../progress-dashboard.component.html | 2 +- .../progress-dashboard.component.spec.ts | 15 ++ .../states/plan/project-plan.component.html | 2 + .../plan/project-plan.component.spec.ts | 92 ++++++++++++ .../unit-task-list.component.html | 2 +- .../unit-task-list.component.spec.ts | 133 +++++++++++++++++- .../unit-task-list.component.ts | 64 +++++++-- 7 files changed, 290 insertions(+), 20 deletions(-) create mode 100644 src/app/projects/states/plan/project-plan.component.spec.ts diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html index 199a65492e..8eb72cbf50 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.html @@ -36,7 +36,7 @@

        Select Target Grade diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts index 9664b38441..e3f280b28c 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts @@ -100,6 +100,21 @@ describe('ProgressDashboardComponent', () => { expect(component.numberOfTasks).toEqual({completed: 1, remaining: 2}); }); + it('locks the selector when staff are viewing another student project', async () => { + project.unit.myRole = 'Tutor'; + project.student = {id: 99} as Project['student']; + fixture.detectChanges(); + await fixture.whenStable(); + + const loader = TestbedHarnessEnvironment.loader(fixture); + const select = await loader.getHarness( + MatSelectHarness.with({selector: '[aria-label="Target grade"]'}), + ); + + expect(component.viewingOtherStudentProject).toBe(true); + expect(await select.isDisabled()).toBe(true); + }); + it('restores the previous target grade when the update fails', () => { projectServiceUpdate.mockReturnValueOnce(throwError(() => new Error('update failed'))); vi.spyOn(console, 'error').mockImplementation(() => undefined); diff --git a/src/app/projects/states/plan/project-plan.component.html b/src/app/projects/states/plan/project-plan.component.html index 50714cdf88..fec6f873fa 100644 --- a/src/app/projects/states/plan/project-plan.component.html +++ b/src/app/projects/states/plan/project-plan.component.html @@ -23,7 +23,9 @@

        Target Grade diff --git a/src/app/projects/states/plan/project-plan.component.spec.ts b/src/app/projects/states/plan/project-plan.component.spec.ts new file mode 100644 index 0000000000..36aa3beab7 --- /dev/null +++ b/src/app/projects/states/plan/project-plan.component.spec.ts @@ -0,0 +1,92 @@ +import {beforeEach, describe, expect, it, vi} from 'vitest'; +import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {FormsModule} from '@angular/forms'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatSelectModule} from '@angular/material/select'; +import {MatSelectHarness} from '@angular/material/select/testing'; +import {NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {ActivatedRoute} from '@angular/router'; +import {of} from 'rxjs'; +import {Project} from 'src/app/api/models/project'; +import {ProjectService} from 'src/app/api/services/project.service'; +import {UserService} from 'src/app/api/services/user.service'; +import {CalendarModalService} from 'src/app/common/modals/calendar-modal/calendar-modal.service'; +import {AlertService} from 'src/app/common/services/alert.service'; +import {GradeService} from 'src/app/common/services/grade.service'; +import {ProjectPlanComponent} from './project-plan.component'; + +describe('ProjectPlanComponent', () => { + let component: ProjectPlanComponent; + let fixture: ComponentFixture; + let project: Project; + + const buildProject = (myRole: string, studentId: number): Project => + ({ + id: 18, + targetGrade: 0, + student: {id: studentId}, + unit: { + myRole, + allowFlexibleDates: false, + gradeDefinitions: [ + {value: 0, label: 'Pass', abbreviation: 'P'}, + {value: 1, label: 'Credit', abbreviation: 'C'}, + ], + }, + }) as unknown as Project; + + const createComponent = async (currentProject: Project) => { + project = currentProject; + + await TestBed.configureTestingModule({ + declarations: [ProjectPlanComponent], + imports: [FormsModule, MatFormFieldModule, MatSelectModule, NoopAnimationsModule], + providers: [ + { + provide: GradeService, + useValue: { + gradeValuesFor: () => [0, 1], + gradeLabel: (grade: number) => (grade === 0 ? 'Pass' : 'Credit'), + }, + }, + {provide: ProjectService, useValue: {update: vi.fn()}}, + {provide: AlertService, useValue: {success: vi.fn(), error: vi.fn()}}, + {provide: CalendarModalService, useValue: {show: vi.fn()}}, + {provide: UserService, useValue: {currentUser: {id: 25}}}, + {provide: ActivatedRoute, useValue: {parent: null}}, + ], + schemas: [NO_ERRORS_SCHEMA], + }).compileComponents(); + + fixture = TestBed.createComponent(ProjectPlanComponent); + component = fixture.componentInstance; + component.project$ = of(project); + fixture.detectChanges(); + await fixture.whenStable(); + }; + + const targetGradeSelect = () => + TestbedHarnessEnvironment.loader(fixture).getHarness( + MatSelectHarness.with({selector: '[aria-label="Target grade"]'}), + ); + + beforeEach(() => { + TestBed.resetTestingModule(); + }); + + it('lets a student change their own target grade', async () => { + await createComponent(buildProject('Student', 25)); + + expect(component.viewingOtherStudentProject).toBe(false); + expect(await (await targetGradeSelect()).isDisabled()).toBe(false); + }); + + it('locks the selector when staff are viewing another student project', async () => { + await createComponent(buildProject('Tutor', 99)); + + expect(component.viewingOtherStudentProject).toBe(true); + expect(await (await targetGradeSelect()).isDisabled()).toBe(true); + }); +}); diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html index c25ba50e8e..809fc698d3 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html @@ -179,7 +179,7 @@ class="shrink-0 text-formatif-blue disabled:text-gray-400" mat-button type="button" - [disabled]="activeViewPreferenceCount === 0" + [disabled]="!hasNonDefaultViewPreferences" (click)="resetViewPreferences()" > Reset diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts index b9ff6240d9..84c968c3df 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.spec.ts @@ -25,14 +25,40 @@ const taskDefinition = ( name: abbreviation, startDate, targetGrade, + targetGradeText: 'Pass', }) as TaskDefinition; -const taskForDefinition = (definition: TaskDefinition, topWeight: number): Task => +const taskForDefinition = ( + definition: TaskDefinition, + topWeight: number, + numNewComments = 0, +): Task => ({ definition, topWeight, + numNewComments, }) as Task; +const studentProject = () => + ({ + id: 10, + targetGrade: 0, + unit: {id: 20}, + calcTopTasks: () => undefined, + }) as unknown as Project; + +// Mirrors the wiring ngOnInit does, without the route lookup it also performs. +const openTaskDefinition = ( + component: FUnitTaskListComponent, + taskDef: TaskDefinition, +): BehaviorSubject => { + const selectedTaskDefinition$: BehaviorSubject = new BehaviorSubject(taskDef); + component.selectedTaskDefinition$ = selectedTaskDefinition$; + selectedTaskDefinition$.subscribe((value) => (component.selectedTaskDef = value)); + + return selectedTaskDefinition$; +}; + describe('FUnitTaskListComponent', () => { let component: FUnitTaskListComponent; let fixture: ComponentFixture; @@ -277,7 +303,7 @@ describe('FUnitTaskListComponent', () => { component.applyFilters(); expect(component.filteredTaskDefinitions).toEqual([passTask]); - expect(component.activeViewPreferenceCount).toBe(0); + expect(component.activeViewPreferenceCount).toBe(1); }); it('reveals tasks beyond the target grade only when explicitly selected', () => { @@ -295,12 +321,12 @@ describe('FUnitTaskListComponent', () => { component.toggleShowAboveTargetGrade(true); expect(component.filteredTaskDefinitions).toEqual([passTask, creditTask]); - expect(component.activeViewPreferenceCount).toBe(1); + expect(component.activeViewPreferenceCount).toBe(0); component.resetViewPreferences(); expect(component.filteredTaskDefinitions).toEqual([passTask]); - expect(component.activeViewPreferenceCount).toBe(0); + expect(component.activeViewPreferenceCount).toBe(1); }); it('reapplies target-grade filtering when the selected target changes', () => { @@ -334,4 +360,103 @@ describe('FUnitTaskListComponent', () => { expect(component.filteredTaskDefinitions).toEqual([passTask, distinctionTask]); }); + + it('keeps the open task selected when the search term stops matching it', () => { + const openTask = taskDefinition(1, 'P1'); + const otherTask = taskDefinition(2, 'P2'); + component.project = studentProject(); + component.targetGrade = 0; + component.taskDefinitions = [openTask, otherTask]; + component.tasks = []; + const selectedTaskDefinition$ = openTaskDefinition(component, openTask); + + component.searchText = 'P1'; + component.applyFilters(); + + expect(component.filteredTaskDefinitions).toEqual([openTask]); + expect(selectedTaskDefinition$.value).toBe(openTask); + + component.searchText = 'P2'; + component.applyFilters(); + + expect(component.filteredTaskDefinitions).toEqual([otherTask]); + expect(selectedTaskDefinition$.value).toBe(openTask); + }); + + it('drops the selection when a view filter hides the open task', () => { + const passTask = taskDefinition(1, 'P1', undefined, 0); + const creditTask = taskDefinition(2, 'C1', undefined, 1); + component.project = studentProject(); + component.targetGrade = 0; + component.taskDefinitions = [passTask, creditTask]; + component.tasks = []; + component.toggleShowAboveTargetGrade(true); + const selectedTaskDefinition$ = openTaskDefinition(component, creditTask); + + component.toggleShowAboveTargetGrade(false); + + expect(component.filteredTaskDefinitions).toEqual([passTask]); + expect(selectedTaskDefinition$.value).toBeNull(); + }); + + it('drops the selection when the open task leaves the task definitions', () => { + const passTask = taskDefinition(1, 'P1'); + const removedTask = taskDefinition(2, 'P2'); + component.project = studentProject(); + component.targetGrade = 0; + component.taskDefinitions = [passTask, removedTask]; + component.tasks = []; + const selectedTaskDefinition$ = openTaskDefinition(component, removedTask); + + component.taskDefinitions = [passTask]; + component.applyFilters(); + + expect(selectedTaskDefinition$.value).toBeNull(); + }); + + it('badges the filter button while tasks beyond the target grade are hidden', () => { + component.project = studentProject(); + component.targetGrade = 0; + component.taskDefinitions = [taskDefinition(1, 'P1')]; + component.tasks = []; + + component.applyFilters(); + + expect(component.hidingTasksAboveTargetGrade).toBe(true); + expect(component.activeViewPreferenceCount).toBe(1); + expect(component.hasNonDefaultViewPreferences).toBe(false); + + component.toggleShowAboveTargetGrade(true); + + expect(component.hidingTasksAboveTargetGrade).toBe(false); + expect(component.activeViewPreferenceCount).toBe(0); + expect(component.hasNonDefaultViewPreferences).toBe(true); + }); + + it('does not badge target-grade hiding on an all-tasks list', () => { + component.mode = 'all-tasks'; + component.taskDefinitions = [taskDefinition(1, 'P1')]; + component.tasks = []; + + component.applyFilters(); + + expect(component.activeViewPreferenceCount).toBe(0); + }); + + it('still shows a task beyond the target grade when it has unread comments', () => { + const passTask = taskDefinition(1, 'P1', undefined, 0); + const creditTask = taskDefinition(2, 'C1', undefined, 1); + const distinctionTask = taskDefinition(3, 'D1', undefined, 2); + component.project = studentProject(); + component.targetGrade = 0; + component.taskDefinitions = [passTask, creditTask, distinctionTask]; + component.tasks = [ + taskForDefinition(creditTask, 2, 3), + taskForDefinition(distinctionTask, 3, 0), + ]; + + component.applyFilters(); + + expect(component.filteredTaskDefinitions).toEqual([passTask, creditTask]); + }); }); diff --git a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts index 20400dded7..3bf8c86b6f 100644 --- a/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts +++ b/src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.ts @@ -104,13 +104,27 @@ export class FUnitTaskListComponent implements OnChanges, OnInit, OnDestroy { .filter((taskDef) => this.shouldShowTaskDefinition(taskDef)) .sort((a, b) => this.compareTaskDefinitions(a, b)); - if ( - this.selectedTaskDef && - !this.filteredTaskDefinitions.some((taskDef) => taskDef.id === this.selectedTaskDef.id) - ) { - this.selectedTaskDefinition$?.next(null); - this.replaceSelectionUrl(null); + this.deselectHiddenTaskDefinition(); + } + + // The search term only narrows what the list shows, so typing must not close the + // open task. Drop the selection when the task itself has gone or a view filter + // hides it. + private deselectHiddenTaskDefinition(): void { + if (!this.selectedTaskDef) { + return; } + + const selectedTaskDefinition = this.taskDefinitions?.find( + (taskDef) => taskDef.id === this.selectedTaskDef.id, + ); + + if (selectedTaskDefinition && this.shouldShowTaskDefinition(selectedTaskDefinition)) { + return; + } + + this.selectedTaskDefinition$?.next(null); + this.replaceSelectionUrl(null); } public setSortBy(sortBy: TaskListSortOption): void { @@ -182,7 +196,22 @@ export class FUnitTaskListComponent implements OnChanges, OnInit, OnDestroy { return ( (this.viewPreferences.sortBy !== 'default' ? 1 : 0) + (this.viewPreferences.hideCompleted ? 1 : 0) + - (this.viewPreferences.showAboveTargetGrade ? 1 : 0) + (this.hidingTasksAboveTargetGrade ? 1 : 0) + ); + } + + // The list hides tasks beyond the target grade unless the student opts in, so the + // badge has to count the hiding, not the opt-in that switches it off. + public get hidingTasksAboveTargetGrade(): boolean { + return !this.viewPreferences.showAboveTargetGrade && this.effectiveTargetGrade !== null; + } + + public get hasNonDefaultViewPreferences(): boolean { + return ( + this.viewPreferences.sortBy !== DEFAULT_VIEW_PREFERENCES.sortBy || + this.viewPreferences.sortDirection !== DEFAULT_VIEW_PREFERENCES.sortDirection || + this.viewPreferences.hideCompleted !== DEFAULT_VIEW_PREFERENCES.hideCompleted || + this.viewPreferences.showAboveTargetGrade !== DEFAULT_VIEW_PREFERENCES.showAboveTargetGrade ); } @@ -388,19 +417,26 @@ export class FUnitTaskListComponent implements OnChanges, OnInit, OnDestroy { } return !( - !this.viewPreferences.showAboveTargetGrade && this.isTaskDefinitionAboveTargetGrade(taskDef) + !this.viewPreferences.showAboveTargetGrade && + this.isTaskDefinitionAboveTargetGrade(taskDef) && + !this.hasNewComments(task) ); } private isTaskDefinitionAboveTargetGrade(taskDef: TaskDefinition): boolean { + const targetGrade = this.effectiveTargetGrade; + + return targetGrade !== null && taskDef.targetGrade > targetGrade; + } + + private get effectiveTargetGrade(): number | null { const targetGrade = this.targetGrade ?? this.project?.targetGrade; - return ( - !!this.project && - targetGrade !== undefined && - targetGrade !== null && - taskDef.targetGrade > targetGrade - ); + if (!this.project || targetGrade === undefined || targetGrade === null) { + return null; + } + + return targetGrade; } private hasNewComments(task: Task): boolean { From e7977f64dbd6a73db062f5d623ce6caced51df12 Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Wed, 26 Aug 2026 01:26:56 +1000 Subject: [PATCH 1482/1531] fix(dashboard): do not reload the project on every re-emission Swapping first() for takeUntil made the subscription permanent, which is what unit switching needs. It also meant every emission re-ran activateProject, which resets projectReady and clears the selected task. The portfolios progress tab re-emits on every change detection pass, because its taskSelectionUrlBase getter returned a new array each call and ngOnChanges pushed into the project subject unconditionally. The tab reset itself continuously. activateProject now returns early when the project is already the active one, the url base is memoised, and ngOnChanges only pushes when the project input actually changed. --- .../project-dashboard.component.spec.ts | 111 ++++++++++++++++++ .../project-dashboard.component.ts | 8 ++ .../portfolios-project-progress.component.ts | 5 +- .../states/portfolios/portfolios.component.ts | 20 +++- 4 files changed, 141 insertions(+), 3 deletions(-) diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts index 198552b369..1ae1ac81ef 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts @@ -1,5 +1,6 @@ import {beforeEach, describe, expect, it, vi} from 'vitest'; import {BreakpointObserver} from '@angular/cdk/layout'; +import {CommonModule} from '@angular/common'; import {NO_ERRORS_SCHEMA} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {ActivatedRoute, convertToParamMap} from '@angular/router'; @@ -266,3 +267,113 @@ describe('ProjectDashboardComponent route reuse', () => { component.ngOnDestroy(); }); }); + +describe('ProjectDashboardComponent rendered by its host', () => { + let fixture: ComponentFixture; + let component: ProjectDashboardComponent; + let hostProject$: BehaviorSubject; + let project: Project; + let unit: Unit; + let projectResponses: Subject[]; + let projectGet: ReturnType; + let unitGet: ReturnType; + + // The portfolios progress tab hands its dashboard a new task selection url every check, because + // the host builds that array in a getter. Each one re-runs the host's ngOnChanges, which pushes + // the project it is already showing back down the same subject. + const rebindHost = (): void => { + fixture.componentRef.setInput('taskSelectionUrlBase', [ + '/units', + 1, + 'students', + 'portfolios', + project.id, + 'progress', + ]); + hostProject$.next(project); + fixture.detectChanges(); + }; + + beforeEach(async () => { + unit = { + id: 101, + taskDefinitions: [], + studentCache: {add: vi.fn()}, + } as unknown as Unit; + project = { + id: 2, + targetGrade: 0, + unit, + tasks: [], + findTaskForDefinition: () => null, + } as unknown as Project; + + projectResponses = []; + projectGet = vi.fn( + (_params: {id: number}, options: {mappingCompleteCallback: (project: Project) => void}) => { + const response: Subject = new Subject(); + projectResponses.push(response); + return response.pipe(tap((loaded) => options.mappingCompleteCallback(loaded))); + }, + ); + unitGet = vi.fn(() => of(unit)); + + await TestBed.configureTestingModule({ + imports: [CommonModule], + declarations: [ProjectDashboardComponent], + providers: [ + {provide: UserService, useValue: {}}, + {provide: ProjectService, useValue: {get: projectGet}}, + {provide: UnitService, useValue: {get: unitGet}}, + {provide: GlobalStateService, useValue: {setView: vi.fn()}}, + { + provide: ActivatedRoute, + useValue: {parent: {data: of({}), snapshot: {paramMap: convertToParamMap({})}}}, + }, + { + provide: BreakpointObserver, + useValue: {observe: () => of({matches: false, breakpoints: {}})}, + }, + ], + schemas: [NO_ERRORS_SCHEMA], + }).compileComponents(); + + fixture = TestBed.createComponent(ProjectDashboardComponent); + component = fixture.componentInstance; + hostProject$ = new BehaviorSubject(project); + fixture.componentRef.setInput('project$', hostProject$); + fixture.detectChanges(); + }); + + it('keeps the loaded project and the open task when the host re-emits the same project', () => { + projectResponses[0].next(project); + fixture.detectChanges(); + + const selectedTaskDefinition = {id: 7} as TaskDefinition; + component.selectedTaskDefinition$.next(selectedTaskDefinition); + fixture.detectChanges(); + + rebindHost(); + rebindHost(); + + expect(component.selectedTaskDefinition$.value).toBe(selectedTaskDefinition); + expect(component.isProjectTaskListReady(project)).toBe(true); + expect(projectGet).toHaveBeenCalledTimes(1); + expect(unitGet).toHaveBeenCalledTimes(1); + + fixture.destroy(); + }); + + it('does not cancel a load that is still in flight when the same project comes back', () => { + rebindHost(); + + expect(projectGet).toHaveBeenCalledTimes(1); + + projectResponses[0].next(project); + fixture.detectChanges(); + + expect(component.isProjectTaskListReady(project)).toBe(true); + + fixture.destroy(); + }); +}); diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts index 147a9f6489..f087e1e730 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts @@ -206,6 +206,14 @@ export class ProjectDashboardComponent implements OnInit, OnDestroy { return; } + // Hosts re-emit the project they are already showing. The portfolios progress tab does it on + // every change detection pass, and the reset below would drop the loaded project back to its + // skeleton and close the open task each time. Activating is only for a project we are not + // already showing or already fetching, so a repeat of the active one is left alone. + if (projectId === this.activeProjectId) { + return; + } + this.projectLoadCancel$.next(); const activation = ++this.projectActivation; this.activeProjectId = projectId; diff --git a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts index 0c90dcaf1e..02e826996e 100644 --- a/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts +++ b/src/app/units/states/portfolios/directives/portfolios-project-progress/portfolios-project-progress.component.ts @@ -5,6 +5,7 @@ import { HostListener, Input, OnChanges, + SimpleChanges, } from '@angular/core'; import {BehaviorSubject} from 'rxjs'; import {Project} from 'src/app/api/models/project'; @@ -76,8 +77,8 @@ export class PortfoliosProjectProgressComponent implements OnChanges { scrollContainer.scrollBy({top: event.deltaY}); } - ngOnChanges(): void { - if (this.project) { + ngOnChanges(changes: SimpleChanges): void { + if (changes.project && this.project) { this.project$.next(this.project); } } diff --git a/src/app/units/states/portfolios/portfolios.component.ts b/src/app/units/states/portfolios/portfolios.component.ts index 88e0c665bb..cbb33fdd59 100644 --- a/src/app/units/states/portfolios/portfolios.component.ts +++ b/src/app/units/states/portfolios/portfolios.component.ts @@ -47,6 +47,8 @@ export class PortfoliosComponent implements OnInit, OnDestroy { private subscriptions: Subscription[] = []; private selectedProjectId: number | null = null; + private progressTaskSelectionUrlBaseCache: unknown[] | null = null; + private progressTaskSelectionUrlBaseKey: string | null = null; constructor( private projectService: ProjectService, @@ -102,7 +104,23 @@ export class PortfoliosComponent implements OnInit, OnDestroy { return null; } - return ['/units', this.unit.id, 'students', 'portfolios', this.selectedProject.id, 'progress']; + // Cache the array so the binding keeps the same reference between change detection passes. + // A new literal each call makes the input dirty every check, which pushes the progress tab + // to re-emit its project over and over. + const key = `${this.unit.id}/${this.selectedProject.id}`; + if (key !== this.progressTaskSelectionUrlBaseKey) { + this.progressTaskSelectionUrlBaseKey = key; + this.progressTaskSelectionUrlBaseCache = [ + '/units', + this.unit.id, + 'students', + 'portfolios', + this.selectedProject.id, + 'progress', + ]; + } + + return this.progressTaskSelectionUrlBaseCache; } public studentSelected(project: Project): void { From 7e8190c007364066b7779c121be75a2ddea4be4a Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Thu, 27 Aug 2026 18:38:37 +1000 Subject: [PATCH 1483/1531] fix(layout): complete page-container migration --- .../institution-settings.component.html | 8 +- .../institution-settings.component.scss | 3 - .../page-container.component.html | 4 +- .../page-container.component.spec.html | 3 + .../page-container.component.spec.ts | 51 ++ .../page-container.component.ts | 7 +- src/app/doubtfire-angular.module.ts | 2 +- .../project-groups.component.html | 4 +- .../states/plan/project-plan.component.html | 12 +- .../tutor-discussion.component.html | 446 +++++++++--------- .../states/tutorials/tutorials.component.html | 4 +- .../edit/unit-admin-state.component.html | 13 +- .../unit-groups/unit-groups.component.html | 34 +- .../states/rollover/rollover.component.html | 2 +- 14 files changed, 331 insertions(+), 262 deletions(-) create mode 100644 src/app/common/page-container/page-container.component.spec.html create mode 100644 src/app/common/page-container/page-container.component.spec.ts diff --git a/src/app/admin/institution-settings/institution-settings.component.html b/src/app/admin/institution-settings/institution-settings.component.html index 5526a8dc96..b10bafbc64 100644 --- a/src/app/admin/institution-settings/institution-settings.component.html +++ b/src/app/admin/institution-settings/institution-settings.component.html @@ -1,4 +1,4 @@ -
        +
        Learning Outcomes

        } @case ('turnitin') { - +
        + +
        } }

        -
        \ No newline at end of file +
        diff --git a/src/app/admin/institution-settings/institution-settings.component.scss b/src/app/admin/institution-settings/institution-settings.component.scss index 7017d84036..b1baa5aebe 100644 --- a/src/app/admin/institution-settings/institution-settings.component.scss +++ b/src/app/admin/institution-settings/institution-settings.component.scss @@ -1,6 +1,3 @@ -.institution-settings-container { - padding: 0 5rem 0 5rem; -} .learning-outcomes-container { padding: 0 1rem 1rem 1rem; } diff --git a/src/app/common/page-container/page-container.component.html b/src/app/common/page-container/page-container.component.html index fda1420fbc..0f16dbb224 100644 --- a/src/app/common/page-container/page-container.component.html +++ b/src/app/common/page-container/page-container.component.html @@ -1,3 +1,3 @@ -
        +
        -
        \ No newline at end of file +
        diff --git a/src/app/common/page-container/page-container.component.spec.html b/src/app/common/page-container/page-container.component.spec.html new file mode 100644 index 0000000000..79b2eb2ba5 --- /dev/null +++ b/src/app/common/page-container/page-container.component.spec.html @@ -0,0 +1,3 @@ + + Projected content + diff --git a/src/app/common/page-container/page-container.component.spec.ts b/src/app/common/page-container/page-container.component.spec.ts new file mode 100644 index 0000000000..58801448c6 --- /dev/null +++ b/src/app/common/page-container/page-container.component.spec.ts @@ -0,0 +1,51 @@ +import {beforeEach, describe, expect, it} from 'vitest'; +import {Component} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {PageContainerComponent} from './page-container.component'; + +@Component({ + templateUrl: './page-container.component.spec.html', + standalone: false, +}) +class PageContainerTestHostComponent { + fullWidth = false; +} + +describe('PageContainerComponent', () => { + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PageContainerComponent, PageContainerTestHostComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(PageContainerTestHostComponent); + fixture.detectChanges(); + }); + + it('renders a block-level constrained container with projected content', () => { + const host: HTMLElement = fixture.nativeElement.querySelector('f-page-container'); + const container: HTMLElement = host.querySelector(':scope > div'); + + expect(host.classList.contains('block')).toBe(true); + expect(host.classList.contains('w-full')).toBe(true); + expect(new Set(container.classList)).toEqual( + new Set(['mx-auto', 'w-full', 'px-4', 'sm:px-6', 'lg:px-8', 'max-w-screen-xl']), + ); + expect(container.querySelector('[data-testid="projected-content"]')?.textContent).toContain( + 'Projected content', + ); + }); + + it('removes the width constraint while retaining responsive padding', () => { + const pageContainerFixture = TestBed.createComponent(PageContainerComponent); + pageContainerFixture.componentRef.setInput('fullWidth', true); + pageContainerFixture.detectChanges(); + + const container: HTMLElement = pageContainerFixture.nativeElement.querySelector('div'); + + expect(new Set(container.classList)).toEqual( + new Set(['mx-auto', 'w-full', 'px-4', 'sm:px-6', 'lg:px-8']), + ); + }); +}); diff --git a/src/app/common/page-container/page-container.component.ts b/src/app/common/page-container/page-container.component.ts index 5cf01368fe..463eb57634 100644 --- a/src/app/common/page-container/page-container.component.ts +++ b/src/app/common/page-container/page-container.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; +import {Component, Input, booleanAttribute} from '@angular/core'; @Component({ selector: 'f-page-container', templateUrl: './page-container.component.html', + host: {class: 'block w-full'}, standalone: false, }) export class PageContainerComponent { - @Input() fullWidth = false; -} \ No newline at end of file + @Input({transform: booleanAttribute}) fullWidth = false; +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index eb8f54dcad..98d9e825be 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -184,7 +184,6 @@ import {TasksForInboxSearchPipe} from './common/filters/tasks-for-inbox-search.p import {TasksInTutorialsPipe} from './common/filters/tasks-in-tutorials.pipe'; import {TasksOfTaskDefinitionPipe} from './common/filters/tasks-of-task-definition.pipe'; import {FooterComponent} from './common/footer/footer.component'; -import {PageContainerComponent} from './common/page-container/page-container.component'; import {GradeIconComponent} from './common/grade-icon/grade-icon.component'; import {HeaderComponent} from './common/header/header.component'; import {TaskDropdownComponent} from './common/header/task-dropdown/task-dropdown.component'; @@ -212,6 +211,7 @@ import {SpecConModalService} from './common/modals/spec-con-modal/spec-con-modal import {TaskAssessmentModalComponent} from './common/modals/task-assessment-modal/task-assessment-modal.component'; import {TutorNotesModalComponent} from './common/modals/tutor-notes-modal/tutor-notes-modal.component'; import {ObjectSelectComponent} from './common/obect-select/object-select.component'; +import {PageContainerComponent} from './common/page-container/page-container.component'; import {PdfViewerPanelComponent} from './common/pdf-viewer-panel/pdf-viewer-panel.component'; import {fPdfViewerComponent} from './common/pdf-viewer/pdf-viewer.component'; import {HumanizedDatePipe} from './common/pipes/humanized-date.pipe'; diff --git a/src/app/projects/states/groups/project-groups/project-groups.component.html b/src/app/projects/states/groups/project-groups/project-groups.component.html index 7eca48477b..80e6de1aee 100644 --- a/src/app/projects/states/groups/project-groups/project-groups.component.html +++ b/src/app/projects/states/groups/project-groups/project-groups.component.html @@ -1,4 +1,4 @@ -
        + @if (unit.hasGroupwork()) { @@ -9,4 +9,4 @@

        No Group Work

        There is no group work enabled for this unit.

        } -
        + diff --git a/src/app/projects/states/plan/project-plan.component.html b/src/app/projects/states/plan/project-plan.component.html index 0463c3ab6b..7e69eb6996 100644 --- a/src/app/projects/states/plan/project-plan.component.html +++ b/src/app/projects/states/plan/project-plan.component.html @@ -12,8 +12,8 @@

        View and adjust the due dates for your tasks. Remember to leave time to get and respond to feedback. } @else { - View the task deadlines for your project, so you can organise your work and ensure you meet - all submission requirements on time. + View the task deadlines for your project, so you can organise your work and ensure you + meet all submission requirements on time. }

        @@ -43,7 +43,9 @@

        - - + +
        + +
        -} \ No newline at end of file +} diff --git a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html index 78089a4f36..130d3ff248 100644 --- a/src/app/projects/states/tutor-discussion/tutor-discussion.component.html +++ b/src/app/projects/states/tutor-discussion/tutor-discussion.component.html @@ -27,248 +27,256 @@
        -
        - @if (attendance && unit) { -
        - - - @for ( - td of $safeNavigationMigration(unit?.taskDefinitionCache.values) | async; - track td - ) { - {{ td.abbreviation }} - {{ td.name }} - } - - - @if (selectedTaskDefinition) { - - } -
        - } - -
        -
        - @if (project && project?.student) { - -
        -
        - {{ project?.student?.firstName }} {{ project?.student?.lastName }} - @if (project?.student.studentId) { - ({{ project?.student.studentId }}) + +
        + @if (attendance && unit) { +
        + + + @for ( + td of $safeNavigationMigration(unit?.taskDefinitionCache.values) | async; + track td + ) { + {{ td.abbreviation }} - {{ td.name }} } + + + @if (selectedTaskDefinition) { + + } +
        + } + +
        +
        + @if (project && project?.student) { + +
        +
        + {{ project?.student?.firstName }} {{ project?.student?.lastName }} + @if (project?.student.studentId) { + ({{ project?.student.studentId }}) + } +
        +
        + Target Grade: + {{ getTargetTradeString($safeNavigationMigration(project?.targetGrade)) }} +
        -
        - Target Grade: {{ getTargetTradeString($safeNavigationMigration(project?.targetGrade)) }} -
        -
        - } @else { -
        -
        Click the QR code to open the scanner..
        - } - -
        + } @else { +
        +
        Click the QR code to open the scanner..
        + } + +
        - @if (project && !filteredTasks.length) { -
        No tasks to discuss.
        - } - - @for (task of filteredTasks; track task) { - - @if (task) { -
        -
        - - No tasks to discuss.
        + } + + @for (task of filteredTasks; track task) { + + @if (task) { +
        +
        - -
        -

        {{ task.definition.name }}

        - - {{ task.definition.abbreviation }} - - {{ getTargetTradeString(task.definition.targetGrade) }} Task - -
        - @if (task.hasGrade()) { -
        - {{ task.gradeDesc() }} - + + + +
        +

        {{ task.definition.name }}

        + + {{ task.definition.abbreviation }} - + {{ getTargetTradeString(task.definition.targetGrade) }} Task +
        - } - + @if (task.hasGrade()) { +
        + {{ task.gradeDesc() }} + +
        + } + - + +
        +
        - -
        + } +
        + } + + +
        + @if (project) { +
        + @if (this.allTasks?.length > 0) { + @if (this.filteredTasks?.length < this.allTasks?.length) { + + } @else { + + } } - +
        } - - - @if (project) { -
        - @if (this.allTasks?.length > 0) { - @if (this.filteredTasks?.length < this.allTasks?.length) { -
        + + @if (project && filteredTasks.length) { +
        +
        + @if (attendance) { + } @else { - + - } - } -
        - } - - -
        - - @if (project && filteredTasks.length) { -
        -
        - @if (attendance) { - - } @else { - - - - @if (selectedTasksIncludeDiscuss) { + @if (selectedTasksIncludeDiscuss) { + + } } - } +
        -
        - } + } - @if (selectedTask && project) { - - + @if (selectedTask && project) { + + - - - + + + - @if (footerTabView === TutorDiscussionTabView.SHOW_COMMENTS) { -
        - + @if (footerTabView === TutorDiscussionTabView.SHOW_COMMENTS) { +
        + - - -
        - } @else if (footerTabView === TutorDiscussionTabView.SHOW_STAFF_NOTES) { - - } @else if (footerTabView === TutorDiscussionTabView.SHOW_DISCUSSION_PROMPTS) { - + + +
        + } @else if (footerTabView === TutorDiscussionTabView.SHOW_STAFF_NOTES) { + + } @else if (footerTabView === TutorDiscussionTabView.SHOW_DISCUSSION_PROMPTS) { + + } } - } -
        +
        + diff --git a/src/app/projects/states/tutorials/tutorials.component.html b/src/app/projects/states/tutorials/tutorials.component.html index 1cacaa3902..8d518cd183 100644 --- a/src/app/projects/states/tutorials/tutorials.component.html +++ b/src/app/projects/states/tutorials/tutorials.component.html @@ -105,6 +105,6 @@

        Tutorials

        -
        +
        -} \ No newline at end of file +} diff --git a/src/app/units/states/edit/unit-admin-state.component.html b/src/app/units/states/edit/unit-admin-state.component.html index 9c5602fbe0..eaedf22db4 100644 --- a/src/app/units/states/edit/unit-admin-state.component.html +++ b/src/app/units/states/edit/unit-admin-state.component.html @@ -12,11 +12,16 @@
        @if (loadingUnit) { - +
        Tutorials

        mX@yWmb}hh36QMsXueN7gGlHs0pcw_#h&uS-0OHueSAb~^KWB3 zw$DyL?ywPqp!igUX>AJKX=W!<%k7t&eN1}11=E2N^&u}Uv z0?1i}cN5PjkATS@tpgan(SsT?mn$+-^gcVN*N=t3MqJ}WK)aY00#v6mnccJ7Z$v9E3x}YNp(*v}ZgJ@Q$$};c1N=s_ zOe}fzbBQt@w^9I2@qxOt!~rd@yT-rWA;VE20I`Lk@!lP7HT{_r(=~{lJjuTB%l%|c)T4SeH4SN_AN(qM`AV(BP5q!f2NBiB>;&f78SjVyjAUyW&$IOZ@@Ws4*I6N1lvlmF}9S@XFriJu~8Ex5K*^#ahrK+3^_PDv$t38+1(nrUA zFA`%l6eC8Q=yUXSY>UBU3IC9ORKd=%->XUO54TW}>7*6j>4@A;JkY0D{{~w?o*n6E zOLE^D32bCP;BvD-n`w>YmzuXq^tM(2KQ#$wa=WIz(67(#w??)``FCP+0Yxa9(OanC zfvMoVqCin46`G6ZqC7)SpmWqui}nggV^$Z$5snQgCV&A-3f!m#g0V64i-^ytMi{<3C3i{$?JUiKwx~O9{1g?(x`^a zDwS;ox6+4#5ajJiyVE>y_&4?3l0_94QYk=~ZG^?~-yo(RzT-Z$SMG-`7s%PHQ^&k? z7(_rd&uDpN-n*GEXRh}0?I{_Tc?>QmJ%v6&6=u<$NZf(Gm;9@@l17|UzA;dL<}^2@zdJTIT`w8A+jl`|o}S06 z``Ke-U$l$P+!9~QnU_f(%#e&=YjD5wVw(aBWE9W>KVkk*^uiI?P~_~2mIpBl{Ps*S zVJ9)KAQACE_C|=Y5 za9y#w`107!i;5Gk`f*A(;wK!fQp;e%3lH-+rA%>4`oQOtj!)j=P)3jP80ccP&Hpp27n4){ZcR8K$ogPVslJpSJxf9`5FijfVdybHH) z7F6qV2DcQ*Bao=t^*Fs{5L~F6}G<`;nak+n83uPUT1_gSyn}AucIV%A6fgX ztR|K6&PVglS9RgDTgB$T%un5F4Bx1In}akWAsVyF3y1Fj{t0XqJhH(a$2gLaq|z=S zjqePyL5@?NOcLhNu85E}mq*9=8k$xTCp4b3Q5YV3^ zx5{UdQKcxwKjfk}zEbmP+?#29ux47P=A!{MV2#d^zt#hK@Mm4>{9|t3^3wsS-^6&K z+3V4T^g-zhX`e6Ge9)>ekQ;6Pa;h7L1n(hv8hZlX|IKiESH_~S)1EnM2&!KSHH&XV z{aRmd^*+W6m&@GCUqm>%*F#1&9x)J}#hH>Yga=uXv*#!Z=Utkn)JduP+l7&Ff}Kmx z^AD-KquQST3(=fRR(la<(CizU*faylh@S9GZ1&R?sBvmQUw0Ake^{A)xX!E#!Nx;> zZpF{-i}3C2t@Dprzw86qzY)5_q|z`B9%vlZW+HkniNDLDN=MU=)0)Dw0a$|^F+Wp8Zx@=PCl_(9T)~k%Vahn_Lkvg8 zIlQ-ElP;M0m+6kyFd=w;ljfEl4VQJ1Udoo#u0UO-X8o&qAu-AKTUza3L4?)KXJkz= zgu>fYksly4AyS-^YaI^23OtICh>FukDBC z-{5P*-(Xajvx0|`jKv&zV%F|tsWVusP{W}cWn+OD6@1b9dImg#SfIu=9 z0V!9824P`0=K`1q3Z5|n8=*^DB40gh2!zdoF*iOw`f4JNF_mJe-r5W7a~yGw9Jeq8 z=qj^x)PZ|v!Oqsv_^^0IZomhF`sn?R*XU@)(OZb)7%2nlnT2fD>DSh_(|b6R+eK^U zK-7c17It5cjYGex9_E-YiN%{L-KE^#WVxtIW$lG<%^B!Z*@^p20J_Ew z_^gZMq1_L0aa+jU4AOC{=2O5qIlHohB#)AOLNm>@Rx&b@{u5*;*5LMq6Ydu+ggi#W zA2cw*ntQKO6s==(-yc7=cmI#YLcF8P57W_dW-+wpte}lQwUZjdk8}BD?FxVJNq$as zpDFb66wacnchn5nstnUo*cwzF{@DVV39Afj$-Gx*>d&lUcb7Vd9ycdiZ+NM*YY}|a zwJR_vIEK@F@E;ioVhk-?rlB@Pv3{F~Y#=v|qqRyW-4&ii4Mcio? z6=tLf17Xncgwv|yEDiX%$?2ck`v@utaVlX_r-L4O1j%s~w^5HHTbQ_F8B%&Mn_Tbg z;El2-=f|w_zZ$zlP2{#)AR2?fYY(3g1Aafwsk+Q&elmiU$j7?Pgn!`E?_+eN$~qcx znDIL33F(Xkev-z=sM!^*AT5+~co~}PmaK%-UxQ-x>_}_QEr6_d7UMACp|u-;jc=@F zezFA4C!+p;nNMj3R07SH}vk)+|1j6wCTi)3?-%t_-roWiu z#cKXaP!>;+zhs$kNqc&1L;dl|@bJ7xkGvb3`Eo0yr+0IK(`0Y}cRfBu%`Ghr0SbqB zd3B65H6iQw1bhZ4Fu@w5c-$yq7gj;T7+}K^nAplxe9y2EeD4uw$sq?01{k#AMHGWH z%Y>@%fpR5_B#i5k6f%r3f3X9b;q0{$l?&3Ahvb>@RQ?Hr%-0kE6es9g16w48YW^CE zP4DjZ;o?4ee1cy7rDzXR*Plbi4LKL1` zL?$XO9-f>GDyWdBRH0CT778q3>_Ni!wIk*$3&_qEPWO4L&{I@be^n8rfP;ly?eXO| zF*&%=gb5I^w4~{I9ilI-uJ)mRO>Syp{dl<{fT(&G2LpJo1(cOh_}|9lhx@R)zw2m_ zJUutkywgMAIqkkmq*qFH4Eu(N;eWAtEh>ryA(FKgM_0~A5~s~gGq zF{4iaD@z9OG?#dbeB6Km-d5li+Z~gW>8!`+XCK23kCQCd)iy_psi`T$gMQnI-7R_U;uw=dSZa~y1T#M2lVe4K7Er4WDr6E z0M6V0>h0x0-C^P3?*R`(Mnz@0-n6#1{;&2)MNQ4;!c+^OV7@)o_)cA}H4xB*fX@~K z#5nWEl_Y??D1H&&>h!+-5}#dFfh0~JL*R%OXrT)!o%`;$oMvm?+|)cs?TBTOnjg z+4KAZZT}GBwcQjbl)VjvL81??KBU+vCrFS2;LY0!y>ACtHS%!c=H}+X!9o4Me+2=F zrhqilqK*#FO&+tIZtnyA!5xU)D*$L~wN?)XaLTJys{7~U5TH=V6*e^`d4D{|Wn@GE zO1Mx(0RadjA2&Vx$u5Ao2hg@yfz#pnp+P}l06}}R-5Ca;pngB_|DYsEiT?S6fx~Wt zdm>!1WPyu^H@C1*P+ops*XfP*-)yARy+jtXChA_?J)evo=F9coPQSADx40vXmvF`+Kx+QRXSHd3g^pNStrg?nOs0?g zlr3v;6*}rUsWQ3wWHIsSPkGMPS|C!OqvU ztKIvft28qoKDi9$kGn4Z=cVbujgHRV!wkXCRW|SKoVdL2^s4&niLcM6V;e3pNl1?1 z+-Zk2h}p-66o}cvDM4G-=j@dhNt6$zOHG|JKmlJ37sJkxC6VRNo!fEk$usxF{vwfT zc>Ztq;{UcVeiQ&Yxd$a&?o|jq-~d4f7*@eg#JeCscfcd;>HUJi`ut8XiBH$LUB#W2 zrhjLe5rE)b9Pn%I!!hb|jfeTLIJ48}o%CG~xcP*dJnZH%Vlda4G@P;BOeL1(m5& z*d`_CqSS~qb8U-c`Cx&D3V>`&R!H|#r3V7@Z&yL^v)FDhNn~Y(-t~$6I z+0H~B>1TGa58L3aIsHe>;;ShNV`~uAu&p(J$J$w~T$l-aJ-iqsjD2~n+aTH!(?u=5 zK(T*gFbx?)_cc7#HZT|nY)9RzalKT~$EjJ16uCg!?DbhiHxF%TyShb$=Rex=))EESMr`X39>EK^NvDh*{$x;1~$yd-p~V~Wfso>R6A z4*T>ntNdqrYkWfc_h@mwhTKe}Ixey9U&+Pa0kpl>IQjQ9n&qeCuLSY+;cuPHi9RhD ztN4r&rYBT$@yoM{ano@v%#yTmxj4wegYs&KJZrxoLG6sUr7hq}`3mIiPJ#9u4T{bDt%_kZi3eYIh!5k}lo+N(JLlw+xqC5Q z2F02VhHi8M)wGm0AD7QR9{z>uuneKD4>kn3K8ZWrzEHEK1Yc`En!S zk`n=GmwUlkA~9>t=;|5cvCheJIu3q=kxa-J6bt6ZVK-jlz+07b31f)s<#COuiuOnF zV@2Rj8ld(1L%_=-@_o8m0uePk)uiR9rRDMq3U;a9oOp%fUyM0SF{&`X)7Ym1`UKJ9 zmn}nIq^MdKWz?d`m{JJQt8f3N?TC;|iX=|CFP7jF^R-1TE{{E~gY8`~rio@Br(&6r z^mqnVr{h*@cghWev1W;VyYb;nv|}7M^a?<}47HI_7B#_GA#K@ol?JI_qag z&>mBh9UH)nSK}P&v`VS<5%RM6Pey1B#hX!>ocnX)5pEZfQw4e7peb)!L<|HsiQK4% zX5@i#2e+h@AJRUWe9^mONqQ}w%562KsH2<@%Y(q-12rx&Ejpw*-k>_3S0dBy2pD`j zBSnzo7>d9xQT)jCcSveq<^)X-vqP#Mi2Xz3kh&IHF|H;*eh^i{`Qu5>z--&YsBaZ{Er&Sggx4 zfpwMMuW<)t$D>4-j$Op=$fS%;buLx^Y@U$*t-H$&-w<#Z`Qw|-(frf1R*Bt-yxrh* zsWXWWg6YHU-H2{73Et*Ahg4q6Ex=yRMYp`^`%Pr7~ zFdj}gkxy+R@{-{LI+3#cD^zso$jI*Codc&=>2&+{uaMm2=ZAsth1>?k5?>-DqvTC} z4e&5vJkrb!5uQl74pD1Q_G0y!eAd5-(|FB^!==l6AoTSOL zwaZ_a1lf6u{+((Wn62X1Y*9Fc(dN*Uo#;T~Q3(vCy(h1IsDj%l$Tkb#0|`{nqbK%Jr7d-D z6Q`UTVd205<3eXRV1cpOcnG^lk#MKTW2$^J$Fv4lf;Kmq$%TY*D8rxtxZ)GCmIH4Y zx3O0~4&QA^-&L?pmO-jrcK2KLiQ8w!!j0gILV4Sa zd~s*|1K~ECo`*k1W@^piQ0RbDqsi`nsr+fPC(qfsVY8Fw1iQ%*t><)b)FRRzcK zUUhu(7ade)&b|F=8AQj9JMR24;c}v!ylyPOhvd((r`y3EQ(Bq}lhx!SW^BuXTD*wt zn(_U{m04DOKyRo38#pHOk{L&8VL4Su^Soi^L^9J%R2Z`L9emQsO#I^qa5-wUjK>?+=l*6YNnluk zp@b_Q$R7YpoHlVL1#|w?35fQB&eLT}y|~D`wh*aki*3(X%A`+LqJJ19@gS-=&`z~1 z43gmt&EFNSF1|S$z)3#T=n}A7Mc#&-8=5PGbKVhk;Ey=D-R8PZoihEV$q0+IHz@|4 zT)LXok~5YfhnQYgS~U3AlmemKcP+yYS!d%VgeQZ8|d;6Suo5V>LO(FV| zecKY&h985PjUC167$mQN6b0pZYm!&+p`m->irL%=cE8GxKF?KSs_AwV{M9BEZ7wx? zP9?TK@s>bl|8gCP7d6i2QxDKATl^nY_N?v+)7{rjjq0sRV)z9Mq@?%oW8zBxp5C`I}L`6Uj0A6jhJ9RHf9r= z=G+dLQWoaN+Lq@oR|3W^gWG2C)Eb z`e!@L^V1%V0&#Z9+5G#GCf&P!R==kly@EQrv@tq;C#qLc=2Rg)3f}Frx>*wmk{Q@m zC#XAsFJF#O(d&}&aNup~TBwWGlw5pZ6yd^w~02|AuKTk-#XrIok|aU z*~H?|3|-BrKvZ?GfT6P^;f|^3T7CrhGHvZ)>l&O=&50qNoX_JE);@d~ho;z8YxD;8 zPX_GR(QDB@;wWwBb>j!-P>eHc5Ro#q@1S4)27iH)mmOhV@Z=U0CFdV{RjZC-rQ%Od zCgFstGa#|!v3i6{B|5i}W_OQ<0mrEcQ+N??-a5GUOXT%R-2EzB6*B(ImO_6RXFn1< z9u{$@(Hxc)QH;ne8zj;yKC{FUk6;w*R+nJH&5k?JpL)Ro#NLH3C!4|kX@s3R7svfPLk#AW7T649llQzT z_jkfVu>pVC0|--=LPC1p>5?#OT(f)QcvnpR?R}wDql3Ex6-TV|@UBeS(vz(Ypwi5g zhXqQCtu);04))NP`MIrybX z%=`nP)w)F>Qxt0vWA-dCh_-Bx=tXc4i_7G{dmJf*+*pn}R}86Ukwukw<}YMYC<~m4 z^AZ{@oYC9aZtv55f_lAT>w(RMG2BN%D%uhSm)()Y=5>?d+oR*|D3EnuiIcjkNY&aGQaHJ*3i8=f7{_{v7_cOM)=c+uVyTcUa!AlwvE&}KHvh*fJ8Ax(fuCR zlfPR^BL`)nrPA=u#P|4gfV2)HxOz@IcBpRwt#Btk?}P`U2GO=yo~2*ya!A6|@41+o zdLEgw$0a4>STHrj+SvHfDtWD(!AdHZ$eUl!s40&6WoXhIpXQVHF4d-QH`ZhGT}-YD z4EaO=z50=OeFvRpFQYF`m^TTqWlZ?u#b#O&W!?yBkh~$2?3Qt0W-g&;3Zk>Lwx~@- zLfe$FalghfQe|`$gI>GXhsawOea=h}cUuA)?x8)m{Rj@T>{e?A%n@CM2Kx)atUX?C z-Z!(PQ4?Vx>f+9u5!RIi3f_P}-k*ktQtDu|&S82dwy&|xP3-;P+{{0#9>;Lan=75V ztX+L{se;yMQIjYKQ)I9lGFyuijUIpmgm#a++2rucDcR$Yt^1hCKAHGeAU%{|`xA<; zX#>Fpp`tIvt6NCq2vhc1lB~9FB4Jb!z29V!Jox^|DBXixyYo#%rs$G-HN(S1c7x=~ z+T*O##k)3#@|t&TB9ZUo?S;<((?>p5rrFHLL@A=dnU`I9*QE9zO9H+LgdZP>TCpT+ zPZR|r+1?8t%>Xp>PiWp)~n2`i)T*AYdZk}aeWfjr!pyX&p32zj38v?gZu=5;WaX0;{E zGU(~vFANV0+z+;)8^ExhAjH3|Y20g8VTEt|%WH$ix$IUhfB~)tr6vw{+q6(OSqJ;Q z@pb#~InvG#96qs2q>Cgj zaUlT#I}?+fn3hZuS;z;IY7_oinp_*60Y0vRG%TIFLGrw0aYz@fVsW zl);(`I{o6;;to0!TaV!qQAm-nU9;z-R%+986hO6SFEYbQp^v;XPT}cM7Q0fSOyK)3 zagytP=|O=TVxQd;*q<40c41z~rw07(%Aq>>(5|g9kv!{cw9^$4u_a8M0Pnc$5K`1u zIo2%_!G=@Oq$lAN(bos5GNvfb>N7r|9I5V#sjZ}eBYj<_$bonvu=DQLp-&g5(%2f( zfO&;JSs~LUNz5L)IPXHel?n4F4EVX857cHsEnTkv8&|G)yGYGoScJgVWXh#)WC$LD zhPm(y@3iIUA-6s99}j2IR<#U#nEsNO?dKI71F~RorLcEREDQym9Zx}&MPK$A%-8L0 zc3464s7N{zM0zPLZGQVDxCVP;DW=^JrxVr1fl0&m47fMY;P(ft4!6u-7p{`(b49AB z{xxUpzq$#vY|J8w>;+36aUH7c65XZ6nrFk4w?TtdX@MO<@a;UHKIJ!sbGn@oAR+M_ zK1=_C$13i$n}V7qPLTD%6P!eHW0J!g60i6s!wOcYFf+r=AFfD{^O0oZy8#Zc79m=P`g<&M`-yBTPlgQLDe-wYj zR^@h1Hzk~`z1*o*!^`}AUxpL0y*G}=UyXc5y=plddnK4}aCj{=20}3D8g0m<<2k8{ z=zgZmtqSjZM~45&OB{ryDnmjNr1{Smr{tRy7kc;LCI%ZaqfYP% zhkzCZ$o>Cg?3}_QX~VTUv2Al=+qN|m+sR~N+jb__#I}uzZQHiB>$~>9&;OG;>b|8gK`$y+N zYcIe-mqU~L{bLB`vFN`!?3t|`A8cSKT`4^w{#yqU7#b3ksu^}RMU2p@gs>HvJ=6kC z{N<%jTl<@Zirb6rwbLh-E?oStIki zVm-LN-PnEW-^u-lTI$CHYJpY|b)X0?ru+e2V1qqP5f6VPPlFLB69QtJS0YlVma9^R z3^bHR$XRnC)uBjbit)hf7=w!yV+xn5{KZ@-QS0|l9*Fmw4bTz_02fXoE(v9B1kF_` z#lglFVIa!w))%(5B@!JKetmt7lYxkezOSic=^s`~fkAU(VnbzOOCTKv4?(wrgbW?a zFZ?d7tt~_W(WvFGQY!TKryuzJL)2H1|Ar)q%zr#!sVOTn^BIsBGchqeM^2GMkYX|D zY+vv6>%(E7ilfld(t?74g-1sZ%*@<`FNqYY*k7)5D`fMH0JG!Wn3<-448*{IxLm#3 ztS<;=Z&r;8z2kmX7Elt$9*q6_7ZfY_iH(Psadq$-)7L36hb4{z*g^nzM<=t!zqwOs zrNZVdA3R3JYFmUKxcK<{!0Tr6dnQ965qgtW445&0dXA#NOAs&- z9xL1nD3t+`@xOrqV26Q$ajHKu`wrY`X=zC*DY0N=|3wUTLWy=yPQs}o;NjtGjE4{} z*INULp~LcqgJ95>8?Bdst|Nem85@%UgzTs<7!G)t*9H3nP>co$NrFN`1Tg&?YHH#D zn4%2$Ko-vSt=JV56aYEzA3%XIv|0tYT&DkuW&(+X@Fgu|aNtvNKPgN}WwV@hJ%uAj zg#n1o!4nW+Smsuv!T3)&4FE8Llp+8yH7@Dpx3swFa07PcfhZi-F4V(^A;Hgh)nbKc zSpaywbpu8hpNb7&_he<^Y`b0#TO6YR^>5@KTJ<{Tv!B48x;-qYQ`6HEz@feYW{%YV z=JaKo8yb>;x%newA!MK>&%%PL`(?tm>((Rs(VocXnPgyKK;IHCfEXDWxd-qA+qt+9 zro<3Kqhn#+P4ZqT>Fa-KbdH#?{O3f8WbBfXkbvxd+qfEBwN_F>{<J>4iy)>i zcvMS1sR<-xw;rloJ3X(SSZ#2-KOd@XTZrPw!z;C$Z-FB`ySnP3s(lT}zi)t)haqtoMo+`>d9F@3&3AWs11KTPP<6m|WlBkR6#^|FOt zQ&~z5Zg;Dxs^^U3WilQFD@VH__!9H%*@vEHCiII+J90(aGg1Ry3oq2&a3xf#nR=Ij z7FL!pV{~eBr1Lx74m5F6JzSC5Z}rT@YQZbab1+l485 zyMQr=Gl~Qa74;c-0w*F{I{~&v0=bHcip8&A|EwDIpe*p-CT+d;@BmHHrc?FzF&03| z($LgoRKHRM)({=NaaP?uxn|q#EqTyu~>1ZKLxfB;KwMMV@~%YNg;&j8{Y zO}{r})YRskm3A|t_cZW%N~QT*aOLwzN|=~Y&<)wdDa&7&o56n<2ke7p{OC3Nb3$Zi zSStmO)LN^pt0AGo^@}D~K7mcD&hH#ksbB^_gDqV>soGB(+>mXjIZri^5T4E1=A}k3Nku~35p2{1PBfaMmq&5^ez>) zDV;A*Q|O;>Sas)O$mI80Oc_qc&bS@?4{jbO*AL9wJEa5X)CP~>fyzSF>T5GrKWO7H z4B6Bxa;bhJn}8RD{|s?hs<$u3MZe!qE=#ThdM z>)XfAZm8}?q1FK@uwug%i-wGra9r>KIy9Xpa=ux#*Tv#>PIAGjcGi*Vd71^yd_;cE z)yGN;trbu_^qf)(`d3t(eRX+quFIa1aA1Dkrks6!j_LR5fAJiysWD}yEG=AdJ3{Jt z-CTCxH7*ege!X_5q-ZUsvwh1`YNNo zzB40>3$=%d7{OB&LyO(c=gK@Kw>qKN)*Dk!dnmIRnz-|%xVW$Zan#1EWnn!DcSPF5;M|gDbw!y+stB#faWTyY&A?;M6m&z;K>%IM(zoh%+)>JEVvMV&a+R*TU z%2NKJ8JFkdVC_=>CFkYhqZ5yml+saHx1a^vY1_s^;cLv@kzgA48}T4A(USe(KyMUI znXXl1S@-3++TL1nvZ9MEi*Hw3EV{UJW=6VNH`i;+Kat?fP%i0&EgJupcbGt-c!AA*H~=z091Y zEPGI=z37i0t!<4GPpCpPSYr2Fl;l7AcFXTv;hjhWb!XQ4h9?2UW;EOGvAXIKtID_n z`#qDcD>{o}g|ragA2fgRJ%FDjMisn7VVK~*`GHTGNig8=+qr-L6UyMwU<#fwf+U^a zE1DE1326_2h4c_}6+}(@m@ZDFnCvZ3$T3wtq32{2cpgW?y~Leq$8=VXZ-5l z&}6h84K+#SXcCW(w;RpR7gtZUXSYs#cV97--F4wZyA9)a9YxqpY@mV84NI4Wb?;ml zLmn1{3CJHE!eBg_eH?57bROHxWQipZv?C)@r2KN^ZXGlwaO<57S6hQS0UPJ*uIUsc zNdhxag3*C~H5zOvC*a4gFg72o9HCk1ep4tl=T~kdV;Mg_`NI%w?S6TJe3cJ}28J|N ztkfi3`A~$En$Ztq9`g$y&2*xlbBpYR3osy#xIw+;3Jd2CV;9R0VWWggY9qWR4lIjc z8c%!*ME;y069mtjXlC9RE5@O6i>~~>@ZM(oeKF~47=m$r3YL5*{(^+wWg3eUVav2*mw%^vNNx0?%^{ z0#sK!Nz_@(?2313#VPeXxB-x{jxSOW?XWc5)4z(l^m{C3cP%lIF?bO}<$SB7xVcKnL@%De}r-RUpC#8MV(*%HNG;7xm*?Q?VZbHmT;KyW$ubU;ro-*uWH#P_6ARe zL|EKa;RgnVyW-gqC@{YKU>21ZFljR+FbyZbOr<=Qn$en`*#Mm^x1g)5^I1ee=f4Nq zv)Lm$gba1=bco5r-+aw}oy;5FaL|lM%n6Z&RH6U!kBH2ol>^J(h|F!D>NkYW+{_}w zHN?*|^940mh3}_@Q@77ccTx|S;bPwS%lzx%h1a1;SicXj=^#uNT3RWI&Jgpxmo89~qtTwfYLfT}rJG}5c>d&$HJIaH%Co4#C*NVOfF50k( zD8p&9&|b2t(pObytRoWWD1q75qEpABUPCjJ=-$go>vaVgQlnS4GrV|#e#P^z_BUm6 zZs{=TGc<8}elK=Vbth*10r8N|P3EI#^835Imu)c8NUyhnpxgtIz&=tp_XLhTW_{PE z`yzkNART|u&bQa&GWr55S(Nq&tCr(9dpZ3G4j+g})}OZ;ZH%P?m~5hymK*vq1DlEG z&yHH*|2GT3KO>qU4lH9L)36q%oRj_nItiH6bXmErttJNyrZ4cUFq>Iaq6s2Qh3$KPTaZ#d`FVU%3M=Ze#MR~(0LB{uel zbei+ed@PHOVtx)NpIzY`EZhulNLkT*kPT657l2Y zlnZboFvRs_o|w)%{a)Nu% zc<3J4oyNyAs-BM_Lv~j_zVhtilDOO+ORZE|Vd0PDa)_P{2OW7oXKSkSymfsyfKHyym44#lU zRl7Q|BrlD}zdp@1vCo7_VIg&-lFe2TQyg3J(j)fhb!sxO9jvdJEvH9CsTlA+9FRHY z;LR9Dz8h<@aF_0YpZ0`-!_WD;5FtQ4sjB%Ty%MHzw1Wid1r{qvIK^(;og6p1ZKEa1 zhzzpS-KnHu{icuuYpw#R{1!;%K=!BGCney^GwN}gZMXXkgXO0Lvn)t=?NobPJd~n+ zSzT%%6kZ9}rgYA>zpgp1F72;nsJC89ND`XB*0l0r=|}_Rf5%#eSHY~l`*J4?J{?2j zdWHz@v5b43Q-df+-i%16)Wf31H5`AG+dAX;p&+@udc&Eg!D9UkbP^a14fV(;A?^Pu zJm`C3H%QiRXT;Xt6gnNAvRgo99CNn>M(m2nOu^f&?!=1Dpq`WD_6Lwl!!M6Z6;T;s z9mJ)_E4XN3$Makxo5r=B2q+JZoLWWDoN;mf%ANb$KUdIOVNcRRuaO1$O1BA4$w)$N z%}ncX71rzSD-^%BRqX;DP) z1rw?N!eYJnFM&=jNX^CHDJn7J>2~eQJHGzXE!pdfIeV2Y)-u44()E?N9A3j-TfzR< z*xR|+5!0GA2EH;5-C9FBR(AS89}_!fXBq!M_{Xjx1JRnKvNZdG4a4L;ty}7Y8?LEX zGerBE*jE@Q$%w4fq+Vadx+eLX)is*LTEfLPm-tgHsf%r;ndHEC2CW`^!iWGE#=v+> z%bg%G_nGcy|HlAKc*pwGo63~ou?U0YZ$+<9mYX-KKDz9~?QK(NSvP!w!$_p8lWr+~ zO(0y|!69Y*9rhZz4X&`NVE6^0kE~o4M{?zO?Q_9;`Ao~!1C?%joQx?29bP}_qK&hW zo@2O`%qdm2q+`_49j^`0{y6KxTXxo1BczJqM9)QdTR@W#gUHK4-qrt1U}sE)K;da* z`jUd0|Kem9A9!ye_tT0U()gMu)my=qZ;^K0)A&_@X>AO%)}&Tzn)3%uUZIbaOlsIS zp`b(O_UH{YKQrHQNPp!$79-PP5c%eUG5$t}#?e_l;+hO0@PTe3REA5*IpH?lW%WYq zT!OJ7FF@I47yDS88G=lbj>PB2$^lD}l1w7DTTjTIx8}!tW+FuQ9+q=&Qm9v8$2-Ei zMR2^u)^C$BpHZI&5Z`BAw24nRDc_gKinTbYI%t2XTzFPD7orEKM^zoYu@k*um!T5H zd0DC$kjwxq{!8dSG**rD_P7Nc<$oTQ({lsvCR?T+#RX`sKKzd69?YWs zSp!XIp)S{aw`oXJTWx7ikBzGI41+b-?u);4CX8>i4&C%wmoTun7^i)U5=1?b>Yk>> z74%&USYPtOND1?TJWG&Lw8hfuzI|!Bn;g-RdWNKF*xrn0s?otOV%c{!#Mul;a!p@J z*Uw4$jmR5Zqnlib^>vtFb?4oBMqmfay2K;d1r+5PvHz zImx?B!0_r+y4SiN<_eLl(aKCMnxJ%ZK}@4fW)<8FB)7%N^GbUJ<1O9Plj+@5Z8-a= zeFZoA7alqZH-I0jK!(Dl6Ev|R-pY$c@)GG~dO_ON2HkOwRjWgFxRG;3HLMc zY4m7V0fE>*+^^}5Nk_Ez?9J`2I}|%c*7QM;U*hxK5?ueGE8}HNxQ1{~XMn-woKKK_LXL!l>No$VPqr96^w5&F>`?OFJ%0U8rvtxZ_Xj+8xWK;=hK8X}5#1Xi_x4`# z!r#<{$HUVNe$HWY{iGW%coZ}K12nVd4<=St9FBGM8d>~_IC|T(@P0aybB_e?N8M_w z8{EN`j9opi)z#z^lH{m3C{T}8XqnYj23wnf_*S^N1D1n@Vb7^TPDpz{bEo(rys!B% z56lu%Fs1@Z&7!EFqlniS9on`t8Vi%l|WCXA-5^pZrE|{P6L>% zH^gA0m+2W`rzCeGbO!3D%x@l?4TFxq*ozt#&<2 zGdxMiQ@**k97Av};1uD}ua^FSxx-7JMX7#xn+D+{<{6s{pS?Z4xq;6&E%h=Zdk<}P z&Vv+%3$kI+aXt&lavm?`^$MHJC~s_ho@U?p7RLRB#mjarmUs_%BjN z@j6w5QQoD0APb)0leOCRWG6bgFo<#D=nv!fM4~gt2c89Y@R#GOWgUC}oJK}TndRZ9 zMX_4@CJ<#iX0N{ij=^hGbQRmvaq*bmR1(4@!@0t%a;t11`yU-MU*s2%;$znqSd&h$i|F%B8kaWfYRIJ{<)6oxkG?DotdM zqOrkSoz$FNGg&ZOZiM}Y<0$qQD5vxfkCf8tO6^#8ABUet%WLiG>38PnAyzn(mhtUM z%j3j7me-jazw!+)j0{MFaSQO^l(t4`S{1x$ucUu(vIo&S!FzthI;y3XmWV@ge7!(= zp3+}bF%CB$R2LX}Wi(@&0wawB!CP#?og}EptvF|r)UIscmZQppv?a4xCu`XN?Ibg6 z@Q0C`8aA@r^kPB%fWb0#x-|QRRld^R8I%yg5u=MgVVfFt3=Uyxg8g(24L&J?m(jbs zj-NdBNJii1_ozV1sLm)O2~kYzQk!4nKbxokiSF+gM!atHjUt~@x*j12qMciHek>d| z9w@%kxC{JI5&1Z%DloJ%(Y+s-<0Z5(Ob4(3Oj)NVW$sM;FKS7?8BDiF7j6m61mJYfoGI+2-J!Cs-P{|#M^C_{i4_H$6 zLs0>6<)dzLdwZ0q!8f3)TmMU*i(%2OrX^~Wi~#=^uE^~@cp^v^asD#>^4pt|*IqnX zN?dY%@&PppUF@O(COv$kP5yPGex0>Brwv@U$Zd0%_@@q7nqF@A*;&g^yQVp{rs&(s z1N2Kl@#+;g^Icp%G$P}VTMGf!PLv`4jrYUig`|dHw1-`|imz8#l}_=Z=%IFwZS;?! z^5>7(7-gsB$kM6(>-%zAsRxdo{Fa%P)fyc>DVzT;%hOA32nUVsd+ASarm3KtK-Lv_ zf9|nC1ND3^gqm=9nrs_*WX4MOv80X5X~xG~&R-v_k6qod4&I1;dt2t>zwvXz{lE2B z?ta74U9feyt?u6KRE3q??Gm{?#d;p~Lc$ED?SU3Wc;oUk5FGHdE;&nX*=Nd~v%Hya z?U@M`WuB#%|8DTAg2|vSF!>hP;geQEsN-CR&`%b^zaqF>#NlbwF5!@ z?WCwO3jY(Xdztah^K6g2pn9J&7J|h#0udcb6v343YE54F#Lx`z^A_f?~Hm#kQV>i38(<%w>If`v=Q(i6|%T2DdaeY%$&lYiwHodo=OB03DXP!}xBhD1*wj zrx3XN`OAZT&KQ-JZY)tFsvXC`TIYw^t?7^rdXf{imRDY(MHc+Hn61o({eyx;!J$O# zE0`r~{Hz9|<&oN1l}CKOAx-Wup8+X9Ws&N;-ZF4hjFLFiP4Q;&v37P63sP3MlVEo* zW=d2fkT@Fy+x^)Y2gDx>Dn2FAaQ(0xft-1eauIk(28?x!c>)+u zm$-^HY1WH5??S)U2dZVn83roIzODqP;1nrXB%%ECZHc(*vx;1ONA#OAO~$5CJL>dz z@1_c`2M$zQ$}&3((GW{M@Ej+ z8iGzmC)9E-OqaIKf7-ZwZ7-p# zwH=SWaoly?pjx9g(6K3kH#`{Ql@)FiZ58cTUqsRAiH{<64=0$|CZIzk<`TEJ9rJet zs(v5%wXq}wNQxLzLhNj>5hH{jvlS{Nkzme`G8e}6q3Xg?+x^wmCF>|O;aW~?U*n7c zVbRq^OV97CKj3^fKe}3IvaycRndLxNFQpUxnxy4VKaZ7x3|gplUHYpU`5^5P&FG)J zQHJ7xxt*eF+pz2|lD78O8Z811x}PREV#DVlt@m zW-L&|L82wRW2qwY$GM&5Or!_trKJ)A$VaGHhU)_IN(w{SEl@Ck?2OX11-Oak;E7tz z3VEhNT09CZW@PZ+9Yb`@K7;way}j^}5=yFJDFZ)DeP4c_K*;8b?Suu;39V>91+YA- zJr`bkE*q{5M6u|wX4h>CkRipN5qZ;dbAja2*zl0=A0Jn|sglUxZSC#c&Zp=pjQWFC zjd@hC0s;a-!NDj51o9dh%eua{l9Esl4-ZZ*F1t=V%IFZjzP^3^{o&!^Buq@#$u_V7 zLbkSy3@LER=rFLbuNp&37HqpmM^EuX>d4>{5)#;igg}4{pmkT+eD-8ng1*^gwXgMvTyY|DWXqM8((F*SvMXMMV@qfQnOKQBO}#OhO_dGc&5V_{clW^LKLw zAQwXy?_FENLqdwp038nr38~SbgANcg0gkt)tu9+3|0Fy68;~AfDdZQqCnv)BGylDd00_9j9rFNUCN8e91uOCL1yp2Y zJISXU4o=Rw`T3x+gFXW$WGt+q`BK%ZVW@_N20H*4YiVo8o8kx~|5pnEv`8#3FY|VN zE&Og~Wn%g!BqY>>ARP4{oTFebZBLOPyFF8ny$kGh8eLjf!v2;NO z0rJ{@{{Afc##K{{aKjPqs7zLK;!A#0xTG?T^KY$+bL&e7r|^m+A4gaHUJuttzbmFh zEQePsu-v8THlOi_0fF7d{W1%u*v)8l^7e_R?-FtG+z6xZi>%A#y1T4WLwC2}*4yTj zl%ircNx@@2=<51!PW_Klbz7KR?;Jb<6;aT4~P-i;k2FTKY7K_Bm-zrEY;1r;JNi#$XURhf2gBPHo z2E*7mz2ctOlQ+S0b$_jEo}b&qUh8l{*m~fF@l_mJ7Nn2T9LU>6em%sHn&n}=GVTvR4Fh;qJg`3$jDjZ2JTstYy;J zf#3A|N92#qa)Bz)Polz&*nA6PkpL_Gw6vwbSBlepX}3H1l8X1|H>YkBmfm#sQ(BUp z!zNZ1(6#3NoKGiblF`^PNIw1rfrCR4hudi5$nZ8Nn9)&#HI5dyo6D{QW{t!4#+eC>(1B8uf&u%=(F&ATnGp4ql8=dNX*X?XSK{l>AqvxQd5 zo7y8ML91F+RDKCSn*06r_vBs9X91>1=TF~vGQf&Q$;wF#5@Qg1pcCGW_0W3O<8FSZ}lPL&&_?D)OqUyvp17 zb!Cc}Z145S7rkY&c%?Yj`0ABv{3Diy!S!|J*uw4Aa(MFRU*zU=EDVeq_j*_s54HEf zji@=`*zTEhi7V&y3OjdhcD(G}R3mA@-`HPl-Fqw$*{qiYc>g|#b-4<8+H7|Xn~8p9 zs}&?9yl$*6-Sf#`dz6%z$9~&z{XsRgC3AUVIFiU$X8+N@zb81-xzUe|6?L&!U;iU_ z>tcSjY*2ZvSrGeXMDRV3CuZq1=Tkb17j5tA-D}~~Y`n$YlYpQMX{+O9@tdfyk|U9# zAcEuJy4Tj8L+|Iu_2Zh|`EtLlV5~^j=iF~smK@Gf;G98$4aUOro*mfy12!4+{Uws1 z(-hHug~?sUlJ1_KM4_*w;rj8TduNH^?59k*#74pny8F*>82I#U|CILW^0GChXPtg_67Adp`95?gDq!_a(6a|^_9)x zpUm3TE`_WV3>CWNJwSgav8H!)VAWtAilqW^>iY*NRM%is&Uhd+Ls*6jSt4LNV20Dj zaIlQDP0 zqVSfU+I&37(qP#IjPrGsvG7j=(3EQPk<}OSSJTOxSw)lAVnFn!s8b+&lWX1+Gjr_!HOn5vIAX|fAqGfc){rG+XX}He!j1ij zf;JCvjGlyOlUKX#j-NGMVhXmS+@lum@-;9h|6(u#Hzz{sCM3BXBmxCYQ7jc1j1^Mj zk(&wr`p}xkqSrSL}a2%1j@4fncE)gHsjx^`% zh2;q=Lv0=O5o6+XGp3o6Gv;XdISxGoih8-3??k}xx1=T$3@a=1*a-|(E0EKrIc?Z| zOln+L`u8FHp&QJzjkQv{Ujc?4Eg@ANk$t3kLT1{; zXrXGFVGu35O;)ZGlal^mZCyV4pGAA0o<7r=oKF;A(qhV*_i!;Yg{R`qmaND8pMCYS zQtnn9tn#>GM>vz0%LD!!&hR1R+ZnC!t=(z8qc&`dIe*0;59@ve3Y(LPR{6iH7 zwFT~?VR{6Po>R=Ph?q)U^?qfJ-t#y|BvZqbjtg3g6rRk2`-|e)rmlj?bK>(CD+-zu z?ubt(mP8E(9PZnXdVbt)9HsI6y?kl+R8kmyNToJR2z6?O#T&{|4ouDY4S?&K-n<#JYRb=fAB`{4#pw=D06D$mz zZ~U12tk24H#6D?mW5SE(B3I-SHIg3J6!n-CNghg<{CF`%w?>n6B`oMDh$PH8k@Mw? zeSsqjL*HKYEYsbHj+*Zp=t`VGU&bOCtUe5%H>fjmR>u$N)^Kqawfy2p(gbb zE<3M-dECs!lo7>+k2~(qET`EJu`q9!a1WWeNdSK zY_93pZPo2>r;#tYPyX4AQjm-b1%dJy-g`Gugea!eR~Mw`tun-LK9OM~ENA_0zy%{@ zt-H>tPk8Te-ygJq?t07%Z^vpaPgX7Tq~djopWRErNgy|=ButqL=Vl_bc_uxipD-1d zAcreDWrA7v7pC&V5O4igs{6*(wg=kja}y-kn6U5OD;HP}=f5|&p*wbvt`hO6W>+)N zd!xV!3akxCh$Df+Nv7ln6~vUrJdPa@gH@u`F@`~psH+O|*OSU%#X)R`404C12Zlju z4NutLR)wq%Z{t;Bl5%oeZs9LnI0+oSVM>03p&l`*$Wd_0g*s~1E$G%Iwz7e>EH^{_ zJ7=Im4lcAhJoS;W(pnnHlIjes;MMcW-7i^ZMtz5H%?Jj^^h2eaR~cs;m$kN6@~mYS|?S1BVyHAUA#3_|%TQ1*t@LzrV^ zg?pbNl4OMo#LVU@aM5UzKyb2ssKbJ#sNO&t6fY%cyLxHeq$)Odd2&WWM{48}H=`05>7d?BnfPYZ)WiBw<>e>A#HAAGQZ+F*YYg@T#uwjWHs5SdPp#48CAFb` z|F_00SdL<}#1*)VIWZ+K*zndDll@6k!hppzN1i#(eP-VswW9E-H?#tQ{VKBg6m%trlHi0rUHJCzCRr#c z8{w}1=;Y=cQ*-{v`=m40dj-$1&m!pjvp@Mp^zH<=*7RT~Jz;)At50m*MKl7NdgVfU zaU9g85@WkEI<>_=1hT}ZlH(DNCDpEw2M z5hl7`WWt;MzuK|o+fzr=-3=?GAB7w<^32qA=8v^J^5XhEN2#l-if4WUg2-TH%H74_ zJU2OGpG_;4Tg*8Aey|*vPAA07ye}mX4Bn@j?ga&T&K8}YQJZsi9*iVLr|7f&F=(et z1I%l3kbLSjr1buc(gw3GhTUG7-d99_+Xns7bNVu)xyNJfNI_fb2F}2>(b#!UscD-G zkRr(*TAfsO1Ft(zy*XpUdt&n2lLtp-WZ=rVS2%ja+v7ilp<`l5Zo=tM%?FJ(^<(d@ z-P!6@uD9YQ#!Cssh8eitA)OC=cP3(x%RsY9M^txl%CIfD`;+fbhZt9`r!A*LDe?g~ z!}uR}lc`u@_J2(2#Y#^&1felX&pVov_fW`5i6a5*)c@R}!D9z>BfvrwrtM2o>pCf^ z`Bo{UTYZqh7d8jUAQ`ZMsPKmA9T;7t5(zhb?jF8^D!lN`76 zvi7omE3F^j69WIJ0ce=0O~fhV9Zt!L3n)dZAcK!PiTIx8w31KG(wUTq+pqmCAT=22;N+`qqg4D8gFr=+YUQV5jb5UNrNZ!uc+`2h&fP2o_G6)9J zQ82>a237*sb;iRJD$y5QRA-OPhOPRyPa?%RqkE>MFe!y}sMvHK3s-REPXovo8FTv7 z6hAB;UKI*1^XJjAYRfyq>jD`}L_x!?)$86{*&O!3V7@g}DHJ^R&tqb#{B#WOq+~S4 z>Y=xa*I^j{TR$DlXkzGs$Q{`yg*2xZ?%VPMo*WEweKIoh*^X!^f{~fcnPQHklAPMm zXj94m(wHk_bj7hGBjE8QwTRKkTMu5A3; zXI|{wmyx=+Es`rUV-3iE`wqaT(Cb&YlUkwWjCgTvDAoP?Y+O3AZ@@ebVduResEt zxCFzz>ir}{40}4vXzIjl@ga)M;@*e_p%&r4O*LU}ac1$iGp2>q|f+dm>53x?c zox8g*-GqTtQ|9rzHqgk8Brm1rt zVVmjQDqbF8G9;n7`}iD%&rF-SKS{YdP; zQ>VFCq+KaSY%P4V*CaG3s0ynuY^SCZ6sugwX{uqD)9y$%uM^e4uuIMcWA|#w4@A5I zN6j84qvy|*>angMa7CIu5S_=sQgLXBu0u9*l|8B89dBpXijlD#*J4VPU)d2$ZB#$_al#eWY0s#AY8sIR7ao=~b~MW$PDr-i z`lbwtq@=DQr2GT#yCj1#7Q}j9*nW*6Y&PP~Nr6cfv8N%MY%z`+^s+b492!~6jDtUP z{tN6`D+?l)dX4dvFasj3)2cI<1l_ZIPPG0cMS_`Fg41uPPXdGn@rphHU;aBZ=kcEv z&<`2h&bgULYyDhU_grwQ3GQZ9C|emgG4%-QV?Kx&$to&q(hH@(*Le^W*tQ|Bmc`vD zOcLvjaNMOm@`fOVYyIqEHq&W7U)Rvic~3~q9`I3FMNb5sBj(y49ZSn&QR{6r zGI;fY&pp}fGtm3YTq|?>Dsu19fHPyt#3Q;>^AchSkJJ?bS> z=)yvn=-|r1^_JksVmK*lA^nC!)Z73y>*x#=#P}~);#@sz!PWsJuHN5|1c^e?mVa^h zyzdd!TP>8~y>drO^t*Q55tNmc4faAKh6bkS`=k|Tdz>0SMgKoMA}w#Fl9N=?&(QSY z3f6?Ol%-zL=5L}&;wg&GJi-a}0UOX$D!Os*euiI+_%OZ76*jRep-jv)E+&@Ac~{@B z`SOeIZ@epHaHpGDSn=Vn!IB@W@d1!}FAFL^eK{^;{?-M23+zO6`K*oaFC=i%!|%OF zxv9`Oob@yi6DPdn(@Xx;ed2QV^L0t_VoS0K}%MGxfOOo4PB078I+ z>Zw}t+tZWxs^bpP+1VLrb}?YXm6ns+zsvdJ15$MA-Uc)9R+dGh7AhK= z`}@rhPz^+pKz;*ACudeyBYu{f0(&DSF0T8ukw9K+v&KO~OM7yDE`}}+RF!LV`|#JB zPYqtU-2M0X#l;X}Xugm8IY76lvowi)?DllI0R;QZ@LlL4NP(Ckz~fk4FLf{(blfnm z<^ESc8AHHp$CCvh!^H|sQ3r=xXXN(&P$X3?tq8g?fMx=P=Tasn`v|e6xw(FIbu6oE zYs%=sKyNvqYV0lhQ9if^m>2Vbd|@J`;_S*wIJxxm+Z(I#Abee2T`CY5D+tV(7bUi5 zYo{n%5(-x4$^dtv<*H!fBV}bfHgQ{)_sxlpN1^=i=BVgLq{DjUbi-%_aneL7RM9o8^uR~|GUtDm4`t$D(y!%m`!Y8fqcG98IB~Be=V-TSue%33kU@} zcD~;}eY|gv>HmbAwz}G}*OXR?6#6{mbVW)J zlq8zQLF zjt2i&Pb4`3)$QYfmoedm33T;vGFV+d7+|JVIUgU_wqKCq;zU=O@8pI=($X{*j*sV_ zZ&g(c&#}Oiz1for#x=lf9H)Ahx_v&j7cexo)jVWuy&oU#`z#Mr z+B73Y#JXd@-4jurFSocewiU9LjS3 zQZl~bZC$_Vyb`uN3G8%PKj!LwH*M4>Vt1~0Wd!`L%}-D{`#SE(AL}2p#rBt%#R4O# zHZKm(03<~;Zp~U<-QN1r4NhK1N|U>G^(}toi9VbZTv{pyT_1Y22Ph_zNY3Ta=7Vzj z8xdvhgn`muRXom3LKcV0(b4(4jjgZix9GL##F2v6xM;kq%SR~9kf$y6r;jJF*Z153 zWTK-_0BbKai%D*|x4ZCmycEHbbgvC*|Aw%*dkEJ5kO?kcS2&vLub=w7*v}?R<{Qb! zT@r*B_?%l_;~%#7@3s5BIeT(hNmN*9rSobzNa+e{k->xE^DK&i?o!-l2Ldd>7*ej4 zeftI`)u*l3xL-qyIgPX90^bIt&`RMR_0P z6*#5uHW@hB36*r>>e}StOZ}$Yu00ZHKwsQhlL};PQB6gq>E6bzx?WqI%&^(9TkQ?K zfVe{zyi3FE=A!gcoY+zgp5}buWYkK3;&urYXrE~6ZvKEMzfzTlnrvM@yz}(JrpS?B z;G{6t?-aBdR^$OrNMAw5B8$~)70Bc7*pVa&Lbm*W37a9QHVpjik(>=KEDmO&oid7c zF|b7{Vj-(X&!dUhg+`};zmFmb^_1IWZ68Q_$3hA_yF6Mi;E<1x%lwO0#WjARo68$Y@Q z%Or87S@UNcswEw~y$^?7J=)sal7WA@wzrq4*ztO`DC7%Xkte%^M`D4nd{`w}Q!08n zCT^C&`EyV>?v#TLi6E`G9qmsEpKHA9zdE)-mk6 z5E=-@k!xbXUV@G((FARt{8Ef|!VP-IRhbu7jf zP-b5z9J+BEyx$24ewLeUT*wwKYx4JCd1ywuiMv=!t@zF4I z+v^+7W%x7&N5LY*ZA-Z-o%|%LK&?=j5~*ye7qeJLe&VMwfs>2ah`iY_1A6!a#R=b{ zbUPU`&A{k0xFecuOD&?v2mi5GMBlvkxZ*@@lIyUWut+WTg}0>T8R7P@0k7`=aP^e| zZMDnRxEC+(PH}ga0>ug~ZpAIQyB2qMhvIHUixzha?i$=7@Z~-Co_o*zo?rQsKz8d!HE)^D!6at3Nv_nmq^J*bODjV& z=*Ru+-0@QQn(3tS99(4yAX1k+x!I2&w&H1pxF*+*NEmBBuJ{K@+h^Bod2#xG*DK`~ zo18ylm>cuNGo`Qa4G-KdLZc6I8E)|`_?D(xImaB6XKHMnI`S=IFdFrbM)opPb%fnB z4y_^6|pEjpQ58<(Q}cx#|_O5ZDudf8BVrmm4_nbt@!(vU;Y*PRIT-*F@*-W2kN z<5#Bwh<2Hw5uWCyPPmewfv}h3lh_$av#h5yU9EyPhs2cd*^C}lzKe9R`9UX&4)QiSh%`$XY6Ir~D zjBv4#5{^iVt0Bhgfi$oz#;{w(*ZewZ43jxjJfedhbmP{m>?0ej$}aHX@VvxZRKK{H z=A0E{EdCljt2Fe)v}s+4ZAtp2E?jwMq-!6{+s5u^hoLkT1j~DQC1!Jx6j$nVHNwr6 zV@AaC#(rqQbT*ZFiu5R#KNzMXAkH)9IBbZ&Q{@c8v8E-7nQ`7j8VM9d5bPgdgoV?) zuH<6Q&NlV@zT-+tDY`6W@ooCx+hj1S0moopxpwNI{vz3CvmbE+s5#_9Nh?Y}&krXn5&ge)1pNEfXwuPB-a{0Vda=Aj#M+7qfCPBiycZ9D1Uh?59LC%{QM2$lZZcCYzx@ z$ENvizp%KGF?H^GcPeFZOO+|DfS zP122`B5Q)%N5YS##Z)xE1&_s2^F{ECU0qU)b>=v;X$0aa=pbHs`I?St!|A!1W~Rm| zPlMkTP$Fw+2msXckbN}nY@dI6AKRx5v^?UqTTV2KC{33oxm zv^q8M_?7o(gFV71`1qkY=nQReo|*b4Q@b_ELz8d#rD!0SwyAaedYMFB-SfJ@4H$<$ zz3`ECsMPaIZDNMLxiPnj#;~PWYH=C8vMIh_>-9m#vFOt?n=&puahd6#rF9)+(WW=BDAE6(kvu(N(W$X=73NtMrkRXj zlFpDKye&cj_^vi|lh#V}dTCY2_8wT#F`4$;4$sZ-G$Y%#38-czK3iZ&4Tl|FSe0<8 zIx2nB({v16TZ6-)HW@EPfkac>6xcs_LEA_oQvEJy=$y+qv|o{*uOs7gOkEu#)W1k* znBnV-07yE({4n zl)D||TRFVm=4>0oQH+b`Y^>`u9i`Tv#*C(f{UPY>C67*CU{4{TQrDMi8QLK%>*knP z?-IU0jY&FU7wfK27>Mn`m`Zn$o;jX?(K6#!oL6(6s&vy)A8|bLmCjr(TCpa6vb~K8 zYPNuObAMV+wPi(b@t1(7l_71c&vyGf6C-#gHRN6iMpm)lNt>-{4lollsD@O}Z zL6)BIESfVJ$@V2+V2CT_aMp2XsBA(n^JZF^081G&qM6I(jKMcpAFb){hZdQR$~IIS z#hlK#krM8ta_sg*aoHp|9fTu=p<{qP72as$5iJ8hEE>%!fkFWFwMRRx`Dgre-OFi! zykPA83>Jo6w#i6f>*$V0YA5ivMI?+^E@|QV@(doz2S*l7db;Vev#`MXgPXf4+ zm@%yh{GxIe4LMtSC_EiOM@KX+#c`%z0>U*5FN05?7L>^Mf4=-~qkS?abKa18dY{xb zX0IEcqSqi)@#GIA_;W8>2$GK_AvVotQuwTDt7WlwfS*pHPx&1U=lG(;hFxAaAKTR4 z*4oi7x_m@Hwsek}_0YlbGF}>pE!`29ctp0fES_9*d2qUP)Cbdk{B=krhO;@*LeOj| z7Uz_j*Usf>%R=B>V%v#WK{jb@@{bBL>g7K3F{>sL&J3GdTNU8 z$kH!RpMN6ocL*tZd&WAbzY%$ctn3S`e}TWQk%XrTHwuaEme}d)NBiJ1O^y>X9T29e zV}3PH5Y;H)#Ns>fGj4X}oM2PVmI(0V*_lE(bfBR45j$j6NI-B}(uu3Lr46MrX}r`a z8ds14I5=aPe(up5t*IY$hFc!-lAf;2!KrIRt2=-?sJg9;J%WxPL@HRAnc@@Pw5kC4 zCAYf?SZqYSp;4lk6=S(X+s6l@!xE9P`=xHhenq|Ahubej#%Gy$8Yf4ra2L&u?V%33 zzSGaB6j#UnDF|$S>M9tFyfCy$`C;XfI>;zy=iw4?f4?Poi$c*8uAsstplL*fKWufn zE$7c9!a_Hcn3G{*?341HP1d$9uI3HSv21pd=`!`NN*sqk*WbVMDCG;xwE5Bjsy2xZ zFBJM+z9ggy({l|gZ1)bDbn-EA92^||#>yO;)ZLE7LXvvtxPQJ$;~!|{W|}+sB!n)I z2w>6ZqT$329SbeWsMw=gxBngW_-W)V1o?H3q7jhdsfC1w*8Y-=`6(6@+0XsPg~w&A zV&(L|5N6UwEbECINT6{HLy4~q+7WIqPf}E#;NVQNuxk!?(zyzf7Zm)>e`p! zQy-c^Nm0e7p13_DL;&>HA923vMuLO$<=^o%VM4rxjszCvE2)udT%9p;a%g!3hW7Tj zxyrGfnPh}%K4DU>VV5~y5=3nH#okIo7B7Vefmr(NhmxGsnPa0H`Ew{YXFt0E9ah? zXHgiwQ6o29opEai{_cRuzr?+zYNNOE0T}> zK+C^TiwqA}W=>J7b97;ER>$?*F{kRdzgS)f zNw+`892=D$3|tUUzKqAPIax0j;ezrXEXjRy55gZve&Kxo3YXHPki(ozP zWFf?AhMeJ6Mny$4!-KsUK_s9E>>52(YxoSp$V%tvD!BBbENO2c`a}sTiFy!8h;mY{ zwvjb}6;$S(pQF((ns%aw?tVps3i$whA%7vbjYlRf)iqp=W zQ7!T6KbUxM59CzhxI_j2tSLks?+0b52Y;2^W*`lQR7j*-a{k%p`SJzGtfAw~Q4dOW z$+O9VVG$S)Nzs6qbw>M?&?GMA3EWFy(m>q9+y?e?Tg@fsuN1+K2zV!y;)O;Iuo6!XD5@SW+fD^on30mjAN-qqsLhC$>^x0Ne40 zZY$FSn@XX40&%HIJ9)@;;wt4@b(AY2P)1;+kh_8G8PFI7U1&Ggl&(Cjf5KX!vO}p z{+e=qud^Ub)Z?DAa)maFmCes5;mv6b=7E^wRl-tKe=w5z zVQeTFa5~(~Y4x|d@48`l$2hR0MEK@LV73w-?{LnP%d>$nPEA7fQ^2X9IFtltH7WP3 zI54^QhP$HJ;Y$s)6LKJ$LNPTaXJ?$|9wOeDOES2!{4VaE5&*=2Nrf$+ecuWOehRev z=+IKlj(2mPC;QyXOFk{zi`XP!Q-&LWiyn&+lF)z_jl-ZXT@FK=B6W-{ag2o?L`{k3 z9NzrX5`a3lNJg6wKC?ht#zIE50>ZQj^&o}|HWSY}9M;hfQI%^K$p?IHW*qPWKRG&s z{Qc>=!n(xRuAv$}z8QYKO8D4YXb#hKETuM#jX9w)40&JjX}pYBjV?s-|583#<))$8 zAV2JYBc$jDPsEUc28UKWkry{s$En?|ao5t#I``<;z&B}Y^Rz-l z_D2_+&%V_1x=bI@h{FFKgv1&?W4|sK0$%Mr2t=Pos)rwU@V6)I?OwB0d_TQTY}$hT z%n@>5)^Zm5W$-gX;y@tp+PQr*XVTWShDI`-tl#8~iV=`AvtE4qA@*!sWZmR5u@#oXN-AQV_&d*eaw9H9IZM>_ zW}>693||jQ#jgPxhuf)=I)#(B_M7#2dy&(4*Y=0YrZSK{ap@ewz->SI#=A)gA>hLA zY3@OD6;w7EGKCkH^&7}|`#ZJ!&DG;nmojS|%z=QgMg9h@oV~pMrqkc^it6*&|AJ^~ zlgbHN0^Zfdfal;XPfs|-W4p%NxwsJCxJ3QxK(bw4C&wI6W3pR%%`Ok?m&5*@-r=&1 zPnc!i;QM^UKdwuJ>_9un90XBTW72aCyd_gDEct!iQ0z_aLvIY9sDrTzBCWEM7Wmn` z_3B{>SfdRNGR59_Qs#d->q;|mU3hGRm_5EPUxAe%Fn>?fIOY!F0i2x#eNL$wszYk)k} z!M}nrEY$-BOu#dzJXY_aY>Zc%x|P_;94{BoW`*NOYcGs`kL!6?=kKIj8v~Frk_zW1 zaMX*X`>VXK2os$yl-bAqX%t}qw)x0JL?f1^{?|8=PH-`}!U}G-bj-8M`c;GRW|pvT zzM#sFx2Z?Qw){z{=R27KYO;f($h=LZNSDY?0oWz8!8#%3nD3kD|daNal)9BS`<|N&X8UhN#Qb+DXNBsk zZ!IGE@qYuBXFoI>S`AHI#_bXx>CnknUh`;1<5)N6TqfDr)zEJmcpaE|mu`q#+ynFs`~3}tBdE~o{1K0yX*55Y?@pY zohGWy%PEVrJ3fGUB~({IEBu<@ve;q(-@hmE)iQiz2iS=MZy^|n?F(q+D5+IT72 z9Y+@q#eX{p_8i&mh*)TwtSFm)6HFF7o%YrCUwFVFCK}mq$F(v5;>A1%qktHbQ@bw= z$r(-=tzS#eE&z(Og?*xqZh8*2Qw%v#{k*FnoZ1Z1( z<4mQKqywn}e`?t%PinZvA7|vW*P*|SesgOscbj;4SoM`^ohQ?=5(fAne_p)#8e_;( zS?&7DIZxzI3>-*Uy`7rqPReK$G4rXj7PU4RbHQ+UU5;3GL#gVLy$759NaPqHZ6nyv zZCTuG$+%d`@%9f?wGmYxdPvR^3eaFsDZ-TdyhwhN3-ftCBFDCsz_#~&1%LBfVbev- zQbYY{-lTMwt9Q)FH$Rv+>$m1|+s4UdfKO3@^>T2WE?;TgNb8axekI<;tluo-cL2EJ z^=_W`w86<2d3VV+=gY|oc~5oIFOJ+#i@HKpWs%u59pT<-r}lGNH8^9*3$eRadLQJ< zPK3+c8o7a24TY0D+^S!P&Q)CvfQ$4uz5>@(^O_G}klWcB?i1$e3)11$kBOh89(Tq%&ed@4 z(ovk~Ss=8fJ+0dBm|Q%OZFVs!zY=QRL~9!Uk3OyDuuHYamUS!u0- zP?issagNQPObaQ+M6U;gd9QK3(@YK=kYN(?-~u6kip?K@PxLcu#>Rmk!s?LcI7l1^ zwzeJp4)tr-%eV1z$sPW}it2gSgYZ%Q?)z8k%2VBNeGJ+C!}h9_U~Br*+I|XD%f<$4 zQBqm)ERCP7y5<2X&P1rY=DSu(1zQbG$v^DOQwBr1qoOLSYRpIQBjK{4s;faX*rbs8 z(P#fpuQaE zw)Xjo--L|>z{W~_?~hw0M9MDwrq)I)!wbPKo{8&glu*gQ7LSm?Kgx;vj)I9lj9G#f zH6+-Xk>ExHgk?r1zA_vzmcztSTLPN@0VdjE$H&KEu}PtgEA+l?hrvf&;X{F`?Fbbg zs{a0d{@DJV9jbqpaXu~&iw;4ibbs<6Ko)C4W<5m;RR3yJr2OYuATu?#G~-W4&X0g< zqh-M5{t^|hGs`^QF+O3IVfdGwFN-dTHBo0gaV&+w^kXhW1u375LWM*jy&P90U`ab8 zC#+edhtaxMAdKVh9CYyH^hdNy%fL^=9pp(|9~a+((hJnNoDm+jhRH@L=Eabyk(m1g z1^A8Kr{?+K1$%D2`lY^T_GWF<=_Ox{ltw4l^{7_9OoCM}GID z(~ax6;)9!YT!aS1Ho{MvligtL=e+>YEGt7=N0t0pAhpbBMa$dk)V9FX$}@Oa%nqBE zui~?4gI8ZaU(ZUw67Oka9{eUrm6ab^O{ddtBjMdGaH$W~pziKv%D-E%tvc1C}%!3;auZwDvl!dVL%pyHh=KiaVb*E2VFd7YM3{L7nV&ab=#egkaBf6>`Rewz2b zA{^XA?zD`yJrku??R*%=+R=@Xhl?>_Ojs>AjZE$wp6WS|iGuLl*HX7Wb zZ96W(sNOh<@v?wV{GEE=22bqF<>>Y11BE3$52iBegZz1!49vFZ{spcdM0PX z63xWTu`k(&={zsf(;H)c!=yuDtBjq$SA4?fy8K?&4$)i$GS*fF&byWZN{B+67GRnN zjW0WTR@*i`_fzWXE_)+HNR#srSq85IgqkDn2U}DPSb32a}n(QR4 zMYQaAFxbVBrSi_=dcSz*aRt|f5n3J^#3Ekiy<07Q6}ltNEO;mR=>hiBtBg7P-WoN5 z`A-_j{Qsqquo#v%o8}cc*^4w`RXM~?i1PB4odP8X{=I8yn-lLo4+f(8Z7_G~X*WSp zFONAla6j6E2OjTKI-8@t#|wd%UySZ<{uF*Pko}db=MHv_i;_q_&0zTGIu22eQOx!!35>%j`x@6Ubm_FEuUWl%PH) z{)7JT!S}wf+gzUvPF%Y~=V3u4@ui@TwwYgS4u@F#8QtAki0@Zpu5Mo3sAKeqgX%Zv zytikq-)SW05g5*Da_=Qa^urJ@fEd8ii;GclK7MiE#X(-)x=CSu{5Dm1xo8AmwkL1< z9j=QPygYEMtk?mgFsQj_WDrA{9ZmYaF@`AU6Q2`_zgji2jMwT+bW7`}!+j z0}LV%b6`E(u@H+`(i0gl(&ApU|5PJ$F(mpO3g{9;n^KCh_A9}w3i-ZT&8_Q8&sU}% z+rpMOO6w;bV;lw-e8_Ig{#m|}4M)`XOPM$oWwAthgIl?`oz^%`TnvDJ$R|`z`yE|H z|0iFc=L5oSiW;it5SzAxLiAkc78+Glvf_t77owp2%SgdZSHtzLDQ$zWk>76{yaBwM zo^!6?)~^1qX!#(+r@L0M(VjQXKNBNqR|92wfAaK+cI7$)Q9s(E{#nM)GtNqvq#iCu z#IPD?u?rAvN*j#C_`Hgjy9yOx(rRN0f{m_xN!aIn99|#FSU$p7tihk-=7IA2@G>>} zkk=Zaa#mwZbPMrJ64!iOa>dL301b5O*tlH%v1C*J({_Rkq^6YVNo!==RTC;K;^t$2 z+CUmzMmjv_W`oL9Yn;V<4OsW9Zht5Q>|Qoc?$gs_yBg;fPTtENl&l+;>DavJ-+ld% zDcHOF!P&xB2#}w5#_8v%Gj03gfB-_Ihjl%W!&zPH8DoS6c2D?spL(y|R%!ri+afJq zXByk;R(}K___TkBf9c|PJGI&GdO2Gie7h@MHWd*k{^+Y_+k>~pTB^E4Ys2lPNsn-z zCKHKZyU&_cNmZrp8hhzjb6Vf=yT!rYQ7$hYhZ55F>mzslaA%2*VT((bSwrF2p3{`PJ=@lINN zgyO-8o|D{?V@Rb)Qy-tS#yh~}nxj29oEx92ZD7x%%VSJ1aAd^89W0bSr5JS%zzoWV zZi;}yWOv|TQL36zZ>tH@7!{7#a{k-Y7{^i5?EQU*dyV@OEb#S^ut}>YgYMg)H=~*K z*Qej3@3pOrE`*aBeuTqUOmgXQ*Y8yEvsV`dST&L&~l#6_6CEEA~&a*-%k4#>yqH#doUN!-;%Pw7_Hl&E~zb zcv0JleQ?m?XNZdSu!G-U>%YD%P}@UB_B>s^*>e?hxlqgN7Hv}#sM&RLyKu4jRt^2k zUD%IgDfI5+G3AY>WiECbOx|lk-qFel+I&U0@Ich_*cPo8!F_!kzC8MTQH>$|JVO_; z@3-(|-gPMAup86dN{%bO`uDG?EdrTK zY+m80TQln>+JXRT&zyy=zcH`NSqn=1a~QO*#woG?CE{gLUbf%Mzrmm3U*NxjPrTr^ zZ$l?$+vB>ZeHn;xW)Jh;fC4|q`mol>dBs`m7_U+`W9vWNU23zF5Y^>A)D1P9iWeCzmn+6MW{J?uHBHC*w(WEY}E2aazu z#BM3MVyDFX{U>jd@(4V>QrALjFwH&m*h3x0h$cCXu|SA7jH=~1iHIZ;jh=38z$>_` z#YVPgYw8Ux_n{Na)_=s%c_gDM*v}BD6VT%SOb^?923mg+*myN>WNqI@I67NBuu`|Tws?p5TJLVkvBaVQ47Ms4CzCk<#s z!hwC3-FbYGqnv)TA2s5o93R7K*Gm{2{76TSucbdhP2=J+U}+N*e-=5Lfi|~JOpAw# z8Jqm@-2?ZklPZ@r2s1joUXku)Z+voaGflwf{MXXc$@2y_$N^ z7@l$B7u45b|9NGj3Lc*e@5@29K2mprctZ-P;NVib+HNn4i2f<= zd=NZaz*2Y1{e39><9wOo>|PSRQs4T$o5yAF_UxDKjHwWZwt8nCAma1O_U7A%ovV}8 zC>dC+wtc*|Q`YqC5T6ZU@A(yEdgb0-GDH=BFOYP-PS$D70$=VOvwAG38}<>nWMo?G zwGL43ZQq1!?EQU6_SlEN^;s;aos)ne;Z#$H3q(iOwFw8tlh_#1g<2n_%YGJvdF%y;)h9gcSkmvvza z8)8Wuy@#?U#uMgzMAc<#$lYK7j$y}*GEQ0owwKoypI`qYb)1hW2%MI-J<3Fkc+8!J z;rM&Wer~RGZNc~lWY7d6a;NhnjLE!PmBA<6`r5VR`9S2py!Mv&7^1D7CunvyEJbd; zNIm64*9plOV(f+MAiWPpWhVki@1yBzqOQe;x5vm~dKtZJ6ksvM<$IvJsq-L@3a=jf z=BG|RAL^vQ zVPWS}^ZOV8f8Z~5TdZudp({poHA3gRh#UPj8@bIm?*`fx(M>|x+MbW>G@o&^E9 zO9;rJw?n$RClsSFK(}A2>^Zgn)&jgTk8e(jY`)_eJ|EKAcB zMIg<2CsE@p>cjsgoiSrHovt_Z8P6N7k5_5-2mTkYJVh+N(u1j=Rn4Nr*3Y3iI~pY2jGNW7;tx5uX+8Ejl%>-+Hr&O8+Qx zm?Hd~E#Y@#YuSeEjKh8d>*sdU`glEc_&CHCwRiKC?DlVz$74yF!^$AWj>orYW1E*i z6AlR3eBmG8(Q}6-`Zxy1M{hV8if=fXr$0NYt-r{t_1`$Xph?sg^|abO5_8d+VZT90 z|2AIf0j$g$+kJr*M*0Wk1R)EKc$q2><_ch%kR$Hla#8JO5S!$0sDjXpp=@OS7K?CZ zz^ErRLh!Dktxd7K7%7yhsb$E@Dq?nFUBX+JY1;v=1THkF@Y^iib|Y)qBr|;=D?JIW zjR0jcuQ*?ccu|672zOnZxGE+Za^a1h`)3YfM;7!a zzgis9?*89X>8nOKtr5Fm#o|Dcglu#|+s4 zU#b=;6D$jQYJ;UeCsPj_-`>L=lcV9-B={MV#q1s_1+LE{AmkQQ!#g0Av8GZOWU`5ssLq>4nnwN@_JR$HC zV;u7i+E$XnM=PW1(MHr*iia3yzd9z(OUY#N2c(qK&}hE9csC#oxf}LJYh7;vzp=2; zT^$_gHsw9Sz3z%>Y?k2>oZqi*FVt?lWyks2-t8szyfw>*wC5OesCVlia~&RTU%XAy zc&#g^8KBg9>x1@^A%vq)k4fU^#kn7_P2d^wKT!tXI+P)8?WC>NTvYFc?+Dn_NWTss zrlN`Rk9+h=Vilz-e%Ko?8_$4^C5w}MgNB=&rW8zbMO)=-o!BLx`^EzTRMgcxHUe(> zZ2$KMrJeDK%p4wH!7M;k_r^o_iTnXEJj+=L8*k#Jt0&>x+r@U)X4S>e{cZ2&>x2e@ znYM`uo#Xj2Nz#iI6WJZZoJu82ARYa-{skv*9oEv@S>p#x(Cba5z5k)mwh6hA2u#Yo6CkwkvS|nweA^Y@@Jt9n;g@MWpu24Ky z#wzTY@FqGRM^rNFOuF8{XBJsDsG-)YJ+*$W7NBp7n%%}mBMSka0t4jT{Fd|~MGn%B z=h;h#I}kaT!DkCLCeVarc)4HfRmudX;+UG8BfpA^M#Cd2qvzlCG;h-rCW`xZ zQhNfc;?`hiIm8KCL?=0@@6mi&M!MZ4-ej-;<#neX%ctiJ0CZfH@?|_-QvhRRPmWtw zw;=rQjk}1*%Svg_Qbn0fEsuCwaNC=3(kUPN)(l^Fy&p4kLI7VUG;4R;^S$Js=;Mrx zt`x=`Ugy3ke}j%#l^mco7l!xQF~y)fdY0j46>m4;qT2-Txxw8hh=}FHZ69c}Z6UV0 zG3EI*X0!SW@|_$#mi)@`@~hPz)?n@Z8lQBhe)b$ftdE)j8mx%^FRi8Ii$oTZ1Rk4A zhT6U_j~>4Kj*UQ2KS8b7+;H=iFr+GwHH8L*8RAX5{rwkP@fB~nMQWe!$8*Q)tFGa; zSP$QjQe(gLPqw}5GO?U8(U!Cu#2`2j>VJTUP%?5_azl^t?U%g$#i{l2r3)qw|HV)= zk>hebw<~IoohyhrEF78Kxtrt1p`MBIy!Z5}H|D?V*9pR}R~Y;4DnzCf*mdg%6t}ju za#pvzc=Q+hqQ1!s8>j?Fv6ox?Aw<50{LUzJ_B$_z;7{c5ZzP+Bg32%2DhGs9ZP8`I zpGG{pBv9i$^6!}T6MJsHM8DtK_*fN(3ITH`J$tS!bKk=mz<~cm4|D=**QL0p0}H;c;zsOf81`y5?RlL6Vuf@l)DB9U$ zVf7?u=JBceYz4{^sV`rMArq?*@HjdP$B79=h6}=tj34vDjY7ecJH|vxH|^hto6xE4 zUkS-8(mK9Fye)zIY@JOZHyi+r-};^DWAOE_w`qeX1UJg}%^KQCR&4R6oWJJMk)Y3E z+Z1$F$5`@9(%@0zB4fwGh0BrzQOYyWpyhuE)F@q7u)|WppKx>`B%sICp>V{Mq(Y`h zfGZB3#@0kukO@4@z#r}Z5iVQs%}HBll!K>PK`@6tYhst5&dP}jtE8+fW_z3Fs)e1! z(aOk$GG^DqQn<-sMyJ397XqPzN7#~eot@*$%LH6pT*mWW8PzW2%rG2Zv8 z*Ol|>J6egqF`sX19Z9E4$1PCvtF6D(#iCY1HCeU0*;d0TWbo<;Me`0Xq(Bmpf5PoFfxn>!({C zo7G*LJz(N&=gFaqNSP#dzm8&WHve{cxOVOLr#!mAGq;K~xa$pXC74&)M77j~IoS7G z6}n>pkMCvhkAqT=w++90D3Ae-1Yu zMCV$Gzp`6mUmEy%f;V|)H6Z9?@4dQs0oh|`+OnZlRf0pWh`pbi+jTc)j?fenN6fHy z>teERX~kjkbTo6ans<{8dU4}|0*0_VOd^U{p0?=Paez5Z3iXkvhC~LedfTx!mM7`ZOLV&VGbej9HhlX2!QBc%Lxy|z>9t~ zE_SjIj%$9y?o5uShc<_IYvrF{y({u|bpSL?(fjSb_QPiiK*QIoo9JnJYF&_CL0XJdwT|w@Gr05S@rRf;Rs zs?}|aJr3Lj90qNPT=5;r6yn>XU2T+5L~`rM%-^phqs`Hl+T) z{V@iJMD#ecj8dfUto)_T#5QHd2eDuh2l9|3PoAL8e$7BF%WfPS{hw1oSw1UV?tNkW zdhV#qDphkzFoHwR|6++B{8b{qZ^lo&ZPfsaGpUMs+|kLPf%&)Gy_=IyehS_&D=&IT zQ=fiDLA+8z0_fMGLE#ViHRu&f9K1A2k|aWPxg z+cl>w1SbA>!+|tk2{jqf06u>rfdVFeDow8T_xO~#w*CZ{SnI&3LZmI-7YYI@GCqi= zkXu1lSe5}-Tp>(SB5BGySuX}NQM~t$BifoGqchoZvU?N6k2S;)9Wi8@f}1F2Hqy36 z4iZ>%CL0qK8Z(s}o0=4Pv#9gNp2WG77zn7aV`mqEvfOwD)zvW`y3vb^1dxzBV;P{u z9DobM2sb+CFvZw64`@jBEYw*wO z1v@hWh_2+w6K09W9hHkv>C?XB$+tgVHL9n@G22h z7q8UNT5b=IeVRhd2Ycipd=Ri0xf~m9N^(kXPPEr}GiXTg)ad?me9?h$CQ;Z5-Bhj= zRuj?$sJ%9beX4|{`Y6(bv!#52KqCI!duV`yWV1Y!3tp#ih~SdsZf zXvIpY5J#4H+NQs-GWp^R%!(upY|2zv`$t#&u&|T}h(%4!2uMF6(g3woD11hdIRhKt z&$f>b8!yK2=^(T}IcV8(RA)-pUF9pEF4;>t_>pqHomTHYD$Yk?L^KHQfhz?_8Mw${ zB~jv`vjc*YgT(XEEOp;?HAKW$HRy`|xlgng7I(=FNv+*h0dxf$ZqIXKp%6+xX45kl zy4sAh`N8|Ha(j?%;~Ct%lxbRbcYE$m%rIql{~>JqCNHd|rFylr>_do!r|02ax?+{{6)FCP{+?GRv_7|Ln#!X0Mln1b>U?SzZ=RQ zyd)%Kz>Y-z2$k(^2ioMG)p&oqaJXO5U5~b@4b`<@2j7v2SYuz?7$;`gA*zQQ zz&E8Rl!`&NZ%>}=MW}GIM_WH9i3Miai~5>4_1Ma=)E&h6+n)JZVK8o5(|)jnQ*O?3 z!|S72JU`#~4Ptx8?ta}L8hb0m&wv}r;t@pY0k2xv8Q2Z^tw!^fu8huC-Sqp})FS6( zEnuv&EnEjS@j_<#!-T{R$loX-jje@NeP13$C7umsGxFE_Rd<6}^K2n&P-~shBE3+c zi^e2V9=Iyd&2DiZByc`EqJH-5ZQWpD9N_-@@Fr*ZJgswJIl%h&xge}8Fy?LQJy5f| z;ko6Zd+D}I=j1ea%BR$e;L-36Ui7vgC#9qaR`fdIvGtI$u&~ z;cls4iv0K8i_itP$$tJy4Cv(eWixE4+s&eNJ%qh31BbrFuH#O_x$~dI90!t^cY`j# zWaH!9eu|7A>h`YUHh;5Z@lX_aIh%EHg7@ez5&i2rY(&QE%YyOf1#JC%xqy%6+N(UP zZ7&CWlz5dJwJ4!OQ+aaf9tI3euB)ep7@KeR8Cm|P(7*<5k8Mk`cDED4tbUH7g56U zgU)u(82p>myjpnkfEKTJ+5bG(3+P~5c*#usq-M?tdc{)2z)Qn7fARL!QpwlmuyTwT zak<8Ot+4@{g2={nu3lMJ7&7zP_omudfd~3iZqQ6k9`Qwy~XEuA-n+x2pJa zV39b5Gy_3lGp(}lh5}?Sgouc~3oVYz-9SXEjAc}q;o0B3uoc;^(fkLpW79g)~8RKLf3UK7^N2Kn)oR0Dk&mO$?bbWhKxds*+kB zr(+0{VPdr22UHkmy^jN)+9kK&wWu#44w>Bi%?jdK#;pOouSHLJJmOj8wKyon80M=` zmX!m8^~alU^-bk)1!#N9j1gsH0lefsdl@Fy!otE$_n2ziaxx70jv;-H3gO}#P{6+h zuFxf@A(EM?9_cl?8rTsG!*Roe1mW!5xYT4Am}rs|`3Y*f{4y;tzyU#{+8v$SXPn$D zownzP6w(<7(0m50&^BU0$)Bfc*T`Uz!i&5Yu*H_A9Y}0ydMgetsEl#))xQldpL@m?ruO!WS-8y(qw%ZDu@j`Atq!l zMWF4B^X5!O#P@ZVj?$#W@1DzJkm=;&p>3FO8ffl&W^y^{zPO>H@HoWRLg&w%f`)6? zVfvP4XqRZDF=vOfn(F!ozIm*hl;MaS8fe#vH7RIw`au31FCX7S+;vxdnOrts`@&W5 zg)OwT3vl{y+$3Mz@%#6UNv>;ZAk(~4NsCS8&15AyDTH;gp{HAqu!bgq&@zvsnk}0> z+R%VJFmopuBvgyRIH6UO8hu-B&odILvXs8YrhBFG4yWSLH*|6B2}_xkv##rJ1qfB~ zMFFnz`HAr&O!>bZTOI23PF?tu8{A|LjrsL|xQq|81;6!^|HSaS9G@7QShUZY8R9m{ z$aM7MCk5I_9-80v-+yWL$zPAv5Aaxvo|))ogAg_`^6~4ILK9Q{DVpc3rW?`D!~YZm z1WSlwmbMReccpxPK5Bj=pGwnrGapiDd~x^w&eghpoIB-i+)-KG{0Hir!Cl4r<{Nh3 z{9QkJx9jTTqXv|BNlp7uws)g)F8ABAoq>wyb<+05d-wf4Xz{~@R_Qu0uwV54!J6C# zbn1E8c?d$wRa?AxRleitKeKiHtJ=64<8@b@oY6Ww>~7GalV6yCbhs$+cHqjA=K><$HU$IP-u=`~ri%&-p$;NVKM#dR-gv z|Ksc}fTHaCwqd2EyGua2MLGqPMnH*OLReyv?gm+;q(r()K%@kgrMr|4S-MNQyS~%w zey{txp6|V9zIkqjS$5_e80MVa-yXlC{wDww&i4BMpR+I4WQ2IlZ$oc@v-BF#pZrZU z8yM{Nubg?AyZIeef51RIhmT6jwtn-P`L1ha2j@$3`+9aA_|+rxDB@I?fNUatL2ZUz9BR<*0O(I-Qy4cMx)Hxr8}HZ*{hgnXudL!RdO2G)Yms~e4M+^ zkcflsgCo=~Y7B|g@Bw2+lgKh1sPJZ@=vf;MWt(QaXQXw;LZkf>?>R4?JrHjtMfLdi zX=C?u#wWF9OeP0EzNoI^&_As@R?}1$kdhkMnWZgSdqYl<_+#y;*8UM2;Q^hj=9_ z1?<2hH2a@o2yUa_zJamQF&r;NL%D*edG%L{J4!w0RH zPEU8BF~gKz6JkL>(TnnGLtFn)EB~J__i|vWZDW5_lq*6jif2u5uG??sUWxO%3pg8; zRIB_ZJ-IJdleky5x8>%2792|_M@k3u@ zXs8MKvzIY)vl?Qk$)w3XS%jo)8h9_*G@YmK$LNfM->CDwne%H{KOfW?n=9O!_t~4; zt1JBG?=aM?9D=EXOA!53fc~vI>F$%T7t|x)9$BnF$$FA0Emcl*FVeH$uor)H(9`g{ zDPGi(w^o`OnaZqO&MWy)df+kQg^|4zN%yTCyU?dXZr~HafPeX~2VEA!MMnLi3WrHl zTd`tKzNQd=Gmv6tQhmHKO)4zlA}E=MZ@Js>T}CoVATQ@tw4z)ZkJ936)6yxk0(3jh z*0IE|RtJ)7dODdT@SIUJ)}TkD3b`Q)s*!_bmLTxT&Sb3l@j4n9Arzy>j~|xZW^ICqlo8erH2nH&8qXs**vth zyZa2fF?0l4-sP{_cHw+H!auJt+w8EZCeVB1&*f>uK(X|*m)C}`PpJNUtzPy=q6M-NT!d#+%3SWD8;WmYxju^*z>Qh(&$ z!?2G68C+|_T>4hLE;Dg|5p&db8F0$=hv4ixT44yal4%gSeJSHC7s#c>2SY^BEM@wr zj2(N4?n_eA8BKf9y5IuhbV8O1ha5QneQC{{uCZwCEBpFKgOXJ@F302J)f0(lR12Xv zyp9jkiu0?Gxy|7nKO~t+nXS?Wcm{z|XW39d3JF2;*Fvh|p&=t8CT|yJloNt;zcUx$h z3CH&hSUNqK+pk|lMm#B*h(-uc){RNI?I15ed5?@o@qDCvS* zu8OO@?(2xp9b#nmSU#)z;q21wv-8DX&7aTSIC6N^Uo7Vl zq4bveu<+C0c|4sY!d~)(lp&#Pzqe^}3JbHs!-c#SMu&%$gs7PT{ise%*(DdfREmFb z!#A>;61AIi7+aHzNsC};>^%vbN+;4vRN_;G0OFHKn1axV(udZXFHgl@yr}vzCXI=I zQW+3HfO&S#&o8RLnc(D%XpBK;ip5f~MqxPeVhAp%s0csZMpjw$y+D@lo6khMm6&9G z@sY==_)5~Vb}ZdZ=_?Z|AjbVLbK{6U>IF`_C_%oEu*1&{KW7652zMsMWBM49!}M&P ztgOUgFJrCe6#SBs-HXFm5C}v;Qc+cv*=RdeS*XX_&L&%cD2IdSF*Pb&&YB?~m+;R` z_{Z&O*G}Pr_F0nE(MICZguL|4oPDM|bSESwMS@F^Pf3-|_>BIo9qEt_E3tL^SQI-6 zrrFy(w7~B3jO+o*;BI+?wN7X~qk@a-2Tyu-J7vtxDXO$fGO335u9jHS1;z#IbLj6t z!yy@oaP=l=h?<7ZdN{{inmc9+Mx(V#=&h%6- zAf)w5-{uvkZ1MXrt6_23ZAldgxwI$20#qmx$}E=9cbr($pYd!LGR?=Zs%m{~FVKZls(BBdDO) z=+6j$5xVaCCGs(&=&YhemvdRXUZJ07=Ari0fobm$`PGJCqDf8^*e2uKYYxfM5m25~ zj8bREaU(3dl-)XQBmnq7KGvS&&;4~@`+L@sl9JN=R+$}p=n`uFxCJ*PRL9EedmoLh z=V`zF=`s}D)^;@0c$9DubFZIzx2f6Cx^sM(u`lc6V|^tt|4`;a?$qKEM$ziC08W(_ zc*y6iwZ@^*gf%@VRpa~Vch-HQZxc_*{hb4w8OS#C-A}1=(MNNJcYFJbOQA{43qYMH zpxPY`4e06B%&mVQe|ov=uoUG`GUpX=HRjmMQ8o7B**u&_x$ zdQ1)A20W`AJsI-te#Dtntcf(cR)PGYS@=Dz&f_`g(u-3heY4a{41c#pW$3s9iQ!Sd z9}ZnCYgk{n`^aTTxL7B7mW=bY<@1Nqxe%wwN07{RPd|P9Z+O3HkzV>dUxoPY1{@Z* ziaWG40cT7c->+|m9ge&DKb<@U?3$*ViO(*L^otbdcsz{B#obL@i3|h$tgp(9fH=f2 z)|j}W|Pa)$(h)T6nuQVmP`p-O>Vkkr9wq#t2YYLX8nMq z%lgx$mb+phKgaKtYQG)5sHvR%nsg^3y$yUo5!)=MqU8i*lnjYJ4g6;fL%tXq(seh@ z&4+k3EubGQx}Q~G2vp4UPYxBfb09CCBe(LPm-GfV(hJA*K>Bs`q~pI8?Yl=oV)okCITA0P=HczaW3SnP38Bp&9k$WCt>oDHR!`NjyT7 zN=>4`q-A!9Avq*(9dlxyI5Hx@+N}-Uja3q=YHo-qbF-7&{f%ckhx~~w&FD0Xg=O=! zn#o?uzCXjA)=@BC|8Iz*VUC3YUjW-H7(0sHj;^M@d{0!i=me6pZ6zGBRrcY?}zzY z=%k=z`bxMF3A)^jXh#soi%?c2b+oq-1*QRoJayHb>{b*Hh_hz?b321|q zraf|jZKkvyO(Z;KOtw%n3cSmEE!SCaC>f)~qD=_*LKg#T4X+=q&hJ-~p=y(@+3tA| z!5_gKJvAgN8fSN|7x)+=;Xk58+9OOPfkV69A0GP#+^sa9Rj;8wzw2wMW!zr-N*W2A zT)1@JB6D+C-(ZwIT!$9e=fe5M&p`NDU89dh$e$?u*)CU$5iqvO8t?)ATIiM}>pdV= z)mQqBr7b$#Ssr?QBeSzRnA=Y*DAWc_g7rh}JP9ghftOp~ihiDs)h&fLACXb`HtF7U z$g~z4zexoQX}tQoOIUf?yB;k;E%(>?Nj>9w9TrJEr6#2aK+=}+UcxbI9Rm%IYWw5f zpViE{qZ` z@7eQcL^Zw|9X;Xmdt_giFYHw!BvQLC?K#n)GNvgrH#aemPhR<%PJ%Nc58q>fuv?PH zjaF3q>dqN!I?>w?HLQngVhuzivd&fb4oyv^jnBX0!daYnoiLOHp5ap#SHwd$6og6t zzPo#L1IVQP-Ug@m^m?28b0~%QG<-j60O;6`80PNQAcFde8c{i4s=y8uRp z{4krUt*A^t?tl6?t<;E~3z$ce|CmRo%>bG@{fITa#Xtlf7h{5wAen%Nf4I1Q_xmd5~manV8jY0ivInf7B;hJUcr zJVeUJd$PfUufan`Q9R?x)M#(WUKC3zu~3arUK193%t)-$l@I1`8BwLTxYH2;d#GZi z_ZbpB)35ci6tXdR+6mE;EIsrKdPB}#D0g@zeg%iFS0hI{6DmZLs~yodq3RQ2^UP&=F4 z3IP~WV+%v>O`z<*@6Delre)bYNpH+u_=U_U>Ce1w!kxU&3a4ru(w72(rLhMGhWJVX zSNyXs+L+0b+At-{lAzHeN!_^VRlK128ICUuh8L|5T;+xl$<;&4#FqIRs{02xIp1LAg|hKCXR9CIX@moi_@1#Uygw<_7_BDM5Pc|pe>r;Mvlp0V&)G5{ z((=g2sA`OrErZ>@d8W-uhDQ4CaP*{yfsdilsc6=li`K{1`by@OQFM$-AgQxuIb<3^0=+@V+@o{A~;LkRALwdmT z+I1PEkAS%YUT}VBtC#m@-0U(l6mjz!*ssUszae2qgniqL|WhkX+Ex7L=km` zTJ#keZxG@X)nw9(oPSIF7o-uoO|?nCfeLtC?RfwuX}d$Oujkc;)wLShF~?W@QHQ3r zH8?gcHa0;G`|g7I!TjP|^CTCWnoAopp%oPebKuvXv*z4sW_^#B&-Ijtg$0((!>aos zPvpSKJ-gn9}_4-N4*VN zJ@TSXBX)JS%g(P(@GK$HuFy3todL6~6NN)1cTFSP&mSkbJgo6uxb3&}6HMWb zi?aqyG*cy-oC%N92F3_uM#krRLr&=wa<#g9#!k+n_@z@Uhvsijc4mg+8nW6kLQd!A zXnp!e;5F4_)5wpb)bWXgyiqQy?*Oog+QAjN}op z;Md|o)zZ3aa_F8~@hLUWO|!dvc;ceHm_A{T_`Qa;VEL}?CcZCiB%lmjhDjPolt5JwkW8`(lu}6&QdSpw~;Xw7`FI7f_ejc z^Ip^c$bL<4Ge%iSsolApxSl9#v< zS&OL39lt$B#UWn*DkhUe5Uj01^_s!tk=v*Y1V)w+x=AMf5vk~v40@{yDiB1FLt=LR zz#`$HrFO-yWZNAYBLyd%!V%QxrZ&2|)^&nz`6JWT0!f7g#YH%^UA5aw*zpU$`Yp6z z!eBx;6`O7bTUI6oxQUztfZX~|XI)9sy)3P-6e)mXSo1e~Xi-hBw5_jRN~3tpRtyWY zqhs3JWn?s45j1YS$uD1k|3rU~(WmK;GGQWfe>f;XaCe!dI>z9c?R%wNcld%Wl1s09 z4d(Lv7Hhis>dji0iE?e%2zB5A+?Ja(7%O-5h zZQAVK-&60#yAQ6Zm%XGBsrR0)uYRr3M5z0G7(u@7!PWL|e9qZqh(g>wVAtlA{`0gh zAn~B1InEk0gJ{d}NGu@0Po$7-yc}@c%+KEhW)Tf)@mimW`)E_w?4K1)l@2pHzPW`K zh5**p(arInI?3HpmxCK6Rg7^4Q_i41m#}x+b~!c)$A@JeZK}rFsdqrRP}4atucm5( z9`bs63}nbw)Z^us+D@P>GGFjU~6VWEv6088dh;N*-LoAc)o0K|@bh(hxK z__HX-Mq6U>7v!1s-*Rg5&p&S%J)ZM686x@Mt%zoK8Uw%{S^x^$5dFc!|6oY|{oDo* zxbpns>r1&b&Q4{a?$0V4lnev>VzCyUo{_OjL>QQ%hsV-*;g;ePrEDp-d5@7{y41UH zi(tl~J<80&uorGi`X3qJ`(|=zrB(AwXIeTsevl9KrlO_>22k9<)kU+WV2b&1Hy&-Z zAD4PmRHWvY&0QKxrUc7?p~q(oqMh@8*CW%FUSr-Gl6O#X@o8%t&3clGVGn4$lqTN6 zDx^s*+KMtujmY6Z2`=P#bC@P}_hEq6r5~d)j45s4si3$9YZ7Z39dlBKf+BACI>z*L znleIojM5>y;<1XnPF3MLbD@9>A;?~asA3_Yjx9k7%vsdO)6;H4<7wYO% zNOiURoSucAz(#%i8*!(NK7_|J^Q91V$Fa~`e%8=x3`mtMzC3xvwNVlGC(KHX*#ehN8d9E8^^%$4 z7ho{S%Uz{P3ms;#ut=QRi!cRQn}`jn8ahQe@S*QI=`^lg2Jdl+DWY=Ev41wyXzwH6 z4+~^tPU$QCrwc*)kLuz$br$+u7}v}{yt8<%9m)lPWS|W-&3zZN*eU&S$f_8Y8W$^mtpv0W?yRPbqdgtUmHkn5zH)fZ1 zTZ+SHt*C3kk5ut!CF9QAF9toxvkE~@Kc5^V*2EX^J!?HRENhuR?dbY7&SmllpyP{0 z?0uI>G(e7`z-R&w_*YNE5ZC*m=FV=@s;nzt9#ofYFagUelx<)hdqXk;rUY*kVoCu`*jw%CC zMnEif>D2<`=If6^O}8hf1kQ`E`0((E+;=8_6cy6cdzr% zOv3BZkVwmEa2%Y48ep6Rkl|B?Z*BO4FFtm2e#Z{N`9^!lNbUqfsEKz>dZxbSROHNH z%IG6Z<{nA5oU7LrF4@n`d#Ws-_u{4FXJHFnmLFgKIid-9KQ5RQcj>v!T_u2Va8VTB zlIqHF+ELLRdu{#Xmb$LonR}{ivQK$?3&D+1BVK)$j0IBsE*$a*8zxMHn*K%IfIt(V zmytw5nPV}OPuCtheM_8vG`&6(A>MCN)kpcd?J}>I&f-OGcYSDTF_X?%u;C8_ttDZw zuCBpwK|IDb((blV^HUZ%P+ua@7>0?K%!mmvM2}V93Zlz_$@9|<)i))3j}Muo@uKK| zB3SE1;A6=7&gfkpTM&cQSOIHlnpCb1=85E;@;Vp|*r=6k3mTt&r-|T(!Jek%LD_T$8>*x|$OB9R$8E>OY##zP)5aJ0~)A6~C)-EvNBt@Oy zGEX<~)@Xu(wM;_2=_r-JmW%by+Exu0IEz8)oN4?`T zBIM3{OweMx%x`md6fOF5GfQi{7|~r zE=XSbE4eax1?aDF?4}wY*e2-FK4SpZqiXz^_+~&kT+8bCP?U~rr!}kF+C9$V3n;H6 z-pxfGF99sew+*+?%$J76Qx246I5s&8P0M7Cr{nfgWz>Lid0+Zs$10=KHs7G+##XwW z5sKq-O(d6AvQZj*MEt>9_J4&f^yJcT$e}68N>7D^+9oGim^)U~B7u@v;pj));p;3$ zz^h4KGO$n;-40nVni3m!ZQZX1$RcUg`o)ti0iSy4ebP;Cw>%^-SM3E;XxRyDxWP5H zD_=-7m*F~^5F3h5b|Go71-3_S%=bgr%nhc4tR zG~Q>?hpQyaH+ScLxMwjg2d%PlAqDB#yYY6kF0}gDc!B7n$vR*-Kb`;3raRK2g61_5&oM9+B5jwU!ZyH1} z;c?ucU`h&Of<|ngRoDx%3?n;Wy;1h@`P|J)zz2(iTSs&yMYH__QaFBibu&K=FdxrM zrZR}(28wUVknF>s2HHE#Tbup7@ORHQr;-ZFJ>uu*wL&o1l&nykQ{K1gp*6dk3Dd|C z$rn?CM6%zImgaei!;o6>;~K9lxsjy0j}xBfB!68REzCG3;Z**zUhu7`^y7S1N;xMd z@>N%;oateFT$MG-PQ0x}cVZ%yj8$*%#~$R<=w$(&q`dg+CU)qtAA=1~tkMU-63mj@ zhJn`oXc{H1Eg9GU6VrF9l7YM?NkYPK^iH#noibO+EF{>J#R%;!1!I%yc{9Gn85;URJtudVCjeGpo?C z8R6n*tw1^YUQ`CZaz>a@rM+EiXZcVO2?%tFO=qMYD+8av(`&_%RHJ;G9iyQ*QSGfN zq}dH{oA}YMu&-)1Ql|%!QOIwfq_2Nj4K4JB8Ce<1OYzme+tmVu!tV$mvTb^MHD%r4 zA@OipEm!Me{#+%JBHS6=47?^-M4c<|SUsbT6}pGkZ5M41Lv z@L$BNfvOj1V7tTl@xzP`v6lvWjUO(jA0EtZv;+DKiC?L^abi{Z2Wx*lu6BJ7Q>qAs zVZ`^_iMZ@trOj(5DELmSAM}Yf*aF|_ODP%8GtJZHv)B9EEHAg}czY(RKTiZ#3-bNm zf=x7H0CehCCfbJ&QgDIps)GTCvYk3)UN%qvE}$k?X4a7RsuFHJ1o%)HU{bj#46~Lf z0uTRqJ^sI+LnY7tTv^JSN3-K?wSTNsM~W$p-#j~#jR;$^q8dV!MqmkQ+Q?Cc9b zo+E)j6Us>leU3_xto0*Bx9bY!_=5Rx)%jsu+`~HBlarI9)wqU>g?qoSxrX!Q4U|SD z(tJsT{akN&4?|B?rWdDC#%^Skm6+%7qiKA4>g)h$*!;XdvAR>V_q3&k#4eh!?eFX= z=I5VKNhpCg^U*3v2LJ{9a0xUH9QrwOU1Pi)$k(=0gmKv%U>Kt309kj}07{ zu&*nNtW8!3h9U$Kso)Z6Zo|AwH&C)LtWsGTyLXBQXC(zbl|jf8UoaJ-~nSljooqzqojY`?R%VA5Z>F%k|tr#y^?Sgb(PzTjq7EoN{zoKi2WfrB znH%f=a{x|}KZX--S0OiJ4w|x0!fJ3jWu~O(3&~g@TEHC?3Yg*i5Iv&Fi z)9Xdky8(w0M`N2q{_cu5ouLB|o~!fC!iEZWUQ|?GeYn7wHK>8Hdv`a#{2tKIFW(QF z+WrTEb#X(+W2M)5AW+w(nRMNzC&GAjPtKKWI~3WjquBg;?(NgPsRnubR=WpLk zm3f@r^_S}WFG}Mt7;zk2l-@2Gs=w#`$6GU&Rpx)MXM&exgs82vE8S<<^4l$%pHPne zxxY;^GPj3HAb@V#+qr z5cx6(YHbZM+7SO-y4$%DNXjPmw-+D^nr}F4dJ>;rdLdi)pobiAlL@F69^(=K=Yqsq zEi@aS?Mk#V++VO`5}f6h09KY@sL&vCAWihjdPeMWb;a7o#?+IgZ$4A*#Y-Jp(czv} zS(#A$v(aHfs~#<|*Lo4#SW`~ipgX}z&>`Nn&x^^^3q}GN=dh7jp%nD-9F zCFe0EJ>uki?e{)iVT(ihygaj-nmHwP@>{`-$7%TASwEgWQ|THJe<3veVFUR2@p;~1 zt2Y{wn39c72g-zA_fy{zq^ccRSCY(Q5Hz(_wY(7TH9zQSUvO7)k`^!~2sc<0EW9Zs zFn|BR6;RnZ8FR6jo|5sGhH|a;dcPfy4DE}`cmhe|vPv5)eO@O8k|z|EOKV%U23AKF ze!{o5^d)U*R5y(B(n;-;+`0f`9dYKHN=%eW62$^egW6~gkHlvC$aDQfVu&~7vZQ9` zqc1x}Y)k=KzP3SpZ%(xd*3D~DxWM-Q=%}%wgsVl0>U!c|v38Sl8|DFIrZj@uF+Z!fL`~zZ0xjR^N-hme%LBA@*p{%xfF08l&|29Ye6pUN9Z=bD>O^h zki2A(JVg7VJy!11L9^&qUR;J-TohEz-%`Bs*Gy|z2u2`APmYH| z@9w5oojNdp78{i@Ow2wU#4bjU7HOregp$ zx%!Q&_}h@nJD0lc-Li&7d4_NP_YMIPjXM_koBLh_vp)O1vpN7btJ72-M_aT38u0IM zbf`((Kpz;`Yf5jqz|k9A>pgPR-<}`4nA_K7Z8>HCvnh#vMzb4l6rm^(K>Rm?kjAhj z8S?#U+Yn92ix-;=lmOcL08ow2UJNAq@kdZq#MpR6G}4@=!V?u#^jubh!gCU(`@MiW z=vN36c@X3GFWO@Gbkq=6p{{1XCIJ2PL1LuZT3ZQ;=$NNQH6ZdNV1(`RSGqLO&CU#= z8Wu|GpWnBO9*4XfJvpH@`(7Rsgh}vcu3eweNv`~|8f|J08pMw}ZNo^+yk(ZW^kj&+ zIb>XcP>pWV4h%SfK+CiqhHO3bGhJtNyJ$%Mlq0cU61~I2gx3UnxejmnQu^6>exmK} zDhu1{zdXOv$V9ks(TJ4gRX>xHb|~1M0in!ZdV`2gNr{FYO~W1>dC4!%JQt&h6o}M} z77!P1|9!zvE)TYGksC%n&wZjHR2J6rEVHH_CY(BQxiHnYlUqD5#CNM10J?R+|7^ua{I{Jmx8O`gUiV%$+q&Q-Xo1Y5>4BG&>l8hWr zhJ~pu5seVRk0{j>R3V+Luh|3l|$VY92 zeNivUeueq8+9~)JY~{j|VhPoBTH9OamNumz5I~)lx~tn0sB$;dPDe;cR)<6(kGwP^Tb+Xq z8YBt2c6le8aM@6a?O=cF`lyWN=%OPSB6kwk5@)&>5B$e=VVVQ4k!VBC zI&G+$z`*t?ch@diK_r^#x2Z-Ai_gjprkzX-OpnR&>Npb< z;5{#$z5Br57VdrKQLVC?YU{m6A`BUkYxZMYa}4iB$djr}N-gAO=sa4_c0(B)^ddm$ zE6rE$YIgw7pwGVBZHZETcDc+|tW8$2V)C>dWlu8yI!EM0DF4|XlIC5TUNee>dwhY3 zznJ9J?`c}i4&U8Z*wXi2qIW>m4-IO|Wt5Fcj3kPtRJCK#ICvff$XOdv>FQwGnELAt zxltr;U)t5Q4QBMs>;r9FB9?<|hdq5m`Mf{@cGbEz*P{_s0@0ivv+n(WdzV3xF~BZ3 zcWlt>-{E^-H+y>4!O%W4uX}sv@E3R+J*h)ET5BvU0rYKV(~MOm$%%JoG=P)FJB0#@ z$Cmz}Fk`*DQb)r{;Cf?aDHNzc8tuyaiN6!!Pey9LA6O>M2I>1x$@idMS)o3a;<6*mgu@b{H zmHO6~X{fCkIF#+_&Wul3&^1A&!_dQ5^mB9DQ(pZ7@amc|*5a1f7<_aXm#OkcVYFo6UN9*olgqvHT#~6 zftUw=S>}R2gDH%EbVt!B@;?6c#qV~RqGgdy=JHYVJ`kblev)MP+{fpd$Y~D~pLTJt zVc*i%H(iOPeab3ppepmU#9|Yy!m-zQtl_>pjovz#AyM}`Hv->h-?!H9^z`&0zFSDFp6qmO9b8z` z{UyF+_o>BKsl_r}Vp+?_??QGWI=+HF`t@TfKrd|~$JR}3)9lk8OCmIw5j*Tsr z#Sy^uapEJfa11dJ8&O#nqI_nTlqRmK`WCM_i;dxek|rD8HKzDb?fo13-LcOdAO?uD ztgH|Qo;s14mZEB9c%nIp-7XJ6T8$u)N-wR_*VnOregPLpiO8~;9m3Ip9Xj7x7C#?_ zoE5sl|4hgPoOQ?1k-2yU&-na!fb8L$+zaW*@86FysMpA~x-T2W09(-2_gCr+_`7xb z5nZ_n4fZxe@;2rCLnH6q^x9$BQRrCHCC}b-ggxPih5w~_bsennb&R|m(zw3e2a4O~ z_IY?57yNi@*VO+aby-t^ypYyH4Q6o4oxkn%JUEkUGD^cRT)FXDLUweui zJsHsw-Jt#2^-GhZ_TFDl!^LaYW~rj5*Fld1YjwA#qemKXas$)`Y0y4RS|f(v_5`%z zm;i?D=5ye5%WWwR{rp%J+^=PY?qD=YS1)Az zR~uj<8h4osUh}@YJMW;firaaiZ!++RqKU9YRS04NRD$VA>y!4g5Z{-iYy869OV{XP2RZSSK5T*bD z&LkTdnO9a-<*M+c<)(yGyr_E*>z0aqqa&A<;G8w1h3zbsb$E!o2_MRl?*R5wz~1Bi zTS7>QcN^l%<^irLODo)+9jxe~m$%X*UZ5OJ5o*o?JkiqbGG6c5vP4@~&7->u(C9Mg zI%%ktSW?4YNHVDih^GUTbL8E;Q{=diu+Z4tTwA>x53QdomxMdZR8}qi@IFD|g{5sqR+9t)t#mTF)UULG< zvvD6J*rCY7&Fye%$UhN*KrlD+0Mw7kDo{3e68~ifozL^(zW;f{b~DdVeCjXIu&~ZI zi_&iWR!%l34)+vLvKs0-{W%p^NfXrl!dXqt60lN0oCUispdWY4Gk=EDro_iQ;`UlF zLwP_@ng`v@am5YGcEc@Y+VdzL>4mV6scklLkEK@SB1^uaa7p(>x+e2ja%Cp!R)0q0 z5CZhS2gSbZKc?aZq1$;0azv!&FWq0%ZB5lxKYd~soTZ{JW99f6K~)WT2*JB#)Lgu# z+zvuOEwp-J?xUhuvJH|3G}+aU$;X65dcwLSL7$^oK&gOb^zqcR5|EccetD_Wo>!zr z6b{VSOvLZpY&_J}hb;%^zA$0S^n2}@2E&HnUdSR4ZkieG^%Qt+upkm&VW7f5{%$mM z0!2e(JtzLUC?U0ZYlsl;1lXjwqOSvLI{mPqmmV=%R>XjW*|P>5k! zCChgG_F|!o(Up_Ty%&Y3GwZ^=bmMV`#+T#U{f437{?$PVF3fYjmy-B07Z2lU$oU#@ z=>riyk8B@V9V>j{6~E1CcJVp7D;X6dPxO9(c8hE zhn^ln&t&(kWm0l{uYPyh6av|Fp)f+bKIijWP*>N$dQ)acUsgsGnR|WZE53`;XIWLO zhyPD=W&7m+u{3p0`0R1W%yTCK{m`PjLTuNQO*HPi&NAn_s0${|heAMt&ZDVMS!Cnr zpyMD!r1m-~-?@*ctfZKuopIntHJt zLvaaUZ*~^DC~k2+{+jQ+SEnJV75%UD3BUtxHSJHB`I5@bY-J8bhsDr6tR#fxz)?fD8$Q132kd zN!{`{bbtAGUd$2@$2K1;U>T`pntvOn;CHsWy>d=)dT`KjE#?Z1_mu|TxvCL8G|+cY zCi3t&bPBT1LSJx`HZB}7>+l}9OX;X-2Dih-B^CFSa2KXlhoBIswMScyU zo>0CO5>%ll)KHDi%{_aom2O@QQB%wrgxeT0lQB*pxs?#jU7Q^r90r)J$VS32(B&RX zmH6c?Iy!I(@XS!MJmu37XTqsqVwM?dWq|pL6UZIG;!G?jMRhZHrE<6! zL~wL9(URHy+?CjdN5Xw)vGI5?uev%RFz_J|_cS>imM4fE+EDyU2KvRL!a?t~N<{Cu z_>h&AbrNAm0~E~nDX|c1i~fP1fM=|4t{G6L5NLKS7hQa{OCdA`A8=FDLOhzbjnaMg z>XPe_A|VYRDU$k`)K<0l74-A-Y1IU0uQa( zepnkJB?AP7+ds!hpA;j$i@k&U!~IzGfxZR{86WAbCDy>&Lnh^%U53ZQiqSjH$k z9~sULr$AaWXLgOr9{RqP`&Hme+MN;b7~;Nl?~E>5bweKGi(`~5fx-KNo)v~j;8^K6 zb>i^PNjgl@yxfJ{okk^7&bGk+KBtNYuQgR>ew9=_7jKM|FdBqLzH zjb$18x2&x2hCzW-`6^3Ehn<@x$3FvD?xw=N4!!v#KY#yRk(0WM(t7%sd`7d? zRkVN{`;rdG%#5k$w=LN4h+wT$uN0fOjef2pRZLfXLho_B;oPq1=wI;&o^Yb)Oh@ji6ggFggeF5_^F# zUci~vT2|VA^W#V_(3a?{A-@*#l{~;rb?%#3xxl{=!0XX8ZbthJuIqV!dr*E~UwIyX z+IZ&rr6i6PXtV$rLT3jGg#QE*L&BrJCz@`o#l*Xa=yQ%QC@s)7 z*+~i1HkRhGP=mr0mh~AbQzZ4(U2;>@(}b)1uE~WR_RO!NUkH~>z!B7=DUzu2US|x+ zUjiKCgPN|XXvGy+C0@9=L?)V}&TUWY*OX=CWg&v2(!{ORg=72B(LxL!j+LSh=_oLL zguc$hh9L}*YUqM*s9X8Pqz4av^LGRVp*3rAljl8|dY)SsjzqA2{)sUSq6zP2{+is9 z3&@(swTIm_K&irY0nFNd@_Qg3&^RR|B&61)!O_(ggjsir1dHuA9*b^%i9^1YHT<_< zmMaRt?rZiYKsag)bR6a28x+dmpUjB$duwZXRFyBksL1-wP!kC7S)~GFFZ3mYA1MTP zZf?%ddo#akFDT-d%JA6=!+mlM06rCPM#d|rxc7mSz1LKqF`@+WoHJqhY{sFmrG+7% zv@qQndn4UN1KP~>1UNwfXZl<0IT;+Hfp6BPulnj@E>{2w%5BE|`Y$=TFA{05u|5wb zl}ls9!YQm6LBGnN`FeYQ!$4uXU)Jz;8#y&3b-`%p_QtJ8>elt5lTBr8NDOmOW&wRC zOPNrVV|I0QIof3{!Lf@hf0LQn@vv(g-PzvSsZFHM?_>|?a$Qg3a`0IScI?2*-_(@e zL{Z=kPHLG&XX5Q~el!htmy?^BQO)9FBQ#(K7$p{w1pT7cO~7`2GbWQzaDG;Q7H4Ai zwFGGD)sS+tc00YA=vcTlvi6oHNHSc8<>|^>6_Qw!T2R!{N}k5!L|>*1)hKD*TiTY8%Ja|`?3m07p_M)L2BhSq-neh<)dSx?e`&Npdb zfQoQ|R331Y#ds5b=>JUW?iQM602w%i_9&i+1UjA%K->)_*V)jWN)lk`q6$r$+;3Ld z*7~lzhQQtdsBEGBGc%kr_w5wCB^kP4%s;II@{`+tT$zCJ=9FV%|J~!_uR`>gfeo1D zEboh5jbo(N*Y#B|J@1`*!~zxaV~G0y&cc1&Xf}yB1Ux6jKGLdF4$1p6Ne%Pa^{3iH zK@$5P2GUfsu9E@+_x&6!_Bpn_b~lv_*u+K$t5a`7*5-L_Z})(3&P;zkh-&SPUK^0X zE(lnEdN4J_3yh9(7~*^M-=hOCbU6PPp<7NM6ZSX>Pt?`%Q)VVAt>mOCYX&oQ1mNU& zE)QY0D=lRKgRNDBNWv8=EJ4G%zVB1L0Y}HkZ+P|qh~mWB^;cny#|OXbkg1k{_ice% z`1GPbhFke7l$gN?dq_vfE?{|5_j#Efl}4?MP@tk#J}i8BHF>(qh>4H;R9txQ$8W4n zH4F&pA(U40WyK3qXW)bls4{>xESP6%9Lzfk+=cBT$B;Q;ihkYQV<$TdkcB&~7cW>T zHKRTc6aYXB1g6oS7?+)>C!Yqzm27W)spe6J=+HuNK?dCJoL{S}vxO8S)mfIMP0Vpu zk1@ccaE^%Tkno@X4`*K)SJl?;s|cbXAt5QDlt_b=gn%H8bb~ZVhjb`PNK1FO(%sV1 zB_dMN-QD+D`#tZ8-@W(C`LMTJH?B439Al2>U(Xn}Vy}FOh=?C;pF7_VjgB^s$H4%c zIEc`G+`LWskcOi0%WrDE8&w89H$%~K&l{cTuP=#}n!>q~$M^3y`uh6#E?4E2gV_6Hxx}*-0(N(8;l$;X67w-8F)^`0jgisOcGgbP z*43O8*+*aKcxEg(5q^#sHnMYa=Uv*w7gRV;#=STb7UjIoaD}kLq-n-$>`l5%#v>K( zVPKS)43K@R00pwde!1VJr#dGG%reg#oK}+vxvxVR3Ej(Zy>f(eRGMgPXxW4aw}%mM>{R_CW!B!s+z?Zg0^S$KQY`jf&oO&Xuf({K$++hv?6uk3bulrMu%OR)@Ej)& zxLsdeUL1_bkqUZ}R!vwQ1gjKi;E!{WVxod9Dl)?Hb~In~=LsP8po|k2^$+0 z#64A*k8uu%sV>d9?_>C3k$246VB_EjPu0GwxjdSXnu0tNGT2<**@}e31@6!-GK9+n$$)V~Kn&I1ybh;p@#N zDj9`@gaiick2cgp$OS{jEwXhQTx0u;;keF|omMO!mp!U6Eqe^Ov_thK9v&X|<0&Un zUI+i5Kb1IS9>c}(zFUKQO%>dag1*kA6_?=E$z#MVF52l;Xw;moeMQgW;^RxysCY}X zD&V|BK}1CK$=6q*&e76Ped+s$Taa@2oR~-&&tcXw|ow;PQ^~+&1qI4jhn>kaE?_Xc#rhVatUgrqV`u*j+_USKVC^v_l-h zUyB;!Z(|S-mYa7{kuK7pFMw`P}F!9 z!0&eS*Rd`SKG$i|7Ih3SC}i!UVvg)C^f-SB4@Y_d@)YaQLXPLDg5%he95swZ3!6}6bgR+Bn%SH zlf&BTO%%SI#eXSXDrB7j-%HTT{IA zhhA*(==gMR!GfL)gM%szpGu;G{`09g1@;|eqz|d-tZ@f3*oQMRKB+Pk*pV2zY+=?- zK4v3-Td~l|b;+997$0cgQ{BnQyZ`v$#%HI=*~>HQrd6SvJ(7L##m2$g$J1Wq*|H5M zd_hFF9zH+wwElkMcSGIEK&9EOqJ||muc^EUCg&&SE`>T6qxq+vP3g#%H{=8{_+9Zl z`KeLn<|r5oEL@;nXkW&3vUAhFFZU{@6Y=;{Y(<NF^KUzq$SR8dr6P9hun&)*^cQvp+mO3 zw(w*+s=une{IZX;vH-C27lRkG0 zh@c&KQ&o58&OHhS4!p0Ul4@#%&6H`#C@6XgcpUgjRRP(H{1)jca#)WF(8sAHgykKC zNLIj_HZ-c?apMdeF=69*w})gBF<`&3V%txhB69e`PzkTO`Tk2$(fhc#V!`pOFJJo3 zIhZE$ed!o48_&!%1VAFOcDir4yzsa9Ifi`Vr@QKG_YKSLlNo2I^br>3-ItKIxTB|M zjD$qJAxp5_pS9b0HBZVPFRc>&@aw4es4;b=BnvC+ho9ewUOJTH2lCud#<;=oqtv@A zQ}6B#(V^GMHm-K$@55evx$bYue_P|FlsVaEmM>}Sczbn~pxQ==pqx?yR$`0F8|mr7 z{sCw-yu5g2xYauWadFfH-M7R(X>8RG@xnSpqx$dH=N3L?dKEY-q_}&%?Xcb z`z$&%SZ=bcXBtJjzaMSS4D`mak2kng$qB`ezBT$0M(MEjGf#STpW4)IKA0<3&`Ut@ zVn-zH#meYcRg><>CqHxLTTL`J9iLm*@7_*v-;?;VTC7pf*4{o;=VV>P7R%?tM#5?F z-H;7dwAG(^xC8vhiDS;GbZC!Xg)G!%25ecwVzE=JStzi&<6!%N0m6nyo@z~Q8XjJTVo4C62Hn<)>di=Qc zWO}hDMv?JYf=Eq8%192D$JxQ|_!hOq927&tKjmf{u;G{qk0!$dU(AP+%l%2{QM)Tc8K-CK zMPH2Kpo)b>Mz%>YH?&pFcm^``n8u6sL^H;5S`w3mqK0<1dZVDLHF-7+92J=n&v%9{ zgMG@REEq}kncbwn*mUTT!1cxcqaNK6j;sBYYZmA*61FQw)D%{OjyIeMUA?`A^But! z6P3X{_Dh6j;D{S;{;3e-7Y}cPiWSFda9i;5K=I3AQf#a^Y)ymyxlJ;@>ABOEG(1G8 zS67$kxC8{9h?xU{`ZT*TjRM58nRHoB(%D`Nz8M!6=gdcjgNti6R`{^h4~y%iHm2W4 zusVV{E&mXvysMjHP%r)TZvEFR-CQ0|V7oBfzl6B>&Xbuiqd4WSDkV^7N+s_rQ?syy z!7RD)b+j8Muglfxvb-{W-Bf?R@>fKzrl{d4UcL#gr!Rraplm$IK9S!oTD{D87b^Fu zg=Q%OE;+eeljo&-z|__D^;IYw^*t4qfoCBIP-A|#lN=6k0wu(t<NHQGOOJwiT zFJU)6-gaq89RI9t#1+J;l#3#we3q9c*{-5y|8ULQ@k4ju&RZE2Yf zwH&*RWJ4>Uk)X*~q3fWL?!_+Z!KUWL^7_vY_)p!NsyrK#3x`7+T>0Ovygp#Xe`5Mo zUIgpc%2UIBEWwq<1$q(jJW3HsrluYuZjVXs>g%hPqPnTt*ToDUg1#yZP1q^@%o-g{ z<5DiUPU1f2g zBjr;&vb&2l*0~Y?483W2cSXqG-kP0$%#|s?ZF}@13PIcK4c(YL!3%5}xvOQUs22ZK zQR%E3FORm}9QH?Q-|dFq@zV8+BB+|qFEa5cvCUu-p<9<@cAClxm1+E?yxsUUFzTr* z-(hFX{D|D)z}cE#il@erLtER*JEzTxcJi^BGBUMmy90bLof&PkD;=jrQI~JyR<#n_ z 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

      } @case ('tasks') { @if (unit) { - + } @@ -124,4 +129,4 @@

      Communication System

      } }

      d55pdgK+vP1(gBK3hyX_hm6dZ2)%%!Ul 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

  • f*+K9&Q9O4gtrP%gi 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ÐB%FE;g9_tQg($buUGVFw`*7#)k@+qgf2eI+5W+k`B% zCRN>XXGk6Paci4wrx`)8bQm`T6=@io`Ge*jT+rx)Bw8h7v$JQvGiKG2;?A{+hJdl9 zJlh*`j^vUnRxTPT=irG%;$PCHnX$%BPLES+*X-*(YxHeaWgeT+q~fyYuJ>c9L%(a! z(a}Ve>gvd40D35<^`EWp^-8#arqeFyp#>ZQp2_h!P(Fw{&XP~f-Pvd-=ETMpm0Pam zXjojP;Edr2b-Hr}pvZo(Oyf`80cgt_qUN-PFer9;HL$LUDEuF`1>|w^DF!JQ2Q63T zGLe8^^ZtAw%7`p_<*84B-yBp%JjE@Mge^5}bAcBx1wXXPTM9bQeoaGyEYq_a^f^<3><1D1A-slYx?JYZr~{I0t{;fn~b&&%`PcDt?0- zQZC+Vr+4#+|N01APxBg#u#@O;bO~y7Ovf0A6LtG+(&$(T zh;<2Yq)ZTXHSt{ycomcP*Gxzykb4|5kAAZG?gj0N(8I2;%y6LGzw!G}lQ~Hj4ts%z zFumOR3>;Qq7zE^z@YR%LG%@#X!f-93#BZnz7&zvrXlOR`o}wo`Jq5OcPZtQH3Kg7f z)_wFx=)MC7wE5&WC7@HaWi_Av^Bo9a>F8p&I-j4s{8uJd^az;8Y$XI@#w%eNEz{=#M)y&2;jME}!Zdb!zLh56VxD5ULntI8mjJc6fpp17&9rLY;qBSkSz>;BGGILw0+zb( z47+)!!E!aABMXQ%^}t|fzvBTRD**0U5L223hFF%hl=aUbLck1&k^owB=dTBN4Ya-r ziur+z%Lh{a?$NsF-VMW@k*`T9DYFX;LjZAse0mmkZzGpWXeC}_LvlL%`gfTRg+kc# z3lup4h0m_sSHQgMwCXm0zP$e26qS1_Z;}Sm$1b4Rt3big|4Ek$S}=ewy!rp4zXIUy zr3W_kQuw(Zsv05hMN<2s*e5_ts3C#pg#(Bo%0DV6QAt(gQV?Aj4Ho;L%uaok5YUu% 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

    -
    \ No newline at end of file +
    diff --git a/src/app/units/states/groups/unit-groups/unit-groups.component.html b/src/app/units/states/groups/unit-groups/unit-groups.component.html index 73d84dafc6..a3d3f64058 100644 --- a/src/app/units/states/groups/unit-groups/unit-groups.component.html +++ b/src/app/units/states/groups/unit-groups/unit-groups.component.html @@ -1,21 +1,21 @@ -@if (unit.hasGroupwork()) { - + + @if (unit.hasGroupwork()) { - -} @else { -
    - groups + } @else { +
    + groups -

    No Groupwork Enabled

    +

    No Groupwork Enabled

    -

    - There is no group work enabled for this unit. Convenors should create at least one group set - first for groups to be created. This can be found under the groups tab in the unit - administration settings. -

    - -
    -} +

    + There is no group work enabled for this unit. Convenors should create at least one group set + first for groups to be created. This can be found under the groups tab in the unit + administration settings. +

    + +
    + } +
    diff --git a/src/app/units/states/rollover/rollover.component.html b/src/app/units/states/rollover/rollover.component.html index 3c3e6fadab..57aa93020c 100644 --- a/src/app/units/states/rollover/rollover.component.html +++ b/src/app/units/states/rollover/rollover.component.html @@ -64,4 +64,4 @@ - \ No newline at end of file + From 504a48ef08b82b9e4b160f2e15ea424dbf8967b4 Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Wed, 26 Aug 2026 01:26:58 +1000 Subject: [PATCH 1484/1531] fix(visualisations): lift two contrast values above WCAG AA contrastingTextColor left the always-rendered Awaiting Feedback card at 4.44:1, under the 4.5:1 AA wants for normal text. The dark foreground moves to #000000 and the dark-contrast divisor now matches it. The hidden-series legend pill fell to 2.97:1 while still being an interactive control, which misses the 3:1 in 1.4.11. It uses an explicit dimmed state rather than an opacity. Hiding a series zeroed its values instead of removing it, so the pill read as off while the chart still drew the entry. Hidden series are filtered out of the data. The clipping guard asserted a removed class string, so it could not fail for the right reason. It reads computed maxHeight and overflow instead. --- .../progress-dashboard.component.spec.ts | 33 +++++++-- .../progress-burndown-chart.component.html | 6 +- .../progress-burndown-chart.component.scss | 3 +- .../progress-burndown-chart.component.spec.ts | 21 ++++++ .../progress-burndown-chart.component.ts | 67 ++++++++++++------- .../task-visualisation.component.spec.ts | 26 +++++++ .../task-visualisation.component.ts | 8 ++- 7 files changed, 126 insertions(+), 38 deletions(-) diff --git a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts index e3f280b28c..d4c2cc655f 100644 --- a/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/directives/progress-dashboard/progress-dashboard.component.spec.ts @@ -137,15 +137,34 @@ describe('ProgressDashboardComponent', () => { const cardTitles = Array.from(host.querySelectorAll('mat-card-title')); const burndownCard = cardTitles .find((title) => title.textContent.trim() === 'Progress Burndown') - ?.closest('mat-card'); + ?.closest('mat-card') as HTMLElement; const statusCard = cardTitles .find((title) => title.textContent.trim() === 'Task Statuses') - ?.closest('mat-card'); - const burndownContent = burndownCard?.querySelector('mat-card-content'); - - expect(burndownCard?.classList.contains('max-h-[600px]')).toBe(false); - expect(statusCard?.classList.contains('max-h-[600px]')).toBe(false); - expect(burndownContent?.classList.contains('overflow-hidden')).toBe(false); + ?.closest('mat-card') as HTMLElement; + const burndownContent = burndownCard?.querySelector('mat-card-content') as HTMLElement; + + // jsdom loads no stylesheets and lays nothing out, so every element measures 0 high + // and a utility class never reaches getComputedStyle. The computed pair catches a cap + // set inline or in the component styles, and the class scan covers the utility route + // the regression actually took, for any height cap rather than the one literal value. + const clipping = (element: HTMLElement) => { + const computed = getComputedStyle(element); + return { + maxHeight: computed.maxHeight, + overflowY: computed.overflowY, + clippingClasses: Array.from(element.classList).filter((name) => + /^max-h-|^overflow-(y-)?hidden$/.test(name), + ), + }; + }; + const uncapped = {maxHeight: 'none', overflowY: 'visible', clippingClasses: []}; + + expect(burndownCard).toBeTruthy(); + expect(statusCard).toBeTruthy(); + expect(burndownContent).toBeTruthy(); + expect(clipping(burndownCard)).toEqual(uncapped); + expect(clipping(statusCard)).toEqual(uncapped); + expect(clipping(burndownContent)).toEqual(uncapped); }); it('renders fabricated unit peer progress only while demo mode is enabled', () => { diff --git a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html index f445e22ef7..4c6914b24b 100644 --- a/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html +++ b/src/app/visualisations/progress-burndown-chart/progress-burndown-chart.component.html @@ -21,13 +21,13 @@
    - @if (data.length > 0) { + @if (temp.length > 0) {
    - @for (series of data; track series.name; let index = $index) { + @for (series of temp; track series.name; let index = $index) {
    - - {{ project.status }} + + Project status: {{ project.status }}
    @@ -23,7 +23,11 @@

    {{ project.title }}

    } - + Open project diff --git a/src/app/common/project-card/project-card.component.scss b/src/app/common/project-card/project-card.component.scss index d32a89c167..e90278716d 100644 --- a/src/app/common/project-card/project-card.component.scss +++ b/src/app/common/project-card/project-card.component.scss @@ -38,6 +38,18 @@ white-space: nowrap; } +.project-card__status-label { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + .project-card__summary, .project-card__description { margin: 0; @@ -62,4 +74,4 @@ .project-card__status { align-self: flex-start; } -} \ No newline at end of file +} diff --git a/src/app/common/project-card/project-card.component.spec.ts b/src/app/common/project-card/project-card.component.spec.ts index 5342acfc3d..5d8a798c81 100644 --- a/src/app/common/project-card/project-card.component.spec.ts +++ b/src/app/common/project-card/project-card.component.spec.ts @@ -43,7 +43,13 @@ describe('ProjectCardComponent', () => { expect(link).toBeTruthy(); expect(link.getAttribute('href')).toBe('/projects/cpd-f02'); - expect(link.getAttribute('aria-label')).toBe('Open project details'); + expect(link.getAttribute('aria-label')).toBe('Open Cross-Project Dashboard project details'); + }); + + it('should expose the project status to assistive technology', () => { + const status: HTMLSpanElement = fixture.nativeElement.querySelector('.project-card__status'); + + expect(status.textContent.replace(/\s+/g, ' ').trim()).toBe('Project status: In progress'); }); it('should handle missing optional fields', () => { @@ -61,5 +67,8 @@ describe('ProjectCardComponent', () => { expect(text).toContain('Sample Project'); expect(text).toContain('Completed'); expect(text).toContain('Core details are still displayed.'); + + const link: HTMLAnchorElement = fixture.nativeElement.querySelector('a'); + expect(link.getAttribute('aria-label')).toBe('Open Sample Project project details'); }); }); diff --git a/src/app/common/project-card/project-card.component.ts b/src/app/common/project-card/project-card.component.ts index fa86b34983..89e0704e66 100644 --- a/src/app/common/project-card/project-card.component.ts +++ b/src/app/common/project-card/project-card.component.ts @@ -17,8 +17,4 @@ export interface ProjectCardData { }) export class ProjectCardComponent { @Input() project!: ProjectCardData; - - get hasOptionalDetails(): boolean { - return !!this.project?.unitCode || !!this.project?.description; - } } From 85f86b7368b7c7faf04dbae2f6f31607c65f0a32 Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Sun, 23 Aug 2026 22:27:44 +1000 Subject: [PATCH 1488/1531] docs(cpd): document sizing investigation --- docs/cpd-sizing-investigation.md | 26 +++++++++---------- .../cpd-sizing-investigation/README.md | 15 ++++++++--- .../cpd-sizing-investigation/SHA256SUMS | 4 +-- .../source-comparison.txt | 4 +-- .../cpd-sizing-investigation/verification.txt | 17 +++++++----- 5 files changed, 39 insertions(+), 27 deletions(-) diff --git a/docs/cpd-sizing-investigation.md b/docs/cpd-sizing-investigation.md index 3c28d96413..54192f0175 100644 --- a/docs/cpd-sizing-investigation.md +++ b/docs/cpd-sizing-investigation.md @@ -8,7 +8,7 @@ Status: Investigation complete. An initial responsive sizing adjustment was impl This report explains why the Cross-Project Dashboard (CPD) became noticeably larger when its 10.x feature implementation was moved to the 11.x codebase. It records the reproduction, affected dimensions, source and dependency history, existing remediation, remaining limitations, and implementation guidance. -This investigation does not change CPD production code, dashboard behavior, or the implementation completed by CPD-Q04. Two unit-task editor files receive mechanical, behavior-neutral formatting because the target branch's existing warnings prevented the required lint check from passing. +This investigation does not change CPD production code, dashboard behavior, or the implementation completed by CPD-Q04. The docs-only replacement branch contains only this report and its evidence artifacts; it changes no source or configuration files. ## Finding @@ -34,7 +34,8 @@ A secondary height issue has the same migration boundary. Commit [`edab0928c`](h | 11.x CPD reintroduction | [`2c6d2786e`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/2c6d2786e) | `11.0.0-45`, no Bootstrap, Angular Material 22.0.2, Tailwind 4.3.1 | Reintroduced the legacy class values after the repository-wide rescaling. | | 11.x before CPD-Q04 | [`b9386055`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/b9386055) | 11.x | Reproduction baseline immediately before the responsive sizing adjustment. | | CPD-Q04 implementation | [`854f9ce9b`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/854f9ce9ba5f100b0425996c3f5d7e248faa6b32) | 11.x | Existing production remediation by SandilBandara in PR #34. | -| Current shared feature | [`53f1c5532`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/53f1c5532eefc75cadf7834748a5a85c2bc6b3e8) | 11.x | Investigation target and PR base, `feature/cross-unit`. | +| Investigation snapshot | [`53f1c5532`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/53f1c5532eefc75cadf7834748a5a85c2bc6b3e8) | 11.x | Source snapshot used for the measurements and original investigation. | +| Docs-only replacement base | [`9962e7ea1`](https://github.com/ontrack-features-t2-2026/doubtfire-web/commit/9962e7ea171a2bf6d7a12be50874fa5c7ee77e21) | 11.x | Current `feature/cross-unit` base used to re-home the report. The relevant sizing classes are unchanged from the investigation snapshot. | ## Reproduction @@ -114,21 +115,20 @@ The affected legacy-derived sizing values span three CPD templates. [`f-cross-dashboard.component.html`](../src/app/dashboard/f-cross-dashboard.component.html): -- Line 3: fluid unit-scope selector with a 256 px maximum. -- Line 50: fixed horizontal card strip with 32 px gaps, 64 px side padding, and intentional horizontal scrolling. -- Line 52: 512 px fixed unit card. -- Line 72: 224 px search field. -- Lines 80 and 91: Angular Material icon buttons. Their larger accessible control footprints are a secondary header-space constraint and should not be globally reduced to solve this local issue. +- The unit-scope selector is fluid with a 256 px maximum. +- The fixed horizontal card strip has 32 px gaps, 64 px side padding, and intentional horizontal scrolling. +- The fixed unit card is 512 px and its task-search field is 224 px. +- The sort and filter controls use Angular Material icon buttons. Their larger accessible control footprints are a secondary header-space constraint and should not be globally reduced to solve this local issue. [`dashboard-list-item.component.html`](../src/app/dashboard/list-item/dashboard-list-item.component.html): -- Lines 2 and 12: `mr-6`, `ml-2`, and `gap-4` row spacing. -- Lines 2 and 3: `w-4` task rail and `py-4` row padding. -- Lines 14 and 15: `size-8` comment badge and `text-xl` badge text. +- `mr-6`, `ml-2`, and `gap-4` control row spacing. +- `w-4` controls the task rail and `py-4` controls row padding. +- `size-8` and `text-xl` control the comment badge and its text. [`expanded-list-item.component.html`](../src/app/dashboard/list-item/expanded-list-item/expanded-list-item.component.html): -- Lines 2, 3, 5, and 10: `mr-6`, `w-4`, `pb-4`, `pt-2`, and `gap-2` expanded-row spacing. +- `mr-6`, `w-4`, `pb-4`, `pt-2`, and `gap-2` control expanded-row spacing. Related history and context: @@ -169,5 +169,5 @@ No further production change is made by this investigation branch. Any follow-up - Verified the Bootstrap removal commit and its explicit 60 percent rescaling rationale. - Calculated the relevant rem-to-pixel values and one-card containment thresholds. - Reviewed privacy-safe evidence at the specified desktop, tablet, and phone widths. -- Confirmed that this branch changes no CPD behavior; its only source changes are the formatter's mechanical lint cleanup in two unit-task editor files. -- Ran the repository lint, typecheck, full test, and production build checks recorded in the PR. +- Confirmed that the docs-only replacement changes no source, configuration, or CPD behavior. +- Ran the repository lint, typecheck, full test, and production build checks recorded with the evidence. diff --git a/docs/evidence/cpd-sizing-investigation/README.md b/docs/evidence/cpd-sizing-investigation/README.md index be6c419054..d451f8dfda 100644 --- a/docs/evidence/cpd-sizing-investigation/README.md +++ b/docs/evidence/cpd-sizing-investigation/README.md @@ -1,6 +1,8 @@ # CPD sizing investigation evidence -Date: 2026-08-23 +Evidence captured: 2026-08-23 + +Docs-only replacement prepared: 2026-08-27 Report: [`docs/cpd-sizing-investigation.md`](../../cpd-sizing-investigation.md) @@ -13,7 +15,8 @@ This folder contains the evidence for `CPD - Investigate sizing issue`. All visi - CPD reintroduction on 11.x: `2c6d2786e9484c57436099d25281aa45fa89453c`. - 11.x before the responsive adjustment: `b9386055`. - CPD-Q04 responsive adjustment: `854f9ce9ba5f100b0425996c3f5d7e248faa6b32`. -- Current `feature/cross-unit` baseline: `53f1c5532eefc75cadf7834748a5a85c2bc6b3e8`. +- Investigation snapshot: `53f1c5532eefc75cadf7834748a5a85c2bc6b3e8`. +- Docs-only replacement base: `9962e7ea171a2bf6d7a12be50874fa5c7ee77e21`. ## Deterministic comparison set @@ -38,7 +41,13 @@ Supporting files: - `verification.txt` records the passing repository checks. - `SHA256SUMS` provides integrity checks for every evidence artifact. -The harness images are deterministic layout reconstructions, not signed-in application screenshots. This limitation is intentional so the root-scale comparison is repeatable and privacy-safe. +Verify the evidence integrity from the repository root: + +```sh +cd docs/evidence/cpd-sizing-investigation && shasum -a 256 -c SHA256SUMS +``` + +The harness images are deterministic layout reconstructions, not signed-in application screenshots. This limitation is intentional so the root-scale comparison is repeatable and privacy-safe. The exported raster dimensions may exclude browser chrome or scrollbar pixels, so `measurements.txt` is the authoritative record of the captured DOM client and scroll widths. ## CPD-Q04 application capture set diff --git a/docs/evidence/cpd-sizing-investigation/SHA256SUMS b/docs/evidence/cpd-sizing-investigation/SHA256SUMS index 8874c85089..2c7c055543 100644 --- a/docs/evidence/cpd-sizing-investigation/SHA256SUMS +++ b/docs/evidence/cpd-sizing-investigation/SHA256SUMS @@ -17,6 +17,6 @@ da166e582fc08c6dec2c9c8fdadf8fed457e1821b2aed39f6236d0229ab5ba28 after-390x900. 96e810d2ff565123384a962e61be7f462204bedb107951c97a29a64ffd9fe920 before-768x900.png 4b3fdcd12b68fc6a44798f4f58a17881d6c4d30a6c060faec2a46c7bab93486b before-390x900.png 14f2b26c5c0d5dfc9a1a528fdbdaa5c404c68fe5b8b18f76c70c5d734136120e measurements.txt -7a391e9326ed30e25654752199168107eb1bdb202afe56459f8b830ba91abea9 source-comparison.txt +e6b3318cadba254378c1ca8d61f167eb22e000712c3882697d9f86282861446f source-comparison.txt ae8ccfaf88912e57259eac2fbe9236382b559493625ad0a63e654917d7e04744 synthetic-cpd-comparison.html -56995cda119a5e7886c92abaed7dab320be719cd1af4fd3cfcde4281eb71d2ed verification.txt +a1e395fc9c9a76e89815d6064f73ebed35a1152440ab8f414b2c29b4abed0302 verification.txt diff --git a/docs/evidence/cpd-sizing-investigation/source-comparison.txt b/docs/evidence/cpd-sizing-investigation/source-comparison.txt index 9fb3ccbb0a..cacb26e741 100644 --- a/docs/evidence/cpd-sizing-investigation/source-comparison.txt +++ b/docs/evidence/cpd-sizing-investigation/source-comparison.txt @@ -30,8 +30,8 @@ commit: 2c6d2786e9484c57436099d25281aa45fa89453c finding: copied the legacy CPD utility classes after Bootstrap had been removed, reintroducing the unscaled w-[34rem], w-64, px-16, gap-8, gap-4, and p-4 values -Current feature/cross-unit -commit: 53f1c5532eefc75cadf7834748a5a85c2bc6b3e8 +Current feature/cross-unit docs-only replacement base +commit: 9962e7ea171a2bf6d7a12be50874fa5c7ee77e21 package version: 11.0.0-45 component classes: dashboard strip: flex min-h-0 flex-1 flex-row gap-8 overflow-x-auto px-16 pb-4 diff --git a/docs/evidence/cpd-sizing-investigation/verification.txt b/docs/evidence/cpd-sizing-investigation/verification.txt index 70f71c5ca6..e21fdc7bac 100644 --- a/docs/evidence/cpd-sizing-investigation/verification.txt +++ b/docs/evidence/cpd-sizing-investigation/verification.txt @@ -1,7 +1,7 @@ -CPD sizing investigation verification -Date: 2026-08-23 +CPD sizing investigation docs-only replacement verification +Date: 2026-08-27 Branch: docs/cpd-sizing-investigation -Target: feature/cross-unit +Target: feature/cross-unit at 9962e7ea171a2bf6d7a12be50874fa5c7ee77e21 1. npm run lint Result: PASS @@ -13,7 +13,7 @@ Target: feature/cross-unit 3. npm run test:ci Result: PASS - Detail: 60 test files passed. 119 tests passed and 1 existing test is marked todo. + Detail: 68 test files passed. 168 tests passed and 1 existing test is marked todo. 4. CI=true npm run build -- --no-progress Result: PASS @@ -23,6 +23,9 @@ Target: feature/cross-unit Result: PASS Detail: No whitespace errors. -The initial lint run exposed 25 Prettier warnings already present on the shared target branch in -unit-task-editor.component.html and unit-task-editor.component.ts. The formatter made mechanical -style-only changes to those two files. No behavior was changed. +6. Evidence integrity + Result: PASS + Detail: Every file listed in SHA256SUMS matches its recorded digest. + +The replacement diff contains only 25 files under docs/. It changes no application source, +configuration, dependency, or workflow file. From 5255c271778643cd6f972e3bce1d83ecdb2e292d Mon Sep 17 00:00:00 2001 From: maplefoxgit Date: Thu, 27 Aug 2026 20:00:24 +1000 Subject: [PATCH 1489/1531] fix(dashboard): align merged closure coverage --- src/app/api/models/project.ts | 28 ++++++++++++------- .../project-dashboard.component.spec.ts | 4 +++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/app/api/models/project.ts b/src/app/api/models/project.ts index 48c2720701..d786b963fb 100644 --- a/src/app/api/models/project.ts +++ b/src/app/api/models/project.ts @@ -24,6 +24,11 @@ import {Engagement} from './engagement'; import {StaffNote} from './staff-note'; import {TaskOutcomeAlignment} from './task-outcome-alignment'; +export interface ProjectBurndownSeries { + key: string; + values: [timestamp: number, remaining: number][]; +} + export class Project extends Entity { public id: number; public unit: Unit; @@ -52,7 +57,7 @@ export class Project extends Entity { }[]; public orderScale: number; - public burndownChartData: {key: string; values: number[]}[]; + public burndownChartData: ProjectBurndownSeries[]; public readonly taskCache: EntityCache = new EntityCache(); public readonly staffNoteCache: EntityCache = new EntityCache(); public readonly engagementCache: EntityCache = new EntityCache(); @@ -398,15 +403,15 @@ export class Project extends Entity { } public refreshBurndownChartData(): void { - const result: {key: string; values: number[]}[] = []; + const result: ProjectBurndownSeries[] = []; // Setup the dictionaries to contain the keys and values // key = series name // values = array of [ x, y ] values - const projectedResults = {key: 'Projected', values: []}; - const targetTaskResults = {key: 'Target', values: []}; - const doneTaskResults = {key: 'To Submit', values: []}; - const completeTaskResults = {key: 'To Complete', values: []}; + const projectedResults: ProjectBurndownSeries = {key: 'Projected', values: []}; + const targetTaskResults: ProjectBurndownSeries = {key: 'Target', values: []}; + const doneTaskResults: ProjectBurndownSeries = {key: 'To Submit', values: []}; + const completeTaskResults: ProjectBurndownSeries = {key: 'To Complete', values: []}; result.push(targetTaskResults); result.push(projectedResults); @@ -496,7 +501,7 @@ export class Project extends Entity { dates.forEach((date) => { // get the target values - those from the task definitions // amount remaining is the sum of all tasks due after the date - const targetVal = [ + const targetVal: ProjectBurndownSeries['values'][number] = [ date.getTime(), (targetTasks .filter((taskDef) => taskDef.targetDate >= date) @@ -505,7 +510,7 @@ export class Project extends Entity { ]; // get the done values - those done up to today, or the end of the unit - const doneVal = [ + const doneVal: ProjectBurndownSeries['values'][number] = [ date.getTime(), (total - doneTasks @@ -516,7 +521,7 @@ export class Project extends Entity { ]; // get the completed values - those signed off - const completeVal = [ + const completeVal: ProjectBurndownSeries['values'][number] = [ date.getTime(), (total - completedTasks @@ -527,7 +532,10 @@ export class Project extends Entity { ]; // projected value is based on amount done - const projectedVal = [date.getTime(), projectedRemaining / total]; + const projectedVal: ProjectBurndownSeries['values'][number] = [ + date.getTime(), + projectedRemaining / total, + ]; // add one week's worth of completion data projectedRemaining -= completionRate; diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts index 1ae1ac81ef..ceb5795b59 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.spec.ts @@ -324,6 +324,10 @@ describe('ProjectDashboardComponent rendered by its host', () => { providers: [ {provide: UserService, useValue: {}}, {provide: ProjectService, useValue: {get: projectGet}}, + { + provide: TaskService, + useValue: {taskSubmissionCompleted$: new Subject()}, + }, {provide: UnitService, useValue: {get: unitGet}}, {provide: GlobalStateService, useValue: {setView: vi.fn()}}, { From 070840c83419d2adf432ae06fcb62b7ed74668e5 Mon Sep 17 00:00:00 2001 From: Clupai8o0 Date: Thu, 27 Aug 2026 09:56:42 +1000 Subject: [PATCH 1490/1531] docs(theme): define the light, dark and system theme contract Adds docs/theme/THEME-CONTRACT.md, the contract THM-F01 through THM-M05 build against. It fixes the three stored preference states and the two resolved ones, the data-ot-theme marker on , the ontrack.theme.preference key and its allowlist, the semantic --ot-* token set with a light and a dark value for every role, the split between fixed brand colour and theme-aware colour, the WCAG AA floor, and the rules for no-flash startup, live operating-system changes, reduced motion and print. The feature is specified in two phases so that every card on the board has something to build. Phase one stores the preference in localStorage. Phase two, section 6.2, adds the user account as a second store and settles how the two reconcile: local is always the boot store, the account carries the stored preference and never the resolved theme, conflicts go to whichever side was written last, a device with no local value adopts the account value, and the sync never blocks startup. Section 10 configures the Tailwind dark variant against the same root marker rather than banning the prefix, because an unconfigured darkMode is not an absent dark variant, it is one that silently follows the operating system and ignores the stored preference. Section 2 audits the current stylesheet, because THM-D01 has not started and there was no register to work from. Every count has the command printed beside it and Appendix B collects them for re-running. Every contrast ratio is computed with the formula in Appendix A rather than estimated, and all seventy-five were recomputed in one pass before this was handed over. The audit found that eight of thirteen distinct status chip colour pairs already fail AA in light mode, and that task status colour has two sources of truth that agree by hand. Section 8.1 lifts every failing pair to 4.5:1 while leaving thirteen of fifteen fills alone. No code, no styles and no configuration change. The document stays a draft until the four approvals in section 17 are recorded. --- docs/theme/THEME-CONTRACT.md | 1313 ++++++++++++++++++++++++++++++++++ 1 file changed, 1313 insertions(+) create mode 100644 docs/theme/THEME-CONTRACT.md diff --git a/docs/theme/THEME-CONTRACT.md b/docs/theme/THEME-CONTRACT.md new file mode 100644 index 0000000000..39f1bbf84d --- /dev/null +++ b/docs/theme/THEME-CONTRACT.md @@ -0,0 +1,1313 @@ +# OnTrack theme contract + +**Ticket:** THM-D02 · **Status:** Draft, awaiting approval · **Applies to:** `doubtfire-web` + +This is the contract every contributor works to before anyone edits styles for Light/Dark/System. +It fixes the theme states, the semantic token names, how the preference is stored, the +accessibility floor, and what the implementation tickets must prove. It does not implement +anything. + +Read sections 4, 6, 7 and 10 before writing any style code. The rest is why. + +--- + +## 1. Missing inputs, and what is provisional because of them + +THM-D02 was scheduled after two tickets that have not started. + +| Ticket | Owner | What it was meant to hand over | State | +| ------- | ----------------- | -------------------------------------------------- | ----------- | +| THM-D01 | Owen Brian Costin | Theme audit and dark-mode blueprint | Not started | +| MG-05 | Unassigned | CSS style guide (naming, layering, file ownership) | Not started | + +So the audit in section 2 was done from scratch against the working tree at +`origin/11.0.x`. Every number in it comes from a command that is printed next to it, and every +statement about how OnTrack styles itself today comes from a file that was opened. + +Three things stay provisional until those two tickets land. + +| Provisional | Why | Who settles it | +| --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | +| The token **naming prefix** `--ot-*` and the `--ot-color-* / --ot-status-* / --ot-chart-*` grouping | MG-05 owns naming. `--ot-` was chosen because it collides with nothing in the tree today (section 2.6). | MG-05 | +| The **file layout** in section 10 (`src/styles/tokens/_light.scss`, `_dark.scss`) | MG-05 owns which layer may declare a colour. | MG-05 | +| The **per-page migration order** for THM-M01 to THM-M04 | THM-D01's audit was meant to rank pages by risk. Section 2.5 lists the hard surfaces but not an order. | THM-D01, and THM-M05 for the FlexLayout sequencing | + +Everything else here — states, storage, tokens, values, accessibility floor, test list — is +proposed as final and is not waiting on either ticket. + +--- + +## 2. Audit of the current stylesheet, done for this ticket + +Commands were run from the repo root on branch `docs/theme-contract`, cut from `origin/11.0.x`. + +### 2.1 Versions + +`package.json`: Angular `^22.0.3`, Angular Material `^22.0.2`, Tailwind via +`@tailwindcss/postcss ^4.3.2`, tests on `vitest ^4.1.9` through the +`@angular/build:unit-test` builder. Node `>=22.22.3`. + +The Thoth Tech handover says Angular 17 and Karma. Both are stale. Do not plan against them. + +### 2.2 How Material is themed today + +`angular.json` loads two global stylesheets, in this order: `src/theme.scss`, then +`src/styles.scss`. + +`src/theme.scss` builds a **Material 2** theme. It defines three palettes by hand +(`$md-formatif` from `#3939ff`, an accent, a warn), calls `mat.m2-define-light-theme(...)`, then +`@include mat.all-component-themes($theme)`. There is one theme and it is light. The file defines +no dark theme at all — line 162 only reads `is-dark` back off the light config — and there is no +`.dark-theme` class anywhere in the tree. The repo's only `$dark-theme` is at +`src/styles/m3-theme.scss:158`, in the file nothing imports. + +`src/styles/m3-theme.scss` **already exists**, is 177 lines, and is generated +(`// This file was generated by running 'ng generate @angular/material:m3-theme'`). It defines +**both** `$light-theme` and `$dark-theme` with `theme-type: light` / `theme-type: dark`, +`use-system-variables: true` and `system-variables-prefix: sys`. + +It is not used. `src/styles.scss` lines 24-25 have it commented out: + +```scss +// This is the new Angular Material 3 theme file which we will migrate to +// @use './styles/m3-theme.scss'; +``` + +``` +$ grep -rIn -- "--sys-" src/ | wc -l +0 +``` + +Nothing consumes it. Turning that comment into code is **not** the plan — see section 3. + +`mat.app-background()` and `mat.elevation-classes()` are each included twice, once in +`theme.scss` and again in `styles.scss`. Harmless duplication today, worth a cleanup ticket, not +this one. + +### 2.3 The colours the app actually paints + +Because the M2 light theme is what runs, the base surfaces come from Material's own light +palettes at `node_modules/@angular/material/core/m2/_palette.scss`: + +| Role | M2 source | Value | +| -------------- | ------------------------------------------------------ | --------------------- | +| page | `$light-theme-background-palette.background` = grey 50 | `#fafafa` | +| card, dialog | `.card` / `.dialog` | `#ffffff` | +| app bar | grey 100 | `#f5f5f5` | +| body text | `rgba(black, 0.87)` | flattens to `#212121` | +| secondary text | `rgba(black, 0.54)` | flattens to `#757575` | +| disabled text | `rgba(black, 0.38)` | flattens to `#9e9e9e` | +| dividers | `rgba(black, 0.12)` | flattens to `#e0e0e0` | + +Those four flattened values land exactly on M2 grey 900 / 600 / 500 / 300. That is not a +coincidence, it is how the palette was built, and it is why the light column in section 7 is a +derivation and not an invention. + +### 2.4 Hard-coded colour, measured + +``` +$ grep -rIoE '#[0-9a-fA-F]{3,8}\b' src --include='*.scss' | wc -l +350 +$ grep -rIlE 'rgba?\(|hsla?\(' src --include='*.scss' | wc -l +20 +$ find src -name '*.scss' | wc -l +180 +$ grep -rIoh '!important' src --include='*.scss' | wc -l +63 +``` + +238 of the 350 hex literals are in three files that are palettes by design +(`m3-theme.scss` 107, `theme.scss` 84, `task-status-colors.scss` 47). Of the rest, **105 are +scattered across component SCSS under `src/app`**, 6 sit in other shared partials and 1 is in +`styles.scss`. + +``` +$ grep -rIoE '#[0-9a-fA-F]{3,8}\b' src/app --include='*.scss' | wc -l +105 +$ grep -rIlE '#[0-9a-fA-F]{3,8}|rgba?\(|hsla?\(' src/app --include='*.scss' | wc -l +36 +$ grep -rIlE 'color|background|border|fill|stroke' src/app --include='*.scss' | wc -l +48 +$ find src/app -name '*.scss' | wc -l +169 +``` + +So **48 of the 169 component stylesheets under `src/app` declare a colour, a border or a fill**, +against 36 that hold a hex or an `rgba()`. The wider grep is the honest one for sizing a +migration: it also catches `stroke: white`, `border-radius: $border-radius-base` and a +`task-status-color($status)` call, none of which contain a literal but all of which a theme has +to account for. 48 is the number to burn down, 105 is the number of literals inside it. + +Templates carry colour too, as Tailwind arbitrary values: + +``` +$ grep -rIhoE '\b(text|bg|border)-\[#[0-9a-fA-F]{3,8}\]' src --include='*.html' --include='*.ts' \ + | sort | uniq -c | sort -rn + 5 text-[#c5c5c5] 3 bg-[#da532c] 2 text-[#969696] 2 bg-[#e7e7ff] + 1 text-[#fab143] 1 text-[#da532c] 1 text-[#9696969d] 1 text-[#2c2c2c] + 1 bg-[#fab143] 1 bg-[#43a047] 1 bg-[#333] 1 bg-[#126352] +``` + +Nine files. That is the whole of the "someone will invent a new grey" risk, made concrete. + +### 2.5 Status, urgency and the hard surfaces + +**Task status colour has two sources of truth.** +`src/styles/common/task-status-colors.scss` holds a Sass map of 15 statuses with `base`, `dark`, +`light` and `fore`. `src/app/api/models/task-status.ts` holds `STATUS_COLORS`, a second map of +the same 15 hex values in TypeScript. Each file carries a comment telling you to keep it in step +with the other, and the TS one still points at `task-status-colors.less`, a file that no longer +exists. The two maps **do agree today** — all 15 pairs match, checked value by value. They agree +by hand, not by construction. + +**Due-date urgency is inline in one template.** +`src/app/units/task-viewer/directives/unit-task-list/unit-task-list.component.html:264-267`: + +```html +[ngClass]="{ 'text-[#da532c]': task.daysUntilDueDate() <= 0, 'font-normal text-[#fab143]': +task.daysUntilDueDate() > 0 && task.daysUntilDueDate() < 11, 'font-normal text-gray-500': +task.daysUntilDueDate() > 11, }" +``` + +Three urgency bands, no named token, one of them a Tailwind default grey. + +**Surfaces THM-M04 will fight**, all confirmed present in `package.json` and in use: + +| Surface | Library | Why it is hard | +| --------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | +| Code editors | `monaco-editor`, `ngx-monaco-editor-v2-alternative`, `@ngstack/code-editor` | Monaco takes a theme **name**, not CSS. Seven call sites pin `theme: 'vs'` or `'vs-dark'` literally. | +| Charts | `@swimlane/ngx-charts`, `d3` | Colour arrives as a JS `domain` array, not CSS. Two hard-coded domains found. | +| PDF / portfolio | `ng2-pdf-viewer` | Renders into a canvas. CSS cannot reach it; a filter inversion is the only lever. | +| Calendar | `angular-calendar` (CSS imported raw in `styles.scss`) | Third-party CSS with its own light palette. | +| Gantt | `@worktile/gantt` (SCSS loaded in `angular.json`) | Same. | +| Terminal output | `ansi-to-html` | Emits inline `style="color:#..."` from ANSI codes. | +| Emoji picker | `@ctrl/ngx-emoji-mart` (`picker.css`) | Ships a `darkMode` input; `task-comment-composer.component.html:5` currently hard-codes `[darkMode]="false"`. | + +The two chart domains, verbatim: + +```ts +// progress-burndown-chart.component.ts:60 +domain: ['#AAAAAA', '#777777', '#0079d8', '#E01B5D', 'transparent'], +// project-progress-gauge.component.ts:41 +domain: ['#5AA454', '#E44D25', '#CFC0BB', '#7aa3e5', '#a8385d', '#aae3f5'], +``` + +### 2.6 What does not exist yet + +``` +$ grep -rIn "prefers-color-scheme" src/ | wc -l +0 +$ grep -rIn "color-scheme" src/ | wc -l +0 +$ grep -rIn "@media print" src/ | wc -l +0 +$ grep -rIn "prefers-reduced-motion" src/ | wc -l +0 +``` + +No dark preference is stored anywhere. `src/index.html` sets a fixed +`` and `src/manifest.webmanifest` sets +`"theme_color": "#3939ff"`, `"background_color": "#ffffff"`. `` is +the only body class. + +CSS custom properties are barely used, which is why the token namespace is free: + +``` +$ grep -rIhoE '^\s*--[a-z0-9-]+\s*:' src --include='*.scss' | tr -d ' ' | sort | uniq -c + 3 --background-gray: 2 --mat-chip-disabled-label-text-color: + 1 --status-chip-bg: 1 --mat-tab-container-height: + 1 --mat-progress-bar-track-height: 1 --mat-progress-bar-active-indicator-height: +``` + +Focus handling is a live risk: 11 `outline: none` / `outline: 0` declarations against only 7 +`:focus-visible` rules. + +### 2.7 The accessibility problem that already ships + +Status chips pair a `base` fill with a `fore` foreground of `#fff` or `#444`. Measured (method +and script in Appendix A): + +| Status | Fill | Foreground | Ratio | AA 4.5:1 | +| ------------------------------------- | --------- | ---------- | ----- | -------- | +| working-on-it | `#eb8f06` | `#ffffff` | 2.48 | **fail** | +| complete | `#5bb75b` | `#ffffff` | 2.51 | **fail** | +| discuss | `#31b0d5` | `#ffffff` | 2.53 | **fail** | +| attention-required | `#f1814d` | `#ffffff` | 2.63 | **fail** | +| need-help | `#a48fce` | `#ffffff` | 2.84 | **fail** | +| feedback-exceeded | `#d46b54` | `#ffffff` | 3.48 | **fail** | +| demonstrate | `#428bca` | `#ffffff` | 3.63 | **fail** | +| ready-for-feedback | `#0079d8` | `#ffffff` | 4.44 | **fail** | +| fail, time-exceeded | `#d93713` | `#ffffff` | 4.66 | pass | +| not-started | `#cccccc` | `#444444` | 6.06 | pass | +| fix-and-resubmit, assess-in-portfolio | `#f2d85c` | `#444444` | 6.84 | pass | +| rediscuss | `#126352` | `#ffffff` | 7.16 | pass | +| redo | `#804000` | `#ffffff` | 7.92 | pass | + +Eight of thirteen distinct pairs fail AA today, in light mode, before dark mode exists. The +secondary text colour has the same problem: `#757575` on a `#ffffff` card is 4.61 and passes, but +on the `#fafafa` page it is **4.41** and fails. + +This is why section 7 does not simply copy the current values forward. + +--- + +## 3. Material theming approach + +**Decision: a staged bridge. Keep the M2 theme rendering the components, add an independent +semantic token layer on top now, and move Material onto tokens per component group later.** + +### The three options + +| Option | What it means | Verdict | +| ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| A. Stay on M2, add a second `m2-define-dark-theme` under a class | One extra `@include mat.all-component-colors($dark)` in a `.dark` block | Rejected. Roughly doubles emitted CSS, gives no token vocabulary for the 112 loose component hexes, and locks us further into an API Angular is winding down. | +| B. Uncomment `m3-theme.scss` and switch wholesale | Swap M2 for the generated M3 light and dark themes | Rejected. See below. | +| **C. Staged bridge** | Ship `--ot-*` tokens and the state machine first; migrate Material component groups after | **Chosen.** | + +### Why B is rejected + +`m3-theme.scss` was generated from `#3939FF` and never wired up. Switching to it in one commit +would, in a single PR: change every Material component's density, shape and typography scale at +once; re-map the `warn` palette (M2 `#ef4444`) onto the M3 `error` ramp (`#ba1a1a`); and leave +the 105 component-level hex literals and the 15 status colours untouched and now clashing with a +new set of greys. The failure mode is exactly the one this ticket exists to prevent: several +people fixing different dark greys in parallel. + +It is also not a small change. `mat.define-theme` in `m3-theme.scss` is the older M3 entry point. +The installed Material 22.0.2 exposes a newer one, `mat.theme()`, which supports +`theme-type: color-scheme` and emits `light-dark()` values +(`node_modules/@angular/material/core/tokens/_system.scss:57-82` and `:253`). If we are going to +move Material, we should move to that, not to the generated file as written. That is a separate +sized ticket, not a comment uncomment. + +### What C means concretely + +1. **Now (THM-F01).** `src/theme.scss` is untouched. A new token layer declares `--ot-*` on the + root element for both themes. Nothing Material renders changes. +2. **Now.** New and migrated code reads `--ot-*` only. The 105 loose literals get replaced page + by page (THM-M01 to M04) with no visual change in light mode. +3. **Later, per component group.** Material components are pulled onto the tokens with + `mat.theme-overrides()` or `--mat-*` system variables, one group per PR (buttons, then form + fields, then tables, and so on). Each PR is independently reviewable and revertible. +4. **Later still.** When every group is covered, `theme.scss` shrinks to typography and the M2 + colour include is deleted. + +### Compatibility + +- `--ot-*` custom properties inherit and cascade. They cannot break an M2 rule that does not + reference them, so step 1 is inert by construction. +- `light-dark()` is **not** used in the token layer. Values are written literally under the DOM + marker so the resolved theme is legible in DevTools and does not depend on the browser's + `color-scheme` computation. The `color-scheme` CSS property is still set (section 11) so + scrollbars and form controls follow. +- Tailwind's `important: true` in `tailwind.config.js` means every utility already outranks + Material component CSS. Reading a token through a utility keeps that behaviour, it does not + change it. + +### Rollback + +| Stage failing | Rollback | Blast radius | +| -------------------- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | +| Token layer | Remove the `@use` of the token file. Every `var(--ot-x, )` falls back to its literal. | None, if the fallback rule in section 10 is obeyed. | +| Toggle / persistence | Feature-flag the toggle off. The DOM marker is then never set, and the `:root` block is the light theme. | None. Light mode is the unmarked default by design. | +| One component group | Revert that one PR. | That group only. | +| A migrated page | Revert that one PR. | That page only. | + +**Every `var()` in the token layer's consumers must carry a literal fallback matching today's +light value.** That single rule is what makes rollback free, and it is a review gate. + +--- + +## 4. Theme states + +Two vocabularies. They are not the same set and they are never stored in the same place. + +| | Values | Where it lives | Who writes it | +| --------------------- | ------------------------- | -------------------------------- | ------------------------ | +| **Stored preference** | `light`, `dark`, `system` | `localStorage`, key in section 6 | The user, via the toggle | +| **Resolved theme** | `light`, `dark` | In memory, and on the DOM marker | `ThemeService` only | + +The stored preference is the same three values wherever it is kept. THM-B01 adds a second store +for it on the user account (section 6.2); it does not add a fourth value, a fourth state or a +new resolution rule, so everything below survives phase two unchanged. + +`system` is never a resolved value. It is an instruction meaning _follow +`prefers-color-scheme`_. Anything that needs to know what is on screen reads the resolved +theme. Anything that renders the toggle reads the stored preference, so the toggle can show +three options and highlight `system`. + +Resolution is one line: + +``` +resolved = stored === 'system' ? (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') + : stored +``` + +### State diagram + +```mermaid +stateDiagram-v2 + [*] --> Read: app boot (pre-hydration script) + + Read --> System: key missing + Read --> System: value not in the allowlist + Read --> Light: value = "light" + Read --> Dark: value = "dark" + Read --> System: value = "system" + + state "stored = system" as System { + [*] --> ResolveOS + ResolveOS --> SysLight: prefers-color-scheme is not dark + ResolveOS --> SysDark: prefers-color-scheme is dark + SysLight --> SysDark: OS switches to dark (live) + SysDark --> SysLight: OS switches to light (live) + } + + state "stored = light" as Light + state "stored = dark" as Dark + + Light --> Dark: user picks Dark + Light --> System: user picks System + Dark --> Light: user picks Light + Dark --> System: user picks System + System --> Light: user picks Light + System --> Dark: user picks Dark + + note right of System + resolved = light or dark + OS changes apply live, no reload + end note + note right of Dark + resolved = dark, pinned + OS changes are ignored + end note +``` + +Three rules fall out of the diagram and are testable: + +1. An unreadable, missing or invalid stored value resolves to `system`. Never to a hard `dark`. +2. While stored is `light` or `dark`, OS changes are ignored. The user's explicit choice wins. +3. Changing the OS preference while stored is `system` repaints without a reload. + +--- + +## 5. DOM marker + +**One attribute, on ``, carrying the resolved theme only:** + +```html + +``` + +- Name: `data-ot-theme`. Values: exactly `light` or `dark`. Nothing else is ever written. +- It goes on `document.documentElement`, not ``. `` is + already load-bearing and the pre-hydration script (section 11) runs in ``, before + `` exists. +- **In light mode the attribute is present and set to `light`.** It is not omitted. A selector + should never have to mean "absence of dark". +- A data attribute, not a class, because `` classes are a shared namespace that Angular, + Material and Tailwind all write into, and a stray `.dark` is easy to add by accident. An + attribute with a fixed two-value domain is not. +- Selector form for the token layer, and the only two blocks that may declare a colour value: + +```scss +:root, +:root[data-ot-theme='light'] { + /* light values */ +} + +:root[data-ot-theme='dark'] { + /* dark values */ +} +``` + +The bare `:root` first means the app is correct in light mode even if the script never runs. + +--- + +## 6. Storage + +| Field | Value | +| ------------------- | ---------------------------------------------------------------------------- | +| Key | `ontrack.theme.preference` | +| Allowed values | `light`, `dark`, `system` — exactly these three lowercase ASCII strings | +| Default when absent | `system` | +| Format | A bare string. **Not** JSON, not an object, not a serialised class | +| Scope | `localStorage`, per browser profile and origin. Section 6.2 adds the account | + +The key follows the convention already in the tree: `unit-task-list.component.ts:501-504` writes +`ontrack.unitTaskList.${unitId}.viewPreferences`. Namespace, dot separators, camelCase leaf. + +### 6.1 Validation, and the rule that matters + +```ts +export type ThemePreference = 'light' | 'dark' | 'system'; +const THEME_PREFERENCES: readonly ThemePreference[] = ['light', 'dark', 'system'] as const; +const THEME_STORAGE_KEY = 'ontrack.theme.preference'; + +function isThemePreference(v: unknown): v is ThemePreference { + return typeof v === 'string' && (THEME_PREFERENCES as readonly string[]).includes(v); +} + +function readThemePreference(): ThemePreference { + try { + const raw = localStorage.getItem(THEME_STORAGE_KEY); + return isThemePreference(raw) ? raw : 'system'; + } catch { + return 'system'; // private mode, blocked storage, quota + } +} +``` + +**The stored string is never evaluated as CSS or as code.** It is compared against a fixed +allowlist and then used only to pick one of two literal attribute values. It is never +interpolated into a stylesheet, a `style` attribute, a class name, a selector, an +`innerHTML`, a `Function`, or an `eval`. There is no path from `localStorage` to the CSSOM. + +Any value not in the allowlist — a typo, a stale value from an older build, a string another +tab wrote, a value a user typed into DevTools — falls back to `system` **and is not rewritten**. +Silently overwriting it would hide the fact that something is writing junk to that key. + +The same allowlist governs the write side. `setPreference` takes `ThemePreference`, so an +invalid value cannot be stored through the service at all. + +### 6.2 Cross-device persistence — THM-B01, phase two + +`localStorage` is per browser profile. Sign in on a laptop and on a lab machine and you set the +preference twice. **THM-B01 closes that**, and this section is the contract it builds to, so the +card can be specified now and landed after THM-F01 without reopening anything here. + +The client-only store is not "local forever". It is phase one of two. + +| Phase | Store | Ticket | +| ---------------- | ---------------------------------------- | ------- | +| One, ships first | `localStorage` only | THM-F01 | +| Two, adds to it | `localStorage` **plus** the user account | THM-B01 | + +Phase two **adds** a store. It does not replace one, and it changes nothing in section 4, +section 5 or the startup script. Five rules hold the two stores together. + +**1. Local is always the boot store.** The script in section 11 runs before the app has a +session, so `localStorage` is the only thing it can read. The account value is not reachable at +first paint and must never be waited on, or the no-flash guarantee is gone. Phase two therefore +does not touch startup at all. + +**2. The account stores the preference, never the resolved theme.** A user who picked `system` +has `system` on their account. It never becomes `dark` because their operating system was dark +when they last signed in. Same three values, same allowlist as 6.1, validated again server-side. +This is the rule that keeps section 15's objection answered: the account never learns the user's +OS appearance. + +**3. Conflict is settled by last write, not by store.** Neither side outranks the other. + +- The device writes `ontrack.theme.preference.updatedAt`, an ISO 8601 string, beside the + preference. A **second** key on purpose, so the key section 11 reads stays a bare allowlisted + enum and the boot script never parses a date. +- The API carries the equivalent beside its field. +- Newer wins. On a tie the account value wins, so two devices cannot ping-pong. +- A local timestamp that is missing, unparseable or in the future counts as older, and the + account value is taken. +- The winner is written to **both** sides in the same pass, so one round trip converges them. + +**4. A device that has never set a preference adopts the account value.** Nothing valid in +`localStorage` means nothing to compare, so the account value is adopted, written locally, and +the next boot on that device is flash-free. Until the response lands, that first session follows +`system`. One repaint, on the first session on a new device, is the accepted cost of rule 1. It +is stated behaviour, not a defect for THM-Q01 to raise. + +**5. The sync never blocks and never fails loudly.** A 4xx, a 5xx, an offline device, or a +request still in flight, all leave the local value applied and in charge. The retry is the next +boot. A theme preference is not worth a spinner, a toast or an error state. + +Two further constraints, both review gates. + +- **Sign-out does not clear the key.** It is presentation state, not session state. The next + person on a shared machine sees the previous theme until their own preference arrives, then it + repaints. Clearing it would reintroduce a flash for the common single-user case to fix the rare + shared-machine one. +- **Writes are debounced and only fire on a real change.** Cycling the toggle three times sends + one request. + +What THM-B01 owns and this document does not decide: the field name, whether it hangs off the +user record or a separate preferences table, and the endpoint shape. Those are `doubtfire-api` +decisions made with that repo's reviewers. The three values, the allowlist, last-write-wins, and +"preference not resolved theme" are fixed here and are not THM-B01's to change. + +--- + +## 7. Semantic tokens + +Every one of these is a **role**, not a place. There is no `--ot-dashboard-bg`. If a page needs +a colour that is not here, that is a conversation in the theme thread, not a new hex in a +component stylesheet. + +**Derivation.** The light column is the M2 light theme the app renders today (section 2.3), +flattened where Material used alpha, and darkened in 0.5% HSL lightness steps only where the +current value misses 4.5:1 against the **page** background `#fafafa`, which is the worst case. +The dark column is taken from the neutral and primary ramps in the already-checked-in +`src/styles/m3-theme.scss`, so the dark greys are not invented either, then lifted the same way +where needed. Ratios were computed, not estimated. Appendix A has the script. + +| Token | Role | Light | Dark | Worst-case ratio | +| ---------------------------- | --------------------------------------------------------- | --------- | --------- | --------------------- | +| `--ot-color-page` | Page background behind everything | `#fafafa` | `#131316` | — | +| `--ot-color-surface` | Cards, dialogs, table bodies, panels | `#ffffff` | `#201f23` | — | +| `--ot-color-surface-raised` | Menus, popovers, sticky headers, anything above a surface | `#ffffff` | `#2a292d` | — | +| `--ot-color-text` | Body and heading text | `#212121` | `#e5e1e6` | 11.18 on dark raised | +| `--ot-color-text-muted` | Secondary text, captions, hints | `#616161` | `#adaaaf` | 5.93 on light page | +| `--ot-color-border` | Control boundaries: inputs, outlined buttons, chips | `#8a8a8a` | `#78767a` | 3.21 on dark raised | +| `--ot-color-divider` | Decorative rules between rows and sections | `#e0e0e0` | `#353438` | n/a, decorative | +| `--ot-color-focus` | Focus ring | `#3939ff` | `#c0c1ff` | 6.28 light, 8.47 dark | +| `--ot-color-link` | Inline links | `#3939ff` | `#c0c1ff` | 6.28 on light page | +| `--ot-color-primary` | Primary actions, active nav, brand accents | `#3939ff` | `#c0c1ff` | 6.28 on light page | +| `--ot-color-on-primary` | Text and icons on a primary fill | `#ffffff` | `#131316` | 6.56 / 10.87 | +| `--ot-color-success` | Success text and icons | `#398239` | `#5bb75b` | 4.55 on light page | +| `--ot-color-warning` | Warning text and icons | `#a56504` | `#eb8f06` | 4.51 on light page | +| `--ot-color-error` | Error text, invalid fields, destructive actions | `#d73613` | `#ef6445` | 4.53 on dark raised | +| `--ot-color-info` | Informational text and icons | `#0075d0` | `#0792ff` | 4.52 on light page | +| `--ot-color-inverse-surface` | Snackbars, tooltips, anything inverted | `#212121` | `#e5e1e6` | — | +| `--ot-color-inverse-text` | Text on an inverse surface | `#fafafa` | `#201f23` | 15.43 / 12.67 | + +Three notes that are part of the contract, not commentary. + +- **`--ot-color-surface` and `--ot-color-surface-raised` are the same value in light** (`#ffffff`). + In light mode a raised surface is separated by `--ot-elevation-1`, not by hue. In dark mode it + is separated by hue, because shadows do not read on a dark ground. **Never rely on the + raised-versus-surface difference alone to communicate anything.** +- **`--ot-color-border` and `--ot-color-divider` are different tokens on purpose.** WCAG 1.4.11 + requires 3:1 for boundaries that carry meaning, such as the edge of a text input. It does not + apply to a decorative rule between two table rows. `--ot-color-border` clears 3:1 in both + themes. `--ot-color-divider` does not, and must never be used as a control boundary. +- **`--ot-color-text-muted` in light is `#616161`, not the `#757575` the app uses today**, because + `#757575` measures 4.41 against `--ot-color-page`. This is a real fix, not a restyle. + +--- + +## 8. Domain tokens + +### 8.1 Task status + +Fifteen statuses. The method, applied in order: keep the shipped fill if white text on it already +clears 4.5:1; otherwise keep the shipped fill and use `--ot-color-text` (`#212121`) if that +clears 4.5:1; only if neither works, darken the fill in 0.5% HSL lightness steps, hue and +saturation held, until white text reaches 4.5:1. **Thirteen of fifteen fills come through +unchanged.** The dark fill is a container: same hue, same saturation, lightness pinned to 22%. +The dark on-fill is the same hue lifted until it clears 4.5:1 on that container. + +| Status | Shipped fill | `--ot-status-*` light | `-on` light | Ratio | `--ot-status-*` dark | `-on` dark | Ratio | +| --------------------- | ------------ | --------------------- | ----------- | ----- | -------------------- | ---------- | ----- | +| `ready-for-feedback` | `#0079d8` | `#0078d5` | `#ffffff` | 4.52 | `#003f70` | `#47aeff` | 4.51 | +| `not-started` | `#cccccc` | `#cccccc` | `#212121` | 10.03 | `#383838` | `#a1a1a1` | 4.54 | +| `working-on-it` | `#eb8f06` | `#eb8f06` | `#212121` | 6.49 | `#6d4303` | `#fab042` | 4.63 | +| `need-help` | `#a48fce` | `#a48fce` | `#212121` | 5.67 | `#31224e` | `#9d86ca` | 4.56 | +| `fix-and-resubmit` | `#f2d85c` | `#f2d85c` | `#212121` | 11.31 | `#685708` | `#f1d44c` | 4.83 | +| `feedback-exceeded` | `#d46b54` | `#d46b54` | `#212121` | 4.62 | `#5a2317` | `#dc8572` | 4.53 | +| `redo` | `#804000` | `#804000` | `#ffffff` | 7.92 | `#703800` | `#ff9e3d` | 4.53 | +| `discuss` | `#31b0d5` | `#31b0d5` | `#212121` | 6.37 | `#134c5d` | `#5ec1de` | 4.58 | +| `rediscuss` | `#126352` | `#126352` | `#ffffff` | 7.16 | `#115f4f` | `#5be1c5` | 4.69 | +| `demonstrate` | `#428bca` | `#337ab7` | `#ffffff` | 4.56 | `#193a58` | `#6ea6d6` | 4.53 | +| `complete` | `#5bb75b` | `#5bb75b` | `#212121` | 6.42 | `#224e22` | `#78c478` | 4.57 | +| `fail` | `#d93713` | `#d93713` | `#ffffff` | 4.66 | `#671a09` | `#f17c62` | 4.51 | +| `time-exceeded` | `#d93713` | `#d93713` | `#ffffff` | 4.66 | `#671a09` | `#f17c62` | 4.51 | +| `assess-in-portfolio` | `#f2d85c` | `#f2d85c` | `#212121` | 11.31 | `#685708` | `#f1d44c` | 4.83 | +| `attention-required` | `#f1814d` | `#f1814d` | `#212121` | 6.12 | `#682708` | `#f28a5a` | 4.55 | + +Token names are `--ot-status-` and `--ot-status--on`, where `` is the existing +kebab-case class from `TaskStatus.statusClass()`. + +Only two light fills move: `ready-for-feedback` (`#0079d8` → `#0078d5`) and `demonstrate` +(`#428bca` → `#337ab7`). Six flip their foreground from `#ffffff` to `--ot-color-text` with the +fill untouched — `working-on-it`, `need-help`, `feedback-exceeded`, `discuss`, `complete`, +`attention-required`. Three keep their fill and move their foreground off the shipped `#444444` +onto the same token — `not-started`, `fix-and-resubmit`, `assess-in-portfolio`. That leaves four +untouched in both fill and foreground: `redo`, `rediscuss`, `fail`, `time-exceeded`. + +Thirteen of fifteen dark fills are distinct. The two collisions are `fail`/`time-exceeded` and +`fix-and-resubmit`/`assess-in-portfolio`, which already share a base colour today. No **new** +collision is introduced. + +**The two-maps problem must be closed during the shared-component migration, not carried +forward.** No card on the board names it in its own words, and both files are shared rather than +per-page — `src/styles/common/task-status-colors.scss` and `src/app/api/models/task-status.ts` — +so it belongs to **THM-M01, shell and shared components**, and THM-JL01 should confirm that when +the card is written up. After migration `STATUS_COLORS` in `task-status.ts` is deleted and any +TypeScript that needs a status colour reads `var(--ot-status-)`. Where a JS value is +unavoidable (charts), it is read once via +`getComputedStyle(document.documentElement).getPropertyValue(...)` and re-read on theme change. +One source of truth, in CSS. + +### 8.2 Everything else + +| Group | Token | Light | Dark | Note | +| --------- | ----------------------------- | ---------------------------- | ---------------------------- | ---------------------------------------------------------------- | +| Urgency | `--ot-urgency-overdue` | `#c94823` | `#e06f4f` | from `#da532c`; 4.54 light page, 4.51 dark raised | +| | `--ot-urgency-soon` | `#a56504` | `#fab143` | from `#fab143`; 4.51 light page, 7.87 dark raised | +| | `--ot-urgency-later` | `#616161` | `#adaaaf` | alias of `--ot-color-text-muted`; replaces `text-gray-500` | +| Charts | `--ot-chart-1` | `#3939ff` | `#6c6cff` | series slots, ≥3:1 vs their own page (1.4.11); worst 3.02 / 4.52 | +| | `--ot-chart-2` | `#0079d8` | `#007fe2` | | +| | `--ot-chart-3` | `#58a152` | `#5aa454` | | +| | `--ot-chart-4` | `#e44d25` | `#e44d25` | | +| | `--ot-chart-5` | `#a8385d` | `#c7587d` | | +| | `--ot-chart-6` | `#d07e05` | `#eb8f06` | | +| | `--ot-chart-grid` | `#e0e0e0` | `#353438` | gridlines, decorative | +| | `--ot-chart-axis` | `#616161` | `#adaaaf` | axis labels are text, 4.5:1 | +| Code | `--ot-code-surface` | `#f5f5f5` | `#0e0e11` | `
    `, ANSI output, diff panes                                 |
    +|           | `--ot-code-text`              | `#212121`                    | `#e5e1e6`                    | 14.77 / 14.91 on their own surface                               |
    +|           | Monaco theme name             | `vs`                         | `vs-dark`                    | not a CSS var; set in TS from the resolved theme                 |
    +| Overlays  | `--ot-scrim`                  | `rgba(0, 0, 0, 0.32)`        | `rgba(0, 0, 0, 0.60)`        | dialog and drawer backdrop                                       |
    +|           | `--ot-elevation-1`            | `0 1px 3px rgba(0,0,0,0.12)` | `0 1px 3px rgba(0,0,0,0.50)` | shadow, not colour                                               |
    +| Disabled  | `--ot-color-disabled-text`    | `#9e9e9e`                    | `#6f6d72`                    | 1.4.3 exempts inactive controls; still needs a non-colour cue    |
    +|           | `--ot-color-disabled-surface` | `#eeeeee`                    | `#2a292d`                    |                                                                  |
    +| Selection | `--ot-color-selected`         | `#e7e7ff`                    | `#2e2e5c`                    | selected row or chip fill                                        |
    +|           | `--ot-color-selected-text`    | `#212121`                    | `#e5e1e6`                    | 13.24 / 9.78                                                     |
    +|           | `--ot-color-hover`            | `rgba(0, 0, 0, 0.04)`        | `rgba(255, 255, 255, 0.06)`  | matches the M2 `hover` slot already in use                       |
    +
    +`--ot-color-selected` light is `#e7e7ff`, which is `formatif-blue-lighter` from
    +`tailwind.config.js` and `$md-formatif.50` from `theme.scss`. It is already the app's selection
    +tint, it just had no name.
    +
    +---
    +
    +## 9. Fixed brand vs theme-aware
    +
    +| Fixed in both themes                                                                       | Why                                                                                                                          |
    +| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
    +| `#3939ff` as the **brand mark** — the logo, the favicon, `icon.svg`, the PWA `theme_color` | Brand identity. A logo that changes colour is a different logo.                                                              |
    +| The status **identity**, meaning which hue means `complete`                                | Green means complete in both themes. Teaching staff read these chips daily and re-learning them in dark mode is a real cost. |
    +| `#da532c`, `$doubtfire-color` in `variables.scss`                                          | Legacy brand colour. Keep or retire it, do not theme it.                                                                     |
    +
    +| Theme-aware                                                 | Why                                                                                                                                |
    +| ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
    +| `--ot-color-primary`, `--ot-color-link`, `--ot-color-focus` | `#3939ff` is 6.28:1 on the light page, 2.83:1 on the dark page and 2.20:1 on the worst-case dark raised surface. It misses 4.5:1 for text and 3:1 for a focus ring, so the brand blue cannot be the dark-mode interactive colour. |
    +| Every status **fill and foreground**                        | The hue stays recognisable; the lightness has to move or the chip is unreadable. Section 8.1.                                      |
    +| All surfaces, text, borders, dividers, shadows, scrims      | Definitionally.                                                                                                                    |
    +| Chart series                                                | A series colour is a graphical object under WCAG 1.4.11 and needs 3:1 against its own ground.                                      |
    +| The `theme-color` meta tag                                  | Section 12.                                                                                                                        |
    +
    +The distinction in one sentence: **the brand mark is fixed, the brand as an interface colour is
    +theme-aware.**
    +
    +---
    +
    +## 10. Who may declare a colour, and how each layer reads the tokens
    +
    +Four layers. Exactly one of them is allowed to contain a colour value.
    +
    +| Layer                                                           | May declare a colour?  | Job                                                                           |
    +| --------------------------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------- |
    +| **Token layer** — `src/styles/tokens/_light.scss`, `_dark.scss` | **Yes, and only here** | Declare every `--ot-*` for one theme. Two files, two blocks, no logic.        |
    +| **Material theme** — `src/theme.scss`                           | Transitional           | M2 palettes stay until section 3 step 4 retires them. No new colour goes in.  |
    +| **Shared SCSS** — `src/styles/common`, `src/styles/mixins`      | No                     | Mixins and layout. Colour only through `var(--ot-*)`.                         |
    +| **Component SCSS and templates**                                | No                     | Consume `var(--ot-*)` or a Tailwind utility. A new hex is a review rejection. |
    +
    +### Tailwind
    +
    +Tailwind must **map** to the tokens, never restate them. Tailwind 4 is in use with a v3-style
    +JS config loaded through `@config '../tailwind.config.js'` from `src/styles.scss` and
    +`src/tailwind-intellisense.css`. Extend the theme with `var()` references:
    +
    +```js
    +// tailwind.config.js
    +theme: {
    +  extend: {
    +    colors: {
    +      'formatif-blue': '#3939ff',                    // brand mark, stays literal
    +      'formatif-blue-lighter': '#e7e7ff',
    +      page: 'var(--ot-color-page)',
    +      surface: 'var(--ot-color-surface)',
    +      'surface-raised': 'var(--ot-color-surface-raised)',
    +      content: 'var(--ot-color-text)',
    +      muted: 'var(--ot-color-text-muted)',
    +      border: 'var(--ot-color-border)',
    +      divider: 'var(--ot-color-divider)',
    +      primary: 'var(--ot-color-primary)',
    +      link: 'var(--ot-color-link)',
    +      success: 'var(--ot-color-success)',
    +      warning: 'var(--ot-color-warning)',
    +      error: 'var(--ot-color-error)',
    +      info: 'var(--ot-color-info)',
    +    },
    +  },
    +},
    +```
    +
    +`bg-surface text-content border-border` then resolves per theme with **no dark variant on a
    +colour utility**. Tokens are the default and they stay the default. A `dark:bg-x` on a colour
    +doubles every class list and moves the palette back into templates, which is the thing this
    +contract exists to stop.
    +
    +#### The dark variant is configured and pointed at the marker — THM-F03
    +
    +`darkMode` is not set today, and leaving it unset is **not** the same as having no dark variant.
    +Tailwind's default `dark:` is `@media (prefers-color-scheme: dark)`. So the prefix already works
    +in this build, and it already **follows the operating system and ignores the stored
    +preference**. A `dark:bg-black` written today stays dark for a user whose preference is `light`,
    +which breaks rule 2 of section 4 without anyone editing a line of this contract.
    +
    +Configuring it is a correctness fix before it is a feature. **THM-F03 binds the variant to
    +`data-ot-theme`**, the marker section 5 fixes, so the app has one dark authority and it is the
    +resolved theme:
    +
    +```css
    +/* src/styles.scss, beside the existing @config line */
    +@custom-variant dark (&:where([data-ot-theme='dark'], [data-ot-theme='dark'] *));
    +```
    +
    +Tailwind here is `4.3.1` driven by a v3-style JS config through `@config` (`src/styles.scss:7`
    +and `src/tailwind-intellisense.css:2`), so the legacy
    +`darkMode: ['selector', '[data-ot-theme="dark"]']` may be honoured as well. **THM-F03 picks one
    +form, proves it with a build, and records which.** Two mechanisms for one variant is how they
    +drift apart.
    +
    +Three rules bound what the variant is then for.
    +
    +1. **Never for a colour that already has a token.** `bg-surface` flips on its own.
    +   `dark:bg-[#201f23]` is a rejection and so is `dark:bg-surface-raised`.
    +2. **Yes for what a custom property cannot carry.** A different asset, `dark:invert` on the PDF
    +   viewer canvas, a border width, an opacity, a `mix-blend-mode`, a shadow that has to change
    +   shape rather than colour. Section 7 has no token for these and never will.
    +3. **Yes for third-party CSS the token layer cannot reach**, where a `dark:` utility carried by
    +   `important: true` is a smaller intervention than forking a vendor stylesheet.
    +
    +`dark:` on a colour utility is a lint violation (rule 2 below). `dark:` on anything else is
    +allowed and needs no exception.
    +
    +`important: true` stays as it is. It is what lets a utility override Material today, and
    +changing it is out of scope.
    +
    +### Shared SCSS
    +
    +```scss
    +// src/styles/mixins/_surface.scss
    +@mixin card-surface {
    +  background-color: var(--ot-color-surface, #ffffff);
    +  color: var(--ot-color-text, #212121);
    +  border: 1px solid var(--ot-color-border, #8a8a8a);
    +}
    +```
    +
    +The fallback is the current light value. That is the rollback guarantee from section 3, applied
    +at every call site.
    +
    +### Material
    +
    +Material components are pulled onto the tokens with `mat.theme-overrides()` inside the same two
    +theme blocks, one component group per PR:
    +
    +```scss
    +:root[data-ot-theme='dark'] {
    +  @include mat.theme-overrides(
    +    (
    +      surface: var(--ot-color-surface),
    +      on-surface: var(--ot-color-text),
    +      outline: var(--ot-color-border),
    +    )
    +  );
    +}
    +```
    +
    +### The three lint rules that hold the line
    +
    +These belong in MG-05 and are proposed here so the reviewer knows what to enforce until then.
    +
    +1. No hex, `rgb()` or `hsl()` literal in any file under `src/app`. Grep gate in CI, allowlist the
    +   token files and `theme.scss`.
    +2. No Tailwind arbitrary colour value, and no `dark:` prefix on a colour utility.
    +   `eslint-plugin-tailwindcss` is already wired (`eslint.config.js:89-101`); add
    +   `tailwindcss/no-arbitrary-value` for colour utilities, and a grep gate for
    +   `dark:(bg|text|border|fill|stroke|ring|outline|from|via|to)-`.
    +3. No new `--ot-*` name without an entry in section 7 or 8 of this document.
    +
    +Today's baseline for rule 1 is 105 literals in component SCSS under `src/app` plus 20 Tailwind
    +arbitrary colour values across 9 template files. That number is the migration burn-down and
    +should only go down.
    +
    +---
    +
    +## 11. Startup and live system changes
    +
    +### Live OS changes
    +
    +`ThemeService` holds one listener for the whole app lifetime. It fires only when the stored
    +preference is `system`.
    +
    +```ts
    +private readonly query = window.matchMedia('(prefers-color-scheme: dark)');
    +
    +constructor() {
    +  this.query.addEventListener('change', () => {
    +    if (this.preference() === 'system') {
    +      this.applyResolved();
    +    }
    +  });
    +}
    +```
    +
    +- `addEventListener('change', ...)`, not the deprecated `addListener`.
    +- Registered once, in a root-provided service, and removed on destroy. One listener, not one per
    +  component.
    +- No reload, no re-render of the router outlet. Changing `data-ot-theme` repaints via CSS.
    +- Charts and Monaco cannot repaint from CSS, so the service also emits a signal that those
    +  components subscribe to in order to re-read their colours. That subscription is part of
    +  THM-M04, and this is the hook it uses.
    +
    +### No-flash startup — THM-F04
    +
    +Two cards touch startup. THM-F01 builds the foundation, which includes System detection and
    +persistence, and THM-F04 specifies and implements the no-flash mechanism. They overlap, so the
    +split is fixed here: **THM-F04 writes the `` script below and the drift test in section 14
    +item 15. THM-F01 consumes whatever that script already set, at bootstrap, and owns the theme
    +from that point on.** Neither card writes the other's half.
    +
    +The wrong theme flashing for one frame on every page load is the single most visible defect a
    +theme feature can ship. Angular bootstraps after `` paints, so the marker has to be set
    +before that. One small blocking inline script in `` of `src/index.html`, before any
    +stylesheet:
    +
    +```html
    +
    +```
    +
    +Constraints on that script, all reviewable:
    +
    +- **Inline and synchronous.** A deferred or external script paints late and the flash returns.
    +- **Under 400 bytes, no dependencies**, so it cannot meaningfully delay first paint.
    +- **The whole body is inside `try`.** Safari private mode throws on `localStorage.getItem`.
    +  Anything thrown here would block the app from booting at all.
    +- **It writes only `'light'` or `'dark'`.** The stored value never reaches `setAttribute`
    +  directly. This is the same allowlist as section 6, restated in the one place that runs before
    +  the service exists.
    +- **It duplicates the storage key as a literal.** That is deliberate: it runs before any module
    +  loads, so it cannot import the constant. THM-T01 must assert the literal in `index.html`
    +  matches `THEME_STORAGE_KEY` in the service, or the two will drift.
    +- `d.style.colorScheme = t` makes native scrollbars, `
    - +

    {{privacyPolicy.privacy}} - +

    Plagiarism and collusion

    Plagiarism and Collusion

    diff --git a/src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment-modal/task-ilo-alignment-modal.tpl.html b/src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment-modal/task-ilo-alignment-modal.tpl.html index 91fdabc350..a89b929a99 100644 --- a/src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment-modal/task-ilo-alignment-modal.tpl.html +++ b/src/app/tasks/task-ilo-alignment/modals/task-ilo-alignment-modal/task-ilo-alignment-modal.tpl.html @@ -14,7 +14,7 @@

    -
    +
    Click to add one

    diff --git a/src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.tpl.html b/src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.tpl.html index 2032d7bf1d..79fc40a50b 100644 --- a/src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.tpl.html +++ b/src/app/tasks/task-ilo-alignment/task-ilo-alignment-viewer/task-ilo-alignment-viewer.tpl.html @@ -34,7 +34,7 @@

    Description
    -
    +
    {{ilo.description}}
    Visualisation
    @@ -50,7 +50,7 @@
    Visualisation
    Rationale
    -
    +
    Related Tasks
    From ce7e69f2aa43b409bbf91eec29273e9cd19cd973 Mon Sep 17 00:00:00 2001 From: ShounakB <65479699+Shounaks@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:29:57 +1100 Subject: [PATCH 0219/1531] rebase migration:grade-icon onto origin/8.0.x --- src/app/common/common.coffee | 1 - src/app/common/grade-icon/grade-icon.coffee | 16 - .../grade-icon/grade-icon.component.html | 16 + .../grade-icon/grade-icon.component.scss | 20 + .../common/grade-icon/grade-icon.component.ts | 35 ++ src/app/common/grade-icon/grade-icon.scss | 48 --- src/app/common/grade-icon/grade-icon.tpl.html | 8 - src/app/doubtfire-angular.module.ts | 2 + src/app/doubtfire-angularjs.module.ts | 3 +- ...roup-member-contribution-assigner.tpl.html | 82 ++-- .../project-progress-dashboard.tpl.html | 2 +- .../grade-task-modal.tpl.html | 54 +-- .../states/portfolios/portfolios.tpl.html | 6 +- .../students-list/students-list.tpl.html | 364 +++++++++--------- 14 files changed, 329 insertions(+), 328 deletions(-) delete mode 100644 src/app/common/grade-icon/grade-icon.coffee create mode 100644 src/app/common/grade-icon/grade-icon.component.html create mode 100644 src/app/common/grade-icon/grade-icon.component.scss create mode 100644 src/app/common/grade-icon/grade-icon.component.ts delete mode 100644 src/app/common/grade-icon/grade-icon.scss delete mode 100644 src/app/common/grade-icon/grade-icon.tpl.html diff --git a/src/app/common/common.coffee b/src/app/common/common.coffee index e5bbea48a2..f330d8f6ac 100644 --- a/src/app/common/common.coffee +++ b/src/app/common/common.coffee @@ -3,6 +3,5 @@ angular.module("doubtfire.common", [ 'doubtfire.common.filters' 'doubtfire.common.modals' 'doubtfire.common.file-uploader' - 'doubtfire.common.grade-icon' 'doubtfire.common.content-editable' ]) diff --git a/src/app/common/grade-icon/grade-icon.coffee b/src/app/common/grade-icon/grade-icon.coffee deleted file mode 100644 index f35f7fbfa4..0000000000 --- a/src/app/common/grade-icon/grade-icon.coffee +++ /dev/null @@ -1,16 +0,0 @@ -angular.module('doubtfire.common.grade-icon', []) - -.directive 'gradeIcon', -> - restrict: 'E' - replace: true - templateUrl: 'common/grade-icon/grade-icon.tpl.html' - scope: - inputGrade: '=?grade' - colorful: '=?' - controller: ($scope, gradeService) -> - $scope.$watch 'inputGrade', (newGrade) -> - $scope.grade = if _.isString($scope.inputGrade) then gradeService.stringToGrade($scope.inputGrade) else $scope.inputGrade - $scope.gradeText = (grade) -> - if grade? then gradeService.grades[grade] or "Grade" - $scope.gradeLetter = (grade) -> - gradeService.gradeAcronyms[grade] or 'G' diff --git a/src/app/common/grade-icon/grade-icon.component.html b/src/app/common/grade-icon/grade-icon.component.html new file mode 100644 index 0000000000..2cb10af9d8 --- /dev/null +++ b/src/app/common/grade-icon/grade-icon.component.html @@ -0,0 +1,16 @@ +
    + + {{ gradeLetter }} + +
    diff --git a/src/app/common/grade-icon/grade-icon.component.scss b/src/app/common/grade-icon/grade-icon.component.scss new file mode 100644 index 0000000000..76ea15e629 --- /dev/null +++ b/src/app/common/grade-icon/grade-icon.component.scss @@ -0,0 +1,20 @@ +.grade-icon { + color: #fff; + font-size: 1em; + background-color: #333333; + border-radius: 100%; + width: 2.25em; + height: 2.25em; + font-weight: 100; + font-size: 1em; + margin: 0 auto; + display: flex; + align-items: center; + justify-content: center; +} +.text-left .grade-icon { + margin-left: 0; +} +.text-right .grade-icon { + margin-right: 0; +} diff --git a/src/app/common/grade-icon/grade-icon.component.ts b/src/app/common/grade-icon/grade-icon.component.ts new file mode 100644 index 0000000000..5c539d5ead --- /dev/null +++ b/src/app/common/grade-icon/grade-icon.component.ts @@ -0,0 +1,35 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { Component, Inject, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; +import { GradeService } from '../services/grade.service'; +import { Project } from 'src/app/api/models/project'; + +@Component({ + selector: 'grade-icon', + templateUrl: './grade-icon.component.html', + styleUrls: ['./grade-icon.component.scss'], +}) +export class GradeIconComponent implements OnInit, OnChanges { + @Input() grade?: number; + @Input() colorful: boolean = false; + + InputGrade?: number; + gradeText: string = 'Grade'; + gradeLetter: string = 'G'; + + constructor(private gradeService: GradeService) {} + + ngOnInit(): void { + this.updateGrade(); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes['grade']) { + this.updateGrade(); + } + } + + private updateGrade(): void { + this.gradeText = this.gradeService.grades[this.grade] || 'Grade'; + this.gradeLetter = this.gradeService.gradeAcronyms[this.grade] || 'G'; + } +} diff --git a/src/app/common/grade-icon/grade-icon.scss b/src/app/common/grade-icon/grade-icon.scss deleted file mode 100644 index 08db661a8b..0000000000 --- a/src/app/common/grade-icon/grade-icon.scss +++ /dev/null @@ -1,48 +0,0 @@ -.grade-icon.text-muted { - background-color: $text-muted; -} -.grade-icon.text-primary { - background-color: $brand-primary; -} -.grade-icon.text-success { - background-color: $brand-success; -} -.grade-icon.text-danger { - background-color: $brand-danger; -} -.grade-icon.text-info { - background-color: $brand-info; -} -.grade-icon.text-warning { - background-color: $brand-warning; -} -a .grade-icon:hover { - background-color: $link-hover-color; -} -.grade-icon { - color: #fff; - font-size: 1em; - background-color: $text-color; - border-radius: 100%; - width: 2.25em; - height: 2.25em; - font-weight: 100; - font-size: 1em; - @include no-select; - margin: 0 auto; - display: flex; - align-items: center; - justify-content: center; -} -.grade-icon.colorful { - &.grade-0 { background-color: $grade-color-p; } - &.grade-1 { background-color: $grade-color-c; } - &.grade-2 { background-color: $grade-color-d; } - &.grade-3 { background-color: $grade-color-hd; } -} -.text-left .grade-icon { - margin-left: 0; -} -.text-right .grade-icon { - margin-right: 0; -} diff --git a/src/app/common/grade-icon/grade-icon.tpl.html b/src/app/common/grade-icon/grade-icon.tpl.html deleted file mode 100644 index 1939b21361..0000000000 --- a/src/app/common/grade-icon/grade-icon.tpl.html +++ /dev/null @@ -1,8 +0,0 @@ -
    - - {{gradeLetter(grade)}} - -
    diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index 991ac397b4..4b06266dc1 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -170,6 +170,7 @@ import {TaskAssessmentModalComponent} from './common/modals/task-assessment-moda import {TaskSubmissionHistoryComponent} from './tasks/task-submission-history/task-submission-history.component'; import {HomeComponent} from './home/states/home/home.component'; import {IsActiveUnitRole} from './common/pipes/is-active-unit-role.pipe'; +import {GradeIconComponent} from './common/grade-icon/grade-icon.component'; import {HeaderComponent} from './common/header/header.component'; import {UnitDropdownComponent} from './common/header/unit-dropdown/unit-dropdown.component'; import {TaskDropdownComponent} from './common/header/task-dropdown/task-dropdown.component'; @@ -316,6 +317,7 @@ const MY_DATE_FORMAT = { TaskAssessmentCommentComponent, TaskAssessmentModalComponent, TaskSubmissionHistoryComponent, + GradeIconComponent, HeaderComponent, UnitDropdownComponent, TaskDropdownComponent, diff --git a/src/app/doubtfire-angularjs.module.ts b/src/app/doubtfire-angularjs.module.ts index e14fdbb545..1f42ca4907 100644 --- a/src/app/doubtfire-angularjs.module.ts +++ b/src/app/doubtfire-angularjs.module.ts @@ -122,7 +122,6 @@ import 'build/src/app/common/modals/confirmation-modal/confirmation-modal.js'; import 'build/src/app/common/modals/comments-modal/comments-modal.js'; import 'build/src/app/common/modals/csv-result-modal/csv-result-modal.js'; import 'build/src/app/common/modals/modals.js'; -import 'build/src/app/common/grade-icon/grade-icon.js'; import 'build/src/app/common/file-uploader/file-uploader.js'; import 'build/src/app/common/common.js'; import 'build/src/app/common/services/listener-service.js'; @@ -193,6 +192,7 @@ import {CheckForUpdateService} from './sessions/service-worker-updater/check-for import {TaskSubmissionService} from './common/services/task-submission.service'; import {TaskAssessmentModalService} from './common/modals/task-assessment-modal/task-assessment-modal.service'; import {TaskSubmissionHistoryComponent} from './tasks/task-submission-history/task-submission-history.component'; +import {GradeIconComponent} from './common/grade-icon/grade-icon.component'; import {HeaderComponent} from './common/header/header.component'; import {SplashScreenComponent} from './home/splash-screen/splash-screen.component'; import {GlobalStateService} from './projects/states/index/global-state.service'; @@ -313,6 +313,7 @@ DoubtfireAngularJSModule.directive( 'objectSelect', downgradeComponent({component: ObjectSelectComponent}), ); +DoubtfireAngularJSModule.directive('gradeIcon', downgradeComponent({component: GradeIconComponent})); DoubtfireAngularJSModule.directive('appHeader', downgradeComponent({component: HeaderComponent})); DoubtfireAngularJSModule.directive( 'splashScreen', diff --git a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html index 4caab308f5..149ebb8a13 100644 --- a/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html +++ b/src/app/groups/group-member-contribution-assigner/group-member-contribution-assigner.tpl.html @@ -1,41 +1,41 @@ -
    - - - - - - - - - - - - - - - -
    Team MemberTarget GradeContribution
    {{contrib.project.student.name}} - - - - - - - {{contrib.percent}} % effort - - - No effort - - -
    -
    +
    + + + + + + + + + + + + + + + +
    Team MemberTarget GradeContribution
    {{contrib.project.student.name}} + + + + + + + {{contrib.percent}} % effort + + + No effort + + +
    +
    diff --git a/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html b/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html index 5dc40dc5b0..7e59cac17b 100644 --- a/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html +++ b/src/app/projects/project-progress-dashboard/project-progress-dashboard.tpl.html @@ -22,7 +22,7 @@

    Target Grade

    diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html b/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html index 0906d7b593..4d02cce31f 100644 --- a/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html +++ b/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html @@ -1,27 +1,27 @@ -
    - - - -
    +
    + + + +
    diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html index 2b8a2277eb..800d4f4cbe 100644 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ b/src/app/units/states/portfolios/portfolios.tpl.html @@ -65,7 +65,7 @@

    Mark Portfolios

    btn-radio="{{$index}}" > Mark Portfolios

    {{student.tutorNames()}} {{student.shortTutorialDescription()}} - + - + diff --git a/src/app/units/states/students-list/students-list.tpl.html b/src/app/units/states/students-list/students-list.tpl.html index 929cefe386..d81fdb4cd6 100644 --- a/src/app/units/states/students-list/students-list.tpl.html +++ b/src/app/units/states/students-list/students-list.tpl.html @@ -1,182 +1,182 @@ -
    -
    -
    -
    - - - - -
    - -
    -
    -
    - -
    -
    - - -
    -
    -
    -
    - -
    -
    - - - -
    -
    -

    - Click the button twice to reverse the sort ordering. -

    -
    -
    -
    -
    -

    No students found

    -

    - No students were found using the filters specified. -

    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - -
    - - Username - - - - Name - - - - Stats - - - - Flags - - - - - Campus - - - - Tutorial - -
    - - - {{project.student.username || "N/A"}} - - {{project.student.name}} - - - - {{bar.value !== bar.value ? 'No Interaction' : (bar.value + '%')}} - - - - - - - - - - - - - - - - - - -
    - -
    -
    +
    +
    +
    +
    + + + + +
    + +
    +
    +
    + +
    +
    + + +
    +
    +
    +
    + +
    +
    + + + +
    +
    +

    + Click the button twice to reverse the sort ordering. +

    +
    +
    +
    +
    +

    No students found

    +

    + No students were found using the filters specified. +

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    + + Username + + + + Name + + + + Stats + + + + Flags + + + + + Campus + + + + Tutorial + +
    + + + {{project.student.username || "N/A"}} + + {{project.student.name}} + + + + {{bar.value !== bar.value ? 'No Interaction' : (bar.value + '%')}} + + + + + + + + + + + + + + + + + + +
    + +
    +
    From 91b42988188a2e9ebfdfbcca338382da656a7e32 Mon Sep 17 00:00:00 2001 From: ShounakB <65479699+Shounaks@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:21:41 +1100 Subject: [PATCH 0220/1531] Fixing All components and CSS Cleanup --- .../common/grade-icon/grade-icon.component.html | 14 +++++++------- .../common/grade-icon/grade-icon.component.scss | 14 -------------- .../common/grade-icon/grade-icon.component.ts | 17 +++++++++-------- src/app/doubtfire-angularjs.module.ts | 2 +- .../group-member-contribution-assigner.tpl.html | 2 +- .../group-member-list.tpl.html | 2 +- .../project-progress-dashboard.tpl.html | 2 +- .../portfolio-grade-select-step.tpl.html | 6 +++--- .../grade-task-modal/grade-task-modal.tpl.html | 2 +- .../units/states/portfolios/portfolios.tpl.html | 8 ++++---- .../states/students-list/students-list.tpl.html | 2 +- 11 files changed, 29 insertions(+), 42 deletions(-) diff --git a/src/app/common/grade-icon/grade-icon.component.html b/src/app/common/grade-icon/grade-icon.component.html index 2cb10af9d8..7af15c0ba3 100644 --- a/src/app/common/grade-icon/grade-icon.component.html +++ b/src/app/common/grade-icon/grade-icon.component.html @@ -1,12 +1,12 @@ -
    +
    {{contrib.project.student.name}} - + No members in group {{member.student.username || "N/A"}} {{member.student.name}} - +

    diff --git a/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html b/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html index 4d02cce31f..7fa8e7055e 100644 --- a/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html +++ b/src/app/tasks/modals/grade-task-modal/grade-task-modal.tpl.html @@ -7,7 +7,7 @@

    Assess Task Quality

    Please provide a grade to change the student's status for task .

    diff --git a/src/app/units/states/portfolios/portfolios.tpl.html b/src/app/units/states/portfolios/portfolios.tpl.html index 800d4f4cbe..c67b13e400 100644 --- a/src/app/units/states/portfolios/portfolios.tpl.html +++ b/src/app/units/states/portfolios/portfolios.tpl.html @@ -64,12 +64,12 @@

    Mark Portfolios

    ng-model="filterOptions.selectedGrade" btn-radio="{{$index}}" > - + >