From 8b64bbbaba764b4bdf67578cc8751073fe1df0ec Mon Sep 17 00:00:00 2001 From: Matti Lupari Date: Fri, 12 Jan 2024 15:12:05 +0200 Subject: [PATCH] CSCEXAM-000 Introduction to signals --- .../calendar/booking-calendar.component.ts | 24 +++++---- .../calendar/helpers/exam-info.component.ts | 36 ++++++------- .../helpers/organisation-picker.component.ts | 32 +++++++----- .../helpers/selected-room.component.ts | 20 ++++--- .../helpers/slot-picker.component.html | 22 ++++---- .../calendar/helpers/slot-picker.component.ts | 52 +++++++++++-------- ui/src/app/shared/miscellaneous/helpers.ts | 6 +++ 7 files changed, 106 insertions(+), 86 deletions(-) diff --git a/ui/src/app/calendar/booking-calendar.component.ts b/ui/src/app/calendar/booking-calendar.component.ts index 8d3efb4229..b31bef2b01 100644 --- a/ui/src/app/calendar/booking-calendar.component.ts +++ b/ui/src/app/calendar/booking-calendar.component.ts @@ -24,6 +24,7 @@ import { Output, SimpleChanges, ViewChild, + signal, } from '@angular/core'; import { FullCalendarComponent, FullCalendarModule } from '@fullcalendar/angular'; import { CalendarOptions, EventApi, EventClickArg, EventInput } from '@fullcalendar/core'; @@ -46,7 +47,7 @@ import { CalendarService } from './calendar.service';
@if (visible) {
- +
}
@@ -72,13 +73,13 @@ export class BookingCalendarComponent implements OnInit, OnChanges, AfterViewIni @ViewChild('fc') calendar!: FullCalendarComponent; - calendarOptions: CalendarOptions; + calendarOptions = signal({}); constructor( private translate: TranslateService, private Calendar: CalendarService, ) { - this.calendarOptions = { + this.calendarOptions.set({ plugins: [luxon2Plugin, timeGridPlugin], initialView: 'timeGridWeek', firstDay: 1, @@ -92,9 +93,9 @@ export class BookingCalendarComponent implements OnInit, OnChanges, AfterViewIni eventMinHeight: 45, events: this.refetch, eventClick: this.eventClicked.bind(this), - }; + }); this.translate.onLangChange.subscribe((event) => { - this.calendarOptions = { ...this.calendarOptions, locale: event.lang }; + this.calendarOptions.set({ ...this.calendarOptions(), locale: event.lang }); //this.calendar.getApi().destroy(); //this.calendar.getApi().render(); }); @@ -102,7 +103,7 @@ export class BookingCalendarComponent implements OnInit, OnChanges, AfterViewIni ngOnInit() { if (this.minDate && this.maxDate) { - this.calendarOptions.validRange = { + this.calendarOptions().validRange = { end: DateTime.fromJSDate(this.maxDate).endOf('week').plus({ hours: 1 }).toFormat('yyyy-MM-dd'), start: DateTime.fromJSDate(this.minDate).startOf('week').toFormat('yyyy-MM-dd'), }; @@ -127,10 +128,13 @@ export class BookingCalendarComponent implements OnInit, OnChanges, AfterViewIni latestClosing.getHours() < 23 ? DateTime.fromJSDate(latestClosing).plus({ hour: 1 }).toJSDate() : latestClosing; - this.calendarOptions.hiddenDays = this.Calendar.getClosedWeekdays(this.room); - this.calendarOptions.slotMinTime = DateTime.fromJSDate(minTime).toFormat('HH:mm:ss'); - this.calendarOptions.slotMaxTime = DateTime.fromJSDate(maxTime).toFormat('HH:mm:ss'); - this.calendarOptions.timeZone = this.room.localTimezone; + this.calendarOptions.update((cos) => ({ + ...cos, + hiddenDays: this.Calendar.getClosedWeekdays(this.room), + slotMinTime: DateTime.fromJSDate(minTime).toFormat('HH:mm:ss'), + slotMaxTime: DateTime.fromJSDate(maxTime).toFormat('HH:mm:ss'), + timeZone: this.room.localTimezone, + })); if (this.calendar) this.calendar.getApi().refetchEvents(); } if (changes.accessibilities && this.calendar) { diff --git a/ui/src/app/calendar/helpers/exam-info.component.ts b/ui/src/app/calendar/helpers/exam-info.component.ts index c69b33ff9e..ae38b7c6ce 100644 --- a/ui/src/app/calendar/helpers/exam-info.component.ts +++ b/ui/src/app/calendar/helpers/exam-info.component.ts @@ -1,5 +1,5 @@ import { DatePipe } from '@angular/common'; -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, computed, signal } from '@angular/core'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { DateTime } from 'luxon'; import { DateTimeService } from '../../shared/date/date.service'; @@ -71,10 +71,10 @@ import type { ExamInfo } from '../calendar.service';
- @if (showReservationWindowInfo()) { + @if (showReservationWindowDescription()) { - {{ getReservationWindowDescription() }} + {{ reservationWindowDescription() }} }
@@ -90,7 +90,18 @@ export class CalendarExamInfoComponent implements OnInit { @Input() reservationWindowSize = 0; @Input() collaborative = false; - reservationWindowEndDate = new Date(); + reservationWindowEndDate = signal(new Date()); + reservationWindowDescription = computed(() => { + const text = this.translate + .instant('i18n_description_reservation_window') + .replace('{}', this.reservationWindowSize.toString()); + return `${text} (${DateTime.fromJSDate(this.reservationWindowEndDate()).toFormat('dd.MM.yyyy')})`; + }); + showReservationWindowDescription = computed( + () => + !!this.reservationWindowEndDate && + DateTime.fromISO(this.examInfo.periodEnd as string).toJSDate() > this.reservationWindowEndDate(), + ); constructor( private translate: TranslateService, @@ -98,21 +109,10 @@ export class CalendarExamInfoComponent implements OnInit { ) {} ngOnInit() { - this.reservationWindowEndDate = DateTime.fromJSDate(this.reservationWindowEndDate) - .plus({ day: this.reservationWindowSize }) - .toJSDate(); + this.reservationWindowEndDate.set( + DateTime.fromJSDate(this.reservationWindowEndDate()).plus({ day: this.reservationWindowSize }).toJSDate(), + ); } printExamDuration = (exam: { duration: number }) => this.DateTimeService.printExamDuration(exam); - - getReservationWindowDescription(): string { - const text = this.translate - .instant('i18n_description_reservation_window') - .replace('{}', this.reservationWindowSize.toString()); - return `${text} (${DateTime.fromJSDate(this.reservationWindowEndDate).toFormat('dd.MM.yyyy')})`; - } - - showReservationWindowInfo = (): boolean => - !!this.reservationWindowEndDate && - DateTime.fromISO(this.examInfo.periodEnd as string).toJSDate() > this.reservationWindowEndDate; } diff --git a/ui/src/app/calendar/helpers/organisation-picker.component.ts b/ui/src/app/calendar/helpers/organisation-picker.component.ts index 57ab7fc4fb..343403da76 100644 --- a/ui/src/app/calendar/helpers/organisation-picker.component.ts +++ b/ui/src/app/calendar/helpers/organisation-picker.component.ts @@ -1,5 +1,5 @@ import { NgClass } from '@angular/common'; -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, signal } from '@angular/core'; import { NgbDropdown, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; import type { Organisation } from '../calendar.service'; @@ -8,7 +8,10 @@ import { CalendarService } from '../calendar.service'; @Component({ selector: 'xm-calendar-organisation-picker', template: ` -
+
@@ -17,7 +20,7 @@ import { CalendarService } from '../calendar.service'; - @if (selectedOrganisation) { + @if (selectedOrganisation()) { @@ -41,7 +44,7 @@ import { CalendarService } from '../calendar.service'; {{ 'i18n_faculty_name' | translate }} 
    - @for (org of organisations; track org.code) { + @for (org of organisations(); track org.code) {
- @if (selectedOrganisation) { + @if (selectedOrganisation()) {
- {{ selectedOrganisation?.name }} ({{ selectedOrganisation?.code }}) + {{ selectedOrganisation()?.name }} ({{ selectedOrganisation()?.code }})
@@ -86,21 +91,22 @@ export class OrganisationPickerComponent implements OnInit { @Output() selected = new EventEmitter(); @Output() cancelled = new EventEmitter(); - organisations: Organisation[] = []; - selectedOrganisation?: Organisation; + organisations = signal([]); + selectedOrganisation = signal(undefined); constructor(private Calendar: CalendarService) {} ngOnInit() { - this.Calendar.listOrganisations$().subscribe( - (resp) => (this.organisations = resp.filter((org) => !org.homeOrg && org.facilities.length > 0)), + this.Calendar.listOrganisations$().subscribe((resp) => + this.organisations.set(resp.filter((org) => !org.homeOrg && org.facilities.length > 0)), ); } setOrganisation = (organisation: Organisation) => { - this.organisations.forEach((o) => (o.filtered = false)); - organisation.filtered = true; - this.selectedOrganisation = organisation; + const orgs = this.organisations().map((o) => ({ ...o, filtered: false })); + const i = this.organisations().findIndex((o) => o._id === organisation._id); + this.organisations.set(orgs.splice(i, 1, { ...orgs[i], filtered: true })); + this.selectedOrganisation.set({ ...organisation, filtered: true }); this.selected.emit(organisation); }; diff --git a/ui/src/app/calendar/helpers/selected-room.component.ts b/ui/src/app/calendar/helpers/selected-room.component.ts index 60cff89daa..faf7c61c76 100644 --- a/ui/src/app/calendar/helpers/selected-room.component.ts +++ b/ui/src/app/calendar/helpers/selected-room.component.ts @@ -1,5 +1,5 @@ import { DatePipe, NgClass, UpperCasePipe } from '@angular/common'; -import { Component, Input, OnChanges, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, OnInit, signal } from '@angular/core'; import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { DateTime } from 'luxon'; @@ -29,7 +29,7 @@ import { CalendarService } from '../calendar.service';
- @for (oh of openingHours; track oh.ord) { + @for (oh of openingHours(); track oh.ord) {
{{ oh.name | uppercase }}
{{ oh.periodText }}
@@ -55,7 +55,7 @@ import { CalendarService } from '../calendar.service';
{{ 'i18n_exception_datetimes' | translate }}:
- @for (eh of exceptionHours; track eh.id) { + @for (eh of exceptionHours(); track eh.id) {
([]); + exceptionHours = signal<(ExceptionWorkingHours & { start: string; end: string; description: string })[]>([]); constructor( private translate: TranslateService, @@ -99,7 +99,7 @@ export class SelectedRoomComponent implements OnInit, OnChanges { ngOnInit() { this.translate.onLangChange.subscribe(() => { - this.openingHours = this.Calendar.processOpeningHours(this.room); + this.openingHours.set(this.Calendar.processOpeningHours(this.room)); }); } @@ -123,11 +123,9 @@ export class SelectedRoomComponent implements OnInit, OnChanges { this.room.accessibilities ? this.room.accessibilities.map((a) => a.name).join(', ') : ''; private init() { - this.openingHours = this.Calendar.processOpeningHours(this.room); - this.exceptionHours = this.Calendar.getExceptionHours( - this.room, - this.viewStart, - this.viewStart.plus({ week: 1 }), + this.openingHours.set(this.Calendar.processOpeningHours(this.room)); + this.exceptionHours.set( + this.Calendar.getExceptionHours(this.room, this.viewStart, this.viewStart.plus({ week: 1 })), ); } } diff --git a/ui/src/app/calendar/helpers/slot-picker.component.html b/ui/src/app/calendar/helpers/slot-picker.component.html index 5bd936ed20..5e500f84a0 100644 --- a/ui/src/app/calendar/helpers/slot-picker.component.html +++ b/ui/src/app/calendar/helpers/slot-picker.component.html @@ -20,15 +20,15 @@

{{ sequenceNumber }}. {{ 'i18n_calendar_phase_2 @if (!disabled) { @@ -38,7 +38,7 @@

{{ sequenceNumber }}. {{ 'i18n_calendar_phase_2 {{ 'i18n_calendar_room_accessibility_info' | translate }} } -
+
@@ -48,7 +48,7 @@

{{ sequenceNumber }}. {{ 'i18n_calendar_phase_2

- @for (accessibility of accessibilities; track accessibility.id) { + @for (accessibility of accessibilities(); track accessibility.id) {