fix: 5 bugs — couleur tag, tags existants, modal settings, rename, filtrage
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped

1. ctxAddNewTag lit window._ctxMenuData.ctxNewTagColor (pas this.ctxNewTagColor)
   → la couleur sélectionnée dans le menu est maintenant sauvegardée

2. onContextMenu: charge workspaceTags si vide avant de calculer ctxAvailTags
   → les tags existants apparaissent dans le dropdown

3. Settings: CSS modal-overlay/modal-box/.btn-danger ajouté
   → le modal delete n'est plus transparent

4. Rename tag: modal avec input au lieu de prompt()
   → double-clic → modal avec couleur + input + autofocus

5. doFilter: _filterTreeByTag filtre displayTree quand tagFilter est actif
   → le filtrage par tags fonctionne dans toutes les vues
This commit is contained in:
2026-07-13 11:34:43 -04:00
parent 53865f136d
commit 51c6002f08
2 changed files with 69 additions and 6 deletions
+25 -2
View File
@@ -751,6 +751,10 @@ window._wsInitData = (function() {
if (!id) { menu.style.display = 'none'; return; }
var node = this._findNodeById(this.displayTree, id);
if (!node) { menu.style.display = 'none'; return; }
// Ensure workspace tags are loaded
if (!this.workspaceTags || this.workspaceTags.length === 0) {
this.loadWorkspaceTags();
}
// Store in Alpine data for menu actions (ctxMenuOpenPage, etc.)
this.ctxMenu = {visible:true, x:ev.clientX, y:ev.clientY, node:node, tags:[...(node.tags||[])]};
this.ctxTagAdding = false;
@@ -868,7 +872,7 @@ window._wsInitData = (function() {
if (!tagName) return;
var node = this.ctxMenu.node;
if (!node) return;
color = color || this.ctxNewTagColor;
color = color || window._ctxMenuData.ctxNewTagColor;
var r = await fetch('/api/local-workspace/items/' + node.id + '/tags', {
method: 'POST', headers: {'Content-Type':'application/json'},
body: JSON.stringify({name: tagName.trim(), color: color})
@@ -1393,9 +1397,28 @@ window._wsInitData = (function() {
var q = (this.searchQuery || '').toLowerCase().trim();
var ft = this.filterType || '';
if (!q && !ft && !this.tagFilter) { this.displayTree = [...this.tree]; this._computeFilteredTableItems(); return; }
this.displayTree = [...this.tree];
if (this.tagFilter) {
// Filter tree by tag
this.displayTree = this._filterTreeByTag([...this.tree], this.tagFilter);
} else {
this.displayTree = [...this.tree];
}
this._computeFilteredTableItems();
},
_filterTreeByTag(nodes, tagName) {
var result = [];
for (var i=0; i<nodes.length; i++) {
var n = nodes[i];
var hasTag = (n.tags || []).some(function(t) { return t.name === tagName; });
var filteredChildren = n.children ? this._filterTreeByTag(n.children, tagName) : [];
if (hasTag || filteredChildren.length > 0) {
var clone = Object.assign({}, n);
clone.children = filteredChildren;
result.push(clone);
}
}
return result;
},
filterByType(type) {
this.filterType = (this.filterType === type) ? '' : type;
this.doFilter();