Refactors all-day event layout tracking logic
Removes redundant state tracking for all-day event layouts Shifts from maintaining internal layout state to reading directly from DOM elements Simplifies event handling and updates by using DOM as the source of truth Improves performance by reducing unnecessary state management
This commit is contained in:
parent
4cc110d9f2
commit
2656bae054
3 changed files with 83 additions and 67 deletions
|
|
@ -33,11 +33,9 @@ export class AllDayManager {
|
|||
|
||||
private layoutEngine: AllDayLayoutEngine | null = null;
|
||||
|
||||
// State tracking for differential updates
|
||||
private currentLayouts: IEventLayout[] = [];
|
||||
// State tracking for layout calculation
|
||||
private currentAllDayEvents: ICalendarEvent[] = [];
|
||||
private currentWeekDates: IColumnBounds[] = [];
|
||||
private newLayouts: IEventLayout[] = [];
|
||||
|
||||
// Expand/collapse state
|
||||
private isExpanded: boolean = false;
|
||||
|
|
@ -128,23 +126,12 @@ export class AllDayManager {
|
|||
if (dragEndPayload.target === 'swp-day-column' && dragEndPayload.originalElement?.hasAttribute('data-allday')) {
|
||||
const eventId = dragEndPayload.originalElement.dataset.eventId;
|
||||
|
||||
console.log('🔄 AllDayManager: All-day → timed conversion', {
|
||||
eventId,
|
||||
currentLayoutsCount: this.currentLayouts.length,
|
||||
layoutsBeforeFilter: this.currentLayouts.map(l => l.calenderEvent.id)
|
||||
});
|
||||
console.log('🔄 AllDayManager: All-day → timed conversion', { eventId });
|
||||
|
||||
// Remove event from currentLayouts since it's now a timed event
|
||||
this.currentLayouts = this.currentLayouts.filter(
|
||||
layout => layout.calenderEvent.id !== eventId
|
||||
);
|
||||
// No need to filter currentLayouts - DOM is source of truth!
|
||||
// The element is already removed from all-day container by DragDropManager
|
||||
|
||||
console.log('📊 AllDayManager: After filter', {
|
||||
currentLayoutsCount: this.currentLayouts.length,
|
||||
layoutsAfterFilter: this.currentLayouts.map(l => l.calenderEvent.id)
|
||||
});
|
||||
|
||||
// Recalculate and animate header height
|
||||
// Recalculate and animate header height based on remaining DOM elements
|
||||
this.checkAndAnimateAllDayHeight();
|
||||
}
|
||||
});
|
||||
|
|
@ -171,9 +158,9 @@ export class AllDayManager {
|
|||
// Filter for all-day events
|
||||
const allDayEvents = events.filter(event => event.allDay);
|
||||
|
||||
this.currentLayouts = this.calculateAllDayEventsLayout(allDayEvents, headerReadyEventPayload.headerElements)
|
||||
const layouts = this.calculateAllDayEventsLayout(allDayEvents, headerReadyEventPayload.headerElements);
|
||||
|
||||
this.allDayEventRenderer.renderAllDayEventsForPeriod(this.currentLayouts);
|
||||
this.allDayEventRenderer.renderAllDayEventsForPeriod(layouts);
|
||||
this.checkAndAnimateAllDayHeight();
|
||||
});
|
||||
|
||||
|
|
@ -194,6 +181,65 @@ export class AllDayManager {
|
|||
return document.querySelector('swp-header-spacer');
|
||||
}
|
||||
|
||||
/**
|
||||
* Read current max row from DOM elements
|
||||
*/
|
||||
private getMaxRowFromDOM(): number {
|
||||
const container = this.getAllDayContainer();
|
||||
if (!container) return 0;
|
||||
|
||||
let maxRow = 0;
|
||||
const allDayEvents = container.querySelectorAll('swp-allday-event:not(.max-event-indicator)');
|
||||
|
||||
allDayEvents.forEach((element: Element) => {
|
||||
const htmlElement = element as HTMLElement;
|
||||
const row = parseInt(htmlElement.style.gridRow) || 1;
|
||||
maxRow = Math.max(maxRow, row);
|
||||
});
|
||||
|
||||
return maxRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current gridArea for an event from DOM
|
||||
*/
|
||||
private getGridAreaFromDOM(eventId: string): string | null {
|
||||
const container = this.getAllDayContainer();
|
||||
if (!container) return null;
|
||||
|
||||
const element = container.querySelector(`[data-event-id="${eventId}"]`) as HTMLElement;
|
||||
return element?.style.gridArea || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count events in a specific column by reading DOM
|
||||
*/
|
||||
private countEventsInColumnFromDOM(columnIndex: number): number {
|
||||
const container = this.getAllDayContainer();
|
||||
if (!container) return 0;
|
||||
|
||||
let count = 0;
|
||||
const allDayEvents = container.querySelectorAll('swp-allday-event:not(.max-event-indicator)');
|
||||
|
||||
allDayEvents.forEach((element: Element) => {
|
||||
const htmlElement = element as HTMLElement;
|
||||
const gridColumn = htmlElement.style.gridColumn;
|
||||
|
||||
// Parse "1 / 3" format
|
||||
const match = gridColumn.match(/(\d+)\s*\/\s*(\d+)/);
|
||||
if (match) {
|
||||
const startCol = parseInt(match[1]);
|
||||
const endCol = parseInt(match[2]) - 1; // End is exclusive in CSS
|
||||
|
||||
if (startCol <= columnIndex && endCol >= columnIndex) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate all-day height based on number of rows
|
||||
*/
|
||||
|
|
@ -221,36 +267,14 @@ export class AllDayManager {
|
|||
|
||||
/**
|
||||
* Check current all-day events and animate to correct height
|
||||
* Reads max row directly from DOM elements
|
||||
*/
|
||||
public checkAndAnimateAllDayHeight(): void {
|
||||
console.log('📏 AllDayManager: checkAndAnimateAllDayHeight called', {
|
||||
currentLayoutsCount: this.currentLayouts.length,
|
||||
layouts: this.currentLayouts.map(l => ({
|
||||
id: l.calenderEvent.id,
|
||||
row: l.row,
|
||||
title: l.calenderEvent.title
|
||||
}))
|
||||
});
|
||||
|
||||
// Calculate required rows - 0 if no events (will collapse)
|
||||
let maxRows = 0;
|
||||
|
||||
if (this.currentLayouts.length > 0) {
|
||||
// Find the HIGHEST row number in use from currentLayouts
|
||||
let highestRow = 0;
|
||||
|
||||
this.currentLayouts.forEach((layout) => {
|
||||
highestRow = Math.max(highestRow, layout.row);
|
||||
});
|
||||
|
||||
// Max rows = highest row number (e.g. if row 3 is used, height = 3 rows)
|
||||
maxRows = highestRow;
|
||||
|
||||
}
|
||||
// Read max row directly from DOM
|
||||
const maxRows = this.getMaxRowFromDOM();
|
||||
|
||||
console.log('📊 AllDayManager: Height calculation', {
|
||||
maxRows,
|
||||
currentLayoutsLength: this.currentLayouts.length,
|
||||
isExpanded: this.isExpanded
|
||||
});
|
||||
|
||||
|
|
@ -508,17 +532,15 @@ export class AllDayManager {
|
|||
];
|
||||
|
||||
// 4. Calculate new layouts for ALL events
|
||||
this.newLayouts = this.calculateAllDayEventsLayout(tempEvents, this.currentWeekDates);
|
||||
const newLayouts = this.calculateAllDayEventsLayout(tempEvents, this.currentWeekDates);
|
||||
|
||||
// 5. Apply differential updates - only update events that changed
|
||||
let changedCount = 0;
|
||||
// 5. Apply differential updates - compare with DOM instead of currentLayouts
|
||||
let container = this.getAllDayContainer();
|
||||
this.newLayouts.forEach((layout) => {
|
||||
// Find current layout for this event
|
||||
let currentLayout = this.currentLayouts.find(old => old.calenderEvent.id === layout.calenderEvent.id);
|
||||
newLayouts.forEach((layout) => {
|
||||
// Get current gridArea from DOM
|
||||
const currentGridArea = this.getGridAreaFromDOM(layout.calenderEvent.id);
|
||||
|
||||
if (currentLayout?.gridArea !== layout.gridArea) {
|
||||
changedCount++;
|
||||
if (currentGridArea !== layout.gridArea) {
|
||||
let element = container?.querySelector(`[data-event-id="${layout.calenderEvent.id}"]`) as HTMLElement;
|
||||
if (element) {
|
||||
|
||||
|
|
@ -542,9 +564,6 @@ export class AllDayManager {
|
|||
}
|
||||
});
|
||||
|
||||
if (changedCount > 0)
|
||||
this.currentLayouts = this.newLayouts;
|
||||
|
||||
// 6. Clean up drag styles from the dropped clone
|
||||
dragEndEvent.draggedClone.classList.remove('dragging');
|
||||
dragEndEvent.draggedClone.style.zIndex = '';
|
||||
|
|
@ -625,18 +644,10 @@ export class AllDayManager {
|
|||
}
|
||||
/**
|
||||
* Count number of events in a specific column using IColumnBounds
|
||||
* Reads directly from DOM elements
|
||||
*/
|
||||
private countEventsInColumn(columnBounds: IColumnBounds): number {
|
||||
let columnIndex = columnBounds.index;
|
||||
let count = 0;
|
||||
|
||||
this.currentLayouts.forEach((layout) => {
|
||||
// Check if event spans this column
|
||||
if (layout.startColumn <= columnIndex && layout.endColumn >= columnIndex) {
|
||||
count++;
|
||||
}
|
||||
});
|
||||
return count;
|
||||
return this.countEventsInColumnFromDOM(columnBounds.index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue