Adds header drawer event rendering support
Extends calendar rendering to support all-day events in header drawer Implements rendering logic for all-day events in header drawer: - Fetches events for visible date range - Filters and creates header items for all-day events - Dynamically positions events with color classes - Expands header drawer when events are present Enhances event persistence with header drop detection
This commit is contained in:
parent
f670598e7a
commit
d88956f47b
3 changed files with 92 additions and 4 deletions
|
|
@ -2,13 +2,15 @@ import { IRenderer, IRenderContext } from './IGroupingRenderer';
|
||||||
import { buildPipeline } from './RenderBuilder';
|
import { buildPipeline } from './RenderBuilder';
|
||||||
import { EventRenderer } from '../features/event/EventRenderer';
|
import { EventRenderer } from '../features/event/EventRenderer';
|
||||||
import { ScheduleRenderer } from '../features/schedule/ScheduleRenderer';
|
import { ScheduleRenderer } from '../features/schedule/ScheduleRenderer';
|
||||||
|
import { HeaderDrawerRenderer } from '../features/headerdrawer/HeaderDrawerRenderer';
|
||||||
import { ViewConfig } from './ViewConfig';
|
import { ViewConfig } from './ViewConfig';
|
||||||
|
|
||||||
export class CalendarOrchestrator {
|
export class CalendarOrchestrator {
|
||||||
constructor(
|
constructor(
|
||||||
private allRenderers: IRenderer[],
|
private allRenderers: IRenderer[],
|
||||||
private eventRenderer: EventRenderer,
|
private eventRenderer: EventRenderer,
|
||||||
private scheduleRenderer: ScheduleRenderer
|
private scheduleRenderer: ScheduleRenderer,
|
||||||
|
private headerDrawerRenderer: HeaderDrawerRenderer
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async render(viewConfig: ViewConfig, container: HTMLElement): Promise<void> {
|
async render(viewConfig: ViewConfig, container: HTMLElement): Promise<void> {
|
||||||
|
|
@ -48,8 +50,11 @@ export class CalendarOrchestrator {
|
||||||
// Render schedule unavailable zones (før events)
|
// Render schedule unavailable zones (før events)
|
||||||
await this.scheduleRenderer.render(container, filter);
|
await this.scheduleRenderer.render(container, filter);
|
||||||
|
|
||||||
// Render events med hele filter (date + resource)
|
// Render timed events in grid
|
||||||
await this.eventRenderer.render(container, filter);
|
await this.eventRenderer.render(container, filter);
|
||||||
|
|
||||||
|
// Render allDay events in header drawer
|
||||||
|
await this.headerDrawerRenderer.render(container, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private selectRenderers(viewConfig: ViewConfig): IRenderer[] {
|
private selectRenderers(viewConfig: ViewConfig): IRenderer[] {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
import { IEventBus } from '../../types/CalendarTypes';
|
import { IEventBus, ICalendarEvent } from '../../types/CalendarTypes';
|
||||||
import { IGridConfig } from '../../core/IGridConfig';
|
import { IGridConfig } from '../../core/IGridConfig';
|
||||||
import { CoreEvents } from '../../constants/CoreEvents';
|
import { CoreEvents } from '../../constants/CoreEvents';
|
||||||
import { HeaderDrawerManager } from '../../core/HeaderDrawerManager';
|
import { HeaderDrawerManager } from '../../core/HeaderDrawerManager';
|
||||||
|
import { EventService } from '../../storage/events/EventService';
|
||||||
|
import { DateService } from '../../core/DateService';
|
||||||
import {
|
import {
|
||||||
IDragEnterHeaderPayload,
|
IDragEnterHeaderPayload,
|
||||||
IDragMoveHeaderPayload,
|
IDragMoveHeaderPayload,
|
||||||
|
|
@ -26,11 +28,90 @@ export class HeaderDrawerRenderer {
|
||||||
constructor(
|
constructor(
|
||||||
private eventBus: IEventBus,
|
private eventBus: IEventBus,
|
||||||
private gridConfig: IGridConfig,
|
private gridConfig: IGridConfig,
|
||||||
private headerDrawerManager: HeaderDrawerManager
|
private headerDrawerManager: HeaderDrawerManager,
|
||||||
|
private eventService: EventService,
|
||||||
|
private dateService: DateService
|
||||||
) {
|
) {
|
||||||
this.setupListeners();
|
this.setupListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render allDay events into the header drawer
|
||||||
|
*/
|
||||||
|
async render(container: HTMLElement, filter: Record<string, string[]>): Promise<void> {
|
||||||
|
const drawer = container.querySelector('swp-header-drawer');
|
||||||
|
if (!drawer) return;
|
||||||
|
|
||||||
|
const visibleDates = filter['date'] || [];
|
||||||
|
if (visibleDates.length === 0) return;
|
||||||
|
|
||||||
|
// Fetch events for date range
|
||||||
|
const startDate = new Date(visibleDates[0]);
|
||||||
|
const endDate = new Date(visibleDates[visibleDates.length - 1]);
|
||||||
|
endDate.setHours(23, 59, 59, 999);
|
||||||
|
|
||||||
|
const events = await this.eventService.getByDateRange(startDate, endDate);
|
||||||
|
|
||||||
|
// Filter to allDay events only (allDay !== false)
|
||||||
|
const allDayEvents = events.filter(event => event.allDay !== false);
|
||||||
|
|
||||||
|
// Clear existing items
|
||||||
|
drawer.innerHTML = '';
|
||||||
|
|
||||||
|
// Render each allDay event
|
||||||
|
allDayEvents.forEach(event => {
|
||||||
|
const item = this.createHeaderItem(event, visibleDates);
|
||||||
|
if (item) drawer.appendChild(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Expand drawer if there are items
|
||||||
|
if (allDayEvents.length > 0) {
|
||||||
|
this.headerDrawerManager.expand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a header item element for an allDay event
|
||||||
|
*/
|
||||||
|
private createHeaderItem(event: ICalendarEvent, visibleDates: string[]): HTMLElement | null {
|
||||||
|
const dateKey = this.dateService.getDateKey(event.start);
|
||||||
|
const colIndex = visibleDates.indexOf(dateKey);
|
||||||
|
if (colIndex === -1) return null; // Event not in visible range
|
||||||
|
|
||||||
|
const item = document.createElement('swp-header-item');
|
||||||
|
item.dataset.eventId = event.id;
|
||||||
|
item.dataset.itemType = 'event';
|
||||||
|
item.dataset.date = dateKey;
|
||||||
|
item.textContent = event.title;
|
||||||
|
|
||||||
|
// Color class
|
||||||
|
const colorClass = this.getColorClass(event);
|
||||||
|
if (colorClass) item.classList.add(colorClass);
|
||||||
|
|
||||||
|
// Grid position (1-indexed)
|
||||||
|
const col = colIndex + 1;
|
||||||
|
item.style.gridArea = `1 / ${col} / 2 / ${col + 1}`;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get color class based on event metadata or type
|
||||||
|
*/
|
||||||
|
private getColorClass(event: ICalendarEvent): string {
|
||||||
|
if (event.metadata?.color) {
|
||||||
|
return `is-${event.metadata.color}`;
|
||||||
|
}
|
||||||
|
const typeColors: Record<string, string> = {
|
||||||
|
'customer': 'is-blue',
|
||||||
|
'vacation': 'is-green',
|
||||||
|
'break': 'is-amber',
|
||||||
|
'meeting': 'is-purple',
|
||||||
|
'blocked': 'is-red'
|
||||||
|
};
|
||||||
|
return typeColors[event.type] || 'is-blue';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup event listeners for drag events
|
* Setup event listeners for drag events
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,13 @@ export class EventPersistenceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update and save - start/end already calculated in SwpEvent
|
// Update and save - start/end already calculated in SwpEvent
|
||||||
|
// If dropped in header, mark as allDay
|
||||||
const updatedEvent: ICalendarEvent = {
|
const updatedEvent: ICalendarEvent = {
|
||||||
...event,
|
...event,
|
||||||
start: swpEvent.start,
|
start: swpEvent.start,
|
||||||
end: swpEvent.end,
|
end: swpEvent.end,
|
||||||
resourceId: swpEvent.resourceId ?? event.resourceId,
|
resourceId: swpEvent.resourceId ?? event.resourceId,
|
||||||
|
allDay: payload.target === 'header' ? true : event.allDay,
|
||||||
syncStatus: 'pending'
|
syncStatus: 'pending'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue