From 66dfe9f2efce13449df3bd58d07b2d3b802c04bb Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Wed, 17 Dec 2025 18:37:32 +0100 Subject: [PATCH] Adds resource filtering and view customization Enhances calendar view with dynamic resource selection Enables users to filter and customize calendar views by resources Introduces new event for view updates and dynamic rendering Supports flexible calendar view configuration --- src/v2/constants/CoreEvents.ts | 3 ++- src/v2/core/CalendarApp.ts | 30 ++++++++++++++++++++++++++---- src/v2/demo/DemoApp.ts | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/v2/constants/CoreEvents.ts b/src/v2/constants/CoreEvents.ts index 1425a2f..d4c9894 100644 --- a/src/v2/constants/CoreEvents.ts +++ b/src/v2/constants/CoreEvents.ts @@ -74,5 +74,6 @@ export const CoreEvents = { CALENDAR_CMD_NAVIGATE_NEXT: 'calendar:cmd:navigate:next', CALENDAR_CMD_DRAWER_TOGGLE: 'calendar:cmd:drawer:toggle', CALENDAR_CMD_RENDER: 'calendar:cmd:render', - CALENDAR_CMD_WORKWEEK_CHANGE: 'calendar:cmd:workweek:change' + CALENDAR_CMD_WORKWEEK_CHANGE: 'calendar:cmd:workweek:change', + CALENDAR_CMD_VIEW_UPDATE: 'calendar:cmd:view:update' } as const; diff --git a/src/v2/core/CalendarApp.ts b/src/v2/core/CalendarApp.ts index 375ca76..43b3c27 100644 --- a/src/v2/core/CalendarApp.ts +++ b/src/v2/core/CalendarApp.ts @@ -23,6 +23,7 @@ export class CalendarApp { private weekOffset = 0; private currentViewId = 'simple'; private workweekPreset: IWorkweekPreset | null = null; + private groupingOverrides: Map = new Map(); constructor( private orchestrator: CalendarOrchestrator, @@ -102,6 +103,12 @@ export class CalendarApp { const { presetId } = e.detail; this.handleWorkweekChange(presetId); }) as EventListener); + + // View update via EventBus + this.eventBus.on(CoreEvents.CALENDAR_CMD_VIEW_UPDATE, ((e: CustomEvent) => { + const { type, values } = e.detail; + this.handleViewUpdate(type, values); + }) as EventListener); } private async handleRenderCommand(viewId: string): Promise { @@ -131,6 +138,12 @@ export class CalendarApp { } } + private async handleViewUpdate(type: string, values: string[]): Promise { + this.groupingOverrides.set(type, values); + await this.render(); + this.emitStatus('rendered', { viewId: this.currentViewId }); + } + private async render(): Promise { const storedConfig = await this.viewConfigService.getById(this.currentViewId); if (!storedConfig) { @@ -144,12 +157,21 @@ export class CalendarApp { ? this.dateService.getWeekDates(this.weekOffset, 1) : this.dateService.getWorkWeekDates(this.weekOffset, workDays); - // Clone config and populate dates + // Clone config and apply overrides const viewConfig: ViewConfig = { ...storedConfig, - groupings: storedConfig.groupings.map(g => - g.type === 'date' ? { ...g, values: dates } : g - ) + groupings: storedConfig.groupings.map(g => { + // Apply date values + if (g.type === 'date') { + return { ...g, values: dates }; + } + // Apply grouping overrides + const override = this.groupingOverrides.get(g.type); + if (override) { + return { ...g, values: override }; + } + return g; + }) }; await this.orchestrator.render(viewConfig, this.container); diff --git a/src/v2/demo/DemoApp.ts b/src/v2/demo/DemoApp.ts index c7083cd..a36ecf0 100644 --- a/src/v2/demo/DemoApp.ts +++ b/src/v2/demo/DemoApp.ts @@ -3,6 +3,7 @@ import { DataSeeder } from '../workers/DataSeeder'; import { AuditService } from '../storage/audit/AuditService'; import { CalendarApp } from '../core/CalendarApp'; import { DateService } from '../core/DateService'; +import { ResourceService } from '../storage/resources/ResourceService'; import { IEventBus } from '../types/CalendarTypes'; import { CoreEvents } from '../constants/CoreEvents'; @@ -16,6 +17,7 @@ export class DemoApp { private auditService: AuditService, private calendarApp: CalendarApp, private dateService: DateService, + private resourceService: ResourceService, private eventBus: IEventBus ) {} @@ -42,6 +44,7 @@ export class DemoApp { this.setupDrawerToggle(); this.setupViewSwitching(); this.setupWorkweekSelector(); + await this.setupResourceSelector(); // Listen for calendar status events this.setupStatusListeners(); @@ -70,12 +73,19 @@ export class DemoApp { const view = (chip as HTMLElement).dataset.view; if (view) { this.currentView = view; + this.updateSelectorVisibility(); this.eventBus.emit(CoreEvents.CALENDAR_CMD_RENDER, { viewId: view }); } }); }); } + private updateSelectorVisibility(): void { + const selector = document.querySelector('swp-resource-selector'); + const showSelector = this.currentView === 'picker' || this.currentView === 'day'; + selector?.classList.toggle('hidden', !showSelector); + } + private setupDrawerToggle(): void { document.getElementById('btn-drawer')!.onclick = () => { this.eventBus.emit(CoreEvents.CALENDAR_CMD_DRAWER_TOGGLE); @@ -90,6 +100,29 @@ export class DemoApp { }); } + private async setupResourceSelector(): Promise { + const resources = await this.resourceService.getAll(); + const container = document.querySelector('.resource-checkboxes') as HTMLElement; + if (!container) return; + + container.innerHTML = ''; + + resources.forEach(r => { + const label = document.createElement('label'); + label.innerHTML = ` + + ${r.displayName} + `; + container.appendChild(label); + }); + + container.addEventListener('change', () => { + const checked = container.querySelectorAll('input:checked') as NodeListOf; + const values = Array.from(checked).map(cb => cb.value); + this.eventBus.emit(CoreEvents.CALENDAR_CMD_VIEW_UPDATE, { type: 'resource', values }); + }); + } + private setupStatusListeners(): void { this.container.addEventListener('calendar:status:ready', () => { console.log('[DemoApp] Calendar ready');