feat: star favoris dynamique + sidebar refresh sans reload
- page_editor: étoile ⭐/☆ dynamique selon favorited (x-text)
- toggleFavorite() appelle refreshFavorites() du sidebar
- base.html: refreshFavorites() fetch /api/library/favorites + rebuild DOM
- Context menu 'Add to Favorites' → refreshFavorites() au lieu de location.reload()
- Les items dynamiques ont onclick/oncontextmenu pour fonctionner hors Alpine
This commit is contained in:
+35
-2
@@ -601,6 +601,40 @@
|
||||
|
||||
// ── Favorites tracking ──
|
||||
favoriteIds: new Set([{% for p in favorite_pages %}'{{ p.id }}'{% if not loop.last %},{% endif %}{% endfor %}]),
|
||||
|
||||
refreshFavorites() {
|
||||
const self = this;
|
||||
fetch('/api/library/favorites', {credentials:'same-origin'})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
const items = data.items || [];
|
||||
self.favoriteIds = new Set(items.map(i => i.id));
|
||||
const favList = document.querySelector('.sidebar-items[data-section="favorites"]');
|
||||
if (!favList) return;
|
||||
if (items.length === 0) {
|
||||
favList.innerHTML = '<li class="sidebar-item empty-hint"><span class="page-icon">⭐</span><span class="page-name text-dim">No favorites yet</span></li>';
|
||||
} else {
|
||||
favList.innerHTML = items.map(function(item) {
|
||||
const icon = item.icon || '📄';
|
||||
const name = (item.title || 'Untitled');
|
||||
const safeName = name.replace(/'/g, "\\'").replace(/"/g, '"');
|
||||
const url = item.url || ('/pages/' + item.id);
|
||||
return '<li class="sidebar-item" style="padding-left:8px;cursor:pointer" ' +
|
||||
'data-page-id="' + item.id + '" data-page-depth="0" data-has-children="false" ' +
|
||||
'onclick="window.appState.navigateTo(\'' + url + '\')" ' +
|
||||
'oncontextmenu="event.preventDefault();window.appState.showContextMenu(event,\'' + item.id + '\',\'' + safeName + '\')">' +
|
||||
'<span class="tree-toggle-placeholder"></span>' +
|
||||
'<span class="page-icon">' + icon + '</span>' +
|
||||
'<span class="page-name">' + safeName + '</span>' +
|
||||
'<span class="item-actions">' +
|
||||
'<button class="item-action-btn" title="View in Library" onclick="event.stopPropagation();window.appState.navigateTo(\'/library\')">📚</button>' +
|
||||
'<button class="item-action-btn" title="New sub-page" onclick="event.stopPropagation();window.appState.newSubPage(\'' + item.id + '\')">+</button>' +
|
||||
'</span>' +
|
||||
'</li>';
|
||||
}).join('');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ── Sections collapsible ──
|
||||
sectionsOpen: (function() {
|
||||
@@ -727,8 +761,7 @@
|
||||
if (isFav) self.favoriteIds.delete(pageId);
|
||||
else self.favoriteIds.add(pageId);
|
||||
self.contextMenu.visible = false;
|
||||
// Reload to update sidebar
|
||||
location.reload();
|
||||
self.refreshFavorites();
|
||||
})
|
||||
.catch(e => this.toast('Favorite action failed', 'error'));
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user