mirror of
https://github.com/wizarrrr/wizarr.git
synced 2026-08-02 16:27:28 -04:00
223 lines
12 KiB
HTML
223 lines
12 KiB
HTML
<!-- Delete User Confirmation Modal -->
|
|
<div class="relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all w-full max-w-md dark:bg-gray-800"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="modal-title">
|
|
<!-- Modal header -->
|
|
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
|
|
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">{{ _("Remove User") }}: {{ display_name }}</h3>
|
|
<button type="button"
|
|
onclick="closeModal()"
|
|
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white">
|
|
<svg class="w-3 h-3"
|
|
aria-hidden="true"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 14 14">
|
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<!-- Modal body -->
|
|
<div class="bg-white px-4 pb-4 pt-5 sm:p-6 sm:pb-4 dark:bg-gray-800">
|
|
<form hx-post="{{ url_for('admin.process_user_deletion') }}"
|
|
hx-include="this">
|
|
<!-- User info -->
|
|
<div class="mb-4 p-3 bg-gray-50 rounded-lg dark:bg-gray-600">
|
|
<div class="flex items-center space-x-3">
|
|
<div class="flex-shrink-0 w-10 h-10 bg-gray-200 dark:bg-gray-700 rounded-full flex items-center justify-center">
|
|
<span class="text-sm font-medium text-gray-600 dark:text-gray-300">{{ display_name[0]|upper }}</span>
|
|
</div>
|
|
<div>
|
|
<div class="font-medium text-gray-900 dark:text-white">{{ display_name }}</div>
|
|
<div class="text-sm text-gray-500 dark:text-gray-400">{{ user_email or _("Home User") }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p class="mb-4 text-sm text-gray-500 dark:text-gray-400">{{ _("Select which servers to remove the user from:") }}</p>
|
|
<!-- Server list -->
|
|
<div class="space-y-2 mb-6">
|
|
{% for account in accounts %}
|
|
<label class="flex items-center p-3 border border-gray-200 rounded-lg hover:bg-gray-50 dark:border-gray-600 dark:hover:bg-gray-700 cursor-pointer">
|
|
<input type="checkbox"
|
|
name="server_accounts"
|
|
value="{{ account.id }}"
|
|
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600">
|
|
<div class="ml-3 flex-1">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center space-x-2">
|
|
<span class="text-sm font-medium text-gray-900 dark:text-white">
|
|
{% if account.server %}
|
|
{{ account.server.server_type|title }}
|
|
{% else %}
|
|
{{ _("Local") }}
|
|
{% endif %}
|
|
</span>
|
|
{% if account.server %}
|
|
<span class="text-xs px-2 py-1 bg-gray-100 text-gray-600 rounded dark:bg-gray-600 dark:text-gray-300">
|
|
{{ account.server.name }}
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
<div class="text-xs text-gray-500 dark:text-gray-400">{{ _("User ID") }}: {{ account.id }}</div>
|
|
</div>
|
|
</div>
|
|
</label>
|
|
{% endfor %}
|
|
</div>
|
|
<!-- Select all checkbox -->
|
|
<div class="mb-6 p-3 bg-red-50 border border-red-200 rounded-lg dark:bg-red-900 dark:border-red-700">
|
|
<label class="flex items-center cursor-pointer">
|
|
<input type="checkbox"
|
|
id="select_all_servers"
|
|
class="w-4 h-4 text-red-600 bg-gray-100 border-gray-300 rounded focus:ring-red-500 dark:focus:ring-red-600 dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600">
|
|
<div class="ml-3">
|
|
<div class="text-sm font-medium text-red-800 dark:text-red-300">{{ _("Delete from ALL servers") }}</div>
|
|
<div class="text-xs text-red-700 dark:text-red-400">
|
|
{{ _("This will remove the user completely and cannot be undone") }}
|
|
</div>
|
|
</div>
|
|
</label>
|
|
</div>
|
|
<!-- Action buttons -->
|
|
<div class="flex items-center justify-end space-x-3">
|
|
<button type="button"
|
|
onclick="closeModal()"
|
|
class="px-4 py-2 text-sm font-medium text-gray-500 bg-gray-100 hover:bg-gray-200 rounded-lg dark:bg-gray-600 dark:text-gray-300 dark:hover:bg-gray-700">
|
|
{{ _("Cancel") }}
|
|
</button>
|
|
<button type="submit"
|
|
id="delete_submit_btn"
|
|
disabled
|
|
class="px-4 py-2 text-sm font-medium text-white bg-red-600 hover:bg-red-700 disabled:bg-gray-400 disabled:cursor-not-allowed rounded-lg">
|
|
<span id="delete-btn-text">{{ _("Remove Selected") }}</span>
|
|
<span id="delete-btn-loading" class="hidden">
|
|
<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white inline"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24">
|
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">
|
|
</path>
|
|
</svg>
|
|
{{ _("Deleting user...") }}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
// Initialize modal functionality immediately when content loads
|
|
(function() {
|
|
// Handle select all checkbox
|
|
const selectAllCheckbox = document.getElementById('select_all_servers');
|
|
const serverCheckboxes = document.querySelectorAll('input[name="server_accounts"]');
|
|
const submitBtn = document.getElementById('delete_submit_btn');
|
|
|
|
if (!selectAllCheckbox || !submitBtn) {
|
|
console.warn('Delete modal elements not found');
|
|
return;
|
|
}
|
|
|
|
// Toggle all server checkboxes when "select all" is clicked
|
|
selectAllCheckbox.addEventListener('change', function() {
|
|
serverCheckboxes.forEach(checkbox => {
|
|
checkbox.checked = this.checked;
|
|
});
|
|
updateSubmitButton();
|
|
});
|
|
|
|
// Update select all checkbox state when individual checkboxes change
|
|
serverCheckboxes.forEach(checkbox => {
|
|
checkbox.addEventListener('change', function() {
|
|
const allChecked = Array.from(serverCheckboxes).every(cb => cb.checked);
|
|
const someChecked = Array.from(serverCheckboxes).some(cb => cb.checked);
|
|
|
|
selectAllCheckbox.checked = allChecked;
|
|
selectAllCheckbox.indeterminate = someChecked && !allChecked;
|
|
updateSubmitButton();
|
|
});
|
|
});
|
|
|
|
// Enable/disable submit button based on selections
|
|
function updateSubmitButton() {
|
|
const anySelected = Array.from(serverCheckboxes).some(cb => cb.checked);
|
|
submitBtn.disabled = !anySelected;
|
|
|
|
const btnText = document.getElementById('delete-btn-text');
|
|
const btnLoading = document.getElementById('delete-btn-loading');
|
|
if (selectAllCheckbox.checked) {
|
|
btnText.textContent = '{{ _("Delete from ALL Servers") }}';
|
|
btnLoading.innerHTML = '<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white inline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>{{ _("Deleting from ALL servers...") }}';
|
|
submitBtn.className = submitBtn.className.replace('bg-red-600 hover:bg-red-700', 'bg-red-800 hover:bg-red-900');
|
|
} else {
|
|
btnText.textContent = '{{ _("Remove Selected") }}';
|
|
btnLoading.innerHTML = '<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white inline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>{{ _("Deleting user...") }}';
|
|
submitBtn.className = submitBtn.className.replace('bg-red-800 hover:bg-red-900', 'bg-red-600 hover:bg-red-700');
|
|
}
|
|
}
|
|
|
|
// HTMX loading state management
|
|
const form = document.querySelector('form[hx-post*="process_user_deletion"]');
|
|
if (form) {
|
|
form.addEventListener('htmx:beforeRequest', function(event) {
|
|
const btnText = document.getElementById('delete-btn-text');
|
|
const btnLoading = document.getElementById('delete-btn-loading');
|
|
const submitButton = document.getElementById('delete_submit_btn');
|
|
|
|
console.log('Before request - showing loading state');
|
|
|
|
if (btnText && btnLoading && submitButton) {
|
|
// Disable the button immediately to prevent double submissions
|
|
submitButton.disabled = true;
|
|
|
|
// Show loading state
|
|
btnText.classList.add('hidden');
|
|
btnLoading.classList.remove('hidden');
|
|
}
|
|
});
|
|
|
|
form.addEventListener('htmx:afterRequest', function(event) {
|
|
const btnText = document.getElementById('delete-btn-text');
|
|
const btnLoading = document.getElementById('delete-btn-loading');
|
|
const submitButton = document.getElementById('delete_submit_btn');
|
|
|
|
console.log('After request - hiding loading state');
|
|
|
|
if (btnText && btnLoading && submitButton) {
|
|
// Re-enable button and hide loading
|
|
submitButton.disabled = false;
|
|
btnText.classList.remove('hidden');
|
|
btnLoading.classList.add('hidden');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Also handle direct button click for immediate feedback
|
|
if (submitBtn) {
|
|
submitBtn.addEventListener('click', function(e) {
|
|
// Only show loading if button is enabled and checkboxes are selected
|
|
if (!this.disabled && Array.from(serverCheckboxes).some(cb => cb.checked)) {
|
|
const btnText = document.getElementById('delete-btn-text');
|
|
const btnLoading = document.getElementById('delete-btn-loading');
|
|
|
|
console.log('Button clicked - showing loading state immediately');
|
|
|
|
if (btnText && btnLoading) {
|
|
// Small delay to ensure it shows before HTMX takes over
|
|
setTimeout(() => {
|
|
this.disabled = true;
|
|
btnText.classList.add('hidden');
|
|
btnLoading.classList.remove('hidden');
|
|
}, 10);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Initial state
|
|
updateSubmitButton();
|
|
})();
|
|
</script>
|