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;