Calendar/src/v2/demo/DemoApp.ts
Janus C. H. Knudsen d4249eecfb Adds hierarchical grouping and entity resolution support
Enhances calendar rendering with dynamic parent-child relationships between entities

Introduces EntityResolver for dot-notation references
Supports belongsTo configuration in grouping
Implements flexible filtering across hierarchical entities

Improves rendering flexibility for complex organizational structures
2025-12-15 17:10:43 +01:00

174 lines
6 KiB
TypeScript

import { CalendarOrchestrator } from '../core/CalendarOrchestrator';
import { TimeAxisRenderer } from '../features/timeaxis/TimeAxisRenderer';
import { NavigationAnimator } from '../core/NavigationAnimator';
import { DateService } from '../core/DateService';
import { ScrollManager } from '../core/ScrollManager';
import { HeaderDrawerManager } from '../core/HeaderDrawerManager';
import { IndexedDBContext } from '../storage/IndexedDBContext';
import { DataSeeder } from '../workers/DataSeeder';
import { ViewConfig } from '../core/ViewConfig';
import { DragDropManager } from '../managers/DragDropManager';
import { EdgeScrollManager } from '../managers/EdgeScrollManager';
import { ResizeManager } from '../managers/ResizeManager';
import { EventPersistenceManager } from '../managers/EventPersistenceManager';
import { HeaderDrawerRenderer } from '../features/headerdrawer/HeaderDrawerRenderer';
import { AuditService } from '../storage/audit/AuditService';
export class DemoApp {
private animator!: NavigationAnimator;
private container!: HTMLElement;
private weekOffset = 0;
private currentView: 'day' | 'simple' | 'resource' | 'team' = 'simple';
constructor(
private orchestrator: CalendarOrchestrator,
private timeAxisRenderer: TimeAxisRenderer,
private dateService: DateService,
private scrollManager: ScrollManager,
private headerDrawerManager: HeaderDrawerManager,
private indexedDBContext: IndexedDBContext,
private dataSeeder: DataSeeder,
private dragDropManager: DragDropManager,
private edgeScrollManager: EdgeScrollManager,
private resizeManager: ResizeManager,
private headerDrawerRenderer: HeaderDrawerRenderer,
private eventPersistenceManager: EventPersistenceManager,
private auditService: AuditService
) {}
async init(): Promise<void> {
// Set base date to match mock data (8. december 2025 = mandag)
this.dateService.setBaseDate(new Date('2025-12-08'));
// Initialize IndexedDB
await this.indexedDBContext.initialize();
console.log('[DemoApp] IndexedDB initialized');
// Seed data if empty
await this.dataSeeder.seedIfEmpty();
console.log('[DemoApp] Data seeding complete');
this.container = document.querySelector('swp-calendar-container') as HTMLElement;
// NavigationAnimator har DOM-dependencies - tilladt med new
this.animator = new NavigationAnimator(
document.querySelector('swp-header-track') as HTMLElement,
document.querySelector('swp-content-track') as HTMLElement
);
// Render time axis (06:00 - 18:00)
this.timeAxisRenderer.render(document.getElementById('time-axis') as HTMLElement, 6, 18);
// Init scroll synkronisering
this.scrollManager.init(this.container);
// Init header drawer
this.headerDrawerManager.init(this.container);
// Init drag-drop
this.dragDropManager.init(this.container);
// Init edge scroll
const scrollableContent = this.container.querySelector('swp-scrollable-content') as HTMLElement;
this.edgeScrollManager.init(scrollableContent);
// Init resize
this.resizeManager.init(this.container);
// Setup event handlers
this.setupNavigation();
this.setupDrawerToggle();
this.setupViewSwitching();
// Initial render
this.render();
}
private async render(): Promise<void> {
const viewConfig = this.buildViewConfig();
await this.orchestrator.render(viewConfig, this.container);
}
private buildViewConfig(): ViewConfig {
const dates = this.dateService.getWeekDates(this.weekOffset, 3);
const today = this.dateService.getWeekDates(this.weekOffset, 1);
switch (this.currentView) {
case 'day':
return {
templateId: 'day',
groupings: [
{ type: 'resource', values: ['EMP001', 'EMP002'], idProperty: 'resourceId' },
{ type: 'date', values: today, idProperty: 'date', derivedFrom: 'start' }
]
};
case 'simple':
return {
templateId: 'simple',
groupings: [
{ type: 'date', values: dates, idProperty: 'date', derivedFrom: 'start' }
]
};
case 'resource':
return {
templateId: 'resource',
groupings: [
{ type: 'resource', values: ['EMP001', 'EMP002'], idProperty: 'resourceId' },
{ type: 'date', values: dates, idProperty: 'date', derivedFrom: 'start' }
]
};
case 'team':
return {
templateId: 'team',
groupings: [
{ type: 'team', values: ['team1', 'team2'] },
{ type: 'resource', values: ['EMP001', 'EMP002', 'EMP003', 'EMP004'], idProperty: 'resourceId', belongsTo: 'team.resourceIds' },
{ type: 'date', values: dates, idProperty: 'date', derivedFrom: 'start' }
]
};
}
}
private setupNavigation(): void {
document.getElementById('btn-prev')!.onclick = () => {
this.weekOffset--;
this.animator.slide('right', () => this.render());
};
document.getElementById('btn-next')!.onclick = () => {
this.weekOffset++;
this.animator.slide('left', () => this.render());
};
}
private setupViewSwitching(): void {
document.getElementById('btn-day')?.addEventListener('click', () => {
this.currentView = 'day';
this.render();
});
document.getElementById('btn-simple')?.addEventListener('click', () => {
this.currentView = 'simple';
this.render();
});
document.getElementById('btn-resource')?.addEventListener('click', () => {
this.currentView = 'resource';
this.render();
});
document.getElementById('btn-team')?.addEventListener('click', () => {
this.currentView = 'team';
this.render();
});
}
private setupDrawerToggle(): void {
document.getElementById('btn-drawer')!.onclick = () => {
this.headerDrawerManager.toggle();
};
}
}