Refactors calendar initialization with factory
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.
This commit is contained in:
parent
32ee35eb02
commit
26f0cb8aaa
11 changed files with 333 additions and 150 deletions
|
|
@ -5,7 +5,8 @@
|
||||||
"Bash(npm run build:*)",
|
"Bash(npm run build:*)",
|
||||||
"Bash(powershell:*)",
|
"Bash(powershell:*)",
|
||||||
"Bash(rg:*)",
|
"Bash(rg:*)",
|
||||||
"Bash(find:*)"
|
"Bash(find:*)",
|
||||||
|
"Bash(mv:*)"
|
||||||
],
|
],
|
||||||
"deny": []
|
"deny": []
|
||||||
}
|
}
|
||||||
|
|
|
||||||
133
docs/calendar-initialization-sequence.md
Normal file
133
docs/calendar-initialization-sequence.md
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
# Calendar Initialization Sequence Diagram
|
||||||
|
|
||||||
|
Dette diagram viser den aktuelle initialization sekvens baseret på koden.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant Browser
|
||||||
|
participant Index as index.ts
|
||||||
|
participant MF as ManagerFactory
|
||||||
|
participant CTF as CalendarTypeFactory
|
||||||
|
participant EB as EventBus
|
||||||
|
participant CM as CalendarManager
|
||||||
|
participant EM as EventManager
|
||||||
|
participant ERS as EventRenderingService
|
||||||
|
participant GM as GridManager
|
||||||
|
participant GSM as GridStyleManager
|
||||||
|
participant GR as GridRenderer
|
||||||
|
participant SM as ScrollManager
|
||||||
|
participant NM as NavigationManager
|
||||||
|
participant NR as NavigationRenderer
|
||||||
|
participant VM as ViewManager
|
||||||
|
|
||||||
|
Browser->>Index: DOMContentLoaded
|
||||||
|
Index->>Index: initializeCalendar()
|
||||||
|
|
||||||
|
Index->>CTF: initialize()
|
||||||
|
CTF-->>Index: Factory ready
|
||||||
|
|
||||||
|
Index->>MF: getInstance()
|
||||||
|
MF-->>Index: Factory instance
|
||||||
|
|
||||||
|
Index->>MF: createManagers(eventBus, config)
|
||||||
|
|
||||||
|
MF->>EM: new EventManager(eventBus)
|
||||||
|
EM->>EB: setupEventListeners()
|
||||||
|
EM-->>MF: EventManager ready
|
||||||
|
|
||||||
|
MF->>ERS: new EventRenderingService(eventBus, eventManager)
|
||||||
|
ERS->>EB: setupEventListeners()
|
||||||
|
ERS-->>MF: EventRenderingService ready
|
||||||
|
|
||||||
|
MF->>GM: new GridManager()
|
||||||
|
GM->>GSM: new GridStyleManager(config)
|
||||||
|
GM->>GR: new GridRenderer(config)
|
||||||
|
GM->>EB: subscribeToEvents()
|
||||||
|
GM-->>MF: GridManager ready
|
||||||
|
|
||||||
|
MF->>SM: new ScrollManager()
|
||||||
|
SM->>EB: subscribeToEvents()
|
||||||
|
SM-->>MF: ScrollManager ready
|
||||||
|
|
||||||
|
MF->>NM: new NavigationManager(eventBus)
|
||||||
|
NM->>NR: new NavigationRenderer(eventBus)
|
||||||
|
NR->>EB: setupEventListeners()
|
||||||
|
NM->>EB: setupEventListeners()
|
||||||
|
NM-->>MF: NavigationManager ready
|
||||||
|
|
||||||
|
MF->>VM: new ViewManager(eventBus)
|
||||||
|
VM->>EB: setupEventListeners()
|
||||||
|
VM-->>MF: ViewManager ready
|
||||||
|
|
||||||
|
MF->>CM: new CalendarManager(eventBus, config, deps...)
|
||||||
|
CM->>EB: setupEventListeners()
|
||||||
|
CM-->>MF: CalendarManager ready
|
||||||
|
|
||||||
|
MF-->>Index: All managers created
|
||||||
|
|
||||||
|
Index->>EB: setDebug(true)
|
||||||
|
Index->>MF: initializeManagers(managers)
|
||||||
|
MF->>CM: initialize()
|
||||||
|
|
||||||
|
CM->>EM: loadData()
|
||||||
|
EM->>EM: loadMockData()
|
||||||
|
EM->>EM: processCalendarData()
|
||||||
|
EM-->>CM: Data loaded
|
||||||
|
|
||||||
|
CM->>GM: setResourceData(resourceData)
|
||||||
|
GM-->>CM: Resource data set
|
||||||
|
|
||||||
|
CM->>GM: render()
|
||||||
|
GM->>GSM: updateGridStyles(resourceData)
|
||||||
|
GM->>GR: renderGrid(grid, currentWeek, resourceData, allDayEvents)
|
||||||
|
GR-->>GM: Grid rendered
|
||||||
|
|
||||||
|
GM->>EB: emit(GRID_RENDERED, context)
|
||||||
|
EB-->>ERS: GRID_RENDERED event
|
||||||
|
|
||||||
|
ERS->>EM: getEventsForPeriod(startDate, endDate)
|
||||||
|
EM-->>ERS: Filtered events
|
||||||
|
ERS->>ERS: strategy.renderEvents()
|
||||||
|
|
||||||
|
CM->>SM: initialize()
|
||||||
|
SM->>SM: setupScrolling()
|
||||||
|
|
||||||
|
CM->>CM: setView(currentView)
|
||||||
|
CM->>EB: emit(VIEW_CHANGED, viewData)
|
||||||
|
|
||||||
|
CM->>CM: setCurrentDate(currentDate)
|
||||||
|
CM->>EB: emit(DATE_CHANGED, dateData)
|
||||||
|
|
||||||
|
CM->>EB: emit(CALENDAR_INITIALIZED, initData)
|
||||||
|
|
||||||
|
EB-->>NM: CALENDAR_INITIALIZED
|
||||||
|
NM->>NM: updateWeekInfo()
|
||||||
|
NM->>EB: emit(WEEK_INFO_UPDATED, weekInfo)
|
||||||
|
EB-->>NR: WEEK_INFO_UPDATED
|
||||||
|
NR->>NR: updateWeekInfoInDOM()
|
||||||
|
|
||||||
|
EB-->>VM: CALENDAR_INITIALIZED
|
||||||
|
VM->>VM: initializeView()
|
||||||
|
VM->>EB: emit(VIEW_RENDERED, viewData)
|
||||||
|
|
||||||
|
CM-->>MF: Initialization complete
|
||||||
|
MF-->>Index: All managers initialized
|
||||||
|
|
||||||
|
Index->>Browser: Calendar ready
|
||||||
|
```
|
||||||
|
|
||||||
|
## Aktuel Arkitektur Status
|
||||||
|
|
||||||
|
### Factory Pattern
|
||||||
|
- ManagerFactory håndterer manager instantiering
|
||||||
|
- Proper dependency injection via constructor
|
||||||
|
|
||||||
|
### Event-Driven Communication
|
||||||
|
- EventBus koordinerer kommunikation mellem managers
|
||||||
|
- NavigationRenderer lytter til WEEK_INFO_UPDATED events
|
||||||
|
- EventRenderingService reagerer på GRID_RENDERED events
|
||||||
|
|
||||||
|
### Separation of Concerns
|
||||||
|
- Managers håndterer business logic
|
||||||
|
- Renderers håndterer DOM manipulation
|
||||||
|
- EventBus håndterer kommunikation
|
||||||
88
src/factories/ManagerFactory.ts
Normal file
88
src/factories/ManagerFactory.ts
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { IEventBus } from '../types/CalendarTypes';
|
||||||
|
import { CalendarConfig } from '../core/CalendarConfig';
|
||||||
|
import { EventManager } from '../managers/EventManager';
|
||||||
|
import { EventRenderingService } from '../renderers/EventRendererManager';
|
||||||
|
import { GridManager } from '../managers/GridManager';
|
||||||
|
import { ScrollManager } from '../managers/ScrollManager';
|
||||||
|
import { NavigationManager } from '../managers/NavigationManager';
|
||||||
|
import { ViewManager } from '../managers/ViewManager';
|
||||||
|
import { CalendarManager } from '../managers/CalendarManager';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for creating and managing calendar managers with proper dependency injection
|
||||||
|
*/
|
||||||
|
export class ManagerFactory {
|
||||||
|
private static instance: ManagerFactory;
|
||||||
|
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
public static getInstance(): ManagerFactory {
|
||||||
|
if (!ManagerFactory.instance) {
|
||||||
|
ManagerFactory.instance = new ManagerFactory();
|
||||||
|
}
|
||||||
|
return ManagerFactory.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create all managers with proper dependency injection
|
||||||
|
*/
|
||||||
|
public createManagers(eventBus: IEventBus, config: CalendarConfig): {
|
||||||
|
eventManager: EventManager;
|
||||||
|
eventRenderer: EventRenderingService;
|
||||||
|
gridManager: GridManager;
|
||||||
|
scrollManager: ScrollManager;
|
||||||
|
navigationManager: NavigationManager;
|
||||||
|
viewManager: ViewManager;
|
||||||
|
calendarManager: CalendarManager;
|
||||||
|
} {
|
||||||
|
console.log('🏭 ManagerFactory: Creating managers with proper DI...');
|
||||||
|
|
||||||
|
// Create managers in dependency order
|
||||||
|
const eventManager = new EventManager(eventBus);
|
||||||
|
const eventRenderer = new EventRenderingService(eventBus, eventManager);
|
||||||
|
const gridManager = new GridManager();
|
||||||
|
const scrollManager = new ScrollManager();
|
||||||
|
const navigationManager = new NavigationManager(eventBus);
|
||||||
|
const viewManager = new ViewManager(eventBus);
|
||||||
|
|
||||||
|
// CalendarManager depends on all other managers
|
||||||
|
const calendarManager = new CalendarManager(
|
||||||
|
eventBus,
|
||||||
|
config,
|
||||||
|
eventManager,
|
||||||
|
gridManager,
|
||||||
|
eventRenderer,
|
||||||
|
scrollManager
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('✅ ManagerFactory: All managers created successfully');
|
||||||
|
|
||||||
|
return {
|
||||||
|
eventManager,
|
||||||
|
eventRenderer,
|
||||||
|
gridManager,
|
||||||
|
scrollManager,
|
||||||
|
navigationManager,
|
||||||
|
viewManager,
|
||||||
|
calendarManager
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize all managers in the correct order
|
||||||
|
*/
|
||||||
|
public async initializeManagers(managers: {
|
||||||
|
calendarManager: CalendarManager;
|
||||||
|
[key: string]: any;
|
||||||
|
}): Promise<void> {
|
||||||
|
console.log('🚀 ManagerFactory: Initializing managers...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await managers.calendarManager.initialize();
|
||||||
|
console.log('✅ ManagerFactory: All managers initialized successfully');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ ManagerFactory: Manager initialization failed:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
60
src/index.ts
60
src/index.ts
|
|
@ -1,29 +1,14 @@
|
||||||
// Main entry point for Calendar Plantempus
|
// Main entry point for Calendar Plantempus
|
||||||
import { eventBus } from './core/EventBus.js';
|
import { eventBus } from './core/EventBus.js';
|
||||||
import { CalendarManager } from './managers/CalendarManager.js';
|
|
||||||
import { NavigationManager } from './managers/NavigationManager.js';
|
|
||||||
import { ViewManager } from './managers/ViewManager.js';
|
|
||||||
import { EventManager } from './managers/EventManager.js';
|
|
||||||
import { EventRenderer } from './renderers/EventRendererManager.js';
|
|
||||||
import { GridManager } from './managers/GridManager.js';
|
|
||||||
import { ScrollManager } from './managers/ScrollManager.js';
|
|
||||||
import { calendarConfig } from './core/CalendarConfig.js';
|
import { calendarConfig } from './core/CalendarConfig.js';
|
||||||
import { CalendarTypeFactory } from './factories/CalendarTypeFactory.js';
|
import { CalendarTypeFactory } from './factories/CalendarTypeFactory.js';
|
||||||
|
import { ManagerFactory } from './factories/ManagerFactory.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the calendar application with simple direct calls
|
* Initialize the calendar application with simple direct calls
|
||||||
*/
|
*/
|
||||||
async function initializeCalendar(): Promise<void> {
|
async function initializeCalendar(): Promise<void> {
|
||||||
console.log('🗓️ Initializing Calendar Plantempus with simple coordination...');
|
console.log('🗓️ Initializing Calendar Plantempus with factory pattern...');
|
||||||
|
|
||||||
// Declare managers outside try block for global access
|
|
||||||
let calendarManager: CalendarManager;
|
|
||||||
let navigationManager: NavigationManager;
|
|
||||||
let viewManager: ViewManager;
|
|
||||||
let eventManager: EventManager;
|
|
||||||
let eventRenderer: EventRenderer;
|
|
||||||
let gridManager: GridManager;
|
|
||||||
let scrollManager: ScrollManager;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use the singleton calendar configuration
|
// Use the singleton calendar configuration
|
||||||
|
|
@ -33,46 +18,29 @@ async function initializeCalendar(): Promise<void> {
|
||||||
console.log('🏭 Initializing CalendarTypeFactory...');
|
console.log('🏭 Initializing CalendarTypeFactory...');
|
||||||
CalendarTypeFactory.initialize();
|
CalendarTypeFactory.initialize();
|
||||||
|
|
||||||
// Create all managers
|
// Create managers using factory pattern
|
||||||
console.log('📋 Creating managers...');
|
const managerFactory = ManagerFactory.getInstance();
|
||||||
calendarManager = new CalendarManager(eventBus, config);
|
const managers = managerFactory.createManagers(eventBus, config);
|
||||||
navigationManager = new NavigationManager(eventBus); // No EventRenderer dependency
|
|
||||||
viewManager = new ViewManager(eventBus);
|
|
||||||
eventManager = new EventManager(eventBus);
|
|
||||||
eventRenderer = new EventRenderer(eventBus, eventManager); // Pass EventManager
|
|
||||||
gridManager = new GridManager();
|
|
||||||
scrollManager = new ScrollManager();
|
|
||||||
|
|
||||||
// Set manager references in CalendarManager
|
|
||||||
calendarManager.setManagers(eventManager, gridManager, eventRenderer, scrollManager);
|
|
||||||
|
|
||||||
// Enable debug mode for development
|
// Enable debug mode for development
|
||||||
eventBus.setDebug(true);
|
eventBus.setDebug(true);
|
||||||
|
|
||||||
// Initialize using simple direct calls
|
// Initialize all managers
|
||||||
console.log('🚀 Starting simple initialization...');
|
await managerFactory.initializeManagers(managers);
|
||||||
await calendarManager.initialize();
|
|
||||||
|
|
||||||
console.log('🎊 Calendar Plantempus initialized successfully!');
|
console.log('🎊 Calendar Plantempus initialized successfully!');
|
||||||
console.log('📊 Initialization Report:', calendarManager.getInitializationReport());
|
console.log('📊 Initialization Report:', managers.calendarManager.getInitializationReport());
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('💥 Calendar initialization failed:', error);
|
|
||||||
// Could implement fallback or retry logic here
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expose to window for debugging
|
// Expose to window for debugging
|
||||||
(window as any).calendarDebug = {
|
(window as any).calendarDebug = {
|
||||||
eventBus,
|
eventBus,
|
||||||
calendarManager,
|
...managers
|
||||||
navigationManager,
|
|
||||||
viewManager,
|
|
||||||
eventManager,
|
|
||||||
eventRenderer,
|
|
||||||
gridManager,
|
|
||||||
scrollManager
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('💥 Calendar initialization failed:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize when DOM is ready - now handles async properly
|
// Initialize when DOM is ready - now handles async properly
|
||||||
|
|
|
||||||
53
src/interfaces/IManager.ts
Normal file
53
src/interfaces/IManager.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* Base interface for all managers
|
||||||
|
*/
|
||||||
|
export interface IManager {
|
||||||
|
/**
|
||||||
|
* Initialize the manager
|
||||||
|
*/
|
||||||
|
initialize?(): Promise<void> | void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the manager's state
|
||||||
|
*/
|
||||||
|
refresh?(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the manager and clean up resources
|
||||||
|
*/
|
||||||
|
destroy?(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for managers that handle events
|
||||||
|
*/
|
||||||
|
export interface IEventManager extends IManager {
|
||||||
|
loadData(): Promise<void>;
|
||||||
|
getEvents(): any[];
|
||||||
|
getEventsForPeriod(startDate: Date, endDate: Date): any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for managers that handle rendering
|
||||||
|
*/
|
||||||
|
export interface IRenderingManager extends IManager {
|
||||||
|
render(): Promise<void> | void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for managers that handle navigation
|
||||||
|
*/
|
||||||
|
export interface INavigationManager extends IManager {
|
||||||
|
getCurrentWeek(): Date;
|
||||||
|
navigateToToday(): void;
|
||||||
|
navigateToNextWeek(): void;
|
||||||
|
navigateToPreviousWeek(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for managers that handle scrolling
|
||||||
|
*/
|
||||||
|
export interface IScrollManager extends IManager {
|
||||||
|
scrollTo(scrollTop: number): void;
|
||||||
|
scrollToHour(hour: number): void;
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ import { CalendarConfig } from '../core/CalendarConfig.js';
|
||||||
import { CalendarEvent, CalendarView, IEventBus } from '../types/CalendarTypes.js';
|
import { CalendarEvent, CalendarView, IEventBus } from '../types/CalendarTypes.js';
|
||||||
import { EventManager } from './EventManager.js';
|
import { EventManager } from './EventManager.js';
|
||||||
import { GridManager } from './GridManager.js';
|
import { GridManager } from './GridManager.js';
|
||||||
import { EventRenderer } from '../renderers/EventRendererManager.js';
|
import { EventRenderingService } from '../renderers/EventRendererManager.js';
|
||||||
import { ScrollManager } from './ScrollManager.js';
|
import { ScrollManager } from './ScrollManager.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,27 +16,28 @@ export class CalendarManager {
|
||||||
private config: CalendarConfig;
|
private config: CalendarConfig;
|
||||||
private eventManager: EventManager;
|
private eventManager: EventManager;
|
||||||
private gridManager: GridManager;
|
private gridManager: GridManager;
|
||||||
private eventRenderer: EventRenderer;
|
private eventRenderer: EventRenderingService;
|
||||||
private scrollManager: ScrollManager;
|
private scrollManager: ScrollManager;
|
||||||
private currentView: CalendarView = 'week';
|
private currentView: CalendarView = 'week';
|
||||||
private currentDate: Date = new Date();
|
private currentDate: Date = new Date();
|
||||||
private isInitialized: boolean = false;
|
private isInitialized: boolean = false;
|
||||||
|
|
||||||
constructor(eventBus: IEventBus, config: CalendarConfig) {
|
constructor(
|
||||||
|
eventBus: IEventBus,
|
||||||
|
config: CalendarConfig,
|
||||||
|
eventManager: EventManager,
|
||||||
|
gridManager: GridManager,
|
||||||
|
eventRenderer: EventRenderingService,
|
||||||
|
scrollManager: ScrollManager
|
||||||
|
) {
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.setupEventListeners();
|
|
||||||
console.log('📋 CalendarManager: Created with direct coordination');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set manager references (called from index.ts)
|
|
||||||
*/
|
|
||||||
public setManagers(eventManager: EventManager, gridManager: GridManager, eventRenderer: EventRenderer, scrollManager: ScrollManager): void {
|
|
||||||
this.eventManager = eventManager;
|
this.eventManager = eventManager;
|
||||||
this.gridManager = gridManager;
|
this.gridManager = gridManager;
|
||||||
this.eventRenderer = eventRenderer;
|
this.eventRenderer = eventRenderer;
|
||||||
this.scrollManager = scrollManager;
|
this.scrollManager = scrollManager;
|
||||||
|
this.setupEventListeners();
|
||||||
|
console.log('📋 CalendarManager: Created with proper dependency injection');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -184,81 +184,6 @@ export class EventManager {
|
||||||
this.syncEvents();
|
this.syncEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load events for a specific week into a container (POC-style)
|
|
||||||
*/
|
|
||||||
private loadEventsForWeek(weekStart: Date, weekEnd: Date, container: HTMLElement): void {
|
|
||||||
console.log(`EventManager: Loading events for week ${weekStart.toDateString()} - ${weekEnd.toDateString()}`);
|
|
||||||
|
|
||||||
// Filter events for this week
|
|
||||||
const weekEvents = this.events.filter(event => {
|
|
||||||
const eventDate = new Date(event.start);
|
|
||||||
return eventDate >= weekStart && eventDate <= weekEnd;
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`EventManager: Found ${weekEvents.length} events for this week`);
|
|
||||||
|
|
||||||
// Render events in the container (POC approach)
|
|
||||||
this.renderEventsInContainer(weekEvents, container);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render events in a specific container (POC-style)
|
|
||||||
*/
|
|
||||||
private renderEventsInContainer(events: CalendarEvent[], container: HTMLElement): void {
|
|
||||||
const dayColumns = container.querySelectorAll('swp-day-column');
|
|
||||||
|
|
||||||
events.forEach(event => {
|
|
||||||
const eventDate = new Date(event.start);
|
|
||||||
const dayOfWeek = eventDate.getDay(); // 0 = Sunday
|
|
||||||
const column = dayColumns[dayOfWeek];
|
|
||||||
|
|
||||||
if (column) {
|
|
||||||
const eventsLayer = column.querySelector('swp-events-layer');
|
|
||||||
if (eventsLayer) {
|
|
||||||
this.renderEventInColumn(event, eventsLayer as HTMLElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render a single event in a column (POC-style)
|
|
||||||
*/
|
|
||||||
private renderEventInColumn(event: CalendarEvent, eventsLayer: HTMLElement): void {
|
|
||||||
const eventElement = document.createElement('swp-event');
|
|
||||||
eventElement.dataset.type = event.type || 'meeting';
|
|
||||||
|
|
||||||
// Calculate position (simplified - assumes 7 AM start like POC)
|
|
||||||
const startTime = new Date(event.start);
|
|
||||||
const hours = startTime.getHours();
|
|
||||||
const minutes = startTime.getMinutes();
|
|
||||||
const startMinutes = (hours - 7) * 60 + minutes; // 7 is start hour like POC
|
|
||||||
|
|
||||||
// Calculate duration
|
|
||||||
const endTime = new Date(event.end);
|
|
||||||
const durationMs = endTime.getTime() - startTime.getTime();
|
|
||||||
const durationMinutes = Math.floor(durationMs / (1000 * 60));
|
|
||||||
|
|
||||||
eventElement.style.top = `${startMinutes}px`;
|
|
||||||
eventElement.style.height = `${durationMinutes}px`;
|
|
||||||
|
|
||||||
eventElement.innerHTML = `
|
|
||||||
<swp-event-time>${this.formatTime(hours, minutes)}</swp-event-time>
|
|
||||||
<swp-event-title>${event.title}</swp-event-title>
|
|
||||||
`;
|
|
||||||
|
|
||||||
eventsLayer.appendChild(eventElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format time for display (POC-style)
|
|
||||||
*/
|
|
||||||
private formatTime(hours: number, minutes: number): string {
|
|
||||||
const period = hours >= 12 ? 'PM' : 'AM';
|
|
||||||
const displayHours = hours % 12 || 12;
|
|
||||||
return `${displayHours}:${String(minutes).padStart(2, '0')} ${period}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
public destroy(): void {
|
public destroy(): void {
|
||||||
this.events = [];
|
this.events = [];
|
||||||
|
|
|
||||||
|
|
@ -197,25 +197,12 @@ export class NavigationManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility functions (from POC) - moved formatting to NavigationRenderer
|
|
||||||
|
|
||||||
private updateWeekInfo(): void {
|
private updateWeekInfo(): void {
|
||||||
const weekNumber = DateUtils.getWeekNumber(this.currentWeek);
|
const weekNumber = DateUtils.getWeekNumber(this.currentWeek);
|
||||||
const weekEnd = DateUtils.addDays(this.currentWeek, 6);
|
const weekEnd = DateUtils.addDays(this.currentWeek, 6);
|
||||||
const dateRange = DateUtils.formatDateRange(this.currentWeek, weekEnd);
|
const dateRange = DateUtils.formatDateRange(this.currentWeek, weekEnd);
|
||||||
|
|
||||||
// Update week info in DOM
|
// Notify other managers about week info update - DOM manipulation should happen via events
|
||||||
const weekNumberElement = document.querySelector('swp-week-number');
|
|
||||||
const dateRangeElement = document.querySelector('swp-date-range');
|
|
||||||
|
|
||||||
if (weekNumberElement)
|
|
||||||
weekNumberElement.textContent = `Week ${weekNumber}`;
|
|
||||||
|
|
||||||
|
|
||||||
if (dateRangeElement)
|
|
||||||
dateRangeElement.textContent = dateRange;
|
|
||||||
|
|
||||||
// Notify other managers about week info update
|
|
||||||
this.eventBus.emit(EventTypes.WEEK_INFO_UPDATED, {
|
this.eventBus.emit(EventTypes.WEEK_INFO_UPDATED, {
|
||||||
weekNumber,
|
weekNumber,
|
||||||
dateRange,
|
dateRange,
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ import { EventManager } from '../managers/EventManager';
|
||||||
import { EventRendererStrategy } from './EventRenderer';
|
import { EventRendererStrategy } from './EventRenderer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EventRenderer - Render events i DOM med positionering using Strategy Pattern
|
* EventRenderingService - Render events i DOM med positionering using Strategy Pattern
|
||||||
* Håndterer event positioning og overlap detection
|
* Håndterer event positioning og overlap detection
|
||||||
*/
|
*/
|
||||||
export class EventRenderer {
|
export class EventRenderingService {
|
||||||
private eventBus: IEventBus;
|
private eventBus: IEventBus;
|
||||||
private eventManager: EventManager;
|
private eventManager: EventManager;
|
||||||
private strategy: EventRendererStrategy;
|
private strategy: EventRendererStrategy;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { ResourceCalendarData } from '../types/CalendarTypes';
|
||||||
import { CalendarTypeFactory } from '../factories/CalendarTypeFactory';
|
import { CalendarTypeFactory } from '../factories/CalendarTypeFactory';
|
||||||
import { HeaderRenderContext } from './HeaderRenderer';
|
import { HeaderRenderContext } from './HeaderRenderer';
|
||||||
import { ColumnRenderContext } from './ColumnRenderer';
|
import { ColumnRenderContext } from './ColumnRenderer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GridRenderer - Handles DOM rendering for the calendar grid
|
* GridRenderer - Handles DOM rendering for the calendar grid
|
||||||
* Separated from GridManager to follow Single Responsibility Principle
|
* Separated from GridManager to follow Single Responsibility Principle
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,34 @@ export class NavigationRenderer {
|
||||||
|
|
||||||
constructor(eventBus: IEventBus) {
|
constructor(eventBus: IEventBus) {
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
|
this.setupEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup event listeners for DOM updates
|
||||||
|
*/
|
||||||
|
private setupEventListeners(): void {
|
||||||
|
this.eventBus.on(EventTypes.WEEK_INFO_UPDATED, (event: Event) => {
|
||||||
|
const customEvent = event as CustomEvent;
|
||||||
|
const { weekNumber, dateRange } = customEvent.detail;
|
||||||
|
this.updateWeekInfoInDOM(weekNumber, dateRange);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update week info in DOM elements
|
||||||
|
*/
|
||||||
|
private updateWeekInfoInDOM(weekNumber: number, dateRange: string): void {
|
||||||
|
const weekNumberElement = document.querySelector('swp-week-number');
|
||||||
|
const dateRangeElement = document.querySelector('swp-date-range');
|
||||||
|
|
||||||
|
if (weekNumberElement) {
|
||||||
|
weekNumberElement.textContent = `Week ${weekNumber}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dateRangeElement) {
|
||||||
|
dateRangeElement.textContent = dateRange;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue