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
4.7 KiB
FilterTemplate System
Problem
En kolonne har en unik nøgle baseret på view-konfigurationen (f.eks. team + resource + date). Events skal matches mod denne nøgle - men kun på de felter viewet definerer.
Løsning: FilterTemplate
ViewConfig definerer hvilke felter (idProperties) der indgår i kolonnens nøgle. Samme template bruges til at bygge nøgle for både kolonne og event.
Princip: Kolonnens nøgle-template bestemmer hvad der matches på.
ViewConfig med idProperty
ViewConfig er kilden til sandhed - den definerer grupper OG deres relations-id property.
interface GroupingConfig {
type: string; // 'team', 'resource', 'date'
values: string[]; // ['EMP001', 'EMP002']
idProperty: string; // property-navn på event (eks. 'resourceId')
derivedFrom?: string; // for date: udledes fra 'start'
}
Eksempler
Team → Resource → Date view:
{
groupings: [
{ type: 'team', values: ['team-a'], idProperty: 'teamId' },
{ type: 'resource', values: ['EMP001', 'EMP002'], idProperty: 'resourceId' },
{ type: 'date', values: ['2025-12-09', '2025-12-10'], idProperty: 'date', derivedFrom: 'start' }
]
}
Simple date-only view:
{
groupings: [
{ type: 'date', values: ['2025-12-09', '2025-12-10'], idProperty: 'date', derivedFrom: 'start' }
]
}
FilterTemplate Klasse
class FilterTemplate {
private fields: Array<{
idProperty: string;
derivedFrom?: string;
}> = [];
addField(idProperty: string, derivedFrom?: string): this {
this.fields.push({ idProperty, derivedFrom });
return this;
}
buildKeyFromColumn(column: HTMLElement): string {
return this.fields
.map(f => column.dataset[f.idProperty] || '')
.join(':');
}
buildKeyFromEvent(event: ICalendarEvent, dateService: DateService): string {
return this.fields
.map(f => {
if (f.derivedFrom) {
return dateService.getDateKey((event as any)[f.derivedFrom]);
}
return (event as any)[f.idProperty] || '';
})
.join(':');
}
}
Flow
Orchestrator
│
├── Læs ViewConfig.groupings
│
├── Byg FilterTemplate fra groupings:
│ for (grouping of viewConfig.groupings) {
│ template.addField(grouping.idProperty, grouping.derivedFrom);
│ }
│
├── Kør group-renderers (bygger headers + kolonner)
│ └── DateRenderer sætter column.dataset[idProperty] for ALLE grupperinger
│
└── EventRenderer.render(ctx, template)
│
└── for each column:
columnKey = template.buildKeyFromColumn(column)
columnEvents = events.filter(e =>
template.buildKeyFromEvent(e) === columnKey
)
Eksempler
3-niveau view: Team → Resource → Date
ViewConfig:
groupings: [
{ type: 'team', values: ['team-a'], idProperty: 'teamId' },
{ type: 'resource', values: ['EMP001'], idProperty: 'resourceId' },
{ type: 'date', values: ['2025-12-09'], idProperty: 'date', derivedFrom: 'start' }
]
Template: ['teamId', 'resourceId', 'date']
Kolonne-nøgle: "team-a:EMP001:2025-12-09"
Event-nøgle: "team-a:EMP001:2025-12-09"
Match!
2-niveau view: Resource → Date
ViewConfig:
groupings: [
{ type: 'resource', values: ['EMP001'], idProperty: 'resourceId' },
{ type: 'date', values: ['2025-12-09'], idProperty: 'date', derivedFrom: 'start' }
]
Template: ['resourceId', 'date']
Kolonne-nøgle: "EMP001:2025-12-09"
Event-nøgle: "EMP001:2025-12-09" (teamId ignoreres - ikke i template)
Match!
1-niveau view: Kun Date
ViewConfig:
groupings: [
{ type: 'date', values: ['2025-12-09'], idProperty: 'date', derivedFrom: 'start' }
]
Template: ['date']
Kolonne-nøgle: "2025-12-09"
Event-nøgle: "2025-12-09" (alle andre felter ignoreres)
Match! Samme event vises i alle views - kun de relevante felter indgår i matching.
Kerneprincipper
- ViewConfig definerer nøgle-template - hvilke idProperties der indgår
- Samme template til kolonne og event - sikrer konsistent matching
- Felter udenfor template ignoreres - event med ekstra felter matcher stadig
- idProperty - eksplicit mapping mellem gruppering og event-felt
- derivedFrom - håndterer felter der udledes (f.eks. date fra start)