2025-12-09 00:51:41 +01:00
|
|
|
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[] = [];
|
|
|
|
|
|
2025-12-09 15:24:19 +01:00
|
|
|
constructor(private context: RenderContext) {}
|
2025-12-09 00:51:41 +01:00
|
|
|
|
|
|
|
|
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) => {
|
2025-12-09 15:24:19 +01:00
|
|
|
level.renderer.render(items, nextChain, this.context);
|
2025-12-09 00:51:41 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|