Refactor CalendarOrchestrator with ts-linq-light

Replaces native array methods with ts-linq-light for improved functional programming
Simplifies data transformation and grouping logic
Enhances code readability and introduces more declarative data manipulation
This commit is contained in:
Janus C. H. Knudsen 2025-12-08 22:26:38 +01:00
parent 23fcaa9985
commit 27561750f8
4 changed files with 52 additions and 29 deletions

View file

@ -1,3 +1,4 @@
import { from } from 'ts-linq-light';
import { ViewConfig, GroupingConfig } from './ViewConfig';
import { RenderContext } from './RenderContext';
import { IGroupingRenderer } from './IGroupingRenderer';
@ -25,11 +26,11 @@ export class CalendarOrchestrator {
) {}
private getRenderer(type: string): IGroupingRenderer | undefined {
return this.renderers.find(r => r.type === type);
return from(this.renderers).firstOrDefault(r => r.type === type);
}
private getStore(type: string): IGroupingStore | undefined {
return this.stores.find(s => s.type === type);
return from(this.stores).firstOrDefault(s => s.type === type);
}
async render(viewConfig: ViewConfig, container: HTMLElement): Promise<void> {
@ -45,7 +46,7 @@ export class CalendarOrchestrator {
container.style.setProperty('--grid-columns', String(totalColumns));
const types = viewConfig.groupings.map(g => g.type);
const types = from(viewConfig.groupings).select(g => g.type).toArray();
headerContainer.dataset.levels = types.join(' ');
headerContainer.innerHTML = '';
@ -58,12 +59,8 @@ export class CalendarOrchestrator {
await this.eventRenderer.render(container, visibleDates);
}
/**
* Extract visible dates from view config
*/
private extractVisibleDates(viewConfig: ViewConfig): string[] {
const dateGrouping = viewConfig.groupings.find(g => g.type === 'date');
return dateGrouping?.values || [];
return from(viewConfig.groupings).firstOrDefault(g => g.type === 'date')?.values || [];
}
private fetchAllData(groupings: GroupingConfig[]): Map<string, GroupingData> {
@ -72,7 +69,7 @@ export class CalendarOrchestrator {
for (const g of groupings) {
if (g.type === 'date') {
result.set(g.type, {
items: g.values.map(v => ({ id: v, data: { id: v } })),
items: from(g.values).select(v => ({ id: v, data: { id: v } })).toArray(),
byParent: null
});
continue;
@ -81,10 +78,17 @@ export class CalendarOrchestrator {
const store = this.getStore(g.type);
if (!store) continue;
const rawItems = store.getByIds(g.values);
const items = rawItems.map((item: any) => ({ id: item.id, data: item }));
const byParent = g.parentKey
? this.groupBy(items, item => (item.data as any)[g.parentKey!])
: null;
const items = from(rawItems).select((item: any) => ({ id: item.id, data: item })).toArray();
let byParent: Map<string, { id: string; data: unknown }[]> | null = null;
if (g.parentKey) {
byParent = new Map();
const grouped = from(items)
.where(item => (item.data as any)[g.parentKey!] != null)
.groupBy(item => (item.data as any)[g.parentKey!] as string);
for (const group of grouped) {
byParent.set(group.key, group.toArray());
}
}
result.set(g.type, { items, byParent });
}
@ -108,24 +112,13 @@ export class CalendarOrchestrator {
? gData.byParent.get(parentId) ?? []
: gData.items;
return items.map(item => ({
return from(items).select(item => ({
type: g.type,
id: item.id,
data: item.data,
parentId,
children: this.buildHierarchy(groupings, data, level + 1, item.id)
}));
}
private groupBy<T>(items: T[], keyFn: (item: T) => string): Map<string, T[]> {
const map = new Map<string, T[]>();
for (const item of items) {
const key = keyFn(item);
if (key == null) continue;
if (!map.has(key)) map.set(key, []);
map.get(key)!.push(item);
}
return map;
})).toArray();
}
private countLeaves(nodes: HierarchyNode[]): number {