175 lines
5.8 KiB
JavaScript
175 lines
5.8 KiB
JavaScript
|
|
/**
|
||
|
|
* AllDayDomReader - Centralized DOM reading utilities for all-day services
|
||
|
|
*
|
||
|
|
* STATELESS UTILITY - Pure functions for reading DOM state
|
||
|
|
* - Consistent selectors across all services
|
||
|
|
* - Unified computed style approach (not inline styles)
|
||
|
|
* - Type-safe return values
|
||
|
|
* - Single source of truth for DOM queries
|
||
|
|
*/
|
||
|
|
export class AllDayDomReader {
|
||
|
|
// ============================================
|
||
|
|
// CONTAINER GETTERS
|
||
|
|
// ============================================
|
||
|
|
/**
|
||
|
|
* Get the all-day events container element
|
||
|
|
*/
|
||
|
|
static getAllDayContainer() {
|
||
|
|
return document.querySelector('swp-calendar-header swp-allday-container');
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get the calendar header element
|
||
|
|
*/
|
||
|
|
static getCalendarHeader() {
|
||
|
|
return document.querySelector('swp-calendar-header');
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get the header spacer element
|
||
|
|
*/
|
||
|
|
static getHeaderSpacer() {
|
||
|
|
return document.querySelector('swp-header-spacer');
|
||
|
|
}
|
||
|
|
// ============================================
|
||
|
|
// EVENT ELEMENT GETTERS
|
||
|
|
// ============================================
|
||
|
|
/**
|
||
|
|
* Get all all-day event elements (excluding overflow indicators)
|
||
|
|
* Returns raw HTMLElements for DOM manipulation
|
||
|
|
*/
|
||
|
|
static getEventElements() {
|
||
|
|
const container = this.getAllDayContainer();
|
||
|
|
if (!container)
|
||
|
|
return [];
|
||
|
|
return Array.from(container.querySelectorAll('swp-allday-event:not(.max-event-indicator)'));
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get all-day events as ICalendarEvent objects
|
||
|
|
* Returns parsed data for business logic
|
||
|
|
*/
|
||
|
|
static getEventsAsData() {
|
||
|
|
const elements = this.getEventElements();
|
||
|
|
return elements
|
||
|
|
.map(element => {
|
||
|
|
const eventId = element.dataset.eventId;
|
||
|
|
const startStr = element.dataset.start;
|
||
|
|
const endStr = element.dataset.end;
|
||
|
|
// Validate required fields
|
||
|
|
if (!eventId || !startStr || !endStr) {
|
||
|
|
console.warn('AllDayDomReader: Invalid event data in DOM:', element);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
const start = new Date(startStr);
|
||
|
|
const end = new Date(endStr);
|
||
|
|
if (isNaN(start.getTime()) || isNaN(end.getTime())) {
|
||
|
|
console.warn('AllDayDomReader: Invalid event dates:', { startStr, endStr });
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
id: eventId,
|
||
|
|
title: element.dataset.title || '',
|
||
|
|
start,
|
||
|
|
end,
|
||
|
|
type: element.dataset.type || 'task',
|
||
|
|
allDay: true,
|
||
|
|
syncStatus: (element.dataset.syncStatus || 'synced')
|
||
|
|
};
|
||
|
|
})
|
||
|
|
.filter((event) => event !== null);
|
||
|
|
}
|
||
|
|
// ============================================
|
||
|
|
// GRID POSITION READERS
|
||
|
|
// ============================================
|
||
|
|
/**
|
||
|
|
* Get grid row from element using computed style
|
||
|
|
* Always uses computed style for consistency
|
||
|
|
*/
|
||
|
|
static getGridRow(element) {
|
||
|
|
const computedStyle = window.getComputedStyle(element);
|
||
|
|
return parseInt(computedStyle.gridRowStart) || 0;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get grid column range from element using computed style
|
||
|
|
*/
|
||
|
|
static getGridColumnRange(element) {
|
||
|
|
const computedStyle = window.getComputedStyle(element);
|
||
|
|
return {
|
||
|
|
start: parseInt(computedStyle.gridColumnStart) || 0,
|
||
|
|
end: parseInt(computedStyle.gridColumnEnd) || 0
|
||
|
|
};
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get grid area from element using computed style
|
||
|
|
*/
|
||
|
|
static getGridArea(element) {
|
||
|
|
const computedStyle = window.getComputedStyle(element);
|
||
|
|
return computedStyle.gridArea;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Calculate max row number from all events
|
||
|
|
* Uses computed styles for accurate reading
|
||
|
|
*/
|
||
|
|
static getMaxRowFromEvents() {
|
||
|
|
const events = this.getEventElements();
|
||
|
|
if (events.length === 0)
|
||
|
|
return 0;
|
||
|
|
let maxRow = 0;
|
||
|
|
events.forEach(event => {
|
||
|
|
const row = this.getGridRow(event);
|
||
|
|
maxRow = Math.max(maxRow, row);
|
||
|
|
});
|
||
|
|
return maxRow;
|
||
|
|
}
|
||
|
|
// ============================================
|
||
|
|
// STATE READERS
|
||
|
|
// ============================================
|
||
|
|
/**
|
||
|
|
* Check if all-day container is expanded
|
||
|
|
*/
|
||
|
|
static isExpanded() {
|
||
|
|
const container = this.getAllDayContainer();
|
||
|
|
return container?.classList.contains('expanded') || false;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Get current all-day height from CSS variable
|
||
|
|
*/
|
||
|
|
static getCurrentHeight() {
|
||
|
|
const root = document.documentElement;
|
||
|
|
const heightStr = root.style.getPropertyValue('--all-day-row-height') || '0px';
|
||
|
|
return parseInt(heightStr) || 0;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Count events in specific column
|
||
|
|
*/
|
||
|
|
static countEventsInColumn(columnIndex) {
|
||
|
|
const events = this.getEventElements();
|
||
|
|
let count = 0;
|
||
|
|
events.forEach((event) => {
|
||
|
|
const { start, end } = this.getGridColumnRange(event);
|
||
|
|
if (start <= columnIndex && end > columnIndex) {
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
// ============================================
|
||
|
|
// LAYOUT READERS
|
||
|
|
// ============================================
|
||
|
|
/**
|
||
|
|
* Get current layouts from DOM elements
|
||
|
|
* Returns map of eventId → layout info for comparison
|
||
|
|
*/
|
||
|
|
static getCurrentLayouts() {
|
||
|
|
const layoutsMap = new Map();
|
||
|
|
const events = this.getEventElements();
|
||
|
|
events.forEach(event => {
|
||
|
|
const eventId = event.dataset.eventId;
|
||
|
|
if (eventId) {
|
||
|
|
layoutsMap.set(eventId, {
|
||
|
|
gridArea: this.getGridArea(event)
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
return layoutsMap;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=AllDayDomReader.js.map
|