278 lines
No EOL
7.3 KiB
TypeScript
278 lines
No EOL
7.3 KiB
TypeScript
// Calendar configuration management
|
|
|
|
import { eventBus } from './EventBus';
|
|
import { EventTypes } from '../constants/EventTypes';
|
|
import { CalendarConfig as ICalendarConfig, ViewType, CalendarType } from '../types/CalendarTypes';
|
|
|
|
/**
|
|
* View-specific settings interface
|
|
*/
|
|
interface ViewSettings {
|
|
columns: number;
|
|
showAllDay: boolean;
|
|
scrollToHour: number | null;
|
|
}
|
|
|
|
/**
|
|
* Calendar configuration management
|
|
*/
|
|
export class CalendarConfig {
|
|
private config: ICalendarConfig;
|
|
private calendarType: CalendarType = 'date';
|
|
private selectedDate: Date | null = null;
|
|
|
|
constructor() {
|
|
this.config = {
|
|
// View settings
|
|
view: 'week', // 'day' | 'week' | 'month'
|
|
weekDays: 7, // 4-7 days for week view
|
|
firstDayOfWeek: 1, // 0 = Sunday, 1 = Monday
|
|
|
|
// Time settings
|
|
dayStartHour: 0, // Calendar starts at midnight (default)
|
|
dayEndHour: 24, // Calendar ends at midnight (default)
|
|
workStartHour: 8, // Work hours start
|
|
workEndHour: 17, // Work hours end
|
|
snapInterval: 15, // Minutes: 5, 10, 15, 30, 60
|
|
|
|
// Display settings
|
|
hourHeight: 60, // Pixels per hour
|
|
showCurrentTime: true,
|
|
showWorkHours: true,
|
|
fitToWidth: false, // Fit columns to calendar width (no horizontal scroll)
|
|
|
|
// 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
|
|
};
|
|
|
|
// Set computed values
|
|
this.config.minEventDuration = this.config.snapInterval;
|
|
|
|
// Load calendar type from URL parameter
|
|
this.loadCalendarType();
|
|
|
|
// Load from data attributes
|
|
this.loadFromDOM();
|
|
}
|
|
|
|
/**
|
|
* Load calendar type and date from URL parameters
|
|
*/
|
|
private loadCalendarType(): void {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const typeParam = urlParams.get('type');
|
|
const dateParam = urlParams.get('date');
|
|
|
|
// Set calendar type
|
|
if (typeParam === 'resource' || typeParam === 'date') {
|
|
this.calendarType = typeParam;
|
|
console.log(`CalendarConfig: Calendar type set to '${this.calendarType}' from URL parameter`);
|
|
} else {
|
|
this.calendarType = 'date'; // Default
|
|
console.log(`CalendarConfig: Calendar type defaulted to '${this.calendarType}'`);
|
|
}
|
|
|
|
// Set selected date
|
|
if (dateParam) {
|
|
const parsedDate = new Date(dateParam);
|
|
if (!isNaN(parsedDate.getTime())) {
|
|
this.selectedDate = parsedDate;
|
|
console.log(`CalendarConfig: Selected date set to '${this.selectedDate.toISOString()}' from URL parameter`);
|
|
} else {
|
|
console.warn(`CalendarConfig: Invalid date parameter '${dateParam}', using current date`);
|
|
this.selectedDate = new Date();
|
|
}
|
|
} else {
|
|
this.selectedDate = new Date(); // Default to today
|
|
console.log(`CalendarConfig: Selected date defaulted to today: ${this.selectedDate.toISOString()}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load configuration from DOM data attributes
|
|
*/
|
|
private loadFromDOM(): void {
|
|
const calendar = document.querySelector('swp-calendar') as HTMLElement;
|
|
if (!calendar) return;
|
|
|
|
// Read data attributes
|
|
const attrs = calendar.dataset;
|
|
|
|
if (attrs.view) this.config.view = attrs.view as ViewType;
|
|
if (attrs.weekDays) this.config.weekDays = parseInt(attrs.weekDays);
|
|
if (attrs.snapInterval) this.config.snapInterval = parseInt(attrs.snapInterval);
|
|
if (attrs.dayStartHour) this.config.dayStartHour = parseInt(attrs.dayStartHour);
|
|
if (attrs.dayEndHour) this.config.dayEndHour = parseInt(attrs.dayEndHour);
|
|
if (attrs.hourHeight) this.config.hourHeight = parseInt(attrs.hourHeight);
|
|
if (attrs.fitToWidth !== undefined) this.config.fitToWidth = attrs.fitToWidth === 'true';
|
|
}
|
|
|
|
/**
|
|
* Get a config value
|
|
*/
|
|
get<K extends keyof ICalendarConfig>(key: K): ICalendarConfig[K] {
|
|
return this.config[key];
|
|
}
|
|
|
|
/**
|
|
* Set a config value
|
|
*/
|
|
set<K extends keyof ICalendarConfig>(key: K, value: ICalendarConfig[K]): void {
|
|
const oldValue = this.config[key];
|
|
this.config[key] = value;
|
|
|
|
// Update computed values
|
|
if (key === 'snapInterval') {
|
|
this.config.minEventDuration = value as number;
|
|
}
|
|
|
|
// Emit config update event
|
|
eventBus.emit(EventTypes.CONFIG_UPDATE, {
|
|
key,
|
|
value,
|
|
oldValue
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Update multiple config values
|
|
*/
|
|
update(updates: Partial<ICalendarConfig>): void {
|
|
Object.entries(updates).forEach(([key, value]) => {
|
|
this.set(key as keyof ICalendarConfig, value);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get all config
|
|
*/
|
|
getAll(): ICalendarConfig {
|
|
return { ...this.config };
|
|
}
|
|
|
|
/**
|
|
* Calculate derived values
|
|
*/
|
|
|
|
get minuteHeight(): number {
|
|
return this.config.hourHeight / 60;
|
|
}
|
|
|
|
get totalHours(): number {
|
|
return this.config.dayEndHour - this.config.dayStartHour;
|
|
}
|
|
|
|
get totalMinutes(): number {
|
|
return this.totalHours * 60;
|
|
}
|
|
|
|
get slotsPerHour(): number {
|
|
return 60 / this.config.snapInterval;
|
|
}
|
|
|
|
get totalSlots(): number {
|
|
return this.totalHours * this.slotsPerHour;
|
|
}
|
|
|
|
get slotHeight(): number {
|
|
return this.config.hourHeight / this.slotsPerHour;
|
|
}
|
|
|
|
/**
|
|
* Validate snap interval
|
|
*/
|
|
isValidSnapInterval(interval: number): boolean {
|
|
return [5, 10, 15, 30, 60].includes(interval);
|
|
}
|
|
|
|
/**
|
|
* Get view-specific settings
|
|
*/
|
|
getViewSettings(view: ViewType = this.config.view): ViewSettings {
|
|
const settings: Record<ViewType, ViewSettings> = {
|
|
day: {
|
|
columns: 1,
|
|
showAllDay: true,
|
|
scrollToHour: 8
|
|
},
|
|
week: {
|
|
columns: this.config.weekDays,
|
|
showAllDay: true,
|
|
scrollToHour: 8
|
|
},
|
|
month: {
|
|
columns: 7,
|
|
showAllDay: false,
|
|
scrollToHour: null
|
|
}
|
|
};
|
|
|
|
return settings[view] || settings.week;
|
|
}
|
|
|
|
/**
|
|
* Get calendar type
|
|
*/
|
|
getCalendarType(): CalendarType {
|
|
return this.calendarType;
|
|
}
|
|
|
|
/**
|
|
* Set calendar type
|
|
*/
|
|
setCalendarType(type: CalendarType): void {
|
|
const oldType = this.calendarType;
|
|
this.calendarType = type;
|
|
|
|
// Emit calendar type change event
|
|
eventBus.emit(EventTypes.CALENDAR_TYPE_CHANGED, {
|
|
oldType,
|
|
newType: type
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get selected date
|
|
*/
|
|
getSelectedDate(): Date | null {
|
|
return this.selectedDate;
|
|
}
|
|
|
|
/**
|
|
* Set selected date
|
|
*/
|
|
setSelectedDate(date: Date): void {
|
|
this.selectedDate = date;
|
|
|
|
// Emit date change event
|
|
eventBus.emit(EventTypes.SELECTED_DATE_CHANGED, {
|
|
date: date
|
|
});
|
|
}
|
|
}
|
|
|
|
// Create singleton instance
|
|
export const calendarConfig = new CalendarConfig(); |