Improves all-day event layout and drag behavior
Refactors all-day event layout calculation and rendering for improved accuracy and performance. Improves drag-and-drop behavior for all-day events, ensuring correct event placement and column detection. Addresses issues with event overflow display and provides a more responsive user experience.
This commit is contained in:
parent
6a17bba343
commit
ae3aab5dd0
5 changed files with 50 additions and 66 deletions
|
|
@ -54,7 +54,6 @@ export class AllDayManager {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.handleConvertToAllDay(payload);
|
this.handleConvertToAllDay(payload);
|
||||||
this.checkAndAnimateAllDayHeight();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
eventBus.on('drag:mouseleave-header', (event) => {
|
eventBus.on('drag:mouseleave-header', (event) => {
|
||||||
|
|
@ -64,7 +63,7 @@ export class AllDayManager {
|
||||||
originalElementId: originalElement?.dataset?.eventId
|
originalElementId: originalElement?.dataset?.eventId
|
||||||
});
|
});
|
||||||
|
|
||||||
this.checkAndAnimateAllDayHeight();
|
//this.checkAndAnimateAllDayHeight();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listen for drag operations on all-day events
|
// Listen for drag operations on all-day events
|
||||||
|
|
@ -117,15 +116,8 @@ export class AllDayManager {
|
||||||
reason
|
reason
|
||||||
});
|
});
|
||||||
|
|
||||||
// Recalculate all-day height since clones may have been removed
|
|
||||||
this.checkAndAnimateAllDayHeight();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listen for height check requests from EventRendererManager
|
|
||||||
eventBus.on('allday:checkHeight', () => {
|
|
||||||
console.log('📏 AllDayManager: Received allday:checkHeight request');
|
|
||||||
this.checkAndAnimateAllDayHeight();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAllDayContainer(): HTMLElement | null {
|
private getAllDayContainer(): HTMLElement | null {
|
||||||
|
|
@ -313,7 +305,19 @@ export class AllDayManager {
|
||||||
return layoutEngine.calculateLayout(events);
|
return layoutEngine.calculateLayout(events);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
public initAllDayEventsLayout(events: CalendarEvent[], weekDates: string[]): EventLayout[] {
|
||||||
|
|
||||||
|
// Store current state
|
||||||
|
this.currentAllDayEvents = events;
|
||||||
|
this.currentWeekDates = weekDates;
|
||||||
|
|
||||||
|
// Initialize layout engine with provided week dates
|
||||||
|
var layoutEngine = new AllDayLayoutEngine(weekDates);
|
||||||
|
|
||||||
|
// Calculate layout for all events together - AllDayLayoutEngine handles CalendarEvents directly
|
||||||
|
this.currentLayouts = layoutEngine.calculateLayout(events);
|
||||||
|
return this.currentLayouts;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle conversion of timed event to all-day event - SIMPLIFIED
|
* Handle conversion of timed event to all-day event - SIMPLIFIED
|
||||||
|
|
@ -412,12 +416,8 @@ export class AllDayManager {
|
||||||
if (dragEndEvent.draggedClone == null)
|
if (dragEndEvent.draggedClone == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
// 2. Normalize clone ID
|
// 2. Normalize clone ID
|
||||||
const cloneId = dragEndEvent.draggedClone?.dataset.eventId;
|
dragEndEvent.draggedClone.dataset.eventId = dragEndEvent.draggedClone.dataset.eventId?.replace('clone-', '');
|
||||||
if (cloneId?.startsWith('clone-')) {
|
|
||||||
dragEndEvent.draggedClone.dataset.eventId = cloneId.replace('clone-', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Create temporary array with existing events + the dropped event
|
// 3. Create temporary array with existing events + the dropped event
|
||||||
let eventId = dragEndEvent.draggedClone.dataset.eventId;
|
let eventId = dragEndEvent.draggedClone.dataset.eventId;
|
||||||
|
|
@ -430,7 +430,7 @@ export class AllDayManager {
|
||||||
|
|
||||||
const droppedEvent: CalendarEvent = {
|
const droppedEvent: CalendarEvent = {
|
||||||
id: eventId,
|
id: eventId,
|
||||||
title: dragEndEvent.draggedClone.dataset.title || dragEndEvent.draggedClone.textContent || '',
|
title: dragEndEvent.draggedClone.dataset.title|| '',
|
||||||
start: new Date(eventDate),
|
start: new Date(eventDate),
|
||||||
end: new Date(eventDate),
|
end: new Date(eventDate),
|
||||||
type: eventType,
|
type: eventType,
|
||||||
|
|
@ -449,16 +449,14 @@ export class AllDayManager {
|
||||||
this.newLayouts.forEach((layout) => {
|
this.newLayouts.forEach((layout) => {
|
||||||
// Find current layout for this event
|
// Find current layout for this event
|
||||||
var currentLayout = this.currentLayouts.find(old => old.calenderEvent.id === layout.calenderEvent.id);
|
var currentLayout = this.currentLayouts.find(old => old.calenderEvent.id === layout.calenderEvent.id);
|
||||||
var currentGridArea = currentLayout?.gridArea;
|
|
||||||
var newGridArea = layout.gridArea;
|
|
||||||
|
|
||||||
if (currentGridArea !== newGridArea) {
|
if (currentLayout?.gridArea !== layout.gridArea) {
|
||||||
changedCount++;
|
changedCount++;
|
||||||
const element = dragEndEvent.draggedClone;
|
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 = layout.gridArea;
|
||||||
element.style.gridRow = layout.row.toString();
|
element.style.gridRow = layout.row.toString();
|
||||||
element.style.gridColumn = `${layout.startColumn} / ${layout.endColumn + 1}`;
|
element.style.gridColumn = `${layout.startColumn} / ${layout.endColumn + 1}`;
|
||||||
|
|
||||||
|
|
@ -546,23 +544,26 @@ export class AllDayManager {
|
||||||
const container = this.getAllDayContainer();
|
const container = this.getAllDayContainer();
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
container.querySelectorAll('swp-event').forEach((element) => {
|
// Create overflow indicators for each column that needs them
|
||||||
const event = element as HTMLElement;
|
var columns = ColumnDetectionUtils.getColumns();
|
||||||
const gridRow = parseInt(event.style.gridRow) || 1;
|
|
||||||
|
|
||||||
if (gridRow === 4) {
|
columns.forEach((columnBounds) => {
|
||||||
|
var totalEventsInColumn = this.countEventsInColumn(columnBounds);
|
||||||
|
var overflowCount = Math.max(0, totalEventsInColumn - 3);
|
||||||
|
|
||||||
// Convert row 4 events to indicators
|
if (overflowCount > 0) {
|
||||||
const overflowCount = this.actualRowCount - 3; // Total overflow rows
|
// Create new overflow indicator element
|
||||||
event.classList.add('max-event-overflow');
|
var overflowElement = document.createElement('swp-event');
|
||||||
event.innerHTML = `<span>+${overflowCount} more</span>`;
|
overflowElement.className = 'max-event-overflow';
|
||||||
event.onclick = (e) => {
|
overflowElement.style.gridRow = '4';
|
||||||
|
overflowElement.style.gridColumn = columnBounds.index.toString();
|
||||||
|
overflowElement.innerHTML = `<span>+${overflowCount} more</span>`;
|
||||||
|
overflowElement.onclick = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.toggleExpanded();
|
this.toggleExpanded();
|
||||||
};
|
};
|
||||||
} else if (gridRow > 4) {
|
|
||||||
// Hide events beyond row 4
|
container.appendChild(overflowElement);
|
||||||
event.style.display = 'none';
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -574,21 +575,12 @@ export class AllDayManager {
|
||||||
const container = this.getAllDayContainer();
|
const container = this.getAllDayContainer();
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
container.querySelectorAll('.max-event-overflow').forEach((event) => {
|
// Remove all overflow indicator elements
|
||||||
const htmlEvent = event as HTMLElement;
|
container.querySelectorAll('.max-event-overflow').forEach((element) => {
|
||||||
htmlEvent.classList.remove('max-event-overflow');
|
element.remove();
|
||||||
htmlEvent.onclick = null;
|
|
||||||
|
|
||||||
// Restore original title from data-title
|
|
||||||
if (htmlEvent.dataset.title) {
|
|
||||||
htmlEvent.innerHTML = htmlEvent.dataset.title;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show all hidden events
|
|
||||||
container.querySelectorAll('swp-event[style*="display: none"]').forEach((event) => {
|
|
||||||
(event as HTMLElement).style.display = '';
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -243,8 +243,10 @@ export class DragDropManager {
|
||||||
|
|
||||||
// Check for column change using cached data
|
// Check for column change using cached data
|
||||||
const newColumn = ColumnDetectionUtils.getColumnBounds(currentPosition);
|
const newColumn = ColumnDetectionUtils.getColumnBounds(currentPosition);
|
||||||
|
if (newColumn == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (newColumn && newColumn !== this.currentColumnBounds) {
|
if (newColumn?.index !== this.currentColumnBounds?.index) {
|
||||||
const previousColumn = this.currentColumnBounds;
|
const previousColumn = this.currentColumnBounds;
|
||||||
this.currentColumnBounds = newColumn;
|
this.currentColumnBounds = newColumn;
|
||||||
|
|
||||||
|
|
@ -300,6 +302,8 @@ export class DragDropManager {
|
||||||
this.eventBus.emit('drag:end', dragEndPayload);
|
this.eventBus.emit('drag:end', dragEndPayload);
|
||||||
|
|
||||||
|
|
||||||
|
this.draggedElement = null;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// This was just a click - emit click event instead
|
// This was just a click - emit click event instead
|
||||||
this.eventBus.emit('event:click', {
|
this.eventBus.emit('event:click', {
|
||||||
|
|
|
||||||
|
|
@ -371,15 +371,13 @@ export class EventRenderingService {
|
||||||
// Pass current events to AllDayManager for state tracking
|
// Pass current events to AllDayManager for state tracking
|
||||||
this.allDayManager.setCurrentEvents(allDayEvents, weekDates);
|
this.allDayManager.setCurrentEvents(allDayEvents, weekDates);
|
||||||
|
|
||||||
const layouts = this.allDayManager.calculateAllDayEventsLayout(allDayEvents, weekDates);
|
const layouts = this.allDayManager.initAllDayEventsLayout(allDayEvents, weekDates);
|
||||||
|
|
||||||
// Render each all-day event with pre-calculated layout
|
// Render each all-day event with pre-calculated layout
|
||||||
layouts.forEach(layout => {
|
layouts.forEach(layout => {
|
||||||
this.allDayEventRenderer.renderAllDayEventWithLayout(layout.calenderEvent, layout);
|
this.allDayEventRenderer.renderAllDayEventWithLayout(layout.calenderEvent, layout);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check and adjust all-day container height after rendering
|
|
||||||
this.eventBus.emit('allday:checkHeight');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,6 @@ export interface CalendarEventPayloadMap {
|
||||||
};
|
};
|
||||||
|
|
||||||
// All-day events
|
// All-day events
|
||||||
'allday:checkHeight': undefined;
|
|
||||||
'allday:convert-to-allday': {
|
'allday:convert-to-allday': {
|
||||||
eventId: string;
|
eventId: string;
|
||||||
element: HTMLElement;
|
element: HTMLElement;
|
||||||
|
|
|
||||||
|
|
@ -83,17 +83,8 @@ export class ColumnDetectionUtils {
|
||||||
return column || null;
|
return column || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear cache (useful for testing or when DOM structure changes)
|
|
||||||
*/
|
|
||||||
public static clearCache(): void {
|
|
||||||
this.columnBoundsCache = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
public static getColumns(): ColumnBounds[] {
|
||||||
* Get current cache for debugging
|
|
||||||
*/
|
|
||||||
public static getCache(): ColumnBounds[] {
|
|
||||||
return [...this.columnBoundsCache];
|
return [...this.columnBoundsCache];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue