2024-10-14 23:09:27 +02:00
|
|
|
import { Controller } from "@hotwired/stimulus";
|
2024-06-07 12:44:06 -04:00
|
|
|
|
|
|
|
// Connects to data-controller="bulk-select"
|
|
|
|
export default class extends Controller {
|
2024-10-14 23:09:27 +02:00
|
|
|
static targets = [
|
|
|
|
"row",
|
|
|
|
"group",
|
|
|
|
"selectionBar",
|
|
|
|
"selectionBarText",
|
|
|
|
"bulkEditDrawerTitle",
|
|
|
|
];
|
2024-06-07 12:44:06 -04:00
|
|
|
static values = {
|
2024-11-04 20:27:31 -05:00
|
|
|
singularLabel: String,
|
|
|
|
pluralLabel: String,
|
2024-10-14 23:09:27 +02:00
|
|
|
selectedIds: { type: Array, default: [] },
|
|
|
|
};
|
2024-06-07 12:44:06 -04:00
|
|
|
|
|
|
|
connect() {
|
2024-10-14 23:09:27 +02:00
|
|
|
document.addEventListener("turbo:load", this._updateView);
|
2024-06-07 12:44:06 -04:00
|
|
|
|
2024-10-14 23:09:27 +02:00
|
|
|
this._updateView();
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
disconnect() {
|
2024-10-14 23:09:27 +02:00
|
|
|
document.removeEventListener("turbo:load", this._updateView);
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
2024-06-07 18:59:46 -04:00
|
|
|
bulkEditDrawerTitleTargetConnected(element) {
|
2024-10-14 23:09:27 +02:00
|
|
|
element.innerText = `Edit ${
|
|
|
|
this.selectedIdsValue.length
|
|
|
|
} ${this._pluralizedResourceName()}`;
|
2024-06-07 18:59:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
submitBulkRequest(e) {
|
2024-06-07 16:56:30 -04:00
|
|
|
const form = e.target.closest("form");
|
2024-10-14 23:09:27 +02:00
|
|
|
const scope = e.params.scope;
|
|
|
|
this._addHiddenFormInputsForSelectedIds(
|
|
|
|
form,
|
|
|
|
`${scope}[entry_ids][]`,
|
|
|
|
this.selectedIdsValue,
|
|
|
|
);
|
|
|
|
form.requestSubmit();
|
2024-06-07 16:56:30 -04:00
|
|
|
}
|
|
|
|
|
2024-06-07 12:44:06 -04:00
|
|
|
togglePageSelection(e) {
|
|
|
|
if (e.target.checked) {
|
2024-10-14 23:09:27 +02:00
|
|
|
this._selectAll();
|
2024-06-07 12:44:06 -04:00
|
|
|
} else {
|
2024-10-14 23:09:27 +02:00
|
|
|
this.deselectAll();
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
toggleGroupSelection(e) {
|
2024-10-14 23:09:27 +02:00
|
|
|
const group = this.groupTargets.find((group) => group.contains(e.target));
|
2024-06-07 12:44:06 -04:00
|
|
|
|
2024-10-14 23:09:27 +02:00
|
|
|
this._rowsForGroup(group).forEach((row) => {
|
2024-06-07 12:44:06 -04:00
|
|
|
if (e.target.checked) {
|
2024-10-14 23:09:27 +02:00
|
|
|
this._addToSelection(row.dataset.id);
|
2024-06-07 12:44:06 -04:00
|
|
|
} else {
|
2024-10-14 23:09:27 +02:00
|
|
|
this._removeFromSelection(row.dataset.id);
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
2024-10-14 23:09:27 +02:00
|
|
|
});
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
toggleRowSelection(e) {
|
|
|
|
if (e.target.checked) {
|
2024-10-14 23:09:27 +02:00
|
|
|
this._addToSelection(e.target.dataset.id);
|
2024-06-07 12:44:06 -04:00
|
|
|
} else {
|
2024-10-14 23:09:27 +02:00
|
|
|
this._removeFromSelection(e.target.dataset.id);
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
deselectAll() {
|
2024-10-14 23:09:27 +02:00
|
|
|
this.selectedIdsValue = [];
|
|
|
|
this.element.querySelectorAll('input[type="checkbox"]').forEach((el) => {
|
|
|
|
el.checked = false;
|
|
|
|
});
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
selectedIdsValueChanged() {
|
2024-10-14 23:09:27 +02:00
|
|
|
this._updateView();
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
2024-10-11 14:40:13 -04:00
|
|
|
_addHiddenFormInputsForSelectedIds(form, paramName, transactionIds) {
|
|
|
|
this._resetFormInputs(form, paramName);
|
2024-06-19 23:50:32 +03:00
|
|
|
|
2024-10-14 23:09:27 +02:00
|
|
|
transactionIds.forEach((id) => {
|
2024-06-07 16:56:30 -04:00
|
|
|
const input = document.createElement("input");
|
2024-10-14 23:09:27 +02:00
|
|
|
input.type = "hidden";
|
|
|
|
input.name = paramName;
|
|
|
|
input.value = id;
|
|
|
|
form.appendChild(input);
|
|
|
|
});
|
2024-06-07 16:56:30 -04:00
|
|
|
}
|
|
|
|
|
2024-10-11 14:40:13 -04:00
|
|
|
_resetFormInputs(form, paramName) {
|
2024-06-19 23:50:32 +03:00
|
|
|
const existingInputs = form.querySelectorAll(`input[name='${paramName}']`);
|
|
|
|
existingInputs.forEach((input) => input.remove());
|
|
|
|
}
|
|
|
|
|
2024-10-11 14:40:13 -04:00
|
|
|
_rowsForGroup(group) {
|
2025-01-07 09:41:24 -05:00
|
|
|
return this.rowTargets.filter(
|
|
|
|
(row) => group.contains(row) && !row.disabled,
|
|
|
|
);
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
2024-10-11 14:40:13 -04:00
|
|
|
_addToSelection(idToAdd) {
|
2024-06-07 12:44:06 -04:00
|
|
|
this.selectedIdsValue = Array.from(
|
2024-10-14 23:09:27 +02:00
|
|
|
new Set([...this.selectedIdsValue, idToAdd]),
|
|
|
|
);
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
2024-10-11 14:40:13 -04:00
|
|
|
_removeFromSelection(idToRemove) {
|
2024-10-14 23:09:27 +02:00
|
|
|
this.selectedIdsValue = this.selectedIdsValue.filter(
|
|
|
|
(id) => id !== idToRemove,
|
|
|
|
);
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
2024-10-11 14:40:13 -04:00
|
|
|
_selectAll() {
|
2025-01-07 09:41:24 -05:00
|
|
|
this.selectedIdsValue = this.rowTargets
|
|
|
|
.filter((t) => !t.disabled)
|
|
|
|
.map((t) => t.dataset.id);
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
2024-10-11 11:34:51 -04:00
|
|
|
_updateView = () => {
|
2024-10-14 23:09:27 +02:00
|
|
|
this._updateSelectionBar();
|
|
|
|
this._updateGroups();
|
|
|
|
this._updateRows();
|
|
|
|
};
|
2024-06-07 12:44:06 -04:00
|
|
|
|
2024-10-11 14:40:13 -04:00
|
|
|
_updateSelectionBar() {
|
2024-10-14 23:09:27 +02:00
|
|
|
const count = this.selectedIdsValue.length;
|
|
|
|
this.selectionBarTextTarget.innerText = `${count} ${this._pluralizedResourceName()} selected`;
|
2024-10-28 13:02:49 +01:00
|
|
|
this.selectionBarTarget.classList.toggle("hidden", count === 0);
|
2024-10-14 23:09:27 +02:00
|
|
|
this.selectionBarTarget.querySelector("input[type='checkbox']").checked =
|
|
|
|
count > 0;
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
2024-10-11 14:40:13 -04:00
|
|
|
_pluralizedResourceName() {
|
2024-11-04 20:27:31 -05:00
|
|
|
if (this.selectedIdsValue.length === 1) {
|
|
|
|
return this.singularLabelValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.pluralLabelValue;
|
2024-06-07 18:59:46 -04:00
|
|
|
}
|
|
|
|
|
2024-10-11 14:40:13 -04:00
|
|
|
_updateGroups() {
|
2024-10-14 23:09:27 +02:00
|
|
|
this.groupTargets.forEach((group) => {
|
|
|
|
const rows = this.rowTargets.filter((row) => group.contains(row));
|
|
|
|
const groupSelected =
|
|
|
|
rows.length > 0 &&
|
|
|
|
rows.every((row) => this.selectedIdsValue.includes(row.dataset.id));
|
|
|
|
group.querySelector("input[type='checkbox']").checked = groupSelected;
|
|
|
|
});
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
|
2024-10-11 14:40:13 -04:00
|
|
|
_updateRows() {
|
2024-10-14 23:09:27 +02:00
|
|
|
this.rowTargets.forEach((row) => {
|
|
|
|
row.checked = this.selectedIdsValue.includes(row.dataset.id);
|
|
|
|
});
|
2024-06-07 12:44:06 -04:00
|
|
|
}
|
|
|
|
}
|