feat: filtre sauvegardes (Tous/Recherches/Repertoires) extensible
- Barre de filtres avec 3 pills: Tous, Recherches, Repertoires - Chaque saved-search-item a data-type=search|directory - _applySavedFilter() masque/affiche selon le filtre actif - _initSavedFilter() initialise les listeners (run once) - Extensible: ajouter un pill + data-type suffit - Gere l'etat empty quand aucun resultat pour le filtre
This commit is contained in:
+6
-1
@@ -838,13 +838,18 @@
|
|||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
aria-labelledby="sidebar-tab-saved"
|
aria-labelledby="sidebar-tab-saved"
|
||||||
>
|
>
|
||||||
|
<div class="saved-filter-bar" id="saved-filter-bar">
|
||||||
|
<button class="saved-filter-pill active" data-filter="all">Tous</button>
|
||||||
|
<button class="saved-filter-pill" data-filter="search">Recherches</button>
|
||||||
|
<button class="saved-filter-pill" data-filter="directory">Repertoires</button>
|
||||||
|
</div>
|
||||||
<div id="saved-searches-list" class="recent-list"></div>
|
<div id="saved-searches-list" class="recent-list"></div>
|
||||||
<div id="saved-searches-empty" class="recent-empty">
|
<div id="saved-searches-empty" class="recent-empty">
|
||||||
<i
|
<i
|
||||||
data-lucide="bookmark"
|
data-lucide="bookmark"
|
||||||
style="width: 32px; height: 32px"
|
style="width: 32px; height: 32px"
|
||||||
></i>
|
></i>
|
||||||
<span>Aucune recherche sauvegardée</span>
|
<span>Aucune recherche sauvegardee</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
@@ -347,16 +347,19 @@ async function loadSavedSearches() {
|
|||||||
if (s.exclude_paths) pathFilters.push(`<span class="saved-search-path" title="Exclure: ${escapeHtml(s.exclude_paths)}">\u{1F4E4} ${escapeHtml(s.exclude_paths)}</span>`);
|
if (s.exclude_paths) pathFilters.push(`<span class="saved-search-path" title="Exclure: ${escapeHtml(s.exclude_paths)}">\u{1F4E4} ${escapeHtml(s.exclude_paths)}</span>`);
|
||||||
const vaultStr = s.vault && s.vault !== "all" ? `<span class="saved-search-vault">\u{1F4C1} ${escapeHtml(s.vault)}</span>` : "";
|
const vaultStr = s.vault && s.vault !== "all" ? `<span class="saved-search-vault">\u{1F4C1} ${escapeHtml(s.vault)}</span>` : "";
|
||||||
return `
|
return `
|
||||||
<div class="saved-search-item${isDirSearch ? ' saved-search-dir' : ''}">
|
<div class="saved-search-item${isDirSearch ? ' saved-search-dir' : ''}" data-type="${isDirSearch ? 'directory' : 'search'}">
|
||||||
<div class="saved-search-query">${displayQuery}</div>
|
<div class="saved-search-query">${displayQuery}</div>
|
||||||
<div class="saved-search-meta">
|
<div class="saved-search-meta">
|
||||||
<span class="saved-search-badges">${badges.join("")} ${vaultStr}</span>
|
<span class="saved-search-badges">${badges.join("")} ${vaultStr}</span>
|
||||||
${typeIcon}
|
${typeIcon}
|
||||||
</div>
|
</div>
|
||||||
${pathFilters.length ? '<div class="saved-search-filters">' + pathFilters.join(" ") + '</div>' : ""}
|
${pathFilters.length ? '<div class="saved-search-filters">' + pathFilters.join(" ") + '</div>' : ""}
|
||||||
<button class="saved-search-delete" data-id="${s.id}" title="Supprimer"><E2><9C><95></button>
|
<button class="saved-search-delete" data-id="${s.id}" title="Supprimer">✕</button>
|
||||||
</div>
|
</div>
|
||||||
`}).join("");
|
`}).join("");
|
||||||
|
// Apply saved filter + init filter bar
|
||||||
|
if (typeof _applySavedFilter === 'function') _applySavedFilter();
|
||||||
|
if (typeof _initSavedFilter === 'function') _initSavedFilter();
|
||||||
list.querySelectorAll(".saved-search-item").forEach(item => {
|
list.querySelectorAll(".saved-search-item").forEach(item => {
|
||||||
item.addEventListener("click", (e) => {
|
item.addEventListener("click", (e) => {
|
||||||
if (e.target.classList.contains("saved-search-delete")) return;
|
if (e.target.classList.contains("saved-search-delete")) return;
|
||||||
|
|||||||
+38
-1
@@ -1054,7 +1054,7 @@ export async function loadSavedSearches() {
|
|||||||
if (s.exclude_paths) pathFilters.push(`<span class="saved-search-path" title="Exclure: ${escapeHtml(s.exclude_paths)}">📤 ${escapeHtml(s.exclude_paths)}</span>`);
|
if (s.exclude_paths) pathFilters.push(`<span class="saved-search-path" title="Exclure: ${escapeHtml(s.exclude_paths)}">📤 ${escapeHtml(s.exclude_paths)}</span>`);
|
||||||
const vaultStr = s.vault && s.vault !== "all" ? `<span class="saved-search-vault">📁 ${escapeHtml(s.vault)}</span>` : "";
|
const vaultStr = s.vault && s.vault !== "all" ? `<span class="saved-search-vault">📁 ${escapeHtml(s.vault)}</span>` : "";
|
||||||
return `
|
return `
|
||||||
<div class="saved-search-item${isDirSearch ? ' saved-search-dir' : ''}">
|
<div class="saved-search-item${isDirSearch ? ' saved-search-dir' : ''}" data-type="${isDirSearch ? 'directory' : 'search'}">
|
||||||
<div class="saved-search-query">${displayQuery}</div>
|
<div class="saved-search-query">${displayQuery}</div>
|
||||||
<div class="saved-search-meta">
|
<div class="saved-search-meta">
|
||||||
<span class="saved-search-badges">${badges.join("")} ${vaultStr}</span>
|
<span class="saved-search-badges">${badges.join("")} ${vaultStr}</span>
|
||||||
@@ -1064,6 +1064,10 @@ export async function loadSavedSearches() {
|
|||||||
<button class="saved-search-delete" data-id="${s.id}" title="Supprimer">✕</button>
|
<button class="saved-search-delete" data-id="${s.id}" title="Supprimer">✕</button>
|
||||||
</div>
|
</div>
|
||||||
`}).join("");
|
`}).join("");
|
||||||
|
// Apply saved filter
|
||||||
|
_applySavedFilter();
|
||||||
|
// Set up filter bar (once)
|
||||||
|
_initSavedFilter();
|
||||||
list.querySelectorAll(".saved-search-item").forEach(item => {
|
list.querySelectorAll(".saved-search-item").forEach(item => {
|
||||||
item.addEventListener("click", (e) => {
|
item.addEventListener("click", (e) => {
|
||||||
if (e.target.classList.contains("saved-search-delete")) return;
|
if (e.target.classList.contains("saved-search-delete")) return;
|
||||||
@@ -1453,7 +1457,40 @@ function _renderSyncPanel(panel) {
|
|||||||
});
|
});
|
||||||
html += `</div>`;
|
html += `</div>`;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Saved searches filter ──
|
||||||
|
var _savedFilterType = 'all';
|
||||||
|
var _savedFilterInitDone = false;
|
||||||
|
|
||||||
|
function _initSavedFilter() {
|
||||||
|
if (_savedFilterInitDone) return;
|
||||||
|
var bar = document.getElementById('saved-filter-bar');
|
||||||
|
if (!bar) return;
|
||||||
|
bar.querySelectorAll('.saved-filter-pill').forEach(function(btn) {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
bar.querySelectorAll('.saved-filter-pill').forEach(function(b) { b.classList.remove('active'); });
|
||||||
|
btn.classList.add('active');
|
||||||
|
_savedFilterType = btn.dataset.filter;
|
||||||
|
_applySavedFilter();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
_savedFilterInitDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _applySavedFilter() {
|
||||||
|
var items = document.querySelectorAll('.saved-search-item');
|
||||||
|
var hasVisible = false;
|
||||||
|
items.forEach(function(item) {
|
||||||
|
var type = item.dataset.type;
|
||||||
|
var show = _savedFilterType === 'all' || type === _savedFilterType;
|
||||||
|
item.style.display = show ? '' : 'none';
|
||||||
|
if (show) hasVisible = true;
|
||||||
|
});
|
||||||
|
// Show/hide empty state
|
||||||
|
var empty = document.getElementById('saved-searches-empty');
|
||||||
|
if (empty) empty.style.display = hasVisible ? 'none' : '';
|
||||||
|
}
|
||||||
panel.innerHTML = html;
|
panel.innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2094,6 +2094,29 @@ select {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
/* Saved filter bar */
|
||||||
|
.saved-filter-bar {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 8px 10px 10px;
|
||||||
|
}
|
||||||
|
.saved-filter-pill {
|
||||||
|
padding: 3px 10px;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 500;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 12px;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.15s, color 0.15s, border-color 0.15s;
|
||||||
|
}
|
||||||
|
.saved-filter-pill:hover { background: var(--bg-hover); color: var(--text-primary); }
|
||||||
|
.saved-filter-pill.active {
|
||||||
|
background: var(--accent-bg, rgba(99,102,241,0.12));
|
||||||
|
color: var(--accent);
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
.saved-search-vault {
|
.saved-search-vault {
|
||||||
font-size: 0.65rem;
|
font-size: 0.65rem;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
|
|||||||
Reference in New Issue
Block a user