diff --git a/src/v2/V2CompositionRoot.ts b/src/v2/V2CompositionRoot.ts index a71d912..a0112b4 100644 --- a/src/v2/V2CompositionRoot.ts +++ b/src/v2/V2CompositionRoot.ts @@ -1,5 +1,5 @@ import { Container } from '@novadi/core'; -import { Renderer } from './core/IGroupingRenderer'; +import { IRenderer } from './core/IGroupingRenderer'; import { IGroupingStore } from './core/IGroupingStore'; import { DateRenderer } from './features/date/DateRenderer'; import { DateService } from './core/DateService'; @@ -111,9 +111,9 @@ export function createV2Container(): Container { builder.registerType(EventRenderer).as(); // Renderers - registreres som Renderer (array injection til CalendarOrchestrator) - builder.registerType(DateRenderer).as(); - builder.registerType(ResourceRenderer).as(); - builder.registerType(TeamRenderer).as(); + builder.registerType(DateRenderer).as(); + builder.registerType(ResourceRenderer).as(); + builder.registerType(TeamRenderer).as(); // Stores - registreres som IGroupingStore builder.registerType(MockTeamStore).as(); diff --git a/src/v2/core/CalendarOrchestrator.ts b/src/v2/core/CalendarOrchestrator.ts index 09f9c87..b78b4c3 100644 --- a/src/v2/core/CalendarOrchestrator.ts +++ b/src/v2/core/CalendarOrchestrator.ts @@ -1,11 +1,11 @@ -import { Renderer, RenderContext } from './IGroupingRenderer'; +import { IRenderer, IRenderContext } from './IGroupingRenderer'; import { buildPipeline } from './RenderBuilder'; import { EventRenderer } from '../features/event/EventRenderer'; import { ViewConfig } from './ViewConfig'; export class CalendarOrchestrator { constructor( - private allRenderers: Renderer[], + private allRenderers: IRenderer[], private eventRenderer: EventRenderer ) {} @@ -22,7 +22,7 @@ export class CalendarOrchestrator { filter[grouping.type] = grouping.values; } - const context: RenderContext = { headerContainer, columnContainer, filter }; + const context: IRenderContext = { headerContainer, columnContainer, filter }; // Clear headerContainer.innerHTML = ''; @@ -41,18 +41,18 @@ export class CalendarOrchestrator { // Byg og kør pipeline const pipeline = buildPipeline(activeRenderers); - pipeline.run(context); + await pipeline.run(context); // Render events med hele filter (date + resource) await this.eventRenderer.render(container, filter); } - private selectRenderers(viewConfig: ViewConfig): Renderer[] { + private selectRenderers(viewConfig: ViewConfig): IRenderer[] { const types = viewConfig.groupings.map(g => g.type); // Sortér renderers i samme rækkefølge som viewConfig.groupings return types .map(type => this.allRenderers.find(r => r.type === type)) - .filter((r): r is Renderer => r !== undefined); + .filter((r): r is IRenderer => r !== undefined); } private calculateTotalColumns(viewConfig: ViewConfig): number { diff --git a/src/v2/core/IGroupingRenderer.ts b/src/v2/core/IGroupingRenderer.ts index c6e5453..5c44c1b 100644 --- a/src/v2/core/IGroupingRenderer.ts +++ b/src/v2/core/IGroupingRenderer.ts @@ -1,10 +1,10 @@ -export interface RenderContext { +export interface IRenderContext { headerContainer: HTMLElement; columnContainer: HTMLElement; filter: Record; // { team: ['alpha'], resource: ['alice', 'bob'], date: [...] } } -export interface Renderer { +export interface IRenderer { readonly type: string; - render(context: RenderContext): void; + render(context: IRenderContext): void | Promise; } diff --git a/src/v2/core/RenderBuilder.ts b/src/v2/core/RenderBuilder.ts index b745883..68f0ee3 100644 --- a/src/v2/core/RenderBuilder.ts +++ b/src/v2/core/RenderBuilder.ts @@ -1,14 +1,14 @@ -import { Renderer, RenderContext } from './IGroupingRenderer'; +import { IRenderer, IRenderContext } from './IGroupingRenderer'; export interface Pipeline { - run(context: RenderContext): void; + run(context: IRenderContext): Promise; } -export function buildPipeline(renderers: Renderer[]): Pipeline { +export function buildPipeline(renderers: IRenderer[]): Pipeline { return { - run(context: RenderContext) { + async run(context: IRenderContext) { for (const renderer of renderers) { - renderer.render(context); + await renderer.render(context); } } }; diff --git a/src/v2/demo/DemoApp.ts b/src/v2/demo/DemoApp.ts index da5ec78..d8e535a 100644 --- a/src/v2/demo/DemoApp.ts +++ b/src/v2/demo/DemoApp.ts @@ -73,7 +73,7 @@ export class DemoApp { return { templateId: 'day', groupings: [ - { type: 'resource', values: ['res1', 'res2'] }, + { type: 'resource', values: ['EMP001', 'EMP002'] }, { type: 'date', values: today } ] }; @@ -90,7 +90,7 @@ export class DemoApp { return { templateId: 'resource', groupings: [ - { type: 'resource', values: ['res1', 'res2'] }, + { type: 'resource', values: ['EMP001', 'EMP002'] }, { type: 'date', values: dates } ] }; diff --git a/src/v2/features/date/DateRenderer.ts b/src/v2/features/date/DateRenderer.ts index 87a4622..9295c4d 100644 --- a/src/v2/features/date/DateRenderer.ts +++ b/src/v2/features/date/DateRenderer.ts @@ -1,12 +1,12 @@ -import { Renderer, RenderContext } from '../../core/IGroupingRenderer'; +import { IRenderer, IRenderContext } from '../../core/IGroupingRenderer'; import { DateService } from '../../core/DateService'; -export class DateRenderer implements Renderer { +export class DateRenderer implements IRenderer { readonly type = 'date'; constructor(private dateService: DateService) {} - render(context: RenderContext): void { + render(context: IRenderContext): void { const dates = context.filter['date'] || []; const resourceIds = context.filter['resource'] || []; diff --git a/src/v2/features/resource/ResourceRenderer.ts b/src/v2/features/resource/ResourceRenderer.ts index 79e7ab0..4262d4c 100644 --- a/src/v2/features/resource/ResourceRenderer.ts +++ b/src/v2/features/resource/ResourceRenderer.ts @@ -1,31 +1,20 @@ -import { Renderer, RenderContext } from '../../core/IGroupingRenderer'; +import { IRenderer, IRenderContext } from '../../core/IGroupingRenderer'; +import { ResourceService } from '../../storage/resources/ResourceService'; -interface Resource { - id: string; - name: string; -} - -export class ResourceRenderer implements Renderer { +export class ResourceRenderer implements IRenderer { readonly type = 'resource'; - // Hardcoded data - private resources: Resource[] = [ - { id: 'res1', name: 'Anders' }, - { id: 'res2', name: 'Bente' }, - { id: 'res3', name: 'Carsten' } - ]; - - render(context: RenderContext): void { - const allowedIds = context.filter['resource'] || []; - const filteredResources = this.resources.filter(r => allowedIds.includes(r.id)); + constructor(private resourceService: ResourceService) {} + async render(context: IRenderContext): Promise { + const resourceIds = context.filter['resource'] || []; + const resources = await this.resourceService.getByIds(resourceIds); const dateCount = context.filter['date']?.length || 1; - // Render ALLE resource headers - for (const resource of filteredResources) { + for (const resource of resources) { const header = document.createElement('swp-resource-header'); header.dataset.resourceId = resource.id; - header.textContent = resource.name; + header.textContent = resource.displayName; header.style.gridColumn = `span ${dateCount}`; context.headerContainer.appendChild(header); } diff --git a/src/v2/features/team/TeamRenderer.ts b/src/v2/features/team/TeamRenderer.ts index 953f3b5..0b2a5d1 100644 --- a/src/v2/features/team/TeamRenderer.ts +++ b/src/v2/features/team/TeamRenderer.ts @@ -1,4 +1,4 @@ -import { Renderer, RenderContext } from '../../core/IGroupingRenderer'; +import { IRenderer, IRenderContext } from '../../core/IGroupingRenderer'; interface Team { id: string; @@ -6,7 +6,7 @@ interface Team { resourceIds: string[]; } -export class TeamRenderer implements Renderer { +export class TeamRenderer implements IRenderer { readonly type = 'team'; // Hardcoded data @@ -15,7 +15,7 @@ export class TeamRenderer implements Renderer { { id: 'team2', name: 'Team Beta', resourceIds: ['res3'] } ]; - render(context: RenderContext): void { + render(context: IRenderContext): void { const allowedIds = context.filter['team'] || []; const filteredTeams = this.teams.filter(t => allowedIds.includes(t.id)); diff --git a/src/v2/index.ts b/src/v2/index.ts index 5976bd8..6e390a0 100644 --- a/src/v2/index.ts +++ b/src/v2/index.ts @@ -1,6 +1,6 @@ // Core exports export { ViewTemplate, ViewConfig, GroupingConfig } from './core/ViewConfig'; -export { Renderer, RenderContext } from './core/IGroupingRenderer'; +export { IRenderer as Renderer, IRenderContext as RenderContext } from './core/IGroupingRenderer'; export { IGroupingStore } from './core/IGroupingStore'; export { CalendarOrchestrator } from './core/CalendarOrchestrator'; export { NavigationAnimator } from './core/NavigationAnimator'; diff --git a/src/v2/storage/resources/ResourceService.ts b/src/v2/storage/resources/ResourceService.ts index 7bd7f2e..769210c 100644 --- a/src/v2/storage/resources/ResourceService.ts +++ b/src/v2/storage/resources/ResourceService.ts @@ -22,6 +22,16 @@ export class ResourceService extends BaseEntityService { return all.filter(r => r.isActive !== false); } + /** + * Get resources by IDs + */ + async getByIds(ids: string[]): Promise { + if (ids.length === 0) return []; + + const results = await Promise.all(ids.map(id => this.get(id))); + return results.filter((r): r is IResource => r !== null); + } + /** * Get resources by type */