From f2ad13776f2c166a4ddb6b7c2c8fa3870545ca17 Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Thu, 2 Oct 2025 01:03:35 +0200 Subject: [PATCH] Improves all-day event row height calculation Ensures consistent all-day event row height calculation across CSS and TypeScript. The all-day event row height calculation is adjusted by removing redundant container padding from the TypeScript constant and synchronizing the CSS variable with the event height. Additionally, the layout engine is directly tested in the test file for better coverage. --- src/core/CalendarConfig.ts | 2 +- src/managers/AllDayManager.ts | 20 +++---- test/managers/AllDayManager.test.ts | 84 +++++++++++++++-------------- wwwroot/css/calendar-base-css.css | 1 + wwwroot/css/calendar-layout-css.css | 4 +- 5 files changed, 58 insertions(+), 53 deletions(-) diff --git a/src/core/CalendarConfig.ts b/src/core/CalendarConfig.ts index 57c57ed..fd29c66 100644 --- a/src/core/CalendarConfig.ts +++ b/src/core/CalendarConfig.ts @@ -13,7 +13,7 @@ export const ALL_DAY_CONSTANTS = { EVENT_GAP: 2, // Gap between stacked events CONTAINER_PADDING: 4, // Container padding (top + bottom) get SINGLE_ROW_HEIGHT() { - return this.EVENT_HEIGHT + this.EVENT_GAP + this.CONTAINER_PADDING; // 28px + return this.EVENT_HEIGHT + this.EVENT_GAP; // 28px } } as const; diff --git a/src/managers/AllDayManager.ts b/src/managers/AllDayManager.ts index 50b2cbb..1d04e86 100644 --- a/src/managers/AllDayManager.ts +++ b/src/managers/AllDayManager.ts @@ -42,6 +42,13 @@ export class AllDayManager { constructor(eventManager: EventManager) { this.eventManager = eventManager; this.allDayEventRenderer = new AllDayEventRenderer(); + + // Sync CSS variable with TypeScript constant to ensure consistency + document.documentElement.style.setProperty( + '--single-row-height', + `${ALL_DAY_CONSTANTS.EVENT_HEIGHT}px` + ); + this.setupEventListeners(); } @@ -134,9 +141,9 @@ export class AllDayManager { // Filter for all-day events const allDayEvents = events.filter(event => event.allDay); - let eventLayouts = this.calculateAllDayEventsLayout(allDayEvents, headerReadyEventPayload.headerElements) + this.currentLayouts = this.calculateAllDayEventsLayout(allDayEvents, headerReadyEventPayload.headerElements) - this.allDayEventRenderer.renderAllDayEventsForPeriod(eventLayouts); + this.allDayEventRenderer.renderAllDayEventsForPeriod(this.currentLayouts ); this.checkAndAnimateAllDayHeight(); }); @@ -166,7 +173,7 @@ export class AllDayManager { heightDifference: number; } { const root = document.documentElement; - const targetHeight = targetRows * ALL_DAY_CONSTANTS.SINGLE_ROW_HEIGHT; + const targetHeight = targetRows * ALL_DAY_CONSTANTS.SINGLE_ROW_HEIGHT + 2; // 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; @@ -199,12 +206,7 @@ export class AllDayManager { // Max rows = highest row number (e.g. if row 3 is used, height = 3 rows) maxRows = highestRow; - - console.log('🔍 AllDayManager: Height calculation using currentLayouts', { - totalLayouts: this.currentLayouts.length, - highestRowFound: highestRow, - maxRows - }); + } // Store actual row count diff --git a/test/managers/AllDayManager.test.ts b/test/managers/AllDayManager.test.ts index 05f342c..5e39a35 100644 --- a/test/managers/AllDayManager.test.ts +++ b/test/managers/AllDayManager.test.ts @@ -1,41 +1,43 @@ -import { describe, it, expect, beforeEach } from 'vitest'; -import { AllDayManager } from '../../src/managers/AllDayManager'; -import { setupMockDOM, createMockEvent } from '../helpers/dom-helpers'; - -describe('AllDayManager - Manager Functionality', () => { - let allDayManager: AllDayManager; - - beforeEach(() => { - setupMockDOM(); - allDayManager = new AllDayManager(); - }); - - describe('Layout Calculation Integration', () => { - it('should delegate layout calculation to AllDayLayoutEngine', () => { - // Simple integration test to verify manager uses the layout engine correctly - const event = createMockEvent('test', 'Test Event', '2024-09-24', '2024-09-24'); - const weekDates = ['2024-09-22', '2024-09-23', '2024-09-24', '2024-09-25', '2024-09-26']; - - const layouts = allDayManager.calculateAllDayEventsLayout([event], weekDates); - - expect(layouts.length).toBe(1); - expect(layouts[0].calenderEvent.id).toBe('test'); - expect(layouts[0].startColumn).toBe(3); // Sept 24 is column 3 - expect(layouts[0].row).toBe(1); - }); - - it('should handle empty event list', () => { - const weekDates = ['2024-09-22', '2024-09-23', '2024-09-24', '2024-09-25', '2024-09-26']; - const layouts = allDayManager.calculateAllDayEventsLayout([], weekDates); - - expect(layouts.length).toBe(0); - }); - - it('should handle empty week dates', () => { - const event = createMockEvent('test', 'Test Event', '2024-09-24', '2024-09-24'); - const layouts = allDayManager.calculateAllDayEventsLayout([event], []); - - expect(layouts.length).toBe(0); - }); - }); -}); \ No newline at end of file +import { describe, it, expect, beforeEach } from 'vitest'; +import { AllDayLayoutEngine } from '../../src/utils/AllDayLayoutEngine'; +import { setupMockDOM, createMockEvent } from '../helpers/dom-helpers'; + +describe('AllDayManager - Layout Engine Integration', () => { + let layoutEngine: AllDayLayoutEngine; + + beforeEach(() => { + setupMockDOM(); + }); + + describe('Layout Calculation Integration', () => { + it('should delegate layout calculation to AllDayLayoutEngine', () => { + // Test AllDayLayoutEngine directly since calculateAllDayEventsLayout is private + const event = createMockEvent('test', 'Test Event', '2024-09-24', '2024-09-24'); + const weekDates = ['2024-09-22', '2024-09-23', '2024-09-24', '2024-09-25', '2024-09-26']; + + layoutEngine = new AllDayLayoutEngine(weekDates); + const layouts = layoutEngine.calculateLayout([event]); + + expect(layouts.length).toBe(1); + expect(layouts[0].calenderEvent.id).toBe('test'); + expect(layouts[0].startColumn).toBe(3); // Sept 24 is column 3 + expect(layouts[0].row).toBe(1); + }); + + it('should handle empty event list', () => { + const weekDates = ['2024-09-22', '2024-09-23', '2024-09-24', '2024-09-25', '2024-09-26']; + layoutEngine = new AllDayLayoutEngine(weekDates); + const layouts = layoutEngine.calculateLayout([]); + + expect(layouts.length).toBe(0); + }); + + it('should handle empty week dates', () => { + const event = createMockEvent('test', 'Test Event', '2024-09-24', '2024-09-24'); + layoutEngine = new AllDayLayoutEngine([]); + const layouts = layoutEngine.calculateLayout([event]); + + expect(layouts.length).toBe(0); + }); + }); +}); diff --git a/wwwroot/css/calendar-base-css.css b/wwwroot/css/calendar-base-css.css index 8843133..06c1d1a 100644 --- a/wwwroot/css/calendar-base-css.css +++ b/wwwroot/css/calendar-base-css.css @@ -18,6 +18,7 @@ --header-height: 80px; --all-day-row-height: 0px; /* Default height for all-day events row */ --all-day-event-height: 26px; /* Height of single all-day event including gaps */ + --single-row-height: 28px; /* Height of single row in all-day container - synced with TypeScript */ --stack-levels: 1; /* Number of stack levels for all-day events */ /* Time boundaries - Default fallback values */ diff --git a/wwwroot/css/calendar-layout-css.css b/wwwroot/css/calendar-layout-css.css index c029484..7e9b85d 100644 --- a/wwwroot/css/calendar-layout-css.css +++ b/wwwroot/css/calendar-layout-css.css @@ -200,8 +200,8 @@ swp-allday-container { grid-row: 2; display: grid; grid-template-columns: repeat(var(--grid-columns, 7), minmax(var(--day-column-min-width), 1fr)); - grid-template-rows: repeat(1, auto); - gap: 2px; + grid-auto-rows: var(--single-row-height); /* Each row is exactly SINGLE_ROW_HEIGHT */ + gap: 2px 0px; padding: 2px; align-items: center; overflow: hidden;