Improves all-day event drag and drop

Refactors all-day event conversion during drag and drop to
use the event payload, improving code clarity and reducing
redundancy.

Removes unnecessary style settings and fixes column detection
logic. Addresses an issue where event removal occurred before
successful placement.
This commit is contained in:
Janus C. H. Knudsen 2025-09-29 20:50:52 +02:00
parent 8b5420f367
commit 83e01f9cb7
7 changed files with 29 additions and 49 deletions

View file

@ -88,7 +88,6 @@ export class SwpEventElement extends BaseEventElement {
*/
private applyPositioning(): void {
const position = this.calculateEventPosition();
this.element.style.position = 'absolute';
this.element.style.top = `${position.top + 1}px`;
this.element.style.height = `${position.height - 3}px`;
this.element.style.left = '2px';

View file

@ -38,18 +38,15 @@ export class AllDayManager {
*/
private setupEventListeners(): void {
eventBus.on('drag:mouseenter-header', (event) => {
const { targetColumn: targetColumnBounds, mousePosition, originalElement, cloneElement } = (event as CustomEvent<DragMouseEnterHeaderEventPayload>).detail;
const payload = (event as CustomEvent<DragMouseEnterHeaderEventPayload>).detail;
console.log('🔄 AllDayManager: Received drag:mouseenter-header', {
targetDate: targetColumnBounds,
originalElementId: originalElement?.dataset?.eventId,
originalElementTag: originalElement?.tagName
targetDate: payload.targetColumn,
originalElementId: payload.originalElement?.dataset?.eventId,
originalElementTag: payload.originalElement?.tagName
});
if (targetColumnBounds && cloneElement) {
this.handleConvertToAllDay(targetColumnBounds, cloneElement);
}
this.handleConvertToAllDay(payload);
this.checkAndAnimateAllDayHeight();
});
@ -318,28 +315,28 @@ export class AllDayManager {
* Handle conversion of timed event to all-day event - SIMPLIFIED
* During drag: Place in row 1 only, calculate column from targetDate
*/
private handleConvertToAllDay(targetColumnBounds: ColumnBounds, cloneElement: HTMLElement): void {
private handleConvertToAllDay(payload: DragMouseEnterHeaderEventPayload): void {
console.log('🔄 AllDayManager: Converting to all-day (row 1 only during drag)', {
eventId: cloneElement.dataset.eventId,
targetDate: targetColumnBounds
eventId: payload.cloneElement.dataset.eventId,
targetDate: payload.targetColumn
});
// Get all-day container, request creation if needed
let allDayContainer = this.getAllDayContainer();
cloneElement.removeAttribute('style');
cloneElement.classList.add('all-day-style');
cloneElement.style.gridRow = '1';
cloneElement.style.gridColumn = targetColumnBounds.index.toString();
cloneElement.dataset.allday = 'true'; // Set the all-day attribute for filtering
payload.cloneElement.removeAttribute('style');
payload.cloneElement.classList.add('all-day-style');
payload.cloneElement.style.gridRow = '1';
payload.cloneElement.style.gridColumn = payload.targetColumn.index.toString();
payload.cloneElement.dataset.allday = 'true'; // Set the all-day attribute for filtering
// Add to container
allDayContainer?.appendChild(cloneElement);
allDayContainer?.appendChild(payload.cloneElement);
console.log('✅ AllDayManager: Converted to all-day style (simple row 1)', {
eventId: cloneElement.dataset.eventId,
gridColumn: targetColumnBounds,
eventId: payload.cloneElement.dataset.eventId,
gridColumn: payload.targetColumn,
gridRow: 1
});
}

View file

@ -304,6 +304,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
this.removeEventFromExistingGroups(originalElement);
// Fade out original
// TODO: this should be changed into a subscriber which only after a succesful placement is fired, not just mouseup as this can remove elements that are not placed.
this.fadeOutAndRemove(originalElement);
// Remove clone prefix and normalize clone to be a regular event

View file

@ -80,7 +80,7 @@ export interface DragMouseEnterHeaderEventPayload {
targetColumn: ColumnBounds;
mousePosition: MousePosition;
originalElement: HTMLElement | null;
cloneElement: HTMLElement | null;
cloneElement: HTMLElement;
}
// Drag mouse leave header event payload

View file

@ -27,7 +27,7 @@ export class ColumnDetectionUtils {
// Find alle kolonner
const columns = document.querySelectorAll('swp-day-column');
let index = 0;
let index = 1;
// Cache hver kolonnes x-grænser
columns.forEach(column => {
const rect = column.getBoundingClientRect();

View file

@ -274,20 +274,6 @@ swp-day-header[data-today="true"] swp-day-date {
margin: 4px auto 0;
}
/* All-day container - initially hidden, animated in when first event is dragged */
swp-allday-container {
grid-column: 1 / -1; /* Span all columns */
grid-row: 2; /* Second row of calendar header */
display: grid;
grid-template-columns: repeat(var(--grid-columns, 7), minmax(var(--day-column-min-width), 1fr));
grid-template-rows: repeat(1, auto); /* Default to 1 row, dynamically updated by JS */
gap: 2px;
padding: 2px;
align-items: center;
overflow: hidden;
}
/* Ghost columns for mouseenter events */
swp-allday-column {
position: relative;
@ -299,8 +285,7 @@ swp-allday-column {
}
/* All-day events in containers */
swp-allday-container swp-event,
swp-event.all-day-style {
swp-allday-container swp-event {
height: 22px !important; /* Fixed height for consistent stacking */
position: relative !important;
width: auto !important;
@ -308,13 +293,11 @@ swp-event.all-day-style {
right: auto !important;
top: auto !important;
padding: 2px 4px;
margin-bottom: 2px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
background: #ff9800; /* Default orange background */
background: hsl(208, 100%, 50%);
display: flex;
position: relative;
z-index: 2; /* Above ghost columns */
align-items: center;
justify-content: flex-start;
@ -326,11 +309,11 @@ swp-event.all-day-style {
text-overflow: ellipsis;
white-space: nowrap;
border-left: 3px solid rgba(0, 0, 0, 0.2);
&.dragging {
background: lab(70.24% -13.38 -46.17);
}
swp-allday-container swp-event:last-child,
swp-event.all-day-style:last-child {
margin-bottom: 0;
}
/* Hide time element for all-day styled events */