421 lines
12 KiB
JavaScript
421 lines
12 KiB
JavaScript
|
|
// Calendar configuration management
|
||
|
|
import { eventBus } from './EventBus';
|
||
|
|
import { CoreEvents } from '../constants/CoreEvents';
|
||
|
|
import { TimeFormatter } 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)
|
||
|
|
get SINGLE_ROW_HEIGHT() {
|
||
|
|
return this.EVENT_HEIGHT + this.EVENT_GAP + this.CONTAINER_PADDING; // 28px
|
||
|
|
}
|
||
|
|
};
|
||
|
|
/**
|
||
|
|
* Calendar configuration management
|
||
|
|
*/
|
||
|
|
export class CalendarConfig {
|
||
|
|
constructor() {
|
||
|
|
this.calendarMode = 'date';
|
||
|
|
this.selectedDate = null;
|
||
|
|
this.currentWorkWeek = 'standard';
|
||
|
|
this.config = {
|
||
|
|
// 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
|
||
|
|
};
|
||
|
|
// Grid display settings
|
||
|
|
this.gridSettings = {
|
||
|
|
hourHeight: 60,
|
||
|
|
dayStartHour: 0,
|
||
|
|
dayEndHour: 24,
|
||
|
|
workStartHour: 8,
|
||
|
|
workEndHour: 17,
|
||
|
|
snapInterval: 15,
|
||
|
|
showCurrentTime: true,
|
||
|
|
showWorkHours: true,
|
||
|
|
fitToWidth: false,
|
||
|
|
scrollToHour: 8
|
||
|
|
};
|
||
|
|
// Date view settings
|
||
|
|
this.dateViewSettings = {
|
||
|
|
period: 'week',
|
||
|
|
weekDays: 7,
|
||
|
|
firstDayOfWeek: 1,
|
||
|
|
showAllDay: true
|
||
|
|
};
|
||
|
|
// Resource view settings
|
||
|
|
this.resourceViewSettings = {
|
||
|
|
maxResources: 10,
|
||
|
|
showAvatars: true,
|
||
|
|
avatarSize: 32,
|
||
|
|
resourceNameFormat: 'full',
|
||
|
|
showResourceDetails: true,
|
||
|
|
showAllDay: true
|
||
|
|
};
|
||
|
|
// Time format settings - default to Denmark
|
||
|
|
this.timeFormatConfig = {
|
||
|
|
timezone: 'Europe/Copenhagen',
|
||
|
|
use24HourFormat: true,
|
||
|
|
locale: 'da-DK'
|
||
|
|
};
|
||
|
|
// Set computed values
|
||
|
|
this.config.minEventDuration = this.gridSettings.snapInterval;
|
||
|
|
// Initialize TimeFormatter with default settings
|
||
|
|
TimeFormatter.configure(this.timeFormatConfig);
|
||
|
|
// Load calendar type from URL parameter
|
||
|
|
this.loadCalendarType();
|
||
|
|
// Load from data attributes
|
||
|
|
this.loadFromDOM();
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Load calendar type and date from URL parameters
|
||
|
|
*/
|
||
|
|
loadCalendarType() {
|
||
|
|
const urlParams = new URLSearchParams(window.location.search);
|
||
|
|
const typeParam = urlParams.get('type');
|
||
|
|
const dateParam = urlParams.get('date');
|
||
|
|
// Set calendar mode
|
||
|
|
if (typeParam === 'resource' || typeParam === 'date') {
|
||
|
|
this.calendarMode = typeParam;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
this.calendarMode = 'date'; // Default
|
||
|
|
}
|
||
|
|
// Set selected date
|
||
|
|
if (dateParam) {
|
||
|
|
const parsedDate = new Date(dateParam);
|
||
|
|
if (!isNaN(parsedDate.getTime())) {
|
||
|
|
this.selectedDate = parsedDate;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
this.selectedDate = new Date();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
this.selectedDate = new Date(); // Default to today
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Load configuration from DOM data attributes
|
||
|
|
*/
|
||
|
|
loadFromDOM() {
|
||
|
|
const calendar = document.querySelector('swp-calendar');
|
||
|
|
if (!calendar)
|
||
|
|
return;
|
||
|
|
// Read data attributes
|
||
|
|
const attrs = calendar.dataset;
|
||
|
|
// Update date view settings
|
||
|
|
if (attrs.view)
|
||
|
|
this.dateViewSettings.period = attrs.view;
|
||
|
|
if (attrs.weekDays)
|
||
|
|
this.dateViewSettings.weekDays = parseInt(attrs.weekDays);
|
||
|
|
// Update grid settings
|
||
|
|
if (attrs.snapInterval)
|
||
|
|
this.gridSettings.snapInterval = parseInt(attrs.snapInterval);
|
||
|
|
if (attrs.dayStartHour)
|
||
|
|
this.gridSettings.dayStartHour = parseInt(attrs.dayStartHour);
|
||
|
|
if (attrs.dayEndHour)
|
||
|
|
this.gridSettings.dayEndHour = parseInt(attrs.dayEndHour);
|
||
|
|
if (attrs.hourHeight)
|
||
|
|
this.gridSettings.hourHeight = parseInt(attrs.hourHeight);
|
||
|
|
if (attrs.fitToWidth !== undefined)
|
||
|
|
this.gridSettings.fitToWidth = attrs.fitToWidth === 'true';
|
||
|
|
// Update computed values
|
||
|
|
this.config.minEventDuration = this.gridSettings.snapInterval;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get a config value
|
||
|
|
*/
|
||
|
|
get(key) {
|
||
|
|
return this.config[key];
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Set a config value
|
||
|
|
*/
|
||
|
|
set(key, value) {
|
||
|
|
const oldValue = this.config[key];
|
||
|
|
this.config[key] = value;
|
||
|
|
// Update computed values handled in specific update methods
|
||
|
|
// Emit config update event
|
||
|
|
eventBus.emit(CoreEvents.REFRESH_REQUESTED, {
|
||
|
|
key,
|
||
|
|
value,
|
||
|
|
oldValue
|
||
|
|
});
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Update multiple config values
|
||
|
|
*/
|
||
|
|
update(updates) {
|
||
|
|
Object.entries(updates).forEach(([key, value]) => {
|
||
|
|
this.set(key, value);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get all config
|
||
|
|
*/
|
||
|
|
getAll() {
|
||
|
|
return { ...this.config };
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Calculate derived values
|
||
|
|
*/
|
||
|
|
get minuteHeight() {
|
||
|
|
return this.gridSettings.hourHeight / 60;
|
||
|
|
}
|
||
|
|
get totalHours() {
|
||
|
|
return this.gridSettings.dayEndHour - this.gridSettings.dayStartHour;
|
||
|
|
}
|
||
|
|
get totalMinutes() {
|
||
|
|
return this.totalHours * 60;
|
||
|
|
}
|
||
|
|
get slotsPerHour() {
|
||
|
|
return 60 / this.gridSettings.snapInterval;
|
||
|
|
}
|
||
|
|
get totalSlots() {
|
||
|
|
return this.totalHours * this.slotsPerHour;
|
||
|
|
}
|
||
|
|
get slotHeight() {
|
||
|
|
return this.gridSettings.hourHeight / this.slotsPerHour;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Validate snap interval
|
||
|
|
*/
|
||
|
|
isValidSnapInterval(interval) {
|
||
|
|
return [5, 10, 15, 30, 60].includes(interval);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get grid display settings
|
||
|
|
*/
|
||
|
|
getGridSettings() {
|
||
|
|
return { ...this.gridSettings };
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Update grid display settings
|
||
|
|
*/
|
||
|
|
updateGridSettings(updates) {
|
||
|
|
this.gridSettings = { ...this.gridSettings, ...updates };
|
||
|
|
// Update computed values
|
||
|
|
if (updates.snapInterval) {
|
||
|
|
this.config.minEventDuration = updates.snapInterval;
|
||
|
|
}
|
||
|
|
// Grid settings changes trigger general refresh - avoid specific event
|
||
|
|
eventBus.emit(CoreEvents.REFRESH_REQUESTED, {
|
||
|
|
key: 'gridSettings',
|
||
|
|
value: this.gridSettings
|
||
|
|
});
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get date view settings
|
||
|
|
*/
|
||
|
|
getDateViewSettings() {
|
||
|
|
return { ...this.dateViewSettings };
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Update date view settings
|
||
|
|
*/
|
||
|
|
updateDateViewSettings(updates) {
|
||
|
|
this.dateViewSettings = { ...this.dateViewSettings, ...updates };
|
||
|
|
// Date view settings changes trigger general refresh - avoid specific event
|
||
|
|
eventBus.emit(CoreEvents.REFRESH_REQUESTED, {
|
||
|
|
key: 'dateViewSettings',
|
||
|
|
value: this.dateViewSettings
|
||
|
|
});
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get resource view settings
|
||
|
|
*/
|
||
|
|
getResourceViewSettings() {
|
||
|
|
return { ...this.resourceViewSettings };
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Update resource view settings
|
||
|
|
*/
|
||
|
|
updateResourceViewSettings(updates) {
|
||
|
|
this.resourceViewSettings = { ...this.resourceViewSettings, ...updates };
|
||
|
|
// Resource view settings changes trigger general refresh - avoid specific event
|
||
|
|
eventBus.emit(CoreEvents.REFRESH_REQUESTED, {
|
||
|
|
key: 'resourceViewSettings',
|
||
|
|
value: this.resourceViewSettings
|
||
|
|
});
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Check if current mode is resource-based
|
||
|
|
*/
|
||
|
|
isResourceMode() {
|
||
|
|
return this.calendarMode === 'resource';
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Check if current mode is date-based
|
||
|
|
*/
|
||
|
|
isDateMode() {
|
||
|
|
return this.calendarMode === 'date';
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get calendar mode
|
||
|
|
*/
|
||
|
|
getCalendarMode() {
|
||
|
|
return this.calendarMode;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Set calendar mode
|
||
|
|
*/
|
||
|
|
setCalendarMode(mode) {
|
||
|
|
const oldMode = this.calendarMode;
|
||
|
|
this.calendarMode = mode;
|
||
|
|
// Emit calendar mode change event
|
||
|
|
eventBus.emit(CoreEvents.VIEW_CHANGED, {
|
||
|
|
oldType: oldMode,
|
||
|
|
newType: mode
|
||
|
|
});
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get selected date
|
||
|
|
*/
|
||
|
|
getSelectedDate() {
|
||
|
|
return this.selectedDate;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Set selected date
|
||
|
|
*/
|
||
|
|
setSelectedDate(date) {
|
||
|
|
this.selectedDate = date;
|
||
|
|
// Emit date change event
|
||
|
|
eventBus.emit(CoreEvents.DATE_CHANGED, {
|
||
|
|
date: date
|
||
|
|
});
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get work week presets
|
||
|
|
*/
|
||
|
|
getWorkWeekPresets() {
|
||
|
|
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
|
||
|
|
*/
|
||
|
|
getWorkWeekSettings() {
|
||
|
|
const presets = this.getWorkWeekPresets();
|
||
|
|
return presets[this.currentWorkWeek] || presets['standard'];
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Set work week preset
|
||
|
|
*/
|
||
|
|
setWorkWeek(workWeekId) {
|
||
|
|
const presets = this.getWorkWeekPresets();
|
||
|
|
if (presets[workWeekId]) {
|
||
|
|
this.currentWorkWeek = workWeekId;
|
||
|
|
// Update dateViewSettings to match work week
|
||
|
|
this.dateViewSettings.weekDays = presets[workWeekId].totalDays;
|
||
|
|
// Emit work week change event
|
||
|
|
eventBus.emit(CoreEvents.WORKWEEK_CHANGED, {
|
||
|
|
workWeekId: workWeekId,
|
||
|
|
settings: presets[workWeekId]
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get current work week ID
|
||
|
|
*/
|
||
|
|
getCurrentWorkWeek() {
|
||
|
|
return this.currentWorkWeek;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get time format settings
|
||
|
|
*/
|
||
|
|
getTimeFormatSettings() {
|
||
|
|
return { ...this.timeFormatConfig };
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Update time format settings
|
||
|
|
*/
|
||
|
|
updateTimeFormatSettings(updates) {
|
||
|
|
this.timeFormatConfig = { ...this.timeFormatConfig, ...updates };
|
||
|
|
// Update TimeFormatter with new settings
|
||
|
|
TimeFormatter.configure(this.timeFormatConfig);
|
||
|
|
// Emit time format change event
|
||
|
|
eventBus.emit(CoreEvents.REFRESH_REQUESTED, {
|
||
|
|
key: 'timeFormatSettings',
|
||
|
|
value: this.timeFormatConfig
|
||
|
|
});
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Set timezone (convenience method)
|
||
|
|
*/
|
||
|
|
setTimezone(timezone) {
|
||
|
|
this.updateTimeFormatSettings({ timezone });
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Set 12/24 hour format (convenience method)
|
||
|
|
*/
|
||
|
|
set24HourFormat(use24Hour) {
|
||
|
|
this.updateTimeFormatSettings({ use24HourFormat: use24Hour });
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get configured timezone
|
||
|
|
*/
|
||
|
|
getTimezone() {
|
||
|
|
return this.timeFormatConfig.timezone;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Check if using 24-hour format
|
||
|
|
*/
|
||
|
|
is24HourFormat() {
|
||
|
|
return this.timeFormatConfig.use24HourFormat;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// Create singleton instance
|
||
|
|
export const calendarConfig = new CalendarConfig();
|
||
|
|
//# sourceMappingURL=CalendarConfig.js.map
|