From 6edff77bb45c8fcdb24bdf6e959d08bfcd080c4f Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Thu, 17 Jul 2025 11:21:36 +0200 Subject: [PATCH] refactor: convert to signals --- .../schedule-week.component.html | 32 ++--- .../schedule-week/schedule-week.component.ts | 121 +++++++++--------- 2 files changed, 76 insertions(+), 77 deletions(-) diff --git a/src/app/features/schedule/schedule-week/schedule-week.component.html b/src/app/features/schedule/schedule-week/schedule-week.component.html index 62639fd0a..573420c79 100644 --- a/src/app/features/schedule/schedule-week/schedule-week.component.html +++ b/src/app/features/schedule/schedule-week/schedule-week.component.html @@ -1,7 +1,7 @@
@@ -24,12 +24,12 @@ } - @for (day of daysToShow; track $index) { + @for (day of daysToShow(); track $index) {
{{ T.F.SCHEDULE.PLAN_START_DAY | translate }}
@@ -38,24 +38,26 @@ class="col end-of-day" [attr.data-day]="day" style="grid-column: {{ $index + 2 }}; grid-row: {{ - $index === 0 ? currentTimeRow : endOfDayColRowStart - }} / span {{ totalRows - ($index === 0 ? currentTimeRow : endOfDayColRowStart) }}" + $index === 0 ? currentTimeRow() : endOfDayColRowStart() + }} / span {{ + totalRows - ($index === 0 ? currentTimeRow() : endOfDayColRowStart()) + }}" >
{{ T.F.SCHEDULE.PLAN_END_DAY | translate }}
} - @if (workStartEnd) { + @if (workStartEnd()) {
{{ T.F.SCHEDULE.START | translate }}
{{ T.F.SCHEDULE.END | translate }}
@@ -63,13 +65,13 @@
- @for (ev of safeEvents; track ev.id) { + @for (ev of safeEvents(); track ev.id) { @if ( ev.type === SVEType.Task || ev.type === SVEType.SplitTask || @@ -92,7 +94,7 @@ } - @for (beyondBudgetDay of safeBeyondBudget; track i; let i = $index) { + @for (beyondBudgetDay of safeBeyondBudget(); track i; let i = $index) { @if (beyondBudgetDay.length > 0) {
diff --git a/src/app/features/schedule/schedule-week/schedule-week.component.ts b/src/app/features/schedule/schedule-week/schedule-week.component.ts index f1d34dc6a..397c93303 100644 --- a/src/app/features/schedule/schedule-week/schedule-week.component.ts +++ b/src/app/features/schedule/schedule-week/schedule-week.component.ts @@ -1,16 +1,16 @@ import { ChangeDetectionStrategy, Component, - DestroyRef, ElementRef, inject, - Input, + input, LOCALE_ID, OnDestroy, OnInit, viewChild, + signal, + computed, } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; import { ScheduleEvent } from '../schedule.model'; import { CdkDrag, @@ -24,14 +24,12 @@ import { FH, SVEType, T_ID_PREFIX } from '../schedule.const'; import { throttle } from 'helpful-decorators'; import { CreateTaskPlaceholderComponent } from '../create-task-placeholder/create-task-placeholder.component'; import { ScheduleEventComponent } from '../schedule-event/schedule-event.component'; -import { AsyncPipe } from '@angular/common'; import { TranslatePipe } from '@ngx-translate/core'; import { MatIcon } from '@angular/material/icon'; import { T } from '../../../t.const'; import { IS_TOUCH_PRIMARY } from '../../../util/is-mouse-primary'; import { DRAG_DELAY_FOR_TOUCH } from '../../../app.constants'; import { MatTooltip } from '@angular/material/tooltip'; -import { ShortcutService } from '../../../core-ui/shortcut/shortcut.service'; import { Log } from '../../../core/log'; const D_HOURS = 24; @@ -43,7 +41,6 @@ const IS_NOT_DRAGGING_CLASS = 'is-not-dragging'; @Component({ selector: 'schedule-week', imports: [ - AsyncPipe, ScheduleEventComponent, CdkDrag, CreateTaskPlaceholderComponent, @@ -58,16 +55,14 @@ const IS_NOT_DRAGGING_CLASS = 'is-not-dragging'; }) export class ScheduleWeekComponent implements OnInit, OnDestroy { private _store = inject(Store); - shortcutService = inject(ShortcutService); private locale = inject(LOCALE_ID); - destroyRef = inject(DestroyRef); - @Input() events: ScheduleEvent[] | null = []; - @Input() beyondBudget: ScheduleEvent[][] | null = []; - @Input() daysToShow: string[] = []; - @Input() workStartEnd: { workStartRow: number; workEndRow: number } | null = null; - @Input() currentTimeRow: number = 0; - @Input() isCtrlPressed: boolean = false; + events = input([]); + beyondBudget = input([]); + daysToShow = input([]); + workStartEnd = input<{ workStartRow: number; workEndRow: number } | null>(null); + currentTimeRow = input(0); + isCtrlPressed = input(false); FH = FH; IS_TOUCH_PRIMARY = IS_TOUCH_PRIMARY; @@ -76,13 +71,13 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy { T: typeof T = T; rowsByNr = Array.from({ length: D_HOURS * FH }, (_, index) => index).filter( - (v, index) => index % FH === 0, + (_, index) => index % FH === 0, ); is12HourFormat = Intl.DateTimeFormat(this.locale, { hour: 'numeric' }).resolvedOptions() .hour12; - times: string[] = this.rowsByNr.map((rowVal, index) => { + times: string[] = this.rowsByNr.map((_, index) => { return this.is12HourFormat ? index >= 13 ? (index - 12).toString() + ':00 PM' @@ -90,36 +85,32 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy { : index.toString() + ':00'; }); - endOfDayColRowStart: number = D_HOURS * 0.5 * FH; + endOfDayColRowStart = signal(D_HOURS * 0.5 * FH); totalRows: number = D_HOURS * FH; - get safeEvents(): ScheduleEvent[] { - return this.events || []; - } + safeEvents = computed(() => this.events() || []); + safeBeyondBudget = computed(() => this.beyondBudget() || []); - get safeBeyondBudget(): ScheduleEvent[][] { - return this.beyondBudget || []; - } - - newTaskPlaceholder$ = new BehaviorSubject<{ + newTaskPlaceholder = signal<{ style: string; time: string; date: string; } | null>(null); - isDragging = false; - isDraggingDelayed = false; - isCreateTaskActive = false; - containerExtraClass = IS_NOT_DRAGGING_CLASS; - prevDragOverEl: HTMLElement | null = null; - dragCloneEl: HTMLElement | null = null; + isDragging = signal(false); + isDraggingDelayed = signal(false); + isCreateTaskActive = signal(false); + containerExtraClass = signal(IS_NOT_DRAGGING_CLASS); + prevDragOverEl = signal(null); + dragCloneEl = signal(null); readonly gridContainer = viewChild.required('gridContainer'); private _currentAniTimeout: number | undefined; ngOnInit(): void { - this.endOfDayColRowStart = this.workStartEnd?.workStartRow || D_HOURS * 0.5 * FH; + const workStartEnd = this.workStartEnd(); + this.endOfDayColRowStart.set(workStartEnd?.workStartRow || D_HOURS * 0.5 * FH); } ngOnDestroy(): void { @@ -129,17 +120,17 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy { onGridClick(ev: MouseEvent): void { if (ev.target instanceof HTMLElement) { if (ev.target.classList.contains('col')) { - this.isCreateTaskActive = true; + this.isCreateTaskActive.set(true); } } } @throttle(30) onMoveOverGrid(ev: MouseEvent): void { - if (this.isDragging || this.isDraggingDelayed) { + if (this.isDragging() || this.isDraggingDelayed()) { return; } - if (this.isCreateTaskActive) { + if (this.isCreateTaskActive()) { return; } @@ -173,19 +164,19 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy { const minutes = Math.floor(((row - 1) % FH) * (60 / FH)); const time = `${hours}:${minutes.toString().padStart(2, '0')}`; - this.newTaskPlaceholder$.next({ + this.newTaskPlaceholder.set({ style: `grid-row: ${row} / span 6; grid-column: ${targetColColOffset} / span 1`, time, - date: this.daysToShow[targetColColOffset - 2], + date: this.daysToShow()[targetColColOffset - 2], }); } else { - this.newTaskPlaceholder$.next(null); + this.newTaskPlaceholder.set(null); } } @throttle(30) dragMoved(ev: CdkDragMove): void { - if (!this.isDragging) { + if (!this.isDragging()) { return; } @@ -201,13 +192,14 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy { return; } - if (targetEl !== this.prevDragOverEl) { + const prevEl = this.prevDragOverEl(); + if (targetEl !== prevEl) { Log.log('dragMoved targetElChanged', targetEl); - if (this.prevDragOverEl) { - this.prevDragOverEl.classList.remove(DRAG_OVER_CLASS); + if (prevEl) { + prevEl.classList.remove(DRAG_OVER_CLASS); } - this.prevDragOverEl = targetEl; + this.prevDragOverEl.set(targetEl); if ( targetEl.classList.contains(SVEType.Task) || @@ -224,38 +216,43 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy { dragStarted(ev: CdkDragStart): void { Log.log('dragStart', ev); - this.isDragging = this.isDraggingDelayed = true; - this.containerExtraClass = IS_DRAGGING_CLASS + ' ' + ev.source.data.type; + this.isDragging.set(true); + this.isDraggingDelayed.set(true); + this.containerExtraClass.set(IS_DRAGGING_CLASS + ' ' + ev.source.data.type); const cur = ev.source.element.nativeElement; - if (this.dragCloneEl) { - this.dragCloneEl.remove(); + const cloneEl = this.dragCloneEl(); + if (cloneEl) { + cloneEl.remove(); } - this.dragCloneEl = cur.cloneNode(true) as HTMLElement; - this.dragCloneEl.style.transform = 'translateY(0)'; - this.dragCloneEl.style.opacity = '.1'; - this.dragCloneEl.classList.add(DRAG_CLONE_CLASS); - cur.parentNode?.insertBefore(this.dragCloneEl, cur); + const newCloneEl = cur.cloneNode(true) as HTMLElement; + newCloneEl.style.transform = 'translateY(0)'; + newCloneEl.style.opacity = '.1'; + newCloneEl.classList.add(DRAG_CLONE_CLASS); + cur.parentNode?.insertBefore(newCloneEl, cur); + this.dragCloneEl.set(newCloneEl); } dragReleased(ev: CdkDragRelease): void { + const prevEl = this.prevDragOverEl(); Log.log('dragReleased', { target: ev.event.target, source: ev.source.element.nativeElement, ev, - dragOverEl: this.prevDragOverEl, + dragOverEl: prevEl, }); - const target = (this.prevDragOverEl || ev.event.target) as HTMLElement; - if (this.prevDragOverEl) { - this.prevDragOverEl.classList.remove(DRAG_OVER_CLASS); - this.prevDragOverEl = null; + const target = (prevEl || ev.event.target) as HTMLElement; + if (prevEl) { + prevEl.classList.remove(DRAG_OVER_CLASS); + this.prevDragOverEl.set(null); } - if (this.dragCloneEl) { - this.dragCloneEl.remove(); + const cloneEl = this.dragCloneEl(); + if (cloneEl) { + cloneEl.remove(); } - this.isDragging = false; + this.isDragging.set(false); ev.source.element.nativeElement.style.pointerEvents = ''; ev.source.element.nativeElement.style.opacity = '0'; @@ -264,10 +261,10 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy { ev.source.element.nativeElement.style.opacity = ''; ev.source.element.nativeElement.style.pointerEvents = ''; } - this.isDraggingDelayed = false; + this.isDraggingDelayed.set(false); }, 100); - this.containerExtraClass = IS_NOT_DRAGGING_CLASS; + this.containerExtraClass.set(IS_NOT_DRAGGING_CLASS); if (target.tagName.toLowerCase() === 'div' && target.classList.contains('col')) { const isMoveToEndOfDay = target.classList.contains('end-of-day');