Moving away from Azure Devops #1
5 changed files with 517 additions and 22 deletions
266
.workbench/inspiration.md
Normal file
266
.workbench/inspiration.md
Normal file
|
|
@ -0,0 +1,266 @@
|
||||||
|
Selvfølgelig—her er en **opdateret, selvstændig `.md`-spec**, som **understøtter variable antal resources per team**, dynamisk kolonnebredde, ingen inline layout-styles, pipeline‐rendering i grupper, og CSS-controlling via custom properties.
|
||||||
|
|
||||||
|
Kopier → gem som fx:
|
||||||
|
`grid-render-pipeline-dynamic-columns.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
````md
|
||||||
|
# Grid Render Pipeline — Dynamic Columns Spec
|
||||||
|
|
||||||
|
Denne specifikation beskriver en generisk render-pipeline til at bygge et
|
||||||
|
dynamisk CSS Grid layout, hvor hver "gruppe" (teams, resources, dates) har sin
|
||||||
|
egen renderer og pipeline-styring. Layoutet understøtter **variable antal
|
||||||
|
resources pr. team** og beregner automatisk antal kolonner. Ingen inline-styles
|
||||||
|
til positionering anvendes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ Formål
|
||||||
|
|
||||||
|
- Ét globalt CSS Grid.
|
||||||
|
- Variabelt antal resources pr. team → dynamisk antal kolonner.
|
||||||
|
- CSS-grid auto-placerer rækker.
|
||||||
|
- Ingen inline styling af layout (ingen `element.style.gridRow = ...`).
|
||||||
|
- CSS custom properties bruges til at definere dynamiske spænder.
|
||||||
|
- Renderere har ens interface og bindes i pipeline.
|
||||||
|
- `pipeline.run(ctx)` executer alle renderers i rækkefølge.
|
||||||
|
- Hver renderer kan hente sin egen data (API, async osv.).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧩 Data Model
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type DateString = string;
|
||||||
|
|
||||||
|
interface Resource {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
dates: DateString[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Team {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
resources: Resource[];
|
||||||
|
}
|
||||||
|
````
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧠 Context
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface RenderContext {
|
||||||
|
grid: HTMLElement; // root grid container
|
||||||
|
teams: Team[]; // data
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`grid` er HTML-elementet med `display:grid`, og `teams` er data.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 CSS Layout
|
||||||
|
|
||||||
|
Grid kolonner bestemmes dynamisk via CSS variablen `--total-cols`.
|
||||||
|
|
||||||
|
```css
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(var(--total-cols), minmax(0, 1fr));
|
||||||
|
gap: 6px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Teams (øverste række)
|
||||||
|
|
||||||
|
Hver team-header spænder **antal resources for team'et**:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.team-header {
|
||||||
|
grid-column: span var(--team-cols, 1);
|
||||||
|
font-weight: 700;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
padding: 4px 2px;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resources (2. række)
|
||||||
|
|
||||||
|
```css
|
||||||
|
.resource-cell {
|
||||||
|
padding: 4px 2px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dates (3. række)
|
||||||
|
|
||||||
|
```css
|
||||||
|
.dates-cell { padding: 2px 0; }
|
||||||
|
|
||||||
|
.dates-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 4px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-pill {
|
||||||
|
padding: 3px 6px;
|
||||||
|
background: #e3e3e3;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Beregning af kolonner
|
||||||
|
|
||||||
|
**Total cols = sum(resources.length for all teams)**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const totalCols = ctx.teams.reduce((sum, t) => sum + t.resources.length, 0);
|
||||||
|
ctx.grid.style.setProperty('--total-cols', totalCols.toString());
|
||||||
|
```
|
||||||
|
|
||||||
|
For hvert team defineres hvor mange kolonner det spænder:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
cell.style.setProperty('--team-cols', team.resources.length.toString());
|
||||||
|
```
|
||||||
|
|
||||||
|
> Bemærk: vi bruger **kun CSS vars** til layoutparametre – ikke inline
|
||||||
|
> grid-row/grid-column.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙ Renderer Interface
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface Renderer {
|
||||||
|
id: string;
|
||||||
|
next: Renderer | null;
|
||||||
|
render(ctx: RenderContext): void;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Factory
|
||||||
|
|
||||||
|
```ts
|
||||||
|
function createRenderer(id: string, fn: (ctx: RenderContext) => void): Renderer {
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
next: null,
|
||||||
|
render(ctx) {
|
||||||
|
fn(ctx);
|
||||||
|
if (this.next) this.next.render(ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧱 De tre render-lag (grupper)
|
||||||
|
|
||||||
|
### Teams
|
||||||
|
|
||||||
|
* Appender én `.team-header` per team.
|
||||||
|
* Sætter `--team-cols`.
|
||||||
|
|
||||||
|
### Resources
|
||||||
|
|
||||||
|
* Appender én `.resource-cell` per resource.
|
||||||
|
* Foregår i teams-orden → CSS auto-row sørger for næste række.
|
||||||
|
|
||||||
|
### Dates
|
||||||
|
|
||||||
|
* Appender én `.dates-cell` per resource.
|
||||||
|
* Hver celle indeholder flere `.date-pill`.
|
||||||
|
|
||||||
|
Append-rækkefølge giver 3 rækker automatisk:
|
||||||
|
|
||||||
|
1. teams, 2) resources, 3) dates.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔗 Pipeline
|
||||||
|
|
||||||
|
```ts
|
||||||
|
function buildPipeline(renderers: Renderer[]) {
|
||||||
|
for (let i = 0; i < renderers.length - 1; i++) {
|
||||||
|
renderers[i].next = renderers[i + 1];
|
||||||
|
}
|
||||||
|
const first = renderers[0] ?? null;
|
||||||
|
return {
|
||||||
|
run(ctx: RenderContext) {
|
||||||
|
if (first) first.render(ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Brug
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const pipeline = buildPipeline([
|
||||||
|
teamsRenderer,
|
||||||
|
resourcesRenderer,
|
||||||
|
datesRenderer
|
||||||
|
]);
|
||||||
|
|
||||||
|
pipeline.run(ctx);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Kørsel
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// 1) beregn total kolonner
|
||||||
|
const totalCols = ctx.teams.reduce((sum, t) => sum + t.resources.length, 0);
|
||||||
|
ctx.grid.style.setProperty('--total-cols', totalCols);
|
||||||
|
|
||||||
|
// 2) pipeline
|
||||||
|
pipeline.run(ctx);
|
||||||
|
```
|
||||||
|
|
||||||
|
CSS klarer resten.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧽 Principper
|
||||||
|
|
||||||
|
* **Ingen inline style-positionering**.
|
||||||
|
* **CSS Grid** owner layout.
|
||||||
|
* **JS** owner data & rækkefølge.
|
||||||
|
* **Renderers** er udskiftelige og genbrugelige.
|
||||||
|
* **Append i grupper** = rækker automatisk.
|
||||||
|
* **CSS vars** styrer spans dynamisk.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✔ TL;DR
|
||||||
|
|
||||||
|
* Grid-cols bestemmes ud fra data.
|
||||||
|
* Team-header `span = resources.length`.
|
||||||
|
* Append rækkefølge = rækker.
|
||||||
|
* Renderere i pipeline.
|
||||||
|
* Ingen koordinater, ingen inline layout-styles.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```
|
||||||
246
.workbench/plan-comparison.md
Normal file
246
.workbench/plan-comparison.md
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
# Plan Sammenligning: Spec vs Min Plan
|
||||||
|
|
||||||
|
## 1. Grid Container
|
||||||
|
|
||||||
|
| Spec | Min Plan | Kommentar |
|
||||||
|
|------|----------|-----------|
|
||||||
|
| Ét grid (`ctx.grid`) | To containers (`headerContainer` + `columnContainer`) | **Afvigelse:** Vi har 2 containers for at understøtte header drawer og sticky headers. Spec'en bruger ét grid hvor append-rækkefølge = rækker. |
|
||||||
|
|
||||||
|
**Spørgsmål:** Er 2 containers ok, eller skal vi følge spec'en med ét grid?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. RenderContext
|
||||||
|
|
||||||
|
| Spec | Min Plan |
|
||||||
|
|------|----------|
|
||||||
|
| `{ grid: HTMLElement, teams: Team[] }` | `{ headerContainer: HTMLElement, columnContainer: HTMLElement }` |
|
||||||
|
|
||||||
|
**Spec:**
|
||||||
|
```typescript
|
||||||
|
interface RenderContext {
|
||||||
|
grid: HTMLElement;
|
||||||
|
teams: Team[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Min plan:**
|
||||||
|
```typescript
|
||||||
|
interface RenderContext {
|
||||||
|
headerContainer: HTMLElement;
|
||||||
|
columnContainer: HTMLElement;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kommentar:** Spec'en har `teams` data i context. Min plan har ingen data i context - renderers henter selv. Er det korrekt at fjerne data fra context?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Data Model
|
||||||
|
|
||||||
|
| Spec | Min Plan |
|
||||||
|
|------|----------|
|
||||||
|
| Nested: `team.resources[]`, `resource.dates[]` | Flad med id-relationer, renderers henter selv |
|
||||||
|
|
||||||
|
**Spec:**
|
||||||
|
```typescript
|
||||||
|
interface Team {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
resources: Resource[]; // nested
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Min plan:**
|
||||||
|
```typescript
|
||||||
|
// Hardcoded i renderer
|
||||||
|
private resourcesByTeam = {
|
||||||
|
'team1': ['res1', 'res2'], // kun ids
|
||||||
|
'team2': ['res3']
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kommentar:** Spec'en har nested data. Min plan bruger id-relationer og renderers slår selv op. Begge dele virker - min plan er mere fleksibel for store datasets.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Renderer Interface
|
||||||
|
|
||||||
|
| Spec | Min Plan |
|
||||||
|
|------|----------|
|
||||||
|
| `render(ctx): void` | `render(ids, next, context): void` |
|
||||||
|
|
||||||
|
**Spec:**
|
||||||
|
```typescript
|
||||||
|
interface Renderer {
|
||||||
|
id: string;
|
||||||
|
next: Renderer | null;
|
||||||
|
render(ctx: RenderContext): void;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Min plan:**
|
||||||
|
```typescript
|
||||||
|
interface IGroupingRenderer {
|
||||||
|
readonly type: string;
|
||||||
|
count?(ids: string[], next: NextFunction): number;
|
||||||
|
render(ids: string[], next: NextFunction, context: RenderContext): void;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kommentar:**
|
||||||
|
- Spec'en: Renderer har `next` som property, kalder selv `this.next.render(ctx)`
|
||||||
|
- Min plan: `next` kommer som parameter, kalder `next.render(ids)`
|
||||||
|
|
||||||
|
Min plan sender ids eksplicit. Spec'en bruger nested data så ids er unødvendige.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Pipeline / Builder
|
||||||
|
|
||||||
|
| Spec | Min Plan |
|
||||||
|
|------|----------|
|
||||||
|
| `buildPipeline()` linker `renderer.next` | `RenderBuilder` med `buildChain()` |
|
||||||
|
|
||||||
|
**Spec:**
|
||||||
|
```typescript
|
||||||
|
function buildPipeline(renderers: Renderer[]) {
|
||||||
|
for (let i = 0; i < renderers.length - 1; i++) {
|
||||||
|
renderers[i].next = renderers[i + 1];
|
||||||
|
}
|
||||||
|
return { run(ctx) { first.render(ctx); } };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Min plan:**
|
||||||
|
```typescript
|
||||||
|
class RenderBuilder {
|
||||||
|
add(renderer): this { ... }
|
||||||
|
build(startIds): void { ... }
|
||||||
|
private buildChain(index): NextFunction { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kommentar:** Samme koncept, forskellig implementering. Spec'en muterer renderers (`next` property). Min plan bruger closures (functional chain).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Colspan Beregning
|
||||||
|
|
||||||
|
| Spec | Min Plan |
|
||||||
|
|------|----------|
|
||||||
|
| Beregnes før render: `team.resources.length` | Beregnes via `next.count()` |
|
||||||
|
|
||||||
|
**Spec:**
|
||||||
|
```typescript
|
||||||
|
// I renderer
|
||||||
|
cell.style.setProperty('--team-cols', team.resources.length.toString());
|
||||||
|
```
|
||||||
|
|
||||||
|
**Min plan:**
|
||||||
|
```typescript
|
||||||
|
// I renderer
|
||||||
|
const colspan = next.count(resourceIds);
|
||||||
|
cell.style.setProperty('--team-cols', String(colspan));
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kommentar:** Spec'en ved colspan direkte fra nested data. Min plan kalder `next.count()` rekursivt for at beregne. Resultat er det samme.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. CSS Custom Properties
|
||||||
|
|
||||||
|
| Spec | Min Plan |
|
||||||
|
|------|----------|
|
||||||
|
| `--total-cols`, `--team-cols` | `--grid-columns`, `--team-cols` |
|
||||||
|
|
||||||
|
**Kommentar:** Næsten identisk. Begge bruger CSS vars til dynamisk colspan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Append Rækkefølge
|
||||||
|
|
||||||
|
| Spec | Min Plan |
|
||||||
|
|------|----------|
|
||||||
|
| Alle teams → alle resources → alle dates | Per team: resources → dates |
|
||||||
|
|
||||||
|
**Spec flow:**
|
||||||
|
```
|
||||||
|
TeamRenderer: append team1, team2, team3 headers
|
||||||
|
ResourceRenderer: append res1, res2, res3, res4 headers
|
||||||
|
DateRenderer: append alle dates
|
||||||
|
```
|
||||||
|
|
||||||
|
**Min plan flow:**
|
||||||
|
```
|
||||||
|
TeamRenderer:
|
||||||
|
append team1 header → next.render(['res1','res2'])
|
||||||
|
ResourceRenderer: append res1 → next.render(dates)
|
||||||
|
append res2 → next.render(dates)
|
||||||
|
append team2 header → next.render(['res3'])
|
||||||
|
ResourceRenderer: append res3 → next.render(dates)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kommentar:** Dette er en **væsentlig forskel**.
|
||||||
|
|
||||||
|
Spec'en renderer alle teams først, så alle resources, så alle dates - CSS grid auto-row placerer dem.
|
||||||
|
|
||||||
|
Min plan renderer nested: team1 → team1's resources → team1's dates → team2 → osv.
|
||||||
|
|
||||||
|
**Spørgsmål:** Hvilken approach foretrækker du? Spec'ens "lag for lag" eller min "nested traversal"?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Hvem kalder next?
|
||||||
|
|
||||||
|
| Spec | Min Plan |
|
||||||
|
|------|----------|
|
||||||
|
| Renderer kalder `this.next.render(ctx)` efter egen render | Renderer kalder `next.render(ids)` per item |
|
||||||
|
|
||||||
|
**Spec:**
|
||||||
|
```typescript
|
||||||
|
render(ctx) {
|
||||||
|
// render alle teams
|
||||||
|
for (const team of ctx.teams) { ... }
|
||||||
|
// derefter kald next
|
||||||
|
if (this.next) this.next.render(ctx);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Min plan:**
|
||||||
|
```typescript
|
||||||
|
render(ids, next, context) {
|
||||||
|
for (const id of ids) {
|
||||||
|
// render ét team
|
||||||
|
next.render(childIds); // kald next PER team
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kommentar:** Spec'en kalder next ÉN gang efter alle items. Min plan kalder next PER item. Dette hænger sammen med punkt 8.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Opsummering af Afvigelser
|
||||||
|
|
||||||
|
| # | Emne | Status |
|
||||||
|
|---|------|--------|
|
||||||
|
| 1 | 2 containers vs 1 grid | **Accepteret** (header drawer) |
|
||||||
|
| 2 | Data i context | **Afvigelse** - fjernet |
|
||||||
|
| 3 | Nested vs flad data | **Accepteret** (id-relationer) |
|
||||||
|
| 4 | next som parameter vs property | **Afvigelse** - funktionel |
|
||||||
|
| 5 | Pipeline implementation | Lignende |
|
||||||
|
| 6 | Colspan beregning | Lignende |
|
||||||
|
| 7 | CSS vars | Identisk |
|
||||||
|
| 8 | Render rækkefølge | **Væsentlig afvigelse** |
|
||||||
|
| 9 | Hvornår next kaldes | **Væsentlig afvigelse** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Åbne Spørgsmål
|
||||||
|
|
||||||
|
1. **Render rækkefølge:** Skal vi følge spec'ens "lag for lag" approach, eller er "nested traversal" ok?
|
||||||
|
|
||||||
|
2. **Context data:** Spec'en har `teams` i context. Skal vi have noget data i context, eller er det ok at renderers henter selv?
|
||||||
|
|
||||||
|
3. **2 containers:** Er det ok at beholde 2 containers for header drawer support?
|
||||||
|
|
@ -2,7 +2,7 @@ import { from } from 'ts-linq-light';
|
||||||
import { ViewConfig } from './ViewConfig';
|
import { ViewConfig } from './ViewConfig';
|
||||||
import { IGroupingRenderer, RenderContext } from './IGroupingRenderer';
|
import { IGroupingRenderer, RenderContext } from './IGroupingRenderer';
|
||||||
import { IGroupingStore } from './IGroupingStore';
|
import { IGroupingStore } from './IGroupingStore';
|
||||||
import { RenderBuilder, RenderData } from './RenderBuilder';
|
import { RenderBuilder } from './RenderBuilder';
|
||||||
import { EventRenderer } from '../features/event/EventRenderer';
|
import { EventRenderer } from '../features/event/EventRenderer';
|
||||||
|
|
||||||
export class CalendarOrchestrator {
|
export class CalendarOrchestrator {
|
||||||
|
|
@ -37,15 +37,8 @@ export class CalendarOrchestrator {
|
||||||
const types = from(viewConfig.groupings).select(g => g.type).toArray();
|
const types = from(viewConfig.groupings).select(g => g.type).toArray();
|
||||||
headerContainer.dataset.levels = types.join(' ');
|
headerContainer.dataset.levels = types.join(' ');
|
||||||
|
|
||||||
// Hent alt data
|
|
||||||
const data: RenderData = {
|
|
||||||
teams: this.getItems('team', viewConfig),
|
|
||||||
resources: this.getItems('resource', viewConfig),
|
|
||||||
dates: this.getItems('date', viewConfig)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Byg renderer chain
|
// Byg renderer chain
|
||||||
const builder = new RenderBuilder(context, data);
|
const builder = new RenderBuilder(context);
|
||||||
|
|
||||||
for (const grouping of viewConfig.groupings) {
|
for (const grouping of viewConfig.groupings) {
|
||||||
const renderer = this.getRenderer(grouping.type);
|
const renderer = this.getRenderer(grouping.type);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { IEnumerable } from 'ts-linq-light';
|
import { IEnumerable } from 'ts-linq-light';
|
||||||
import { NextFunction, RenderData } from './RenderBuilder';
|
import { NextFunction } from './RenderBuilder';
|
||||||
|
|
||||||
export interface RenderContext {
|
export interface RenderContext {
|
||||||
headerContainer: HTMLElement;
|
headerContainer: HTMLElement;
|
||||||
|
|
@ -10,7 +10,6 @@ export interface IGroupingRenderer<T = unknown> {
|
||||||
readonly type: string;
|
readonly type: string;
|
||||||
render(
|
render(
|
||||||
items: IEnumerable<T>,
|
items: IEnumerable<T>,
|
||||||
data: RenderData,
|
|
||||||
next: NextFunction,
|
next: NextFunction,
|
||||||
context: RenderContext
|
context: RenderContext
|
||||||
): void;
|
): void;
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,6 @@ export interface NextFunction {
|
||||||
render(items: IEnumerable<unknown>): void;
|
render(items: IEnumerable<unknown>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RenderData {
|
|
||||||
teams?: IEnumerable<unknown>;
|
|
||||||
resources?: IEnumerable<unknown>;
|
|
||||||
dates?: IEnumerable<unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface RenderLevel {
|
interface RenderLevel {
|
||||||
renderer: IGroupingRenderer;
|
renderer: IGroupingRenderer;
|
||||||
items: IEnumerable<unknown>;
|
items: IEnumerable<unknown>;
|
||||||
|
|
@ -20,10 +14,7 @@ interface RenderLevel {
|
||||||
export class RenderBuilder {
|
export class RenderBuilder {
|
||||||
private levels: RenderLevel[] = [];
|
private levels: RenderLevel[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(private context: RenderContext) {}
|
||||||
private context: RenderContext,
|
|
||||||
private data: RenderData
|
|
||||||
) {}
|
|
||||||
|
|
||||||
add(renderer: IGroupingRenderer, items: IEnumerable<unknown>): this {
|
add(renderer: IGroupingRenderer, items: IEnumerable<unknown>): this {
|
||||||
this.levels.push({ renderer, items });
|
this.levels.push({ renderer, items });
|
||||||
|
|
@ -66,7 +57,7 @@ export class RenderBuilder {
|
||||||
return total || from(items).count();
|
return total || from(items).count();
|
||||||
},
|
},
|
||||||
render: (items) => {
|
render: (items) => {
|
||||||
level.renderer.render(items, this.data, nextChain, this.context);
|
level.renderer.render(items, nextChain, this.context);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue