112 lines
3.9 KiB
TypeScript
112 lines
3.9 KiB
TypeScript
export type SelectionEntry = {
|
|
id: string
|
|
path: string
|
|
requirementLabel: string
|
|
resolvedName: string
|
|
quantity?: number
|
|
_definition?: Record<string, any>
|
|
}
|
|
|
|
export type StructureSelectionResult = {
|
|
pieces: SelectionEntry[]
|
|
products: SelectionEntry[]
|
|
components: SelectionEntry[]
|
|
}
|
|
|
|
type CatalogMap = Map<string, { name?: string, [key: string]: any }>
|
|
|
|
type LabelResolvers = {
|
|
resolvePieceLabel: (definition: Record<string, any>) => string
|
|
resolveProductLabel: (definition: Record<string, any>) => string
|
|
resolveSubcomponentLabel: (definition: Record<string, any>) => string
|
|
}
|
|
|
|
const isNonEmptyString = (value: unknown): value is string =>
|
|
typeof value === 'string' && value.trim().length > 0
|
|
|
|
export function collectStructureSelections(
|
|
root: any,
|
|
catalogs: {
|
|
pieceCatalogMap: CatalogMap
|
|
productCatalogMap: CatalogMap
|
|
componentCatalogMap: CatalogMap
|
|
},
|
|
resolvers: LabelResolvers,
|
|
): StructureSelectionResult {
|
|
const piecesSelected: SelectionEntry[] = []
|
|
const productsSelected: SelectionEntry[] = []
|
|
const componentsSelected: SelectionEntry[] = []
|
|
|
|
if (!root || typeof root !== 'object') {
|
|
return { pieces: piecesSelected, products: productsSelected, components: componentsSelected }
|
|
}
|
|
|
|
const visitNode = (node: any, fallbackPath = 'racine') => {
|
|
if (!node || typeof node !== 'object') {
|
|
return
|
|
}
|
|
|
|
const nodePath = isNonEmptyString(node.path) ? node.path : fallbackPath
|
|
|
|
const nodePieces = Array.isArray(node.pieces) ? node.pieces : []
|
|
nodePieces.forEach((entry: any, index: number) => {
|
|
const selectedId = entry?.selectedPieceId
|
|
if (!isNonEmptyString(selectedId)) {
|
|
return
|
|
}
|
|
const definition = entry?.definition ?? entry
|
|
const catalogPiece = catalogs.pieceCatalogMap.get(selectedId)
|
|
piecesSelected.push({
|
|
id: selectedId,
|
|
path: isNonEmptyString(entry?.path) ? entry.path : `${nodePath}:piece-${index + 1}`,
|
|
requirementLabel: resolvers.resolvePieceLabel(definition),
|
|
resolvedName: catalogPiece?.name || selectedId,
|
|
quantity: typeof definition?.quantity === 'number' ? definition.quantity : undefined,
|
|
_definition: definition,
|
|
})
|
|
})
|
|
|
|
const nodeProducts = Array.isArray(node.products) ? node.products : []
|
|
nodeProducts.forEach((entry: any, index: number) => {
|
|
const selectedId = entry?.selectedProductId
|
|
if (!isNonEmptyString(selectedId)) {
|
|
return
|
|
}
|
|
const definition = entry?.definition ?? entry
|
|
const catalogProduct = catalogs.productCatalogMap.get(selectedId)
|
|
productsSelected.push({
|
|
id: selectedId,
|
|
path: isNonEmptyString(entry?.path) ? entry.path : `${nodePath}:product-${index + 1}`,
|
|
requirementLabel: resolvers.resolveProductLabel(definition),
|
|
resolvedName: catalogProduct?.name || selectedId,
|
|
})
|
|
})
|
|
|
|
const nodeChildren = Array.isArray(node.subcomponents)
|
|
? node.subcomponents
|
|
: Array.isArray(node.subComponents)
|
|
? node.subComponents
|
|
: []
|
|
|
|
nodeChildren.forEach((child: any, index: number) => {
|
|
const selectedId = child?.selectedComponentId
|
|
if (isNonEmptyString(selectedId)) {
|
|
const definition = child?.definition ?? child
|
|
const catalogComponent = catalogs.componentCatalogMap.get(selectedId)
|
|
componentsSelected.push({
|
|
id: selectedId,
|
|
path: isNonEmptyString(child?.path) ? child.path : `${nodePath}:subcomponent-${index + 1}`,
|
|
requirementLabel: resolvers.resolveSubcomponentLabel(definition),
|
|
resolvedName: catalogComponent?.name || selectedId,
|
|
})
|
|
}
|
|
|
|
visitNode(child, isNonEmptyString(child?.path) ? child.path : `${nodePath}:subcomponent-${index + 1}`)
|
|
})
|
|
}
|
|
|
|
visitNode(root, isNonEmptyString(root?.path) ? root.path : 'racine')
|
|
|
|
return { pieces: piecesSelected, products: productsSelected, components: componentsSelected }
|
|
}
|