Sets up calendar package with core infrastructure

Adds core calendar package components including:
- Base services for events, resources, and settings
- Calendar app and orchestrator
- Build and bundling configuration
- IndexedDB storage setup

Prepares foundational architecture for calendar functionality
This commit is contained in:
Janus C. H. Knudsen 2026-01-28 15:24:03 +01:00
parent 12e7594f30
commit ceb44446f0
97 changed files with 13858 additions and 1 deletions

View file

@ -0,0 +1,69 @@
import { IRenderContext } from '../../core/IGroupingRenderer';
import { BaseGroupingRenderer, IGroupingRendererConfig } from '../../core/BaseGroupingRenderer';
import { ResourceService } from '../../storage/resources/ResourceService';
import { IResource } from '../../types/CalendarTypes';
export class ResourceRenderer extends BaseGroupingRenderer<IResource> {
readonly type = 'resource';
protected readonly config: IGroupingRendererConfig = {
elementTag: 'swp-resource-header',
idAttribute: 'resourceId',
colspanVar: '--resource-cols'
};
constructor(private resourceService: ResourceService) {
super();
}
protected getEntities(ids: string[]): Promise<IResource[]> {
return this.resourceService.getByIds(ids);
}
protected getDisplayName(entity: IResource): string {
return entity.displayName;
}
/**
* Override render to handle:
* 1. Special ordering when parentChildMap exists (resources grouped by parent)
* 2. Different colspan calculation (just dateCount, not childCount * dateCount)
*/
async render(context: IRenderContext): Promise<void> {
const resourceIds = context.filter['resource'] || [];
const dateCount = context.filter['date']?.length || 1;
// Determine render order based on parentChildMap
// If parentChildMap exists, render resources grouped by parent (e.g., team)
// Otherwise, render in filter order
let orderedResourceIds: string[];
if (context.parentChildMap) {
// Render resources in parent-child order
orderedResourceIds = [];
for (const childIds of Object.values(context.parentChildMap)) {
for (const childId of childIds) {
if (resourceIds.includes(childId)) {
orderedResourceIds.push(childId);
}
}
}
} else {
orderedResourceIds = resourceIds;
}
const resources = await this.getEntities(orderedResourceIds);
// Create a map for quick lookup to preserve order
const resourceMap = new Map(resources.map(r => [r.id, r]));
for (const resourceId of orderedResourceIds) {
const resource = resourceMap.get(resourceId);
if (!resource) continue;
const header = this.createHeader(resource, context);
header.style.gridColumn = `span ${dateCount}`;
context.headerContainer.appendChild(header);
}
}
}