Add file deletion endpoint with multi-tag filtering support and redesigned editor UI with icon-only buttons

This commit is contained in:
2026-03-21 22:42:55 -04:00
parent eba5af2fe0
commit b73aa19c51
5 changed files with 196 additions and 113 deletions
+84 -34
View File
@@ -429,47 +429,70 @@
function addTagFilter(tag) {
if (!selectedTags.includes(tag)) {
selectedTags.push(tag);
renderActiveTags();
performTagSearch();
}
}
function removeTagFilter(tag) {
selectedTags = selectedTags.filter(t => t !== tag);
renderActiveTags();
if (selectedTags.length > 0) {
performTagSearch();
} else {
const input = document.getElementById("search-input");
if (!input.value.trim()) {
if (input.value.trim()) {
performSearch(input.value.trim(), document.getElementById("vault-filter").value, null);
} else {
showWelcome();
}
}
}
function renderActiveTags() {
const container = document.getElementById("active-tags");
if (!container) return;
container.innerHTML = "";
selectedTags.forEach(tag => {
const tagEl = el("div", { class: "active-tag" }, [
document.createTextNode(`#${tag}`),
el("span", { class: "remove-icon" }, [icon("x", 14)])
]);
tagEl.addEventListener("click", () => removeTagFilter(tag));
container.appendChild(tagEl);
});
safeCreateIcons();
}
function performTagSearch() {
const input = document.getElementById("search-input");
const query = input.value.trim();
const vault = document.getElementById("vault-filter").value;
performSearch(query, vault, selectedTags.join(","));
performSearch(query, vault, selectedTags.length > 0 ? selectedTags.join(",") : null);
}
function buildSearchResultsHeader(data, query, tagFilter) {
const header = el("div", { class: "search-results-header" });
const summaryText = el("span", { class: "search-results-summary-text" });
if (query && tagFilter) {
summaryText.textContent = `${data.count} résultat(s) pour "${query}" avec les tags`;
} else if (query) {
summaryText.textContent = `${data.count} résultat(s) pour "${query}"`;
} else if (tagFilter) {
summaryText.textContent = `${data.count} fichier(s) avec les tags`;
} else {
summaryText.textContent = `${data.count} résultat(s)`;
}
header.appendChild(summaryText);
if (selectedTags.length > 0) {
const activeTags = el("div", { class: "search-results-active-tags" });
selectedTags.forEach((tag) => {
const removeBtn = el("button", {
class: "search-results-active-tag-remove",
title: `Retirer ${tag} du filtre`,
"aria-label": `Retirer ${tag} du filtre`
}, [document.createTextNode("×")]);
removeBtn.addEventListener("click", (e) => {
e.stopPropagation();
removeTagFilter(tag);
});
const chip = el("span", { class: "search-results-active-tag" }, [
document.createTextNode(`#${tag}`),
removeBtn,
]);
activeTags.appendChild(chip);
});
header.appendChild(activeTags);
}
return header;
}
function searchByTag(tag) {
@@ -679,16 +702,7 @@
const area = document.getElementById("content-area");
area.innerHTML = "";
const header = el("div", { class: "search-results-header" });
if (query && tagFilter) {
const tags = tagFilter.split(',').map(t => `#${t}`).join(', ');
header.textContent = `${data.count} résultat(s) pour "${query}" avec les tags ${tags}`;
} else if (query) {
header.textContent = `${data.count} résultat(s) pour "${query}"`;
} else if (tagFilter) {
const tags = tagFilter.split(',').map(t => `#${t}`).join(', ');
header.textContent = `${data.count} fichier(s) avec les tags ${tags}`;
}
const header = buildSearchResultsHeader(data, query, tagFilter);
area.appendChild(header);
if (data.results.length === 0) {
@@ -982,7 +996,7 @@
try {
saveBtn.disabled = true;
saveBtn.innerHTML = '<i data-lucide="loader" style="width:14px;height:14px"></i><span class="editor-btn-text">Sauvegarde...</span>';
saveBtn.innerHTML = '<i data-lucide="loader" style="width:16px;height:16px"></i>';
safeCreateIcons();
const response = await fetch(
@@ -999,7 +1013,7 @@
throw new Error(error.detail || "Erreur de sauvegarde");
}
saveBtn.innerHTML = '<i data-lucide="check" style="width:14px;height:14px"></i><span class="editor-btn-text">Sauvegardé !</span>';
saveBtn.innerHTML = '<i data-lucide="check" style="width:16px;height:16px"></i>';
safeCreateIcons();
setTimeout(() => {
@@ -1017,12 +1031,48 @@
}
}
async function deleteFile() {
if (!editorVault || !editorPath) return;
const deleteBtn = document.getElementById("editor-delete");
const originalHTML = deleteBtn.innerHTML;
try {
deleteBtn.disabled = true;
deleteBtn.innerHTML = '<i data-lucide="loader" style="width:16px;height:16px"></i>';
safeCreateIcons();
const response = await fetch(
`/api/file/${encodeURIComponent(editorVault)}?path=${encodeURIComponent(editorPath)}`,
{ method: "DELETE" }
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || "Erreur de suppression");
}
closeEditor();
showWelcome();
await refreshSidebarForContext();
await refreshTagsForContext();
} catch (err) {
console.error("Delete error:", err);
alert(`Erreur: ${err.message}`);
deleteBtn.innerHTML = originalHTML;
deleteBtn.disabled = false;
safeCreateIcons();
}
}
function initEditor() {
const cancelBtn = document.getElementById("editor-cancel");
const deleteBtn = document.getElementById("editor-delete");
const saveBtn = document.getElementById("editor-save");
const modal = document.getElementById("editor-modal");
cancelBtn.addEventListener("click", closeEditor);
deleteBtn.addEventListener("click", deleteFile);
saveBtn.addEventListener("click", saveFile);
// Close on overlay click