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
|
|
@ -1,14 +1,20 @@
|
|||
import { IGroupingRenderer } from '../../core/IGroupingRenderer';
|
||||
import { RenderContext } from '../../core/RenderContext';
|
||||
import { IEnumerable } from 'ts-linq-light';
|
||||
import { IGroupingRenderer, RenderContext } from '../../core/IGroupingRenderer';
|
||||
import { NextFunction, RenderData } from '../../core/RenderBuilder';
|
||||
import { DateService } from '../../core/DateService';
|
||||
|
||||
export class DateRenderer implements IGroupingRenderer {
|
||||
export class DateRenderer implements IGroupingRenderer<string> {
|
||||
readonly type = 'date';
|
||||
|
||||
constructor(private dateService: DateService) {}
|
||||
|
||||
render(context: RenderContext): void {
|
||||
for (const dateStr of context.values) {
|
||||
render(
|
||||
dates: IEnumerable<string>,
|
||||
_data: RenderData,
|
||||
_next: NextFunction,
|
||||
context: RenderContext
|
||||
): void {
|
||||
for (const dateStr of dates) {
|
||||
const date = this.dateService.parseISO(dateStr);
|
||||
|
||||
const headerCell = document.createElement('swp-day-header');
|
||||
|
|
@ -21,9 +27,10 @@ export class DateRenderer implements IGroupingRenderer {
|
|||
|
||||
const column = document.createElement('swp-day-column');
|
||||
column.dataset.date = dateStr;
|
||||
if (context.parentId) column.dataset.parentId = context.parentId;
|
||||
column.innerHTML = '<swp-events-layer></swp-events-layer>';
|
||||
context.columnContainer.appendChild(column);
|
||||
|
||||
// Leaf renderer - ingen next.render() kald
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,37 @@
|
|||
import { IGroupingRenderer } from '../../core/IGroupingRenderer';
|
||||
import { RenderContext } from '../../core/RenderContext';
|
||||
import { from, IEnumerable } from 'ts-linq-light';
|
||||
import { IGroupingRenderer, RenderContext } from '../../core/IGroupingRenderer';
|
||||
import { NextFunction, RenderData } from '../../core/RenderBuilder';
|
||||
|
||||
export class ResourceRenderer implements IGroupingRenderer {
|
||||
interface Resource {
|
||||
id: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export class ResourceRenderer implements IGroupingRenderer<Resource> {
|
||||
readonly type = 'resource';
|
||||
|
||||
render(context: RenderContext): void {
|
||||
for (const resourceId of context.values) {
|
||||
render(
|
||||
resources: IEnumerable<Resource>,
|
||||
data: RenderData,
|
||||
next: NextFunction,
|
||||
context: RenderContext
|
||||
): void {
|
||||
const dates = data.dates || from([]);
|
||||
|
||||
for (const resource of resources) {
|
||||
const colspan = next.count(dates);
|
||||
|
||||
const cell = document.createElement('swp-resource-header');
|
||||
cell.dataset.resourceId = resourceId;
|
||||
cell.textContent = resourceId;
|
||||
if (context.colspan > 1) cell.style.gridColumn = `span ${context.colspan}`;
|
||||
cell.dataset.resourceId = resource.id;
|
||||
cell.textContent = resource.name || resource.id;
|
||||
|
||||
if (colspan > 1) {
|
||||
cell.style.gridColumn = `span ${colspan}`;
|
||||
}
|
||||
|
||||
context.headerContainer.appendChild(cell);
|
||||
|
||||
next.render(dates);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,47 @@
|
|||
import { IGroupingRenderer } from '../../core/IGroupingRenderer';
|
||||
import { RenderContext } from '../../core/RenderContext';
|
||||
import { from, IEnumerable } from 'ts-linq-light';
|
||||
import { IGroupingRenderer, RenderContext } from '../../core/IGroupingRenderer';
|
||||
import { NextFunction, RenderData } from '../../core/RenderBuilder';
|
||||
|
||||
export class TeamRenderer implements IGroupingRenderer {
|
||||
interface Team {
|
||||
id: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
interface Resource {
|
||||
id: string;
|
||||
teamId?: string;
|
||||
}
|
||||
|
||||
export class TeamRenderer implements IGroupingRenderer<Team> {
|
||||
readonly type = 'team';
|
||||
|
||||
render(context: RenderContext): void {
|
||||
for (const teamId of context.values) {
|
||||
render(
|
||||
teams: IEnumerable<Team>,
|
||||
data: RenderData,
|
||||
next: NextFunction,
|
||||
context: RenderContext
|
||||
): void {
|
||||
const resources = data.resources as IEnumerable<Resource> || from([]);
|
||||
const resourcesByTeam = from(resources).groupBy((r: Resource) => r.teamId || '');
|
||||
|
||||
for (const team of teams) {
|
||||
const teamResources = from(resourcesByTeam)
|
||||
.firstOrDefault(g => g.key === team.id);
|
||||
|
||||
const teamResourcesEnum = teamResources ? from(teamResources) : from([]);
|
||||
const colspan = next.count(teamResourcesEnum);
|
||||
|
||||
const cell = document.createElement('swp-team-header');
|
||||
cell.dataset.teamId = teamId;
|
||||
cell.textContent = teamId;
|
||||
if (context.colspan > 1) cell.style.gridColumn = `span ${context.colspan}`;
|
||||
cell.dataset.teamId = team.id;
|
||||
cell.textContent = team.name || team.id;
|
||||
|
||||
if (colspan > 1) {
|
||||
cell.style.gridColumn = `span ${colspan}`;
|
||||
}
|
||||
|
||||
context.headerContainer.appendChild(cell);
|
||||
|
||||
next.render(teamResourcesEnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue