Moving away from Azure Devops #1
10 changed files with 46 additions and 47 deletions
|
|
@ -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<EventRenderer>();
|
||||
|
||||
// Renderers - registreres som Renderer (array injection til CalendarOrchestrator)
|
||||
builder.registerType(DateRenderer).as<Renderer>();
|
||||
builder.registerType(ResourceRenderer).as<Renderer>();
|
||||
builder.registerType(TeamRenderer).as<Renderer>();
|
||||
builder.registerType(DateRenderer).as<IRenderer>();
|
||||
builder.registerType(ResourceRenderer).as<IRenderer>();
|
||||
builder.registerType(TeamRenderer).as<IRenderer>();
|
||||
|
||||
// Stores - registreres som IGroupingStore
|
||||
builder.registerType(MockTeamStore).as<IGroupingStore>();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
export interface RenderContext {
|
||||
export interface IRenderContext {
|
||||
headerContainer: HTMLElement;
|
||||
columnContainer: HTMLElement;
|
||||
filter: Record<string, string[]>; // { team: ['alpha'], resource: ['alice', 'bob'], date: [...] }
|
||||
}
|
||||
|
||||
export interface Renderer {
|
||||
export interface IRenderer {
|
||||
readonly type: string;
|
||||
render(context: RenderContext): void;
|
||||
render(context: IRenderContext): void | Promise<void>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<void>;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
]
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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'] || [];
|
||||
|
||||
|
|
|
|||
|
|
@ -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<void> {
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -22,6 +22,16 @@ export class ResourceService extends BaseEntityService<IResource> {
|
|||
return all.filter(r => r.isActive !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resources by IDs
|
||||
*/
|
||||
async getByIds(ids: string[]): Promise<IResource[]> {
|
||||
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
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue