Refactors calendar type to calendar mode

Updates the codebase to utilize `CalendarMode` instead of the deprecated `CalendarType`.

Simplifies `CalendarConfig` by removing legacy methods and related type aliases, enhancing code maintainability and clarity.

Improves event rendering by ensuring `GRID_RENDERED` events include explicit start and end dates, preventing errors and ensuring correct data filtering.
This commit is contained in:
Janus Knudsen 2025-08-20 21:51:49 +02:00
parent 83c0ce801c
commit 0ea4e47324
10 changed files with 61 additions and 91 deletions

View file

@ -2,7 +2,7 @@
import { eventBus } from './EventBus'; import { eventBus } from './EventBus';
import { CoreEvents } from '../constants/CoreEvents'; import { CoreEvents } from '../constants/CoreEvents';
import { CalendarConfig as ICalendarConfig, ViewPeriod, CalendarMode, DateViewType, CalendarType } from '../types/CalendarTypes'; import { CalendarConfig as ICalendarConfig, ViewPeriod, CalendarMode } from '../types/CalendarTypes';
/** /**
* Layout and timing settings for the calendar grid * Layout and timing settings for the calendar grid
@ -305,13 +305,6 @@ export class CalendarConfig {
getDateViewSettings(): DateViewSettings { getDateViewSettings(): DateViewSettings {
return { ...this.dateViewSettings }; return { ...this.dateViewSettings };
} }
/**
* Legacy method - for backwards compatibility
*/
getDateHeaderSettings(): DateViewSettings {
return this.getDateViewSettings();
}
/** /**
* Update date view settings * Update date view settings
@ -326,13 +319,6 @@ export class CalendarConfig {
oldValue: this.dateViewSettings oldValue: this.dateViewSettings
}); });
} }
/**
* Legacy method - for backwards compatibility
*/
updateDateHeaderSettings(updates: Partial<DateViewSettings>): void {
this.updateDateViewSettings(updates);
}
/** /**
* Get resource view settings * Get resource view settings
@ -340,13 +326,6 @@ export class CalendarConfig {
getResourceViewSettings(): ResourceViewSettings { getResourceViewSettings(): ResourceViewSettings {
return { ...this.resourceViewSettings }; return { ...this.resourceViewSettings };
} }
/**
* Legacy method - for backwards compatibility
*/
getResourceHeaderSettings(): ResourceViewSettings {
return this.getResourceViewSettings();
}
/** /**
* Update resource view settings * Update resource view settings
@ -361,13 +340,6 @@ export class CalendarConfig {
oldValue: this.resourceViewSettings oldValue: this.resourceViewSettings
}); });
} }
/**
* Legacy method - for backwards compatibility
*/
updateResourceHeaderSettings(updates: Partial<ResourceViewSettings>): void {
this.updateResourceViewSettings(updates);
}
/** /**
* Check if current mode is resource-based * Check if current mode is resource-based
@ -383,16 +355,6 @@ export class CalendarConfig {
return this.calendarMode === 'date'; return this.calendarMode === 'date';
} }
/**
* Legacy methods - for backwards compatibility
*/
isResourceView(): boolean {
return this.isResourceMode();
}
isDateView(): boolean {
return this.isDateMode();
}
/** /**
* Get calendar mode * Get calendar mode

View file

@ -1,6 +1,6 @@
// Factory for creating calendar type-specific renderers // Factory for creating calendar type-specific renderers
import { CalendarType } from '../types/CalendarTypes'; import { CalendarMode } from '../types/CalendarTypes';
import { HeaderRenderer, DateHeaderRenderer, ResourceHeaderRenderer } from '../renderers/HeaderRenderer'; import { HeaderRenderer, DateHeaderRenderer, ResourceHeaderRenderer } from '../renderers/HeaderRenderer';
import { ColumnRenderer, DateColumnRenderer, ResourceColumnRenderer } from '../renderers/ColumnRenderer'; import { ColumnRenderer, DateColumnRenderer, ResourceColumnRenderer } from '../renderers/ColumnRenderer';
import { EventRendererStrategy, DateEventRenderer, ResourceEventRenderer } from '../renderers/EventRenderer'; import { EventRendererStrategy, DateEventRenderer, ResourceEventRenderer } from '../renderers/EventRenderer';
@ -19,7 +19,7 @@ export interface RendererConfig {
* Factory for creating calendar type-specific renderers * Factory for creating calendar type-specific renderers
*/ */
export class CalendarTypeFactory { export class CalendarTypeFactory {
private static renderers: Map<CalendarType, RendererConfig> = new Map(); private static renderers: Map<CalendarMode, RendererConfig> = new Map();
private static isInitialized: boolean = false; private static isInitialized: boolean = false;
/** /**
@ -27,7 +27,7 @@ export class CalendarTypeFactory {
*/ */
static initialize(): void { static initialize(): void {
if (this.isInitialized) { if (this.isInitialized) {
console.warn('CalendarTypeFactory: Already initialized, skipping'); console.warn('CalendarModeFactory: Already initialized, skipping');
return; return;
} }
@ -45,25 +45,25 @@ export class CalendarTypeFactory {
}); });
this.isInitialized = true; this.isInitialized = true;
console.log('CalendarTypeFactory: Initialized with default renderers', Array.from(this.renderers.keys())); console.log('CalendarModeFactory: Initialized with default renderers', Array.from(this.renderers.keys()));
} }
/** /**
* Register renderers for a calendar type * Register renderers for a calendar type
*/ */
static registerRenderers(type: CalendarType, config: RendererConfig): void { static registerRenderers(type: CalendarMode, config: RendererConfig): void {
this.renderers.set(type, config); this.renderers.set(type, config);
console.log(`CalendarTypeFactory: Registered renderers for type '${type}'`); console.log(`CalendarModeFactory: Registered renderers for type '${type}'`);
} }
/** /**
* Get renderers for a calendar type * Get renderers for a calendar type
*/ */
static getRenderers(type: CalendarType): RendererConfig { static getRenderers(type: CalendarMode): RendererConfig {
const renderers = this.renderers.get(type); const renderers = this.renderers.get(type);
if (!renderers) { if (!renderers) {
console.warn(`CalendarTypeFactory: No renderers found for type '${type}', falling back to 'date'`); console.warn(`CalendarModeFactory: No renderers found for type '${type}', falling back to 'date'`);
return this.renderers.get('date')!; return this.renderers.get('date')!;
} }
@ -73,35 +73,35 @@ export class CalendarTypeFactory {
/** /**
* Get header renderer for a calendar type * Get header renderer for a calendar type
*/ */
static getHeaderRenderer(type: CalendarType): HeaderRenderer { static getHeaderRenderer(type: CalendarMode): HeaderRenderer {
return this.getRenderers(type).headerRenderer; return this.getRenderers(type).headerRenderer;
} }
/** /**
* Get column renderer for a calendar type * Get column renderer for a calendar type
*/ */
static getColumnRenderer(type: CalendarType): ColumnRenderer { static getColumnRenderer(type: CalendarMode): ColumnRenderer {
return this.getRenderers(type).columnRenderer; return this.getRenderers(type).columnRenderer;
} }
/** /**
* Get event renderer for a calendar type * Get event renderer for a calendar type
*/ */
static getEventRenderer(type: CalendarType): EventRendererStrategy { static getEventRenderer(type: CalendarMode): EventRendererStrategy {
return this.getRenderers(type).eventRenderer; return this.getRenderers(type).eventRenderer;
} }
/** /**
* Check if a calendar type is supported * Check if a calendar type is supported
*/ */
static isSupported(type: CalendarType): boolean { static isSupported(type: CalendarMode): boolean {
return this.renderers.has(type); return this.renderers.has(type);
} }
/** /**
* Get all supported calendar types * Get all supported calendar types
*/ */
static getSupportedTypes(): CalendarType[] { static getSupportedTypes(): CalendarMode[] {
return Array.from(this.renderers.keys()); return Array.from(this.renderers.keys());
} }
@ -110,6 +110,6 @@ export class CalendarTypeFactory {
*/ */
static clear(): void { static clear(): void {
this.renderers.clear(); this.renderers.clear();
console.log('CalendarTypeFactory: All renderers cleared'); console.log('CalendarModeFactory: All renderers cleared');
} }
} }

View file

@ -144,7 +144,6 @@ export class CalendarManager {
this.eventBus.emit(CoreEvents.DATE_CHANGED, { this.eventBus.emit(CoreEvents.DATE_CHANGED, {
previousDate, previousDate,
currentDate: this.currentDate, currentDate: this.currentDate,
date: this.currentDate, // Add for backward compatibility
view: this.currentView view: this.currentView
}); });

View file

@ -54,25 +54,6 @@ export class GridManager {
); );
// Listen for data changes // Listen for data changes
// REMOVED: GridManager should not re-render on DATE_CHANGED
// Date navigation is handled by NavigationManager
// this.eventCleanup.push(
// eventBus.on(CoreEvents.DATE_CHANGED, (e: Event) => {
// const detail = (e as CustomEvent).detail;
// this.currentDate = detail.currentDate;
// this.render();
// })
// );
// REMOVED: GridManager should not re-render on WEEK_CHANGED
// Navigation is handled by NavigationManager + NavigationRenderer
// this.eventCleanup.push(
// eventBus.on(CoreEvents.WEEK_CHANGED, (e: Event) => {
// const detail = (e as CustomEvent).detail;
// this.currentDate = detail.weekStart;
// this.render();
// })
// );
this.eventCleanup.push( this.eventCleanup.push(
eventBus.on(CoreEvents.DATA_LOADED, (e: Event) => { eventBus.on(CoreEvents.DATA_LOADED, (e: Event) => {
@ -156,12 +137,17 @@ export class GridManager {
// Get layout info from strategy // Get layout info from strategy
const layoutConfig = this.currentStrategy.getLayoutConfig(); const layoutConfig = this.currentStrategy.getLayoutConfig();
console.log(`GridManager: Emitting GRID_RENDERED for main container`); // Get period range from current strategy
const periodRange = this.currentStrategy.getPeriodRange(this.currentDate);
// Emit grid rendered event console.log(`GridManager: Emitting GRID_RENDERED for main container with period ${periodRange.startDate.toDateString()} - ${periodRange.endDate.toDateString()}`);
// Emit grid rendered event with explicit date range
eventBus.emit(CoreEvents.GRID_RENDERED, { eventBus.emit(CoreEvents.GRID_RENDERED, {
container: this.container, container: this.container,
currentDate: this.currentDate, currentDate: this.currentDate,
startDate: periodRange.startDate,
endDate: periodRange.endDate,
layoutConfig: layoutConfig, layoutConfig: layoutConfig,
columnCount: layoutConfig.columnCount columnCount: layoutConfig.columnCount
}); });

View file

@ -65,17 +65,17 @@ export class NavigationManager {
// Listen for external navigation requests // Listen for external navigation requests
this.eventBus.on(CoreEvents.DATE_CHANGED, (event: Event) => { this.eventBus.on(CoreEvents.DATE_CHANGED, (event: Event) => {
const customEvent = event as CustomEvent; const customEvent = event as CustomEvent;
const dateFromEvent = customEvent.detail.date || customEvent.detail.currentDate; const dateFromEvent = customEvent.detail.currentDate;
// Validate date before processing // Validate date before processing
if (!dateFromEvent) { if (!dateFromEvent) {
console.warn('NavigationManager: No date provided in DATE_CHANGED event', customEvent.detail); console.warn('NavigationManager: No currentDate provided in DATE_CHANGED event', customEvent.detail);
return; return;
} }
const targetDate = new Date(dateFromEvent); const targetDate = new Date(dateFromEvent);
if (isNaN(targetDate.getTime())) { if (isNaN(targetDate.getTime())) {
console.warn('NavigationManager: Invalid date in DATE_CHANGED event', dateFromEvent); console.warn('NavigationManager: Invalid currentDate in DATE_CHANGED event', dateFromEvent);
return; return;
} }

View file

@ -90,17 +90,12 @@ export class EventRenderingService {
let periodEnd: Date; let periodEnd: Date;
if (startDate && endDate) { if (startDate && endDate) {
// Legacy format with explicit dates // Direct date format - use as provided
periodStart = startDate; periodStart = startDate;
periodEnd = endDate; periodEnd = endDate;
} else if (currentDate) { } else if (currentDate) {
// New format - calculate period from current date console.error('EventRenderer: GRID_RENDERED events must include explicit startDate and endDate', event.detail);
// For now, use a week period. This could be improved by getting the actual period from the strategy return;
const baseDate = new Date(currentDate);
periodStart = new Date(baseDate);
periodStart.setDate(baseDate.getDate() - baseDate.getDay() + 1); // Monday
periodEnd = new Date(periodStart);
periodEnd.setDate(periodStart.getDate() + 6); // Sunday
} else { } else {
console.error('EventRenderer: No date information in GRID_RENDERED event', event.detail); console.error('EventRenderer: No date information in GRID_RENDERED event', event.detail);
return; return;

View file

@ -142,6 +142,22 @@ export class MonthViewStrategy implements ViewStrategy {
return this.getMonthDates(baseDate); return this.getMonthDates(baseDate);
} }
getPeriodRange(baseDate: Date): { startDate: Date; endDate: Date } {
// Month view shows events for the entire month grid (including partial weeks)
const firstOfMonth = new Date(baseDate.getFullYear(), baseDate.getMonth(), 1);
// Get Monday of the week containing first day
const startDate = this.dateCalculator.getISOWeekStart(firstOfMonth);
// End date is 41 days after start (42 total days)
const endDate = this.dateCalculator.addDays(startDate, 41);
return {
startDate,
endDate
};
}
destroy(): void { destroy(): void {
console.log('MonthViewStrategy: Cleaning up'); console.log('MonthViewStrategy: Cleaning up');
} }

View file

@ -60,6 +60,11 @@ export interface ViewStrategy {
*/ */
getDisplayDates(baseDate: Date): Date[]; getDisplayDates(baseDate: Date): Date[];
/**
* Get the period start and end dates for event filtering
*/
getPeriodRange(baseDate: Date): { startDate: Date; endDate: Date };
/** /**
* Clean up any view-specific resources * Clean up any view-specific resources
*/ */

View file

@ -67,6 +67,16 @@ export class WeekViewStrategy implements ViewStrategy {
return this.dateCalculator.getWorkWeekDates(baseDate); return this.dateCalculator.getWorkWeekDates(baseDate);
} }
getPeriodRange(baseDate: Date): { startDate: Date; endDate: Date } {
const weekStart = this.dateCalculator.getISOWeekStart(baseDate);
const weekEnd = this.dateCalculator.addDays(weekStart, 6);
return {
startDate: weekStart,
endDate: weekEnd
};
}
destroy(): void { destroy(): void {
// Clean up any week-specific resources // Clean up any week-specific resources
// For now, just log // For now, just log

View file

@ -6,11 +6,8 @@ export type ViewPeriod = 'day' | 'week' | 'month';
// Calendar mode types (how to organize the data) // Calendar mode types (how to organize the data)
export type CalendarMode = 'date' | 'resource'; export type CalendarMode = 'date' | 'resource';
// Legacy aliases for backwards compatibility // Type aliases
export type DateViewType = ViewPeriod; export type CalendarView = ViewPeriod;
export type ViewType = DateViewType;
export type CalendarView = ViewType;
export type CalendarType = CalendarMode;
export type SyncStatus = 'synced' | 'pending' | 'error'; export type SyncStatus = 'synced' | 'pending' | 'error';