feat: badge emoji partagé (noir & blanc) dans l'arborescence + sidebar «Par moi» inclut is_shared
- board/dashboard: helper _load_shared_sidebar_pages intégrant les pages marquées is_shared directement - _workspace_tree_macro: badge 👥 N&B sur les fichiers partagés du tree du sidebar - local_workspace: badge 👥 en noir & blanc - static/css/app.css: style .page-shared-badge
This commit is contained in:
+67
-50
@@ -175,7 +175,9 @@ def _load_workspace_pages(ws_cookie: str) -> list:
|
|||||||
ws_id = int(ws_cookie)
|
ws_id = int(ws_cookie)
|
||||||
with get_conn() as conn:
|
with get_conn() as conn:
|
||||||
rows = conn.execute(
|
rows = conn.execute(
|
||||||
"SELECT id, title, parent_section, content_format FROM pages WHERE workspace_id=? AND parent_id IS NULL AND deleted_at IS NULL ORDER BY created_at DESC",
|
"SELECT id, title, parent_section, content_format, "
|
||||||
|
"is_shared, share_mode, COALESCE(published,0) AS published "
|
||||||
|
"FROM pages WHERE workspace_id=? AND parent_id IS NULL AND deleted_at IS NULL ORDER BY created_at DESC",
|
||||||
(ws_id,),
|
(ws_id,),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
items = []
|
items = []
|
||||||
@@ -183,11 +185,13 @@ def _load_workspace_pages(ws_cookie: str) -> list:
|
|||||||
is_folder = r["parent_section"] == "Workspace"
|
is_folder = r["parent_section"] == "Workspace"
|
||||||
title = r["title"] or "Untitled"
|
title = r["title"] or "Untitled"
|
||||||
sub_children = _load_children(r["id"])
|
sub_children = _load_children(r["id"])
|
||||||
|
is_shared = bool(r["is_shared"] or r["share_mode"] != "private" or r["published"])
|
||||||
items.append({
|
items.append({
|
||||||
"db_id": r["id"], "name": title,
|
"db_id": r["id"], "name": title,
|
||||||
"id": f"page/{r['id']}",
|
"id": f"page/{r['id']}",
|
||||||
"icon": "📁" if is_folder else _file_icon(title, r["content_format"]),
|
"icon": "📁" if is_folder else _file_icon(title, r["content_format"]),
|
||||||
"is_folder": is_folder,
|
"is_folder": is_folder,
|
||||||
|
"is_shared": is_shared,
|
||||||
"child_count": len(sub_children),
|
"child_count": len(sub_children),
|
||||||
"children": sub_children,
|
"children": sub_children,
|
||||||
})
|
})
|
||||||
@@ -200,7 +204,9 @@ def _load_children(parent_id: int) -> list:
|
|||||||
"""Recursively load children of a page."""
|
"""Recursively load children of a page."""
|
||||||
with get_conn() as conn:
|
with get_conn() as conn:
|
||||||
rows = conn.execute(
|
rows = conn.execute(
|
||||||
"SELECT id, title, parent_section, content_format FROM pages WHERE parent_id=? AND deleted_at IS NULL ORDER BY created_at",
|
"SELECT id, title, parent_section, content_format, "
|
||||||
|
"is_shared, share_mode, COALESCE(published,0) AS published "
|
||||||
|
"FROM pages WHERE parent_id=? AND deleted_at IS NULL ORDER BY created_at",
|
||||||
(parent_id,),
|
(parent_id,),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
children = []
|
children = []
|
||||||
@@ -208,11 +214,13 @@ def _load_children(parent_id: int) -> list:
|
|||||||
is_folder = r["parent_section"] == "Workspace"
|
is_folder = r["parent_section"] == "Workspace"
|
||||||
title = r["title"] or "Untitled"
|
title = r["title"] or "Untitled"
|
||||||
sub_children = _load_children(r["id"])
|
sub_children = _load_children(r["id"])
|
||||||
|
is_shared = bool(r["is_shared"] or r["share_mode"] != "private" or r["published"])
|
||||||
children.append({
|
children.append({
|
||||||
"db_id": r["id"], "name": title,
|
"db_id": r["id"], "name": title,
|
||||||
"id": f"page/{r['id']}",
|
"id": f"page/{r['id']}",
|
||||||
"icon": "📁" if is_folder else _file_icon(title, r["content_format"]),
|
"icon": "📁" if is_folder else _file_icon(title, r["content_format"]),
|
||||||
"is_folder": is_folder,
|
"is_folder": is_folder,
|
||||||
|
"is_shared": is_shared,
|
||||||
"child_count": len(sub_children),
|
"child_count": len(sub_children),
|
||||||
"children": sub_children,
|
"children": sub_children,
|
||||||
})
|
})
|
||||||
@@ -235,6 +243,61 @@ def _local_workspaces_for_user(user: dict | None, workspace_id: int = 0) -> list
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def _load_shared_sidebar_pages(user_id: int) -> tuple[list, list, list, list]:
|
||||||
|
"""Shared / received / published pages for the sidebar (reused by dashboard)."""
|
||||||
|
with get_conn() as conn:
|
||||||
|
made_nominal = conn.execute(
|
||||||
|
"SELECT DISTINCT p.id, p.title, p.workspace, p.updated_at FROM page_shares s "
|
||||||
|
"JOIN pages p ON p.id=s.page_id "
|
||||||
|
"WHERE s.created_by=? AND p.deleted_at IS NULL",
|
||||||
|
(user_id,),
|
||||||
|
).fetchall()
|
||||||
|
made_link = conn.execute(
|
||||||
|
"SELECT id, title, workspace, updated_at FROM pages "
|
||||||
|
"WHERE share_mode='anyone' AND published=0 AND deleted_at IS NULL"
|
||||||
|
).fetchall()
|
||||||
|
made_flag = conn.execute(
|
||||||
|
"SELECT id, title, workspace, updated_at FROM pages "
|
||||||
|
"WHERE (is_shared=1 OR share_mode != 'private') AND COALESCE(published,0)=0 AND deleted_at IS NULL"
|
||||||
|
).fetchall()
|
||||||
|
published_rows = conn.execute(
|
||||||
|
"SELECT id, title, workspace, updated_at FROM pages "
|
||||||
|
"WHERE published=1 AND deleted_at IS NULL ORDER BY updated_at DESC LIMIT 20"
|
||||||
|
).fetchall()
|
||||||
|
received_rows = conn.execute(
|
||||||
|
"SELECT DISTINCT p.id, p.title, p.workspace, p.updated_at FROM page_shares s "
|
||||||
|
"JOIN pages p ON p.id=s.page_id "
|
||||||
|
"WHERE s.shared_with_user_id=? AND p.deleted_at IS NULL",
|
||||||
|
(user_id,),
|
||||||
|
).fetchall()
|
||||||
|
|
||||||
|
def _entry(r, icon):
|
||||||
|
return {
|
||||||
|
"id": f"page/{r['id']}",
|
||||||
|
"db_id": r["id"],
|
||||||
|
"name": r["title"] or "New page",
|
||||||
|
"icon": icon,
|
||||||
|
"url": f"/pages/{r['id']}",
|
||||||
|
"active": False,
|
||||||
|
"indent": 0,
|
||||||
|
"depth": 0,
|
||||||
|
"has_children": False,
|
||||||
|
"children": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
made_map = {}
|
||||||
|
for r in (*made_nominal, *made_link, *made_flag):
|
||||||
|
made_map.setdefault(r["id"], r)
|
||||||
|
made_sorted = sorted(made_map.values(), key=lambda r: r["updated_at"] or "", reverse=True)[:20]
|
||||||
|
shared_made = [_entry(r, "link") for r in made_sorted]
|
||||||
|
received_sorted = [r for r in received_rows if r["id"] not in made_map]
|
||||||
|
received_sorted = sorted(received_sorted, key=lambda r: r["updated_at"] or "", reverse=True)[:20]
|
||||||
|
shared_received = [_entry(r, "users") for r in received_sorted]
|
||||||
|
published = [_entry(r, "globe") for r in published_rows]
|
||||||
|
shared_all = [_entry(r, "link") for r in made_sorted]
|
||||||
|
return shared_made, shared_received, published, shared_all
|
||||||
|
|
||||||
|
|
||||||
def _sidebar_data(request: Request, owner: str = "", repo: str = "") -> dict:
|
def _sidebar_data(request: Request, owner: str = "", repo: str = "") -> dict:
|
||||||
user = SessionManager.decode_session(request.cookies.get("flowdeck_session", ""))
|
user = SessionManager.decode_session(request.cookies.get("flowdeck_session", ""))
|
||||||
ws_name = user.get("login", "Bruno") if user else "Bruno"
|
ws_name = user.get("login", "Bruno") if user else "Bruno"
|
||||||
@@ -338,54 +401,8 @@ def _sidebar_data(request: Request, owner: str = "", repo: str = "") -> dict:
|
|||||||
"children": [],
|
"children": [],
|
||||||
})
|
})
|
||||||
|
|
||||||
# Load shared pages: made (page_shares created by me + link-mode pages) and
|
# Load shared pages
|
||||||
# received (page_shares toward me), plus published pages.
|
shared_made_pages, shared_received_pages, published_pages, shared_pages = _load_shared_sidebar_pages(uid)
|
||||||
with get_conn() as conn:
|
|
||||||
made_nominal = conn.execute(
|
|
||||||
"SELECT DISTINCT p.id, p.title, p.workspace, p.updated_at FROM page_shares s "
|
|
||||||
"JOIN pages p ON p.id=s.page_id "
|
|
||||||
"WHERE s.created_by=? AND p.deleted_at IS NULL",
|
|
||||||
(uid,),
|
|
||||||
).fetchall()
|
|
||||||
made_link = conn.execute(
|
|
||||||
"SELECT id, title, workspace, updated_at FROM pages "
|
|
||||||
"WHERE share_mode='anyone' AND published=0 AND deleted_at IS NULL"
|
|
||||||
).fetchall()
|
|
||||||
published_rows = conn.execute(
|
|
||||||
"SELECT id, title, workspace, updated_at FROM pages "
|
|
||||||
"WHERE published=1 AND deleted_at IS NULL ORDER BY updated_at DESC LIMIT 20"
|
|
||||||
).fetchall()
|
|
||||||
received_rows = conn.execute(
|
|
||||||
"SELECT DISTINCT p.id, p.title, p.workspace, p.updated_at FROM page_shares s "
|
|
||||||
"JOIN pages p ON p.id=s.page_id "
|
|
||||||
"WHERE s.shared_with_user_id=? AND p.deleted_at IS NULL",
|
|
||||||
(uid,),
|
|
||||||
).fetchall()
|
|
||||||
|
|
||||||
def _shared_entry(r, icon):
|
|
||||||
return {
|
|
||||||
"id": f"page/{r['id']}",
|
|
||||||
"db_id": r["id"],
|
|
||||||
"name": r["title"] or "New page",
|
|
||||||
"icon": icon,
|
|
||||||
"url": f"/pages/{r['id']}",
|
|
||||||
"active": False,
|
|
||||||
"indent": 0,
|
|
||||||
"depth": 0,
|
|
||||||
"has_children": False,
|
|
||||||
"children": [],
|
|
||||||
}
|
|
||||||
|
|
||||||
made_map = {}
|
|
||||||
for r in (*made_nominal, *made_link):
|
|
||||||
made_map.setdefault(r["id"], r)
|
|
||||||
made_sorted = sorted(made_map.values(), key=lambda r: r["updated_at"] or "", reverse=True)[:20]
|
|
||||||
shared_made_pages = [_shared_entry(r, "link") for r in made_sorted]
|
|
||||||
received_sorted = [r for r in received_rows if r["id"] not in made_map]
|
|
||||||
received_sorted = sorted(received_sorted, key=lambda r: r["updated_at"] or "", reverse=True)[:20]
|
|
||||||
shared_received_pages = [_shared_entry(r, "users") for r in received_sorted]
|
|
||||||
published_pages = [_shared_entry(r, "globe") for r in published_rows]
|
|
||||||
shared_pages = [_shared_entry(r, "link") for r in made_sorted]
|
|
||||||
|
|
||||||
# Auth method & OAuth badge data
|
# Auth method & OAuth badge data
|
||||||
auth_method = "local"
|
auth_method = "local"
|
||||||
|
|||||||
@@ -208,6 +208,15 @@ def _sidebar_data(request: Request, repos: list[dict], include_workspace: bool =
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Shared / received / published pages for the sidebar (Par moi / Avec moi)
|
||||||
|
shared_made_pages = []
|
||||||
|
shared_received_pages = []
|
||||||
|
published_pages = []
|
||||||
|
shared_pages = []
|
||||||
|
if user and user.get("id"):
|
||||||
|
from app.routers.board import _load_shared_sidebar_pages
|
||||||
|
shared_made_pages, shared_received_pages, published_pages, shared_pages = _load_shared_sidebar_pages(user["id"])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"workspace_name": ws, "workspace_initial": initial,
|
"workspace_name": ws, "workspace_initial": initial,
|
||||||
"active_ws_name": active_ws_name,
|
"active_ws_name": active_ws_name,
|
||||||
@@ -221,10 +230,10 @@ def _sidebar_data(request: Request, repos: list[dict], include_workspace: bool =
|
|||||||
"recent_pages": recent_pages,
|
"recent_pages": recent_pages,
|
||||||
"private_pages": private_pages,
|
"private_pages": private_pages,
|
||||||
"favorite_pages": [],
|
"favorite_pages": [],
|
||||||
"shared_pages": [],
|
"shared_pages": shared_pages,
|
||||||
"shared_made_pages": [],
|
"shared_made_pages": shared_made_pages,
|
||||||
"shared_received_pages": [],
|
"shared_received_pages": shared_received_pages,
|
||||||
"published_pages": [],
|
"published_pages": published_pages,
|
||||||
"user": user,
|
"user": user,
|
||||||
"avatar_url": avatar_url,
|
"avatar_url": avatar_url,
|
||||||
"avatar_color": avatar_color,
|
"avatar_color": avatar_color,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
<span style="width:12px;flex-shrink:0;"></span>
|
<span style="width:12px;flex-shrink:0;"></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span class="page-icon">{% set valid_icons = ["folder","file","star","link","trash","book","home","settings","lock","globe","image","edit","calendar","users","user","search","tag","bar-chart","grid","list","align-left","zap"] %}{% if page.icon in valid_icons %}{{ fd_icon(page.icon,14) }}{% elif page.is_folder %}{{ fd_icon("folder",14) }}{% else %}{{ fd_icon("file",14) }}{% endif %}</span>
|
<span class="page-icon">{% set valid_icons = ["folder","file","star","link","trash","book","home","settings","lock","globe","image","edit","calendar","users","user","search","tag","bar-chart","grid","list","align-left","zap"] %}{% if page.icon in valid_icons %}{{ fd_icon(page.icon,14) }}{% elif page.is_folder %}{{ fd_icon("folder",14) }}{% else %}{{ fd_icon("file",14) }}{% endif %}</span>
|
||||||
|
{% if page.is_shared %}<span class="page-shared-badge" title="Partagé">👥</span>{% endif %}
|
||||||
{% if page.is_folder %}
|
{% if page.is_folder %}
|
||||||
<span class="page-name tree-folder-link"
|
<span class="page-name tree-folder-link"
|
||||||
@click.stop="navigateToFolder({{ page.db_id }})"
|
@click.stop="navigateToFolder({{ page.db_id }})"
|
||||||
|
|||||||
@@ -165,7 +165,7 @@
|
|||||||
.ws-tree-item .name.file{display:inline-flex;align-items:center;max-width:100%;overflow:hidden;}
|
.ws-tree-item .name.file{display:inline-flex;align-items:center;max-width:100%;overflow:hidden;}
|
||||||
.ws-tree-item .name.file .inline-rename-input{flex:0 1 auto;}
|
.ws-tree-item .name.file .inline-rename-input{flex:0 1 auto;}
|
||||||
.ws-tree-item .name.file .btn-open{flex:0 0 auto;}
|
.ws-tree-item .name.file .btn-open{flex:0 0 auto;}
|
||||||
.ws-shared-badge{flex-shrink:0;margin-right:4px;font-size:13px;line-height:1;opacity:.9;}
|
.ws-shared-badge{flex-shrink:0;margin-right:4px;font-size:13px;line-height:1;opacity:.9;filter:grayscale(1) brightness(1.6);}
|
||||||
.ws-tree-item .actions{display:none;gap:2px;}
|
.ws-tree-item .actions{display:none;gap:2px;}
|
||||||
.ws-tree-item:hover .actions{display:flex;}
|
.ws-tree-item:hover .actions{display:flex;}
|
||||||
.ws-chevron{width:16px;height:16px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:none;border:none;color:var(--text-tertiary);cursor:pointer;font-size:8px;padding:0;border-radius:3px;transition:transform 150ms,color 100ms;}
|
.ws-chevron{width:16px;height:16px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:none;border:none;color:var(--text-tertiary);cursor:pointer;font-size:8px;padding:0;border-radius:3px;transition:transform 150ms,color 100ms;}
|
||||||
@@ -2537,6 +2537,7 @@ console.log('FLOWDECK v2.4.6 — IIFE done, _wsInitData keys:', Object.keys(wind
|
|||||||
<template x-if="node.is_folder">
|
<template x-if="node.is_folder">
|
||||||
<span class="name folder" @click.stop="navigateToFolder(node.id)"
|
<span class="name folder" @click.stop="navigateToFolder(node.id)"
|
||||||
@dblclick.prevent.stop="startInlineRename(node, $event)">
|
@dblclick.prevent.stop="startInlineRename(node, $event)">
|
||||||
|
<span x-show="node.is_shared" class="ws-shared-badge" title="Partagé" x-text="'👥'"></span>
|
||||||
<span x-show="renamingId !== node.id" x-text="node.name"></span>
|
<span x-show="renamingId !== node.id" x-text="node.name"></span>
|
||||||
<span class="child-count" x-show="node.child_count > 0 && renamingId !== node.id"
|
<span class="child-count" x-show="node.child_count > 0 && renamingId !== node.id"
|
||||||
x-text="'(' + node.child_count + ')'"></span>
|
x-text="'(' + node.child_count + ')'"></span>
|
||||||
@@ -2550,6 +2551,7 @@ console.log('FLOWDECK v2.4.6 — IIFE done, _wsInitData keys:', Object.keys(wind
|
|||||||
@mouseenter="showPreview($event, node)"
|
@mouseenter="showPreview($event, node)"
|
||||||
@mouseleave="hidePreview()"
|
@mouseleave="hidePreview()"
|
||||||
title="Click to rename, double-click to open">
|
title="Click to rename, double-click to open">
|
||||||
|
<span x-show="node.is_shared" class="ws-shared-badge" title="Partagé" x-text="'👥'"></span>
|
||||||
<span x-show="renamingId !== node.id" x-text="node.name"></span>
|
<span x-show="renamingId !== node.id" x-text="node.name"></span>
|
||||||
<input x-show="renamingId === node.id" class="inline-rename-input" x-model="renamingName"
|
<input x-show="renamingId === node.id" class="inline-rename-input" x-model="renamingName"
|
||||||
@keydown.enter="commitRename(node)" @keydown.escape="cancelRename()"
|
@keydown.enter="commitRename(node)" @keydown.escape="cancelRename()"
|
||||||
@@ -2629,6 +2631,7 @@ console.log('FLOWDECK v2.4.6 — IIFE done, _wsInitData keys:', Object.keys(wind
|
|||||||
<td><input type="checkbox" :checked="!!selectedIds[node.id]" @click.stop="toggleSelect(node, $event)"></td>
|
<td><input type="checkbox" :checked="!!selectedIds[node.id]" @click.stop="toggleSelect(node, $event)"></td>
|
||||||
<td>
|
<td>
|
||||||
<span class="table-icon" x-html="_fileIcon(node.name, node.is_folder, node.content_format)"></span>
|
<span class="table-icon" x-html="_fileIcon(node.name, node.is_folder, node.content_format)"></span>
|
||||||
|
<span x-show="node.is_shared" class="ws-shared-badge" title="Partagé" x-text="'👥'"></span>
|
||||||
<span class="col-name" @click="node.is_folder ? navigateToFolder(node.id) : openPage(node.id)" x-text="node.name"></span>
|
<span class="col-name" @click="node.is_folder ? navigateToFolder(node.id) : openPage(node.id)" x-text="node.name"></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="col-path" x-text="node._path || '—'"></td>
|
<td class="col-path" x-text="node._path || '—'"></td>
|
||||||
@@ -2684,7 +2687,8 @@ console.log('FLOWDECK v2.4.6 — IIFE done, _wsInitData keys:', Object.keys(wind
|
|||||||
</tr>
|
</tr>
|
||||||
<template x-for="node in displayTree" :key="'l'+node.id">
|
<template x-for="node in displayTree" :key="'l'+node.id">
|
||||||
<tr :data-ws-id="node.id" @click="node.is_folder ? navigateToFolder(node.id) : selectForPreview(node)" @mouseenter="showPreview($event, node)" @mouseleave="hidePreview()" style="cursor:pointer">
|
<tr :data-ws-id="node.id" @click="node.is_folder ? navigateToFolder(node.id) : selectForPreview(node)" @mouseenter="showPreview($event, node)" @mouseleave="hidePreview()" style="cursor:pointer">
|
||||||
<td><span x-html="_fileIcon(node.name, node.is_folder, node.content_format)"></span></td>
|
<td><span x-html="_fileIcon(node.name, node.is_folder, node.content_format)"></span>
|
||||||
|
<span x-show="node.is_shared" class="ws-shared-badge" title="Partagé" x-text="'👥'"></span></td>
|
||||||
<td class="col-name" x-text="node.name"></td>
|
<td class="col-name" x-text="node.name"></td>
|
||||||
<td style="font-size:12px;color:var(--text-tertiary)" x-text="node.is_folder ? 'Folder' : _fileTypeLabel(node.name, node.content_format)"></td>
|
<td style="font-size:12px;color:var(--text-tertiary)" x-text="node.is_folder ? 'Folder' : _fileTypeLabel(node.name, node.content_format)"></td>
|
||||||
<td style="font-size:12px;color:var(--text-secondary)" x-text="node.is_folder ? (node.child_count||0)+' items' : (node.size_display||'—')"></td>
|
<td style="font-size:12px;color:var(--text-secondary)" x-text="node.is_folder ? (node.child_count||0)+' items' : (node.size_display||'—')"></td>
|
||||||
@@ -2721,7 +2725,8 @@ console.log('FLOWDECK v2.4.6 — IIFE done, _wsInitData keys:', Object.keys(wind
|
|||||||
<template x-for="node in displayTree" :key="'d'+node.id">
|
<template x-for="node in displayTree" :key="'d'+node.id">
|
||||||
<tr :data-ws-id="node.id" @click="node.is_folder ? navigateToFolder(node.id) : selectForPreview(node)" @mouseenter="showPreview($event, node)" @mouseleave="hidePreview()" style="cursor:pointer"
|
<tr :data-ws-id="node.id" @click="node.is_folder ? navigateToFolder(node.id) : selectForPreview(node)" @mouseenter="showPreview($event, node)" @mouseleave="hidePreview()" style="cursor:pointer"
|
||||||
:class="{ 'selected-row': previewItem && previewItem.id === node.id }">
|
:class="{ 'selected-row': previewItem && previewItem.id === node.id }">
|
||||||
<td><span class="table-icon" x-html="_fileIcon(node.name, node.is_folder, node.content_format)"></span></td>
|
<td><span class="table-icon" x-html="_fileIcon(node.name, node.is_folder, node.content_format)"></span>
|
||||||
|
<span x-show="node.is_shared" class="ws-shared-badge" title="Partagé" x-text="'👥'"></span></td>
|
||||||
<td class="col-name" x-text="node.name"></td>
|
<td class="col-name" x-text="node.name"></td>
|
||||||
<td class="col-path" x-text="node._path || '—'"></td>
|
<td class="col-path" x-text="node._path || '—'"></td>
|
||||||
<td class="col-size" x-text="node.size_display || '—'"></td>
|
<td class="col-size" x-text="node.size_display || '—'"></td>
|
||||||
@@ -2752,7 +2757,10 @@ console.log('FLOWDECK v2.4.6 — IIFE done, _wsInitData keys:', Object.keys(wind
|
|||||||
<div class="title-card" :data-ws-id="node.id" @click="node.is_folder ? navigateToFolder(node.id) : selectForPreview(node)" @mouseenter="showPreview($event, node)" @mouseleave="hidePreview()"
|
<div class="title-card" :data-ws-id="node.id" @click="node.is_folder ? navigateToFolder(node.id) : selectForPreview(node)" @mouseenter="showPreview($event, node)" @mouseleave="hidePreview()"
|
||||||
:class="{ 'selected-card': previewItem && previewItem.id === node.id }">
|
:class="{ 'selected-card': previewItem && previewItem.id === node.id }">
|
||||||
<div class="title-card-icon" x-html="node.is_folder ? getSvgIcon('folder',24) : _fileIcon(node.name, node.is_folder, node.content_format)"></div>
|
<div class="title-card-icon" x-html="node.is_folder ? getSvgIcon('folder',24) : _fileIcon(node.name, node.is_folder, node.content_format)"></div>
|
||||||
<div class="title-card-name" x-text="node.name"></div>
|
<div class="title-card-name">
|
||||||
|
<span x-show="node.is_shared" class="ws-shared-badge" title="Partagé" x-text="'👥'"></span>
|
||||||
|
<span x-text="node.name"></span>
|
||||||
|
</div>
|
||||||
<div class="title-card-meta">
|
<div class="title-card-meta">
|
||||||
<span x-text="_formatDate(node.updated_at)"></span>
|
<span x-text="_formatDate(node.updated_at)"></span>
|
||||||
<span x-text="node.size_display || '—'"></span>
|
<span x-text="node.size_display || '—'"></span>
|
||||||
@@ -2776,6 +2784,7 @@ console.log('FLOWDECK v2.4.6 — IIFE done, _wsInitData keys:', Object.keys(wind
|
|||||||
:class="{ 'selected-row': previewItem && previewItem.id === node.id }">
|
:class="{ 'selected-row': previewItem && previewItem.id === node.id }">
|
||||||
<div class="content-item-header">
|
<div class="content-item-header">
|
||||||
<span x-html="_fileIcon(node.name, node.is_folder, node.content_format)"></span>
|
<span x-html="_fileIcon(node.name, node.is_folder, node.content_format)"></span>
|
||||||
|
<span x-show="node.is_shared" class="ws-shared-badge" title="Partagé" x-text="'👥'"></span>
|
||||||
<span class="col-name" x-text="node.name"></span>
|
<span class="col-name" x-text="node.name"></span>
|
||||||
<span style="font-size:11px;color:var(--text-tertiary);margin-left:auto" x-text="_formatDate(node.updated_at)"></span>
|
<span style="font-size:11px;color:var(--text-tertiary);margin-left:auto" x-text="_formatDate(node.updated_at)"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -696,6 +696,15 @@ input, select, textarea { font-family: inherit; color: inherit; }
|
|||||||
background: var(--bg-hover);
|
background: var(--bg-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Shared badge — black & white (grayscale) */
|
||||||
|
.page-shared-badge {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 2px;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1;
|
||||||
|
filter: grayscale(1) brightness(1.6);
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-item.active {
|
.sidebar-item.active {
|
||||||
background: var(--bg-active);
|
background: var(--bg-active);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user