Refactors calendar configuration and event handling

Streamlines calendar configuration by adopting a singleton pattern for consistent access and simplifies event handling.

- Removes direct `CalendarConfig` dependency injection in favor of the `calendarConfig` singleton, reducing code complexity.
- Replaces specific event emissions for grid, date, and resource settings updates with a general `REFRESH_REQUESTED` event.
- Updates event names to be more descriptive and consistent ("NAVIGATION_COMPLETED", "PERIOD_INFO_UPDATE").
- Removes the need to pass the calendar config to renderers since it is now a singleton.

This improves code maintainability and simplifies the event emission process.
This commit is contained in:
Janus Knudsen 2025-09-03 20:04:47 +02:00
parent d0936d1838
commit 2083c6921e
19 changed files with 139 additions and 173 deletions

View file

@ -2,7 +2,7 @@
import { CalendarEvent } from '../types/CalendarTypes';
import { ALL_DAY_CONSTANTS } from '../core/CalendarConfig';
import { CalendarConfig } from '../core/CalendarConfig';
import { calendarConfig } from '../core/CalendarConfig';
import { DateCalculator } from '../utils/DateCalculator';
import { eventBus } from '../core/EventBus';
import { CoreEvents } from '../constants/CoreEvents';
@ -11,7 +11,7 @@ import { CoreEvents } from '../constants/CoreEvents';
* Interface for event rendering strategies
*/
export interface EventRendererStrategy {
renderEvents(events: CalendarEvent[], container: HTMLElement, config: CalendarConfig): void;
renderEvents(events: CalendarEvent[], container: HTMLElement): void;
clearEvents(container?: HTMLElement): void;
}
@ -20,16 +20,14 @@ export interface EventRendererStrategy {
*/
export abstract class BaseEventRenderer implements EventRendererStrategy {
protected dateCalculator: DateCalculator;
protected config: CalendarConfig;
// Drag and drop state
private draggedClone: HTMLElement | null = null;
private originalEvent: HTMLElement | null = null;
constructor(config: CalendarConfig, dateCalculator?: DateCalculator) {
this.config = config;
constructor(dateCalculator?: DateCalculator) {
if (!dateCalculator) {
DateCalculator.initialize(config);
DateCalculator.initialize(calendarConfig);
}
this.dateCalculator = dateCalculator || new DateCalculator();
}
@ -69,7 +67,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
});
// Handle navigation period change (when slide animation completes)
eventBus.on(CoreEvents.PERIOD_CHANGED, () => {
eventBus.on(CoreEvents.NAVIGATION_COMPLETED, () => {
// Animate all-day height after navigation completes
this.triggerAllDayHeightAnimation();
});
@ -146,7 +144,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
* Update clone timestamp based on new position
*/
private updateCloneTimestamp(clone: HTMLElement, snappedY: number): void {
const gridSettings = this.config.getGridSettings();
const gridSettings = calendarConfig.getGridSettings();
const hourHeight = gridSettings.hourHeight;
const dayStartHour = gridSettings.dayStartHour;
const snapInterval = 15; // TODO: Get from config
@ -175,7 +173,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
* Calculate event duration in minutes from element height
*/
private getEventDuration(element: HTMLElement): number {
const gridSettings = this.config.getGridSettings();
const gridSettings = calendarConfig.getGridSettings();
const hourHeight = gridSettings.hourHeight;
// Get height from style or computed
@ -424,7 +422,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
}
}
renderEvents(events: CalendarEvent[], container: HTMLElement, config: CalendarConfig): void {
renderEvents(events: CalendarEvent[], container: HTMLElement): void {
// NOTE: Removed clearEvents() to support sliding animation
// With sliding animation, multiple grid containers exist simultaneously
@ -437,7 +435,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
// Always call renderAllDayEvents to ensure height is set correctly (even to 0)
this.renderAllDayEvents(allDayEvents, container, config);
this.renderAllDayEvents(allDayEvents, container);
// Find columns in the specific container for regular events
const columns = this.getColumns(container);
@ -448,7 +446,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
const eventsLayer = column.querySelector('swp-events-layer');
if (eventsLayer) {
columnEvents.forEach(event => {
this.renderEvent(event, eventsLayer, config);
this.renderEvent(event, eventsLayer);
});
// Debug: Verify events were actually added
@ -465,7 +463,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
/**
* Render all-day events in the header row 2
*/
protected renderAllDayEvents(allDayEvents: CalendarEvent[], container: HTMLElement, config: CalendarConfig): void {
protected renderAllDayEvents(allDayEvents: CalendarEvent[], container: HTMLElement): void {
// Find the calendar header
const calendarHeader = container.querySelector('swp-calendar-header');
@ -565,7 +563,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
}
protected renderEvent(event: CalendarEvent, container: Element, config: CalendarConfig): void {
protected renderEvent(event: CalendarEvent, container: Element): void {
const eventElement = document.createElement('swp-event');
eventElement.dataset.eventId = event.id;
eventElement.dataset.title = event.title;
@ -575,7 +573,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
eventElement.dataset.duration = event.metadata?.duration?.toString() || '60';
// Calculate position based on time
const position = this.calculateEventPosition(event, config);
const position = this.calculateEventPosition(event);
eventElement.style.position = 'absolute';
eventElement.style.top = `${position.top + 1}px`;
eventElement.style.height = `${position.height - 3}px`; //adjusted so bottom does not cover horizontal time lines.
@ -601,11 +599,11 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
container.appendChild(eventElement);
}
protected calculateEventPosition(event: CalendarEvent, config: CalendarConfig): { top: number; height: number } {
protected calculateEventPosition(event: CalendarEvent): { top: number; height: number } {
const startDate = new Date(event.start);
const endDate = new Date(event.end);
const gridSettings = config.getGridSettings();
const gridSettings = calendarConfig.getGridSettings();
const dayStartHour = gridSettings.dayStartHour;
const hourHeight = gridSettings.hourHeight;
@ -681,8 +679,8 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
* Date-based event renderer
*/
export class DateEventRenderer extends BaseEventRenderer {
constructor(config: CalendarConfig, dateCalculator?: DateCalculator) {
super(config, dateCalculator);
constructor(dateCalculator?: DateCalculator) {
super(dateCalculator);
this.setupDragEventListeners();
}