Introduces flexible key-based filtering for calendar events across different view configurations Adds new FilterTemplate class to: - Define event matching rules based on view configuration - Support multi-level grouping (team/resource/date) - Handle dynamic key generation for columns and events Enhances view configuration with explicit id properties and derived fields
82 lines
3.4 KiB
TypeScript
82 lines
3.4 KiB
TypeScript
import { IRenderer, IRenderContext } from './IGroupingRenderer';
|
|
import { buildPipeline } from './RenderBuilder';
|
|
import { EventRenderer } from '../features/event/EventRenderer';
|
|
import { ScheduleRenderer } from '../features/schedule/ScheduleRenderer';
|
|
import { HeaderDrawerRenderer } from '../features/headerdrawer/HeaderDrawerRenderer';
|
|
import { ViewConfig } from './ViewConfig';
|
|
import { FilterTemplate } from './FilterTemplate';
|
|
import { DateService } from './DateService';
|
|
|
|
export class CalendarOrchestrator {
|
|
constructor(
|
|
private allRenderers: IRenderer[],
|
|
private eventRenderer: EventRenderer,
|
|
private scheduleRenderer: ScheduleRenderer,
|
|
private headerDrawerRenderer: HeaderDrawerRenderer,
|
|
private dateService: DateService
|
|
) {}
|
|
|
|
async render(viewConfig: ViewConfig, container: HTMLElement): Promise<void> {
|
|
const headerContainer = container.querySelector('swp-calendar-header') as HTMLElement;
|
|
const columnContainer = container.querySelector('swp-day-columns') as HTMLElement;
|
|
if (!headerContainer || !columnContainer) {
|
|
throw new Error('Missing swp-calendar-header or swp-day-columns');
|
|
}
|
|
|
|
// Byg filter fra viewConfig
|
|
const filter: Record<string, string[]> = {};
|
|
for (const grouping of viewConfig.groupings) {
|
|
filter[grouping.type] = grouping.values;
|
|
}
|
|
|
|
// Byg FilterTemplate fra viewConfig groupings
|
|
const filterTemplate = new FilterTemplate(this.dateService);
|
|
for (const grouping of viewConfig.groupings) {
|
|
filterTemplate.addField(grouping.idProperty, grouping.derivedFrom);
|
|
}
|
|
|
|
const context: IRenderContext = { headerContainer, columnContainer, filter };
|
|
|
|
// Clear
|
|
headerContainer.innerHTML = '';
|
|
columnContainer.innerHTML = '';
|
|
|
|
// Sæt data-levels attribut for CSS grid-row styling
|
|
const levels = viewConfig.groupings.map(g => g.type).join(' ');
|
|
headerContainer.dataset.levels = levels;
|
|
|
|
// Vælg renderers baseret på groupings types
|
|
const activeRenderers = this.selectRenderers(viewConfig);
|
|
|
|
// Beregn total kolonner dynamisk
|
|
const totalColumns = this.calculateTotalColumns(viewConfig);
|
|
container.style.setProperty('--grid-columns', String(totalColumns));
|
|
|
|
// Byg og kør pipeline
|
|
const pipeline = buildPipeline(activeRenderers);
|
|
await pipeline.run(context);
|
|
|
|
// Render schedule unavailable zones (før events)
|
|
await this.scheduleRenderer.render(container, filter);
|
|
|
|
// Render timed events in grid (med filterTemplate til matching)
|
|
await this.eventRenderer.render(container, filter, filterTemplate);
|
|
|
|
// Render allDay events in header drawer (med filterTemplate til matching)
|
|
await this.headerDrawerRenderer.render(container, filter, filterTemplate);
|
|
}
|
|
|
|
private selectRenderers(viewConfig: ViewConfig): IRenderer[] {
|
|
const types = viewConfig.groupings.map(g => g.type);
|
|
// Sortér renderers i samme rækkefølge som viewConfig.groupings
|
|
return types
|
|
.map(type => this.allRenderers.find(r => r.type === type))
|
|
.filter((r): r is IRenderer => r !== undefined);
|
|
}
|
|
|
|
private calculateTotalColumns(viewConfig: ViewConfig): number {
|
|
const dateCount = viewConfig.groupings.find(g => g.type === 'date')?.values.length || 1;
|
|
const resourceCount = viewConfig.groupings.find(g => g.type === 'resource')?.values.length || 1;
|
|
return dateCount * resourceCount;
|
|
}
|
|
}
|