Some ignored filles was missing

This commit is contained in:
Janus C. H. Knudsen 2026-02-03 00:02:25 +01:00
parent 7db22245e2
commit fd5ab6bc0d
268 changed files with 31970 additions and 4 deletions

View file

@ -0,0 +1,45 @@
/**
* AllDayCollapseService - Manages collapse/expand UI for all-day events
*
* STATELESS SERVICE - Reads expanded state from DOM via AllDayDomReader
* - No persistent state
* - Reads expanded state from DOM CSS class
* - Updates chevron button and overflow indicators
* - Controls event visibility based on row number
*/
import { AllDayHeightService } from './AllDayHeightService';
export declare class AllDayCollapseService {
private heightService;
constructor(heightService: AllDayHeightService);
/**
* Toggle between expanded and collapsed state
* Reads current state from DOM, toggles it, and updates UI
*/
toggleExpanded(): void;
/**
* Update all UI elements based on current DOM state
*/
private updateUI;
/**
* Update event visibility based on expanded state
*/
private updateEventVisibility;
/**
* Update chevron button visibility and state
*/
private updateChevronButton;
/**
* Update overflow indicators for collapsed state
* Shows "+X more" indicators in columns with overflow
*/
private updateOverflowIndicators;
/**
* Clear all overflow indicators
*/
private clearOverflowIndicators;
/**
* Initialize collapse/expand UI based on current DOM state
* Called after events are rendered
*/
initializeUI(): void;
}

View file

@ -0,0 +1,168 @@
/**
* AllDayCollapseService - Manages collapse/expand UI for all-day events
*
* STATELESS SERVICE - Reads expanded state from DOM via AllDayDomReader
* - No persistent state
* - Reads expanded state from DOM CSS class
* - Updates chevron button and overflow indicators
* - Controls event visibility based on row number
*/
import { ALL_DAY_CONSTANTS } from '../../configurations/CalendarConfig';
import { ColumnDetectionUtils } from '../../utils/ColumnDetectionUtils';
import { AllDayDomReader } from './AllDayDomReader';
export class AllDayCollapseService {
constructor(heightService) {
this.heightService = heightService;
}
/**
* Toggle between expanded and collapsed state
* Reads current state from DOM, toggles it, and updates UI
*/
toggleExpanded() {
const container = AllDayDomReader.getAllDayContainer();
if (!container)
return;
// Read current state from DOM
const isCurrentlyExpanded = container.classList.contains('expanded');
// Toggle state in DOM
if (isCurrentlyExpanded) {
container.classList.remove('expanded');
}
else {
container.classList.add('expanded');
}
// Update UI based on new state
this.updateUI();
}
/**
* Update all UI elements based on current DOM state
*/
updateUI() {
const isExpanded = AllDayDomReader.isExpanded();
const maxRows = AllDayDomReader.getMaxRowFromEvents();
// Update chevron button
if (maxRows > ALL_DAY_CONSTANTS.MAX_COLLAPSED_ROWS) {
this.updateChevronButton(true, isExpanded);
if (isExpanded) {
this.clearOverflowIndicators();
}
else {
this.updateOverflowIndicators();
}
}
else {
this.updateChevronButton(false, isExpanded);
this.clearOverflowIndicators();
}
// Update event visibility
this.updateEventVisibility(isExpanded);
// Calculate height based on expanded state
// When collapsed, show max MAX_COLLAPSED_ROWS, when expanded show all rows
const targetRows = isExpanded ? maxRows : Math.min(maxRows, ALL_DAY_CONSTANTS.MAX_COLLAPSED_ROWS);
this.heightService.animateToRows(targetRows);
}
/**
* Update event visibility based on expanded state
*/
updateEventVisibility(isExpanded) {
const events = AllDayDomReader.getEventElements();
events.forEach(event => {
const row = AllDayDomReader.getGridRow(event);
if (row > ALL_DAY_CONSTANTS.MAX_COLLAPSED_ROWS) {
if (isExpanded) {
event.classList.remove('max-event-overflow-hide');
event.classList.add('max-event-overflow-show');
}
else {
event.classList.remove('max-event-overflow-show');
event.classList.add('max-event-overflow-hide');
}
}
});
}
/**
* Update chevron button visibility and state
*/
updateChevronButton(show, isExpanded) {
const headerSpacer = AllDayDomReader.getHeaderSpacer();
if (!headerSpacer)
return;
let chevron = headerSpacer.querySelector('.allday-chevron');
if (show && !chevron) {
// Create chevron button
chevron = document.createElement('button');
chevron.className = 'allday-chevron collapsed';
chevron.innerHTML = `
<svg width="12" height="8" viewBox="0 0 12 8">
<path d="M1 1.5L6 6.5L11 1.5" stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
`;
chevron.onclick = () => this.toggleExpanded();
headerSpacer.appendChild(chevron);
}
else if (!show && chevron) {
// Remove chevron button
chevron.remove();
}
else if (chevron) {
// Update chevron state
chevron.classList.toggle('collapsed', !isExpanded);
chevron.classList.toggle('expanded', isExpanded);
}
}
/**
* Update overflow indicators for collapsed state
* Shows "+X more" indicators in columns with overflow
*/
updateOverflowIndicators() {
const container = AllDayDomReader.getAllDayContainer();
if (!container)
return;
const columns = ColumnDetectionUtils.getColumns();
columns.forEach((columnBounds) => {
const totalEventsInColumn = AllDayDomReader.countEventsInColumn(columnBounds.index);
const overflowCount = totalEventsInColumn - ALL_DAY_CONSTANTS.MAX_COLLAPSED_ROWS;
if (overflowCount > 0) {
// Check if indicator already exists
let existingIndicator = container.querySelector(`.max-event-indicator[data-column="${columnBounds.index}"]`);
if (existingIndicator) {
// Update existing indicator
existingIndicator.innerHTML = `<span>+${overflowCount + 1} more</span>`;
}
else {
// Create new overflow indicator
const overflowElement = document.createElement('swp-allday-event');
overflowElement.className = 'max-event-indicator';
overflowElement.setAttribute('data-column', columnBounds.index.toString());
overflowElement.style.gridRow = ALL_DAY_CONSTANTS.MAX_COLLAPSED_ROWS.toString();
overflowElement.style.gridColumn = columnBounds.index.toString();
overflowElement.innerHTML = `<span>+${overflowCount + 1} more</span>`;
overflowElement.onclick = (e) => {
e.stopPropagation();
this.toggleExpanded();
};
container.appendChild(overflowElement);
}
}
});
}
/**
* Clear all overflow indicators
*/
clearOverflowIndicators() {
const container = AllDayDomReader.getAllDayContainer();
if (!container)
return;
container.querySelectorAll('.max-event-indicator').forEach((element) => {
element.remove();
});
}
/**
* Initialize collapse/expand UI based on current DOM state
* Called after events are rendered
*/
initializeUI() {
this.updateUI();
}
}
//# sourceMappingURL=AllDayCollapseService.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"AllDayCollapseService.js","sourceRoot":"","sources":["../../../../src/features/all-day/AllDayCollapseService.ts"],"names":[],"mappings":"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"}

View file

@ -0,0 +1,45 @@
/**
* AllDayCoordinator - Orchestrates all-day event functionality
*
* NO STATE - Only coordinates between services
* - Listens to EventBus events
* - Delegates to specialized services
* - Manages service lifecycle
*/
import { AllDayEventRenderer } from '../../renderers/AllDayEventRenderer';
import { EventManager } from '../../managers/EventManager';
import { DateService } from '../../utils/DateService';
import { AllDayHeightService } from './AllDayHeightService';
import { AllDayCollapseService } from './AllDayCollapseService';
import { AllDayDragService } from './AllDayDragService';
/**
* AllDayCoordinator - Orchestrates all-day event functionality
* Replaces the monolithic AllDayManager with a coordinated service architecture
*/
export declare class AllDayCoordinator {
private allDayEventRenderer;
private eventManager;
private dateService;
private heightService;
private collapseService;
private dragService;
constructor(eventManager: EventManager, allDayEventRenderer: AllDayEventRenderer, dateService: DateService, heightService: AllDayHeightService, collapseService: AllDayCollapseService, dragService: AllDayDragService);
/**
* Setup event listeners and delegate to services
*/
private setupEventListeners;
/**
* Calculate layout for ALL all-day events using AllDayLayoutEngine
*/
private calculateAllDayEventsLayout;
/**
* Recalculate layouts and update height
* Called after events are added/removed/moved in all-day area
* Uses AllDayLayoutEngine to optimally reorganize all events
*/
private recalculateLayoutsAndHeight;
/**
* Public API for collapsing all-day row
*/
collapseAllDayRow(): void;
}

View file

@ -0,0 +1,168 @@
/**
* AllDayCoordinator - Orchestrates all-day event functionality
*
* NO STATE - Only coordinates between services
* - Listens to EventBus events
* - Delegates to specialized services
* - Manages service lifecycle
*/
import { eventBus } from '../../core/EventBus';
import { ALL_DAY_CONSTANTS } from '../../configurations/CalendarConfig';
import { AllDayLayoutEngine } from '../../utils/AllDayLayoutEngine';
import { CoreEvents } from '../../constants/CoreEvents';
import { AllDayDomReader } from './AllDayDomReader';
import { ColumnDetectionUtils } from '../../utils/ColumnDetectionUtils';
/**
* AllDayCoordinator - Orchestrates all-day event functionality
* Replaces the monolithic AllDayManager with a coordinated service architecture
*/
export class AllDayCoordinator {
constructor(eventManager, allDayEventRenderer, dateService, heightService, collapseService, dragService) {
this.eventManager = eventManager;
this.allDayEventRenderer = allDayEventRenderer;
this.dateService = dateService;
this.heightService = heightService;
this.collapseService = collapseService;
this.dragService = dragService;
// Sync CSS variable with TypeScript constant
document.documentElement.style.setProperty('--single-row-height', `${ALL_DAY_CONSTANTS.EVENT_HEIGHT}px`);
this.setupEventListeners();
}
/**
* Setup event listeners and delegate to services
*/
setupEventListeners() {
// Timed → All-day conversion
eventBus.on('drag:mouseenter-header', (event) => {
const payload = event.detail;
if (payload.draggedClone.hasAttribute('data-allday'))
return;
console.log('🔄 AllDayCoordinator: Received drag:mouseenter-header', {
targetDate: payload.targetColumn,
originalElementId: payload.originalElement?.dataset?.eventId,
originalElementTag: payload.originalElement?.tagName
});
this.dragService.handleConvertToAllDay(payload);
// Recalculate layouts and height after timed → all-day conversion
this.recalculateLayoutsAndHeight();
});
eventBus.on('drag:mouseleave-header', (event) => {
const { originalElement } = event.detail;
console.log('🚪 AllDayCoordinator: Received drag:mouseleave-header', {
originalElementId: originalElement?.dataset?.eventId
});
});
// All-day drag start
eventBus.on('drag:start', (event) => {
const payload = event.detail;
if (!payload.draggedClone?.hasAttribute('data-allday'))
return;
this.allDayEventRenderer.handleDragStart(payload);
});
// All-day column change
eventBus.on('drag:column-change', (event) => {
const payload = event.detail;
if (!payload.draggedClone?.hasAttribute('data-allday'))
return;
this.dragService.handleColumnChange(payload);
});
// Drag end
eventBus.on('drag:end', (event) => {
const dragEndPayload = event.detail;
console.log('🎯 AllDayCoordinator: drag:end received', {
target: dragEndPayload.target,
originalElementTag: dragEndPayload.originalElement?.tagName,
hasAllDayAttribute: dragEndPayload.originalElement?.hasAttribute('data-allday'),
eventId: dragEndPayload.originalElement?.dataset.eventId
});
// Handle all-day → all-day drops (within header)
if (dragEndPayload.target === 'swp-day-header') {
console.log('✅ AllDayCoordinator: Handling all-day → all-day drop');
this.dragService.handleDragEnd(dragEndPayload);
// Recalculate layouts and height after all-day → all-day repositioning
this.recalculateLayoutsAndHeight();
return;
}
// Handle all-day → timed conversion (dropped in column)
if (dragEndPayload.target === 'swp-day-column' &&
dragEndPayload.originalElement?.hasAttribute('data-allday')) {
const eventId = dragEndPayload.originalElement.dataset.eventId;
console.log('🔄 AllDayCoordinator: All-day → timed conversion', {
eventId
});
// Remove event element from DOM
const container = AllDayDomReader.getAllDayContainer();
const eventElement = container?.querySelector(`[data-event-id="${eventId}"]`);
if (eventElement) {
eventElement.remove();
}
// Recalculate layouts and height after event removal
this.recalculateLayoutsAndHeight();
}
});
// Drag cancelled
eventBus.on('drag:cancelled', (event) => {
const { draggedElement, reason } = event.detail;
console.log('🚫 AllDayCoordinator: Drag cancelled', {
eventId: draggedElement?.dataset?.eventId,
reason
});
});
// Header ready - render all-day events
eventBus.on('header:ready', async (event) => {
const headerReadyEventPayload = event.detail;
const startDate = new Date(headerReadyEventPayload.headerElements.at(0).date);
const endDate = new Date(headerReadyEventPayload.headerElements.at(-1).date);
const events = await this.eventManager.getEventsForPeriod(startDate, endDate);
// Filter for all-day events
const allDayEvents = events.filter(event => event.allDay);
// Calculate layouts
const layouts = this.calculateAllDayEventsLayout(allDayEvents, headerReadyEventPayload.headerElements);
// Render events
this.allDayEventRenderer.renderAllDayEventsForPeriod(layouts);
// Initialize collapse/expand UI and calculate height
this.collapseService.initializeUI();
});
// View changed
eventBus.on(CoreEvents.VIEW_CHANGED, (event) => {
this.allDayEventRenderer.handleViewChanged(event);
});
}
/**
* Calculate layout for ALL all-day events using AllDayLayoutEngine
*/
calculateAllDayEventsLayout(events, dayHeaders) {
// Initialize layout engine with provided week dates
const layoutEngine = new AllDayLayoutEngine(dayHeaders.map(column => column.date));
// Calculate layout for all events together
return layoutEngine.calculateLayout(events);
}
/**
* Recalculate layouts and update height
* Called after events are added/removed/moved in all-day area
* Uses AllDayLayoutEngine to optimally reorganize all events
*/
recalculateLayoutsAndHeight() {
// 1. Read current events from DOM
const events = AllDayDomReader.getEventsAsData();
const weekDates = ColumnDetectionUtils.getColumns();
// 2. Calculate optimal layouts using greedy algorithm
const layouts = this.calculateAllDayEventsLayout(events, weekDates);
// 3. Apply layouts to DOM
this.dragService.applyLayoutUpdates(layouts);
// 4. Calculate max row from NEW layouts
const maxRow = layouts.length > 0 ? Math.max(...layouts.map(l => l.row)) : 0;
// 5. Check if collapsed state should be maintained
const isExpanded = AllDayDomReader.isExpanded();
const targetRows = isExpanded ? maxRow : Math.min(maxRow, ALL_DAY_CONSTANTS.MAX_COLLAPSED_ROWS);
// 6. Animate height to target
this.heightService.animateToRows(targetRows);
}
/**
* Public API for collapsing all-day row
*/
collapseAllDayRow() {
this.heightService.collapseAllDayRow();
}
}
//# sourceMappingURL=AllDayCoordinator.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,74 @@
import { ICalendarEvent } from '../../types/CalendarTypes';
/**
* 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 declare class AllDayDomReader {
/**
* Get the all-day events container element
*/
static getAllDayContainer(): HTMLElement | null;
/**
* Get the calendar header element
*/
static getCalendarHeader(): HTMLElement | null;
/**
* Get the header spacer element
*/
static getHeaderSpacer(): HTMLElement | null;
/**
* Get all all-day event elements (excluding overflow indicators)
* Returns raw HTMLElements for DOM manipulation
*/
static getEventElements(): HTMLElement[];
/**
* Get all-day events as ICalendarEvent objects
* Returns parsed data for business logic
*/
static getEventsAsData(): ICalendarEvent[];
/**
* Get grid row from element using computed style
* Always uses computed style for consistency
*/
static getGridRow(element: HTMLElement): number;
/**
* Get grid column range from element using computed style
*/
static getGridColumnRange(element: HTMLElement): {
start: number;
end: number;
};
/**
* Get grid area from element using computed style
*/
static getGridArea(element: HTMLElement): string;
/**
* Calculate max row number from all events
* Uses computed styles for accurate reading
*/
static getMaxRowFromEvents(): number;
/**
* Check if all-day container is expanded
*/
static isExpanded(): boolean;
/**
* Get current all-day height from CSS variable
*/
static getCurrentHeight(): number;
/**
* Count events in specific column
*/
static countEventsInColumn(columnIndex: number): number;
/**
* Get current layouts from DOM elements
* Returns map of eventId layout info for comparison
*/
static getCurrentLayouts(): Map<string, {
gridArea: string;
}>;
}

View file

@ -0,0 +1,175 @@
/**
* 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

View file

@ -0,0 +1 @@
{"version":3,"file":"AllDayDomReader.js","sourceRoot":"","sources":["../../../../src/features/all-day/AllDayDomReader.ts"],"names":[],"mappings":"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"}

View file

@ -0,0 +1,50 @@
/**
* AllDayDragService - Manages drag and drop operations for all-day events
*
* STATELESS SERVICE - Reads all data from DOM via AllDayDomReader
* - No persistent state
* - Handles timed all-day conversion
* - Handles all-day all-day repositioning
* - Handles column changes during drag
* - Calculates layouts on-demand from DOM
*/
import { IEventLayout } from '../../utils/AllDayLayoutEngine';
import { IDragMouseEnterHeaderEventPayload, IDragColumnChangeEventPayload, IDragEndEventPayload } from '../../types/EventTypes';
import { EventManager } from '../../managers/EventManager';
import { AllDayEventRenderer } from '../../renderers/AllDayEventRenderer';
import { DateService } from '../../utils/DateService';
export declare class AllDayDragService {
private eventManager;
private allDayEventRenderer;
private dateService;
constructor(eventManager: EventManager, allDayEventRenderer: AllDayEventRenderer, dateService: DateService);
/**
* Handle conversion from timed event to all-day event
* Called when dragging a timed event into the header
*/
handleConvertToAllDay(payload: IDragMouseEnterHeaderEventPayload): void;
/**
* Handle column change during drag of all-day event
* Updates grid position while maintaining event span
*/
handleColumnChange(payload: IDragColumnChangeEventPayload): void;
/**
* Handle drag end for all-day all-day drops
* Recalculates layouts and updates event positions
*/
handleDragEnd(dragEndEvent: IDragEndEventPayload): Promise<void>;
/**
* Calculate layouts for events using AllDayLayoutEngine
*/
private calculateLayouts;
/**
* Apply layout updates to DOM elements
* Only updates elements that have changed position
* Public so AllDayCoordinator can use it for full recalculation
*/
applyLayoutUpdates(newLayouts: IEventLayout[]): void;
/**
* Fade out and remove element
*/
private fadeOutAndRemove;
}

View file

@ -0,0 +1,183 @@
/**
* AllDayDragService - Manages drag and drop operations for all-day events
*
* STATELESS SERVICE - Reads all data from DOM via AllDayDomReader
* - No persistent state
* - Handles timed all-day conversion
* - Handles all-day all-day repositioning
* - Handles column changes during drag
* - Calculates layouts on-demand from DOM
*/
import { SwpAllDayEventElement } from '../../elements/SwpEventElement';
import { AllDayLayoutEngine } from '../../utils/AllDayLayoutEngine';
import { ColumnDetectionUtils } from '../../utils/ColumnDetectionUtils';
import { ALL_DAY_CONSTANTS } from '../../configurations/CalendarConfig';
import { AllDayDomReader } from './AllDayDomReader';
export class AllDayDragService {
constructor(eventManager, allDayEventRenderer, dateService) {
this.eventManager = eventManager;
this.allDayEventRenderer = allDayEventRenderer;
this.dateService = dateService;
}
/**
* Handle conversion from timed event to all-day event
* Called when dragging a timed event into the header
*/
handleConvertToAllDay(payload) {
const allDayContainer = AllDayDomReader.getAllDayContainer();
if (!allDayContainer)
return;
// Create SwpAllDayEventElement from ICalendarEvent
const allDayElement = SwpAllDayEventElement.fromCalendarEvent(payload.calendarEvent);
// Apply grid positioning
allDayElement.style.gridRow = '1';
allDayElement.style.gridColumn = payload.targetColumn.index.toString();
// Remove old swp-event clone
payload.draggedClone.remove();
// Call delegate to update DragDropManager's draggedClone reference
payload.replaceClone(allDayElement);
// Append to container
allDayContainer.appendChild(allDayElement);
ColumnDetectionUtils.updateColumnBoundsCache();
}
/**
* Handle column change during drag of all-day event
* Updates grid position while maintaining event span
*/
handleColumnChange(payload) {
const allDayContainer = AllDayDomReader.getAllDayContainer();
if (!allDayContainer)
return;
const targetColumn = ColumnDetectionUtils.getColumnBounds(payload.mousePosition);
if (!targetColumn || !payload.draggedClone)
return;
// Calculate event span from original grid positioning
const { start: gridColumnStart, end: gridColumnEnd } = AllDayDomReader.getGridColumnRange(payload.draggedClone);
const span = gridColumnEnd - gridColumnStart;
// Update clone position maintaining the span
const newStartColumn = targetColumn.index;
const newEndColumn = newStartColumn + span;
payload.draggedClone.style.gridColumn = `${newStartColumn} / ${newEndColumn}`;
}
/**
* Handle drag end for all-day all-day drops
* Recalculates layouts and updates event positions
*/
async handleDragEnd(dragEndEvent) {
if (!dragEndEvent.draggedClone)
return;
// Normalize clone ID
dragEndEvent.draggedClone.dataset.eventId = dragEndEvent.draggedClone.dataset.eventId?.replace('clone-', '');
dragEndEvent.draggedClone.style.pointerEvents = ''; // Re-enable pointer events
dragEndEvent.originalElement.dataset.eventId += '_';
const eventId = dragEndEvent.draggedClone.dataset.eventId;
const eventDate = dragEndEvent.finalPosition.column?.date;
const eventType = dragEndEvent.draggedClone.dataset.type;
if (!eventDate || !eventId || !eventType)
return;
// Get original dates to preserve time
const originalStartDate = new Date(dragEndEvent.draggedClone.dataset.start);
const originalEndDate = new Date(dragEndEvent.draggedClone.dataset.end);
// Calculate actual duration in milliseconds (preserves hours/minutes/seconds)
const durationMs = originalEndDate.getTime() - originalStartDate.getTime();
// Create new start date with the new day but preserve original time
const newStartDate = new Date(eventDate);
newStartDate.setHours(originalStartDate.getHours(), originalStartDate.getMinutes(), originalStartDate.getSeconds(), originalStartDate.getMilliseconds());
// Create new end date by adding duration in milliseconds
const newEndDate = new Date(newStartDate.getTime() + durationMs);
// Update data attributes with new dates (convert to UTC)
dragEndEvent.draggedClone.dataset.start = this.dateService.toUTC(newStartDate);
dragEndEvent.draggedClone.dataset.end = this.dateService.toUTC(newEndDate);
const droppedEvent = {
id: eventId,
title: dragEndEvent.draggedClone.dataset.title || '',
start: newStartDate,
end: newEndDate,
type: eventType,
allDay: true,
syncStatus: 'synced'
};
// Get all events from DOM and recalculate layouts
const allEventsFromDOM = AllDayDomReader.getEventsAsData();
const weekDates = ColumnDetectionUtils.getColumns();
// Replace old event with dropped event
const updatedEvents = [
...allEventsFromDOM.filter(event => event.id !== eventId),
droppedEvent
];
// Calculate new layouts for ALL events
const newLayouts = this.calculateLayouts(updatedEvents, weekDates);
// Apply layout updates to DOM
this.applyLayoutUpdates(newLayouts);
// Clean up drag styles from the dropped clone
dragEndEvent.draggedClone.classList.remove('dragging');
dragEndEvent.draggedClone.style.zIndex = '';
dragEndEvent.draggedClone.style.cursor = '';
dragEndEvent.draggedClone.style.opacity = '';
// Apply highlight class to show the dropped event with highlight color
dragEndEvent.draggedClone.classList.add('highlight');
// Update event in repository to mark as allDay=true
await this.eventManager.updateEvent(eventId, {
start: newStartDate,
end: newEndDate,
allDay: true
});
this.fadeOutAndRemove(dragEndEvent.originalElement);
}
/**
* Calculate layouts for events using AllDayLayoutEngine
*/
calculateLayouts(events, weekDates) {
const layoutEngine = new AllDayLayoutEngine(weekDates.map(column => column.date));
return layoutEngine.calculateLayout(events);
}
/**
* Apply layout updates to DOM elements
* Only updates elements that have changed position
* Public so AllDayCoordinator can use it for full recalculation
*/
applyLayoutUpdates(newLayouts) {
const container = AllDayDomReader.getAllDayContainer();
if (!container)
return;
// Read current layouts from DOM
const currentLayoutsMap = AllDayDomReader.getCurrentLayouts();
newLayouts.forEach((layout) => {
const currentLayout = currentLayoutsMap.get(layout.calenderEvent.id);
// Only update if layout changed
if (currentLayout?.gridArea !== layout.gridArea) {
const element = container.querySelector(`[data-event-id="${layout.calenderEvent.id}"]`);
if (element) {
element.classList.add('transitioning');
element.style.gridArea = layout.gridArea;
element.style.gridRow = layout.row.toString();
element.style.gridColumn = `${layout.startColumn} / ${layout.endColumn + 1}`;
// Update overflow classes based on row
element.classList.remove('max-event-overflow-hide', 'max-event-overflow-show');
if (layout.row > ALL_DAY_CONSTANTS.MAX_COLLAPSED_ROWS) {
const isExpanded = AllDayDomReader.isExpanded();
if (isExpanded) {
element.classList.add('max-event-overflow-show');
}
else {
element.classList.add('max-event-overflow-hide');
}
}
// Remove transition class after animation
setTimeout(() => element.classList.remove('transitioning'), 200);
}
}
});
}
/**
* Fade out and remove element
*/
fadeOutAndRemove(element) {
element.style.transition = 'opacity 0.3s ease-out';
element.style.opacity = '0';
setTimeout(() => {
element.remove();
}, 300);
}
}
//# sourceMappingURL=AllDayDragService.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,26 @@
/**
* AllDayHeightService - Manages all-day row height calculations and animations
*
* STATELESS SERVICE - Reads all data from DOM via AllDayDomReader
* - No persistent state
* - Calculates required rows by reading DOM elements
* - Animates header height based on DOM state
*/
export declare class AllDayHeightService {
/**
* Main entry point - recalculate and animate header height based on DOM
*/
recalculateAndAnimate(): void;
/**
* Animate all-day container to specific number of rows
*/
animateToRows(targetRows: number): void;
/**
* Calculate all-day height based on number of rows
*/
private calculateAllDayHeight;
/**
* Collapse all-day row (animate to 0 rows)
*/
collapseAllDayRow(): void;
}

View file

@ -0,0 +1,85 @@
/**
* AllDayHeightService - Manages all-day row height calculations and animations
*
* STATELESS SERVICE - Reads all data from DOM via AllDayDomReader
* - No persistent state
* - Calculates required rows by reading DOM elements
* - Animates header height based on DOM state
*/
import { ALL_DAY_CONSTANTS } from '../../configurations/CalendarConfig';
import { eventBus } from '../../core/EventBus';
import { AllDayDomReader } from './AllDayDomReader';
export class AllDayHeightService {
/**
* Main entry point - recalculate and animate header height based on DOM
*/
recalculateAndAnimate() {
const requiredRows = AllDayDomReader.getMaxRowFromEvents();
this.animateToRows(requiredRows);
}
/**
* Animate all-day container to specific number of rows
*/
animateToRows(targetRows) {
const { targetHeight, currentHeight, heightDifference } = this.calculateAllDayHeight(targetRows);
if (targetHeight === currentHeight)
return; // No animation needed
console.log(`🎬 All-day height animation: ${currentHeight}px → ${targetHeight}px (${Math.ceil(currentHeight / ALL_DAY_CONSTANTS.SINGLE_ROW_HEIGHT)}${targetRows} rows)`);
// Get elements
const calendarHeader = AllDayDomReader.getCalendarHeader();
const headerSpacer = AllDayDomReader.getHeaderSpacer();
const allDayContainer = AllDayDomReader.getAllDayContainer();
if (!calendarHeader || !allDayContainer)
return;
// Get current parent height for animation
const currentParentHeight = parseFloat(getComputedStyle(calendarHeader).height);
const targetParentHeight = currentParentHeight + heightDifference;
const animations = [
calendarHeader.animate([
{ height: `${currentParentHeight}px` },
{ height: `${targetParentHeight}px` }
], {
duration: 150,
easing: 'ease-out',
fill: 'forwards'
})
];
// Add spacer animation if spacer exists
if (headerSpacer) {
const root = document.documentElement;
const headerHeightStr = root.style.getPropertyValue('--header-height');
const headerHeight = parseInt(headerHeightStr);
const currentSpacerHeight = headerHeight + currentHeight;
const targetSpacerHeight = headerHeight + targetHeight;
animations.push(headerSpacer.animate([
{ height: `${currentSpacerHeight}px` },
{ height: `${targetSpacerHeight}px` }
], {
duration: 150,
easing: 'ease-out'
}));
}
// Update CSS variable after animation
Promise.all(animations.map(anim => anim.finished)).then(() => {
const root = document.documentElement;
root.style.setProperty('--all-day-row-height', `${targetHeight}px`);
eventBus.emit('header:height-changed');
});
}
/**
* Calculate all-day height based on number of rows
*/
calculateAllDayHeight(targetRows) {
const targetHeight = targetRows * ALL_DAY_CONSTANTS.SINGLE_ROW_HEIGHT;
const currentHeight = AllDayDomReader.getCurrentHeight();
const heightDifference = targetHeight - currentHeight;
return { targetHeight, currentHeight, heightDifference };
}
/**
* Collapse all-day row (animate to 0 rows)
*/
collapseAllDayRow() {
this.animateToRows(0);
}
}
//# sourceMappingURL=AllDayHeightService.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"AllDayHeightService.js","sourceRoot":"","sources":["../../../../src/features/all-day/AllDayHeightService.ts"],"names":[],"mappings":"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"}

View file

@ -0,0 +1,9 @@
/**
* All-day feature barrel export
*
* Exports all public APIs from the all-day feature
*/
export { AllDayCoordinator } from './AllDayCoordinator';
export { AllDayHeightService } from './AllDayHeightService';
export { AllDayCollapseService } from './AllDayCollapseService';
export { AllDayDragService } from './AllDayDragService';

View file

@ -0,0 +1,10 @@
/**
* All-day feature barrel export
*
* Exports all public APIs from the all-day feature
*/
export { AllDayCoordinator } from './AllDayCoordinator';
export { AllDayHeightService } from './AllDayHeightService';
export { AllDayCollapseService } from './AllDayCollapseService';
export { AllDayDragService } from './AllDayDragService';
//# sourceMappingURL=index.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/features/all-day/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}

View file

@ -0,0 +1,74 @@
import { ICalendarEvent } from '../../../types/CalendarTypes';
/**
* 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 declare class AllDayDomReader {
/**
* Get the all-day events container element
*/
static getAllDayContainer(): HTMLElement | null;
/**
* Get the calendar header element
*/
static getCalendarHeader(): HTMLElement | null;
/**
* Get the header spacer element
*/
static getHeaderSpacer(): HTMLElement | null;
/**
* Get all all-day event elements (excluding overflow indicators)
* Returns raw HTMLElements for DOM manipulation
*/
static getEventElements(): HTMLElement[];
/**
* Get all-day events as ICalendarEvent objects
* Returns parsed data for business logic
*/
static getEventsAsData(): ICalendarEvent[];
/**
* Get grid row from element using computed style
* Always uses computed style for consistency
*/
static getGridRow(element: HTMLElement): number;
/**
* Get grid column range from element using computed style
*/
static getGridColumnRange(element: HTMLElement): {
start: number;
end: number;
};
/**
* Get grid area from element using computed style
*/
static getGridArea(element: HTMLElement): string;
/**
* Calculate max row number from all events
* Uses computed styles for accurate reading
*/
static getMaxRowFromEvents(): number;
/**
* Check if all-day container is expanded
*/
static isExpanded(): boolean;
/**
* Get current all-day height from CSS variable
*/
static getCurrentHeight(): number;
/**
* Count events in specific column
*/
static countEventsInColumn(columnIndex: number): number;
/**
* Get current layouts from DOM elements
* Returns map of eventId layout info for comparison
*/
static getCurrentLayouts(): Map<string, {
gridArea: string;
}>;
}

View file

@ -0,0 +1,175 @@
/**
* 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

View file

@ -0,0 +1 @@
{"version":3,"file":"AllDayDomReader.js","sourceRoot":"","sources":["../../../../../src/features/all-day/utils/AllDayDomReader.ts"],"names":[],"mappings":"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"}