Allow bulk editing unread and shared state of bookmarks (#517)

* Move bulk actions into select

* Update tests

* Implement bulk read / unread actions

* Implement bulk share/unshare actions

* Show correct archiving actions

* Allow selecting bookmarks across pages

* Dynamically update select across checkbox

* Filter available bulk actions

* Refactor tag autocomplete toggling
This commit is contained in:
Sascha Ißbrücker
2023-08-25 13:54:23 +02:00
committed by GitHub
parent 2ceac9a87d
commit e2e5930985
25 changed files with 1019 additions and 124 deletions

View File

@@ -36,8 +36,18 @@ class BookmarkPage {
swap(this.bookmarkList, bookmarkListHtml);
swap(this.tagCloud, tagCloudHtml);
// Dispatch list updated event
const listElement = this.bookmarkList.querySelector(
"ul[data-bookmarks-total]",
);
const bookmarksTotal =
(listElement && listElement.dataset.bookmarksTotal) || 0;
this.bookmarkList.dispatchEvent(
new CustomEvent("bookmark-list-updated", { bubbles: true }),
new CustomEvent("bookmark-list-updated", {
bubbles: true,
detail: { bookmarksTotal },
}),
);
});
}

View File

@@ -4,6 +4,9 @@ class BulkEdit {
constructor(element) {
this.element = element;
this.active = false;
this.actionSelect = element.querySelector("select[name='bulk_action']");
this.tagAutoComplete = element.querySelector(".tag-autocomplete");
this.selectAcross = element.querySelector("label.select-across");
element.addEventListener(
"bulk-edit-toggle-active",
@@ -21,6 +24,11 @@ class BulkEdit {
"bookmark-list-updated",
this.onListUpdated.bind(this),
);
this.actionSelect.addEventListener(
"change",
this.onActionSelected.bind(this),
);
}
get allCheckbox() {
@@ -48,23 +56,56 @@ class BulkEdit {
}
onToggleBookmark() {
this.allCheckbox.checked = this.bookmarkCheckboxes.every((checkbox) => {
const allChecked = this.bookmarkCheckboxes.every((checkbox) => {
return checkbox.checked;
});
this.allCheckbox.checked = allChecked;
this.updateSelectAcross(allChecked);
}
onToggleAll() {
const checked = this.allCheckbox.checked;
const allChecked = this.allCheckbox.checked;
this.bookmarkCheckboxes.forEach((checkbox) => {
checkbox.checked = checked;
checkbox.checked = allChecked;
});
this.updateSelectAcross(allChecked);
}
onListUpdated() {
onActionSelected() {
const action = this.actionSelect.value;
if (action === "bulk_tag" || action === "bulk_untag") {
this.tagAutoComplete.classList.remove("d-none");
} else {
this.tagAutoComplete.classList.add("d-none");
}
}
onListUpdated(event) {
// Reset checkbox states
this.reset();
// Update total number of bookmarks
const total = event.detail.bookmarksTotal;
const totalSpan = this.selectAcross.querySelector("span.total");
totalSpan.textContent = total;
}
updateSelectAcross(allChecked) {
if (allChecked) {
this.selectAcross.classList.remove("d-none");
} else {
this.selectAcross.classList.add("d-none");
this.selectAcross.querySelector("input").checked = false;
}
}
reset() {
this.allCheckbox.checked = false;
this.bookmarkCheckboxes.forEach((checkbox) => {
checkbox.checked = false;
});
this.updateSelectAcross(false);
}
}

View File

@@ -14,12 +14,13 @@ class TagAutocomplete {
id: element.id,
name: element.name,
value: element.value,
placeholder: element.getAttribute("placeholder") || "",
apiClient: apiClient,
variant: element.getAttribute("variant"),
},
});
element.replaceWith(wrapper);
element.replaceWith(wrapper.firstElementChild);
}
}

View File

@@ -4,6 +4,7 @@
export let id;
export let name;
export let value;
export let placeholder;
export let apiClient;
export let variant = 'default';
@@ -118,7 +119,7 @@
<!-- autocomplete input container -->
<div class="form-autocomplete-input form-input" class:is-focused={isFocus}>
<!-- autocomplete real input box -->
<input id="{id}" name="{name}" value="{value ||''}" placeholder="&nbsp;"
<input id="{id}" name="{name}" value="{value ||''}" placeholder="{placeholder || ' '}"
class="form-input" type="text" autocomplete="off" autocapitalize="off"
on:input={handleInput} on:keydown={handleKeyDown}
on:focus={handleFocus} on:blur={handleBlur}>
@@ -152,6 +153,7 @@
.form-autocomplete.small .form-autocomplete-input {
height: 1.4rem;
min-height: 1.4rem;
padding: 0.05rem 0.3rem;
}
.form-autocomplete.small .form-autocomplete-input input {