164 lines
6.9 KiB
Markdown
164 lines
6.9 KiB
Markdown
# Future Plans
|
|
|
|
## KV store
|
|
|
|
### Extract into shared library
|
|
`kv-store.mjs` is already copied into at least 3 projects (`electronics-inventory`,
|
|
`fs-views`, `publication-tool`). Should live in its own Gitea repo as an installable
|
|
npm package (`npm install git+https://...`) so changes propagate rather than drift.
|
|
|
|
### Delta / revision tracking
|
|
Add a delta log alongside the main snapshot file (e.g. `inventory.ndjson.deltas`)
|
|
that records every `set`/`delete` as a timestamped entry. The main file stays a
|
|
clean current-state snapshot; the delta file accumulates the full history. Enables
|
|
undo, audit trails, and debugging data corruption.
|
|
|
|
## App architecture
|
|
|
|
### parse_url mutates too many module-level variables
|
|
`parse_url()` directly assigns to a large number of module-level state variables
|
|
(`section`, `grid_view_state`, `grid_tab`, `current_grid_id`, `grid_draft`,
|
|
`current_panel_idx`, `grid_source_id`, `highlight_cell`, `selected_component_id`).
|
|
This is fragile and hard to reason about.
|
|
|
|
Preferred direction: represent the full UI state as a single immutable state object,
|
|
and have `parse_url()` return a new state value rather than mutating globals:
|
|
```js
|
|
function parse_url(path) {
|
|
return { section, grid_view_state, current_grid_id, ... };
|
|
}
|
|
state = parse_url(location.pathname); render(state);
|
|
```
|
|
|
|
### render() if/else chain
|
|
The render dispatcher is a long chain of bare `else if` branches. Replace with a
|
|
lookup table:
|
|
```js
|
|
const SECTION_RENDERERS = {
|
|
components: render_components,
|
|
inventory: render_inventory,
|
|
fields: render_fields,
|
|
grids: render_grids,
|
|
templates: render_templates,
|
|
};
|
|
function render() { sync_nav(); SECTION_RENDERERS[section]?.(); }
|
|
```
|
|
|
|
### app.mjs monolith
|
|
`app.mjs` is large. Consider splitting into per-section modules
|
|
(`views/components.mjs`, `views/grids.mjs`, etc.) that each export their render
|
|
function and own their local state.
|
|
|
|
### DRY / SSoT audit
|
|
As the app grows, patterns are being duplicated rather than centralized. Areas to
|
|
review:
|
|
- Field sorting: same sort-by-name logic appears in both detail view and edit dialog
|
|
- Field rendering: `render_field_value()` exists but call sites still sometimes
|
|
inline display logic
|
|
- Component display name: `component_display_name()` is the SSoT but there may be
|
|
call sites that still use `c.name` directly
|
|
- Server-side: PDF conflict checks, sanitize calls, and rename logic are inline in
|
|
route handlers — could be extracted into a `pdf_service` helper
|
|
- General pass to identify and eliminate copy-paste between routes and between
|
|
render functions before the codebase grows further
|
|
|
|
## Field system
|
|
|
|
### Improvements
|
|
|
|
#### Field display in component detail should use a table
|
|
Currently rendered as CSS grid rows but columns don't align because each row is
|
|
independent. Use an actual `<table>` so name and value columns line up across all
|
|
fields. This is tabular data and a table is the right element.
|
|
|
|
#### Field value parser chain
|
|
Similar to how name formatters use a template chain, field values could be passed
|
|
through a parser chain that returns structured data based on field name/type hints.
|
|
Examples:
|
|
|
|
- A field whose name contains `tolerance` could parse `20` as `{ negative: 20, positive: 20 }`
|
|
and `-10/+30` as `{ negative: 10, positive: 30 }`
|
|
- URL detection (currently hardcoded in `render_field_value()`) could be one parser
|
|
in this chain rather than a special case
|
|
- Mouser/Digi-Key part numbers could be detected and return a structured link target
|
|
|
|
The parser chain would mirror the template system: user-defined or built-in parsers
|
|
keyed by field name pattern, tried in order, returning structured data or `null` to
|
|
pass through to the next. `render_field_value()` would then receive parsed data and
|
|
render accordingly.
|
|
|
|
#### Field rendering integrations
|
|
With or without a parser chain, `render_field_value()` should gain:
|
|
- Mouser/Digi-Key part number fields → auto-craft links to product pages
|
|
- More URL-like patterns (without `https://` prefix)
|
|
|
|
#### Field selector filter
|
|
When adding a field to a component in the edit dialog, the dropdown becomes
|
|
unwieldy with many fields. Add a filter/search input to the field selector.
|
|
|
|
#### Parametric search
|
|
Allow searching/filtering components by field values, not just names. Examples:
|
|
- `resistance < 10k`, `package = 0603`, `voltage_rating >= 50`
|
|
- Cross-field queries: find all 0603 resistors under 10kΩ
|
|
- Should integrate with the existing word-split search or replace it with a
|
|
richer query language
|
|
- Depends on field types (numeric vs string) for range queries to work correctly
|
|
|
|
### Long term
|
|
|
|
#### Field grouping / linkage
|
|
Some fields naturally belong together (e.g. `frequency_stability` and
|
|
`frequency_stability_temp_range`). Options:
|
|
- Soft linkage: tag fields with a group name, display grouped in the UI
|
|
- Structured fields: a field can be a record type with named sub-fields
|
|
(e.g. `stability: { value: 10, unit: "ppm", temp_low: -40, temp_high: 85 }`)
|
|
|
|
Structured records are the more powerful option but require a schema system and
|
|
more complex UI. Grouping/linkage is a lighter short-term win.
|
|
|
|
#### Renderer/parser result cache
|
|
Once parsers and formatters run per-render, a cache keyed on field value + template
|
|
version would avoid redundant work on large inventories. Invalidated when any
|
|
template changes. Not urgent — premature until the parser chain exists.
|
|
|
|
#### Field types
|
|
Currently all field values are free-text strings. Typed fields (numeric,
|
|
enum/dropdown) would enable better formatting, validation, and range-aware search.
|
|
Prerequisite for parametric search with range operators.
|
|
|
|
#### Measurement dimensions and unit conversion
|
|
Instead of a bare unit string on a field, associate a field with a measurement
|
|
dimension (e.g. `temperature`, `resistance`, `frequency`, `voltage`). The dimension
|
|
defines the set of valid units and the conversion factors between them (°C, °K, °R,
|
|
°F for temperature; Ω, kΩ, MΩ for resistance; etc.).
|
|
|
|
This would allow:
|
|
- Entering values in any compatible unit and storing in a canonical unit internally
|
|
- Displaying in the user's preferred unit
|
|
- Parametric search with cross-unit comparisons (e.g. `temp_range > 200K` matching
|
|
a component with `temp_range = -73°C`)
|
|
- Catching unit mismatches at entry time
|
|
|
|
## PDF / files
|
|
|
|
### File picker search filter
|
|
The file picker dialog has no search/filter input. With many datasheets this becomes
|
|
unwieldy. Add a filter input at the top of the list that narrows by display name and
|
|
filename.
|
|
|
|
### PDF page count and multi-page navigation
|
|
Currently only the first page thumbnail is shown. Could show page count and allow
|
|
browsing pages in the lightbox.
|
|
|
|
## Inventory
|
|
|
|
### Inventory URL reflects selected entry
|
|
Similar to how components now reflect `/components/:id` in the URL, inventory
|
|
entries have no URL state — refreshing loses context.
|
|
|
|
## Grids
|
|
|
|
### Grid URL state
|
|
Navigating into a grid viewer updates the URL correctly, but the grid list and
|
|
draft state have no URL representation.
|