Refactors calendar managers and renderers
Improves calendar rendering performance by centralizing DOM manipulation in a dedicated `GridRenderer` class. This reduces redundant DOM queries and improves overall efficiency. Introduces `EventManager` for optimized event lifecycle management with caching and optimized data processing. The `ViewManager` is refactored for optimized view switching and event handling, further streamlining the application's architecture. This change moves from a strategy-based `GridManager` to a simpler approach leveraging the `GridRenderer` directly for DOM updates. This eliminates unnecessary abstractions and improves code maintainability. The changes include removing the old `GridManager`, `EventManager` and introducing new versions.
This commit is contained in:
parent
b8b44ddae8
commit
05bb074e9a
4 changed files with 566 additions and 271 deletions
|
|
@ -1,31 +1,29 @@
|
|||
/**
|
||||
* GridManager - Simplified grid manager using Strategy Pattern
|
||||
* Now delegates view-specific logic to strategy implementations
|
||||
* GridManager - Simplified grid manager using centralized GridRenderer
|
||||
* Delegates DOM rendering to GridRenderer, focuses on coordination
|
||||
*/
|
||||
|
||||
import { eventBus } from '../core/EventBus';
|
||||
import { calendarConfig } from '../core/CalendarConfig';
|
||||
import { CoreEvents } from '../constants/CoreEvents';
|
||||
import { ResourceCalendarData, CalendarView } from '../types/CalendarTypes';
|
||||
import { ViewStrategy, ViewContext } from '../strategies/ViewStrategy';
|
||||
import { WeekViewStrategy } from '../strategies/WeekViewStrategy';
|
||||
import { MonthViewStrategy } from '../strategies/MonthViewStrategy';
|
||||
import { GridRenderer } from '../renderers/GridRenderer';
|
||||
import { DateCalculator } from '../utils/DateCalculator';
|
||||
|
||||
/**
|
||||
* Simplified GridManager focused on coordination, not implementation
|
||||
* Simplified GridManager focused on coordination, delegates rendering to GridRenderer
|
||||
*/
|
||||
export class GridManager {
|
||||
private container: HTMLElement | null = null;
|
||||
private currentDate: Date = new Date();
|
||||
private resourceData: ResourceCalendarData | null = null;
|
||||
private currentStrategy: ViewStrategy;
|
||||
private currentView: CalendarView = 'week';
|
||||
private gridRenderer: GridRenderer;
|
||||
private eventCleanup: (() => void)[] = [];
|
||||
|
||||
constructor() {
|
||||
|
||||
// Default to week view strategy
|
||||
this.currentStrategy = new WeekViewStrategy();
|
||||
|
||||
// Initialize GridRenderer with config
|
||||
this.gridRenderer = new GridRenderer(calendarConfig);
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
|
@ -40,11 +38,12 @@ export class GridManager {
|
|||
}
|
||||
|
||||
private subscribeToEvents(): void {
|
||||
// Listen for view changes to switch strategies
|
||||
// Listen for view changes
|
||||
this.eventCleanup.push(
|
||||
eventBus.on(CoreEvents.VIEW_CHANGED, (e: Event) => {
|
||||
const detail = (e as CustomEvent).detail;
|
||||
this.switchViewStrategy(detail.currentView);
|
||||
this.currentView = detail.currentView;
|
||||
this.render();
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -63,27 +62,10 @@ export class GridManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Switch to a different view strategy
|
||||
* Switch to a different view
|
||||
*/
|
||||
public switchViewStrategy(view: CalendarView): void {
|
||||
|
||||
// Clean up current strategy
|
||||
this.currentStrategy.destroy();
|
||||
|
||||
// Create new strategy based on view
|
||||
switch (view) {
|
||||
case 'week':
|
||||
case 'day':
|
||||
this.currentStrategy = new WeekViewStrategy();
|
||||
break;
|
||||
case 'month':
|
||||
this.currentStrategy = new MonthViewStrategy();
|
||||
break;
|
||||
default:
|
||||
this.currentStrategy = new WeekViewStrategy();
|
||||
}
|
||||
|
||||
// Re-render with new strategy
|
||||
public switchView(view: CalendarView): void {
|
||||
this.currentView = view;
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
|
@ -96,32 +78,27 @@ export class GridManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Main render method - delegates to current strategy
|
||||
* Main render method - delegates to GridRenderer
|
||||
*/
|
||||
public async render(): Promise<void> {
|
||||
if (!this.container) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Delegate to GridRenderer with current view context
|
||||
this.gridRenderer.renderGrid(
|
||||
this.container,
|
||||
this.currentDate,
|
||||
this.resourceData
|
||||
);
|
||||
|
||||
// Create context for strategy
|
||||
const context: ViewContext = {
|
||||
currentDate: this.currentDate,
|
||||
container: this.container,
|
||||
resourceData: this.resourceData
|
||||
};
|
||||
// Calculate period range using DateCalculator
|
||||
const periodRange = this.getPeriodRange();
|
||||
|
||||
// Delegate to current strategy
|
||||
this.currentStrategy.renderGrid(context);
|
||||
// Get layout config based on current view
|
||||
const layoutConfig = this.getLayoutConfig();
|
||||
|
||||
// Get layout info from strategy
|
||||
const layoutConfig = this.currentStrategy.getLayoutConfig();
|
||||
|
||||
// Get period range from current strategy
|
||||
const periodRange = this.currentStrategy.getPeriodRange(this.currentDate);
|
||||
|
||||
|
||||
// Emit grid rendered event with explicit date range
|
||||
// Emit grid rendered event
|
||||
eventBus.emit(CoreEvents.GRID_RENDERED, {
|
||||
container: this.container,
|
||||
currentDate: this.currentDate,
|
||||
|
|
@ -130,22 +107,48 @@ export class GridManager {
|
|||
layoutConfig: layoutConfig,
|
||||
columnCount: layoutConfig.columnCount
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get current period label from strategy
|
||||
* Get current period label using DateCalculator
|
||||
*/
|
||||
public getCurrentPeriodLabel(): string {
|
||||
return this.currentStrategy.getPeriodLabel(this.currentDate);
|
||||
switch (this.currentView) {
|
||||
case 'week':
|
||||
case 'day':
|
||||
const weekStart = DateCalculator.getISOWeekStart(this.currentDate);
|
||||
const weekEnd = DateCalculator.getWeekEnd(this.currentDate);
|
||||
return DateCalculator.formatDateRange(weekStart, weekEnd);
|
||||
case 'month':
|
||||
return this.currentDate.toLocaleDateString('en-US', { month: 'long', year: 'numeric' });
|
||||
default:
|
||||
const defaultWeekStart = DateCalculator.getISOWeekStart(this.currentDate);
|
||||
const defaultWeekEnd = DateCalculator.getWeekEnd(this.currentDate);
|
||||
return DateCalculator.formatDateRange(defaultWeekStart, defaultWeekEnd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate to next period using strategy
|
||||
* Navigate to next period using DateCalculator
|
||||
*/
|
||||
public navigateNext(): void {
|
||||
const nextDate = this.currentStrategy.getNextPeriod(this.currentDate);
|
||||
let nextDate: Date;
|
||||
|
||||
switch (this.currentView) {
|
||||
case 'week':
|
||||
nextDate = DateCalculator.addWeeks(this.currentDate, 1);
|
||||
break;
|
||||
case 'month':
|
||||
nextDate = this.addMonths(this.currentDate, 1);
|
||||
break;
|
||||
case 'day':
|
||||
nextDate = DateCalculator.addDays(this.currentDate, 1);
|
||||
break;
|
||||
default:
|
||||
nextDate = DateCalculator.addWeeks(this.currentDate, 1);
|
||||
}
|
||||
|
||||
this.currentDate = nextDate;
|
||||
|
||||
eventBus.emit(CoreEvents.PERIOD_CHANGED, {
|
||||
|
|
@ -158,14 +161,29 @@ export class GridManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Navigate to previous period using strategy
|
||||
* Navigate to previous period using DateCalculator
|
||||
*/
|
||||
public navigatePrevious(): void {
|
||||
const prevDate = this.currentStrategy.getPreviousPeriod(this.currentDate);
|
||||
let prevDate: Date;
|
||||
|
||||
switch (this.currentView) {
|
||||
case 'week':
|
||||
prevDate = DateCalculator.addWeeks(this.currentDate, -1);
|
||||
break;
|
||||
case 'month':
|
||||
prevDate = this.addMonths(this.currentDate, -1);
|
||||
break;
|
||||
case 'day':
|
||||
prevDate = DateCalculator.addDays(this.currentDate, -1);
|
||||
break;
|
||||
default:
|
||||
prevDate = DateCalculator.addWeeks(this.currentDate, -1);
|
||||
}
|
||||
|
||||
this.currentDate = prevDate;
|
||||
|
||||
eventBus.emit(CoreEvents.PERIOD_CHANGED, {
|
||||
direction: 'previous',
|
||||
direction: 'previous',
|
||||
newDate: prevDate,
|
||||
periodLabel: this.getCurrentPeriodLabel()
|
||||
});
|
||||
|
|
@ -188,26 +206,137 @@ export class GridManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get current view's display dates
|
||||
* Get current view's display dates using DateCalculator
|
||||
*/
|
||||
public getDisplayDates(): Date[] {
|
||||
return this.currentStrategy.getDisplayDates(this.currentDate);
|
||||
switch (this.currentView) {
|
||||
case 'week':
|
||||
const weekStart = DateCalculator.getISOWeekStart(this.currentDate);
|
||||
return DateCalculator.getFullWeekDates(weekStart);
|
||||
case 'month':
|
||||
return this.getMonthDates(this.currentDate);
|
||||
case 'day':
|
||||
return [this.currentDate];
|
||||
default:
|
||||
const defaultWeekStart = DateCalculator.getISOWeekStart(this.currentDate);
|
||||
return DateCalculator.getFullWeekDates(defaultWeekStart);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get period range for current view
|
||||
*/
|
||||
private getPeriodRange(): { startDate: Date; endDate: Date } {
|
||||
switch (this.currentView) {
|
||||
case 'week':
|
||||
const weekStart = DateCalculator.getISOWeekStart(this.currentDate);
|
||||
const weekEnd = DateCalculator.getWeekEnd(this.currentDate);
|
||||
return {
|
||||
startDate: weekStart,
|
||||
endDate: weekEnd
|
||||
};
|
||||
case 'month':
|
||||
return {
|
||||
startDate: this.getMonthStart(this.currentDate),
|
||||
endDate: this.getMonthEnd(this.currentDate)
|
||||
};
|
||||
case 'day':
|
||||
return {
|
||||
startDate: this.currentDate,
|
||||
endDate: this.currentDate
|
||||
};
|
||||
default:
|
||||
const defaultWeekStart = DateCalculator.getISOWeekStart(this.currentDate);
|
||||
const defaultWeekEnd = DateCalculator.getWeekEnd(this.currentDate);
|
||||
return {
|
||||
startDate: defaultWeekStart,
|
||||
endDate: defaultWeekEnd
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get layout config for current view
|
||||
*/
|
||||
private getLayoutConfig(): any {
|
||||
switch (this.currentView) {
|
||||
case 'week':
|
||||
return {
|
||||
columnCount: 7,
|
||||
type: 'week'
|
||||
};
|
||||
case 'month':
|
||||
return {
|
||||
columnCount: 7,
|
||||
type: 'month'
|
||||
};
|
||||
case 'day':
|
||||
return {
|
||||
columnCount: 1,
|
||||
type: 'day'
|
||||
};
|
||||
default:
|
||||
return {
|
||||
columnCount: 7,
|
||||
type: 'week'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up all resources
|
||||
*/
|
||||
public destroy(): void {
|
||||
|
||||
// Clean up event listeners
|
||||
this.eventCleanup.forEach(cleanup => cleanup());
|
||||
this.eventCleanup = [];
|
||||
|
||||
// Clean up current strategy
|
||||
this.currentStrategy.destroy();
|
||||
|
||||
// Clear references
|
||||
this.container = null;
|
||||
this.resourceData = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to add months to a date
|
||||
*/
|
||||
private addMonths(date: Date, months: number): Date {
|
||||
const result = new Date(date);
|
||||
result.setMonth(result.getMonth() + months);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get month start
|
||||
*/
|
||||
private getMonthStart(date: Date): Date {
|
||||
const result = new Date(date);
|
||||
result.setDate(1);
|
||||
result.setHours(0, 0, 0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get month end
|
||||
*/
|
||||
private getMonthEnd(date: Date): Date {
|
||||
const result = new Date(date);
|
||||
result.setMonth(result.getMonth() + 1, 0);
|
||||
result.setHours(23, 59, 59, 999);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get all dates in a month
|
||||
*/
|
||||
private getMonthDates(date: Date): Date[] {
|
||||
const dates: Date[] = [];
|
||||
const monthStart = this.getMonthStart(date);
|
||||
const monthEnd = this.getMonthEnd(date);
|
||||
|
||||
for (let d = new Date(monthStart); d <= monthEnd; d.setDate(d.getDate() + 1)) {
|
||||
dates.push(new Date(d));
|
||||
}
|
||||
|
||||
return dates;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue