Commit Graph

30 Commits

Author SHA1 Message Date
Forbes
da65d4bc1a feat(web): favicon, narrow settings, scrollable token list
- Add kindred-logo.svg as site favicon (#115)
- Narrow settings page to 66% max-width, centered (#116)
- Add max-height and scroll to API token table (#118)

Closes #115, closes #116, closes #118
2026-02-15 12:38:20 -06:00
Forbes
747bae8354 feat(jobs): wire auto-triggering on bom_changed events, add module guard
- Add IsEnabled("jobs") guard to triggerJobs() to skip when module disabled
- Fire bom_changed trigger from HandleAddBOMEntry, HandleUpdateBOMEntry,
  HandleDeleteBOMEntry (matching existing HandleMergeBOM pattern)
- Add 4 integration tests: revision trigger, BOM trigger, filter mismatch,
  module disabled
- Fix AppShell overflow: hidden -> auto so Settings page scrolls
- Clean old frontend assets in deploy script before extracting

Closes #107
2026-02-15 09:43:05 -06:00
Forbes
0be39065ac feat(web): admin settings page with module cards, toggles, config forms
Add admin-only Module Configuration section to the Settings page.
Each module gets a collapsible card with enable/disable toggle,
status badge, module-specific config fields, save and test
connectivity buttons.

- AdminModules: fetches GET /api/modules + GET /api/admin/settings,
  renders Infrastructure and Features groups, restart banner
- ModuleCard: collapsible card with toggle, status badge, field
  layouts per module, save (PUT) and test (POST) actions
- TypeScript types for ModuleInfo, ModulesResponse, admin settings
  API response shapes

Ref: #100
2026-02-15 03:01:33 -06:00
Forbes
ba92dd363c fix(web): align all spacing values to 4px grid
Standardize all spacing to multiples of 4px (0.25rem):
- 0.15rem (2.4px) → 0.25rem (4px)
- 0.35rem (5.6px) → 0.25rem (4px)
- 0.375rem (6px) → 0.25rem (4px) for borderRadius
- 0.4rem (6.4px) → 0.5rem (8px)
- 0.6rem (9.6px) → 0.5rem (8px)

Updated theme.css density variables, silo-base.css focus ring,
and all TSX component inline styles.

Closes #71
2026-02-14 13:36:22 -06:00
Forbes
c7857fdfc9 fix(web): standardize font sizes to style guide scale
Map fontWeight: 700 → 600 in non-title contexts (LoginPage, FileDropZone).
Align FileDropZone badge padding to 4px grid.

Closes #70
2026-02-14 13:36:07 -06:00
Forbes
07c4aa1c28 fix(web): align spacing values to style guide grid (#71)
- Replace 0.3rem padding/margin/gap with 0.25rem (xs)
- Replace 0.2rem margins with 0.25rem (xs)
- Replace 0.1rem padding with 0.15rem (badge spec)
- Replace 0.6rem margins/padding with 0.5rem (sm)
- Fix borderRadius 0.3rem to 0.375rem (6px per style guide)
- Preserve style-guide-specified values: 0.35rem button gap, 0.4rem cell padding, 0.45rem input padding
2026-02-13 14:37:40 -06:00
Forbes
679b730e74 fix(web): standardize font sizes to style guide scale (#70) 2026-02-13 14:33:11 -06:00
Forbes
b53ce94274 feat(web): install lucide-react and replace unicode icons (#67) 2026-02-13 13:44:48 -06:00
Forbes
f4a1c8004b feat(web): add input focus states via silo-base.css (#72)
Create silo-base.css with .silo-input hover/focus pseudo-classes:
- hover: border-color overlay0
- focus: border-color mauve + 0.2rem mauve box-shadow

Applied className='silo-input' to form inputs in:
CreateItemPane, EditItemPane, ProjectsPage, SchemasPage,
SettingsPage, LoginPage

Closes #72
2026-02-13 13:24:39 -06:00
Forbes
a9614e704e fix(web): standardize transition durations to 0.15s ease (#73)
All inline transition properties now use 'all 0.15s ease'.

Files: AppShell, CategoryPicker, AuditDetailPanel,
AuditSummaryBar, AuditTable, FileDropZone

Closes #73
2026-02-13 13:23:08 -06:00
Forbes
289d488469 fix(web): table header color overlay1 + selected row mauve tint (#69)
- All thStyle objects: color subtext1/subtext0 → overlay1
- Selected row bg: surface1 → rgba(mauve, 0.08)

Files: ItemTable, BOMTab, ProjectsPage, SchemasPage,
SettingsPage, AuditTable

Closes #69
2026-02-13 13:22:30 -06:00
Forbes
2585305590 fix(web): standardize button borderRadius, fontSize, fontWeight (#68)
All button style objects now use:
- borderRadius: 0.375rem
- fontSize: 0.75rem
- fontWeight: 500

Files: CreateItemPane, EditItemPane, DeleteItemPane, BOMTab,
CategoryPicker, ProjectsPage, SchemasPage, LoginPage,
ItemsToolbar, SettingsPage, ImportItemsPane, ItemTable

Closes #68
2026-02-13 13:21:54 -06:00
Forbes
648c659e2b fix(web): use system font stack per style guide
Fixes #66

Remove Inter and Roboto from font-family. The style guide specifies
system fonts only: -apple-system, BlinkMacSystemFont, Segoe UI,
system-ui, sans-serif.
2026-02-13 13:09:56 -06:00
Forbes
d4ea6d2739 fix(web): align item type badge colors with style guide
Fixes #65

- Part: blue → green (--ctp-green)
- Assembly: green → mauve (--ctp-mauve)
- Document: yellow → blue (--ctp-blue)
- Add purchased (--ctp-peach) and phantom (--ctp-overlay1)
- Keep tooling as red (--ctp-red)
2026-02-13 13:09:41 -06:00
4edaa35c49 feat: schema-driven form descriptor API and dynamic form rendering
- Add ui section to kindred-rd.yaml with category_picker (multi-stage),
  item_fields, field_groups, category_field_groups, and field_overrides
- Add UIConfig structs to Go schema parser with full YAML/JSON tags
- Add ValidateUI() to validate field references against property schemas
- Add ValuesByDomain() helper to auto-derive subcategory picker stages
- Implement GET /api/schemas/{name}/form endpoint that returns resolved
  form descriptor with field metadata, widget hints, and category picker
- Replace GET /api/schemas/{name}/properties route with /form
- Add FormDescriptor TypeScript types
- Create useFormDescriptor hook (replaces useCategories)
- Rewrite CreateItemPane to render all sections dynamically from descriptor
- Update CategoryPicker with multi-stage domain/subcategory selection
- Delete useCategories.ts (superseded by useFormDescriptor)
2026-02-11 10:14:00 -06:00
b3c748ef10 refactor: move sourcing_link and standard_cost from item columns to revision properties
- Add migration 013 to copy sourcing_link/standard_cost values into
  current revision properties JSONB and drop the columns from items table
- Remove SourcingLink/StandardCost from Go Item struct and all DB queries
  (items.go, audit_queries.go, projects.go)
- Remove from API request/response structs and handlers
- Update CSV/ODS/BOM export/import to read these from revision properties
- Update audit handlers to score as regular property fields
- Remove from frontend Item type and hardcoded form fields
- MainTab now reads sourcing_link/standard_cost from item.properties
- CreateItemPane/EditItemPane no longer have dedicated fields for these;
  they will be rendered as schema-driven property fields
2026-02-11 09:50:31 -06:00
Forbes
25c42bd70b feat(web): add BOM merge resolution UI with source badges and dropdown
- Add source badges (assembly=teal, manual=blue) to BOM display rows
- Add info banner when assembly-sourced entries exist
- Change source input from text field to select dropdown
- Add merge response types to types.ts

Closes #47
2026-02-08 19:56:33 -06:00
Forbes
50985ed805 feat: expose file attachment stats as item properties (#37)
Add file_count and files_total_size to item API responses, computed
via batch query on item_files table (no migration needed).

- Add BatchGetFileStats() to audit_queries.go (follows BatchCheckBOM pattern)
- Add file stats to ItemResponse, HandleListItems, HandleGetItem, HandleGetItemByUUID
- Add 'Files' column to ItemTable (default visible in vertical mode)
- Add has_files computed field to audit completeness scoring (weight 1 for manufactured)
2026-02-08 19:25:46 -06:00
9ce9468474 Merge branch 'main' into issue-44-bom-source 2026-02-09 01:21:13 +00:00
Forbes
163dc9f0f0 feat(db): add source column to relationships table (#44)
Promote BOM source from metadata JSONB to a dedicated VARCHAR(20)
column with CHECK constraint ('manual' or 'assembly').

- Add migration 012_bom_source.sql (column, data migration, cleanup)
- Add Source field to Relationship and BOMEntry structs
- Update all SQL queries (GetBOM, GetWhereUsed, GetExpandedBOM, Create)
- Update API response/request types with source field
- Update CSV/ODS export to read e.Source instead of metadata
- Update CSV import to set source on relationship directly
- Update frontend types and BOMTab to use top-level source field
2026-02-08 18:45:41 -06:00
Forbes
cb88b3977c feat(web): add user-selectable density mode with compact/comfortable toggle
Implements #17, #18, #19, #20, #21

- Add CSS custom properties for density-dependent spacing (--d-* vars)
  in theme.css with comfortable (default) and compact modes
- Create useDensity hook with localStorage persistence and DOM attribute sync
- Add FOUC prevention in main.tsx (sync density before first paint)
- Create shared PageFooter component merging stats + pagination
- Refactor AppShell to flex layout with density toggle button (COM/CMP)
- Consolidate inline pagination from ItemsPage/AuditPage into PageFooter
- Delete FooterStats.tsx (replaced by PageFooter)
- Replace all hardcoded padding/font/gap values in ItemTable, AuditTable,
  ItemsToolbar, and AuditToolbar with var(--d-*) references

Comfortable mode is already tighter than the previous hardcoded values.
Compact mode reduces further for power-user density.
2026-02-08 18:35:25 -06:00
Forbes
c49f8f78c9 fix: render project tags as strings, not objects
The /api/items/{pn}/projects endpoint returns Project objects
({id, code, name, created_at}), but MainTab typed them as string[].
React error #31 was thrown when trying to render the object as a
child node.

Change itemProjects state from string[] to Project[] and use
proj.code in all rendering and comparison logic.

Closes #33
2026-02-08 15:11:20 -06:00
Forbes
888cebe875 feat(web): remove max-width constraint and reduce main padding
Remove maxWidth: 1400 and margin: 0 auto from AppShell main container.
Reduce padding from 2rem to 1rem so content fills available browser width.
Adjust height calc in ItemsPage and AuditPage from 80px to 64px offset
to account for reduced top padding.

Closes #16
2026-02-07 14:51:55 -06:00
Forbes
50923cf56d feat: production release with React SPA, file attachments, and deploy tooling
Backend:
- Add file_handlers.go: presigned upload/download for item attachments
- Add item_files.go: item file and thumbnail DB operations
- Add migration 011: item_files table and thumbnail_key column
- Update items/projects/relationships DB with extended field support
- Update routes: React SPA serving from web/dist, file upload endpoints
- Update auth handlers and middleware for cookie + bearer token auth
- Remove Go HTML templates (replaced by React SPA)
- Update storage client for presigned URL generation

Frontend:
- Add TagInput component for tag/keyword entry
- Add SVG assets for Silo branding and UI icons
- Update API client and types for file uploads, auth, extended fields
- Update AuthContext for session-based auth flow
- Update LoginPage, ProjectsPage, SchemasPage, SettingsPage
- Fix tsconfig.node.json

Deployment:
- Update config.prod.yaml: single-binary SPA layout at /opt/silo
- Update silod.service: ReadOnlyPaths for /opt/silo
- Add scripts/deploy.sh: build, package, ship, migrate, start
- Update docker-compose.yaml and Dockerfile
- Add frontend-spec.md design document
2026-02-07 13:35:22 -06:00
Forbes
d61f939d84 feat(web): redesign CreateItemPane with two-column layout
Rewrite CreateItemPane from single-column scrolling form to a
two-column CSS Grid layout (1fr 280px):

Left column (scrollable form):
- Identity section: Type select, Description input, CategoryPicker
- Sourcing section: Sourcing Type, Standard Cost, Sourcing Link
- Details section: Long Description textarea, Projects TagInput
- Category Properties: dynamic fields from schema (2-column sub-grid)
- Section headers with uppercase labels and horizontal dividers

Right column (sidebar):
- Metadata: auto-assigned revision ('A'), created by (current user)
- Attachments: FileDropZone with presigned upload integration
- Thumbnail: 4:3 preview box, click to upload image

Submission flow:
1. POST /api/items with form data
2. Associate uploaded attachments via POST /api/items/{pn}/files
3. Set thumbnail via PUT /api/items/{pn}/thumbnail
4. File failures are non-blocking (item already created)

Integrates: CategoryPicker (#13), TagInput (#11), FileDropZone (#14),
useFileUpload presigned upload hook (#12)

Closes #15
2026-02-07 10:15:03 -06:00
Forbes
3358e7dd1c feat(web): add FileDropZone component with upload progress
New files:
- web/src/hooks/useFileUpload.ts: presigned upload hook that gets
  a presigned PUT URL from POST /api/uploads/presign then uploads
  via XMLHttpRequest for progress tracking
- web/src/components/items/FileDropZone.tsx: drag-and-drop file
  upload zone with file list, type-colored badges (CAD/PDF/IMG),
  progress bars, and remove buttons

Features:
- Dashed border drop zone with drag-over visual feedback
- Click to browse or drag files to add
- File type detection by extension with colored badges
- Upload progress bar (2px mauve) during active uploads
- Error state display per file
- Configurable accepted file types via accept prop

Closes #14
2026-02-07 10:13:18 -06:00
Forbes
6f357c2199 feat(web): add CategoryPicker searchable selector component
Replace the flat <select> dropdown for category selection in
CreateItemPane with a searchable, scrollable CategoryPicker component.

New files:
- web/src/hooks/useCategories.ts: fetches and caches category enum
  values from GET /api/schemas/kindred-rd, extracts the category
  segment values map
- web/src/components/items/CategoryPicker.tsx: scrollable list with
  search input filtering by code and description, selected item
  highlighted with mauve, breadcrumb showing current selection

Modified:
- web/src/components/items/CreateItemPane.tsx: replaced <select>
  with <CategoryPicker>, uses useCategories hook instead of
  fetching full schema inline

Closes #13
2026-02-07 10:11:59 -06:00
Forbes
cf02ce4231 feat(web): implement Component Audit UI with inline editing
Build the full Audit page replacing the minimal stub with:

Phase 1 - Audit Overview:
- useAudit hook with server-side filtering by project, category,
  tier (mapped to min_score/max_score), sort, and pagination
- AuditSummaryBar: horizontal stacked bar with tier counts, colored
  segments (critical/low/partial/good/complete), clickable to filter
- AuditToolbar: project and category dropdowns, sort selector,
  layout toggle
- AuditTable: sortable table with score badge (colored by tier),
  part number, description, category, sourcing type, missing count
- SplitPanel integration (reused from items) with persistent layout

Phase 2 - Inline Edit Panel:
- AuditDetailPanel: split-panel detail view with field-by-field
  breakdown from GET /api/audit/completeness/{pn}
- Fields grouped into Required, Procurement, Category Properties,
  and Computed sections
- Color-coded left border per field: green if filled, red if empty
- Critical fields (weight >= 3) marked with asterisk
- Inline editing with debounced auto-save on blur (500ms)
- Item-level fields saved via PUT /api/items/{pn}
- Property fields saved via PUT with merged properties + new revision
- Score progress bar updates live after each save
- Computed fields (has_bom) shown read-only

All components use inline CSS with Catppuccin Mocha theme variables,
matching the existing frontend patterns.

Closes #5
2026-02-07 08:48:50 -06:00
Forbes
a4f32b2b49 feat(web): migrate Items page to React with UI improvements
Phase 2 of frontend migration (epic #6, issue #8).

Rebuild the Items page (4,243 lines of vanilla JS) as 16 React
components with full feature parity plus UI improvements.

UI improvements:
- Footer stats bar (28px fixed bottom) replacing top stat cards
- Compact row density (28-32px) with alternating background colors
- Right-click column configuration via reusable ContextMenu component
- Resizable horizontal/vertical split panel layout (persisted)
- In-pane CRUD forms replacing modal dialogs (Infor-style)

Components (web/src/components/items/):
- ItemTable: sortable columns, alternating rows, column config
- ItemsToolbar: search with scope (All/PN/Desc), filters, actions
- SplitPanel: drag-resizable horizontal/vertical container
- FooterStats: fixed bottom bar with reactive item counts
- ItemDetail: 5-tab detail pane (Main, Properties, Revisions, BOM,
  Where Used) with header actions
- MainTab: metadata, inline project tag editor, file download
- PropertiesTab: form/JSON dual-mode editor, save as new revision
- RevisionsTab: comparison diff, status management, rollback
- BOMTab: inline CRUD, cost calculations, CSV export
- WhereUsedTab: parent assemblies table
- CreateItemPane: in-pane form with schema category properties
- EditItemPane: in-pane edit form for basic fields
- DeleteItemPane: in-pane confirmation with warning
- ImportItemsPane: CSV upload with dry-run validation flow

Shared components:
- ContextMenu: positioned right-click menu with checkbox support

Hooks:
- useItems: items fetching with search, filters, pagination, debounce
- useLocalStorage: typed localStorage state hook

Extended api/types.ts with request/response types for search, BOM,
revisions, CSV import, schema properties, and revision comparison.
2026-02-06 17:21:18 -06:00
Forbes
118c32dc14 feat(web): scaffold React + Vite + TypeScript frontend
Phase 1 of frontend migration (epic #6, issue #7).

Project setup (web/):
- React 19, React Router 7, Vite 6, TypeScript 5.7
- Catppuccin Mocha theme CSS variables matching existing Go templates
- Vite dev proxy to Go backend at :8080 for /api/*, /login, /logout,
  /auth/*, /health, /ready

Shared infrastructure:
- api/client.ts: typed fetch wrapper (get/post/put/del) with 401
  redirect and credentials:include for session cookies
- api/types.ts: TypeScript interfaces for all API response types
  (User, Item, Project, Schema, Revision, BOMEntry, Audit, Error)
- context/AuthContext.tsx: AuthProvider calling GET /api/auth/me
- hooks/useAuth.ts: useAuth() hook exposing user/loading/logout

UI shell:
- AppShell.tsx: header nav matching current Go template navbar
  (Items, Projects, Schemas, Audit, Settings) with role badges
  (admin=mauve, editor=blue, viewer=teal) and active tab highlighting
- LoginPage: redirects to Go-served /login during transition
- Placeholder pages: Items, Projects, Schemas fetch from API and
  display data in tables; Audit shows summary stats; Settings shows
  current user profile

Go server changes:
- routes.go: serve web/dist/ at /app/* with SPA index.html fallback
  (only activates when web/dist/ directory exists)
- .gitignore: web/node_modules/, web/dist/
- Makefile: web-install, web-dev, web-build targets
2026-02-06 16:19:52 -06:00