Calendar/wwwroot/js/features/all-day/AllDayCollapseService.js
2026-02-03 00:02:25 +01:00

168 lines
No EOL
6.5 KiB
JavaScript

/**
* 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