- @for (sectionQuestion of section.sectionQuestions; track sectionQuestion) {
+ @for (
+ sectionQuestion of section.sectionQuestions | orderBy: 'sequenceNumber';
+ track sectionQuestion.sequenceNumber
+ ) {
diff --git a/ui/src/app/exam/editor/sections/section.component.ts b/ui/src/app/exam/editor/sections/section.component.ts
index 9f1dc6bc4..a92e84479 100644
--- a/ui/src/app/exam/editor/sections/section.component.ts
+++ b/ui/src/app/exam/editor/sections/section.component.ts
@@ -43,6 +43,7 @@ import { FileService } from '../../../shared/file/file.service';
import type { ExamMaterial, ExamSection, ExamSectionQuestion, Question } from '../../exam.model';
import { ExamService } from '../../exam.service';
import { SectionQuestionComponent } from './section-question.component';
+import { OrderByPipe } from 'src/app/shared/sorting/order-by.pipe';
@Component({
selector: 'xm-section',
@@ -63,6 +64,7 @@ import { SectionQuestionComponent } from './section-question.component';
CdkDragPreview,
SectionQuestionComponent,
TranslateModule,
+ OrderByPipe,
],
})
export class SectionComponent {
From 851286b16c184059c607344b05d076c356ee2bc3 Mon Sep 17 00:00:00 2001
From: Matti Lupari
Date: Tue, 30 Jan 2024 19:01:30 +0200
Subject: [PATCH 3/6] CSCEXAM-000 Lazy load rest of the student components
Co-authored-by: Matti Lupari
---
ui/src/app/{app.routing.ts => app.routes.ts} | 92 +-
.../calendar/booking-calendar.component.ts | 2 +-
ui/src/app/calendar/calendar.component.html | 20 +-
.../calendar/helpers/exam-info.component.ts | 6 +-
.../helpers/organisation-picker.component.ts | 7 +-
.../helpers/slot-picker.component.html | 10 +-
.../accessibility.component.html | 150 ++--
.../rooms/room-mass-edit.component.ts | 2 +-
.../app/facility/rooms/rooms.component.html | 2 +-
.../app/facility/rooms/rooms.component.scss | 50 ++
ui/src/app/facility/rooms/rooms.component.ts | 1 +
.../app/navigation/navigation.component.html | 2 +-
.../app/navigation/navigation.component.scss | 371 ++++++++
ui/src/app/navigation/navigation.component.ts | 1 +
.../general/general-info.component.ts | 6 +-
ui/src/app/shared/styles.scss | 6 +
ui/src/app/software/software.component.html | 143 ++-
ui/src/assets/styles/main.scss | 739 +++++++---------
ui/src/assets/styles/partial/_dashboard.scss | 592 ++-----------
ui/src/assets/styles/partial/_defines.scss | 817 +++++++++---------
ui/src/assets/styles/partial/_dialog.scss | 82 +-
ui/src/assets/styles/partial/_feedback.scss | 3 -
ui/src/assets/styles/partial/_room.scss | 74 --
ui/src/assets/styles/partial/_vmenu.scss | 393 ---------
ui/src/main.ts | 2 +-
25 files changed, 1437 insertions(+), 2136 deletions(-)
rename ui/src/app/{app.routing.ts => app.routes.ts} (50%)
create mode 100644 ui/src/app/facility/rooms/rooms.component.scss
create mode 100644 ui/src/app/navigation/navigation.component.scss
create mode 100644 ui/src/app/shared/styles.scss
delete mode 100644 ui/src/assets/styles/partial/_room.scss
delete mode 100644 ui/src/assets/styles/partial/_vmenu.scss
diff --git a/ui/src/app/app.routing.ts b/ui/src/app/app.routes.ts
similarity index 50%
rename from ui/src/app/app.routing.ts
rename to ui/src/app/app.routes.ts
index c35a5665c..7b94270e1 100644
--- a/ui/src/app/app.routing.ts
+++ b/ui/src/app/app.routes.ts
@@ -1,39 +1,20 @@
-/*
- * Copyright (c) 2017 Exam Consortium
- *
- * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent
- * versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- *
- * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed
- * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and limitations under the Licence.
- */
import { inject } from '@angular/core';
import { Route } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { map, Observable } from 'rxjs';
import { AppComponent } from './app.component';
-import { CalendarComponent } from './calendar/calendar.component';
-import { StudentDashboardComponent } from './dashboard/student/student-dashboard.component';
-import { ExamEnrolmentsComponent } from './enrolment/exams/exam-enrolments.component';
-import { CollaborativeParticipationsComponent } from './enrolment/finished/collaborative-exam-participations.component';
-import { ExamParticipationsComponent } from './enrolment/finished/exam-participations.component';
-import { CollaborativeExamSearchComponent } from './enrolment/search/collaborative-exam-search.component';
-import { ExamSearchComponent } from './enrolment/search/exam-search.component';
-import { WaitingRoomComponent } from './enrolment/waiting-room/waiting-room.component';
-import { WrongLocationComponent } from './enrolment/wrong-location/wrong-location.component';
-import { ExaminationComponent } from './examination/examination.component';
-import { ExaminationLogoutComponent } from './examination/logout/examination-logout.component';
import { LogoutComponent } from './session/logout/logout.component';
const buildTitle = (key: string, extraPart = ''): Observable => {
const tx = inject(TranslateService);
const extra = extraPart ? ` ${extraPart}` : '';
- return tx.get(key).pipe(map(() => `${tx.instant(key)}${extra} - EXAM`));
+ return tx.get(key).pipe(
+ map(
+ () =>
+ `${tx.instant(key)}${extra}
+ - EXAM`,
+ ),
+ );
};
export const APP_ROUTES: Route[] = [
@@ -45,7 +26,8 @@ export const APP_ROUTES: Route[] = [
},
{
path: 'dashboard',
- component: StudentDashboardComponent,
+ loadComponent: () =>
+ import('./dashboard/student/student-dashboard.component').then((mod) => mod.StudentDashboardComponent),
title: () => buildTitle('i18n_enrolments_title'),
},
{
@@ -54,25 +36,28 @@ export const APP_ROUTES: Route[] = [
},
{
path: 'exam/:hash',
- component: ExaminationComponent,
data: {
isPreview: false,
},
title: () => buildTitle('i18n_examination_title'),
+ loadComponent: () => import('./examination/examination.component').then((mod) => mod.ExaminationComponent),
},
{
path: 'waitingroom/:id/:hash',
- component: WaitingRoomComponent,
+ loadComponent: () =>
+ import('./enrolment/waiting-room/waiting-room.component').then((mod) => mod.WaitingRoomComponent),
title: () => buildTitle('i18n_waiting_room_title'),
},
{
path: 'waitingroom',
- component: WaitingRoomComponent,
+ loadComponent: () =>
+ import('./enrolment/waiting-room/waiting-room.component').then((mod) => mod.WaitingRoomComponent),
title: () => buildTitle('i18n_waiting_room_title'),
},
{
path: 'wrongroom/:eid/:mid',
- component: WrongLocationComponent,
+ loadComponent: () =>
+ import('./enrolment/wrong-location/wrong-location.component').then((mod) => mod.WrongLocationComponent),
data: {
cause: 'room',
},
@@ -80,7 +65,8 @@ export const APP_ROUTES: Route[] = [
},
{
path: 'wrongmachine/:eid/:mid',
- component: WrongLocationComponent,
+ loadComponent: () =>
+ import('./enrolment/wrong-location/wrong-location.component').then((mod) => mod.WrongLocationComponent),
data: {
cause: 'machine',
},
@@ -88,37 +74,46 @@ export const APP_ROUTES: Route[] = [
},
{
path: 'exams',
- component: ExamSearchComponent,
+ loadComponent: () => import('./enrolment/search/exam-search.component').then((mod) => mod.ExamSearchComponent),
title: () => buildTitle('i18n_exams_title'),
},
{
path: 'exams/collaborative',
- component: CollaborativeExamSearchComponent,
+ loadComponent: () =>
+ import('./enrolment/search/collaborative-exam-search.component').then(
+ (mod) => mod.CollaborativeExamSearchComponent,
+ ),
title: () => buildTitle('i18n_collaborative_exams_title'),
},
{
path: 'participations',
- component: ExamParticipationsComponent,
+ loadComponent: () =>
+ import('./enrolment/finished/exam-participations.component').then((mod) => mod.ExamParticipationsComponent),
title: () => buildTitle('i18n_participations_title'),
},
{
path: 'participations/collaborative',
- component: CollaborativeParticipationsComponent,
+ loadComponent: () =>
+ import('./enrolment/finished/collaborative-exam-participations.component').then(
+ (mod) => mod.CollaborativeParticipationsComponent,
+ ),
title: () => buildTitle('i18n_collaborative_participations_title'),
},
{
path: 'examination/logout',
- component: ExaminationLogoutComponent,
+ loadComponent: () =>
+ import('./examination/logout/examination-logout.component').then((mod) => mod.ExaminationLogoutComponent),
title: () => buildTitle('i18n_examination_logout_title'),
},
{
path: 'enrolments/:id',
- component: ExamEnrolmentsComponent,
+ loadComponent: () =>
+ import('./enrolment/exams/exam-enrolments.component').then((mod) => mod.ExamEnrolmentsComponent),
title: (route) => buildTitle('i18n_enrolment_title', `#${route.params.id}`),
},
{
path: 'calendar/:id',
- component: CalendarComponent,
+ loadComponent: () => import('./calendar/calendar.component').then((mod) => mod.CalendarComponent),
data: {
isExternal: false,
isCollaborative: false,
@@ -127,22 +122,21 @@ export const APP_ROUTES: Route[] = [
},
{
path: 'calendar/:id/external',
- component: CalendarComponent,
- data: { isExternal: true },
+ loadComponent: () => import('./calendar/calendar.component').then((mod) => mod.CalendarComponent),
+ data: {
+ isExternal: true,
+ },
title: (route) => buildTitle('i18n_external_reservation_title', `#${route.params.id}`),
},
{
path: 'calendar/:id/collaborative',
- component: CalendarComponent,
- data: { isExternal: false, isCollaborative: true },
+ loadComponent: () => import('./calendar/calendar.component').then((mod) => mod.CalendarComponent),
+ data: {
+ isExternal: false,
+ isCollaborative: true,
+ },
title: (route) => buildTitle('i18n_collaborative_reservation_title', `#${route.params.id}`),
},
- /*
- { // this does not work apparently because admin code uses some of calendar dependencies
-- path: 'calendar',
-- loadChildren: () => import('./calendar/calendar.module').then((mod) => mod.CalendarModule),
-- },
- */
{
path: 'staff',
loadChildren: () => import('./dashboard/staff/staff.routes').then((mod) => mod.STAFF_ROUTES),
diff --git a/ui/src/app/calendar/booking-calendar.component.ts b/ui/src/app/calendar/booking-calendar.component.ts
index b31bef2b0..905a58bdf 100644
--- a/ui/src/app/calendar/booking-calendar.component.ts
+++ b/ui/src/app/calendar/booking-calendar.component.ts
@@ -44,7 +44,7 @@ import { CalendarService } from './calendar.service';
template: `
@if (visible) {
-
+
@if (visible) {
diff --git a/ui/src/app/calendar/calendar.component.html b/ui/src/app/calendar/calendar.component.html
index f689de85f..69dbc59f5 100644
--- a/ui/src/app/calendar/calendar.component.html
+++ b/ui/src/app/calendar/calendar.component.html
@@ -1,5 +1,5 @@
-
+
{{ 'i18n_calendar' | translate }}
@@ -16,7 +16,7 @@
{{ 'i18n_calendar' | translate }}
}
@if (examInfo && hasOptionalSections()) {
-
+
{{ 'i18n_calendar' | translate }}
}
@if (isInteroperable && isExternal) {
-
+
{{ 'i18n_calendar' | translate }}
}
-
+
{{ 'i18n_calendar' | translate }}
-
-
+
+
-
+
{{ getSequenceNumber('confirmation') }}. {{ 'i18n_calendar_phase_3' | translate }}
@@ -133,8 +133,8 @@
-
-
+
+
-
+
-
+
{{ 'i18n_course_name' | translate }}:
@@ -61,7 +61,7 @@ import type { ExamInfo } from '../calendar.service';
-
+
{{ 'i18n_calendar_instructions' | translate }}:
@@ -69,7 +69,7 @@ import type { ExamInfo } from '../calendar.service';
-
+
@if (showReservationWindowDescription()) {
diff --git a/ui/src/app/calendar/helpers/organisation-picker.component.ts b/ui/src/app/calendar/helpers/organisation-picker.component.ts
index 343403da7..c937aa7b8 100644
--- a/ui/src/app/calendar/helpers/organisation-picker.component.ts
+++ b/ui/src/app/calendar/helpers/organisation-picker.component.ts
@@ -8,10 +8,7 @@ import { CalendarService } from '../calendar.service';
@Component({
selector: 'xm-calendar-organisation-picker',
template: `
-
+
@@ -29,7 +26,7 @@ import { CalendarService } from '../calendar.service';
-
+
-
+
@if (!disabled) {
@@ -49,7 +49,7 @@ {{ sequenceNumber }}. {{ 'i18n_calendar_phase_2
-
+
@if (selectedRoom) {
-
+
{{ sequenceNumber }}. {{ 'i18n_calendar_phase_2
}
@if (selectedRoom) {
-
+
-
-
-
{{ 'i18n_room_accessibility_info' | translate }}
-
+
+
+
{{ 'i18n_room_accessibility_info' | translate }}
-
+
+
+
-
-
-
-
-
- {{ 'i18n_name' | translate }} |
- {{ 'i18n_edit' | translate }} |
- {{ 'i18n_remove' | translate }} |
-
-
-
- @for (accessibility of accessibilities; track accessibility) {
-
-
-
- {{ accessibility.name }}
+
+
+
+
+
+
+ {{ 'i18n_name' | translate }} |
+ {{ 'i18n_edit' | translate }} |
+ {{ 'i18n_remove' | translate }} |
+
+
+
+ @for (accessibility of accessibilities; track accessibility) {
+
+
+
+ {{ accessibility.name }}
+
+ @if (accessibility.showName) {
+
- @if (accessibility.showName) {
-
- }
- |
-
-
-
-
- |
-
-
-
-
- |
-
- }
-
-
-
+ }
+ |
+
+
+
+
+ |
+
+
+
+
+ |
+
+ }
+
+
diff --git a/ui/src/app/facility/rooms/room-mass-edit.component.ts b/ui/src/app/facility/rooms/room-mass-edit.component.ts
index fcddd28c4..3ae5f68aa 100644
--- a/ui/src/app/facility/rooms/room-mass-edit.component.ts
+++ b/ui/src/app/facility/rooms/room-mass-edit.component.ts
@@ -93,7 +93,6 @@ type SelectableRoom = ExamRoom & { selected: boolean; showBreaks: boolean };
type="checkbox"
class="form-check-input"
name="select_room"
- id="room"
[(ngModel)]="room.selected"
/>