Renaming part 1
This commit is contained in:
parent
36ac8d18ab
commit
29811fd4b5
20 changed files with 1424 additions and 582 deletions
|
|
@ -2,18 +2,22 @@ import { EventBus } from '../core/EventBus';
|
|||
import { IEventBus, CalendarEvent } from '../types/CalendarTypes';
|
||||
import { EventTypes } from '../constants/EventTypes';
|
||||
import { calendarConfig } from '../core/CalendarConfig';
|
||||
import { DateUtils } from '../utils/DateUtils';
|
||||
import { CalendarTypeFactory } from '../factories/CalendarTypeFactory';
|
||||
|
||||
/**
|
||||
* EventRenderer - Render events i DOM med positionering
|
||||
* EventRenderer - Render events i DOM med positionering using Strategy Pattern
|
||||
* Håndterer event positioning og overlap detection
|
||||
*/
|
||||
export class EventRenderer {
|
||||
private eventBus: IEventBus;
|
||||
private pendingEvents: CalendarEvent[] = [];
|
||||
|
||||
constructor(eventBus: IEventBus) {
|
||||
this.eventBus = eventBus;
|
||||
this.setupEventListeners();
|
||||
|
||||
// Initialize the factory (if not already done)
|
||||
CalendarTypeFactory.initialize();
|
||||
}
|
||||
|
||||
private setupEventListeners(): void {
|
||||
|
|
@ -35,17 +39,26 @@ export class EventRenderer {
|
|||
// Clear existing events when view changes
|
||||
this.clearEvents();
|
||||
});
|
||||
|
||||
// Handle calendar type changes
|
||||
this.eventBus.on(EventTypes.CALENDAR_TYPE_CHANGED, () => {
|
||||
// Re-render events with new strategy
|
||||
this.tryRenderEvents();
|
||||
});
|
||||
}
|
||||
|
||||
private pendingEvents: CalendarEvent[] = [];
|
||||
|
||||
private tryRenderEvents(): void {
|
||||
// Only render if we have both events and grid is ready
|
||||
// Only render if we have both events and appropriate columns are ready
|
||||
console.log('EventRenderer: tryRenderEvents called, pending events:', this.pendingEvents.length);
|
||||
|
||||
if (this.pendingEvents.length > 0) {
|
||||
const dayColumns = document.querySelectorAll('swp-day-column');
|
||||
console.log('EventRenderer: Found', dayColumns.length, 'day columns');
|
||||
if (dayColumns.length > 0) {
|
||||
const calendarType = calendarConfig.getCalendarType();
|
||||
let columnsSelector = calendarType === 'resource' ? 'swp-resource-column' : 'swp-day-column';
|
||||
const columns = document.querySelectorAll(columnsSelector);
|
||||
|
||||
console.log(`EventRenderer: Found ${columns.length} ${columnsSelector} elements for ${calendarType} calendar`);
|
||||
|
||||
if (columns.length > 0) {
|
||||
this.renderEvents(this.pendingEvents);
|
||||
this.pendingEvents = []; // Clear pending events after rendering
|
||||
}
|
||||
|
|
@ -54,173 +67,34 @@ export class EventRenderer {
|
|||
|
||||
private renderEvents(events: CalendarEvent[]): void {
|
||||
console.log('EventRenderer: renderEvents called with', events.length, 'events');
|
||||
console.log('EventRenderer: All events:', events.map(e => ({ title: e.title, allDay: e.allDay, start: e.start })));
|
||||
|
||||
// Clear existing events first
|
||||
this.clearEvents();
|
||||
|
||||
// Get current week dates for filtering
|
||||
const currentWeekDates = this.getCurrentWeekDates();
|
||||
// Filter events for current week and exclude all-day events (handled by GridManager)
|
||||
const currentWeekEvents = events.filter(event => {
|
||||
// Skip all-day events - they are handled by GridManager
|
||||
if (event.allDay) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const eventDate = new Date(event.start);
|
||||
const eventDateStr = DateUtils.formatDate(eventDate);
|
||||
const isInCurrentWeek = currentWeekDates.some(weekDate =>
|
||||
DateUtils.formatDate(weekDate) === eventDateStr
|
||||
);
|
||||
return isInCurrentWeek;
|
||||
});
|
||||
|
||||
// Render each event in the correct day column
|
||||
currentWeekEvents.forEach(event => {
|
||||
const eventDate = new Date(event.start);
|
||||
const dayColumn = this.findDayColumn(eventDate);
|
||||
|
||||
if (dayColumn) {
|
||||
const eventsLayer = dayColumn.querySelector('swp-events-layer');
|
||||
if (eventsLayer) {
|
||||
this.renderEvent(event, eventsLayer);
|
||||
} else {
|
||||
console.warn('EventRenderer: No events layer found in day column for', DateUtils.formatDate(eventDate));
|
||||
}
|
||||
} else {
|
||||
console.warn('EventRenderer: No day column found for event date', DateUtils.formatDate(eventDate));
|
||||
}
|
||||
});
|
||||
// Get the appropriate event renderer strategy
|
||||
const calendarType = calendarConfig.getCalendarType();
|
||||
const eventRenderer = CalendarTypeFactory.getEventRenderer(calendarType);
|
||||
|
||||
console.log(`EventRenderer: Using ${calendarType} event renderer strategy`);
|
||||
|
||||
// Use strategy to render events
|
||||
eventRenderer.renderEvents(events, calendarConfig);
|
||||
|
||||
// Emit event rendered
|
||||
this.eventBus.emit(EventTypes.EVENT_RENDERED, {
|
||||
count: currentWeekEvents.length
|
||||
count: events.filter(e => !e.allDay).length
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current week dates (Sunday to Saturday)
|
||||
*/
|
||||
private getCurrentWeekDates(): Date[] {
|
||||
const today = new Date();
|
||||
const weekStart = DateUtils.getWeekStart(today, 0); // Sunday start
|
||||
const dates: Date[] = [];
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const date = DateUtils.addDays(weekStart, i);
|
||||
dates.push(date);
|
||||
}
|
||||
|
||||
return dates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find day column for specific date
|
||||
*/
|
||||
private findDayColumn(date: Date): HTMLElement | null {
|
||||
const dateStr = DateUtils.formatDate(date);
|
||||
const dayColumn = document.querySelector(`swp-day-column[data-date="${dateStr}"]`) as HTMLElement;
|
||||
console.log('EventRenderer: Looking for day column with date', dateStr, 'found:', !!dayColumn);
|
||||
return dayColumn;
|
||||
}
|
||||
|
||||
private renderEvent(event: CalendarEvent, container: Element): void {
|
||||
const eventElement = document.createElement('swp-event');
|
||||
eventElement.dataset.eventId = event.id;
|
||||
eventElement.dataset.type = event.type;
|
||||
|
||||
// Calculate position based on time
|
||||
const position = this.calculateEventPosition(event);
|
||||
eventElement.style.position = 'absolute';
|
||||
eventElement.style.top = `${position.top + 1}px`;
|
||||
eventElement.style.height = `${position.height - 1}px`;
|
||||
|
||||
// Only set positioning and color - rest is in CSS
|
||||
eventElement.style.backgroundColor = event.metadata?.color || '#3498db';
|
||||
|
||||
// Format time for display
|
||||
const startTime = this.formatTime(event.start);
|
||||
const endTime = this.formatTime(event.end);
|
||||
|
||||
// Create event content
|
||||
eventElement.innerHTML = `
|
||||
<swp-event-time>${startTime} - ${endTime}</swp-event-time>
|
||||
<swp-event-title>${event.title}</swp-event-title>
|
||||
`;
|
||||
|
||||
// Add event listeners
|
||||
this.addEventListeners(eventElement, event);
|
||||
|
||||
container.appendChild(eventElement);
|
||||
|
||||
// Event successfully rendered
|
||||
}
|
||||
|
||||
private calculateEventPosition(event: CalendarEvent): { top: number; height: number } {
|
||||
const startDate = new Date(event.start);
|
||||
const endDate = new Date(event.end);
|
||||
|
||||
// Use dayStartHour to match time-axis positioning - this is the visible start hour (6 AM)
|
||||
const dayStartHour = calendarConfig.get('dayStartHour'); // 6 (6 AM)
|
||||
const hourHeight = calendarConfig.get('hourHeight');
|
||||
|
||||
// Calculate minutes from visible day start (6 AM, not midnight)
|
||||
const eventHour = startDate.getHours();
|
||||
const eventMinutes = startDate.getMinutes();
|
||||
const startMinutes = (eventHour - dayStartHour) * 60 + eventMinutes;
|
||||
|
||||
// Calculate duration in minutes
|
||||
const duration = (endDate.getTime() - startDate.getTime()) / (1000 * 60);
|
||||
|
||||
// Convert to pixels - position relative to visible time-grid (starts at dayStartHour)
|
||||
const top = startMinutes * (hourHeight / 60);
|
||||
const height = duration * (hourHeight / 60);
|
||||
|
||||
|
||||
return { top, height };
|
||||
}
|
||||
|
||||
private formatTime(isoString: string): string {
|
||||
const date = new Date(isoString);
|
||||
const hours = date.getHours();
|
||||
const minutes = date.getMinutes();
|
||||
|
||||
const period = hours >= 12 ? 'PM' : 'AM';
|
||||
const displayHours = hours % 12 || 12;
|
||||
const displayMinutes = minutes.toString().padStart(2, '0');
|
||||
|
||||
return `${displayHours}:${displayMinutes} ${period}`;
|
||||
}
|
||||
|
||||
private addEventListeners(eventElement: HTMLElement, event: CalendarEvent): void {
|
||||
// Click handler
|
||||
eventElement.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
this.eventBus.emit(EventTypes.EVENT_SELECTED, {
|
||||
event,
|
||||
element: eventElement
|
||||
});
|
||||
});
|
||||
|
||||
// Hover effects are handled by CSS
|
||||
// Hover effects are now handled by CSS
|
||||
}
|
||||
|
||||
private clearEvents(): void {
|
||||
const eventsLayers = document.querySelectorAll('swp-events-layer');
|
||||
eventsLayers.forEach(layer => {
|
||||
layer.innerHTML = '';
|
||||
});
|
||||
const calendarType = calendarConfig.getCalendarType();
|
||||
const eventRenderer = CalendarTypeFactory.getEventRenderer(calendarType);
|
||||
eventRenderer.clearEvents();
|
||||
}
|
||||
|
||||
public refresh(): void {
|
||||
// Request fresh events from EventManager
|
||||
this.eventBus.emit(EventTypes.REFRESH_REQUESTED);
|
||||
this.tryRenderEvents();
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this.pendingEvents = [];
|
||||
this.clearEvents();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue