Batch update, WIP
This commit is contained in:
parent
8ec5f52872
commit
989c9bd69d
25 changed files with 68 additions and 123 deletions
|
|
@ -97,68 +97,12 @@ export class Configuration {
|
||||||
return Configuration._instance;
|
return Configuration._instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computed properties
|
|
||||||
get minuteHeight(): number {
|
|
||||||
return this.gridSettings.hourHeight / 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalHours(): number {
|
|
||||||
return this.gridSettings.dayEndHour - this.gridSettings.dayStartHour;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalMinutes(): number {
|
|
||||||
return this.totalHours * 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
get slotsPerHour(): number {
|
|
||||||
return 60 / this.gridSettings.snapInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalSlots(): number {
|
|
||||||
return this.totalHours * this.slotsPerHour;
|
|
||||||
}
|
|
||||||
|
|
||||||
get slotHeight(): number {
|
|
||||||
return this.gridSettings.hourHeight / this.slotsPerHour;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Backward compatibility getters
|
|
||||||
getGridSettings(): IGridSettings {
|
|
||||||
return this.gridSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDateViewSettings(): IDateViewSettings {
|
|
||||||
return this.dateViewSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Helper methods
|
||||||
getWorkWeekSettings(): IWorkWeekSettings {
|
getWorkWeekSettings(): IWorkWeekSettings {
|
||||||
return WORK_WEEK_PRESETS[this.currentWorkWeek] || WORK_WEEK_PRESETS['standard'];
|
return WORK_WEEK_PRESETS[this.currentWorkWeek] || WORK_WEEK_PRESETS['standard'];
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentWorkWeek(): string {
|
|
||||||
return this.currentWorkWeek;
|
|
||||||
}
|
|
||||||
|
|
||||||
getTimezone(): string {
|
|
||||||
return this.timeFormatConfig.timezone;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLocale(): string {
|
|
||||||
return this.timeFormatConfig.locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
getTimeFormatSettings(): ITimeFormatConfig {
|
|
||||||
return this.timeFormatConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
is24HourFormat(): boolean {
|
|
||||||
return this.timeFormatConfig.use24HourFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDateFormat(): 'locale' | 'technical' {
|
|
||||||
return this.timeFormatConfig.dateFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
setWorkWeek(workWeekId: string): void {
|
setWorkWeek(workWeekId: string): void {
|
||||||
if (WORK_WEEK_PRESETS[workWeekId]) {
|
if (WORK_WEEK_PRESETS[workWeekId]) {
|
||||||
this.currentWorkWeek = workWeekId;
|
this.currentWorkWeek = workWeekId;
|
||||||
|
|
@ -169,10 +113,6 @@ export class Configuration {
|
||||||
setSelectedDate(date: Date): void {
|
setSelectedDate(date: Date): void {
|
||||||
this.selectedDate = date;
|
this.selectedDate = date;
|
||||||
}
|
}
|
||||||
|
|
||||||
isValidSnapInterval(interval: number): boolean {
|
|
||||||
return [5, 10, 15, 30, 60].includes(interval);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backward compatibility alias
|
// Backward compatibility alias
|
||||||
|
|
@ -14,3 +14,12 @@ export interface IGridSettings {
|
||||||
showCurrentTime: boolean;
|
showCurrentTime: boolean;
|
||||||
showWorkHours: boolean;
|
showWorkHours: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grid settings utility functions
|
||||||
|
*/
|
||||||
|
export namespace GridSettingsUtils {
|
||||||
|
export function isValidSnapInterval(interval: number): boolean {
|
||||||
|
return [5, 10, 15, 30, 60].includes(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { ICalendarEvent } from '../types/CalendarTypes';
|
import { ICalendarEvent } from '../types/CalendarTypes';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { TimeFormatter } from '../utils/TimeFormatter';
|
import { TimeFormatter } from '../utils/TimeFormatter';
|
||||||
import { PositionUtils } from '../utils/PositionUtils';
|
import { PositionUtils } from '../utils/PositionUtils';
|
||||||
import { DateService } from '../utils/DateService';
|
import { DateService } from '../utils/DateService';
|
||||||
|
|
@ -137,7 +137,7 @@ export class SwpEventElement extends BaseSwpEventElement {
|
||||||
this.style.height = `${newHeight}px`;
|
this.style.height = `${newHeight}px`;
|
||||||
|
|
||||||
// 2. Calculate new end time based on height
|
// 2. Calculate new end time based on height
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const { hourHeight, snapInterval } = gridSettings;
|
const { hourHeight, snapInterval } = gridSettings;
|
||||||
|
|
||||||
// Get current start time
|
// Get current start time
|
||||||
|
|
@ -230,7 +230,7 @@ export class SwpEventElement extends BaseSwpEventElement {
|
||||||
* Calculate start/end minutes from Y position
|
* Calculate start/end minutes from Y position
|
||||||
*/
|
*/
|
||||||
private calculateTimesFromPosition(snappedY: number): { startMinutes: number; endMinutes: number } {
|
private calculateTimesFromPosition(snappedY: number): { startMinutes: number; endMinutes: number } {
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const { hourHeight, dayStartHour, snapInterval } = gridSettings;
|
const { hourHeight, dayStartHour, snapInterval } = gridSettings;
|
||||||
|
|
||||||
// Get original duration
|
// Get original duration
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
// Main entry point for Calendar Plantempus
|
// Main entry point for Calendar Plantempus
|
||||||
import { Container } from '@novadi/core';
|
import { Container } from '@novadi/core';
|
||||||
import { eventBus } from './core/EventBus';
|
import { eventBus } from './core/EventBus';
|
||||||
import { ConfigManager } from './configuration/ConfigManager';
|
import { ConfigManager } from './configurations/ConfigManager';
|
||||||
import { Configuration } from './configuration/CalendarConfig';
|
import { Configuration } from './configurations/CalendarConfig';
|
||||||
import { URLManager } from './utils/URLManager';
|
import { URLManager } from './utils/URLManager';
|
||||||
import { IEventBus } from './types/CalendarTypes';
|
import { IEventBus } from './types/CalendarTypes';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// All-day row height management and animations
|
// All-day row height management and animations
|
||||||
|
|
||||||
import { eventBus } from '../core/EventBus';
|
import { eventBus } from '../core/EventBus';
|
||||||
import { ALL_DAY_CONSTANTS } from '../configuration/CalendarConfig';
|
import { ALL_DAY_CONSTANTS } from '../configurations/CalendarConfig';
|
||||||
import { AllDayEventRenderer } from '../renderers/AllDayEventRenderer';
|
import { AllDayEventRenderer } from '../renderers/AllDayEventRenderer';
|
||||||
import { AllDayLayoutEngine, IEventLayout } from '../utils/AllDayLayoutEngine';
|
import { AllDayLayoutEngine, IEventLayout } from '../utils/AllDayLayoutEngine';
|
||||||
import { IColumnBounds, ColumnDetectionUtils } from '../utils/ColumnDetectionUtils';
|
import { IColumnBounds, ColumnDetectionUtils } from '../utils/ColumnDetectionUtils';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { CoreEvents } from '../constants/CoreEvents';
|
import { CoreEvents } from '../constants/CoreEvents';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { CalendarView, IEventBus } from '../types/CalendarTypes';
|
import { CalendarView, IEventBus } from '../types/CalendarTypes';
|
||||||
import { EventManager } from './EventManager';
|
import { EventManager } from './EventManager';
|
||||||
import { GridManager } from './GridManager';
|
import { GridManager } from './GridManager';
|
||||||
|
|
@ -206,7 +206,7 @@ export class CalendarManager {
|
||||||
this.eventBus.emit('workweek:header-update', {
|
this.eventBus.emit('workweek:header-update', {
|
||||||
currentDate: this.currentDate,
|
currentDate: this.currentDate,
|
||||||
currentView: this.currentView,
|
currentView: this.currentView,
|
||||||
workweek: this.config.getCurrentWorkWeek()
|
workweek: this.config.currentWorkWeek
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
import { ICalendarEvent } from '../types/CalendarTypes';
|
import { ICalendarEvent } from '../types/CalendarTypes';
|
||||||
import { EventStackManager, IEventGroup, IStackLink } from './EventStackManager';
|
import { EventStackManager, IEventGroup, IStackLink } from './EventStackManager';
|
||||||
import { PositionUtils } from '../utils/PositionUtils';
|
import { PositionUtils } from '../utils/PositionUtils';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
|
|
||||||
export interface IGridGroupLayout {
|
export interface IGridGroupLayout {
|
||||||
events: ICalendarEvent[];
|
events: ICalendarEvent[];
|
||||||
|
|
@ -59,7 +59,7 @@ export class EventLayoutCoordinator {
|
||||||
|
|
||||||
// Find events that could be in GRID with first event
|
// Find events that could be in GRID with first event
|
||||||
// Use expanding search to find chains (A→B→C where each conflicts with next)
|
// Use expanding search to find chains (A→B→C where each conflicts with next)
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const thresholdMinutes = gridSettings.gridStartThresholdMinutes;
|
const thresholdMinutes = gridSettings.gridStartThresholdMinutes;
|
||||||
|
|
||||||
// Use refactored method for expanding grid candidates
|
// Use refactored method for expanding grid candidates
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { IEventBus, ICalendarEvent } from '../types/CalendarTypes';
|
import { IEventBus, ICalendarEvent } from '../types/CalendarTypes';
|
||||||
import { CoreEvents } from '../constants/CoreEvents';
|
import { CoreEvents } from '../constants/CoreEvents';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { DateService } from '../utils/DateService';
|
import { DateService } from '../utils/DateService';
|
||||||
import { IEventRepository } from '../repositories/IEventRepository';
|
import { IEventRepository } from '../repositories/IEventRepository';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ICalendarEvent } from '../types/CalendarTypes';
|
import { ICalendarEvent } from '../types/CalendarTypes';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
|
|
||||||
export interface IStackLink {
|
export interface IStackLink {
|
||||||
prev?: string; // Event ID of previous event in stack
|
prev?: string; // Event ID of previous event in stack
|
||||||
|
|
@ -51,7 +51,7 @@ export class EventStackManager {
|
||||||
if (events.length === 0) return [];
|
if (events.length === 0) return [];
|
||||||
|
|
||||||
// Get threshold from config
|
// Get threshold from config
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const thresholdMinutes = gridSettings.gridStartThresholdMinutes;
|
const thresholdMinutes = gridSettings.gridStartThresholdMinutes;
|
||||||
|
|
||||||
// Sort events by start time
|
// Sort events by start time
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { eventBus } from '../core/EventBus';
|
import { eventBus } from '../core/EventBus';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { CoreEvents } from '../constants/CoreEvents';
|
import { CoreEvents } from '../constants/CoreEvents';
|
||||||
import { IHeaderRenderer, IHeaderRenderContext } from '../renderers/DateHeaderRenderer';
|
import { IHeaderRenderer, IHeaderRenderContext } from '../renderers/DateHeaderRenderer';
|
||||||
import { IDragMouseEnterHeaderEventPayload, IDragMouseLeaveHeaderEventPayload, IHeaderReadyEventPayload } from '../types/EventTypes';
|
import { IDragMouseEnterHeaderEventPayload, IDragMouseLeaveHeaderEventPayload, IHeaderReadyEventPayload } from '../types/EventTypes';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { eventBus } from '../core/EventBus';
|
import { eventBus } from '../core/EventBus';
|
||||||
import { CoreEvents } from '../constants/CoreEvents';
|
import { CoreEvents } from '../constants/CoreEvents';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { IResizeEndEventPayload } from '../types/EventTypes';
|
import { IResizeEndEventPayload } from '../types/EventTypes';
|
||||||
|
|
||||||
type SwpEventEl = HTMLElement & { updateHeight?: (h: number) => void };
|
type SwpEventEl = HTMLElement & { updateHeight?: (h: number) => void };
|
||||||
|
|
@ -33,7 +33,7 @@ export class ResizeHandleManager {
|
||||||
|
|
||||||
constructor(config: Configuration) {
|
constructor(config: Configuration) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
const grid = this.config.getGridSettings();
|
const grid = this.config.gridSettings;
|
||||||
this.hourHeightPx = grid.hourHeight;
|
this.hourHeightPx = grid.hourHeight;
|
||||||
this.snapMin = grid.snapInterval;
|
this.snapMin = grid.snapInterval;
|
||||||
this.minDurationMin = this.snapMin; // Use snap interval as minimum duration
|
this.minDurationMin = this.snapMin; // Use snap interval as minimum duration
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { CalendarView, IEventBus } from '../types/CalendarTypes';
|
import { CalendarView, IEventBus } from '../types/CalendarTypes';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { CoreEvents } from '../constants/CoreEvents';
|
import { CoreEvents } from '../constants/CoreEvents';
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -113,7 +113,7 @@ export class ViewManager {
|
||||||
this.updateButtonGroup(
|
this.updateButtonGroup(
|
||||||
this.getWorkweekButtons(),
|
this.getWorkweekButtons(),
|
||||||
'data-workweek',
|
'data-workweek',
|
||||||
this.config.getCurrentWorkWeek()
|
this.config.currentWorkWeek
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Work hours management for per-column scheduling
|
// Work hours management for per-column scheduling
|
||||||
|
|
||||||
import { DateService } from '../utils/DateService';
|
import { DateService } from '../utils/DateService';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { PositionUtils } from '../utils/PositionUtils';
|
import { PositionUtils } from '../utils/PositionUtils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -102,7 +102,7 @@ export class WorkHoursManager {
|
||||||
return null; // Full day will be colored via CSS background
|
return null; // Full day will be colored via CSS background
|
||||||
}
|
}
|
||||||
|
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const dayStartHour = gridSettings.dayStartHour;
|
const dayStartHour = gridSettings.dayStartHour;
|
||||||
const hourHeight = gridSettings.hourHeight;
|
const hourHeight = gridSettings.hourHeight;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Column rendering strategy interface and implementations
|
// Column rendering strategy interface and implementations
|
||||||
|
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { DateService } from '../utils/DateService';
|
import { DateService } from '../utils/DateService';
|
||||||
import { WorkHoursManager } from '../managers/WorkHoursManager';
|
import { WorkHoursManager } from '../managers/WorkHoursManager';
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ export class DateColumnRenderer implements IColumnRenderer {
|
||||||
|
|
||||||
const workWeekSettings = config.getWorkWeekSettings();
|
const workWeekSettings = config.getWorkWeekSettings();
|
||||||
const dates = this.dateService.getWorkWeekDates(currentWeek, workWeekSettings.workDays);
|
const dates = this.dateService.getWorkWeekDates(currentWeek, workWeekSettings.workDays);
|
||||||
const dateSettings = config.getDateViewSettings();
|
const dateSettings = config.dateViewSettings;
|
||||||
const daysToShow = dates.slice(0, dateSettings.weekDays);
|
const daysToShow = dates.slice(0, dateSettings.weekDays);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Header rendering strategy interface and implementations
|
// Header rendering strategy interface and implementations
|
||||||
|
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { DateService } from '../utils/DateService';
|
import { DateService } from '../utils/DateService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -33,13 +33,13 @@ export class DateHeaderRenderer implements IHeaderRenderer {
|
||||||
calendarHeader.appendChild(allDayContainer);
|
calendarHeader.appendChild(allDayContainer);
|
||||||
|
|
||||||
// Initialize date service with timezone and locale from config
|
// Initialize date service with timezone and locale from config
|
||||||
const timezone = config.getTimezone();
|
const timezone = config.timeFormatConfig.timezone;
|
||||||
const locale = config.getLocale();
|
const locale = config.timeFormatConfig.locale;
|
||||||
this.dateService = new DateService(config);
|
this.dateService = new DateService(config);
|
||||||
|
|
||||||
const workWeekSettings = config.getWorkWeekSettings();
|
const workWeekSettings = config.getWorkWeekSettings();
|
||||||
const dates = this.dateService.getWorkWeekDates(currentWeek, workWeekSettings.workDays);
|
const dates = this.dateService.getWorkWeekDates(currentWeek, workWeekSettings.workDays);
|
||||||
const weekDays = config.getDateViewSettings().weekDays;
|
const weekDays = config.dateViewSettings.weekDays;
|
||||||
const daysToShow = dates.slice(0, weekDays);
|
const daysToShow = dates.slice(0, weekDays);
|
||||||
|
|
||||||
daysToShow.forEach((date, index) => {
|
daysToShow.forEach((date, index) => {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Event rendering strategy interface and implementations
|
// Event rendering strategy interface and implementations
|
||||||
|
|
||||||
import { ICalendarEvent } from '../types/CalendarTypes';
|
import { ICalendarEvent } from '../types/CalendarTypes';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { SwpEventElement } from '../elements/SwpEventElement';
|
import { SwpEventElement } from '../elements/SwpEventElement';
|
||||||
import { PositionUtils } from '../utils/PositionUtils';
|
import { PositionUtils } from '../utils/PositionUtils';
|
||||||
import { IColumnBounds } from '../utils/ColumnDetectionUtils';
|
import { IColumnBounds } from '../utils/ColumnDetectionUtils';
|
||||||
|
|
@ -312,7 +312,7 @@ export class DateEventRenderer implements IEventRenderer {
|
||||||
// (e.g., if container starts at 07:00 and event starts at 08:15, offset = 75 min)
|
// (e.g., if container starts at 07:00 and event starts at 08:15, offset = 75 min)
|
||||||
const timeDiffMs = event.start.getTime() - containerStart.getTime();
|
const timeDiffMs = event.start.getTime() - containerStart.getTime();
|
||||||
const timeDiffMinutes = timeDiffMs / (1000 * 60);
|
const timeDiffMinutes = timeDiffMs / (1000 * 60);
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const relativeTop = timeDiffMinutes > 0 ? (timeDiffMinutes / 60) * gridSettings.hourHeight : 0;
|
const relativeTop = timeDiffMinutes > 0 ? (timeDiffMinutes / 60) * gridSettings.hourHeight : 0;
|
||||||
|
|
||||||
// Events in grid columns are positioned absolutely within their column container
|
// Events in grid columns are positioned absolutely within their column container
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { CalendarView } from '../types/CalendarTypes';
|
import { CalendarView } from '../types/CalendarTypes';
|
||||||
import { IColumnRenderer, IColumnRenderContext } from './ColumnRenderer';
|
import { IColumnRenderer, IColumnRenderContext } from './ColumnRenderer';
|
||||||
import { eventBus } from '../core/EventBus';
|
import { eventBus } from '../core/EventBus';
|
||||||
|
|
@ -179,7 +179,7 @@ export class GridRenderer {
|
||||||
private createOptimizedTimeAxis(): HTMLElement {
|
private createOptimizedTimeAxis(): HTMLElement {
|
||||||
const timeAxis = document.createElement('swp-time-axis');
|
const timeAxis = document.createElement('swp-time-axis');
|
||||||
const timeAxisContent = document.createElement('swp-time-axis-content');
|
const timeAxisContent = document.createElement('swp-time-axis-content');
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const startHour = gridSettings.dayStartHour;
|
const startHour = gridSettings.dayStartHour;
|
||||||
const endHour = gridSettings.dayEndHour;
|
const endHour = gridSettings.dayEndHour;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,13 @@ import {
|
||||||
fromZonedTime,
|
fromZonedTime,
|
||||||
formatInTimeZone
|
formatInTimeZone
|
||||||
} from 'date-fns-tz';
|
} from 'date-fns-tz';
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
|
|
||||||
export class DateService {
|
export class DateService {
|
||||||
private timezone: string;
|
private timezone: string;
|
||||||
|
|
||||||
constructor(config: Configuration) {
|
constructor(config: Configuration) {
|
||||||
this.timezone = config.getTimezone();
|
this.timezone = config.timeFormatConfig.timezone;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Configuration } from '../configuration/CalendarConfig';
|
import { Configuration } from '../configurations/CalendarConfig';
|
||||||
import { IColumnBounds } from './ColumnDetectionUtils';
|
import { IColumnBounds } from './ColumnDetectionUtils';
|
||||||
import { DateService } from './DateService';
|
import { DateService } from './DateService';
|
||||||
import { TimeFormatter } from './TimeFormatter';
|
import { TimeFormatter } from './TimeFormatter';
|
||||||
|
|
@ -22,7 +22,7 @@ export class PositionUtils {
|
||||||
* Convert minutes to pixels
|
* Convert minutes to pixels
|
||||||
*/
|
*/
|
||||||
public minutesToPixels(minutes: number): number {
|
public minutesToPixels(minutes: number): number {
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const pixelsPerHour = gridSettings.hourHeight;
|
const pixelsPerHour = gridSettings.hourHeight;
|
||||||
return (minutes / 60) * pixelsPerHour;
|
return (minutes / 60) * pixelsPerHour;
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ export class PositionUtils {
|
||||||
* Convert pixels to minutes
|
* Convert pixels to minutes
|
||||||
*/
|
*/
|
||||||
public pixelsToMinutes(pixels: number): number {
|
public pixelsToMinutes(pixels: number): number {
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const pixelsPerHour = gridSettings.hourHeight;
|
const pixelsPerHour = gridSettings.hourHeight;
|
||||||
return (pixels / pixelsPerHour) * 60;
|
return (pixels / pixelsPerHour) * 60;
|
||||||
}
|
}
|
||||||
|
|
@ -41,7 +41,7 @@ export class PositionUtils {
|
||||||
*/
|
*/
|
||||||
public timeToPixels(timeString: string): number {
|
public timeToPixels(timeString: string): number {
|
||||||
const totalMinutes = this.dateService.timeToMinutes(timeString);
|
const totalMinutes = this.dateService.timeToMinutes(timeString);
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const dayStartMinutes = gridSettings.dayStartHour * 60;
|
const dayStartMinutes = gridSettings.dayStartHour * 60;
|
||||||
const minutesFromDayStart = totalMinutes - dayStartMinutes;
|
const minutesFromDayStart = totalMinutes - dayStartMinutes;
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ export class PositionUtils {
|
||||||
*/
|
*/
|
||||||
public dateToPixels(date: Date): number {
|
public dateToPixels(date: Date): number {
|
||||||
const totalMinutes = this.dateService.getMinutesSinceMidnight(date);
|
const totalMinutes = this.dateService.getMinutesSinceMidnight(date);
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const dayStartMinutes = gridSettings.dayStartHour * 60;
|
const dayStartMinutes = gridSettings.dayStartHour * 60;
|
||||||
const minutesFromDayStart = totalMinutes - dayStartMinutes;
|
const minutesFromDayStart = totalMinutes - dayStartMinutes;
|
||||||
|
|
||||||
|
|
@ -65,7 +65,7 @@ export class PositionUtils {
|
||||||
*/
|
*/
|
||||||
public pixelsToTime(pixels: number): string {
|
public pixelsToTime(pixels: number): string {
|
||||||
const minutes = this.pixelsToMinutes(pixels);
|
const minutes = this.pixelsToMinutes(pixels);
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const dayStartMinutes = gridSettings.dayStartHour * 60;
|
const dayStartMinutes = gridSettings.dayStartHour * 60;
|
||||||
const totalMinutes = dayStartMinutes + minutes;
|
const totalMinutes = dayStartMinutes + minutes;
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ export class PositionUtils {
|
||||||
* Snap position til grid interval
|
* Snap position til grid interval
|
||||||
*/
|
*/
|
||||||
public snapToGrid(pixels: number): number {
|
public snapToGrid(pixels: number): number {
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const snapInterval = gridSettings.snapInterval;
|
const snapInterval = gridSettings.snapInterval;
|
||||||
const snapPixels = this.minutesToPixels(snapInterval);
|
const snapPixels = this.minutesToPixels(snapInterval);
|
||||||
|
|
||||||
|
|
@ -121,7 +121,7 @@ export class PositionUtils {
|
||||||
*/
|
*/
|
||||||
public snapTimeToInterval(timeString: string): string {
|
public snapTimeToInterval(timeString: string): string {
|
||||||
const totalMinutes = this.dateService.timeToMinutes(timeString);
|
const totalMinutes = this.dateService.timeToMinutes(timeString);
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const snapInterval = gridSettings.snapInterval;
|
const snapInterval = gridSettings.snapInterval;
|
||||||
|
|
||||||
const snappedMinutes = Math.round(totalMinutes / snapInterval) * snapInterval;
|
const snappedMinutes = Math.round(totalMinutes / snapInterval) * snapInterval;
|
||||||
|
|
@ -182,7 +182,7 @@ export class PositionUtils {
|
||||||
*/
|
*/
|
||||||
public isWithinWorkHours(timeString: string): boolean {
|
public isWithinWorkHours(timeString: string): boolean {
|
||||||
const [hours] = timeString.split(':').map(Number);
|
const [hours] = timeString.split(':').map(Number);
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
return hours >= gridSettings.workStartHour && hours < gridSettings.workEndHour;
|
return hours >= gridSettings.workStartHour && hours < gridSettings.workEndHour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,7 +191,7 @@ export class PositionUtils {
|
||||||
*/
|
*/
|
||||||
public isWithinDayBounds(timeString: string): boolean {
|
public isWithinDayBounds(timeString: string): boolean {
|
||||||
const [hours] = timeString.split(':').map(Number);
|
const [hours] = timeString.split(':').map(Number);
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
return hours >= gridSettings.dayStartHour && hours < gridSettings.dayEndHour;
|
return hours >= gridSettings.dayStartHour && hours < gridSettings.dayEndHour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,7 +207,7 @@ export class PositionUtils {
|
||||||
* Hent maksimum event højde i pixels (hele dagen)
|
* Hent maksimum event højde i pixels (hele dagen)
|
||||||
*/
|
*/
|
||||||
public getMaximumEventHeight(): number {
|
public getMaximumEventHeight(): number {
|
||||||
const gridSettings = this.config.getGridSettings();
|
const gridSettings = this.config.gridSettings;
|
||||||
const dayDurationHours = gridSettings.dayEndHour - gridSettings.dayStartHour;
|
const dayDurationHours = gridSettings.dayEndHour - gridSettings.dayStartHour;
|
||||||
return dayDurationHours * gridSettings.hourHeight;
|
return dayDurationHours * gridSettings.hourHeight;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,32 +9,24 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DateService } from './DateService';
|
import { DateService } from './DateService';
|
||||||
|
import { ITimeFormatConfig } from '../configurations/TimeFormatConfig';
|
||||||
export interface ITimeFormatSettings {
|
|
||||||
timezone: string;
|
|
||||||
use24HourFormat: boolean;
|
|
||||||
locale: string;
|
|
||||||
dateFormat: 'locale' | 'technical';
|
|
||||||
showSeconds: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class TimeFormatter {
|
export class TimeFormatter {
|
||||||
private static settings: ITimeFormatSettings = {
|
private static settings: ITimeFormatConfig | null = null;
|
||||||
timezone: 'Europe/Copenhagen', // Default to Denmark
|
|
||||||
use24HourFormat: true, // 24-hour format standard in Denmark
|
|
||||||
locale: 'da-DK', // Danish locale
|
|
||||||
dateFormat: 'technical', // Use technical format yyyy-mm-dd hh:mm:ss
|
|
||||||
showSeconds: false // Don't show seconds by default
|
|
||||||
};
|
|
||||||
|
|
||||||
// DateService will be initialized lazily to avoid circular dependency with CalendarConfig
|
// DateService will be initialized lazily to avoid circular dependency with CalendarConfig
|
||||||
private static dateService: DateService | null = null;
|
private static dateService: DateService | null = null;
|
||||||
|
|
||||||
private static getDateService(): DateService {
|
private static getDateService(): DateService {
|
||||||
if (!TimeFormatter.dateService) {
|
if (!TimeFormatter.dateService) {
|
||||||
|
if (!TimeFormatter.settings) {
|
||||||
|
throw new Error('TimeFormatter must be configured before use. Call TimeFormatter.configure() first.');
|
||||||
|
}
|
||||||
// Create a minimal config object for DateService
|
// Create a minimal config object for DateService
|
||||||
const config = {
|
const config = {
|
||||||
getTimezone: () => TimeFormatter.settings.timezone
|
timeFormatConfig: {
|
||||||
|
timezone: TimeFormatter.settings.timezone
|
||||||
|
}
|
||||||
};
|
};
|
||||||
TimeFormatter.dateService = new DateService(config as any);
|
TimeFormatter.dateService = new DateService(config as any);
|
||||||
}
|
}
|
||||||
|
|
@ -43,9 +35,10 @@ export class TimeFormatter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure time formatting settings
|
* Configure time formatting settings
|
||||||
|
* Must be called before using TimeFormatter
|
||||||
*/
|
*/
|
||||||
static configure(settings: Partial<ITimeFormatSettings>): void {
|
static configure(settings: ITimeFormatConfig): void {
|
||||||
TimeFormatter.settings = { ...TimeFormatter.settings, ...settings };
|
TimeFormatter.settings = settings;
|
||||||
// Reset DateService to pick up new timezone
|
// Reset DateService to pick up new timezone
|
||||||
TimeFormatter.dateService = null;
|
TimeFormatter.dateService = null;
|
||||||
}
|
}
|
||||||
|
|
@ -71,6 +64,9 @@ export class TimeFormatter {
|
||||||
* @returns Formatted time string (e.g., "09:00")
|
* @returns Formatted time string (e.g., "09:00")
|
||||||
*/
|
*/
|
||||||
private static format24Hour(date: Date): string {
|
private static format24Hour(date: Date): string {
|
||||||
|
if (!TimeFormatter.settings) {
|
||||||
|
throw new Error('TimeFormatter must be configured before use. Call TimeFormatter.configure() first.');
|
||||||
|
}
|
||||||
const localDate = TimeFormatter.convertToLocalTime(date);
|
const localDate = TimeFormatter.convertToLocalTime(date);
|
||||||
return TimeFormatter.getDateService().formatTime(localDate, TimeFormatter.settings.showSeconds);
|
return TimeFormatter.getDateService().formatTime(localDate, TimeFormatter.settings.showSeconds);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue