fix: WORKSPSACES section + remaining emoji icons replaced
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped

- base.html: séparateur entre version et Log out, _local_workspaces_for_user
- board.py: _local_workspaces_for_user helper, app_version, fix emoji icons
- dashboard.py: _local_workspaces_for_user helper
- library.html: 📚📁📄🕒⭐👥🌐🔒📦 → SVG + icon map
- workspaces.html: 📁🔍🗑📝 → SVG
- local_workspace.html: page_icon, empty states, icon functions → SVG
- settings.html: 👤🔔 → SVG nav icons
- _icons.html: +'bell' icon
- CSS: .nav-icon-inline, .empty-state-icon
- 143 tests passent
This commit is contained in:
2026-07-20 20:58:02 -04:00
parent 5372f4f22f
commit b835dd6b5e
10 changed files with 69 additions and 42 deletions
+3 -3
View File
@@ -67,7 +67,7 @@
@mouseleave="dragCloseTimer()">
<template x-for="h in crumb.hidden" :key="h.id">
<div class="fd-nav-item" @click.stop="go(h.url); closeAll()">
<span class="fd-nav-ico" x-text="h.icon || '📄'"></span>
<span class="fd-nav-ico" :title="h.icon || 'file'"></span>
<span class="fd-nav-label" x-text="h.label"></span>
</div>
</template>
@@ -110,7 +110,7 @@
<div class="fd-nav-item"
@mouseenter="openSub(item)"
@click.stop="go(item.url); closeAll()">
<span class="fd-nav-ico" x-text="item.icon || '📄'"></span>
<span class="fd-nav-ico" :title="item.icon || 'file'"></span>
<span class="fd-nav-label" x-text="item.name"></span>
<span class="fd-nav-arrow" x-show="item.has_children">&rsaquo;</span>
<div class="fd-nav-menu fd-nav-submenu" x-show="subOpenId === item.id" x-cloak
@@ -118,7 +118,7 @@
@mouseleave="dragCloseTimer()">
<template x-for="s in subItems" :key="s.id">
<div class="fd-nav-item" @click.stop="go(s.url); closeAll()">
<span class="fd-nav-ico" x-text="s.icon || '📄'"></span>
<span class="fd-nav-ico" :title="s.icon || 'file'"></span>
<span class="fd-nav-label" x-text="s.name"></span>
<span class="fd-nav-arrow" x-show="s.has_children">&rsaquo;</span>
</div>
+2
View File
@@ -46,6 +46,8 @@
<svg width="{{s}}" height="{{s}}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>
{%- elif name == 'plus' -%}
<svg width="{{s}}" height="{{s}}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
{%- elif name == 'bell' -%}
<svg width="{{s}}" height="{{s}}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
{%- elif name == 'chevron-down' -%}
<svg width="{{s}}" height="{{s}}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
{%- elif name == 'inbox' -%}
+2 -1
View File
@@ -123,7 +123,7 @@
{% else %}
<span class="tree-toggle-placeholder"></span>
{% endif %}
<span class="page-icon">{{ page.icon }}</span>
<span class="page-icon">{% if page.icon in ("folder","file","star","link","trash","book") %}{{ fd_icon(page.icon,14) }}{% else %}{{ page.icon }}{% endif %}</span>
<span class="page-name">{{ page.name }}</span>
<span class="item-actions">
<button class="item-action-btn" @click.stop="newSubPage('{{ page.id }}')">+</button>
@@ -191,6 +191,7 @@
{% endif %}
<div class="um-sep"></div>
<div class="um-version">FlowDeck v{{ app_version }}</div>
<div class="um-sep"></div>
<a href="/auth/logout" class="um-item um-danger" @click="workspaceMenuOpen=false">{{ fd_icon("log-out", 16) }} Log out</a>
</div>
</div>
+7 -7
View File
@@ -1,10 +1,10 @@
{% extends "base.html" %}
{% block page_icon %}📚{% endblock %}
{% block page_icon %}{{ fd_icon("book",18) }}{% endblock %}
{% block page_title %}Library{% endblock %}
{% block title_prefix %}Library{% endblock %}
{% block topbar %}
{% set page_icon = "📚" %}
{% set page_icon = "book" %}
{% set page_title = "Library" %}
{% include '_header.html' %}
{% endblock %}
@@ -305,7 +305,7 @@
<div class="lib-loading" id="lib-loading" x-show="loading">
<p x-show="!noWorkspace">Loading…</p>
<div x-show="noWorkspace" style="padding:40px;text-align:center;">
<div style="font-size:48px;margin-bottom:16px;">📁</div>
<div style="margin-bottom:16px;">{{ fd_icon("folder",32) }}</div>
<h3 style="font-size:18px;margin:0 0 8px;">No workspace open</h3>
<p style="color:var(--text-dim);font-size:14px;margin:0 0 20px;">Open a workspace to browse and manage your library items.</p>
<a href="/workspaces" class="btn btn-primary" style="display:inline-block;text-decoration:none;padding:8px 20px;">Go to Workspaces</a>
@@ -449,7 +449,7 @@
<div x-show="peekLoading" class="peek-loading">Loading…</div>
<div x-show="!peekLoading && peekContent" x-html="peekContent"></div>
<div x-show="!peekLoading && !peekContent" class="peek-empty">
<div style="font-size:48px;margin-bottom:8px;">📄</div>
<div style="margin-bottom:8px;">{{ fd_icon("file",32) }}</div>
<div style="font-size:14px;color:var(--text-secondary);">No preview available</div>
</div>
</div>
@@ -782,13 +782,13 @@ function libraryPage() {
},
// ── Empty states ──
emptyIcon: '📄',
emptyIcon: 'file',
emptyTitle: 'No items',
emptyText: '',
_recomputeEmpty() {
var icons = {recents:'🕒',favorites:'⭐',shared:'👥',published:'🌐',private:'🔒',workspace:'📁',repository:'📦'};
this.emptyIcon = icons[this.tab] || '📄';
var icons = {recents:'clock',favorites:'star',shared:'users',published:'globe',private:'lock',workspace:'folder',repository:'folder'};
this.emptyIcon = icons[this.tab] || 'file';
var titles = {recents:'No recent pages',favorites:'No favorites',shared:'No shared pages',
published:'No published pages',private:'No private pages',workspace:'No workspace pages',
repository:'Empty repository'};
+10 -10
View File
@@ -1,10 +1,10 @@
{% extends "base.html" %}
{% block page_title %}{{ workspace_name }}{% endblock %}
{% block title_prefix %}{{ workspace_name }}{% endblock %}
{% block page_icon %}📁{% endblock %}
{% block page_icon %}{{ fd_icon("folder",18) }}{% endblock %}
{% block topbar %}
{% set page_icon = "📁" %}
{% set page_icon = "folder" %}
{% set page_title = workspace_name %}
{% include '_header.html' %}
{% endblock %}
@@ -377,7 +377,7 @@ window._wsInitData = (function() {
sortBy: '',
viewMode: localStorage.getItem('fd_default_view') || 'tree',
viewMenuOpen: false,
viewIcons: {tree:'🌳',list:'📋',details:'📊',title:'🏷️',content:'📝'},
viewIcons: {tree:'',list:'',details:'',title:'',content:''},
viewLabels: {tree:'Tree',list:'List',details:'Details',title:'Cards',content:'Content'},
// Context menu
@@ -677,7 +677,7 @@ window._wsInitData = (function() {
async _loadPreviewContent(node) {
if (node.is_folder) {
this.previewPanelContent = '<div style="text-align:center;padding:40px;color:var(--text-secondary)">'
+ '<span style="font-size:48px;display:block;margin-bottom:12px">📁</span>'
+ '<span class="empty-state-icon">'+getSvgIcon('folder',32)+'</span>'
+ '<div style="font-size:14px">' + (node.child_count||0) + ' item(s)</div>'
+ '<a href="/local-workspace?folder=' + node.id + '" class="btn btn-secondary" style="display:inline-block;text-decoration:none;margin-top:16px">Open folder</a>'
+ '</div>';
@@ -719,7 +719,7 @@ window._wsInitData = (function() {
}
} catch(e) {}
preview = '<div style="text-align:center;padding:20px;color:var(--text-secondary)">'
+ '<span style="font-size:48px;display:block;margin-bottom:8px">📄</span>'
+ '<span class="empty-state-icon">'+getSvgIcon('file',32)+'</span>'
+ (node.size_display || '') + ' — open to view</div>';
} else if (format === 'blocks') {
try {
@@ -1475,23 +1475,23 @@ window._wsInitData = (function() {
// ── File type icon ──
_fileIcon(name, isFolder, contentFormat) {
if (isFolder) return '📁';
if (isFolder) return '<span class="page-icon-svg">'+getSvgIcon('folder',14)+'</span>';
// FlowDeck internal pages (no extension, blocks/markdown format)
if (contentFormat && contentFormat !== 'file') return '📝';
if (contentFormat && contentFormat !== 'file') return '<span class="page-icon-svg">'+getSvgIcon('edit',14)+'</span>';
var n = (name || '').toLowerCase();
if (/\.(png|jpe?g|gif|webp|svg|bmp|ico)$/.test(n)) return '🖼️';
if (/\.pdf$/.test(n)) return '📕';
if (/\.(md|markdown)$/.test(n)) return '📝';
if (/\.(md|markdown)$/.test(n)) return '<span class="page-icon-svg">'+getSvgIcon('edit',14)+'</span>';
if (/\.(py)$/.test(n)) return '🐍';
if (/\.(js|jsx|ts|tsx)$/.test(n)) return '📜';
if (/\.(html?|xml)$/.test(n)) return '🌐';
if (/\.css$/.test(n)) return '🎨';
if (/\.json$/.test(n)) return '📋';
if (/\.json$/.test(n)) return '<span class="page-icon-svg">'+getSvgIcon('file',14)+'</span>';
if (/\.sql$/.test(n)) return '🗃️';
if (/\.(sh|bash|zsh)$/.test(n)) return '💻';
if (/\.ps1$/.test(n)) return '⚡';
if (/\.(rs|go|java|rb|php|c|cpp|h|swift|kt|scala|r)$/.test(n)) return '📜';
if (/\.(txt|log)$/.test(n)) return '📄';
if (/\.(txt|log)$/.test(n)) return '<span class="page-icon-svg">'+getSvgIcon('file',14)+'</span>';
if (/\.(zip|tar|gz|rar|7z)$/.test(n)) return '📦';
return '📄';
},
+2 -2
View File
@@ -81,8 +81,8 @@
<!-- Left navigation -->
<div class="settings-nav">
<div class="settings-nav-header">Account</div>
<div class="settings-nav-item" :class="{ active: activeSection==='account' }" @click="activeSection='account'">👤 My account</div>
<div class="settings-nav-item" :class="{ active: activeSection==='notifications' }" @click="activeSection='notifications'">🔔 Notifications</div>
<div class="settings-nav-item" :class="{ active: activeSection==='account' }" @click="activeSection='account'"><span class="nav-icon-inline">{{ fd_icon("user",14) }}</span> My account</div>
<div class="settings-nav-item" :class="{ active: activeSection==='notifications' }" @click="activeSection='notifications'"><span class="nav-icon-inline">{{ fd_icon("bell",14) }}</span> Notifications</div>
<div class="settings-nav-header">Workspace</div>
<div class="settings-nav-item" :class="{ active: activeSection==='workspace' }" @click="activeSection='workspace'">📋 General</div>
<div class="settings-nav-item" :class="{ active: activeSection==='tags' }" @click="activeSection='tags'">🏷️ Tags</div>
+3 -3
View File
@@ -56,7 +56,7 @@
<!-- ── Local Workspaces ── -->
<div class="ws-section">
<div class="ws-section-title">📁 My Workspaces <span class="badge" x-text="workspaces.length"></span></div>
<div class="ws-section-title">{{ fd_icon("folder",16) }} My Workspaces <span class="badge" x-text="workspaces.length"></span></div>
<div class="ws-grid">
<template x-for="ws in workspaces" :key="'local-'+ws.id">
<div class="ws-card" :class="{active:ws.id===activeId}" @click="selectLocal(ws)">
@@ -64,7 +64,7 @@
<div class="ws-card-count" x-text="ws.page_count+' page(s)'"></div>
<div class="ws-card-actions" @click.stop>
<button class="btn-sm" @click="renameWs(ws)">✏️</button>
<button class="btn-sm" style="color:var(--danger);border-color:rgba(255,80,80,.3)" @click="deleteWs(ws)">🗑</button>
<button class="btn-sm" style="color:var(--danger);border-color:rgba(255,80,80,.3)" @click="deleteWs(ws)">{{ fd_icon("trash",14) }}</button>
</div>
</div>
</template>
@@ -83,7 +83,7 @@
<div>Connect your Gitea account to see your projects.</div>
<a class="gitea-connect" href="/auth/login?provider=gitea&mode=link">🔗 Connect Gitea</a>
<span style="margin:0 8px;color:var(--text-dim);">or</span>
<a class="gitea-connect" href="/auth/login?provider=gitea">📝 Register with Gitea</a>
<a class="gitea-connect" href="/auth/login?provider=gitea">{{ fd_icon("edit",14) }} Register with Gitea</a>
</div>
<!-- Loading skeletons -->