Commit Graph
354 Commits
Author SHA1 Message Date
bruno bd02c9ea8a fix: startup log version v2.1.0 → v4.0.0
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-18 00:28:06 -04:00
bruno e85161dfc1 v4.0.0 — Route publique /p/<slug>, correctifs publish/share UI
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Ajout route /p/<slug> qui sert les pages publiées (no auth, rendu HTML blocks)
- Template public_page.html — design épuré Notion-style
- Fix publishPage()/unpublishPage(): vérifient d.is_published au lieu de d.status==='ok'
- Fix shareInvite(): vérifie d.status==='shared'
- Fix removeShare(): vérifie d.status==='removed'
- ROADMAP.md: toutes les sections 4.0a-4.0e cochées ✅ (déjà implémentées)
- Version bump 2.5.0 → 4.0.0
2026-07-18 00:27:14 -04:00
bruno fe64617677 feat: star favoris dynamique + sidebar refresh sans reload
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- page_editor: étoile ⭐/☆ dynamique selon favorited (x-text)
- toggleFavorite() appelle refreshFavorites() du sidebar
- base.html: refreshFavorites() fetch /api/library/favorites + rebuild DOM
- Context menu 'Add to Favorites' → refreshFavorites() au lieu de location.reload()
- Les items dynamiques ont onclick/oncontextmenu pour fonctionner hors Alpine
2026-07-17 23:50:37 -04:00
bruno 25386bc79f feat: breadcrumb hover Notion-style + nav_workspace_id sur toutes les pages
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- _header.html: remplace click par hover (mouseenter/mouseleave)
  avec timer 200ms anti-flicker, cascade sous-menus au hover
- dashboard.py: ajoute nav_workspace_id à trash, library, workspace,
  gitea-workspace, local-workspace, workspaces, settings, pages/{id}
- La section du popover affiche 'Workspaces' pour Home, 'Private' pour le reste
- Les clics dans les popovers ferment le menu + naviguent
2026-07-17 23:43:16 -04:00
bruno d751415308 feat: add Notion-style breadcrumb navigation with dropdown menus
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
Backend:
- Added _nav_breadcrumb() to build page hierarchy chain (root → current)
- New /api/nav/menu endpoint returns workspace/folder children with has_children flag
- view_page() and view_page_root() now pass breadcrumb_items, nav_workspace_id, nav_page_id to template

Header template (_header.html):
- Replaced static breadcrumb with Alpine.js fdBreadcrumb() component
- Breadcrumb items now clickable with dropdown menus showing
2026-07-17 23:30:59 -04:00
bruno 6f1eabf91d fix: Windows path handling, light theme default, file viewer in editor, first-user admin logic
FlowDeck CI / test (push) Failing after 18s
FlowDeck CI / docker (push) Has been skipped
Config:
- Fixed SQLite path parsing on Windows (handle drive letters without prepending /)
- Changed default theme from dark to light
- Updated OAuth test credentials (gitea_oauth_client_id/secret)

Auth:
- First real user (excluding default admin with no password) becomes admin
- Changed user count query to exclude users without password_hash

File viewer:
- Removed separate _render_file_viewer() —
2026-07-17 20:38:39 -04:00
bruno 84a126cfd1 Merge branch 'main' of https://git.dracodev.net/bruno/flowdeck
FlowDeck CI / test (push) Failing after 18s
FlowDeck CI / docker (push) Has been skipped
2026-07-17 09:00:09 -04:00
bruno 7ea1c852dc chore: remove 44 Notion reference images — cleanup research artifacts
Deleted all Notion UI screenshots and .url shortcut from /images/:
- Kanban views (board, table, team load, status, detailed, sort/filter panels)
- Share menu (general access, permissions, publish section)
- Editor states (H1/paragraph/quote empty, format layouts)
- Navigation (sidebar, context menus, mouse-over states, collapse/expand)
- Misc UI (trash, config panel, library, user menu, filters)

These were research/reference
2026-07-17 08:59:44 -04:00
bruno c2ef7bfaa0 fix: show auto-created workspace name instead of 'Private' in sidebar
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
For Gitea workspaces, the sidebar section now displays the actual
workspace name (e.g. '📁 Projets/Ares') instead of the generic '📁 Private'.
The workspace name is auto-created from the Gitea project's owner/repo
when the remote workspace is first opened.
2026-07-16 14:27:47 -04:00
bruno c990382085 fix: use Alpine.data() to register giteaWorkspace component
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Replaced global function giteaWorkspace() with Alpine.data('giteaWorkspace', ...)
registered via document.addEventListener('alpine:init', ...). This is the
recommended Alpine 3 approach that guarantees the component factory is
available before Alpine processes x-data directives.

Changed x-data="giteaWorkspace()" to x-data="giteaWorkspace" (Alpine.data
calls the factory automatically, no parentheses needed).
2026-07-16 14:12:53 -04:00
bruno b141af886d fix: move giteaWorkspace() script before x-data div to fix init race
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
The <script> defining giteaWorkspace() was placed AFTER the <div x-data>
in the DOM, causing Alpine to try to evaluate giteaWorkspace() before
the function was defined. This resulted in 'Uncaught ReferenceError' for
all component properties (fileLoading, fileLanguage, showFile, etc.).

Fix: moved the <script> block to appear BEFORE the x-data div in the
HTML source, ensuring the function is defined when Alpine initializes.
2026-07-16 14:07:17 -04:00
bruno 56c5739605 fix: remove getter from giteaWorkspace() to fix Alpine 3.14.9 init error
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
The 'get sortedTreeItems()' getter caused Alpine's Proxy to fail during
component initialization, resulting in all properties being undefined
(fileLoading, fileLanguage, showFile, etc. — Uncaught ReferenceError).

Fix:
- Replaced getter with _sortTree() method + sortedTreeItems property
- _sortTree() called after treeItems is updated in loadMainTree()
- sortedTreeItems explicitly set to [] on error/empty paths
2026-07-16 13:48:47 -04:00
bruno 7613129204 fix: Gitea sidebar now has separate Repository section below Private
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Backend:
- _sidebar_data() no longer clears workspace_pages for Gitea workspaces
  The local tree stays intact in the 'Private' section
- workspace_pages is always loaded from DB (local files)

Sidebar template (base.html):
- Workspace section renamed to 'Private' when gitea_workspace is true
- New 'Repository (Gitea)' section added below, visible only for Gitea
  workspaces, with its own toggle (sectionsOpen.gitea) and refresh button
- Uses #sidebar-gitea-items container for the remote file tree

Gitea workspace:
- loadSidebarTree() now targets #sidebar-gitea-items
- window._gwData exposed for sidebar refresh button
- sectionsOpen now includes gitea: true by default
2026-07-16 13:44:10 -04:00
bruno f61f8b61ae fix: Gitea sidebar tree + header actions inline with title
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Gitea workspace sidebar:
- loadSidebarTree() now uses innerHTML replacement instead of DOM
  manipulation (avoids Alpine reactivity overwrites)
- Ensures workspace section is visible when tree loads
- Shows error message when Gitea API fails (no token/gateway)
- Better error handling with console.error catch

Header actions inline:
- page_editor: moved Edited/Share/Copy/Favorite/More buttons into
  the unified header (right_actions), accessible via window.E
  (editorState global reference set in init)
- Removed duplicate page-topbar div from content area
- Share dialog, More menu, and Activity popover stay in content
  area (triggered by header buttons via window.E references)
- Gitea workspace: header now uses page-action-btn for consistency
2026-07-16 13:08:14 -04:00
bruno 3210ac65a6 feat: Move to, Gitea context menu, Activity popover
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Move to workspace:
- movePage() opens a dialog listing all workspaces via /api/workspaces
- doMove(wsId) calls PUT /api/pages/{id}/move with workspace_id
- Updated move API to accept JSON body with workspace_id for cross-workspace moves

Gitea workspace context menu:
- Right-click on any file/folder shows Rename + Delete options
- gwRename() prompts for new name, calls PUT /api/gitea/.../file
- gwDelete() confirms then calls DELETE /api/gitea/.../file
- Both trigger refreshTree() after success

Activity popover:
- 'Edited X ago' timestamp is now clickable (▾ indicator)
- Opens popover showing edited time + created date
- formatDate() helper for readable date formatting
2026-07-16 12:53:38 -04:00
bruno cef267d7b5 feat: real timestamp + working Export + polished More menu in page editor
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- 'Edited X ago' now shows real relative time from page.updated_at
- timeAgo computed getter in editorState() calculates relative time
- Export now generates a Markdown file from blocks and triggers download
- blocksToMarkdown() helper converts blocks to proper Markdown syntax
  (headings, lists, todos, quotes, dividers, code blocks)
- More menu items: Duplicate (was working), Export (now works),
  Move to Trash (was working), Copy link (via shortcut)
2026-07-16 12:49:45 -04:00
bruno 043dd4871c feat: gitea-workspace now has file tree browser like local-workspace
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Main content area now shows file/folder tree with breadcrumb navigation
- Click folders to drill down, click files to open
- Breadcrumb shows current path with clickable segments
- Sorted tree: folders first, then files alphabetically
- refreshTree() now reloads without full page reload
- Empty state with 'New file' button when folder is empty
2026-07-16 12:42:48 -04:00
bruno b5dd37a652 fix: remove duplicate action bar from page_editor (double header)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
The unified _header.html already renders the topbar with breadcrumb. The
page_editor had a second 'page-topbar' div in the content area with the
same buttons (Share, Copy link, Favorite, More). Removed the duplicate
actions from the header, keeping them only in the content area where
they are in the correct Alpine scope (editorState()).

This fixes:
- Double header visual duplication
- Share/Copy/Favorite/More buttons now work (in editorState scope)
2026-07-16 12:41:25 -04:00
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 &#39; 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 &#39; 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