28 lines
1.7 KiB
TypeScript
28 lines
1.7 KiB
TypeScript
import type { Employee, NormalizedOrgChartDataset, OrganizationTreeNode, OrgChartDataset } from './types.js';
|
|
|
|
/** Pure derivation for validated datasets. Multiple roots remain a forest. */
|
|
export function normalizeOrgChartDataset(data: OrgChartDataset): NormalizedOrgChartDataset {
|
|
const organizationsById = new Map(data.organizations.map(org => [org.id, org]));
|
|
const employeesByOrganization = new Map<string, Employee[]>(data.organizations.map(org => [org.id, []]));
|
|
for (const employee of data.employees) employeesByOrganization.get(employee.organizationId)?.push(employee);
|
|
const nodes = new Map<string, OrganizationTreeNode>(data.organizations.map(org => [org.id, { organization: org, children: [] }]));
|
|
const roots: OrganizationTreeNode[] = [];
|
|
for (const node of nodes.values()) {
|
|
if (node.organization.parentId === null) roots.push(node);
|
|
else nodes.get(node.organization.parentId)?.children.push(node);
|
|
}
|
|
const order = new Map((data.presentation?.organizationOrder ?? []).map((id, index) => [id, index]));
|
|
const compare = (a: OrganizationTreeNode, b: OrganizationTreeNode) => {
|
|
const aOrder = order.get(a.organization.id) ?? Infinity;
|
|
const bOrder = order.get(b.organization.id) ?? Infinity;
|
|
if (aOrder !== bOrder) return aOrder < bOrder ? -1 : 1;
|
|
const difference = a.organization.displayOrder - b.organization.displayOrder;
|
|
if (difference) return difference;
|
|
// Code-unit order is deterministic across environments and independent of locale.
|
|
return a.organization.id < b.organization.id ? -1 : a.organization.id > b.organization.id ? 1 : 0;
|
|
};
|
|
roots.sort(compare);
|
|
for (const node of nodes.values()) node.children.sort(compare);
|
|
return { roots, organizationsById, employeesByOrganization };
|
|
}
|