From 53865f136d9610701dad85478d1a7f9ab3728497 Mon Sep 17 00:00:00 2001 From: bruno Date: Mon, 13 Jul 2026 11:20:51 -0400 Subject: [PATCH] fix: tags contextuels + rename/delete confirm dans Settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Context menu (_ctxMenuData): - Remplacé getters par propriétés simples (Alpine ne réagit pas aux getters) - Sync _wsInitData → _ctxMenuData dans onContextMenu, ctxAddNewTag, ctxRemoveTag - Les 4 tags existants apparaissent maintenant dans le dropdown Settings > Tags: - Double-clic sur un tag → prompt rename (PUT /api/settings/tags/) - Suppression: modal de confirmation au lieu de confirm() natif - Affiche le nombre d'items impactés si tag utilisé --- app/templates/local_workspace.html | 30 +++++++++++++-------- app/templates/settings.html | 43 ++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/app/templates/local_workspace.html b/app/templates/local_workspace.html index 6f22562..93d22e3 100644 --- a/app/templates/local_workspace.html +++ b/app/templates/local_workspace.html @@ -774,6 +774,13 @@ window._wsInitData = (function() { menu.style.top = y + 'px'; this.ctxMenu.x = x; this.ctxMenu.y = y; + // Sync to _ctxMenuData for Alpine reactivity + var c = window._ctxMenuData; + c.ctxMenu = this.ctxMenu; + c.ctxTagAdding = this.ctxTagAdding; + c.ctxTagExistingOpen = this.ctxTagExistingOpen; + c.ctxAvailTags = this.ctxAvailTags; + c.ctxNewTagColor = this.ctxNewTagColor; }, // ── Long-press (mobile context menu) ── @@ -851,6 +858,9 @@ window._wsInitData = (function() { this.ctxAvailTags = (this.workspaceTags || []).filter(function(t) { return !(this.ctxMenu.tags||[]).some(function(nt) { return nt.id === t.id; }); }.bind(this)); + // Sync to _ctxMenuData + window._ctxMenuData.ctxAvailTags = this.ctxAvailTags; + window._ctxMenuData.ctxMenu = this.ctxMenu; }, async ctxAddNewTag(tagName, color) { @@ -875,6 +885,9 @@ window._wsInitData = (function() { self.ctxAvailTags = (self.workspaceTags || []).filter(function(t) { return !(self.ctxMenu.tags||[]).some(function(nt) { return nt.id === t.id; }); }); + // Sync to _ctxMenuData + window._ctxMenuData.ctxAvailTags = self.ctxAvailTags; + window._ctxMenuData.ctxMenu = self.ctxMenu; }); }, 200); } this.ctxTagAdding = false; @@ -1918,17 +1931,12 @@ for (var _i = 0; _i < _wsKeys.length; _i++) { _wsInitData = window._wsInitData; // Objet léger pour le ctx-menu (évite le conflit $nextTick avec Alpine) window._ctxMenuData = { - get ctxMenu() { return window._wsInitData.ctxMenu; }, - set ctxMenu(v) { window._wsInitData.ctxMenu = v; }, - get ctxTagAdding() { return window._wsInitData.ctxTagAdding; }, - set ctxTagAdding(v) { window._wsInitData.ctxTagAdding = v; }, - get ctxTagExistingOpen() { return window._wsInitData.ctxTagExistingOpen; }, - set ctxTagExistingOpen(v) { window._wsInitData.ctxTagExistingOpen = v; }, - get ctxAvailTags() { return window._wsInitData.ctxAvailTags; }, - set ctxAvailTags(v) { window._wsInitData.ctxAvailTags = v; }, - get ctxNewTagColor() { return window._wsInitData.ctxNewTagColor; }, - set ctxNewTagColor(v) { window._wsInitData.ctxNewTagColor = v; }, - get ctxTagColors() { return window._wsInitData.ctxTagColors; }, + ctxMenu: {visible:false,x:0,y:0,node:null,tags:[]}, + ctxTagAdding: false, + ctxTagExistingOpen: false, + ctxAvailTags: [], + ctxNewTagColor: '#787774', + ctxTagColors: ['#787774','#E03E3E','#D9730D','#DFAB01','#0F7B6C','#0B6E99','#6940A5','#AD1A72','#E16259','#D4A72C','#448361','#337EA9','#9065B0','#C94D8B'], ctxMenuOpenPage() { window._wsInitData.ctxMenuOpenPage(); }, ctxMenuOpenFolder() { window._wsInitData.ctxMenuOpenFolder(); }, ctxMenuRename() { window._wsInitData.ctxMenuRename(); }, diff --git a/app/templates/settings.html b/app/templates/settings.html index 5fd30d9..ce8b447 100644 --- a/app/templates/settings.html +++ b/app/templates/settings.html @@ -193,10 +193,14 @@
@@ -207,6 +211,22 @@
+ + @@ -267,6 +287,7 @@ document.addEventListener('alpine:init', function() { allTags: [], newTagName: '', newTagColor: '#787774', + deletingTag: null, presetColors: ['#787774','#E03E3E','#D9730D','#DFAB01','#0F7B6C','#0B6E99','#6940A5','#AD1A72','#E16259','#D4A72C','#448361','#337EA9','#9065B0','#C94D8B'], avatarUrl: '{{ avatar_url or "" }}', avatarColor: '{{ avatar_color or "#3A3A3A" }}', @@ -310,6 +331,24 @@ document.addEventListener('alpine:init', function() { await this.loadTags(); }, + async renameTag(tag) { + var newName = prompt('Rename tag "' + tag.name + '":', tag.name); + if (!newName || !newName.trim() || newName.trim().toLowerCase() === tag.name.toLowerCase()) return; + await fetch('/api/settings/tags/' + tag.id, { + method: 'PUT', headers: {'Content-Type':'application/json'}, + body: JSON.stringify({name: newName.trim()}) + }); + await this.loadTags(); + }, + + async confirmDeleteTag() { + var tag = this.deletingTag; + if (!tag) return; + await fetch('/api/settings/tags/' + tag.id, { method: 'DELETE' }); + this.deletingTag = null; + await this.loadTags(); + }, + async uploadAvatar(ev) { var file = ev.target.files[0]; if (!file) return;