Add file deletion endpoint with multi-tag filtering support and redesigned editor UI with icon-only buttons
This commit is contained in:
+84
-34
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user