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:
parent
12e7594f30
commit
ceb44446f0
97 changed files with 13858 additions and 1 deletions
91
packages/calendar/src/core/BaseGroupingRenderer.ts
Normal file
91
packages/calendar/src/core/BaseGroupingRenderer.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import { IRenderer, IRenderContext } from './IGroupingRenderer';
|
||||
|
||||
/**
|
||||
* Entity must have id
|
||||
*/
|
||||
export interface IGroupingEntity {
|
||||
id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for a grouping renderer
|
||||
*/
|
||||
export interface IGroupingRendererConfig {
|
||||
elementTag: string; // e.g., 'swp-team-header'
|
||||
idAttribute: string; // e.g., 'teamId' -> data-team-id
|
||||
colspanVar: string; // e.g., '--team-cols'
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract base class for grouping renderers
|
||||
*
|
||||
* Handles:
|
||||
* - Fetching entities by IDs
|
||||
* - Calculating colspan from parentChildMap
|
||||
* - Creating header elements
|
||||
* - Appending to container
|
||||
*
|
||||
* Subclasses override:
|
||||
* - renderHeader() for custom content
|
||||
* - getDisplayName() for entity display text
|
||||
*/
|
||||
export abstract class BaseGroupingRenderer<T extends IGroupingEntity> implements IRenderer {
|
||||
abstract readonly type: string;
|
||||
protected abstract readonly config: IGroupingRendererConfig;
|
||||
|
||||
/**
|
||||
* Fetch entities from service
|
||||
*/
|
||||
protected abstract getEntities(ids: string[]): Promise<T[]>;
|
||||
|
||||
/**
|
||||
* Get display name for entity
|
||||
*/
|
||||
protected abstract getDisplayName(entity: T): string;
|
||||
|
||||
/**
|
||||
* Main render method - handles common logic
|
||||
*/
|
||||
async render(context: IRenderContext): Promise<void> {
|
||||
const allowedIds = context.filter[this.type] || [];
|
||||
if (allowedIds.length === 0) return;
|
||||
|
||||
const entities = await this.getEntities(allowedIds);
|
||||
const dateCount = context.filter['date']?.length || 1;
|
||||
const childIds = context.childType ? context.filter[context.childType] || [] : [];
|
||||
|
||||
for (const entity of entities) {
|
||||
const entityChildIds = context.parentChildMap?.[entity.id] || [];
|
||||
const childCount = entityChildIds.filter(id => childIds.includes(id)).length;
|
||||
const colspan = childCount * dateCount;
|
||||
|
||||
const header = document.createElement(this.config.elementTag);
|
||||
header.dataset[this.config.idAttribute] = entity.id;
|
||||
header.style.setProperty(this.config.colspanVar, String(colspan));
|
||||
|
||||
// Allow subclass to customize header content
|
||||
this.renderHeader(entity, header, context);
|
||||
|
||||
context.headerContainer.appendChild(header);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method for custom header rendering
|
||||
* Default: just sets textContent to display name
|
||||
*/
|
||||
protected renderHeader(entity: T, header: HTMLElement, _context: IRenderContext): void {
|
||||
header.textContent = this.getDisplayName(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to render a single entity header.
|
||||
* Can be used by subclasses that override render() but want consistent header creation.
|
||||
*/
|
||||
protected createHeader(entity: T, context: IRenderContext): HTMLElement {
|
||||
const header = document.createElement(this.config.elementTag);
|
||||
header.dataset[this.config.idAttribute] = entity.id;
|
||||
this.renderHeader(entity, header, context);
|
||||
return header;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue