Commit graph

15 commits

Author SHA1 Message Date
Phil Dore
1f537b8a3b Add Admin tab, Economics overview, Access Log, fix deliverables and gap data
- Merge Economics + Update Data into single Admin tab with sub-nav (Economics | Update Data | Access Log)
- Add Economics tab: per-market financial metrics parsed from Box MD files, card grid matching Markets dashboard style, drill-in detail view for key characteristics; admin-only
- Add Access Log: DB migration (003_access_log), login events recorded in auth.js, admin endpoint + frontend table showing user/action/IP/timestamp
- Fix deliverable downloads: copy PDFs/XLSXs to clients/adeo/deliverables/ and update deliverables.json paths to container-accessible locations
- Patch gap analysis: extract gaps from Question_XX_Analysis.md files in Box for all 8 markets (90 questions patched)
- Mobile: fix card grid minmax, modal max-width uses min(740px,90vw)
- Loading: replace invisible auth-loading with visible spinner overlay
- Add economic.json with key metrics for all 8 markets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:35:12 +01:00
Phil Dore
b97889a9d9 Add activity log, multilingual support (ES/PT/IT/PL), and QA score column fix
- Activity log: import_log DB table, GET /activity endpoint, collapsible
  panel in Update Data tab showing who changed what score and when
- Sync logging: Box syncs now also write to import_log with before/after scores
- Multilingual: ES, PT, IT, PL UI strings in i18n/ui.js; content translations
  (pillars, scoring labels, About tab) in clients/adeo/config.json; language
  switcher upgraded from EN/FR toggle to 6-language dropdown
- cfg() and pillarDisplayName() generalised to support any language (not just FR)
- import_file.py: reads 'Final QA ...' column first (falls back to Score) so
  QA-updated XLSX files produce the correct overall score on import
- convert_data.py/docker-compose: use ADEO_DATA_ROOT env var for Box path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 13:23:22 +01:00
Phil Dore
b28f49096c Add Focus Areas tab + complete FR translation coverage
- Move Focus Areas from a collapsible panel into its own dedicated tab
- Fix text overflow and badge sizing in question rows
- Translate all Focus Areas strings (pillar performance, questions section)
- Fix About tab: summary, pillar names, scoring labels now switch to FR
- Fix question modal: pillar name now shows translated name
- Fix stat labels (Questions/Pillars/Markets) in About section
- Fix import toast to use translated scoring label
- Add translations block to /api/clients summary response

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 17:58:40 +01:00
DJP
e039ed01b6 Copy i18n/ folder into the Docker image
index.html references /i18n/ui.js (added in 8d0a618 for the EN/FR
toggle) but the Dockerfile only copies index.html, script.js, server/,
and *.py. Without this, the browser 404s on /adeo-maturity/i18n/ui.js
and the language toggle silently fails.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 12:16:21 -04:00
Phil Dore
8d0a618b68 Baseline: EN/FR toggle + question topic translations
Working state before improvements branch:
- Language toggle (EN/FR) for ADEO
- 59 question topics translated to French
- About tab translated and toggle visible on home screen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 16:43:30 +01:00
DJP
faf2e3be66 Restore pillars/scoring/about fields in /api/clients response
These were added in 5eac433 (the About-tab commit) and got dropped
during the auth rewrite. The About tab uses them to render the
Maturity Levels, How To Use, and Pillars sections; without them
the page rendered empty fallbacks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 11:37:57 -04:00
DJP
88e4df59be Validate persisted ports against live host on every deploy
Previously the script only ran port resolution when no compose
containers were already running, on the assumption that running
containers meant the persisted port was still ours. On the shared
optical-dev server that's wrong: another app can grab a port
between our deploys, leaving us with a stale .env value that fails
to bind.

Now find_free_port treats a port as "available for us" if either
nothing is listening, or one of our own compose containers is
publishing it (so re-deploys don't shuffle). Other-app listeners
trigger a re-pick and a warning.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 11:22:06 -04:00
DJP
8e969fe015 Add login + role-based access (admin/user) backed by Postgres
Adds a Postgres-backed user store with bcrypt + JWT cookie sessions,
login screen, role-gated UI, and Microsoft SSO scaffolding ready to
fill in.

Backend
- New `db` service (Postgres 16-alpine) in compose, healthcheck-gated
  app startup, free-port autodetect (5435-5499) like other apps.
- `server/db.js` runs versioned `.sql` migrations on boot.
- `server/auth.js`: bcrypt + JWT cookie (httpOnly, sameSite=strict,
  path-scoped to /adeo-maturity), rate-limited login (10/15min),
  dummy bcrypt-compare on missing users to defeat timing oracles.
- `requireAdmin` on all writes (POST/import/sync); `authenticate`
  on all reads. /api/health stays public.
- Microsoft SSO endpoints stubbed at /api/auth/msft/{login,callback}
  (return 501); DB has azure_oid column ready; comments document
  exactly how to wire @azure/msal-node.

Frontend
- Login screen with email/password + greyed-out "Sign in with
  Microsoft" button; init() checks /api/auth/me first.
- Logout button + user badge in header.
- body.role-user CSS hides .admin-only elements (Update tab, New
  Client cards). Server enforces regardless.

Deploy
- deploy.sh generates DB_PASSWORD and AUTH_SECRET on first run and
  persists to .env, then runs `seed-users.js seed-defaults` to
  create admin@oliver.agency + user@oliver.agency with random
  passwords printed once. Subsequent deploys skip seeding unless
  --reseed is passed.
- node server/seed-users.js set-password <email> <pw> for ad-hoc
  resets later.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 11:14:19 -04:00
DJP
6d4f00e795 Fix logo filename case in adeo config
config.json had "logo": "logo.png" but the file on disk is Logo.png.
Works on macOS (case-insensitive FS) and 404s on Linux (case-sensitive).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 13:57:57 -04:00
DJP
ebedde5fcf Prefix client logo image src with API_BASE
Three <img src="/clients/..."> tags were using absolute paths, so the
browser fetched them from the host root rather than under the app's
URL prefix — broken images when the app is mounted at a sub-path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 13:33:49 -04:00
DJP
6dbd399ac0 Restructure deploy to mirror oliver-sales-ops-platform pattern
Subpath-aware deploy for /adeo-maturity/ behind the shared optical-dev
vhost. Auto-picks a free host port (prefers 3102, scans 3102-3199) and
persists it to .env so re-deploys are idempotent. Renders the Apache
conf from a template on each run.

- script.js: detect URL prefix at load time and prepend it to all /api/
  calls, so the same code works at the root locally and under a
  sub-path behind Apache.
- Dockerfile: fix broken package.json copy (lives at repo root, not
  server/) and install python3 + reportlab + openpyxl for the sync/
  import/PDF endpoints that shell out.
- docker-compose: pin top-level name (per global docker policy),
  configurable host port, bind 127.0.0.1 only.
- deploy/: new deploy.sh + apache-adeo.conf.tmpl. Old root deploy.sh
  removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 13:33:49 -04:00
Phil Dore
5eac433d51 Add heatmap, radar chart, sort/group controls, and About tab
- Heatmap matrix: pillar × market colour-coded table in Compare tab
- Radar/spider chart: pure SVG chart in entity detail view
- Sort controls: sort by overall score, pillar, or group on Markets tab
- Group toggle: cluster entity cards by group (Leroy Merlin / Obramat etc.)
- About tab: home screen tab explaining scoring levels, pillars, and features
- /api/clients now returns pillars, scoring, about for About tab rendering

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 18:15:05 +01:00
Phil Dore
586169b94a Add data quality flags to entity cards and detail view
Highlights markets with missing scores, rationale, gap analysis,
or stale sync data. Also adds per-entity synced date to data.json
and cache-busts script.js.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 17:27:35 +01:00
Phil Dore
aa4d730833 Add Docker deploy files (Dockerfile, docker-compose, deploy.sh)
Matches loreal-spec-tool deploy pattern. Runs on port 3102.
clients/ dir mounted as volume so data.json persists across deploys.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 16:52:07 +01:00
Phil Dore
1fd3dc00ae Initial commit — ADEO Content Maturity Assessment Tool
Multi-client maturity dashboard (Express/vanilla JS, port 3102).
ADEO client: 8 markets, 7 pillars, 59 questions.
Includes data converter, universal PDF summary generator, and
new-client wizard for adding future clients.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 16:15:56 +01:00