Adds I-prefix to all interfaces

This commit is contained in:
Janus C. H. Knudsen 2025-11-03 21:30:50 +01:00
parent 80aaab46f2
commit 8ec5f52872
44 changed files with 1731 additions and 1949 deletions

View file

@ -1,436 +0,0 @@
// Calendar configuration management
// Pure static configuration class - no dependencies, no events
import { ICalendarConfig, ViewPeriod } from '../types/CalendarTypes';
import { TimeFormatter, TimeFormatSettings } from '../utils/TimeFormatter';
/**
* All-day event layout constants
*/
export const ALL_DAY_CONSTANTS = {
EVENT_HEIGHT: 22, // Height of single all-day event
EVENT_GAP: 2, // Gap between stacked events
CONTAINER_PADDING: 4, // Container padding (top + bottom)
MAX_COLLAPSED_ROWS: 4, // Show 4 rows when collapsed (3 events + 1 indicator row)
get SINGLE_ROW_HEIGHT() {
return this.EVENT_HEIGHT + this.EVENT_GAP; // 28px
}
} as const;
/**
* Layout and timing settings for the calendar grid
*/
interface GridSettings {
// Time boundaries
dayStartHour: number;
dayEndHour: number;
workStartHour: number;
workEndHour: number;
// Layout settings
hourHeight: number;
snapInterval: number;
fitToWidth: boolean;
scrollToHour: number | null;
// Event grouping settings
gridStartThresholdMinutes: number; // ±N minutes for events to share grid columns
// Display options
showCurrentTime: boolean;
showWorkHours: boolean;
}
/**
* View settings for date-based calendar mode
*/
interface DateViewSettings {
period: ViewPeriod; // day/week/month
weekDays: number; // Number of days to show in week view
firstDayOfWeek: number; // 0=Sunday, 1=Monday
showAllDay: boolean; // Show all-day event row
}
/**
* Work week configuration settings
*/
interface WorkWeekSettings {
id: string;
workDays: number[]; // ISO 8601: [1,2,3,4,5] for mon-fri (1=Mon, 7=Sun)
totalDays: number; // 5
firstWorkDay: number; // ISO: 1 = Monday, 7 = Sunday
}
/**
* Time format configuration settings
*/
interface TimeFormatConfig {
timezone: string;
use24HourFormat: boolean;
locale: string;
dateFormat: 'locale' | 'technical';
showSeconds: boolean;
}
/**
* Calendar configuration management - Pure static config
*/
export class CalendarConfig {
private static config: ICalendarConfig = {
// Scrollbar styling
scrollbarWidth: 16, // Width of scrollbar in pixels
scrollbarColor: '#666', // Scrollbar thumb color
scrollbarTrackColor: '#f0f0f0', // Scrollbar track color
scrollbarHoverColor: '#b53f7aff', // Scrollbar thumb hover color
scrollbarBorderRadius: 6, // Border radius for scrollbar thumb
// Interaction settings
allowDrag: true,
allowResize: true,
allowCreate: true,
// API settings
apiEndpoint: '/api/events',
dateFormat: 'YYYY-MM-DD',
timeFormat: 'HH:mm',
// Feature flags
enableSearch: true,
enableTouch: true,
// Event defaults
defaultEventDuration: 60, // Minutes
minEventDuration: 15, // Will be same as snapInterval
maxEventDuration: 480 // 8 hours
};
private static selectedDate: Date | null = new Date();
private static currentWorkWeek: string = 'standard';
// Grid display settings
private static gridSettings: GridSettings = {
hourHeight: 60,
dayStartHour: 0,
dayEndHour: 24,
workStartHour: 8,
workEndHour: 17,
snapInterval: 15,
gridStartThresholdMinutes: 30, // Events starting within ±15 min share grid columns
showCurrentTime: true,
showWorkHours: true,
fitToWidth: false,
scrollToHour: 8
};
// Date view settings
private static dateViewSettings: DateViewSettings = {
period: 'week',
weekDays: 7,
firstDayOfWeek: 1,
showAllDay: true
};
// Time format settings - default to Denmark with technical format
private static timeFormatConfig: TimeFormatConfig = {
timezone: 'Europe/Copenhagen',
use24HourFormat: true,
locale: 'da-DK',
dateFormat: 'technical',
showSeconds: false
};
/**
* Initialize configuration - called once at startup
*/
static initialize(): void {
// Set computed values
CalendarConfig.config.minEventDuration = CalendarConfig.gridSettings.snapInterval;
// Initialize TimeFormatter with default settings
TimeFormatter.configure(CalendarConfig.timeFormatConfig);
// Load from data attributes
CalendarConfig.loadFromDOM();
}
/**
* Load configuration from DOM data attributes
*/
private static loadFromDOM(): void {
const calendar = document.querySelector('swp-calendar') as HTMLElement;
if (!calendar) return;
// Read data attributes
const attrs = calendar.dataset;
// Update date view settings
if (attrs.view) CalendarConfig.dateViewSettings.period = attrs.view as ViewPeriod;
if (attrs.weekDays) CalendarConfig.dateViewSettings.weekDays = parseInt(attrs.weekDays);
// Update grid settings
if (attrs.snapInterval) CalendarConfig.gridSettings.snapInterval = parseInt(attrs.snapInterval);
if (attrs.dayStartHour) CalendarConfig.gridSettings.dayStartHour = parseInt(attrs.dayStartHour);
if (attrs.dayEndHour) CalendarConfig.gridSettings.dayEndHour = parseInt(attrs.dayEndHour);
if (attrs.hourHeight) CalendarConfig.gridSettings.hourHeight = parseInt(attrs.hourHeight);
if (attrs.fitToWidth !== undefined) CalendarConfig.gridSettings.fitToWidth = attrs.fitToWidth === 'true';
// Update computed values
CalendarConfig.config.minEventDuration = CalendarConfig.gridSettings.snapInterval;
}
/**
* Get a config value
*/
static get<K extends keyof ICalendarConfig>(key: K): ICalendarConfig[K] {
return CalendarConfig.config[key];
}
/**
* Set a config value (no events - use ConfigManager for updates with events)
*/
static set<K extends keyof ICalendarConfig>(key: K, value: ICalendarConfig[K]): void {
CalendarConfig.config[key] = value;
}
/**
* Update multiple config values (no events - use ConfigManager for updates with events)
*/
static update(updates: Partial<ICalendarConfig>): void {
Object.entries(updates).forEach(([key, value]) => {
CalendarConfig.set(key as keyof ICalendarConfig, value);
});
}
/**
* Get all config
*/
static getAll(): ICalendarConfig {
return { ...CalendarConfig.config };
}
/**
* Calculate derived values
*/
static get minuteHeight(): number {
return CalendarConfig.gridSettings.hourHeight / 60;
}
static get totalHours(): number {
return CalendarConfig.gridSettings.dayEndHour - CalendarConfig.gridSettings.dayStartHour;
}
static get totalMinutes(): number {
return CalendarConfig.totalHours * 60;
}
static get slotsPerHour(): number {
return 60 / CalendarConfig.gridSettings.snapInterval;
}
static get totalSlots(): number {
return CalendarConfig.totalHours * CalendarConfig.slotsPerHour;
}
static get slotHeight(): number {
return CalendarConfig.gridSettings.hourHeight / CalendarConfig.slotsPerHour;
}
/**
* Validate snap interval
*/
static isValidSnapInterval(interval: number): boolean {
return [5, 10, 15, 30, 60].includes(interval);
}
/**
* Get grid display settings
*/
static getGridSettings(): GridSettings {
return { ...CalendarConfig.gridSettings };
}
/**
* Update grid display settings (no events - use ConfigManager for updates with events)
*/
static updateGridSettings(updates: Partial<GridSettings>): void {
CalendarConfig.gridSettings = { ...CalendarConfig.gridSettings, ...updates };
// Update computed values
if (updates.snapInterval) {
CalendarConfig.config.minEventDuration = updates.snapInterval;
}
}
/**
* Get date view settings
*/
static getDateViewSettings(): DateViewSettings {
return { ...CalendarConfig.dateViewSettings };
}
/**
* Get selected date
*/
static getSelectedDate(): Date | null {
return CalendarConfig.selectedDate;
}
/**
* Set selected date
* Note: Does not emit events - caller is responsible for event emission
*/
static setSelectedDate(date: Date): void {
CalendarConfig.selectedDate = date;
}
/**
* Get work week presets
*/
private static getWorkWeekPresets(): { [key: string]: WorkWeekSettings } {
return {
'standard': {
id: 'standard',
workDays: [1,2,3,4,5], // Monday-Friday (ISO)
totalDays: 5,
firstWorkDay: 1
},
'compressed': {
id: 'compressed',
workDays: [1,2,3,4], // Monday-Thursday (ISO)
totalDays: 4,
firstWorkDay: 1
},
'midweek': {
id: 'midweek',
workDays: [3,4,5], // Wednesday-Friday (ISO)
totalDays: 3,
firstWorkDay: 3
},
'weekend': {
id: 'weekend',
workDays: [6,7], // Saturday-Sunday (ISO)
totalDays: 2,
firstWorkDay: 6
},
'fullweek': {
id: 'fullweek',
workDays: [1,2,3,4,5,6,7], // Monday-Sunday (ISO)
totalDays: 7,
firstWorkDay: 1
}
};
}
/**
* Get current work week settings
*/
static getWorkWeekSettings(): WorkWeekSettings {
const presets = CalendarConfig.getWorkWeekPresets();
return presets[CalendarConfig.currentWorkWeek] || presets['standard'];
}
/**
* Set work week preset
* Note: Does not emit events - caller is responsible for event emission
*/
static setWorkWeek(workWeekId: string): void {
const presets = CalendarConfig.getWorkWeekPresets();
if (presets[workWeekId]) {
CalendarConfig.currentWorkWeek = workWeekId;
// Update dateViewSettings to match work week
CalendarConfig.dateViewSettings.weekDays = presets[workWeekId].totalDays;
}
}
/**
* Get current work week ID
*/
static getCurrentWorkWeek(): string {
return CalendarConfig.currentWorkWeek;
}
/**
* Get time format settings
*/
static getTimeFormatSettings(): TimeFormatConfig {
return { ...CalendarConfig.timeFormatConfig };
}
/**
* Get configured timezone
*/
static getTimezone(): string {
return CalendarConfig.timeFormatConfig.timezone;
}
/**
* Get configured locale
*/
static getLocale(): string {
return CalendarConfig.timeFormatConfig.locale;
}
/**
* Check if using 24-hour format
*/
static is24HourFormat(): boolean {
return CalendarConfig.timeFormatConfig.use24HourFormat;
}
/**
* Get current date format
*/
static getDateFormat(): 'locale' | 'technical' {
return CalendarConfig.timeFormatConfig.dateFormat;
}
/**
* Load configuration from JSON
*/
static loadFromJSON(json: string): void {
try {
const data = JSON.parse(json);
if (data.gridSettings) CalendarConfig.updateGridSettings(data.gridSettings);
if (data.dateViewSettings) CalendarConfig.dateViewSettings = { ...CalendarConfig.dateViewSettings, ...data.dateViewSettings };
if (data.timeFormatConfig) {
CalendarConfig.timeFormatConfig = { ...CalendarConfig.timeFormatConfig, ...data.timeFormatConfig };
TimeFormatter.configure(CalendarConfig.timeFormatConfig);
}
} catch (error) {
console.error('Failed to load config from JSON:', error);
}
}
// ========================================================================
// Instance method wrappers for backward compatibility
// These allow injected CalendarConfig to work with existing code
// ========================================================================
get(key: keyof ICalendarConfig) { return CalendarConfig.get(key); }
set(key: keyof ICalendarConfig, value: any) { return CalendarConfig.set(key, value); }
update(updates: Partial<ICalendarConfig>) { return CalendarConfig.update(updates); }
getAll() { return CalendarConfig.getAll(); }
get minuteHeight() { return CalendarConfig.minuteHeight; }
get totalHours() { return CalendarConfig.totalHours; }
get totalMinutes() { return CalendarConfig.totalMinutes; }
get slotsPerHour() { return CalendarConfig.slotsPerHour; }
get totalSlots() { return CalendarConfig.totalSlots; }
get slotHeight() { return CalendarConfig.slotHeight; }
isValidSnapInterval(interval: number) { return CalendarConfig.isValidSnapInterval(interval); }
getGridSettings() { return CalendarConfig.getGridSettings(); }
updateGridSettings(updates: Partial<GridSettings>) { return CalendarConfig.updateGridSettings(updates); }
getDateViewSettings() { return CalendarConfig.getDateViewSettings(); }
getSelectedDate() { return CalendarConfig.getSelectedDate(); }
setSelectedDate(date: Date) { return CalendarConfig.setSelectedDate(date); }
getWorkWeekSettings() { return CalendarConfig.getWorkWeekSettings(); }
setWorkWeek(workWeekId: string) { return CalendarConfig.setWorkWeek(workWeekId); }
getCurrentWorkWeek() { return CalendarConfig.getCurrentWorkWeek(); }
getTimeFormatSettings() { return CalendarConfig.getTimeFormatSettings(); }
getTimezone() { return CalendarConfig.getTimezone(); }
getLocale() { return CalendarConfig.getLocale(); }
is24HourFormat() { return CalendarConfig.is24HourFormat(); }
getDateFormat() { return CalendarConfig.getDateFormat(); }
}

View file

@ -1,14 +1,14 @@
// Core EventBus using pure DOM CustomEvents
import { EventLogEntry, ListenerEntry, IEventBus } from '../types/CalendarTypes';
import { IEventLogEntry, IListenerEntry, IEventBus } from '../types/CalendarTypes';
/**
* Central event dispatcher for calendar using DOM CustomEvents
* Provides logging and debugging capabilities
*/
export class EventBus implements IEventBus {
private eventLog: EventLogEntry[] = [];
private eventLog: IEventLogEntry[] = [];
private debug: boolean = false;
private listeners: Set<ListenerEntry> = new Set();
private listeners: Set<IListenerEntry> = new Set();
// Log configuration for different categories
private logConfig: { [key: string]: boolean } = {
@ -161,7 +161,7 @@ export class EventBus implements IEventBus {
/**
* Get event history
*/
getEventLog(eventType?: string): EventLogEntry[] {
getEventLog(eventType?: string): IEventLogEntry[] {
if (eventType) {
return this.eventLog.filter(e => e.type === eventType);
}