From 45e89dec4f7e2ad36be1f59f78959a633a1b2f16 Mon Sep 17 00:00:00 2001 From: Sven-Ric Date: Wed, 16 Sep 2026 09:41:59 +0200 Subject: [PATCH 1/2] Sort EOL systems to the bottom of the list --- src/model/catalog.test.ts | 18 +++++++++++++++++- src/model/catalog.ts | 24 +++++++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/model/catalog.test.ts b/src/model/catalog.test.ts index 79f02f8..31b49ab 100644 --- a/src/model/catalog.test.ts +++ b/src/model/catalog.test.ts @@ -276,11 +276,27 @@ describe('helpers', () => { expect(switchesForRole('spine').map((i) => i.id)).toContain('switch-as7726') expect(switchesForRole('spine').map((i) => i.id)).not.toContain('switch-as4630') expect(serversForUsage('management').map((i) => i.id)).toEqual([ - 'server-mgmt', 'server-mgmt-121h', + 'server-mgmt', ]) }) + it('sorts eol and withdrawn hardware to the bottom', () => { + // These lists contain eol/withdrawn models today; the other roles and + // usages sort through the same comparator. + const lists = [ + serversForUsage('worker'), + serversForUsage('management'), + switchesForRole('leaf'), + ] + for (const list of lists) { + const current = list.filter((i) => (i.availability ?? 'current') === 'current') + const eol = list.filter((i) => i.availability === 'eol') + const withdrawn = list.filter((i) => i.availability === 'withdrawn') + expect(list).toEqual([...current, ...eol, ...withdrawn]) + } + }) + it('offers GPUs only for GPU-capable servers', () => { expect(gpusForServer('server-microcloud-x13').length).toBeGreaterThan(0) expect(gpusForServer('server-bigtwin-x11')).toEqual([]) diff --git a/src/model/catalog.ts b/src/model/catalog.ts index 8e8c2fc..4950988 100644 --- a/src/model/catalog.ts +++ b/src/model/catalog.ts @@ -622,18 +622,36 @@ export function portCount(item: CatalogItem, speed: PortSpeed): number { return item.ports?.find((p) => p.speed === speed)?.count ?? 0 } +/** Dropdown order: current hardware first, then eol, then withdrawn; catalog + * order within each group (the sort is stable). */ +const availabilityRank: Record = { current: 0, eol: 1, withdrawn: 2 } + +function rankOf(item: CatalogItem): number { + return availabilityRank[item.availability ?? 'current'] +} + +function byAvailability(a: CatalogItem, b: CatalogItem): number { + return rankOf(a) - rankOf(b) +} + export function switchesForRole(role: SwitchRole): CatalogItem[] { - return Object.values(catalog).filter((i) => i.switchRoles?.includes(role)) + return Object.values(catalog) + .filter((i) => i.switchRoles?.includes(role)) + .sort(byAvailability) } export function serversForUsage(usage: ServerUsage): CatalogItem[] { - return Object.values(catalog).filter((i) => i.serverUsages?.includes(usage)) + return Object.values(catalog) + .filter((i) => i.serverUsages?.includes(usage)) + .sort(byAvailability) } /** GPU models offerable for a server model — empty unless it accepts any. */ export function gpusForServer(serverModelId: string): CatalogItem[] { if (!catalog[serverModelId]?.gpuCapable) return [] - return Object.values(catalog).filter((i) => i.category === 'gpu') + return Object.values(catalog) + .filter((i) => i.category === 'gpu') + .sort(byAvailability) } /** How a BOM line names its item: the model people say, else the ordering From bd7128daaea4ff68523b8eda9a8093569d809994 Mon Sep 17 00:00:00 2001 From: Sven-Ric Date: Wed, 16 Sep 2026 10:00:17 +0200 Subject: [PATCH 2/2] Fix comments --- src/model/catalog.test.ts | 2 -- src/model/catalog.ts | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/model/catalog.test.ts b/src/model/catalog.test.ts index 31b49ab..efd7e8f 100644 --- a/src/model/catalog.test.ts +++ b/src/model/catalog.test.ts @@ -282,8 +282,6 @@ describe('helpers', () => { }) it('sorts eol and withdrawn hardware to the bottom', () => { - // These lists contain eol/withdrawn models today; the other roles and - // usages sort through the same comparator. const lists = [ serversForUsage('worker'), serversForUsage('management'), diff --git a/src/model/catalog.ts b/src/model/catalog.ts index 4950988..c3e7a7a 100644 --- a/src/model/catalog.ts +++ b/src/model/catalog.ts @@ -622,8 +622,8 @@ export function portCount(item: CatalogItem, speed: PortSpeed): number { return item.ports?.find((p) => p.speed === speed)?.count ?? 0 } -/** Dropdown order: current hardware first, then eol, then withdrawn; catalog - * order within each group (the sort is stable). */ +// Dropdown order: current hardware first, then eol, then withdrawn. +// Catalog order within each group (the sort is stable). const availabilityRank: Record = { current: 0, eol: 1, withdrawn: 2 } function rankOf(item: CatalogItem): number {