mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-30 01:38:54 +00:00
192 lines
5.6 KiB
JavaScript
192 lines
5.6 KiB
JavaScript
/**
|
|
* Alpine.data('adminReleaseList') - Admin release list bulk selection and category change
|
|
*/
|
|
import Alpine from '@alpinejs/csp';
|
|
|
|
Alpine.data('adminReleaseList', () => ({
|
|
allChecked: false,
|
|
selectedCount: 0,
|
|
rootEl: null,
|
|
|
|
init() {
|
|
this.rootEl = this.$root;
|
|
this.syncSelectionState();
|
|
},
|
|
|
|
componentRoot() {
|
|
return this.rootEl || this.$root;
|
|
},
|
|
|
|
releaseCheckboxes() {
|
|
const root = this.componentRoot();
|
|
|
|
return root ? [...root.querySelectorAll('.release-checkbox')] : [];
|
|
},
|
|
|
|
setAllSelection(checked) {
|
|
const boxes = this.releaseCheckboxes();
|
|
boxes.forEach(cb => {
|
|
cb.checked = checked;
|
|
});
|
|
this.allChecked = checked && boxes.length > 0;
|
|
this.selectedCount = checked ? boxes.length : 0;
|
|
},
|
|
|
|
selectAll() {
|
|
this.setAllSelection(true);
|
|
},
|
|
|
|
clearSelection() {
|
|
this.setAllSelection(false);
|
|
},
|
|
|
|
syncSelectionState() {
|
|
const boxes = this.releaseCheckboxes();
|
|
const checkedCount = boxes.filter(cb => cb.checked).length;
|
|
this.selectedCount = checkedCount;
|
|
this.allChecked = boxes.length > 0 && checkedCount === boxes.length;
|
|
},
|
|
|
|
onCheckboxChange() {
|
|
this.syncSelectionState();
|
|
},
|
|
|
|
showModal(options) {
|
|
if (typeof window.showConfirm === 'function') {
|
|
window.showConfirm(options);
|
|
|
|
return;
|
|
}
|
|
|
|
if (options.onConfirm) {
|
|
options.onConfirm();
|
|
}
|
|
},
|
|
|
|
showToast(message, type) {
|
|
Alpine.store('toast').show(message, type);
|
|
},
|
|
|
|
deleteRelease(e) {
|
|
e.preventDefault();
|
|
|
|
const button = e.currentTarget;
|
|
const deleteUrl = button.dataset.deleteUrl;
|
|
|
|
if (!deleteUrl) {
|
|
this.showToast('Release delete URL is missing.', 'error');
|
|
|
|
return;
|
|
}
|
|
|
|
this.showModal({
|
|
title: 'Delete Release',
|
|
message: 'Are you sure you want to delete this release?',
|
|
details: 'This action cannot be undone.',
|
|
type: 'danger',
|
|
confirmText: 'Delete',
|
|
cancelText: 'Cancel',
|
|
onConfirm: () => this.submitReleaseDelete(button, deleteUrl),
|
|
});
|
|
},
|
|
|
|
submitReleaseDelete(button, deleteUrl) {
|
|
const csrf = document.querySelector('meta[name="csrf-token"]')?.content;
|
|
|
|
if (!csrf) {
|
|
this.showToast('Unable to delete release: CSRF token is missing.', 'error');
|
|
|
|
return;
|
|
}
|
|
|
|
button.disabled = true;
|
|
button.setAttribute('aria-busy', 'true');
|
|
this.showToast('Deleting release...', 'info');
|
|
|
|
fetch(deleteUrl, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
'X-CSRF-TOKEN': csrf,
|
|
'Accept': 'application/json',
|
|
},
|
|
})
|
|
.then(response => response.json().catch(() => ({})).then(data => ({ response, data })))
|
|
.then(({ response, data }) => {
|
|
if (!response.ok || data.success === false) {
|
|
throw new Error(data.message || 'Error deleting release: ' + response.status);
|
|
}
|
|
|
|
const row = button.closest('tr');
|
|
if (row) {
|
|
row.style.transition = 'opacity 0.3s';
|
|
row.style.opacity = '0';
|
|
setTimeout(() => {
|
|
row.remove();
|
|
this.syncSelectionState();
|
|
}, 300);
|
|
} else {
|
|
this.syncSelectionState();
|
|
}
|
|
|
|
this.showToast(data.message || 'Release deleted successfully', 'success');
|
|
})
|
|
.catch(error => {
|
|
button.disabled = false;
|
|
this.showToast(error.message || 'Error deleting release.', 'error');
|
|
})
|
|
.finally(() => {
|
|
button.removeAttribute('aria-busy');
|
|
});
|
|
},
|
|
|
|
validateBulkAction(e) {
|
|
e.preventDefault();
|
|
|
|
const form = e.target;
|
|
const root = this.componentRoot();
|
|
const categorySelect = root?.querySelector('select[name="categories_id"]');
|
|
const categoryId = categorySelect?.value;
|
|
const categoryName = categorySelect?.selectedOptions?.[0]?.text?.trim() || '';
|
|
const checkedCount = this.releaseCheckboxes().filter(cb => cb.checked).length;
|
|
|
|
if (!categoryId || categoryId === '-1') {
|
|
this.showModal({
|
|
title: 'Category required',
|
|
message: 'Please select a category to assign to the selected releases.',
|
|
type: 'warning',
|
|
confirmText: 'OK',
|
|
cancelText: 'Close',
|
|
onConfirm: function() {},
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
if (checkedCount === 0) {
|
|
this.showModal({
|
|
title: 'No releases selected',
|
|
message: 'Please select at least one release before changing its category.',
|
|
type: 'warning',
|
|
confirmText: 'OK',
|
|
cancelText: 'Close',
|
|
onConfirm: function() {},
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
this.showModal({
|
|
title: 'Change category',
|
|
message: 'Change category for ' + checkedCount + ' release(s)?',
|
|
details: 'Assign to: ' + categoryName + '. The database and search index will be updated.',
|
|
type: 'warning',
|
|
confirmText: 'Change category',
|
|
cancelText: 'Cancel',
|
|
onConfirm: function() {
|
|
form.submit();
|
|
},
|
|
});
|
|
},
|
|
}));
|