Add manufacturer catalog, category/manufacturer library management, and built-in cable flag
Normalizes manufacturer as a shared catalog entity (like device categories) instead of free text on each device, giving the admin duplicate-detection nudge a reliable signal. Adds full CRUD (including Admin direct-publish, bypassing the submission queue) for categories, manufacturers, port types, and cable types, plus a Categories & Manufacturers library modal and a browse-by-manufacturer/search view in the device palette. Adds Port.builtInCable so a captive/permanently-attached cable (a keyboard's USB lead, a budget AVR's power cord) can be flagged and excluded from the BOM. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017DUU6CnxECCDeqDNYJgr5x
This commit is contained in:
+26
-2
@@ -1,5 +1,5 @@
|
||||
import { v4 as uuid } from 'uuid'
|
||||
import type { CableType, Catalog, Device, DeviceCategoryDef, Diagram, DeviceTemplate, PortType } from './types'
|
||||
import type { CableType, Catalog, Device, DeviceCategoryDef, Diagram, DeviceTemplate, Manufacturer, PortType } from './types'
|
||||
|
||||
export function allPortTypes(catalog: Catalog): PortType[] {
|
||||
return catalog.portTypes
|
||||
@@ -35,6 +35,22 @@ export function deviceCategoryName(catalog: Catalog, categoryId: string): string
|
||||
return getDeviceCategory(catalog, categoryId)?.name ?? categoryId
|
||||
}
|
||||
|
||||
export function allManufacturers(catalog: Catalog): Manufacturer[] {
|
||||
return catalog.manufacturers
|
||||
}
|
||||
|
||||
export function getManufacturer(catalog: Catalog, manufacturerId: string): Manufacturer | undefined {
|
||||
return allManufacturers(catalog).find((m) => m.id === manufacturerId)
|
||||
}
|
||||
|
||||
/** Friendly name for a manufacturer id — unlike `deviceCategoryName`,
|
||||
* `manufacturerId` is optional (not every device has a known manufacturer),
|
||||
* so this returns undefined rather than a fallback string when it's unset
|
||||
* or, for older data, references a manufacturer that no longer exists. */
|
||||
export function manufacturerName(catalog: Catalog, manufacturerId: string | undefined): string | undefined {
|
||||
return manufacturerId ? getManufacturer(catalog, manufacturerId)?.name : undefined
|
||||
}
|
||||
|
||||
export function getPortType(catalog: Catalog, portTypeId: string): PortType | undefined {
|
||||
return allPortTypes(catalog).find((pt) => pt.id === portTypeId)
|
||||
}
|
||||
@@ -43,6 +59,14 @@ export function getCableType(catalog: Catalog, cableTypeId: string): CableType |
|
||||
return allCableTypes(catalog).find((ct) => ct.id === cableTypeId)
|
||||
}
|
||||
|
||||
/** Best-effort friendly label for a raw family string: the name of whichever
|
||||
* port type owns that family, or the raw string itself if none matches
|
||||
* (e.g. a family that only ever existed as hand-typed text, from before
|
||||
* FamilySelect started sourcing new families from an existing port type). */
|
||||
export function familyLabel(portTypes: PortType[], family: string): string {
|
||||
return portTypes.find((pt) => pt.family === family)?.name ?? family
|
||||
}
|
||||
|
||||
/** The set of connector families a port type will mate with: its own family
|
||||
* plus anything it explicitly lists as also-compatible. Shared with
|
||||
* `compatibility.ts` so "does A connect to B" and "which cable fits" agree. */
|
||||
@@ -145,7 +169,7 @@ export function createDeviceFromTemplate(template: DeviceTemplate, position: { x
|
||||
name: template.name,
|
||||
templateId: template.id,
|
||||
category: template.category,
|
||||
manufacturer: template.manufacturer,
|
||||
manufacturerId: template.manufacturerId,
|
||||
model: template.model,
|
||||
ports: template.ports.map((port) => ({ ...port, id: uuid() })),
|
||||
cost: template.cost,
|
||||
|
||||
Reference in New Issue
Block a user