Some ignored filles was missing
This commit is contained in:
parent
7db22245e2
commit
fd5ab6bc0d
268 changed files with 31970 additions and 4 deletions
528
wwwroot/js/managers/AllDayManager.js
Normal file
528
wwwroot/js/managers/AllDayManager.js
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
// All-day row height management and animations
|
||||
import { eventBus } from '../core/EventBus';
|
||||
import { ALL_DAY_CONSTANTS } from '../configurations/CalendarConfig';
|
||||
import { AllDayLayoutEngine } from '../utils/AllDayLayoutEngine';
|
||||
import { ColumnDetectionUtils } from '../utils/ColumnDetectionUtils';
|
||||
import { SwpAllDayEventElement } from '../elements/SwpEventElement';
|
||||
import { CoreEvents } from '../constants/CoreEvents';
|
||||
/**
|
||||
* AllDayManager - Handles all-day row height animations and management
|
||||
* Uses AllDayLayoutEngine for all overlap detection and layout calculation
|
||||
*/
|
||||
export class AllDayManager {
|
||||
constructor(eventManager, allDayEventRenderer, dateService) {
|
||||
this.layoutEngine = null;
|
||||
// State tracking for layout calculation
|
||||
this.currentAllDayEvents = [];
|
||||
this.currentWeekDates = [];
|
||||
// Expand/collapse state
|
||||
this.isExpanded = false;
|
||||
this.actualRowCount = 0;
|
||||
this.eventManager = eventManager;
|
||||
this.allDayEventRenderer = allDayEventRenderer;
|
||||
this.dateService = dateService;
|
||||
// Sync CSS variable with TypeScript constant to ensure consistency
|
||||
document.documentElement.style.setProperty('--single-row-height', `${ALL_DAY_CONSTANTS.EVENT_HEIGHT}px`);
|
||||
this.setupEventListeners();
|
||||
}
|
||||
/**
|
||||
* Setup event listeners for drag conversions
|
||||
*/
|
||||
setupEventListeners() {
|
||||
eventBus.on('drag:mouseenter-header', (event) => {
|
||||
const payload = event.detail;
|
||||
if (payload.draggedClone.hasAttribute('data-allday'))
|
||||
return;
|
||||
console.log('🔄 AllDayManager: Received drag:mouseenter-header', {
|
||||
targetDate: payload.targetColumn,
|
||||
originalElementId: payload.originalElement?.dataset?.eventId,
|
||||
originalElementTag: payload.originalElement?.tagName
|
||||
});
|
||||
this.handleConvertToAllDay(payload);
|
||||
});
|
||||
eventBus.on('drag:mouseleave-header', (event) => {
|
||||
const { originalElement, cloneElement } = event.detail;
|
||||
console.log('🚪 AllDayManager: Received drag:mouseleave-header', {
|
||||
originalElementId: originalElement?.dataset?.eventId
|
||||
});
|
||||
});
|
||||
// Listen for drag operations on all-day events
|
||||
eventBus.on('drag:start', (event) => {
|
||||
let payload = event.detail;
|
||||
if (!payload.draggedClone?.hasAttribute('data-allday')) {
|
||||
return;
|
||||
}
|
||||
this.allDayEventRenderer.handleDragStart(payload);
|
||||
});
|
||||
eventBus.on('drag:column-change', (event) => {
|
||||
let payload = event.detail;
|
||||
if (!payload.draggedClone?.hasAttribute('data-allday')) {
|
||||
return;
|
||||
}
|
||||
this.handleColumnChange(payload);
|
||||
});
|
||||
eventBus.on('drag:end', (event) => {
|
||||
let dragEndPayload = event.detail;
|
||||
console.log('🎯 AllDayManager: 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' && dragEndPayload.originalElement?.hasAttribute('data-allday')) {
|
||||
console.log('✅ AllDayManager: Handling all-day → all-day drop');
|
||||
this.handleDragEnd(dragEndPayload);
|
||||
return;
|
||||
}
|
||||
// Handle timed → all-day conversion (dropped in header)
|
||||
if (dragEndPayload.target === 'swp-day-header' && !dragEndPayload.originalElement?.hasAttribute('data-allday')) {
|
||||
console.log('🔄 AllDayManager: Timed → all-day conversion on drop');
|
||||
this.handleTimedToAllDayDrop(dragEndPayload);
|
||||
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('🔄 AllDayManager: All-day → timed conversion', { eventId });
|
||||
// Mark for removal (sets data-removing attribute)
|
||||
this.fadeOutAndRemove(dragEndPayload.originalElement);
|
||||
// Recalculate layout WITHOUT the removed event to compress gaps
|
||||
const remainingEvents = this.currentAllDayEvents.filter(e => e.id !== eventId);
|
||||
const newLayouts = this.calculateAllDayEventsLayout(remainingEvents, this.currentWeekDates);
|
||||
// Re-render all-day events with compressed layout
|
||||
this.allDayEventRenderer.renderAllDayEventsForPeriod(newLayouts);
|
||||
// NOW animate height with compressed layout
|
||||
this.checkAndAnimateAllDayHeight();
|
||||
}
|
||||
});
|
||||
// Listen for drag cancellation to recalculate height
|
||||
eventBus.on('drag:cancelled', (event) => {
|
||||
const { draggedElement, reason } = event.detail;
|
||||
console.log('🚫 AllDayManager: Drag cancelled', {
|
||||
eventId: draggedElement?.dataset?.eventId,
|
||||
reason
|
||||
});
|
||||
});
|
||||
// Listen for header ready - when dates are populated with period data
|
||||
eventBus.on('header:ready', async (event) => {
|
||||
let headerReadyEventPayload = event.detail;
|
||||
let startDate = new Date(headerReadyEventPayload.headerElements.at(0).date);
|
||||
let endDate = new Date(headerReadyEventPayload.headerElements.at(-1).date);
|
||||
let events = await this.eventManager.getEventsForPeriod(startDate, endDate);
|
||||
// Filter for all-day events
|
||||
const allDayEvents = events.filter(event => event.allDay);
|
||||
const layouts = this.calculateAllDayEventsLayout(allDayEvents, headerReadyEventPayload.headerElements);
|
||||
this.allDayEventRenderer.renderAllDayEventsForPeriod(layouts);
|
||||
this.checkAndAnimateAllDayHeight();
|
||||
});
|
||||
eventBus.on(CoreEvents.VIEW_CHANGED, (event) => {
|
||||
this.allDayEventRenderer.handleViewChanged(event);
|
||||
});
|
||||
}
|
||||
getAllDayContainer() {
|
||||
return document.querySelector('swp-calendar-header swp-allday-container');
|
||||
}
|
||||
getCalendarHeader() {
|
||||
return document.querySelector('swp-calendar-header');
|
||||
}
|
||||
getHeaderSpacer() {
|
||||
return document.querySelector('swp-header-spacer');
|
||||
}
|
||||
/**
|
||||
* Read current max row from DOM elements
|
||||
* Excludes events marked as removing (data-removing attribute)
|
||||
*/
|
||||
getMaxRowFromDOM() {
|
||||
const container = this.getAllDayContainer();
|
||||
if (!container)
|
||||
return 0;
|
||||
let maxRow = 0;
|
||||
const allDayEvents = container.querySelectorAll('swp-allday-event:not(.max-event-indicator):not([data-removing])');
|
||||
allDayEvents.forEach((element) => {
|
||||
const htmlElement = element;
|
||||
const row = parseInt(htmlElement.style.gridRow) || 1;
|
||||
maxRow = Math.max(maxRow, row);
|
||||
});
|
||||
return maxRow;
|
||||
}
|
||||
/**
|
||||
* Get current gridArea for an event from DOM
|
||||
*/
|
||||
getGridAreaFromDOM(eventId) {
|
||||
const container = this.getAllDayContainer();
|
||||
if (!container)
|
||||
return null;
|
||||
const element = container.querySelector(`[data-event-id="${eventId}"]`);
|
||||
return element?.style.gridArea || null;
|
||||
}
|
||||
/**
|
||||
* Count events in a specific column by reading DOM
|
||||
*/
|
||||
countEventsInColumnFromDOM(columnIndex) {
|
||||
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) => {
|
||||
const htmlElement = element;
|
||||
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
|
||||
*/
|
||||
calculateAllDayHeight(targetRows) {
|
||||
const root = document.documentElement;
|
||||
const targetHeight = targetRows * ALL_DAY_CONSTANTS.SINGLE_ROW_HEIGHT;
|
||||
// Read CSS variable directly from style property or default to 0
|
||||
const currentHeightStr = root.style.getPropertyValue('--all-day-row-height') || '0px';
|
||||
const currentHeight = parseInt(currentHeightStr) || 0;
|
||||
const heightDifference = targetHeight - currentHeight;
|
||||
return { targetHeight, currentHeight, heightDifference };
|
||||
}
|
||||
/**
|
||||
* Check current all-day events and animate to correct height
|
||||
* Reads max row directly from DOM elements
|
||||
*/
|
||||
checkAndAnimateAllDayHeight() {
|
||||
// Read max row directly from DOM
|
||||
const maxRows = this.getMaxRowFromDOM();
|
||||
console.log('📊 AllDayManager: Height calculation', {
|
||||
maxRows,
|
||||
isExpanded: this.isExpanded
|
||||
});
|
||||
// Store actual row count
|
||||
this.actualRowCount = maxRows;
|
||||
// Determine what to display
|
||||
let displayRows = maxRows;
|
||||
if (maxRows > ALL_DAY_CONSTANTS.MAX_COLLAPSED_ROWS) {
|
||||
// Show chevron button
|
||||
this.updateChevronButton(true);
|
||||
// Show 4 rows when collapsed (3 events + indicators)
|
||||
if (!this.isExpanded) {
|
||||
displayRows = ALL_DAY_CONSTANTS.MAX_COLLAPSED_ROWS;
|
||||
this.updateOverflowIndicators();
|
||||
}
|
||||
else {
|
||||
this.clearOverflowIndicators();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Hide chevron - not needed
|
||||
this.updateChevronButton(false);
|
||||
this.clearOverflowIndicators();
|
||||
}
|
||||
console.log('🎬 AllDayManager: Will animate to', {
|
||||
displayRows,
|
||||
maxRows,
|
||||
willAnimate: displayRows !== this.actualRowCount
|
||||
});
|
||||
console.log(`🎯 AllDayManager: Animating to ${displayRows} rows`);
|
||||
// Animate to required rows (0 = collapse, >0 = expand)
|
||||
this.animateToRows(displayRows);
|
||||
}
|
||||
/**
|
||||
* 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 cached elements
|
||||
const calendarHeader = this.getCalendarHeader();
|
||||
const headerSpacer = this.getHeaderSpacer();
|
||||
const allDayContainer = this.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, but don't use fill: 'forwards'
|
||||
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'
|
||||
// No fill: 'forwards' - let CSS calc() take over after animation
|
||||
}));
|
||||
}
|
||||
// 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 layout for ALL all-day events using AllDayLayoutEngine
|
||||
* This is the correct method that processes all events together for proper overlap detection
|
||||
*/
|
||||
calculateAllDayEventsLayout(events, dayHeaders) {
|
||||
// Store current state
|
||||
this.currentAllDayEvents = events;
|
||||
this.currentWeekDates = dayHeaders;
|
||||
// Initialize layout engine with provided week dates
|
||||
let layoutEngine = new AllDayLayoutEngine(dayHeaders.map(column => column.date));
|
||||
// Calculate layout for all events together - AllDayLayoutEngine handles CalendarEvents directly
|
||||
return layoutEngine.calculateLayout(events);
|
||||
}
|
||||
handleConvertToAllDay(payload) {
|
||||
let allDayContainer = this.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();
|
||||
// Recalculate height after adding all-day event
|
||||
this.checkAndAnimateAllDayHeight();
|
||||
}
|
||||
/**
|
||||
* Handle drag move for all-day events - SPECIALIZED FOR ALL-DAY CONTAINER
|
||||
*/
|
||||
handleColumnChange(dragColumnChangeEventPayload) {
|
||||
let allDayContainer = this.getAllDayContainer();
|
||||
if (!allDayContainer)
|
||||
return;
|
||||
let targetColumn = ColumnDetectionUtils.getColumnBounds(dragColumnChangeEventPayload.mousePosition);
|
||||
if (targetColumn == null)
|
||||
return;
|
||||
if (!dragColumnChangeEventPayload.draggedClone)
|
||||
return;
|
||||
// Calculate event span from original grid positioning
|
||||
const computedStyle = window.getComputedStyle(dragColumnChangeEventPayload.draggedClone);
|
||||
const gridColumnStart = parseInt(computedStyle.gridColumnStart) || targetColumn.index;
|
||||
const gridColumnEnd = parseInt(computedStyle.gridColumnEnd) || targetColumn.index + 1;
|
||||
const span = gridColumnEnd - gridColumnStart;
|
||||
// Update clone position maintaining the span
|
||||
const newStartColumn = targetColumn.index;
|
||||
const newEndColumn = newStartColumn + span;
|
||||
dragColumnChangeEventPayload.draggedClone.style.gridColumn = `${newStartColumn} / ${newEndColumn}`;
|
||||
}
|
||||
fadeOutAndRemove(element) {
|
||||
console.log('🗑️ AllDayManager: About to remove all-day event', {
|
||||
eventId: element.dataset.eventId,
|
||||
element: element.tagName
|
||||
});
|
||||
// Mark element as removing so it's excluded from height calculations
|
||||
element.setAttribute('data-removing', 'true');
|
||||
element.style.transition = 'opacity 0.3s ease-out';
|
||||
element.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
element.remove();
|
||||
console.log('✅ AllDayManager: All-day event removed from DOM');
|
||||
}, 300);
|
||||
}
|
||||
/**
|
||||
* Handle timed → all-day conversion on drop
|
||||
*/
|
||||
async handleTimedToAllDayDrop(dragEndEvent) {
|
||||
if (!dragEndEvent.draggedClone || !dragEndEvent.finalPosition.column)
|
||||
return;
|
||||
const clone = dragEndEvent.draggedClone;
|
||||
const eventId = clone.eventId.replace('clone-', '');
|
||||
const targetDate = dragEndEvent.finalPosition.column.date;
|
||||
console.log('🔄 AllDayManager: Converting timed event to all-day', { eventId, targetDate });
|
||||
// Create new dates preserving time
|
||||
const newStart = new Date(targetDate);
|
||||
newStart.setHours(clone.start.getHours(), clone.start.getMinutes(), 0, 0);
|
||||
const newEnd = new Date(targetDate);
|
||||
newEnd.setHours(clone.end.getHours(), clone.end.getMinutes(), 0, 0);
|
||||
// Update event in repository
|
||||
await this.eventManager.updateEvent(eventId, {
|
||||
start: newStart,
|
||||
end: newEnd,
|
||||
allDay: true
|
||||
});
|
||||
// Remove original timed event
|
||||
this.fadeOutAndRemove(dragEndEvent.originalElement);
|
||||
// Add to current all-day events and recalculate layout
|
||||
const newEvent = {
|
||||
id: eventId,
|
||||
title: clone.title,
|
||||
start: newStart,
|
||||
end: newEnd,
|
||||
type: clone.type,
|
||||
allDay: true,
|
||||
syncStatus: 'synced'
|
||||
};
|
||||
const updatedEvents = [...this.currentAllDayEvents, newEvent];
|
||||
const newLayouts = this.calculateAllDayEventsLayout(updatedEvents, this.currentWeekDates);
|
||||
this.allDayEventRenderer.renderAllDayEventsForPeriod(newLayouts);
|
||||
// Animate height
|
||||
this.checkAndAnimateAllDayHeight();
|
||||
}
|
||||
/**
|
||||
* Handle all-day → all-day drop (moving within header)
|
||||
*/
|
||||
async handleDragEnd(dragEndEvent) {
|
||||
if (!dragEndEvent.draggedClone || !dragEndEvent.finalPosition.column)
|
||||
return;
|
||||
const clone = dragEndEvent.draggedClone;
|
||||
const eventId = clone.eventId.replace('clone-', '');
|
||||
const targetDate = dragEndEvent.finalPosition.column.date;
|
||||
// Calculate duration in days
|
||||
const durationDays = this.dateService.differenceInCalendarDays(clone.end, clone.start);
|
||||
// Create new dates preserving time
|
||||
const newStart = new Date(targetDate);
|
||||
newStart.setHours(clone.start.getHours(), clone.start.getMinutes(), 0, 0);
|
||||
const newEnd = new Date(targetDate);
|
||||
newEnd.setDate(newEnd.getDate() + durationDays);
|
||||
newEnd.setHours(clone.end.getHours(), clone.end.getMinutes(), 0, 0);
|
||||
// Update event in repository
|
||||
await this.eventManager.updateEvent(eventId, {
|
||||
start: newStart,
|
||||
end: newEnd,
|
||||
allDay: true
|
||||
});
|
||||
// Remove original and fade out
|
||||
this.fadeOutAndRemove(dragEndEvent.originalElement);
|
||||
// Recalculate and re-render ALL events
|
||||
const updatedEvents = this.currentAllDayEvents.map(e => e.id === eventId ? { ...e, start: newStart, end: newEnd } : e);
|
||||
const newLayouts = this.calculateAllDayEventsLayout(updatedEvents, this.currentWeekDates);
|
||||
this.allDayEventRenderer.renderAllDayEventsForPeriod(newLayouts);
|
||||
// Animate height - this also handles overflow classes!
|
||||
this.checkAndAnimateAllDayHeight();
|
||||
}
|
||||
/**
|
||||
* Update chevron button visibility and state
|
||||
*/
|
||||
updateChevronButton(show) {
|
||||
const headerSpacer = this.getHeaderSpacer();
|
||||
if (!headerSpacer)
|
||||
return;
|
||||
let chevron = headerSpacer.querySelector('.allday-chevron');
|
||||
if (show && !chevron) {
|
||||
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) {
|
||||
chevron.remove();
|
||||
}
|
||||
else if (chevron) {
|
||||
chevron.classList.toggle('collapsed', !this.isExpanded);
|
||||
chevron.classList.toggle('expanded', this.isExpanded);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Toggle between expanded and collapsed state
|
||||
*/
|
||||
toggleExpanded() {
|
||||
this.isExpanded = !this.isExpanded;
|
||||
this.checkAndAnimateAllDayHeight();
|
||||
const elements = document.querySelectorAll('swp-allday-container swp-allday-event.max-event-overflow-hide, swp-allday-container swp-allday-event.max-event-overflow-show');
|
||||
elements.forEach((element) => {
|
||||
if (this.isExpanded) {
|
||||
// ALTID vis når expanded=true
|
||||
element.classList.remove('max-event-overflow-hide');
|
||||
element.classList.add('max-event-overflow-show');
|
||||
}
|
||||
else {
|
||||
// ALTID skjul når expanded=false
|
||||
element.classList.remove('max-event-overflow-show');
|
||||
element.classList.add('max-event-overflow-hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Count number of events in a specific column using IColumnBounds
|
||||
* Reads directly from DOM elements
|
||||
*/
|
||||
countEventsInColumn(columnBounds) {
|
||||
return this.countEventsInColumnFromDOM(columnBounds.index);
|
||||
}
|
||||
/**
|
||||
* Update overflow indicators for collapsed state
|
||||
*/
|
||||
updateOverflowIndicators() {
|
||||
const container = this.getAllDayContainer();
|
||||
if (!container)
|
||||
return;
|
||||
// Create overflow indicators for each column that needs them
|
||||
let columns = ColumnDetectionUtils.getColumns();
|
||||
columns.forEach((columnBounds) => {
|
||||
let totalEventsInColumn = this.countEventsInColumn(columnBounds);
|
||||
let overflowCount = totalEventsInColumn - ALL_DAY_CONSTANTS.MAX_COLLAPSED_ROWS;
|
||||
if (overflowCount > 0) {
|
||||
// Check if indicator already exists in this column
|
||||
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 element
|
||||
let 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 overflow indicators and restore normal state
|
||||
*/
|
||||
clearOverflowIndicators() {
|
||||
const container = this.getAllDayContainer();
|
||||
if (!container)
|
||||
return;
|
||||
// Remove all overflow indicator elements
|
||||
container.querySelectorAll('.max-event-indicator').forEach((element) => {
|
||||
element.remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=AllDayManager.js.map
|
||||
Loading…
Add table
Add a link
Reference in a new issue