diff --git a/archivebox/core/admin_snapshots.py b/archivebox/core/admin_snapshots.py index 55ecddbf..816535bb 100644 --- a/archivebox/core/admin_snapshots.py +++ b/archivebox/core/admin_snapshots.py @@ -534,9 +534,13 @@ class SnapshotAdmin(SearchResultsAdminMixin, ConfigEditorMixin, BaseModelAdmin): messages.warning(request, "No tags specified.") return - # Parse comma-separated tag names and find matching Tag objects + # Parse comma-separated tag names and find matching Tag objects (case-insensitive) tag_names = [name.strip() for name in tags_str.split(',') if name.strip()] - tags = list(Tag.objects.filter(name__in=tag_names)) + tags = [] + for name in tag_names: + tag = Tag.objects.filter(name__iexact=name).first() + if tag: + tags.append(tag) print('[-] Removing tags', [t.name for t in tags], 'from Snapshots', queryset) for obj in queryset: diff --git a/archivebox/core/widgets.py b/archivebox/core/widgets.py index 124e6728..433f5c93 100644 --- a/archivebox/core/widgets.py +++ b/archivebox/core/widgets.py @@ -75,7 +75,7 @@ class TagEditorWidget(forms.Widget): pills_html += f''' {self._escape(tag)} - + ''' @@ -151,7 +151,7 @@ class TagEditorWidget(forms.Widget): }}); }}; - window.removeTag_{widget_id} = function(btn, tagName) {{ + window.removeTag_{widget_id} = function(tagName) {{ currentTags_{widget_id} = currentTags_{widget_id}.filter(function(t) {{ return t.toLowerCase() !== tagName.toLowerCase(); }}); @@ -166,13 +166,31 @@ class TagEditorWidget(forms.Widget): var pill = document.createElement('span'); pill.className = 'tag-pill'; pill.setAttribute('data-tag', tag); - pill.innerHTML = escapeHtml(tag) + - ''; + + var tagText = document.createTextNode(tag); + pill.appendChild(tagText); + + var removeBtn = document.createElement('button'); + removeBtn.type = 'button'; + removeBtn.className = 'tag-remove-btn'; + removeBtn.setAttribute('data-tag-name', tag); + removeBtn.innerHTML = '×'; + pill.appendChild(removeBtn); + container.appendChild(pill); }}); }}; + // Add event delegation for remove buttons + document.getElementById('{widget_id}_pills').addEventListener('click', function(event) {{ + if (event.target.classList.contains('tag-remove-btn')) {{ + var tagName = event.target.getAttribute('data-tag-name'); + if (tagName) {{ + removeTag_{widget_id}(tagName); + }} + }} + }}); + window.handleTagKeydown_{widget_id} = function(event) {{ var input = event.target; var value = input.value.trim(); @@ -285,7 +303,7 @@ class InlineTagEditorWidget(TagEditorWidget): pills_html += f''' {self._escape(td['name'])} - + ''' @@ -362,10 +380,7 @@ class InlineTagEditorWidget(TagEditorWidget): document.getElementById('{widget_id}_input').value = ''; }}; - window.removeInlineTag_{widget_id} = function(event, tagId, tagName) {{ - event.stopPropagation(); - event.preventDefault(); - + window.removeInlineTag_{widget_id} = function(tagId) {{ fetch('/api/v1/core/tags/remove-from-snapshot/', {{ method: 'POST', headers: {{ @@ -399,14 +414,37 @@ class InlineTagEditorWidget(TagEditorWidget): pill.className = 'tag-pill'; pill.setAttribute('data-tag', td.name); pill.setAttribute('data-tag-id', td.id); - pill.innerHTML = '' + - escapeHtml(td.name) + '' + - ''; + + var link = document.createElement('a'); + link.href = '/admin/core/snapshot/?tags__id__exact=' + td.id; + link.className = 'tag-link'; + link.textContent = td.name; + pill.appendChild(link); + + var removeBtn = document.createElement('button'); + removeBtn.type = 'button'; + removeBtn.className = 'tag-remove-btn'; + removeBtn.setAttribute('data-tag-id', td.id); + removeBtn.setAttribute('data-tag-name', td.name); + removeBtn.innerHTML = '×'; + pill.appendChild(removeBtn); + container.appendChild(pill); }}); }}; + // Add event delegation for remove buttons + document.getElementById('{widget_id}_pills').addEventListener('click', function(event) {{ + if (event.target.classList.contains('tag-remove-btn')) {{ + event.stopPropagation(); + event.preventDefault(); + var tagId = parseInt(event.target.getAttribute('data-tag-id'), 10); + if (tagId) {{ + removeInlineTag_{widget_id}(tagId); + }} + }} + }}); + window.handleInlineTagKeydown_{widget_id} = function(event) {{ event.stopPropagation(); var input = event.target;