Files
flowdeck/app/templates/library.html
T
bruno 24e979a05f
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
fix: sidebar Favorites + Shared, Library page with tabs, CSRF fix
- Section Favorites ajoutée dans le sidebar (⭐)
- Section Shared ajoutée (👥)
- Section Library remplacée par bouton 📚 qui ouvre /library
- Page /library avec onglets: Recents | Favorites | Shared | Private
- CSRF token injecté dans les appels fetch (newPage, newSubPage)
- Bouton + sur éléments sidebar corrigé (POST /board/api/pages avec X-CSRF-Token)
- Bouton 📚 sur sections ouvre /library
- sidebar_data inclut favorite_pages=[]
2026-07-08 15:17:14 -04:00

131 lines
5.2 KiB
HTML

{% extends "base.html" %}
{% block page_icon %}📚{% endblock %}
{% block page_title %}Library{% endblock %}
{% block content %}
<div class="page-title-area">
<div class="page-title">
<span class="page-icon-lg">📚</span>
<h1>Library</h1>
</div>
</div>
<!-- Library tabs: Recents | Favorites | Shared | Private -->
<div class="view-tabs" x-data="{ tab: 'recents' }">
<button class="view-tab" :class="{ active: tab === 'recents' }" @click="tab = 'recents'">
<span class="tab-icon">🕒</span> Recents
</button>
<button class="view-tab" :class="{ active: tab === 'favorites' }" @click="tab = 'favorites'">
<span class="tab-icon">⭐</span> Favorites
</button>
<button class="view-tab" :class="{ active: tab === 'shared' }" @click="tab = 'shared'">
<span class="tab-icon">👥</span> Shared
</button>
<button class="view-tab" :class="{ active: tab === 'private' }" @click="tab = 'private'">
<span class="tab-icon">🔒</span> Private
</button>
</div>
<!-- Toolbar -->
<div class="view-toolbar">
<div class="view-toolbar-spacer"></div>
<button class="btn-new" @click="newPage()">New page</button>
</div>
<!-- Library content -->
<div x-data="libraryData()" style="padding: 0 24px;">
<!-- Table headers -->
<div style="display:flex; padding: 8px 12px; border-bottom:1px solid var(--border); font-size:12px; font-weight:600; color:var(--text-dim);">
<span style="flex:1;">Page name</span>
<span style="width:160px;">Last edited time</span>
</div>
<!-- Recents tab -->
<div x-show="tab === 'recents'">
{% for page in recent_pages %}
<a href="{{ page.url }}" style="display:flex; align-items:center; padding:8px 12px; text-decoration:none; color:var(--text-primary); border-radius:6px; transition:background 0.15s;"
onmouseover="this.style.background='var(--bg-hover)'" onmouseout="this.style.background='transparent'">
<span style="font-size:16px; margin-right:10px;">{{ page.icon }}</span>
<span style="flex:1;">{{ page.name }}</span>
<span style="width:160px; font-size:13px; color:var(--text-dim);">{{ page.last_edited }}</span>
</a>
{% endfor %}
{% if not recent_pages %}
<div style="text-align:center; padding:48px; color:var(--text-dim);">
<div style="font-size:48px; margin-bottom:16px;">🕒</div>
<h3>No recent pages</h3>
</div>
{% endif %}
</div>
<!-- Favorites tab -->
<div x-show="tab === 'favorites'">
{% for page in favorite_pages %}
<a href="{{ page.url }}" style="display:flex; align-items:center; padding:8px 12px; text-decoration:none; color:var(--text-primary); border-radius:6px;"
onmouseover="this.style.background='var(--bg-hover)'" onmouseout="this.style.background='transparent'">
<span style="font-size:16px; margin-right:10px;">{{ page.icon }}</span>
<span style="flex:1;">{{ page.name }}</span>
<span style="width:160px; font-size:13px; color:var(--text-dim);">{{ page.last_edited }}</span>
</a>
{% endfor %}
{% if not favorite_pages %}
<div style="text-align:center; padding:48px; color:var(--text-dim);">
<div style="font-size:48px; margin-bottom:16px;">⭐</div>
<h3>No favorites</h3>
<p style="margin-top:8px;">Right-click a page in the sidebar and select "Add to Favorites".</p>
</div>
{% endif %}
</div>
<!-- Shared tab -->
<div x-show="tab === 'shared'">
<div style="text-align:center; padding:48px; color:var(--text-dim);">
<div style="font-size:48px; margin-bottom:16px;">👥</div>
<h3>No shared pages</h3>
<p style="margin-top:8px;">Shared pages from your team will appear here.</p>
</div>
</div>
<!-- Private tab -->
<div x-show="tab === 'private'">
{% for page in private_pages %}
<a href="{{ page.url }}" style="display:flex; align-items:center; padding:8px 12px; text-decoration:none; color:var(--text-primary); border-radius:6px;"
onmouseover="this.style.background='var(--bg-hover)'" onmouseout="this.style.background='transparent'">
<span style="font-size:16px; margin-right:10px;">{{ page.icon }}</span>
<span style="flex:1;">{{ page.name }}</span>
<span style="width:160px; font-size:13px; color:var(--text-dim);">{{ page.last_edited }}</span>
</a>
{% endfor %}
{% if not private_pages %}
<div style="text-align:center; padding:48px; color:var(--text-dim);">
<div style="font-size:48px; margin-bottom:16px;">🔒</div>
<h3>No private pages</h3>
<p style="margin-top:8px;">Create a new page with the + button in the sidebar.</p>
</div>
{% endif %}
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
function libraryData() {
return {
get tab() { return document.querySelector('[x-data]').__x.$data.tab; }
};
}
function newPage() {
const csrf = document.cookie.match(/csrf_token=([^;]+)/);
const token = csrf ? csrf[1] : '';
fetch('/board/api/pages?title=New%20page&section=Private', {
method: 'POST',
headers: { 'X-CSRF-Token': token }
})
.then(r => { if (!r.ok) throw new Error('CSRF error'); return r.json(); })
.then(data => { window.location.href = `/pages/${data.id}`; })
.catch(err => { alert('Failed: ' + err.message); });
}
</script>
{% endblock %}