Refactor calendar rendering with RenderBuilder
Simplifies calendar rendering process by introducing a new RenderBuilder pattern Improves flexibility and modularity of grouping renderer chain Decouples rendering logic from specific grouping types Enables dynamic column span calculation and recursive rendering Reduces complexity in CalendarOrchestrator Enhances type safety and simplifies renderer interfaces
This commit is contained in:
parent
27561750f8
commit
a3a1b9a421
9 changed files with 230 additions and 155 deletions
82
src/v2/core/RenderBuilder.ts
Normal file
82
src/v2/core/RenderBuilder.ts
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
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;
|
||||
}
|
||||
|
||||
export interface RenderData {
|
||||
teams?: IEnumerable<unknown>;
|
||||
resources?: IEnumerable<unknown>;
|
||||
dates?: IEnumerable<unknown>;
|
||||
}
|
||||
|
||||
interface RenderLevel {
|
||||
renderer: IGroupingRenderer;
|
||||
items: IEnumerable<unknown>;
|
||||
}
|
||||
|
||||
export class RenderBuilder {
|
||||
private levels: RenderLevel[] = [];
|
||||
|
||||
constructor(
|
||||
private context: RenderContext,
|
||||
private data: RenderData
|
||||
) {}
|
||||
|
||||
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, this.data, 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;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue