Refactors all-day event layout calculation
Improves all-day event drag and drop by recalculating layouts and applying differential updates to minimize DOM manipulations. This change optimizes the update process by comparing current and new layouts, only updating elements with changed grid areas, leading to smoother transitions. Removes obsolete code.
This commit is contained in:
parent
6223bcd176
commit
cf463cc691
1 changed files with 33 additions and 74 deletions
|
|
@ -24,15 +24,17 @@ export class AllDayManager {
|
||||||
private layoutEngine: AllDayLayoutEngine | null = null;
|
private layoutEngine: AllDayLayoutEngine | null = null;
|
||||||
|
|
||||||
// State tracking for differential updates
|
// State tracking for differential updates
|
||||||
private currentLayouts: Map<string, string> = new Map();
|
private currentLayouts: EventLayout[] = [];
|
||||||
private currentAllDayEvents: CalendarEvent[] = [];
|
private currentAllDayEvents: CalendarEvent[] = [];
|
||||||
private currentWeekDates: string[] = [];
|
private currentWeekDates: string[] = [];
|
||||||
|
private newLayouts: EventLayout[] = [];
|
||||||
|
|
||||||
// Expand/collapse state
|
// Expand/collapse state
|
||||||
private isExpanded: boolean = false;
|
private isExpanded: boolean = false;
|
||||||
private actualRowCount: number = 0;
|
private actualRowCount: number = 0;
|
||||||
private readonly MAX_COLLAPSED_ROWS = 4; // Show 4 rows when collapsed (3 events + 1 indicator row)
|
private readonly MAX_COLLAPSED_ROWS = 4; // Show 4 rows when collapsed (3 events + 1 indicator row)
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.allDayEventRenderer = new AllDayEventRenderer();
|
this.allDayEventRenderer = new AllDayEventRenderer();
|
||||||
this.setupEventListeners();
|
this.setupEventListeners();
|
||||||
|
|
@ -168,13 +170,11 @@ export class AllDayManager {
|
||||||
*/
|
*/
|
||||||
public checkAndAnimateAllDayHeight(): void {
|
public checkAndAnimateAllDayHeight(): void {
|
||||||
const container = this.getAllDayContainer();
|
const container = this.getAllDayContainer();
|
||||||
if (!container) {
|
|
||||||
this.animateToRows(0);
|
|
||||||
this.updateChevronButton(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const allDayEvents = container.querySelectorAll('swp-event');
|
const allDayEvents = container?.querySelectorAll('swp-event');
|
||||||
|
//use currentLayouts here instead of the queryselector
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Calculate required rows - 0 if no events (will collapse)
|
// Calculate required rows - 0 if no events (will collapse)
|
||||||
let maxRows = 0;
|
let maxRows = 0;
|
||||||
|
|
@ -191,11 +191,6 @@ export class AllDayManager {
|
||||||
// Max rows = highest row number (e.g. if row 3 is used, height = 3 rows)
|
// Max rows = highest row number (e.g. if row 3 is used, height = 3 rows)
|
||||||
maxRows = highestRow;
|
maxRows = highestRow;
|
||||||
|
|
||||||
console.log('🔍 AllDayManager: Height calculation FIXED', {
|
|
||||||
totalEvents: allDayEvents.length,
|
|
||||||
highestRowFound: highestRow,
|
|
||||||
maxRows
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store actual row count
|
// Store actual row count
|
||||||
|
|
@ -285,28 +280,6 @@ export class AllDayManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Store current layouts from DOM for comparison
|
|
||||||
*/
|
|
||||||
private storeCurrentLayouts(): void {
|
|
||||||
this.currentLayouts.clear();
|
|
||||||
const container = this.getAllDayContainer();
|
|
||||||
if (!container) return;
|
|
||||||
|
|
||||||
container.querySelectorAll('swp-event').forEach(element => {
|
|
||||||
const htmlElement = element as HTMLElement;
|
|
||||||
const eventId = htmlElement.dataset.eventId;
|
|
||||||
const gridArea = htmlElement.style.gridArea;
|
|
||||||
if (eventId && gridArea) {
|
|
||||||
this.currentLayouts.set(eventId, gridArea);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('📋 AllDayManager: Stored current layouts', {
|
|
||||||
count: this.currentLayouts.size,
|
|
||||||
layouts: Array.from(this.currentLayouts.entries())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set current events and week dates (called by EventRendererManager)
|
* Set current events and week dates (called by EventRendererManager)
|
||||||
|
|
@ -332,10 +305,10 @@ export class AllDayManager {
|
||||||
this.currentWeekDates = weekDates;
|
this.currentWeekDates = weekDates;
|
||||||
|
|
||||||
// Initialize layout engine with provided week dates
|
// Initialize layout engine with provided week dates
|
||||||
this.layoutEngine = new AllDayLayoutEngine(weekDates);
|
var layoutEngine = new AllDayLayoutEngine(weekDates);
|
||||||
|
|
||||||
// Calculate layout for all events together - AllDayLayoutEngine handles CalendarEvents directly
|
// Calculate layout for all events together - AllDayLayoutEngine handles CalendarEvents directly
|
||||||
return this.layoutEngine.calculateLayout(events);
|
return layoutEngine.calculateLayout(events);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -369,11 +342,6 @@ export class AllDayManager {
|
||||||
|
|
||||||
ColumnDetectionUtils.updateColumnBoundsCache();
|
ColumnDetectionUtils.updateColumnBoundsCache();
|
||||||
|
|
||||||
console.log('✅ AllDayManager: Converted to all-day style (simple row 1)', {
|
|
||||||
eventId: payload.draggedClone.dataset.eventId,
|
|
||||||
gridColumn: payload.targetColumn,
|
|
||||||
gridRow: 1
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -432,28 +400,16 @@ export class AllDayManager {
|
||||||
dragClone.style.gridRow = '1'; // Force row 1 during drag
|
dragClone.style.gridRow = '1'; // Force row 1 during drag
|
||||||
dragClone.style.gridArea = `1 / ${targetColumn.index} / 2 / ${targetColumn.index + 1}`;
|
dragClone.style.gridArea = `1 / ${targetColumn.index} / 2 / ${targetColumn.index + 1}`;
|
||||||
|
|
||||||
console.log('🔄 AllDayManager: Updated all-day drag clone position', {
|
|
||||||
eventId: dragClone.dataset.eventId,
|
|
||||||
targetColumn,
|
|
||||||
gridRow: 1,
|
|
||||||
gridArea: dragClone.style.gridArea,
|
|
||||||
mouseX: mousePosition.x
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle drag end for all-day events - WITH DIFFERENTIAL UPDATES
|
* Handle drag end for all-day events - WITH DIFFERENTIAL UPDATES
|
||||||
*/
|
*/
|
||||||
private handleDragEnd(dragEndEvent: DragEndEventPayload): void {
|
private handleDragEnd(dragEndEvent: DragEndEventPayload): void {
|
||||||
console.log('🎯 AllDayManager: Starting drag end with differential updates', {
|
|
||||||
dragEndEvent
|
|
||||||
});
|
|
||||||
|
|
||||||
if (dragEndEvent.draggedClone == null)
|
if (dragEndEvent.draggedClone == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 1. Store current layouts BEFORE any changes
|
|
||||||
this.storeCurrentLayouts();
|
|
||||||
|
|
||||||
// 2. Normalize clone ID
|
// 2. Normalize clone ID
|
||||||
const cloneId = dragEndEvent.draggedClone?.dataset.eventId;
|
const cloneId = dragEndEvent.draggedClone?.dataset.eventId;
|
||||||
|
|
@ -484,19 +440,20 @@ export class AllDayManager {
|
||||||
const tempEvents = [...this.currentAllDayEvents, droppedEvent];
|
const tempEvents = [...this.currentAllDayEvents, droppedEvent];
|
||||||
|
|
||||||
// 4. Calculate new layouts for ALL events
|
// 4. Calculate new layouts for ALL events
|
||||||
const newLayouts = this.calculateAllDayEventsLayout(tempEvents, this.currentWeekDates);
|
this.newLayouts = this.calculateAllDayEventsLayout(tempEvents, this.currentWeekDates);
|
||||||
|
|
||||||
// 5. Apply differential updates - only update events that changed
|
// 5. Apply differential updates - only update events that changed
|
||||||
let changedCount = 0;
|
let changedCount = 0;
|
||||||
newLayouts.forEach((layout) => {
|
this.newLayouts.forEach((layout) => {
|
||||||
const oldGridArea = this.currentLayouts.get(layout.calenderEvent.id);
|
// Find current layout for this event
|
||||||
const newGridArea = layout.gridArea;
|
var currentLayout = this.currentLayouts.find(old => old.calenderEvent.id === layout.calenderEvent.id);
|
||||||
|
var currentGridArea = currentLayout?.gridArea;
|
||||||
|
var newGridArea = layout.gridArea;
|
||||||
|
|
||||||
if (oldGridArea !== newGridArea) {
|
if (currentGridArea !== newGridArea) {
|
||||||
changedCount++;
|
changedCount++;
|
||||||
const element = dragEndEvent.draggedClone; //:end document.querySelector(`[data-event-id="${layout.calenderEvent.id}"]`) as HTMLElement;
|
const element = dragEndEvent.draggedClone;
|
||||||
if (element) {
|
if (element) {
|
||||||
|
|
||||||
// Add transition class for smooth animation
|
// Add transition class for smooth animation
|
||||||
element.classList.add('transitioning');
|
element.classList.add('transitioning');
|
||||||
element.style.gridArea = newGridArea;
|
element.style.gridArea = newGridArea;
|
||||||
|
|
@ -509,6 +466,9 @@ export class AllDayManager {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (changedCount > 0)
|
||||||
|
this.currentLayouts = this.newLayouts;
|
||||||
|
|
||||||
// 6. Clean up drag styles from the dropped clone
|
// 6. Clean up drag styles from the dropped clone
|
||||||
dragEndEvent.draggedClone.classList.remove('dragging');
|
dragEndEvent.draggedClone.classList.remove('dragging');
|
||||||
dragEndEvent.draggedClone.style.zIndex = '';
|
dragEndEvent.draggedClone.style.zIndex = '';
|
||||||
|
|
@ -516,8 +476,7 @@ export class AllDayManager {
|
||||||
dragEndEvent.draggedClone.style.opacity = '';
|
dragEndEvent.draggedClone.style.opacity = '';
|
||||||
|
|
||||||
// 7. Restore original element opacity
|
// 7. Restore original element opacity
|
||||||
dragEndEvent.originalElement.remove();
|
dragEndEvent.originalElement.remove(); //TODO: this should be an event that only fade and remove if confirmed dragdrop
|
||||||
//originalElement.style.opacity = '';
|
|
||||||
|
|
||||||
// 8. Check if height adjustment is needed
|
// 8. Check if height adjustment is needed
|
||||||
this.checkAndAnimateAllDayHeight();
|
this.checkAndAnimateAllDayHeight();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue