Files
xamxam/TODO.md
2026-03-23 11:00:21 +01:00

131 lines
6.7 KiB
Markdown

# TODO
## Styling Redesign (matching design images)
- [x] Redesign shared nav bar (purple gradient top, flat, POSTERG / RÉPERTOIRE / À PROPOS)
- [x] Redesign shared search bar (full-width, icon, bottom border only, white bg)
- [x] Rewrite `common.css` (nav + search bar components)
- [x] Rewrite `main.css` (home page — white bg, media card grid, label below)
- [x] Rewrite `search.css` (répertoire index — 4-col ANNÉES/CATÉGORIES/ÉTUDIANTES/MOTS-CLÉS)
- [x] Rewrite `tfe.css` (TFE page — 2-col, large author/title left, media right)
- [x] Add `apropos.css` (À Propos — 2-col, large monospace text)
- [x] Rewrite `admin.css` (dark bg, purple gradient nav, bottom-border-only form inputs)
- [x] Update `templates/nav.php` (new shared nav partial)
- [x] Update `templates/search-bar.php` (new shared search bar partial)
- [x] Rewrite `public/index.php` (home page with new layout)
- [x] Rewrite `public/search.php` (répertoire index view + search results view)
- [x] Rewrite `public/tfe.php` (individual TFE page)
- [x] Create `public/apropos.php` (À Propos page)
- [x] Rewrite `templates/admin/head.php` (admin nav)
- [x] Rewrite `templates/admin/footer.php` (clean close)
- [x] Rewrite `public/admin/add.php` (form with row layout)
- [x] Rewrite `public/admin/index.php` (dark table)
- [x] Rewrite `public/admin/edit.php` (form with row layout)
- [x] Rewrite `public/admin/login.php` (centered dark login box)
- [x] Rewrite `public/admin/thanks.php` (dark info cards)
- [x] Rewrite `public/admin/import.php` (clean dark form)
## Justfile / Ops
- [x] Simplify `serve` and `deploy` to one recipe each
- [x] Remove sysadmin recipes (server-logs, server-status, deploy-nginx, deploy-admin-tools)
- [x] Extract server scripts to `scripts/` (deploy-server.sh, manage-admin-users.sh)
- [x] Guard `deploy-db` against overwriting existing remote database
- [x] Update README.md and docs/SERVER_SETUP.md to reflect current structure
## Refactor: M2M tags via `tags` + `thesis_tags` junction table
The current schema stores keywords in a `keywords` table joined via `thesis_keywords`.
The field column is named `keyword` (not `name`), breaking the naming convention used by
every other lookup table (`orientations.name`, `format_types.name`, etc.).
More critically, `buildSearchConditions` and the view `v_theses_full` filter keywords
through `GROUP_CONCAT` strings with `LIKE`, bypassing the junction table entirely.
Goal: rename the tables and column to the canonical M2M pattern (`tags`, `thesis_tags`,
`tags.name`), add the missing index, and rewrite all tag queries to use a proper JOIN.
### 1 — Schema migration (`storage/schema.sql` + live DB)
- [ ] Rename table `keywords``tags`; rename column `keywords.keyword``tags.name`
- [ ] Rename junction table `thesis_keywords``thesis_tags`; rename FK column
`thesis_keywords.keyword_id``thesis_tags.tag_id`
- [ ] Composite PK on `thesis_tags(tag_id, thesis_id)` (tag first — matches the lookup
pattern `WHERE t.name = ?`)
- [ ] Add index `idx_tags_name ON tags(name)` (supports exact-match lookup on insert/find)
- [ ] Update `idx_thesis_keywords_*` index names → `idx_thesis_tags_thesis`,
`idx_thesis_tags_tag`
- [ ] Update view `v_theses_full` / `v_theses_public`: replace
`LEFT JOIN keywords k ON tk.keyword_id = k.id … GROUP_CONCAT(DISTINCT k.keyword)`
with `LEFT JOIN tags t ON tt.tag_id = t.id … GROUP_CONCAT(DISTINCT t.name)`
- [ ] Write and test a SQLite migration script
(`storage/migrations/001_rename_keywords_to_tags.sql`)
### 2 — `src/Database.php`
- [ ] `findOrCreateKeyword()``findOrCreateTag()`: query `tags` table, column `name`
- [ ] `getUsedKeywords()``getUsedTags()`: rewrite to use proper M2M JOIN instead of
querying the view:
```sql
SELECT DISTINCT t.* FROM tags t
JOIN thesis_tags tt ON t.id = tt.tag_id
JOIN theses th ON tt.thesis_id = th.id
WHERE th.is_published = 1 ORDER BY t.name
```
- [ ] `buildSearchConditions`: replace the `keywords LIKE :keyword` view-string hack with
a subquery using the junction table:
```sql
EXISTS (
SELECT 1 FROM thesis_tags tt
JOIN tags t ON t.id = tt.tag_id
WHERE tt.thesis_id = theses.id AND t.name LIKE :keyword ESCAPE '\'
)
```
(search still runs on `v_theses_public`; the subquery references the base table)
- [ ] `validateSearchParams`: rename key `'keyword'` → `'tag'` (or keep alias for
backwards-compat during transition)
- [ ] Add backwards-compat alias `findOrCreateKeyword` → `findOrCreateTag` and
`getUsedKeywords` → `getUsedTags` (remove after all callers updated)
### 3 — Admin write paths
- [ ] `public/admin/actions/formulaire.php`: replace `findOrCreateKeyword` +
`INSERT INTO thesis_keywords` with `findOrCreateTag` + `INSERT INTO thesis_tags`
- [ ] `public/admin/edit.php`: same replacement in keyword update block
(`DELETE FROM thesis_keywords` → `DELETE FROM thesis_tags`, insert loop)
### 4 — Public read paths
- [ ] `public/search.php`: rename `$keywords` → `$tags`; update `getUsedKeywords()` call
→ `getUsedTags()`; rename GET param `keyword` → `tag` (keep old param as alias)
- [ ] `public/tfe.php`: `$data['keywords']` → `$data['tags']` (view column rename)
- [ ] `templates/search-bar.php` (if applicable): update any hardcoded `keyword` param refs
### 5 — Tests
- [ ] `tests/Unit/DatabaseTest.php`: add test for `findOrCreateTag` round-trip
- [ ] `tests/Integration/SearchTest.php`: add test for tag-filter search using the new
subquery path (not the LIKE-on-GROUP_CONCAT path)
### 6 — Fixtures / seed data
- [ ] `storage/fixtures/CreateTestDatabase.php`: update to use `tags` / `thesis_tags`
table names and `findOrCreateTag()`
## Pending
- [x] Add flake.nix for Nix-based PHP dev environment
- [x] Add favicon (`<link rel="icon">` → admin_favicon.svg) to all pages; nginx 204 for /favicon.ico
- [ ] Add pagination to répertoire student index (currently capped at 100)
- [ ] Thumbnail generation / cover image support for home grid cards
## Admin / Server
- [x] Create `scripts/setup-server.sh` (one-time server setup: group, ownership, setgid 2775 on dirs)
- [x] Add `just setup-server` recipe (rsync + run setup-server.sh on remote)
- [x] Exclude `.claude` and `.pi` from rsync deploy
- [x] Update `docs/SERVER_SETUP.md` with correct permissions rationale and troubleshooting
- [ ] Add server status view in admin panel (nginx + php-fpm health, site HTTP check)
- [ ] Add server log viewer in admin panel (tail nginx error/access logs via SSH or log endpoint)
- [ ] Add nginx config deploy flow to admin panel (upload `scripts/deploy-server.sh`, run remotely)
- [ ] Add admin user management UI (wraps `scripts/manage-admin-users.sh` on server)