Refactor calendar datasource architecture

Centralizes date calculation logic into DateColumnDataSource
Improves separation of concerns across rendering components

Key changes:
- Introduces IColumnInfo interface for flexible column data
- Moves date calculation from multiple managers to dedicated datasource
- Removes duplicate date rendering logic
- Prepares architecture for future resource-based views
This commit is contained in:
Janus C. H. Knudsen 2025-11-14 16:25:03 +01:00
parent 75a2d4913e
commit f86ae09ec3
15 changed files with 885 additions and 76 deletions

View file

@ -738,7 +738,7 @@ export class DragDropManager {
}
const dragMouseLeavePayload: IDragMouseLeaveHeaderEventPayload = {
targetDate: targetColumn.date,
targetColumn: targetColumn,
mousePosition: position,
originalElement: this.originalElement,
draggedClone: this.draggedClone

View file

@ -87,20 +87,21 @@ export class GridManager {
return;
}
// Get dates from datasource - single source of truth
const dates = this.dataSource.getColumns();
// Get columns from datasource - single source of truth
const columns = this.dataSource.getColumns();
// Get events for the period from EventManager
// Extract dates for EventManager query
const dates = columns.map(col => col.data as Date);
const startDate = dates[0];
const endDate = dates[dates.length - 1];
const events = await this.eventManager.getEventsForPeriod(startDate, endDate);
// Delegate to GridRenderer with dates and events
// Delegate to GridRenderer with columns and events
this.gridRenderer.renderGrid(
this.container,
this.currentDate,
this.currentView,
dates,
columns,
events
);
@ -108,7 +109,7 @@ export class GridManager {
eventBus.emit(CoreEvents.GRID_RENDERED, {
container: this.container,
currentDate: this.currentDate,
dates: dates
columns: columns
});
}
}

View file

@ -4,6 +4,7 @@ import { CoreEvents } from '../constants/CoreEvents';
import { IHeaderRenderer, IHeaderRenderContext } from '../renderers/DateHeaderRenderer';
import { IDragMouseEnterHeaderEventPayload, IDragMouseLeaveHeaderEventPayload, IHeaderReadyEventPayload } from '../types/EventTypes';
import { ColumnDetectionUtils } from '../utils/ColumnDetectionUtils';
import { DateColumnDataSource } from '../datasources/DateColumnDataSource';
/**
* HeaderManager - Handles all header-related event logic
@ -13,10 +14,12 @@ import { ColumnDetectionUtils } from '../utils/ColumnDetectionUtils';
export class HeaderManager {
private headerRenderer: IHeaderRenderer;
private config: Configuration;
private dataSource: DateColumnDataSource;
constructor(headerRenderer: IHeaderRenderer, config: Configuration) {
constructor(headerRenderer: IHeaderRenderer, config: Configuration, dataSource: DateColumnDataSource) {
this.headerRenderer = headerRenderer;
this.config = config;
this.dataSource = dataSource;
// Bind handler methods for event listeners
this.handleDragMouseEnterHeader = this.handleDragMouseEnterHeader.bind(this);
@ -43,11 +46,11 @@ export class HeaderManager {
* Handle drag mouse enter header event
*/
private handleDragMouseEnterHeader(event: Event): void {
const { targetColumn: targetDate, mousePosition, originalElement, draggedClone: cloneElement } =
const { targetColumn, mousePosition, originalElement, draggedClone: cloneElement } =
(event as CustomEvent<IDragMouseEnterHeaderEventPayload>).detail;
console.log('🎯 HeaderManager: Received drag:mouseenter-header', {
targetDate,
targetColumn: targetColumn.identifier,
originalElement: !!originalElement,
cloneElement: !!cloneElement
});
@ -57,11 +60,11 @@ export class HeaderManager {
* Handle drag mouse leave header event
*/
private handleDragMouseLeaveHeader(event: Event): void {
const { targetDate, mousePosition, originalElement, draggedClone: cloneElement } =
const { targetColumn, mousePosition, originalElement, draggedClone: cloneElement } =
(event as CustomEvent<IDragMouseLeaveHeaderEventPayload>).detail;
console.log('🚪 HeaderManager: Received drag:mouseleave-header', {
targetDate,
targetColumn: targetColumn?.identifier,
originalElement: !!originalElement,
cloneElement: !!cloneElement
});
@ -111,9 +114,13 @@ export class HeaderManager {
// Clear existing content
calendarHeader.innerHTML = '';
// Update DataSource with current date and get columns
this.dataSource.setCurrentDate(currentDate);
const columns = this.dataSource.getColumns();
// Render new header content using injected renderer
const context: IHeaderRenderContext = {
currentWeek: currentDate,
columns: columns,
config: this.config
};

View file

@ -191,12 +191,12 @@ export class NavigationManager {
console.log('Calling GridRenderer instead of NavigationRenderer');
console.log('Target week:', targetWeek);
// Update DataSource with target week and get dates
// Update DataSource with target week and get columns
this.dataSource.setCurrentDate(targetWeek);
const dates = this.dataSource.getColumns();
const columns = this.dataSource.getColumns();
// Always create a fresh container for consistent behavior
newGrid = this.gridRenderer.createNavigationGrid(container, dates);
newGrid = this.gridRenderer.createNavigationGrid(container, columns);
console.groupEnd();