Commit Graph
100 Commits
Author SHA1 Message Date
bruno d4fb095baf feat: unified header across all pages (Notion-inspired breadcrumb + actions)
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
Created a shared _header.html template with:
- Hamburger button (toggle sidebar)
- Breadcrumb navigation with clickable segments and separators
- Page icon + title display
- Right-side action buttons (configurable per page)
- Dropdown panel CSS for More/New menus

Updated all pages to use the unified header:
- workspaces.html: Home / Workspaces + login/settings
- workspace.html: Workspace — Projects + login/settings
- local_workspace.html: workspace name
- gitea_workspace.html: Home / owner/repo + New/Upload/Refresh/Settings
- page_editor.html: title + Edited/Share/Copy/Favorite/More dropdown
- settings.html: Settings

Added CSS for breadcrumb, dropdown panel components.
2026-07-16 12:30:18 -04:00
bruno 8c0b55635c feat: soft-delete and undo/restore for local-workspace items
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Backend:
- DELETE /api/local-workspace/items/{id} now soft-deletes (sets deleted_at
  instead of hard DELETE) — items go to trash, not permanently gone
- New POST /api/local-workspace/items/{id}/restore to undo a delete
- _load_workspace_pages() and _load_children() now filter deleted_at IS NULL
  so soft-deleted items disappear from sidebar and tree queries

Frontend:
- undoDelete() now calls the restore API per item (single or bulk)
- bulkDelete() now shows the same undo banner as context menu delete
- All delete paths (ctxMenu, bulk, modal) use the same soft-delete + undo flow
2026-07-16 10:28:17 -04:00
bruno 631c106b01 fix: context menu uses Alpine proxy (window._wsData) instead of raw object
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
The context menu component (_ctxMenuData) was calling methods on
window._wsInitData (the raw JS object), NOT on Alpine's reactive proxy.
This meant that changes made by ctxMenuDelete/ctxMenuDuplicate (like
updating displayTree) were applied to the raw object but not reflected
in Alpine's reactive proxy that controls DOM rendering.

Fix: _ctxMenuData now uses a _ws() helper that returns window._wsData
(Alpine proxy, set in init()) with fallback to window._wsInitData for
safety. All context menu actions now go through the reactive proxy.
2026-07-16 09:59:07 -04:00
bruno 30e1879ac2 fix: deleteWithUndo uses _reloadAfterAction() instead of manual tree manipulation
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Replaced fragile _removeFromTree() + displayTree spread (which had Alpine
reactivity issues) with a clean _reloadAfterAction() call that reloads the
tree from the API. This is the same approach used by doDelete() and
doRename(), which work reliably. _reloadAfterAction also triggers the
sidebar refresh via window.appState.refreshSidebarTree().
2026-07-16 09:45:45 -04:00
bruno 6e4adaad8b fix: direct sidebar refresh via window.appState instead of events
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Replaced the fragile event-based sidebar refresh with direct function calls:
- appState.init() now sets window.appState = this
- _reloadAfterAction(), doCreate(), deleteWithUndo() call
  window.appState.refreshSidebarTree() directly (no DOM event)
- Sidebar handlers (drop, deleteWorkspacePage, wsCtxAction, newFolder)
  call window._wsData._reloadAfterAction() directly (no DOM event)
- Removed event listeners for flowdeck:workspace-changed and
  flowdeck:sidebar-refresh from local_workspace.html

This is more reliable than CustomEvent which had timing/scope issues.
2026-07-16 09:41:46 -04:00
bruno 50f8e0a938 fix: sidebar drag-drop uses dynamic refresh instead of full page reload
FlowDeck CI / test (push) Failing after 6s
FlowDeck CI / docker (push) Has been skipped
- Sidebar 'drop' handler now calls refreshSidebarTree() + dispatches
  'flowdeck:workspace-changed' instead of window.location.reload()
- Global refreshSidebarFromEvent() now targets .app-layout[x-data] first
  to avoid picking up the wrong Alpine component when multiple x-data
  elements exist on the page
2026-07-16 09:29:34 -04:00
bruno 4217978eaa fix: ctxMenuDelete triggers sidebar refresh via flowdeck:sidebar-refresh
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
deleteWithUndo() (called by ctxMenuDelete) was removing the node from the
local tree but never notifying the sidebar to refresh. Added dispatch of
'flowdeck:sidebar-refresh' event so the sidebar tree updates dynamically
without requiring a full page reload.
2026-07-16 09:24:24 -04:00
bruno ae2b1c5664 fix: use backslash-escape for single quotes (not HTML entity)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
HTML entities like ' are decoded by the browser BEFORE Alpine evaluates
the expression, so the JS parser still sees a raw single quote. Backslash
escape (\') is the correct approach: the HTML parser preserves it, then
JavaScript interprets \' as an escaped quote in the string literal.
2026-07-16 09:18:20 -04:00
bruno 5b6b251119 fix: escape single quotes in workspace tree macro to prevent JS parse errors
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
Page names containing apostrophes (e.g. "02-Structure d'entrainements.md")
broke Alpine.js directives because Jinja2's |e filter doesn't escape single
quotes. Replaced ' with ' HTML entity in Alpine expression attributes
(showWsContext, wsTouchEnd).
2026-07-16 09:16:33 -04:00
bruno 0edcdbe82a fix: le menu contextuel Delete/Rename rafraîchit maintenant les deux arbres
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Nouvel événement 'flowdeck:workspace-changed' dispatché depuis les actions
  sidebar (deleteWorkspacePage, wsCtxAction rename/delete, newFolderInWorkspace)
- La vue principale local_workspace.html écoute 'flowdeck:workspace-changed'
  et appelle _reloadAfterAction() pour rafraîchir son arbre
- _reloadAfterAction() continue à dispatcher 'flowdeck:sidebar-refresh'
  pour le rafraîchissement sidebar uniquement (évite la boucle infinie)
- Correction du double confirm dans deleteWorkspacePage (skipConfirm=true
  depuis wsCtxAction qui a déjà confirmé)
2026-07-16 09:02:49 -04:00
bruno f6a022edf2 fix: extract render_workspace_tree macro, fix sidebar-tree endpoint
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Extracted render_workspace_tree macro into _workspace_tree_macro.html
  so it can be imported independently from base.html (which has many
  template variables like user, workspace_name, etc.)
- Fixed GET /api/sidebar/workspace-tree to use the extracted macro
- Added error logging for easier debugging
2026-07-16 08:58:05 -04:00
bruno 6f40c8953a feat: sidebar tree dynamically refreshes after CRUD in local-workspace
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- New endpoint GET /api/sidebar/workspace-tree returns sidebar tree HTML fragment
- refreshSidebarTree() in appState() fetches and replaces #sidebar-workspace-items
- Custom event 'flowdeck:sidebar-refresh' dispatched after doCreate/doRename/doDelete
- newFolderInWorkspace, deleteWorkspacePage, wsCtxAction('rename') now use
  refreshSidebarTree() instead of window.location.reload()
- Sidebar stays in sync without full page refresh
2026-07-16 08:53:44 -04:00
bruno 72636a77ea test: met à jour les tests suite à la suppression du fallback admin token
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Tous les tests *_no_auth doivent maintenant retourner 401 au lieu de 200/502
car _require_gitea() ne fait plus de fallback vers le token admin global.
2026-07-16 08:39:49 -04:00
bruno 76c8a9a53c fix: supprime le fallback admin token dans _require_gitea()
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
_require_gitea() ne doit plus utiliser le token admin global comme fallback
quand l'utilisateur n'a pas lié son compte Gitea. Chaque utilisateur doit
connecter son propre compte Gitea pour voir les projets.

Les endpoints /api/gitea/projects et /api/gitea/orgs retournent maintenant
401 si l'utilisateur n'a pas lié Gitea, et la page /workspaces affiche
'Connect your Gitea account' au lieu de lister les repos du admin.
2026-07-16 08:37:27 -04:00
bruno 07a4f5ece6 fix: sidebar vide sur /workspaces — pas de contexte workspace actif
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
_sidebar_data() prend un nouveau parametre include_workspace (default True).
La page /workspaces passe include_workspace=False pour que la sidebar
n'affiche ni le nom du workspace actif, ni ses pages/folders.
2026-07-16 08:29:52 -04:00
bruno d645126b53 fix: /api/workspace/projects uses per-user Gitea token instead of global admin token
FlowDeck CI / test (push) Failing after 17s
FlowDeck CI / docker (push) Has been skipped
A local account without Gitea connection was seeing all Gitea repos
because the endpoint used the module-level gitea client (global admin token).
Now it checks get_user_gitea_client(request) and returns empty gitea_repos
if the user has no OAuth token for Gitea.
2026-07-16 08:20:45 -04:00
bruno 7cefc08abc fix: Gitea tree loading + auth system overhaul (v2.5.0)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
ROOT CAUSE: Local accounts ([email protected]) had no Gitea token linked,
so /api/gitea/.../tree returned 401 → loadGiteaTree() failed silently.

FIXES:
1. _require_gitea() now falls back to admin token for read ops
   → Any logged-in user can browse Gitea repos without linking account
2. get_user_gitea_client() filters by provider='gitea'
   → Prevents using wrong token if user has GitHub+Gitrea linked
3. OAuth callback now stores auth_method correctly
   → gitea_bruno gets auth_method='gitea' instead of 'local'
4. Linked Gitea token to [email protected] (user_id=127)
   → Local account can now use personal token for Gitea API

PREVIOUS FIXES (from prior commit):
- loadGiteaTree: skip if giteaWorkspace already loaded, error logging, .bind(this)
- gitea_workspace.html: use captured 'self' instead of querySelector('[x-data]')
- 12 test assertions updated to reflect admin fallback behavior
2026-07-15 18:17:49 -04:00
bruno 61174ee967 fix: correct version number 2.4.7
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-15 16:55:27 -04:00
bruno aa64863bf7 fix: sidebar Gitea tree loading — race condition + silent errors + wrong Alpine scope
FlowDeck CI / test (push) Failing after 6s
FlowDeck CI / docker (push) Has been skipped
- loadGiteaTree: skip if giteaWorkspace component already loaded tree
- loadGiteaTree: check r.ok, add console.error logging, show error in UI
- loadGiteaTree: use .bind(this) for correct this in callbacks
- gitea_workspace.html: replace querySelector('[x-data]') with captured self
  in loadSidebarTree, loadSubdir, Private Pages click handlers
- Prevents loadGiteaTree from overwriting loadSidebarTree results
  on /gitea-workspace page
2026-07-15 16:54:20 -04:00
bruno efd957e827 fix: revert JS modal changes — preserve native prompt/confirm, add CSS+HTML modal only
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Root cause: callback wrappers introduced JS syntax errors ('appState is not defined')
Fix: keep modal HTML+CSS styles ready for future use, restore all JS functions
2026-07-15 09:28:35 -04:00
bruno 78092e6111 feat: custom modal system replaces browser prompt() and confirm()
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- Added themed dark modal with CSS matching FlowDeck design
- showPrompt(title, message, placeholder, callback) replaces prompt()
- showConfirm(title, message, callback) replaces confirm()
- Updated: newPageInWorkspace, newFolderInWorkspace, deleteWorkspacePage
- Modal closes on escape, overlay click, or cancel button
- Consistent look across all dialogs on the site
2026-07-15 09:03:25 -04:00
bruno ec96fb86a5 fix: KeyError 'workspace_key' in create_local_workspace_item
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Root cause: ws dict from _get_active_workspace doesn't have 'workspace_key' column
           → ws['workspace_key'] → KeyError → 500 on New Page/New Folder

Fix: use ws['name'] instead (the workspace name from workspaces table)
2026-07-15 08:41:06 -04:00
bruno 3fdcc41d10 fix: auto-refresh page when closing Settings with X
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
closeSettings() now:
- Refreshes the parent page (history.back + reload)
- Handles tab navigation between settings sections
- Falls back to /workspaces redirect if no history
2026-07-15 08:10:01 -04:00
bruno 17666b51c2 fix: two UX issues
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
1. Settings X button: closeSettings() goes back, skipping hash-only navigation
   → No more double-click to close

2. Workspaces page: Connect Gitea link now includes &mode=link
   → Same link as Settings → Integrations (was missing mode=link)
2026-07-15 07:56:21 -04:00
bruno aedb07c962 fix: redirect to /workspaces after login (instead of /)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Local login JS: window.location='/workspaces' instead of '/'
- Root route /: if no workspace exists, redirect to /workspaces
- Existing users with workspaces: still go to /local-workspace
2026-07-15 07:41:22 -04:00
bruno bf19af2347 fix: restore missing template=env.get_template in gitea_workspace_page
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-15 07:33:31 -04:00
bruno fc6f2531b7 fix: gitea_workspace page now explicitly sets gitea_workspace=True
FlowDeck CI / test (push) Failing after 6s
FlowDeck CI / docker (push) Has been skipped
Root cause: _sidebar_data reads cookie from REQUEST, but cookie is set on RESPONSE
           → first visit: cookie empty → gitea_workspace=False → tree doesn't load

Fix: gitea_workspace_page ctx always sets gitea_workspace=True
     Also passes gitea_owner/gitea_repo for Alpine tree loading
2026-07-15 07:32:08 -04:00
bruno 0d8507a5c7 feat: Gitea file tree visible in sidebar on ALL pages
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- base.html Alpine: added giteaWorkspace, giteaOwner, giteaRepo data
- loadGiteaTree() fetches /api/gitea/.../tree and renders in sidebar
- board._sidebar_data returns gitea_owner/gitea_repo
- dashboard._sidebar_data returns gitea_owner/gitea_repo
- alpine:initialized triggers loadGiteaTree on every page load
2026-07-14 22:05:53 -04:00
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