WIP on master

This commit is contained in:
Janus C. H. Knudsen 2025-11-03 14:54:57 +01:00
parent b6ab1ff50e
commit 80aaab46f2
25 changed files with 6291 additions and 927 deletions

View file

@ -25,10 +25,19 @@ interface GridSettings {
/**
* ConfigManager - Handles configuration updates with event emission
* Wraps static CalendarConfig with event-driven functionality for DI system
* Also manages CSS custom properties that reflect config values
*/
export class ConfigManager {
constructor(private eventBus: IEventBus) {}
/**
* Initialize CSS variables on startup
* Must be called after DOM is ready but before any rendering
*/
public initialize(): void {
this.updateCSSVariables();
}
/**
* Set a config value and emit event
*/
@ -36,6 +45,9 @@ export class ConfigManager {
const oldValue = CalendarConfig.get(key);
CalendarConfig.set(key, value);
// Update CSS variables to reflect config change
this.updateCSSVariables();
// Emit config update event
this.eventBus.emit(CoreEvents.REFRESH_REQUESTED, {
key,
@ -59,6 +71,9 @@ export class ConfigManager {
updateGridSettings(updates: Partial<GridSettings>): void {
CalendarConfig.updateGridSettings(updates);
// Update CSS variables to reflect config change
this.updateCSSVariables();
// Emit event after update
this.eventBus.emit(CoreEvents.REFRESH_REQUESTED, {
key: 'gridSettings',
@ -89,6 +104,9 @@ export class ConfigManager {
const oldWorkWeek = CalendarConfig.getCurrentWorkWeek();
CalendarConfig.setWorkWeek(workWeekId);
// Update CSS variables to reflect config change
this.updateCSSVariables();
// Emit event if changed
if (oldWorkWeek !== workWeekId) {
this.eventBus.emit(CoreEvents.REFRESH_REQUESTED, {
@ -98,4 +116,59 @@ export class ConfigManager {
});
}
}
/**
* Update all CSS custom properties based on current config
* This keeps the DOM in sync with config values
*/
private updateCSSVariables(): void {
const root = document.documentElement;
const gridSettings = CalendarConfig.getGridSettings();
const calendar = document.querySelector('swp-calendar') as HTMLElement;
// Set time-related CSS variables
root.style.setProperty('--header-height', '80px'); // Fixed header height
root.style.setProperty('--hour-height', `${gridSettings.hourHeight}px`);
root.style.setProperty('--minute-height', `${gridSettings.hourHeight / 60}px`);
root.style.setProperty('--snap-interval', gridSettings.snapInterval.toString());
root.style.setProperty('--day-start-hour', gridSettings.dayStartHour.toString());
root.style.setProperty('--day-end-hour', gridSettings.dayEndHour.toString());
root.style.setProperty('--work-start-hour', gridSettings.workStartHour.toString());
root.style.setProperty('--work-end-hour', gridSettings.workEndHour.toString());
// Set column count based on view
const columnCount = this.calculateColumnCount();
root.style.setProperty('--grid-columns', columnCount.toString());
// Set column width based on fitToWidth setting
if (gridSettings.fitToWidth) {
root.style.setProperty('--day-column-min-width', '50px'); // Small min-width allows columns to fit available space
} else {
root.style.setProperty('--day-column-min-width', '250px'); // Default min-width for horizontal scroll mode
}
// Set fitToWidth data attribute for CSS targeting
if (calendar) {
calendar.setAttribute('data-fit-to-width', gridSettings.fitToWidth.toString());
}
}
/**
* Calculate number of columns based on view
*/
private calculateColumnCount(): number {
const dateSettings = CalendarConfig.getDateViewSettings();
const workWeekSettings = CalendarConfig.getWorkWeekSettings();
switch (dateSettings.period) {
case 'day':
return 1;
case 'week':
return workWeekSettings.totalDays;
case 'month':
return workWeekSettings.totalDays; // Use work week for month view too
default:
return workWeekSettings.totalDays;
}
}
}

View file

@ -2,83 +2,43 @@ import { IEventBus, CalendarEvent } from '../types/CalendarTypes';
import { CoreEvents } from '../constants/CoreEvents';
import { CalendarConfig } from '../core/CalendarConfig';
import { DateService } from '../utils/DateService';
interface RawEventData {
id: string;
title: string;
start: string | Date;
end: string | Date;
type : string;
color?: string;
allDay?: boolean;
[key: string]: unknown;
}
import { IEventRepository } from '../repositories/IEventRepository';
/**
* EventManager - Event lifecycle and CRUD operations
* Handles data loading and event management
* Handles event management and CRUD operations
*/
export class EventManager {
private events: CalendarEvent[] = [];
private rawData: RawEventData[] | null = null;
private dateService: DateService;
private config: CalendarConfig;
private repository: IEventRepository;
constructor(
private eventBus: IEventBus,
dateService: DateService,
config: CalendarConfig
config: CalendarConfig,
repository: IEventRepository
) {
this.dateService = dateService;
this.config = config;
this.repository = repository;
}
/**
* Load event data from JSON file
* Load event data from repository
*/
public async loadData(): Promise<void> {
try {
await this.loadMockData();
this.events = await this.repository.loadEvents();
} catch (error) {
console.error('Failed to load event data:', error);
this.events = [];
this.rawData = null;
throw error;
}
}
/**
* Optimized mock data loading
*/
private async loadMockData(): Promise<void> {
const jsonFile = 'data/mock-events.json';
const response = await fetch(jsonFile);
if (!response.ok) {
throw new Error(`Failed to load mock events: ${response.status} ${response.statusText}`);
}
const data = await response.json();
// Store raw data and process in one operation
this.rawData = data;
this.events = this.processCalendarData(data);
}
/**
* Process raw event data and convert to CalendarEvent objects
*/
private processCalendarData(data: RawEventData[]): CalendarEvent[] {
return data.map((event): CalendarEvent => ({
...event,
start: new Date(event.start),
end: new Date(event.end),
type : event.type,
allDay: event.allDay || false,
syncStatus: 'synced' as const
}));
}
/**
* Get events with optional copying for performance
*/

View file

@ -7,7 +7,6 @@ import { eventBus } from '../core/EventBus';
import { CoreEvents } from '../constants/CoreEvents';
import { CalendarView } from '../types/CalendarTypes';
import { GridRenderer } from '../renderers/GridRenderer';
import { GridStyleManager } from '../renderers/GridStyleManager';
import { DateService } from '../utils/DateService';
/**
@ -18,16 +17,13 @@ export class GridManager {
private currentDate: Date = new Date();
private currentView: CalendarView = 'week';
private gridRenderer: GridRenderer;
private styleManager: GridStyleManager;
private dateService: DateService;
constructor(
gridRenderer: GridRenderer,
styleManager: GridStyleManager,
dateService: DateService
) {
this.gridRenderer = gridRenderer;
this.styleManager = styleManager;
this.dateService = dateService;
this.init();
}
@ -85,15 +81,13 @@ export class GridManager {
/**
* Main render method - delegates to GridRenderer
* Note: CSS variables are automatically updated by ConfigManager when config changes
*/
public async render(): Promise<void> {
if (!this.container) {
return;
}
// Update CSS variables first
this.styleManager.updateGridStyles();
// Delegate to GridRenderer with current view context
this.gridRenderer.renderGrid(
this.container,