Commit Graph
11 Commits
Author SHA1 Message Date
adebisi-fa 134edb6ebd feat(ui): add Carbon icons to all tool buttons
Cropper: next, search, reset, trash-can, magic-wand, checkmark, misuse,
crop, undo, send, subtract.
Fingerprint Agent: search, renew, fingerprint-recognition, close, save.
2026-10-01 14:39:42 +01:00
adebisi-fa 796094f61b feat(cropper): save with the session token — no OTP, domain from a2loft
Consumes the a2loft cropper-token-auth change: the save now sends the
session's PocketBase token as a bearer credential and no phone/otp. The
backend authorizes with OpenFGA crop_image (domain:<code> -> domain:idid),
so an operator no longer needs super-user rights in the profile's domain —
which is what made saves fail with a blanket 'Invalid OTP specified.'.

- the save's domain comes from a2loft's own record of the picture
  (dims/picture/{uploadId} -> domainCode), falling back to the queue label,
  guarded by a path-safety pattern instead of the catalog check
- the 'core' -> 'uc' alias is deleted: 'core' is a2loft's own pseudo-domain
  for a profile picture (special-cased there), so rewriting it changed the
  attribution and the ID-card notification
- queue loads are enriched with the profile's domainCode; the panel shows
  the profile's domain and, when it differs, the picture target
- the cropper's OTP field, state and parameters are gone; the fingerprint
  wizard is untouched (its own OTP flow on its own endpoints)
- tests updated: bearer + no query auth, resolved domain wins, unsafe values
  refused, no OTP field served (46 pass)

Requires the a2loft change deployed first.
2026-10-01 12:37:25 +01:00
adebisi-fa 1f8fdb47b6 refactor(cropper): drop the cropped preview — the cleaned image is the only preview
The extra cropped-result panel duplicated what the crop pad already shows and
the cleaned image supersedes it. Removes the panel, its state, the pointer-
release refresh handlers and the app.js plumbing. The crop result is still
uploaded (croppa stays the source when nothing is cleaned).
2026-10-01 04:39:08 +01:00
adebisi-fa 95200b6abf fix(cropper): make load failures visible; loud config errors
'Load next queued' did nothing because the running server had been started
without its env file (a restart used '-f .env' from tools/, where no .env
exists), so the cropper was unconfigured and every action answered 503 —
and none of that was visible, because notifications never rendered either:

- notifications used cds-toast/cds-toast-item, which the Carbon bundle does
  not define; a cds-toast-notification element renders nothing standalone in
  this build. The cropper now uses cds-inline-notification in the fixed
  toast viewport (renders, themed, close button) like the wizard
- an unconfigured deployment now says so on the page (503 'Cropper
  unavailable') instead of rendering actions that all fail, and logs a
  startup warning naming the missing credentials
- tests: notifications use a registered element; unconfigured page 503
2026-10-01 04:36:31 +01:00
adebisi-fa cb5b151988 fix(cropper): render reason checkboxes, gate the Others field, add cropped preview
Three defects from the Carbon rewrite, found while fixing the review panel:

- reason checkboxes were invisible: Carbon's .cds--checkbox input is
  visually clipped and needs the .cds--form-item/.cds--checkbox-wrapper +
  .cds--checkbox-label markup to draw the box
- 'Others (please specify)' now appears only when 'Others not specified.'
  is ticked, and clears when unticked (hidden text must not be submitted);
  the textarea gets Carbon's __wrapper so it has a proper height
- new 'Cropped preview' between the original and cleaned previews, so the
  operator sees what will be uploaded; refreshed on pointer release over the
  pad and after load/clean
- REGRESSION: Vue.use(Croppa) had been dropped — the crop canvas never
  rendered, and saving only worked because the cleaned image bypassed
  generateDataUrl. Restored.
- REGRESSION: the OTP field bound v-model="otpSave" while the data property
  is "otp", so Vue's render threw ReferenceError and froze the panel as
  soon as accept was clicked (the OTP could never be entered). Bound to otp;
  the croppa instance is now reached via $refs.croppa (the v-model object is
  not always the live instance)
- after a successful save the review panel stayed open: reset() recreated an
  empty message object, which the template treats as truthy. message is null
  when idle now.

45 tests pass; save round-trip and reject/Others flow verified in the browser.
2026-10-01 04:26:26 +01:00
adebisi-fa 2e4a51d018 feat(ui): Youreka favicon, logout confirmation, nav active states, brand alignment
- favicon is the Youreka logo (64px PNG generated from the source mark),
  on the tools pages and server error pages
- signing out asks first: a Carbon cds-modal (Cancel / danger Sign out)
  shared by the header and the mobile side nav; Cancel closes, Sign out
  confirms and logs out
- the current tool is now visibly selected: Carbon marks active nav via
  a[aria-current=page] INSIDE the shadow, but aria-current sits on the
  host, so the rule never matched — the header item now gets a blue
  underline and the side-nav link a blue left border (via ::part(link)
  for colour, plus the host for the marker)
- logo and wordmark are middle-aligned inside a flex brand wrapper
- tests: favicon/modal/signout-trigger markup and the active-tool marking
  on both navs (45 total)
2026-10-01 04:08:09 +01:00
adebisi-fa 17c407883d feat(ui): g100 dark theme and more space above page titles
- all pages (landing, both tools, server error pages) render on Carbon's
  g100 theme via <body class="app cds--g100">; token consumers follow
  automatically, including component shadow styles through the inherited
  --cds-* custom properties
- dark base on <html> so no light flash around the viewport
- step chips and tool icons use the brand blue: layer-selected-inverse
  inverts to a LIGHT token in g100, which had made them white-on-white
- page titles breathe: .page-head top margin 1.5rem -> 2.75rem
- new test asserting every page renders on g100 (44 total)
2026-10-01 04:01:44 +01:00
adebisi-fa 340d8da19d feat(ui): ui-shell header with tool links, mobile side nav, Youreka logo
- header: Carbon ui-shell (cds-header) with the Youreka logo (from
  idid-enterprise-portal), Image Cropper / Fingerprint Agent nav items
  (aria-current on the active tool), the agent status tag on the wizard,
  and the operator chip + Sign out on desktop
- mobile: cds-side-nav (logo above the items, both tools, a divider, then
  Sign out) toggled by the ui-shell menu button; account actions move out
  of the header below 1056px, the nav is hidden at desktop widths
- the header is built once in server.js (appHeader) and injected into the
  landing, both tools and error pages — no per-page duplication
- removed my duplicate menu-button toggle: ui-shell coordinates the menu
  button and side nav itself (the duplicate cancelled it out)
- fixes: 'cds-header' was hidden by a selector-list typo
  (cds-header, cds-side-nav:not(:defined)); the collapsed side nav no
  longer captures taps

Tools banner logo asset added (public/assets/youreka-logo.png).
2026-10-01 03:53:24 +01:00
adebisi-fa 930af97f05 feat(ui): rebuild all tools pages on Carbon Design System web components
- @carbon/web-components v2.50.0 via the IBM CDN (version-pinned);
  @carbon/styles CSS + IBM Plex Sans for tokens/typography
- landing: Carbon header + cds-tile tool cards
- fingerprint wizard: Carbon-styled form controls, cds-progress-bar scan
  progress, cds-tag badges, cds-inline-notification replacing swal
- cropper: cds-toast replacing toastr, cds-checkbox review reasons,
  cds-tag process badge; vue-croppa pad kept in the Carbon layout
- Bootstrap 4, swal, toastr and jQuery removed from all pages
- behavior frozen: same flows, endpoints, validation and copy
2026-10-01 02:03:07 +01:00
adebisi-fa 2f0a1fab21 fix(cropper): responsive editor layout
Two-column editor at >=900px (crop pad + cleaned preview left, cleaning/
review controls right), single column below; panel headers wrap their
hints onto their own line on narrow screens.
2026-10-01 01:22:18 +01:00
adebisi-fa d689434047 feat(cropper): move the Image Cropper into the tools app at /cropper
- Smart Photo Editor ported from id-image-bot: queue/by-ID picture
  loading, vue-croppa editing, carvekit background cleanup, nodered
  review flow, a2loft save — restyled to the tools design language
- unified login: YOUreka session identity, phone prefilled, OTP only at
  save (a2loft's requirement); artist-login step removed
- crop_image @ domain:idid OpenFGA gate on every cropper route: cached
  5-min on reads, live on save, fail closed
- credentials (minio/azure/nodered/carvekit) via env, sole exception to
  hardcoded config; 503 when unconfigured; native FormData replaces
  form-data; new deps minio + azure-storage
- 10 new tests (35 total) with fake minio/queue/nodered/removebg/a2loft
2026-10-01 01:13:30 +01:00