Calendar/src/v2/core/RenderBuilder.ts

74 lines
1.9 KiB
TypeScript
Raw Normal View History

import { from, IEnumerable } from 'ts-linq-light';
import { IGroupingRenderer, RenderContext } from './IGroupingRenderer';
export interface NextFunction {
count(items: IEnumerable<unknown>): number;
render(items: IEnumerable<unknown>): void;
}
interface RenderLevel {
renderer: IGroupingRenderer;
items: IEnumerable<unknown>;
}
export class RenderBuilder {
private levels: RenderLevel[] = [];
constructor(private context: RenderContext) {}
add(renderer: IGroupingRenderer, items: IEnumerable<unknown>): this {
this.levels.push({ renderer, items });
return this;
}
getTotalCount(): number {
if (this.levels.length === 0) return 0;
const chain = this.buildChain(0);
return chain.count(this.levels[0].items);
}
build(): void {
if (this.levels.length === 0) return;
const chain = this.buildChain(0);
chain.render(this.levels[0].items);
}
private buildChain(index: number): NextFunction {
if (index >= this.levels.length) {
// Leaf - ingen flere levels
return {
count: (items) => from(items).count(),
render: () => {}
};
}
const level = this.levels[index];
const nextChain = this.buildChain(index + 1);
return {
count: (items) => {
let total = 0;
for (const item of items) {
const childItems = this.getChildItems(index, item);
total += nextChain.count(childItems);
}
return total || from(items).count();
},
render: (items) => {
level.renderer.render(items, nextChain, this.context);
}
};
}
private getChildItems(levelIndex: number, _parentItem: unknown): IEnumerable<unknown> {
// Returnerer næste levels items - rendereren selv filtrerer baseret på parent
const nextLevel = this.levels[levelIndex + 1];
if (!nextLevel) {
return from([]);
}
return nextLevel.items;
}
}