feat: ajouter boutons de suppression de tags interactifs avec pills redesignés (border-radius 999px), système de filtrage des tags techniques (note, shaarli-pin, note-color-, notefilter-, notebg-), fonction removeTagFromEntity pour suppression via API, synchronisation bidirectionnelle entre cartes et modale, et amélioration du style avec flexbox, gaps optimisés, et support complet thème clair/sombre
This commit is contained in:
parent
5631c8935b
commit
6f58f6cd67
@ -457,29 +457,53 @@ body.view-notes .content-container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.note-modal-tags .note-tag {
|
.note-modal-tags .note-tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
background: rgba(0, 0, 0, 0.06);
|
background: rgba(0, 0, 0, 0.06);
|
||||||
border: 1px solid rgba(0, 0, 0, 0.14);
|
border: 1px solid rgba(0, 0, 0, 0.14);
|
||||||
color: inherit;
|
color: inherit;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
padding: 4px 10px;
|
padding: 4px 8px;
|
||||||
font-size: 0.72rem;
|
font-size: 0.72rem;
|
||||||
letter-spacing: 0.02em;
|
letter-spacing: 0.02em;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .note-modal-tags .note-tag {
|
.note-modal-tags .note-tag-text {
|
||||||
background: rgba(255, 255, 255, 0.12);
|
line-height: 1.2;
|
||||||
border-color: rgba(255, 255, 255, 0.22);
|
}
|
||||||
|
|
||||||
|
.note-modal-tags .note-tag-remove-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(0, 0, 0, 0.12);
|
||||||
|
color: currentColor;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .note-modal-tags .note-tag-remove-btn {
|
||||||
|
background: rgba(255, 255, 255, 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-modal-actions {
|
.note-modal-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 10px;
|
gap: 6px;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border-top: 1px solid rgba(0, 0, 0, 0.12);
|
border-top: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
background: rgba(0, 0, 0, 0.03);
|
background: rgba(0, 0, 0, 0.03);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .note-modal-actions {
|
[data-theme="dark"] .note-modal-actions {
|
||||||
@ -574,17 +598,13 @@ body.view-notes .content-container {
|
|||||||
border: 1px solid #e0e0e0;
|
border: 1px solid #e0e0e0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
/* spacing for masonry */
|
|
||||||
break-inside: avoid;
|
break-inside: avoid;
|
||||||
/* Prevent split */
|
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: box-shadow 0.2s, transform 0.2s, background-color 0.2s;
|
transition: box-shadow 0.2s, transform 0.2s, background-color 0.2s;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
/* allow palette popup to escape card bounds */
|
|
||||||
color: var(--note-card-fg, #202124);
|
color: var(--note-card-fg, #202124);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dark Mode Card */
|
|
||||||
[data-theme="dark"] .note-card {
|
[data-theme="dark"] .note-card {
|
||||||
background-color: #202124;
|
background-color: #202124;
|
||||||
border: 1px solid #5f6368;
|
border: 1px solid #5f6368;
|
||||||
@ -597,10 +617,14 @@ body.view-notes .content-container {
|
|||||||
|
|
||||||
[data-theme="dark"] .note-card:hover {
|
[data-theme="dark"] .note-card:hover {
|
||||||
background-color: #202124;
|
background-color: #202124;
|
||||||
/* Keep lightens on hover? usually same but controls appear */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cover Image */
|
/* Cover Image */
|
||||||
|
.note-cover {
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
.note-cover img {
|
.note-cover img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
@ -608,11 +632,6 @@ body.view-notes .content-container {
|
|||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-cover {
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: 8px 8px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Inner Content */
|
/* Inner Content */
|
||||||
.note-inner {
|
.note-inner {
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
@ -640,14 +659,12 @@ body.view-notes .content-container {
|
|||||||
line-height: 1.25rem;
|
line-height: 1.25rem;
|
||||||
color: var(--text-color, #202124);
|
color: var(--text-color, #202124);
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
/* Limit to ~12 lines */
|
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 12;
|
-webkit-line-clamp: 12;
|
||||||
line-clamp: 12;
|
line-clamp: 12;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
/* Fallback */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .note-body {
|
[data-theme="dark"] .note-body {
|
||||||
@ -663,9 +680,12 @@ body.view-notes .content-container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.note-tag {
|
.note-tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
background: rgba(0, 0, 0, 0.06);
|
background: rgba(0, 0, 0, 0.06);
|
||||||
padding: 2px 6px;
|
padding: 2px 8px;
|
||||||
border-radius: 4px;
|
border-radius: 999px;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
color: var(--text-light);
|
color: var(--text-light);
|
||||||
}
|
}
|
||||||
@ -675,6 +695,31 @@ body.view-notes .content-container {
|
|||||||
color: #9aa0a6;
|
color: #9aa0a6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.note-tag-text {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-tag-remove-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(0, 0, 0, 0.12);
|
||||||
|
color: currentColor;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .note-tag-remove-btn {
|
||||||
|
background: rgba(255, 255, 255, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
/* Hover Actions */
|
/* Hover Actions */
|
||||||
.note-hover-actions {
|
.note-hover-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -1359,22 +1359,64 @@ input:checked+.theme-slider:before {
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-tag a {
|
.link-tag {
|
||||||
display: inline-block;
|
display: inline-flex;
|
||||||
padding: 0.25rem 0.625rem;
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
background: var(--tag-bg);
|
background: var(--tag-bg);
|
||||||
color: var(--tag-text);
|
color: var(--tag-text);
|
||||||
border-radius: 0.375rem;
|
border-radius: 999px;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
transition: all 0.15s ease;
|
transition: all 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-tag a:hover {
|
.link-tag.is-tech-tag {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-tag .link-tag-link {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-tag:hover {
|
||||||
background: var(--primary);
|
background: var(--primary);
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link-tag:hover .link-tag-link {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-tag .tag-remove-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(0, 0, 0, 0.12);
|
||||||
|
color: currentColor;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .link-tag .tag-remove-btn {
|
||||||
|
background: rgba(255, 255, 255, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-tag:hover .tag-remove-btn {
|
||||||
|
background: rgba(255, 255, 255, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
.view-grid .link-tag-list {
|
.view-grid .link-tag-list {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|||||||
@ -22,7 +22,18 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
if (searchTags === "todo") {
|
if (searchTags === "todo") {
|
||||||
initTodoView(linkList, container);
|
initTodoView(linkList, container);
|
||||||
} else if (searchTags === "note") {
|
} else if (searchTags === "note") {
|
||||||
|
// Pour la vue notes, parser les notes AVANT de supprimer les tags techniques
|
||||||
|
// afin que les propriétés visuelles (couleur, fond, etc.) soient correctement extraites
|
||||||
initNoteView(linkList, container);
|
initNoteView(linkList, container);
|
||||||
|
// Puis supprimer les tags techniques de l'affichage
|
||||||
|
if (typeof initTagDisplayAndRemoval === "function") {
|
||||||
|
initTagDisplayAndRemoval();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Vue standard : supprimer les tags techniques
|
||||||
|
if (typeof initTagDisplayAndRemoval === "function") {
|
||||||
|
initTagDisplayAndRemoval();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -151,6 +162,191 @@ const NOTE_COLOR_TAG_PREFIX = "note-color-";
|
|||||||
const NOTE_FILTER_TAG_PREFIX = "notefilter-";
|
const NOTE_FILTER_TAG_PREFIX = "notefilter-";
|
||||||
const NOTE_BACKGROUND_TAG_PREFIX = "notebg-";
|
const NOTE_BACKGROUND_TAG_PREFIX = "notebg-";
|
||||||
|
|
||||||
|
function isTechnicalTag(tag) {
|
||||||
|
if (typeof tag !== "string") return false;
|
||||||
|
const t = tag.trim();
|
||||||
|
if (!t) return false;
|
||||||
|
|
||||||
|
if (t === "note") return true;
|
||||||
|
if (t === "shaarli-pin") return true;
|
||||||
|
if (t.startsWith(NOTE_FONT_COLOR_TAG_PREFIX)) return true;
|
||||||
|
if (t.startsWith(NOTE_COLOR_TAG_PREFIX)) return true;
|
||||||
|
if (t.startsWith(NOTE_FILTER_TAG_PREFIX)) return true;
|
||||||
|
if (t.startsWith(NOTE_BACKGROUND_TAG_PREFIX)) return true;
|
||||||
|
if (t.startsWith("notefilter-")) return true;
|
||||||
|
if (t.startsWith("notebg-")) return true;
|
||||||
|
if (t.startsWith("note-color-")) return true;
|
||||||
|
|
||||||
|
// Legacy note color tags: note-<color>
|
||||||
|
if (t.startsWith("note-")) {
|
||||||
|
const candidate = t.substring(5);
|
||||||
|
if (NOTE_COLOR_OPTIONS.some((opt) => opt.key === candidate)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTagPill({ tag, onRemoveClass = "tag-remove-btn", tagClass = "tag-pill" }) {
|
||||||
|
const wrapper = document.createElement("span");
|
||||||
|
wrapper.className = tagClass;
|
||||||
|
wrapper.dataset.tag = tag;
|
||||||
|
|
||||||
|
const text = document.createElement("span");
|
||||||
|
text.className = `${tagClass}-text`;
|
||||||
|
text.textContent = tag;
|
||||||
|
wrapper.appendChild(text);
|
||||||
|
|
||||||
|
const canRemove = arguments[0] && Object.prototype.hasOwnProperty.call(arguments[0], "canRemove") ? !!arguments[0].canRemove : true;
|
||||||
|
if (!canRemove) return wrapper;
|
||||||
|
|
||||||
|
const btn = document.createElement("button");
|
||||||
|
btn.type = "button";
|
||||||
|
btn.className = onRemoveClass;
|
||||||
|
btn.dataset.tag = tag;
|
||||||
|
btn.setAttribute("aria-label", `Supprimer le tag ${tag}`);
|
||||||
|
btn.title = "Supprimer";
|
||||||
|
btn.innerHTML = "×";
|
||||||
|
wrapper.appendChild(btn);
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeTagFromEntity(editUrl, tag) {
|
||||||
|
return fetch(editUrl)
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((html) => {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const doc = parser.parseFromString(html, "text/html");
|
||||||
|
const form = doc.querySelector('form[name="linkform"]');
|
||||||
|
if (!form) throw new Error("Could not find edit form");
|
||||||
|
|
||||||
|
const formData = new URLSearchParams();
|
||||||
|
const inputs = form.querySelectorAll("input, textarea");
|
||||||
|
inputs.forEach((input) => {
|
||||||
|
if (input.type === "checkbox") {
|
||||||
|
if (input.checked) formData.append(input.name, input.value || "on");
|
||||||
|
} else if (input.name) {
|
||||||
|
formData.append(input.name, input.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let currentTags = formData.get("lf_tags") || "";
|
||||||
|
let tagsArray = currentTags.split(/[\s,]+/).filter((t) => t.trim() !== "");
|
||||||
|
tagsArray = tagsArray.filter((t) => t !== tag);
|
||||||
|
|
||||||
|
formData.set("lf_tags", tagsArray.join(" "));
|
||||||
|
formData.append("save_edit", "1");
|
||||||
|
|
||||||
|
return fetch(form.action, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
body: formData.toString(),
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (!response.ok) throw new Error("Failed to update tags");
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let tagDisplayRemovalInitialized = false;
|
||||||
|
function initTagDisplayAndRemoval() {
|
||||||
|
if (tagDisplayRemovalInitialized) return;
|
||||||
|
|
||||||
|
// Filter technical tags on bookmarks list (standard view).
|
||||||
|
// Keep shaarli-pin in DOM (hidden) so initPinnedItems can still detect it.
|
||||||
|
document.querySelectorAll(".link-tag-list .link-tag").forEach((el) => {
|
||||||
|
const tag = (el.dataset.tag || el.textContent || "").trim();
|
||||||
|
if (!tag) return;
|
||||||
|
if (tag === "shaarli-pin") {
|
||||||
|
el.classList.add("is-tech-tag");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isTechnicalTag(tag)) {
|
||||||
|
el.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delegate remove button clicks (bookmarks + notes + modal)
|
||||||
|
document.addEventListener("click", function (e) {
|
||||||
|
const btn = e.target.closest(".tag-remove-btn, .note-tag-remove-btn");
|
||||||
|
if (!btn) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const tag = (btn.dataset.tag || "").trim();
|
||||||
|
if (!tag) return;
|
||||||
|
|
||||||
|
const tagEl = btn.closest(".link-tag, .note-tag");
|
||||||
|
const card = btn.closest(".link-outer, .note-card, .note-modal");
|
||||||
|
|
||||||
|
let editUrl = "";
|
||||||
|
if (card && card.classList.contains("note-card")) {
|
||||||
|
editUrl = card.dataset.editUrl || "";
|
||||||
|
} else if (card && card.classList.contains("note-modal")) {
|
||||||
|
editUrl = card.dataset.editUrl || "";
|
||||||
|
} else {
|
||||||
|
const actionsEl = card ? card.querySelector(".link-actions") : null;
|
||||||
|
const editLink = actionsEl ? actionsEl.querySelector('a[href*="admin/shaare"]') : null;
|
||||||
|
editUrl = editLink ? editLink.href : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!editUrl) return;
|
||||||
|
|
||||||
|
removeTagFromEntity(editUrl, tag)
|
||||||
|
.then(() => {
|
||||||
|
if (tagEl) tagEl.remove();
|
||||||
|
|
||||||
|
// Sync note datasets + modal tag list if applicable
|
||||||
|
if (card && card.classList.contains("note-card")) {
|
||||||
|
let tags = (card.dataset.tags || "").split("||").filter((t) => t);
|
||||||
|
tags = tags.filter((t) => t !== tag);
|
||||||
|
card.dataset.tags = tags.join("||");
|
||||||
|
|
||||||
|
const modal = document.querySelector(".note-modal-overlay");
|
||||||
|
if (modal && modal.currentNote && String(modal.currentNote.id) === String(card.dataset.id)) {
|
||||||
|
modal.currentNote.tags = (modal.currentNote.tags || []).filter((t) => t !== tag);
|
||||||
|
const tagsContainer = modal.querySelector("#note-modal-tags");
|
||||||
|
renderModalTags(tagsContainer, modal.currentNote.tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card && card.classList.contains("note-modal")) {
|
||||||
|
let tags = (card.dataset.tags || "").split("||").filter((t) => t);
|
||||||
|
tags = tags.filter((t) => t !== tag);
|
||||||
|
card.dataset.tags = tags.join("||");
|
||||||
|
|
||||||
|
const modal = document.querySelector(".note-modal-overlay");
|
||||||
|
if (modal && modal.currentNote) {
|
||||||
|
modal.currentNote.tags = (modal.currentNote.tags || []).filter((t) => t !== tag);
|
||||||
|
const tagsContainer = modal.querySelector("#note-modal-tags");
|
||||||
|
renderModalTags(tagsContainer, modal.currentNote.tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also update corresponding card if visible
|
||||||
|
const noteId = card.dataset.noteId;
|
||||||
|
const noteCard = noteId ? document.querySelector(`.note-card[data-id="${noteId}"]`) : null;
|
||||||
|
if (noteCard) {
|
||||||
|
const pill = noteCard.querySelector(`.note-tag[data-tag="${CSS.escape(tag)}"]`);
|
||||||
|
if (pill) pill.remove();
|
||||||
|
let noteTags = (noteCard.dataset.tags || "").split("||").filter((t) => t);
|
||||||
|
noteTags = noteTags.filter((t) => t !== tag);
|
||||||
|
noteCard.dataset.tags = noteTags.join("||");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("Error removing tag:", err);
|
||||||
|
alert("Erreur lors de la suppression du tag.");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tagDisplayRemovalInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
function resolveThemeAssetBasePath() {
|
function resolveThemeAssetBasePath() {
|
||||||
const cssLink = Array.from(document.querySelectorAll('link[rel="stylesheet"]')).find(
|
const cssLink = Array.from(document.querySelectorAll('link[rel="stylesheet"]')).find(
|
||||||
(link) => link.href && link.href.includes("/custom_views.css"),
|
(link) => link.href && link.href.includes("/custom_views.css"),
|
||||||
@ -1810,6 +2006,8 @@ function renderNotes(container, notes, viewMode) {
|
|||||||
const card = document.createElement("div");
|
const card = document.createElement("div");
|
||||||
card.className = "note-card";
|
card.className = "note-card";
|
||||||
card.dataset.id = note.id;
|
card.dataset.id = note.id;
|
||||||
|
card.dataset.editUrl = note.editUrl || "";
|
||||||
|
card.dataset.tags = (note.tags || []).filter((t) => t).join("||");
|
||||||
applyNoteVisualState(card, note);
|
applyNoteVisualState(card, note);
|
||||||
if (viewMode === "list") card.classList.add("list-mode");
|
if (viewMode === "list") card.classList.add("list-mode");
|
||||||
|
|
||||||
@ -1857,12 +2055,9 @@ function renderNotes(container, notes, viewMode) {
|
|||||||
const tagContainer = document.createElement("div");
|
const tagContainer = document.createElement("div");
|
||||||
tagContainer.className = "note-tags";
|
tagContainer.className = "note-tags";
|
||||||
note.tags.forEach((t) => {
|
note.tags.forEach((t) => {
|
||||||
if (t !== "note") {
|
if (isTechnicalTag(t)) return;
|
||||||
const span = document.createElement("span");
|
const pill = createTagPill({ tag: t, onRemoveClass: "note-tag-remove-btn", tagClass: "note-tag", canRemove: !!note.editUrl && note.editUrl !== "#" });
|
||||||
span.className = "note-tag";
|
tagContainer.appendChild(pill);
|
||||||
span.textContent = t;
|
|
||||||
tagContainer.appendChild(span);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
inner.appendChild(tagContainer);
|
inner.appendChild(tagContainer);
|
||||||
}
|
}
|
||||||
@ -1929,7 +2124,10 @@ function renderModalTags(container, tags) {
|
|||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
container.innerHTML = "";
|
container.innerHTML = "";
|
||||||
const visibleTags = (tags || []).filter((tag) => tag && tag !== "note");
|
const visibleTags = (tags || []).filter((tag) => tag && !isTechnicalTag(tag));
|
||||||
|
|
||||||
|
const modal = document.querySelector(".note-modal-overlay");
|
||||||
|
const canRemove = !!(modal && modal.currentNote && modal.currentNote.editUrl && modal.currentNote.editUrl !== "#");
|
||||||
|
|
||||||
if (visibleTags.length === 0) {
|
if (visibleTags.length === 0) {
|
||||||
container.classList.add("is-empty");
|
container.classList.add("is-empty");
|
||||||
@ -1938,10 +2136,8 @@ function renderModalTags(container, tags) {
|
|||||||
|
|
||||||
container.classList.remove("is-empty");
|
container.classList.remove("is-empty");
|
||||||
visibleTags.forEach((tag) => {
|
visibleTags.forEach((tag) => {
|
||||||
const tagEl = document.createElement("span");
|
const pill = createTagPill({ tag, onRemoveClass: "note-tag-remove-btn", tagClass: "note-tag", canRemove });
|
||||||
tagEl.className = "note-tag";
|
container.appendChild(pill);
|
||||||
tagEl.textContent = tag;
|
|
||||||
container.appendChild(tagEl);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1966,7 +2162,7 @@ function openNoteModal(note) {
|
|||||||
modalCard.dataset.deleteUrl = note.deleteUrl || "";
|
modalCard.dataset.deleteUrl = note.deleteUrl || "";
|
||||||
modalCard.dataset.background = note.background || "none";
|
modalCard.dataset.background = note.background || "none";
|
||||||
|
|
||||||
const visibleTags = (note.tags || []).filter((tag) => tag && tag !== "note");
|
const visibleTags = (note.tags || []).filter((tag) => tag && !isTechnicalTag(tag));
|
||||||
modalCard.dataset.tags = visibleTags.join("||");
|
modalCard.dataset.tags = visibleTags.join("||");
|
||||||
|
|
||||||
title.textContent = note.title || "Sans titre";
|
title.textContent = note.title || "Sans titre";
|
||||||
|
|||||||
@ -85,8 +85,8 @@
|
|||||||
{if="$value.description"}<div class="link-description">{$value.description}</div>{/if}
|
{if="$value.description"}<div class="link-description">{$value.description}</div>{/if}
|
||||||
<div class="link-footer">
|
<div class="link-footer">
|
||||||
<div class="link-tag-list">
|
<div class="link-tag-list">
|
||||||
{loop="$value.taglist"}<span class="link-tag"><a
|
{loop="$value.taglist"}<span class="link-tag" data-tag="{$value}"><a
|
||||||
href="{$base_path}/add-tag/{$value|urlencode}">{$value}</a></span>{/loop}
|
class="link-tag-link" href="{$base_path}/add-tag/{$value|urlencode}">{$value}</a>{if="$is_logged_in"}<button type="button" class="tag-remove-btn" data-tag="{$value}" aria-label="Supprimer le tag {$value}" title="Supprimer">×</button>{/if}</span>{/loop}
|
||||||
</div>
|
</div>
|
||||||
<div class="link-actions">
|
<div class="link-actions">
|
||||||
{if="$is_logged_in"}
|
{if="$is_logged_in"}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user