Implements a factory pattern for manager creation and initialization, improving dependency management and extensibility. This change replaces direct manager instantiation with a `ManagerFactory` that handles dependency injection. This enhances code organization and testability. It also includes an initialization sequence diagram for better understanding of the calendar's architecture and data flow.
181 lines
No EOL
5.9 KiB
TypeScript
181 lines
No EOL
5.9 KiB
TypeScript
import { CalendarConfig } from '../core/CalendarConfig';
|
|
import { ResourceCalendarData } from '../types/CalendarTypes';
|
|
import { CalendarTypeFactory } from '../factories/CalendarTypeFactory';
|
|
import { HeaderRenderContext } from './HeaderRenderer';
|
|
import { ColumnRenderContext } from './ColumnRenderer';
|
|
/**
|
|
* GridRenderer - Handles DOM rendering for the calendar grid
|
|
* Separated from GridManager to follow Single Responsibility Principle
|
|
*/
|
|
export class GridRenderer {
|
|
private config: CalendarConfig;
|
|
|
|
constructor(config: CalendarConfig) {
|
|
this.config = config;
|
|
}
|
|
|
|
/**
|
|
* Render the complete grid structure
|
|
*/
|
|
public renderGrid(
|
|
grid: HTMLElement,
|
|
currentWeek: Date,
|
|
resourceData: ResourceCalendarData | null,
|
|
allDayEvents: any[]
|
|
): void {
|
|
console.log('GridRenderer: renderGrid called', {
|
|
hasGrid: !!grid,
|
|
hasCurrentWeek: !!currentWeek,
|
|
currentWeek: currentWeek
|
|
});
|
|
|
|
if (!grid || !currentWeek) {
|
|
console.warn('GridRenderer: Cannot render - missing grid or currentWeek');
|
|
return;
|
|
}
|
|
|
|
// Only clear and rebuild if grid is empty (first render)
|
|
if (grid.children.length === 0) {
|
|
console.log('GridRenderer: First render - creating grid structure');
|
|
// Create POC structure: header-spacer + time-axis + grid-container
|
|
this.createHeaderSpacer(grid);
|
|
this.createTimeAxis(grid);
|
|
this.createGridContainer(grid, currentWeek, resourceData, allDayEvents);
|
|
} else {
|
|
console.log('GridRenderer: Re-render - updating existing structure');
|
|
// Just update the calendar header for all-day events
|
|
this.updateCalendarHeader(grid, currentWeek, resourceData, allDayEvents);
|
|
}
|
|
|
|
console.log('GridRenderer: Grid rendered successfully with POC structure');
|
|
}
|
|
|
|
/**
|
|
* Create header spacer to align time axis with week content
|
|
*/
|
|
private createHeaderSpacer(grid: HTMLElement): void {
|
|
const headerSpacer = document.createElement('swp-header-spacer');
|
|
grid.appendChild(headerSpacer);
|
|
}
|
|
|
|
/**
|
|
* Create time axis (positioned beside grid container)
|
|
*/
|
|
private createTimeAxis(grid: HTMLElement): void {
|
|
const timeAxis = document.createElement('swp-time-axis');
|
|
const timeAxisContent = document.createElement('swp-time-axis-content');
|
|
const gridSettings = this.config.getGridSettings();
|
|
const startHour = gridSettings.dayStartHour;
|
|
const endHour = gridSettings.dayEndHour;
|
|
|
|
console.log('GridRenderer: Creating time axis - startHour:', startHour, 'endHour:', endHour);
|
|
|
|
for (let hour = startHour; hour < endHour; hour++) {
|
|
const marker = document.createElement('swp-hour-marker');
|
|
const period = hour >= 12 ? 'PM' : 'AM';
|
|
const displayHour = hour > 12 ? hour - 12 : (hour === 0 ? 12 : hour);
|
|
marker.textContent = `${displayHour} ${period}`;
|
|
timeAxisContent.appendChild(marker);
|
|
}
|
|
|
|
timeAxis.appendChild(timeAxisContent);
|
|
grid.appendChild(timeAxis);
|
|
}
|
|
|
|
/**
|
|
* Create grid container with header and scrollable content
|
|
*/
|
|
private createGridContainer(
|
|
grid: HTMLElement,
|
|
currentWeek: Date,
|
|
resourceData: ResourceCalendarData | null,
|
|
allDayEvents: any[]
|
|
): void {
|
|
const gridContainer = document.createElement('swp-grid-container');
|
|
|
|
// Create calendar header using Strategy Pattern
|
|
const calendarHeader = document.createElement('swp-calendar-header');
|
|
this.renderCalendarHeader(calendarHeader, currentWeek, resourceData, allDayEvents);
|
|
gridContainer.appendChild(calendarHeader);
|
|
|
|
// Create scrollable content
|
|
const scrollableContent = document.createElement('swp-scrollable-content');
|
|
const timeGrid = document.createElement('swp-time-grid');
|
|
|
|
// Add grid lines
|
|
const gridLines = document.createElement('swp-grid-lines');
|
|
timeGrid.appendChild(gridLines);
|
|
|
|
// Create column container using Strategy Pattern
|
|
const columnContainer = document.createElement('swp-day-columns');
|
|
this.renderColumnContainer(columnContainer, currentWeek, resourceData);
|
|
timeGrid.appendChild(columnContainer);
|
|
|
|
scrollableContent.appendChild(timeGrid);
|
|
gridContainer.appendChild(scrollableContent);
|
|
|
|
grid.appendChild(gridContainer);
|
|
}
|
|
|
|
/**
|
|
* Render calendar header using Strategy Pattern
|
|
*/
|
|
private renderCalendarHeader(
|
|
calendarHeader: HTMLElement,
|
|
currentWeek: Date,
|
|
resourceData: ResourceCalendarData | null,
|
|
allDayEvents: any[]
|
|
): void {
|
|
const calendarType = this.config.getCalendarMode();
|
|
const headerRenderer = CalendarTypeFactory.getHeaderRenderer(calendarType);
|
|
|
|
const context: HeaderRenderContext = {
|
|
currentWeek: currentWeek,
|
|
config: this.config,
|
|
allDayEvents: allDayEvents,
|
|
resourceData: resourceData
|
|
};
|
|
|
|
headerRenderer.render(calendarHeader, context);
|
|
}
|
|
|
|
/**
|
|
* Render column container using Strategy Pattern
|
|
*/
|
|
private renderColumnContainer(
|
|
columnContainer: HTMLElement,
|
|
currentWeek: Date,
|
|
resourceData: ResourceCalendarData | null
|
|
): void {
|
|
console.log('GridRenderer: renderColumnContainer called');
|
|
const calendarType = this.config.getCalendarMode();
|
|
const columnRenderer = CalendarTypeFactory.getColumnRenderer(calendarType);
|
|
|
|
const context: ColumnRenderContext = {
|
|
currentWeek: currentWeek,
|
|
config: this.config,
|
|
resourceData: resourceData
|
|
};
|
|
|
|
columnRenderer.render(columnContainer, context);
|
|
}
|
|
|
|
/**
|
|
* Update only the calendar header without rebuilding entire grid
|
|
*/
|
|
private updateCalendarHeader(
|
|
grid: HTMLElement,
|
|
currentWeek: Date,
|
|
resourceData: ResourceCalendarData | null,
|
|
allDayEvents: any[]
|
|
): void {
|
|
const calendarHeader = grid.querySelector('swp-calendar-header');
|
|
if (!calendarHeader) return;
|
|
|
|
// Clear existing content
|
|
calendarHeader.innerHTML = '';
|
|
|
|
// Re-render headers using Strategy Pattern
|
|
this.renderCalendarHeader(calendarHeader as HTMLElement, currentWeek, resourceData, allDayEvents);
|
|
}
|
|
} |