fix(library): supprimer getters Alpine 3.14.9 + Private tab caché quand workspace actif
FlowDeck CI / test (push) Failing after 8s
FlowDeck CI / docker (push) Has been skipped

- Tous les getters (flatItems, selectedCount, allSelected, emptyIcon/Title/Text)
  remplacés par des propriétés + fonctions _recompute().
  Les getters causent un bug connu d'Alpine 3.14.9 qui bloque l'init.
- Private tab: x-show="!workspaceId && !isGiteaActive"
  (caché quand un workspace local OU distant est ouvert)
This commit is contained in:
2026-07-19 13:45:27 -04:00
parent 2ee0a05efd
commit 9f17c39599
+29 -20
View File
@@ -179,7 +179,7 @@
<button class="lib-tab" :class="{ active: tab === 'published' }" @click="switchTab('published')"> <button class="lib-tab" :class="{ active: tab === 'published' }" @click="switchTab('published')">
<span class="tab-icon">🌐</span> Published <span class="tab-icon">🌐</span> Published
</button> </button>
<button class="lib-tab" :class="{ active: tab === 'private' }" @click="switchTab('private')" x-show="!isGiteaActive"> <button class="lib-tab" :class="{ active: tab === 'private' }" @click="switchTab('private')" x-show="!workspaceId && !isGiteaActive">
<span class="tab-icon">🔒</span> Private <span class="tab-icon">🔒</span> Private
</button> </button>
<button class="lib-tab" :class="{ active: tab === 'repository' }" @click="switchTab('repository')" x-show="isGiteaActive"> <button class="lib-tab" :class="{ active: tab === 'repository' }" @click="switchTab('repository')" x-show="isGiteaActive">
@@ -346,10 +346,8 @@ function libraryPage() {
// Selection // Selection
selected: {}, selected: {},
get selectedCount() { return Object.keys(this.selected).length; }, selectedCount: 0,
get allSelected() { allSelected: false,
return this.flatItems.length > 0 && this.selectedCount === this.flatItems.length;
},
// Tree // Tree
expanded: {}, expanded: {},
@@ -369,18 +367,21 @@ function libraryPage() {
peekFavorited: false, peekFavorited: false,
peekMoreOpen: false, peekMoreOpen: false,
// ── Computed flat list ── // ── Computed flat list (NOT a getter — Alpine 3.14.9 bug) ──
get flatItems() { flatItems: [],
_recomputeFlatItems() {
var result = []; var result = [];
this._flatten(this.items, result, 0); this._flatten(this.items, result, 0);
// Apply search filter
if (this.searchQuery.trim()) { if (this.searchQuery.trim()) {
var q = this.searchQuery.toLowerCase(); var q = this.searchQuery.toLowerCase();
result = result.filter(function(r) { result = result.filter(function(r) {
return (r.title || '').toLowerCase().indexOf(q) !== -1; return (r.title || '').toLowerCase().indexOf(q) !== -1;
}); });
} }
return result; this.flatItems = result;
this.selectedCount = Object.keys(this.selected).length;
this.allSelected = this.flatItems.length > 0 && this.selectedCount === this.flatItems.length;
}, },
_flatten(nodes, out, depth) { _flatten(nodes, out, depth) {
@@ -396,17 +397,17 @@ function libraryPage() {
}, },
// ── Empty states ── // ── Empty states ──
get emptyIcon() { emptyIcon: '📄',
emptyTitle: 'No items',
emptyText: '',
_recomputeEmpty() {
var icons = {recents:'🕒',favorites:'⭐',shared:'👥',published:'🌐',private:'🔒',workspace:'📁',repository:'📦'}; var icons = {recents:'🕒',favorites:'⭐',shared:'👥',published:'🌐',private:'🔒',workspace:'📁',repository:'📦'};
return icons[this.tab] || '📄'; this.emptyIcon = icons[this.tab] || '📄';
},
get emptyTitle() {
var titles = {recents:'No recent pages',favorites:'No favorites',shared:'No shared pages', 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', published:'No published pages',private:'No private pages',workspace:'No workspace pages',
repository:'Empty repository'}; repository:'Empty repository'};
return titles[this.tab] || 'No items'; this.emptyTitle = titles[this.tab] || 'No items';
},
get emptyText() {
var texts = {recents:'Pages you\'ve recently viewed or edited will appear here.', var texts = {recents:'Pages you\'ve recently viewed or edited will appear here.',
favorites:'Right-click a page in the sidebar and select "Add to Favorites".', favorites:'Right-click a page in the sidebar and select "Add to Favorites".',
shared:'Shared pages from your team will appear here.', shared:'Shared pages from your team will appear here.',
@@ -414,7 +415,7 @@ function libraryPage() {
private:'Create a new page with the + button.', private:'Create a new page with the + button.',
workspace:'Pages inside workspaces will appear here.', workspace:'Pages inside workspaces will appear here.',
repository:'Repository files and pages will appear here.'}; repository:'Repository files and pages will appear here.'};
return texts[this.tab] || ''; this.emptyText = texts[this.tab] || '';
}, },
// ── Init ── // ── Init ──
@@ -430,6 +431,7 @@ function libraryPage() {
if (t && ['recents','favorites','shared','published','private','workspace','repository'].indexOf(t) !== -1) { if (t && ['recents','favorites','shared','published','private','workspace','repository'].indexOf(t) !== -1) {
this.tab = t; this.tab = t;
} }
this._recomputeEmpty();
this.loadTab(); this.loadTab();
}, },
@@ -439,9 +441,12 @@ function libraryPage() {
this.tab = t; this.tab = t;
this.items = []; this.items = [];
this.selected = {}; this.selected = {};
this.selectedCount = 0;
this.allSelected = false;
this.expanded = {}; this.expanded = {};
this.searchQuery = ''; this.searchQuery = '';
this.searchOpen = false; this.searchOpen = false;
this._recomputeEmpty();
this.updateUrl(); this.updateUrl();
this.loadTab(); this.loadTab();
}, },
@@ -470,6 +475,7 @@ function libraryPage() {
var d = await r.json(); var d = await r.json();
this.items = d.items || []; this.items = d.items || [];
this._markTree(this.items, 0); this._markTree(this.items, 0);
this._recomputeFlatItems();
} catch(e) { } catch(e) {
console.error('Library load:', e); console.error('Library load:', e);
this.items = []; this.items = [];
@@ -490,7 +496,7 @@ function libraryPage() {
} }
}, },
doSearch() { /* flatItems reacts to searchQuery */ }, doSearch() { this._recomputeFlatItems(); },
doSort() { doSort() {
var s = this.sortBy; var s = this.sortBy;
if (!s) return; if (!s) return;
@@ -508,7 +514,7 @@ function libraryPage() {
// Collapse // Collapse
delete this.expanded[item.id]; delete this.expanded[item.id];
this.expanded = Object.assign({}, this.expanded); this.expanded = Object.assign({}, this.expanded);
this.items = [...this.items]; // force reactivity this._recomputeFlatItems();
return; return;
} }
// Expand — load children if not loaded yet // Expand — load children if not loaded yet
@@ -525,7 +531,7 @@ function libraryPage() {
item.children = []; item.children = [];
} }
} }
this.items = [...this.items]; // force Alpine reactivity this._recomputeFlatItems();
}, },
_markChildren(nodes, depth) { _markChildren(nodes, depth) {
@@ -546,6 +552,7 @@ function libraryPage() {
this.selected[item.id] = true; this.selected[item.id] = true;
} }
this.selected = Object.assign({}, this.selected); this.selected = Object.assign({}, this.selected);
this._recomputeFlatItems();
}, },
toggleSelectAll() { toggleSelectAll() {
@@ -558,11 +565,13 @@ function libraryPage() {
} }
this.selected = s; this.selected = s;
} }
this._recomputeFlatItems();
}, },
clearSelection() { clearSelection() {
this.selected = {}; this.selected = {};
this.moreOpen = false; this.moreOpen = false;
this._recomputeFlatItems();
}, },
// ── Multi-select actions ── // ── Multi-select actions ──