Implements FilterTemplate system for event matching
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
This commit is contained in:
parent
c2f7564f8e
commit
dd647acab8
8 changed files with 331 additions and 41 deletions
|
|
@ -7,6 +7,7 @@ import { CoreEvents } from '../../constants/CoreEvents';
|
|||
import { IDragColumnChangePayload, IDragMovePayload, IDragEndPayload, IDragLeaveHeaderPayload } from '../../types/DragTypes';
|
||||
import { calculateColumnLayout } from './EventLayoutEngine';
|
||||
import { IGridGroupLayout } from './EventLayoutTypes';
|
||||
import { FilterTemplate } from '../../core/FilterTemplate';
|
||||
|
||||
/**
|
||||
* EventRenderer - Renders calendar events to the DOM
|
||||
|
|
@ -238,8 +239,9 @@ export class EventRenderer {
|
|||
* Render events for visible dates into day columns
|
||||
* @param container - Calendar container element
|
||||
* @param filter - Filter with 'date' and optionally 'resource' arrays
|
||||
* @param filterTemplate - Template for matching events to columns
|
||||
*/
|
||||
async render(container: HTMLElement, filter: Record<string, string[]>): Promise<void> {
|
||||
async render(container: HTMLElement, filter: Record<string, string[]>, filterTemplate: FilterTemplate): Promise<void> {
|
||||
// Store container reference for later re-renders
|
||||
this.container = container;
|
||||
|
||||
|
|
@ -261,26 +263,12 @@ export class EventRenderer {
|
|||
|
||||
const columns = dayColumns.querySelectorAll('swp-day-column');
|
||||
|
||||
// Render events into each column based on data attributes
|
||||
// Render events into each column based on FilterTemplate matching
|
||||
columns.forEach(column => {
|
||||
const date = (column as HTMLElement).dataset.date;
|
||||
const columnResourceId = (column as HTMLElement).dataset.resourceId;
|
||||
const columnEl = column as HTMLElement;
|
||||
|
||||
if (!date) return;
|
||||
|
||||
// Filter events for this column
|
||||
const columnEvents = events.filter(event => {
|
||||
// Must match date
|
||||
if (this.dateService.getDateKey(event.start) !== date) return false;
|
||||
|
||||
// If column has resourceId, event must match
|
||||
if (columnResourceId && event.resourceId !== columnResourceId) return false;
|
||||
|
||||
// If no resourceId on column but resources in filter, show all
|
||||
// (this handles 'simple' view without resources)
|
||||
|
||||
return true;
|
||||
});
|
||||
// Use FilterTemplate for matching - only fields in template are checked
|
||||
const columnEvents = events.filter(event => filterTemplate.matches(event, columnEl));
|
||||
|
||||
// Get or create events layer
|
||||
let eventsLayer = column.querySelector('swp-events-layer');
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { CoreEvents } from '../../constants/CoreEvents';
|
|||
import { HeaderDrawerManager } from '../../core/HeaderDrawerManager';
|
||||
import { EventService } from '../../storage/events/EventService';
|
||||
import { DateService } from '../../core/DateService';
|
||||
import { FilterTemplate } from '../../core/FilterTemplate';
|
||||
import {
|
||||
IDragEnterHeaderPayload,
|
||||
IDragMoveHeaderPayload,
|
||||
|
|
@ -36,6 +37,7 @@ export class HeaderDrawerRenderer {
|
|||
private container: HTMLElement | null = null;
|
||||
private sourceElement: HTMLElement | null = null;
|
||||
private wasExpandedBeforeDrag = false;
|
||||
private filterTemplate: FilterTemplate | null = null;
|
||||
|
||||
constructor(
|
||||
private eventBus: IEventBus,
|
||||
|
|
@ -49,8 +51,12 @@ export class HeaderDrawerRenderer {
|
|||
|
||||
/**
|
||||
* Render allDay events into the header drawer with row stacking
|
||||
* @param filterTemplate - Template for matching events to columns
|
||||
*/
|
||||
async render(container: HTMLElement, filter: Record<string, string[]>): Promise<void> {
|
||||
async render(container: HTMLElement, filter: Record<string, string[]>, filterTemplate: FilterTemplate): Promise<void> {
|
||||
// Store filterTemplate for buildColumnKeyFromEvent
|
||||
this.filterTemplate = filterTemplate;
|
||||
|
||||
const drawer = container.querySelector('swp-header-drawer');
|
||||
if (!drawer) return;
|
||||
|
||||
|
|
@ -150,14 +156,24 @@ export class HeaderDrawerRenderer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Build columnKey from event fields
|
||||
* This is the only place we construct columnKey from event data
|
||||
* Build columnKey from event using FilterTemplate
|
||||
* Uses the same template that columns use for matching
|
||||
*/
|
||||
private buildColumnKeyFromEvent(event: ICalendarEvent, date?: Date): string {
|
||||
const dateStr = this.dateService.getDateKey(date || event.start);
|
||||
const segments: Record<string, string> = { date: dateStr };
|
||||
if (event.resourceId) segments.resource = event.resourceId;
|
||||
return this.dateService.buildColumnKey(segments);
|
||||
if (!this.filterTemplate) {
|
||||
// Fallback if no template - shouldn't happen in normal flow
|
||||
const dateStr = this.dateService.getDateKey(date || event.start);
|
||||
return dateStr;
|
||||
}
|
||||
|
||||
// For multi-day events, we need to override the date in the event
|
||||
if (date && date.getTime() !== event.start.getTime()) {
|
||||
// Create temporary event with overridden start for key generation
|
||||
const tempEvent = { ...event, start: date };
|
||||
return this.filterTemplate.buildKeyFromEvent(tempEvent);
|
||||
}
|
||||
|
||||
return this.filterTemplate.buildKeyFromEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue