diff --git a/README.md b/README.md
index 798c356..537da1c 100644
--- a/README.md
+++ b/README.md
@@ -11,9 +11,10 @@ The name comes from:
**Feature Overview:**
- Tags for organizing bookmarks
- Search by text or tags
+- Bulk editing
+- Bookmark archive
- Automatically provides titles and descriptions from linked websites
- Import and export bookmarks in Netscape HTML format
-- Bookmark archive
- Extensions for [Firefox](https://addons.mozilla.org/de/firefox/addon/linkding-extension/) and [Chrome](https://chrome.google.com/webstore/detail/linkding-extension/beakmhbijpdhipnjhnclmhgjlddhidpe)
- Bookmarklet that should work in most browsers
- Dark mode
@@ -22,7 +23,7 @@ The name comes from:
- Works without Javascript
- ...but has several UI enhancements when Javascript is enabled
- REST API for developing 3rd party apps
-- Admin panel for user self-service and bulk operations
+- Admin panel for user self-service and raw data access
**Demo:** https://demo.linkding.link/ (configured with open registration)
diff --git a/bookmarks/components/TagAutocomplete.svelte b/bookmarks/components/TagAutocomplete.svelte
index 1ef81aa..5f85e63 100644
--- a/bookmarks/components/TagAutocomplete.svelte
+++ b/bookmarks/components/TagAutocomplete.svelte
@@ -4,8 +4,10 @@
export let id;
export let name;
export let value;
- export let tags;
+ export let apiClient;
+ export let variant = 'default';
+ let tags = [];
let isFocus = false;
let isOpen = false;
let input = null;
@@ -13,6 +15,18 @@
let suggestions = [];
let selectedIndex = 0;
+ init();
+
+ async function init() {
+ // For now we cache all tags on load as the template did before
+ try {
+ tags = await apiClient.getTags({limit: 1000, offset: 0});
+ tags.sort((left, right) => left.name.toLowerCase().localeCompare(right.name.toLowerCase()))
+ } catch (e) {
+ console.warn('TagAutocomplete: Error loading tag list');
+ }
+ }
+
function handleFocus() {
isFocus = true;
}
@@ -27,7 +41,9 @@
const word = getCurrentWord(input);
- suggestions = word ? tags.filter(tag => tag.indexOf(word) === 0) : [];
+ suggestions = word
+ ? tags.filter(tag => tag.name.toLowerCase().indexOf(word.toLowerCase()) === 0)
+ : [];
if (word && suggestions.length > 0) {
open();
@@ -70,7 +86,7 @@
function complete(suggestion) {
const bounds = getCurrentWordBounds(input);
const value = input.value;
- input.value = value.substring(0, bounds.start) + suggestion + value.substring(bounds.end);
+ input.value = value.substring(0, bounds.start) + suggestion.name + value.substring(bounds.end);
close();
}
@@ -87,11 +103,11 @@
}
-
{% if bookmark.tag_names %}
- {% for tag_name in bookmark.tag_names %}
- {{ tag_name|hash_tag }}
- {% endfor %}
-
+ {% for tag_name in bookmark.tag_names %}
+ {{ tag_name|hash_tag }}
+ {% endfor %}
+
{% endif %}
{% if bookmark.tag_names and bookmark.resolved_description %} | {% endif %}
@@ -32,7 +36,7 @@
class="btn btn-link btn-sm">Archive
{% endif %}
Remove
+ class="btn btn-link btn-sm btn-confirmation">Remove
{% endfor %}
@@ -40,39 +44,4 @@
{% pagination bookmarks %}
-
-
-{# Enhance delete links to show inline confirmation #}
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/bookmarks/templates/bookmarks/bulk_edit/bar.html b/bookmarks/templates/bookmarks/bulk_edit/bar.html
new file mode 100644
index 0000000..bc473fe
--- /dev/null
+++ b/bookmarks/templates/bookmarks/bulk_edit/bar.html
@@ -0,0 +1,31 @@
+