Files
core/bible-local/architecture/ui-information-architecture.md
Mikhail Chusavitin 3dbd359d4e Canonical component types, Compare config UI
- Rename parser_hardware.go component type keys to canonical values:
  pcie -> pcie_device, psu -> power_supply
- Update normalizeComponentType to map legacy aliases (pci, psu, dimm,
  ram, processor, network_adapter, etc.) to canonical keys; treat
  "null"/"-" as unknown
- componentTypeTitle handles new canonical keys (pcie_device,
  power_supply)
- Assets list: add Compare config action — opens new window with
  slot-diff and model-count-diff tables for selected servers
- Archive Actions section spec in ui-information-architecture.md
- Add tests: normalizeComponentType aliases, componentTypeTitle aliases,
  FlattenHardwareComponents canonical type keys

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 14:34:22 +03:00

13 KiB
Raw Blame History

UI Information Architecture

Asset Page

Required section order:

  1. Current Components
  2. Previous Components (directly below Current Components)
  3. Movement & Events (timeline cards)

Previous Components lists components that were previously installed on the asset and are currently removed.

Current Components interaction contract:

  • Section header uses the same right-aligned button row pattern as Server Card.
  • Buttons in header:
    • Add
    • Edit
    • Remove
  • Current Components is a single filterable/selectable table (not grouped by type tables) to support bulk actions.
  • Table includes:
    • header Select checkbox (select all visible rows)
    • row checkboxes
    • per-column filters (same visual pattern as All Assets)
  • Selection is asset-page scoped and persisted in local storage keyed by asset id.

Asset page component modals:

  • Add Component modal supports two paths:
    • Create new
    • Attach existing
  • Add duplicate preflight checks:
    • vendor_serial
    • vendor_serial + model
  • If component already exists, UI must guide user to Attach existing instead of creating a duplicate serial component.
  • Attach existing may offer Force attach when component is installed on another server.
  • Edit Components modal supports bulk updates for selected rows:
    • multi-select fields with mixed values render placeholder variable
    • unique fields (vendor serial, slot) are disabled for multi-select
  • Remove modal is de-assert-only:
    • requires Status after removal (Working, Not working, Unknown)
    • detaches component(s) from server and sets mapped component status
  • Destructive asset deletion (Delete with details) is not shown on the asset page; it is available only in Data Admin.

Asset card editing contract:

  • Card has Edit toggle.
  • Card shows compact component-health pizza chart (Healthy, Unknown, Failed) for currently installed components.
  • Vendor and Model values in Server Card are clickable and navigate to semantic asset list filters:
    • /ui/asset/{vendor}
    • /ui/asset/{vendor}/{model}
  • In edit mode:
    • Read-only card fields switch to editable inputs.
    • Edit button changes to Save.
    • Cancel button appears next to Save.
  • Save persists changes through PUT /registry/assets/{id}.
  • Cancel reverts unsaved form values and returns to read-only mode.

Component Page

Required content:

  • Component card including current firmware
  • Component card values are navigable:
    • Vendor -> /ui/component/{vendor}
    • Model -> /ui/component/{vendor}/{model} (model statistics page)
    • Firmware (if present) -> filtered component list for same vendor/model + firmware
  • Installation history table with:
    • Asset
    • Installed At
    • Removed At
  • Timeline is rendered as grouped cards (not raw event rows), same interaction model as asset page.

Timeline UX (Asset + Component Pages)

Timeline rendering rules:

  • Timeline UI renders cards grouped by day, not a flat list of raw timeline_events.
  • Multiple events of the same visual action in one day are visually deduplicated by action + context.
  • Correlated mass operations (correlation_id) are shown as a single bulk card with affected counts.
  • Asset timeline has an additional fallback collapse rule for movement cards:
    • Installation / Removal events without correlation_id are collapsed by source_type + visual_action + 1-hour bucket.
    • correlation_id grouping takes precedence over the 1-hour fallback.
  • Every card shows source label (Ingest, CSV import, Manual edit, System) derived from history event source_type.
  • Every card is clickable and opens a single drilldown modal:
    • left pane: concrete events in the card
    • right pane: details of selected event
    • no nested modal

Scope-specific timeline card content:

  • On asset page, card summary must not repeat the current asset label in each row/card.
  • On component page, card summary must not repeat the current component label/serial/model in each row/card.
  • Instead, show the opposite side of the relation (asset on component page, component on asset page), plus slot/device when available.
  • Collapsed Installation / Removal cards render a two-column summary:
    • left: Models as chips (32x MODEL_A, 8x MODEL_B)
    • right: Slots as chips with aggregation (AOC#[1..4])
    • component serials are not shown in collapsed movement cards
    • raw event counts are not shown in collapsed movement cards

Timeline filters:

  • Filters are server-side (history timeline API) and include:
    • date range
    • action
    • source
    • device
    • slot
    • Part number / Model (v1 maps to model)
    • serial
  • On component page, filters that are invariant for the current component scope (component serial / part number) are hidden.
  • On asset page, filters that are invariant for the current asset scope are hidden.

Timeline drilldown modal:

  • Card drilldown uses the same timezone (tz) as the visible timeline grouping.

Data Admin Page

  • Route: GET /ui/history-admin
  • Purpose: operational/admin data repair tools and destructive maintenance actions.
  • Includes:
    • history batch cancel by source type (single button workflow: Preview -> Execute)
    • Repair (single tool) with default safe actions:
      • restore missing timeline slots from observations
      • rebuild projections (recompute)
    • Cleanup Orphaned Projections (count preview + confirm -> execute)
    • Asset -> Delete with details (single button workflow: Preview -> Execute delete, explicit DELETE confirmation required)
    • History Jobs monitoring table (pagination, newest first, status badges, quick filters)
  • Admin page does not expose raw JSON response blocks; all tools must render human-readable summaries/tables.
  • Collapsed Installation / Removal modal header/meta is human-readable (Installed N components / Removed N components) and avoids raw N events wording.

Component card editing contract:

  • Card has Edit toggle with the same mode behavior as asset card (Edit -> Save, show Cancel).
  • Save persists changes through PUT /registry/components/{id}.
  • Cancel reverts unsaved form values.

Failures Page

Route: GET /ui/failures

Required section order:

  1. Active Failures
  2. Failure Chronology

Active Failures lists unresolved failure incidents (no later replacement in the same slot on the same server).

Failure Chronology includes:

  • failure events
  • repair-by-replacement derived entries (new component installed in the same slot on the same server after failure)

Failure detail page:

  • Routes:
    • primary: GET /ui/failure/{failure_id}
    • compatibility alias: GET /ui/failures/{failure_id}
  • Active Failures table links from Failure Time and Details open the failure detail page.
  • Page aggregates incident context:
    • server and failed component
    • component install time into server (when available)
    • failure time
    • repair-by-replacement details (if detected)
    • open duration
  • Repair / Replacement section must present replacement comparison as paired rows:
    • Model (old / new)
    • Serial (old / new)
  • Avoid redundant duplicate serial rendering across summary blocks when the same identifiers are already shown in the repair comparison.
  • Open Duration on failure detail page is date-precision (whole days), not hour/minute precision.

Manual failure registration UI contract:

  • page header includes Register Failure action button
  • opens modal for manual failure input
  • fields are text inputs with suggestions (datalist/autocomplete style):
    • server serial
    • location
    • component serial (suggestion label includes model on the same line)
    • failure date (YYYY-MM-DD, default = today)
    • description
  • component serial is required to submit
  • if component serial is recognized and current installation is known, server serial is auto-filled
  • if location is selected and maps uniquely, component serial is auto-filled; if ambiguous, UI shows candidate list for explicit selection
  • server serial and location suggestions/filtering are linked (server narrows location suggestions)
  • submit requires explicit confirmation step showing entered and recognized data before request is sent

List Pages

Creation flows:

  • Assets list page provides New Asset action that opens modal form and creates entity via POST /assets.
  • Components list page provides New Component action that opens modal form and creates entity via POST /components.

Shared list behavior:

  • Every table-based list in UI pages must provide pagination in one shared visual style:
    • Summary: Showing XY of N
    • Navigation: Prev, page links with ellipsis when needed, Next
    • Query contract: page number is controlled through URL query (page for list pages, section-specific keys for multi-list pages such as dashboard).
  • Every table header must provide per-column text filtering:
    • A filter input is rendered under each column header.
    • Filtering is case-insensitive and applies as substring match.
    • Filtering semantics are global for the list/query scope: filters apply to the full result set before pagination, not only to the currently rendered page/slice.
    • Page-local header filtering (client-side filtering over only visible rows of a paginated table) is not allowed for primary list pages because it produces misleading results.
    • Input suggestions/datalists should be derived from the full filtered list/query scope (or a server-provided option set for that scope), not only from the current page.
    • Changing any header filter resets the corresponding pagination query parameter to page 1.

List behavior checklist (page-by-page):

  • /ui/asset (assets list / All Assets):
    • per-column filters: server-side, global scope (full dataset before pagination)
    • pagination: single list (page)
    • selection: global across pages (persistent client storage)
  • /ui/component (components list):
    • per-column filters: server-side, global scope (full dataset before pagination)
    • pagination: single list (page)
    • selection: none (row navigation only)
  • /ui/failure and /ui/failures (failures page):
    • Active Failures: paginated section (active_page)
    • Failure Chronology: paginated section (chronology_page)
    • page-local auto header filters are disabled on paginated tables unless replaced with server-side global filters for that section
    • manual registration modal suggestions are derived from page data / server-provided option sets, not from visible rows
  • /ui/search (global search):
    • result sections (Assets, Components, Failure events) use independent pagination
    • generic page-local auto header filters are disabled on paginated result tables
    • if/when header filters are added to search sections, they must be server-side and section-scoped before pagination
  • /ui (dashboard):
    • dashboard tables/lists use independent pagination per section
    • generic page-local auto header filters are disabled on paginated dashboard tables
    • any future header filters must be server-side and applied before section pagination
  • /ui/component/{vendor}/{model} (model stats page):
    • Servers With Installed Components Of This Model: independent pagination (servers_page)
    • Components Of This Model: independent pagination (components_page)
    • generic page-local auto header filters are disabled on both paginated tables unless replaced with server-side global filters
  • /ui/asset/{id} and /ui/component/{id} (detail pages):
    • embedded historical tables may be unpaginated
    • local-only filtering is acceptable only for explicitly unpaginated tables; paginated tables on detail pages must follow the shared global-filter rule

Assets list specifics:

  • All Assets table filtering is server-side and applies to the full dataset before pagination.
  • Actions section includes:
    • New Asset
    • Compare config (opens in a separate window/tab, compares hardware composition for selected servers, shows differences)
    • Delete Selected (With Details)
  • All Assets supports global bulk selection:
    • Header Select checkbox can select all assets across all pagination pages.
  • Selected IDs persist across page navigation and are stored in browser local storage.
  • Global-selection semantics for paginated list bulk actions must be explicit and must not silently degrade to current-page-only selection.

Component model statistics page (/ui/component/{vendor}/{model}):

  • Model Statistics section includes:
    • counts (Total, Installed, Uninstalled, Healthy, Unknown, Failed)
    • compact pizza chart (status distribution: Healthy, Uninstalled, Failed, Unknown)
  • Servers With Installed Components Of This Model table:
    • status-filter chips
    • independent pagination (servers_page)
  • Components Of This Model table (same page, below servers):
    • component rows with status, asset, firmware
    • independent pagination (components_page)
  • UI top bar provides a global search form available on all pages.
  • Global search page (/ui/search) searches across:
    • Assets
    • Components
    • Failure events
  • Results are split by entity type and paginated independently per section.

Supporting Repositories Required By UI

  • timeline.EventRepository.ListLatestBySubjectsAndEventTypes(...)
  • registry.InstallationRepository.ListPreviousComponentsByAsset(...)
  • registry.InstallationRepository.ListInstallationHistoryByComponent(...)