Refactors calendar project structure and build configuration

Consolidates V2 codebase into main project directory
Updates build script to support simplified entry points
Removes redundant files and cleans up project organization

Simplifies module imports and entry points for calendar application
This commit is contained in:
Janus C. H. Knudsen 2025-12-17 23:54:25 +01:00
parent 9f360237cf
commit 863b433eba
200 changed files with 2331 additions and 16193 deletions

View file

@ -1,284 +1,17 @@
// Main entry point for Calendar Plantempus
import { Container } from '@novadi/core';
import { eventBus } from './core/EventBus';
import { ConfigManager } from './configurations/ConfigManager';
import { Configuration } from './configurations/CalendarConfig';
import { URLManager } from './utils/URLManager';
import { ICalendarEvent, IEventBus } from './types/CalendarTypes';
// Import all managers
import { EventManager } from './managers/EventManager';
import { EventRenderingService } from './renderers/EventRendererManager';
import { GridManager } from './managers/GridManager';
import { ScrollManager } from './managers/ScrollManager';
import { NavigationManager } from './managers/NavigationManager';
import { NavigationButtons } from './components/NavigationButtons';
import { ViewSelector } from './components/ViewSelector';
import { CalendarManager } from './managers/CalendarManager';
import { DragDropManager } from './managers/DragDropManager';
import { AllDayManager } from './managers/AllDayManager';
import { ResizeHandleManager } from './managers/ResizeHandleManager';
import { EdgeScrollManager } from './managers/EdgeScrollManager';
import { HeaderManager } from './managers/HeaderManager';
import { WorkweekPresets } from './components/WorkweekPresets';
// Import repositories and storage
import { MockEventRepository } from './repositories/MockEventRepository';
import { MockBookingRepository } from './repositories/MockBookingRepository';
import { MockCustomerRepository } from './repositories/MockCustomerRepository';
import { MockResourceRepository } from './repositories/MockResourceRepository';
import { MockAuditRepository } from './repositories/MockAuditRepository';
import { IApiRepository } from './repositories/IApiRepository';
import { IAuditEntry } from './types/AuditTypes';
import { ApiEventRepository } from './repositories/ApiEventRepository';
import { ApiBookingRepository } from './repositories/ApiBookingRepository';
import { ApiCustomerRepository } from './repositories/ApiCustomerRepository';
import { ApiResourceRepository } from './repositories/ApiResourceRepository';
import { IndexedDBContext } from './storage/IndexedDBContext';
import { IStore } from './storage/IStore';
import { AuditStore } from './storage/audit/AuditStore';
import { AuditService } from './storage/audit/AuditService';
import { BookingStore } from './storage/bookings/BookingStore';
import { CustomerStore } from './storage/customers/CustomerStore';
import { ResourceStore } from './storage/resources/ResourceStore';
import { EventStore } from './storage/events/EventStore';
import { IEntityService } from './storage/IEntityService';
import { EventService } from './storage/events/EventService';
import { BookingService } from './storage/bookings/BookingService';
import { CustomerService } from './storage/customers/CustomerService';
import { ResourceService } from './storage/resources/ResourceService';
// Import workers
import { SyncManager } from './workers/SyncManager';
import { DataSeeder } from './workers/DataSeeder';
// Import renderers
import { DateHeaderRenderer, type IHeaderRenderer } from './renderers/DateHeaderRenderer';
import { DateColumnRenderer, type IColumnRenderer } from './renderers/ColumnRenderer';
import { DateEventRenderer, type IEventRenderer } from './renderers/EventRenderer';
import { AllDayEventRenderer } from './renderers/AllDayEventRenderer';
import { GridRenderer } from './renderers/GridRenderer';
import { WeekInfoRenderer } from './renderers/WeekInfoRenderer';
// Import utilities and services
import { DateService } from './utils/DateService';
import { TimeFormatter } from './utils/TimeFormatter';
import { PositionUtils } from './utils/PositionUtils';
import { AllDayLayoutEngine } from './utils/AllDayLayoutEngine';
import { WorkHoursManager } from './managers/WorkHoursManager';
import { EventStackManager } from './managers/EventStackManager';
import { EventLayoutCoordinator } from './managers/EventLayoutCoordinator';
import { IColumnDataSource } from './types/ColumnDataSource';
import { DateColumnDataSource } from './datasources/DateColumnDataSource';
import { ResourceColumnDataSource } from './datasources/ResourceColumnDataSource';
import { ResourceHeaderRenderer } from './renderers/ResourceHeaderRenderer';
import { ResourceColumnRenderer } from './renderers/ResourceColumnRenderer';
import { IBooking } from './types/BookingTypes';
import { ICustomer } from './types/CustomerTypes';
import { IResource } from './types/ResourceTypes';
/**
* Handle deep linking functionality after managers are initialized
*/
async function handleDeepLinking(eventManager: EventManager, urlManager: URLManager): Promise<void> {
try {
const eventId = urlManager.parseEventIdFromURL();
if (eventId) {
console.log(`Deep linking to event ID: ${eventId}`);
// Wait a bit for managers to be fully ready
setTimeout(async () => {
const success = await eventManager.navigateToEvent(eventId);
if (!success) {
console.warn(`Deep linking failed: Event with ID ${eventId} not found`);
}
}, 500);
}
} catch (error) {
console.warn('Deep linking failed:', error);
}
}
/**
* Initialize the calendar application using NovaDI
*/
async function initializeCalendar(): Promise<void> {
try {
// Load configuration from JSON
const config = await ConfigManager.load();
// Create NovaDI container
const container = new Container();
const builder = container.builder();
// Enable debug mode for development
eventBus.setDebug(true);
// Bind core services as instances
builder.registerInstance(eventBus).as<IEventBus>();
// Register configuration instance
builder.registerInstance(config).as<Configuration>();
// Register storage stores (IStore implementations)
// Open/Closed Principle: Adding new entity only requires adding one line here
builder.registerType(BookingStore).as<IStore>();
builder.registerType(CustomerStore).as<IStore>();
builder.registerType(ResourceStore).as<IStore>();
builder.registerType(EventStore).as<IStore>();
builder.registerType(AuditStore).as<IStore>();
// Register storage and repository services
builder.registerType(IndexedDBContext).as<IndexedDBContext>();
// Register Mock repositories (development/testing - load from JSON files)
// Each entity type has its own Mock repository implementing IApiRepository<T>
builder.registerType(MockEventRepository).as<IApiRepository<ICalendarEvent>>();
builder.registerType(MockBookingRepository).as<IApiRepository<IBooking>>();
builder.registerType(MockCustomerRepository).as<IApiRepository<ICustomer>>();
builder.registerType(MockResourceRepository).as<IApiRepository<IResource>>();
builder.registerType(MockAuditRepository).as<IApiRepository<IAuditEntry>>();
let calendarMode = 'resource' ;
// Register DataSource and HeaderRenderer based on mode
if (calendarMode === 'resource') {
builder.registerType(ResourceColumnDataSource).as<IColumnDataSource>();
builder.registerType(ResourceHeaderRenderer).as<IHeaderRenderer>();
} else {
builder.registerType(DateColumnDataSource).as<IColumnDataSource>();
builder.registerType(DateHeaderRenderer).as<IHeaderRenderer>();
}
// Register entity services (sync status management)
// Open/Closed Principle: Adding new entity only requires adding one line here
builder.registerType(EventService).as<IEntityService<ICalendarEvent>>();
builder.registerType(EventService).as<EventService>();
builder.registerType(BookingService).as<IEntityService<IBooking>>();
builder.registerType(CustomerService).as<IEntityService<ICustomer>>();
builder.registerType(ResourceService).as<IEntityService<IResource>>();
builder.registerType(ResourceService).as<ResourceService>();
builder.registerType(AuditService).as<AuditService>();
// Register workers
builder.registerType(SyncManager).as<SyncManager>();
builder.registerType(DataSeeder).as<DataSeeder>();
// Register renderers
// Note: IHeaderRenderer and IColumnRenderer are registered above based on calendarMode
if (calendarMode === 'resource') {
builder.registerType(ResourceColumnRenderer).as<IColumnRenderer>();
} else {
builder.registerType(DateColumnRenderer).as<IColumnRenderer>();
}
builder.registerType(DateEventRenderer).as<IEventRenderer>();
// Register core services and utilities
builder.registerType(DateService).as<DateService>();
builder.registerType(EventStackManager).as<EventStackManager>();
builder.registerType(EventLayoutCoordinator).as<EventLayoutCoordinator>();
builder.registerType(WorkHoursManager).as<WorkHoursManager>();
builder.registerType(URLManager).as<URLManager>();
builder.registerType(TimeFormatter).as<TimeFormatter>();
builder.registerType(PositionUtils).as<PositionUtils>();
// Note: AllDayLayoutEngine is instantiated per-operation with specific dates, not a singleton
builder.registerType(WeekInfoRenderer).as<WeekInfoRenderer>();
builder.registerType(AllDayEventRenderer).as<AllDayEventRenderer>();
builder.registerType(EventRenderingService).as<EventRenderingService>();
builder.registerType(GridRenderer).as<GridRenderer>();
builder.registerType(GridManager).as<GridManager>();
builder.registerType(ScrollManager).as<ScrollManager>();
builder.registerType(NavigationManager).as<NavigationManager>();
builder.registerType(NavigationButtons).as<NavigationButtons>();
builder.registerType(ViewSelector).as<ViewSelector>();
builder.registerType(DragDropManager).as<DragDropManager>();
builder.registerType(AllDayManager).as<AllDayManager>();
builder.registerType(ResizeHandleManager).as<ResizeHandleManager>();
builder.registerType(EdgeScrollManager).as<EdgeScrollManager>();
builder.registerType(HeaderManager).as<HeaderManager>();
builder.registerType(CalendarManager).as<CalendarManager>();
builder.registerType(WorkweekPresets).as<WorkweekPresets>();
builder.registerType(ConfigManager).as<ConfigManager>();
builder.registerType(EventManager).as<EventManager>();
// Build the container
const app = builder.build();
// Initialize database and seed data BEFORE initializing managers
const indexedDBContext = app.resolveType<IndexedDBContext>();
await indexedDBContext.initialize();
const dataSeeder = app.resolveType<DataSeeder>();
await dataSeeder.seedIfEmpty();
// Get managers from container
const eb = app.resolveType<IEventBus>();
const calendarManager = app.resolveType<CalendarManager>();
const eventManager = app.resolveType<EventManager>();
const resizeHandleManager = app.resolveType<ResizeHandleManager>();
const headerManager = app.resolveType<HeaderManager>();
const dragDropManager = app.resolveType<DragDropManager>();
const viewSelectorManager = app.resolveType<ViewSelector>();
const navigationManager = app.resolveType<NavigationManager>();
const navigationButtonsManager = app.resolveType<NavigationButtons>();
const edgeScrollManager = app.resolveType<EdgeScrollManager>();
const allDayManager = app.resolveType<AllDayManager>();
const urlManager = app.resolveType<URLManager>();
const workweekPresetsManager = app.resolveType<WorkweekPresets>();
const configManager = app.resolveType<ConfigManager>();
// Initialize managers
await calendarManager.initialize?.();
await resizeHandleManager.initialize?.();
// Resolve AuditService (starts listening for entity events)
const auditService = app.resolveType<AuditService>();
// Resolve SyncManager (starts background sync automatically)
const syncManager = app.resolveType<SyncManager>();
// Handle deep linking after managers are initialized
await handleDeepLinking(eventManager, urlManager);
// Expose to window for debugging (with proper typing)
(window as Window & {
calendarDebug?: {
eventBus: typeof eventBus;
app: typeof app;
calendarManager: typeof calendarManager;
eventManager: typeof eventManager;
workweekPresetsManager: typeof workweekPresetsManager;
auditService: typeof auditService;
syncManager: typeof syncManager;
};
}).calendarDebug = {
eventBus,
app,
calendarManager,
eventManager,
workweekPresetsManager,
auditService,
syncManager,
};
} catch (error) {
throw error;
}
}
// Initialize when DOM is ready - now handles async properly
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
initializeCalendar().catch(error => {
console.error('Calendar initialization failed:', error);
});
});
} else {
initializeCalendar().catch(error => {
console.error('Calendar initialization failed:', error);
});
}
// Core exports
export { ViewTemplate, ViewConfig, GroupingConfig } from './core/ViewConfig';
export { IRenderer as Renderer, IRenderContext as RenderContext } from './core/IGroupingRenderer';
export { IGroupingStore } from './core/IGroupingStore';
export { CalendarOrchestrator } from './core/CalendarOrchestrator';
export { NavigationAnimator } from './core/NavigationAnimator';
export { buildPipeline, Pipeline } from './core/RenderBuilder';
// Feature exports
export { DateRenderer } from './features/date';
export { DateService } from './core/DateService';
export { ITimeFormatConfig } from './core/ITimeFormatConfig';
export { EventRenderer } from './features/event';
export { ResourceRenderer } from './features/resource';
export { TeamRenderer } from './features/team';
export { TimeAxisRenderer } from './features/timeaxis/TimeAxisRenderer';