Commit Graph
100 Commits
Author SHA1 Message Date
bruno b83d9b6d35 fix: board._sidebar_data now handles Gitea workspace cookie — tree persists across all pages
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Root cause: board._sidebar_data tried int(gitea:owner:repo) → ValueError → lost context
           Library, Trash, page editor pages showed empty workspace tree

Fix: board._sidebar_data now mirrors dashboard._sidebar_data logic:
     - Detects gitea: prefixed cookie
     - Preserves active_ws_name, workspace_key, gitea_workspace
     - Loads local_ws_id for mirror workspace
     - Tree stays visible on /library, /trash, page editor, etc.
2026-07-14 21:13:37 -04:00
bruno 3c8529fd12 fix: OAuth callback — recover mode from state when session cookie is lost
FlowDeck CI / test (push) Failing after 16s
FlowDeck CI / docker (push) Has been skipped
Root cause: request.session cookie expires during Gitea OAuth redirect
           → oauth_mode lost → link mode falls through to login mode
           → Creates gitea_bruno user instead of linking to local account

Fix: state now carries mode suffix (state:mode)
     Callback recovers mode from state parameter even if session lost
     Allows full session loss but still correctly enters link mode
2026-07-14 20:34:43 -04:00
bruno c5ffab1e39 fix: encode OAuth mode in state parameter — survives session loss
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
Before: oauth_mode stored only in request.session cookie
        → Lost if session expires during Gitea OAuth redirect
        → Link mode falls through to login mode → creates gitea_bruno user

After:  state format: <random>:<mode> (e.g., abc123:link)
        → Mode survives session cookie loss
        → Link mode correctly links to current local user
2026-07-14 16:52:36 -04:00
bruno f4cd301f52 fix: _sidebar_data verifies workspace ownership before loading pages
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Stale numeric workspace cookie from another user now rejected
- workspace_pages only loaded if owner_id matches current user
- Prevents sidebar tree leak of other users' content
2026-07-14 16:25:13 -04:00
bruno de86457f90 fix: prevent cross-user workspace leak via stale cookie
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- _get_active_workspace now verifies workspace owner matches current user
- Fallback: only picks workspace owned by current user (not any user)
- /local-workspace redirects to /workspaces when no workspace exists
- New users no longer see other users' workspaces/projects
2026-07-14 16:09:03 -04:00
bruno 364560c84b fix: Private section populates from mirror workspace when Gitea active
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- private_pages now queried from DB when gitea_workspace=True
- Pages with parent_section='Private' and workspace_id=mirror_ws_id
- Shown in sidebar Private section alongside remote 🔗 tree
2026-07-14 15:44:51 -04:00
bruno 0429ffd824 fix: remove hardcoded workspace_key override in homepage
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Line 146: workspace_key: '' overrideait la valeur correcte de _sidebar_data
→ 🔗 icon now shown for remote workspaces on homepage
2026-07-14 15:28:38 -04:00
bruno a7767f3a94 fix: add missing json import
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-14 15:25:44 -04:00
bruno e8f4cfb631 feat: auto-create local workspace mirror for Gitea projects
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Opening /gitea-workspace auto-creates a local workspace with same name
- New Page/New Folder in remote context → saves to local mirror workspace
- Sidebar stays focused on remote workspace (🔗 icon, remote tree)
- local_ws_id passed to Alpine for API calls
- /api/local-workspace/items accepts workspace_id in body
2026-07-14 15:24:43 -04:00
bruno 7c3f62d094 fix: workspace_key set from cookie → 🔗 icon on homepage for remote workspaces
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-14 12:49:54 -04:00
bruno 9a063bc766 fix: toujours poser cookie gitea workspace côté serveur
FlowDeck CI / test (push) Failing after 8s
FlowDeck CI / docker (push) Has been skipped
2026-07-14 12:47:57 -04:00
bruno 234b880c5b fix: Gitea workspace — correct sidebar name, newPage stays remote, cookie persisted
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
Bug 1: newPageInWorkspace() allait toujours vers local-workspace API
→ Maintenant détecte workspaceKey contient '/' → Gitea API PUT file

Bug 2: workspace_name dans gitea_workspace ne persistait pas
→ Cookie flowdeck_workspace posé côté serveur au premier chargement

Bug 3: icône 📁 fixe dans sidebar — pas d'indication remote
→ 🔗 affiché quand workspace_key contient '/' (remote), 📁 sinon

newFolderInWorkspace() : avertissement si workspace distant
(car les dossiers n'existent pas dans un repo Git)
2026-07-14 12:47:08 -04:00
bruno 724ff4c880 feat(v4.0): wire Share/Publish modal with real API calls
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- publishPage() → POST /api/pages/{id}/publish
- unpublishPage() → DELETE /api/pages/{id}/publish
- shareInvite() → POST /api/pages/{id}/share
- loadShares() → GET /api/pages/{id}/shares
- removeShare() → DELETE /api/pages/{id}/share/{sid}
- All buttons now call real API instead of local state toggle
2026-07-14 12:23:05 -04:00
bruno 15bd9d5ed9 fix: github_routes use access_token (not github_token)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
user_oauth_tokens has generic access_token column, not github_token/gitea_token
2026-07-14 12:21:10 -04:00
bruno 29ef0fb054 feat(v4.0): GitHub routes + CSRF exemptions for share/publish
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
- app/routers/github_routes.py: /api/github/status + disconnect
- CSRF: ajout /api/github, /api/pages, /api/recents aux exclusions
- main.py: registration github_router
2026-07-14 12:19:37 -04:00
bruno bd6fd62734 feat(v4.0): Library tabs + Sidebar OAuth badge + Sharing routes
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
app/routers/library.py: /api/library/recents|favorites|shared|published|private|workspace
app/routers/sharing.py: /api/pages/{id}/share|publish + page_shares
app/templates/base.html: OAuth badge 🦎/🐙, '→ Library' buttons
app/templates/library.html: page avec tabs + filtres source
app/routers/dashboard.py: auth_method + github_linked dans context
tests/test_app.py: tests library + sharing + recents
2026-07-14 12:16:28 -04:00
bruno 802d681212 feat(v4.0): Settings/Integrations — Gitea + GitHub connect/disconnect matrix
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- GitHub integration row ajoutée (🦎 Gitea + 🐙 GitHub)
- Badge 'Primary' sur le provider principal (auth_method)
- Disconnect masqué pour le provider principal
- authMethod, githubLinked, giteaLinked dans Alpine data
- loadGithubStatus() + disconnectGithub() methods
- Matrice respectée: local→déco OK, gitea→déco github OK, github→déco gitea OK
2026-07-14 12:14:41 -04:00
bruno 8eb7049460 docs: ARCHITECTURE v3.0 + ROADMAP v4.0 — comptes, intégrations, sidebar
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
ARCHITECTURE.md:
- Section 6.5: modèle de comptes (local/gitea/github)
- Matrice d'intégrations & règles de déconnexion
- 3 scénarios de workspace (A/B/C)
- Sidebar: règles d'affichage par type de compte
- Share & Publish: modale 2 tabs + schéma DB
- Library: /library?tab= + filtres source
- Trash local-only, édition unifiée, stockage Private
- Plan de migration 5 phases

ROADMAP.md:
- v4.0.0 section prioritaire: Account Model, Intégrations,
  Sidebar rules, Share/Publish, Library, Édition unifiée
2026-07-14 12:07:13 -04:00
bruno e2043123f0 fix: title_prefix block for browser tab — évite conflit Jinja2 page_title double
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Erreur: block 'page_title' defined twice → TemplateAssertionError
Fix: title_prefix (nouveau bloc) pour <title>, page_title (existant) pour Alpine

10 templates mis à jour avec title_prefix.
2026-07-14 09:35:52 -04:00
bruno 8cca247fcd fix: browser tab title uses page_title block — reflète le workspace actif
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
<title>FlowDeck</title> → <title>FlowDeck — {% block page_title %}Home{% endblock %}</title>

Maintenant l'onglet navigateur affiche:
- 'FlowDeck — Home' (page d'accueil)
- 'FlowDeck — bruno/flowdeck' (workspace Gitea)
- 'FlowDeck — Mon workspace local' (workspace local)
2026-07-14 09:34:38 -04:00
bruno cb44652554 fix: Gitea workspace affiche owner/repo dans le titre et topbar
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- Le titre de page (onglet) : 'bruno/flowdeck' au lieu de 'Gitea Workspace'
- Le topbar breadcrumb : owner/repo correctement peuplé
- workspace_name + workspace_initial passés au template
2026-07-14 09:34:02 -04:00
bruno 921f1b7bc1 fix: servir JS/CSS en local — plus de dépendance CDN externe
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Téléchargés et servis depuis /static/js/:
- alpine.min.js (44 KB) — remplace unpkg.com
- htmx.min.js (51 KB) — remplace unpkg.com
- sortable.min.js (45 KB) — remplace cdn.jsdelivr.net
- prism.min.js (19 KB) + prism.css (1.3 KB) — remplace cdnjs

Corrige le bug 'rien ne fonctionne' quand le réseau est lent/absent:
sans CDN, Alpine.js/HTMX/SortableJS ne chargeaient pas →
tous les @click, x-show, x-data, drag-drop inopérants.
2026-07-14 07:44:28 -04:00
bruno 8458cf4a29 fix: defensive display:none on all modals — prevents phantom display
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Si Alpine échoue à s'initialiser, x-show n'était pas traité
et les modals apparaissaient par défaut. display:none en fallback
garantit qu'ils sont cachés, Alpine les montre via x-show.
2026-07-14 07:36:36 -04:00
bruno b755f75f15 fix: rollback Alpine.data registration — keep _wsInitData as global var only
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
L'enregistrement Alpine.data() pouvait créer un conflit avec x-data
qui utilise déjà la variable globale. Revert au comportement original.
2026-07-14 07:23:13 -04:00
bruno b771708bdc fix: @click.away→@click.outside GLOBAL — 16 instances across 5 templates
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Alpine 3.x a renommé .away en .outside. Toutes les occurrences dans:
- base.html (3: user menu, context menu, ws ctx)
- page_editor.html (5: share, perm, access, more, gsMore)
- workspaces.html (1: dialog overlay)
- workspace.html (1: modal overlay)
- local_workspace.html (6: create, rename, delete modals, context menus)

Ces .away cassées empêchaient tous les @click Alpine de fonctionner
sur ces pages (Cancel, Delete, et tous les autres boutons modaux).
2026-07-14 07:16:56 -04:00
bruno 1e15e44a00 fix: Alpine 3.x — @click.away→@click.outside + register _wsInitData
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- @click.away n'existe pas dans Alpine 3.x (renommé @click.outside)
  6 occurrences corrigées dans local_workspace.html
- Ajout Alpine.data('_wsInitData') pour un binding fiable des @click
  (le IIFE seul ne garantissait pas une reconnaissance Alpine propre)
2026-07-14 07:16:27 -04:00
bruno 7edeb373f1 fix: guard delete confirm with null id check — prevents phantom dialog
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Le confirm('Delete') dans contextActions pouvait se déclencher sans
item valide (id null/undefined). Ajout d'un guard if (!id) break.
2026-07-14 07:10:26 -04:00
bruno 449550ac90 fix: wire CSP + RateLimit middleware in main.py (étaient définis mais pas branchés)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Audit v3.0.1: 2/21 features ✗ → CSP/rate-limit middleware
non importés dans main.py. Maintenant branchés.
2026-07-14 00:47:08 -04:00
bruno 72dc4771b4 ROADMAP v4.0.0: ajout Database avancée, Kanban adaptable, Calendar & Meetings
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
4.8 Database Avancée: inline DB, full-page DB, templates de DB,
    validation propriétés, types manquants (Person, Last edited, Created by),
    Timeline/Gantt, Board swimlanes, Calendar drag-drop, Gallery covers

4.9 Kanban Adaptable: colonnes config., cartes configurables,
    couverture, sous-tâches visibles, WIP limits, vues sauvegardées,
    mode compact/détaillé

4.10 Calendar & Meetings: Day/Week/Month, drag-drop reschedule,
    récurrence, timezone, rappels, template Meeting Notes,
    auto-création action items
2026-07-14 00:41:08 -04:00
bruno ec9eb99c98 ROADMAP v4.0.0: delta analysis Notion vs FlowDeck
FlowDeck CI / test (push) Failing after 7s
FlowDeck CI / docker (push) Has been skipped
Analyse exhaustive: 60+ fonctionnalités Notion (2025) vs FlowDeck v3.0.1
→ 45 manquantes identifiées, 30 retenues pour v4.0.0

Tier 1 (Critique — 16 features):
- AI Assistant (LLM intégré, auto-complétion, slash AI)
- Embeds (60+ services, lightbox, previews PDF/vidéo)
- Export (PDF, Markdown, HTML) + Import (Confluence/Evernote)

Tier 2 (Important — 8 features):
- Realtime collaboration (WebSocket, curseurs)
- Comments + @mentions + email notifications
- Callout blocks, table of contents, LaTeX, toggle lists

Tier 3 (Avancé — 6 features):
- Linked databases, charts/dashboards, multi-colonnes
- Command palette Ctrl+P, automations, buttons

v4.1.0 (futur): PWA, SSO, API publique, web clipper
2026-07-14 00:28:26 -04:00
bruno de40c2d83e v3.0.1: qualité & stabilité — tests, sécurité, UX consolidée
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
🧪 Tests: 73 → 130 (+57 tests)
- Upload API, labels sync, commit history (401/400/502/cached)
- File create/update (sha=null, sha=abc)
- Admin delete cascade (12 tests: oauth, tags, workspaces, pages…)
- Gitea status (linked/unlinked/disconnect)
- OAuth link mode (session, redirect, callback)

🔒 Sécurité
- ContentSecurityPolicyMiddleware (CSP headers)
- RateLimitMiddleware (100 req/min/IP)
- Pydantic models: ErrorResponse, SuccessResponse
- Input validation upload (10MB, allowed extensions)
- Pydantic request models

🎨 UX
- static/css/design-tokens.css (500 lines, thèmes + skeletons)
- Toast system: 16 alert() remplacés par toast()
- 59 lignes CSS dupliquées retirées (6 templates)
- Skeletons cohérents sur toutes les vues

⚡ Performance
- Cache TTL sur get_file_commits (consistant avec les autres méthodes)
2026-07-13 23:08:53 -04:00
bruno e04b3a38a4 fix: get_file_commits use consistent caching (_cached/_set_cache)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 22:57:46 -04:00
bruno b863afab59 ROADMAP: v2.8.0-v3.0.0 complétées — roadmap terminée 🎉
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 22:36:01 -04:00
bruno a497c129d3 Upload via FlowDeck
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 22:34:37 -04:00
bruno 6f15ad3ad4 v2.8.0 WIP: create/upload files + commit history + labels sync
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- POST /api/gitea/projects/{owner}/{repo}/upload (binary upload)
- get_file_commits() in GiteaClient
- GET /api/gitea/projects/{owner}/{repo}/commits (per-file history)
- POST .../sync-labels (Gitea labels → FlowDeck tags)
- New file form + upload button in gitea_workspace.html topbar
2026-07-13 22:33:47 -04:00
bruno f25c8ebaf0 feat: force Gitea ré-auth en mode link (_force timestamp)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Ajout d'un paramètre _force avec timestamp dans l'URL d'autorisation
quand mode=link, pour forcer Gitea à ne pas utiliser le cache.

NOTE: Gitea ne supporte pas prompt=login. Si auto-approve persiste,
il faudra ajouter un champ token manuel en fallback.
2026-07-13 22:18:31 -04:00
bruno 06bf016392 fix: bfcache restore — theme persistant après navigation retour
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Problème: window.history.back() restaurait la page depuis bfcache
→ le IIFE initTheme() ne se ré-exécutait pas
→ le thème dark s'affichait même après avoir sélectionné light

Fix:
- applySavedTheme() → fonction nommée, pas IIFE
- window.addEventListener('pageshow', e.persisted → reapply)
- Proper else branch: removeProperty pour le dark mode
2026-07-13 21:45:29 -04:00
bruno 17824deae2 fix: déconnexion Gitea effective + menu user light mode
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
1. _require_gitea: retrait fallback admin token → 401 si pas connecté
2. user-menu-dropdown: background var(--bg-primary) au lieu de #1E1E1E
3. applyTheme() déjà immédiat via style.setProperty sur documentElement
2026-07-13 21:39:16 -04:00
bruno e3851b4f12 feat: OAuth link mode + settings light mode CSS variables
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
1. /auth/login?provider=gitea&mode=link:
   - Sauve 'oauth_mode=link' dans la session
   - Callback: link OAuth token à l'utilisateur courant (pas de nouveau compte)
   - Redirige vers /settings#integrations

2. Bouton Connect dans Settings → mode=link

3. Settings light mode: remplacé 12 couleurs codées en dur par CSS variables
   - .settings-panel, .modal-box, .settings-input
   - .admin-table th/td, .stat-card
   - .btn-sm, .btn-sm:hover
2026-07-13 21:24:04 -04:00
bruno 6c8327c021 fix: delete_user cascade — ajout comments, page_history, favorites, gitea_private_pages, tags
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 21:02:39 -04:00
bruno 1e36b03532 fix: delete_user cascade — pages n'a pas de owner_id, passe par workspace_id
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 21:02:10 -04:00
bruno aa2354a25a fix: exempt /api/admin + /api/gitea du CSRF middleware
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Les endpoints admin ont déjà leur propre protection admin_required.
Le CSRF middleware bloquait les DELETE/PUT sur ces routes.
2026-07-13 21:01:21 -04:00
bruno ef88ee4c55 fix: virgule manquante après saveDefaultView() — SyntaxError cassait tout le JS
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
settings.html:773: '} async' → '}, async'
Cette SyntaxError empêchait Alpine.data('settingsInit') d'être parsé
→ toutes les variables Alpine étaient undefined
2026-07-13 20:56:42 -04:00
bruno 86b34dc063 test via FD
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 20:48:40 -04:00
bruno 6d98070986 fix: ajout X-CSRF-Token dans les requêtes save/delete Gitea
FlowDeck CI / test (push) Failing after 8s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 20:48:40 -04:00
bruno 0d66b5d543 fix: scope Alpine gitea_workspace + commit admin fallback + settings cleanup
FlowDeck CI / test (push) Failing after 6s
FlowDeck CI / docker (push) Has been skipped
1. gitea_workspace.html: owner/repo en Jinja2 dans la topbar (pas Alpine)
2. gitea.py: save_file/delete_file → _require_gitea (admin token can write)
3. settings.html: retrait doublon defaultView, fix workspace_name Jinja2
2026-07-13 20:47:46 -04:00
bruno e22efc1d9c fix: retirer bouton dark/light mode du sidebar, ajouter dans Settings
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Sidebar: retrait du bouton 🌓 (dark/light) + bouton 🚪 logout
- Settings → Account → Preferences: nouveau sélecteur de thème (Dark/Light)
- Persistance localStorage 'fd_theme' — appliqué au chargement de chaque page
- initTheme() dans base.html + applyTheme() dans settings.html
- toggleTheme() conservé dans le JS mais plus utilisé dans l'UI
2026-07-13 17:08:30 -04:00
bruno c1f854a54a docs: mise à jour ROADMAP.md, CHANGELOG.md et docs/ROADMAP.md
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
ROADMAP.md:
- Ajout v2.4.0 (tags/user), v2.5.0 (admin panel), v2.6.0 (my account)
- Ajout v2.7.0 (Gitea P1), v2.7.1 (private pages)
- Roadmap future: v2.8.0 (Gitea P2), v2.9.0 (GitHub), v3.0.0 (Pro UX)

CHANGELOG.md:
- Entries v2.4.0 → v2.7.1 avec tous les détails
- Structure Added/Fixed cohérente

docs/ROADMAP.md (v3.0):
- Phase 1-5 checkboxes mises à jour (45/52 items done)
- Reste: GitHub OAuth, Quick switch, API tokens, sessions actives
2026-07-13 17:05:45 -04:00
bruno 5cc27b4535 fix: get_user_repos(limit=100) — bruno/flowdeck était sur page 2
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 17:02:11 -04:00
bruno caa00c54bc feat: fallback token admin GET + Private Pages persistantes
FlowDeck CI / test (push) Failing after 17s
FlowDeck CI / docker (push) Has been skipped
1. _require_gitea: fallback token admin pour les GET (orgs, projects, tree, file)
   _require_user_gitea: token OAuth requis pour les write (save, delete)

2. Private Pages: table gitea_private_pages (user_id, owner, repo, title, content)
   API CRUD: GET/POST/PUT/DELETE /api/gitea/projects/{o}/{r}/private-pages
   UI: liste + éditeur dans le workspace Gitea, lien 🔒 Private Pages dans sidebar
   Lié logiquement au projet (owner+repo), conservé entre sessions
2026-07-13 17:01:19 -04:00
bruno 6b000d892b fix: chargement tree sidebar 100% client-side (pas de asyncio.run)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Avant: _sidebar_data() utilisait asyncio.run() → RuntimeWarning + 302 redirects
Après: gitea_workspace.html appelle loadSidebarTree() → fetch API → injecte dans #sidebar-workspace-items

- base.html: ajout id='sidebar-workspace-items' sur le <ul> workspace
- dashboard.py: _sidebar_data() ne fait plus de fetch serveur, juste passe owner/repo
2026-07-13 16:43:34 -04:00
bruno e78ca4b775 feat: sidebar arborescence Gitea + tab user repos avec vrai username
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
1. Tab user repos: fetch username via /auth/user → affiche 'bruno' au lieu de 'Personal'
2. Sidebar: ws_cookie='gitea:owner:repo' → _sidebar_data() fetch le tree depuis Gitea API
3. base.html: data-gitea-path/type/sha sur les items workspace pour les projets Gitea
4. gitea_workspace.html: refonte sans tree panel → navigation via sidebar
   - Clic fichier → ouvre dans le contenu (lecture + edit + commit)
   - Clic dossier → lazy-load les enfants dans le sidebar
5. openGitea(): set cookie flowdeck_workspace avant navigation
2026-07-13 16:42:11 -04:00
bruno 5fe31aeffa feat: redirect_uri dynamique basé sur Host header
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
Avant: oauth_redirect_uri codé en dur à localhost:8080
→ impossible d'utiliser l'OAuth depuis une autre machine du réseau

Après: le redirect_uri est construit à partir du header Host de la requête
→ localhost:8080 → http://localhost:8080/auth/callback
→ 192.168.30.101:8080 → http://192.168.30.101:8080/auth/callback

⚠️ L'utilisateur doit ajouter les 2 URIs dans Gitea OAuth App settings.
2026-07-13 15:59:39 -04:00
bruno 7cbb226e62 fix: Register/Link with Gitea ne crée plus de session admin fantôme
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Avant: get_provider('gitea') → None (pas de client OAuth configuré)
       → fallback créait automatiquement une session admin
       → le bouton 'Register with Gitea' connectait l'utilisateur en admin !

Après: affiche une page d'erreur propre:
       '⚠ Gitea OAuth not configured — The Gitea integration has not
        been set up by the server administrator. ↩ Use local login'
2026-07-13 15:23:10 -04:00
bruno e9d1c32b4f feat: Gitea — register, settings connect, tabs org, search
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
1. Pas de Gitea sans config: _require_gitea() → 401 si pas de token OAuth
2. Register Gitea: boutons "Login/Register with Gitea" dynamiques selon l'onglet
3. Settings → Integrations: ✅ Active / 🔗 Connect / Disconnect + API status/disconnect
4. Workspaces: tabs par org (All | org1 | org2) + barre recherche 🔍 filtrage live
5. API: GET /api/gitea/status, DELETE /api/gitea/disconnect
2026-07-13 15:17:17 -04:00
bruno 46336df21b feat: frontend Gitea — workspaces 2 sections + gitea workspace vue
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
workspaces.html:
- Section 📁 Local Workspaces (existante, avec badges)
- Section 🔗 Gitea Projects (par organisation, lazy load)
- États: loading, not_linked (lien pour login OAuth), error (retry), ok

gitea_workspace.html:
- Arbre fichiers (lazy: un dossier à la fois)
- Vue fichier (lecture seule → bouton Edit)
- Éditeur avec zone de commit (message + historique dropdown)
- Section 🔒 Private Pages (placeholder pour pages FlowDeck locales)
- Bouton Delete fichier

Routing: /gitea-workspace?owner=X&repo=Y

Fallback: token admin serveur si pas de token OAuth utilisateur
2026-07-13 14:58:01 -04:00
bruno 00860417a8 fix: param order in gitea routes (request first)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 14:52:33 -04:00
bruno 5baae598bf fix: indentation gitea_client + request defaults
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 14:51:58 -04:00
bruno 9f667ae9e0 feat(gitea): API routes + per-user client + repo contents
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
GiteaClient:
- __init__(user_token=None) — per-user OAuth token ou admin token
- get_repo_contents(owner, repo, path) — lazy: un niveau à la fois
- get_file_content(owner, repo, path) — base64 décodé
- create_or_update_file(...) — PUT avec sha pour update
- delete_file(owner, repo, path, sha, message)
- _invalidate_tree_cache() — invalidation après write

Routes (/api/gitea):
- GET /orgs — liste des organisations
- GET /projects?org=x — repos user ou org
- GET /projects/{owner}/{repo}/tree?path=x — arborescence lazy
- GET /projects/{owner}/{repo}/file?path=x — contenu fichier
- PUT /projects/{owner}/{repo}/file — save + commit
- DELETE /projects/{owner}/{repo}/file?path=x&sha=x — delete
- GET /projects/{owner}/{repo}/labels — labels → tags

Helper: get_user_gitea_client(request) → GiteaClient ou None
2026-07-13 14:50:46 -04:00
bruno 5d1857941e feat: tags personnalisés par utilisateur (user_id)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
DB:
- tags.user_id REFERENCES users(id)
- UNIQUE(name, user_id) au lieu de UNIQUE(name)
- Migration v2.6: alter + recreate table

API (tous les endpoints tags):
- POST/PUT/DELETE /api/settings/tags: filtré par user_id
- GET /api/settings/tags/all: retourne uniquement les tags du user
- GET/POST /api/local-workspace/*/tags: scope user

→ Les tags de l'utilisateur 1 ne sont pas visibles par l'utilisateur 2
2026-07-13 13:58:13 -04:00
bruno f262076545 fix: refresh session cookie après update_account
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Le cookie de session n'était pas mis à jour après modification du compte
→ le template re-rendait avec les anciennes données au rechargement.
Maintenant le serveur émet un nouveau cookie avec les données fraîches.
2026-07-13 13:49:13 -04:00
bruno 4ea512d007 feat: My Account — modifier username, nom, email, mot de passe
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
Backend:
- PUT /api/settings/account (full_name, login, email, password)
- Vérifie que le username n'est pas déjà pris
- Password min 6 caractères

Frontend (Settings → My Account):
- Champs éditables: Username, Full name, Email
- Section Change password avec toggle 👁/🙈
- Bouton Save changes + Update password
- Message de confirmation ✓ / ✗ avec timeout 3s
2026-07-13 13:42:11 -04:00
bruno e42c5e1e4b fix: toggle voir/cacher mot de passe + label 'Email or username'
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
- Bouton 👁/🙈 dans le champ password (login + register)
- Label changé de 'Email' à 'Email or username' (les users créés via admin ont un login, pas forcément un email)
- Type email → type text pour accepter les usernames
2026-07-13 13:34:18 -04:00
bruno e01e410d43 fix: CSRF token dans toutes les requêtes admin (adminFetch)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Tous les appels /api/admin/* passent maintenant par adminFetch()
qui ajoute X-CSRF-Token depuis le cookie csrf_token
2026-07-13 13:26:07 -04:00
bruno 9e9ea181e6 fix: admin_required check DB direct en fallback (session cookie stale)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Le cookie de session peut dater d'avant le flag is_admin →
vérification DB directe si la session ne contient pas is_admin
2026-07-13 13:19:38 -04:00
bruno 057ff9f524 ui: settings panel 1050px (était 820px) pour afficher tous les champs admin
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 13:14:26 -04:00
bruno 253f5b215c fix: admin query adaptée au schéma réel (pas de owner_id/is_folder)
FlowDeck CI / test (push) Failing after 13s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 13:00:42 -04:00
bruno 97d6ad7a91 feat: administration — users, roles, stats, audit
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
DB:
- login_history table (user_id, ip, user_agent, timestamp)
- Migration v2.5: alter users + create login_history

Auth:
- Premier utilisateur = admin (is_admin=1)
- _log_login() après chaque connexion (register, local-login, OAuth)

Backend (app/routers/admin.py):
- admin_required middleware (vérifie is_admin)
- GET  /api/admin/users     → liste users + stats par user
- POST /api/admin/users     → créer user
- PUT  /api/admin/users/:id → modifier (name, email, password, admin, active)
- DELETE /api/admin/users/:id → supprimer + cascade
- GET  /api/admin/stats     → totaux globaux
- GET  /api/admin/audit     → historique login

Frontend (settings.html):
- Nav Admin visible seulement si userIsAdmin
- Users & Roles: stats cards, create/edit/delete users, table complète
- Audit Log: historique login avec date, IP, user-agent
- CSS professionnel: table-wrap, admin-table, stat-card, role-badge, status-dot
2026-07-13 12:59:36 -04:00
bruno ea591bd577 fix: input rename tag en dark theme
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Ajout .settings-input: fond #2A2A2A, bordure #555, texte #ddd, focus bleu
2026-07-13 12:42:19 -04:00
bruno 91032de704 fix: 5 corrections — modals opaques, tags visibles, fermeture menu, filtrage, pastilles
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
1. Settings modals: fond rgba(0,0,0,.85) + boîte #1E1E1E (plus opaque)
2. Tags existants: sync forcé via menuEl._x_dataStack en plus de _ctxMenuData
3. Ajout tag: ferme .ctx-menu après succès (style.display='none')
4. Filtrage tags: toggleTagFilter() appelle doFilter() + _filterTreeByTag
5. Pastilles: tag-dot supprimé, :style="{background: t.color}" sur tag-chip
   → 7 occurrences mises à jour (filter bar, tree, preview, JS gen)
2026-07-13 11:55:29 -04:00
bruno 51c6002f08 fix: 5 bugs — couleur tag, tags existants, modal settings, rename, filtrage
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
1. ctxAddNewTag lit window._ctxMenuData.ctxNewTagColor (pas this.ctxNewTagColor)
   → la couleur sélectionnée dans le menu est maintenant sauvegardée

2. onContextMenu: charge workspaceTags si vide avant de calculer ctxAvailTags
   → les tags existants apparaissent dans le dropdown

3. Settings: CSS modal-overlay/modal-box/.btn-danger ajouté
   → le modal delete n'est plus transparent

4. Rename tag: modal avec input au lieu de prompt()
   → double-clic → modal avec couleur + input + autofocus

5. doFilter: _filterTreeByTag filtre displayTree quand tagFilter est actif
   → le filtrage par tags fonctionne dans toutes les vues
2026-07-13 11:34:43 -04:00
bruno 53865f136d fix: tags contextuels + rename/delete confirm dans Settings
FlowDeck CI / test (push) Failing after 8s
FlowDeck CI / docker (push) Has been skipped
Context menu (_ctxMenuData):
- Remplacé getters par propriétés simples (Alpine ne réagit pas aux getters)
- Sync _wsInitData → _ctxMenuData dans onContextMenu, ctxAddNewTag, ctxRemoveTag
- Les 4 tags existants apparaissent maintenant dans le dropdown

Settings > Tags:
- Double-clic sur un tag → prompt rename (PUT /api/settings/tags/<id>)
- Suppression: modal de confirmation au lieu de confirm() natif
- Affiche le nombre d'items impactés si tag utilisé
2026-07-13 11:20:51 -04:00
bruno c524478ff2 fix: _ctxMenuData — objet léger sans conflit Alpine
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
_wsInitData (162 keys) causait "Cannot redefine property: $nextTick"
quand réutilisé comme x-data sur .ctx-menu. Alpine ajoute des propriétés
magiques ($nextTick, $el, etc.) et certaines entrent en conflit avec
les propriétés de l'objet massif.

Solution: window._ctxMenuData — objet minimal avec getters/setters
déléguant à _wsInitData. Seulement 20 propriétés, zéro conflit.

+ Restauré les directives Alpine (x-show, x-for, :style) dans le menu
  puisque le scope Alpine fonctionne maintenant.
2026-07-13 11:05:34 -04:00
bruno 0a0a330b55 fix: ctx-menu a son propre x-data="_wsInitData" pour que les directives Alpine internes fonctionnent
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Le .ctx-menu était hors du scope _wsInitData dans le DOM (sibling du wrapper).
Ajouter x-data directement sur l'élément lui donne accès à toutes les variables
Alpine internes (ctxTagExistingOpen, ctxTagAdding, ctxAvailTags, ctxTagColors, etc.)

Les toggles de dropdown utilisent maintenant du DOM natif pour éviter les
problèmes de scope.
2026-07-13 10:48:32 -04:00
bruno 92eca626b7 fix: tags contextuels — couleur envoyée et stockée par l'API
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
Backend (dashboard.py):
- POST /api/local-workspace/items/<id>/tags accepte maintenant 'color'
- INSERT INTO tags (name, color) au lieu de INSERT INTO tags (name)
- Si tag existe déjà, garde sa couleur existante

Frontend (local_workspace.html):
- ctxAddNewTag envoie {name, color} dans le body de la requête
  (avant: seul {name} était envoyé, la couleur était ignorée)
2026-07-13 10:45:47 -04:00
bruno 0ad1a69994 fix: menu contextuel en DOM natif (bypass Alpine)
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
Alpine ne détecte pas les changements sur ctxMenu (objet imbriqué
hors du scope _wsInitData dans le DOM). Le :style et x-show restent
bloqués sur les valeurs initiales.

Solution radicale: manipulation DOM directe
- onContextMenu: menu.style.display='block' + position left/top
- ctxMenuOpen*/Rename/Duplicate/Delete: menu.style.display='none'
- @click.outside/@keydown.escape: DOM direct aussi
- ctx-menu HTML: style="display:none" initial
2026-07-13 10:33:52 -04:00
bruno 3e291ddc67 fix: ctx-menu utilise :style display au lieu de x-show
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
x-show="ctxMenu.visible" ne réagit pas aux changements d'objet imbriqué
dans Alpine. :style avec display: ctxMenu.visible ? 'block' : 'none'
est bindé directement sur le style inline, donc réactif.
2026-07-13 10:31:01 -04:00
bruno a57b435bd2 fix: contexte menu — sync raw data to Alpine via réassignation
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
_wsInitData.onContextMenu() remplit _wsInitData.ctxMenu
→ ctxMenu = _wsInitData.ctxMenu recopie dans Alpine
→ Alpine détecte le changement et affiche le menu
2026-07-13 10:29:14 -04:00
bruno c096f09b79 fix: ctxMenu réactivité Alpine — réassignation complète au lieu de propriétés
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Alpine ne détecte pas les changements sur les propriétés imbriquées
d'un objet (ctxMenu.visible = true). Il faut réassigner l'objet entier:
this.ctxMenu = {visible:true, x:..., y:..., node:..., tags:...}

Impact: onContextMenu (show), ctxMenuOpenPage/OpenFolder/Rename/Duplicate/Delete (hide)
+ repositionnement dans nextTick
2026-07-13 10:28:34 -04:00
bruno 74651ee26c fix: contexte menu — .call() pour binder this à Alpine
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Le Alpine proxy ne contient pas les méthodes (onContextMenu, onTouchStart, etc.)
car l'objet _wsInitData est mergé avec appState() et les fonctions ne sont
pas copiées comme propriétés directes.

Fix: _wsInitData.onContextMenu.call(, )
→  = Alpine data réactive → this.ctxMenu.visible = true fonctionne
2026-07-13 10:27:13 -04:00
bruno 282eecf80c fix: menu contextuel right-click + long-press mobile
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Desktop:
- @contextmenu.prevent corrigé: window._wsData → onContextMenu()
  (window._wsData n'existait pas, le handler était mort)

Mobile:
- @touchstart/@touchmove/@touchend ajoutés sur ws-split
- Détection long-press: >600ms sans mouvement >10px
- Recherche du [data-ws-id] le plus proche
- Appel onContextMenu avec les coordonnées tactiles

Fermeture:
- @click.outside ajouté sur .ctx-menu
- @click.self maintenu sur ws-split pour fermer en cliquant ailleurs
2026-07-13 10:25:54 -04:00
bruno b865b5da6c fix: ws-split fermait prématurément (>) — les attributs devenaient du texte
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Le > de fermeture était sur la même ligne que <div class="ws-split">
→ les attributs (@contextmenu, @click, tabindex, x-ref) sur les lignes
  suivantes devenaient du contenu texte affiché dans la page.

Fix: > déplacé à la fin de x-ref="layout">
2026-07-13 09:56:22 -04:00
bruno 589035336d fix: _wsInitData global (sans var) pour que Alpine x-data le trouve
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 09:45:09 -04:00
bruno c8685b6dcc fix: wrapper x-data _wsInitData englobant tout le contenu
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
Les modals (create/rename/delete) étaient des siblings de ws-split dans le DOM,
pas des enfants — à cause d'un problème de nesting HTML avec les <template> Alpine.
Résultat: x-show="showCreate" ne trouvait pas 'showCreate' dans le scope parent.

Fix: wrapper <div x-data="_wsInitData"> autour de tout le {% block content %},
plus déplacement des @dragover/@dragleave/@drop/@keydown sur ce wrapper.
Le ws-split garde ses attributs restants (@contextmenu, @click, tabindex, x-ref).
2026-07-13 09:43:46 -04:00
bruno b555b67546 revert: remettre les icônes seules (l'utilisateur veut juste corriger l'action)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-13 09:39:01 -04:00
bruno a77eab6050 fix: boutons New File/New Folder avec texte visible + CSS btn-create
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Ajouté texte 'New File' et 'New Folder' aux boutons icônes
- Ajouté CSS .btn-create avec width:auto pour accommoder le texte
  (l'ancien CSS .btn-icon imposait width:34px fixe qui coupait le texte)
- Les boutons étaient des icônes seules (📄 📁) sans texte,
  donc difficiles à trouver pour l'utilisateur
2026-07-13 09:28:14 -04:00
bruno b94d25bff5 fix: injecter toutes les props _wsInitData comme globales window
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Alpine évalue les expressions comme tree, flatTree, online, etc.
dans un scope qui n'hérite pas toujours de _wsInitData.
En les exposant comme window.X, Alpine les trouve toujours.

Supprime les 36 erreurs restantes sur /local-workspace.
2026-07-13 08:16:10 -04:00
bruno ca73c6902f fix: x-data sans window. prefix + suppression x-for inutile
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
- Changé x-data="window._wsInitData" → x-data="_wsInitData"
  (Alpine évalue mieux sans le préfixe global)
- Supprimé <template x-for="node in flatTree"> dans une table cachée
  (x-show="false", jamais visible mais Alpine l'évaluait quand même)
2026-07-13 08:15:20 -04:00
bruno 6f8976817a fix: 148 erreurs Alpine.js — IIFE avant le DOM x-data
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Cause: l'IIFE window._wsInitData était située APRÈS le <div ws-split>.
Alpine évaluait x-data="window._wsInitData" AVANT que l'IIFE ne tourne
→ toutes les propriétés (flatTree, tree, online, ctxMenu, preview*, etc.)
   étaient undefined → 148 erreurs Alpine Expression Error.

Fix: déplacement de l'IIFE (lignes 871-2405) avant le ws-split (ligne 339).
Ordre corrigé: IIFE → _wsInitData prêt → ws-split x-data OK.

Vérification: le diagnostic log « ws-split about to render, _wsInitData exists: »
affichera maintenant true au lieu de false.
2026-07-13 08:10:03 -04:00
bruno ae3f8b473a feat: frontend error capture — diagnostic instantané pour Hermes
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- app.js: intercepte window.onerror + unhandledrejection
  Envoie automatiquement au backend via POST /api/frontend-error
  Déduplication, throttling 1/sec, max 50 erreurs buffer local
  window.__flowdeck_errors accessible en console debug

- api.py: 2 nouvelles routes
  POST /api/frontend-error — reçoit erreurs JS, déduplique, logge
  GET /api/frontend-errors?clear=true — Hermes lit les erreurs

- csrf.py: exemption /api/frontend-error du CSRF

Usage Hermes après chaque déploiement:
  curl -s http://localhost:8080/api/frontend-errors | jq .
  → Voir TOUTES les erreurs JS en temps réel
2026-07-13 07:52:52 -04:00
bruno 3718ad488c fix: 6 getters → propriétés plain + _recompute() (étape 1)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Alpine 3.14.9 ne supporte pas les getters dans le Proxy x-data.
Converti en propriétés mises à jour via _recompute() dans:
- init() après chargement tree
- _loadFolder() après chaque navigation
- doSort() / doFilter() après modifs

Getters remplacés:
- pathValue, canGoBack, canGoForward, flatTree,
  filteredTableItems, contentSnippetMap
- _computeFilteredTableItems() extrait de get filteredTableItems

Zéro getter restant, braces/parens équilibrés, 73 tests OK
2026-07-12 22:24:24 -04:00
bruno e34ef6193c Fix Alpine.js _wsInitData global access in workspace template
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-12 21:12:52 -04:00
bruno 9a0a8893c8 fix: 3 derniers ; → , dans les expressions Alpine (15 total)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- addTag(...); → addTag(...),
- ctxAddExistingTag(t); → ctxAddExistingTag(t),
- ctxAddNewTag(...); → ctxAddNewTag(...),

Zéro ; restant dans les expressions Alpine. Vérifié par script.

73 tests OK
2026-07-12 20:59:03 -04:00
bruno 1c88afda85 fix: tous les ; → , dans les expressions Alpine (12 occurrences)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Cause racine: local_workspace.html override le block topbar avec son
propre hamburger button qui avait encore ; au lieu de , dans l'expression
ternaire. Alpine parse les expressions via return <expr> → le ; terminait
le return prématurément → SyntaxError → cascade d'échecs d'initialisation
des composants enfants.

Corrigé dans:
- base.html: sidebar overlay @click (1 occurrence)
- local_workspace.html topbar hamburger (1 occurrence)
- local_workspace.html: 10 autres expressions (viewMode, searchQuery,
  filterType, draggedItemId, tagFilter, ctxAddNewTag, navigateToPath)

73 tests OK
2026-07-12 20:45:24 -04:00
bruno 2f3e52ebb0 fix: ; → , dans l'expression ternaire appState() — cause racine de toutes les ReferenceError
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
Le hamburger button avait mobileSidebarOpen = true; sidebarCollapsed = false
Le ; casse le parser d'expression Alpine (return <expr> → le ; termine le statement)
En cascade, l'erreur empêche l'initialisation correcte du composant parent,
ce qui brise tous les composants enfants (wsInit → ctxMenu, modals, preview, etc.)

C'est le bug qui persistait depuis des jours à travers 5+ approches différentes.
2026-07-12 20:40:05 -04:00
bruno c3291b0231 debug: console.log diagnostics pour identifier si cache ou bug Alpine
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-12 20:32:46 -04:00
bruno 9d300d1984 fix: var _wsInitData globale + anti-cache headers HTML
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- x-data="_wsInitData" référence la variable globale JS (pas window.)
- var _wsInitData = IIFE — propriété window automatique pour compatibilité window._wsData
- Headers Cache-Control: no-cache, no-store, must-revalidate sur la page HTML
- 73 tests OK
2026-07-12 20:24:49 -04:00
bruno 996e50bb06 fix: x-data="window._wsInitData" — IIFE synchrone contourne les bugs Alpine.data/alpine:init
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- window._wsInitData = (function() { return {...}; })() — exécution synchrone garantie
- x-data pointe directement sur l'objet global, sans enregistrement Alpine requis
- Contourne les problèmes de timing alpine:init vs Alpine.data vs nested x-data
- 73 tests OK
2026-07-12 20:20:11 -04:00
bruno cce132d771 fix: Alpine.data() avec x-data="wsInit" (sans parenthèses) + cache busting v2.4.6
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- Changé function wsInit() → Alpine.data('wsInit', ...) avec addEventListener('alpine:init')
- x-data="wsInit()" → x-data="wsInit" (syntaxe correcte pour Alpine.data)
- Ajouté ?v=2.4.6 sur CSS et JS pour bust le cache navigateur
- Version bumpée à 2.4.6
2026-07-12 19:55:30 -04:00
bruno dc630c9ba7 fix: wsInit() en fonction globale — contourne Alpine.data qui ne s'enregistrait pas
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- wsInit() était enregistré via Alpine.data() dans alpine:init →
  ne fonctionnait pas → toutes les variables undefined (ReferenceError)
- Changé en function wsInit() globale → x-data='wsInit()' appelle
  la fonction directement, zéro enregistrement Alpine
- Supprimé les wrappers Alpine.data() et addEventListener('alpine:init')
- Braces vérifiés: 397/397 équilibrés
- window._wsData.set dans init() avant await (contexte menu)
2026-07-12 18:06:43 -04:00