mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 08:51:09 -05:00
263 lines
11 KiB
JavaScript
263 lines
11 KiB
JavaScript
document.addEventListener('DOMContentLoaded', function() {
|
|
// Handle edit button clicks
|
|
document.querySelectorAll('[data-edit-button]').forEach(button => {
|
|
button.addEventListener('click', function() {
|
|
const contentId = this.dataset.contentId;
|
|
const contentType = this.dataset.contentType;
|
|
const editableFields = document.querySelectorAll(`[data-editable][data-content-id="${contentId}"]`);
|
|
|
|
// Toggle edit mode
|
|
editableFields.forEach(field => {
|
|
const currentValue = field.textContent.trim();
|
|
const fieldName = field.dataset.fieldName;
|
|
const fieldType = field.dataset.fieldType || 'text';
|
|
|
|
// Create input field
|
|
let input;
|
|
if (fieldType === 'textarea') {
|
|
input = document.createElement('textarea');
|
|
input.value = currentValue;
|
|
input.rows = 4;
|
|
} else if (fieldType === 'select') {
|
|
input = document.createElement('select');
|
|
// Get options from data attribute
|
|
const options = JSON.parse(field.dataset.options || '[]');
|
|
options.forEach(option => {
|
|
const optionEl = document.createElement('option');
|
|
optionEl.value = option.value;
|
|
optionEl.textContent = option.label;
|
|
optionEl.selected = option.value === currentValue;
|
|
input.appendChild(optionEl);
|
|
});
|
|
} else if (fieldType === 'date') {
|
|
input = document.createElement('input');
|
|
input.type = 'date';
|
|
input.value = currentValue;
|
|
} else if (fieldType === 'number') {
|
|
input = document.createElement('input');
|
|
input.type = 'number';
|
|
input.value = currentValue;
|
|
if (field.dataset.min) input.min = field.dataset.min;
|
|
if (field.dataset.max) input.max = field.dataset.max;
|
|
if (field.dataset.step) input.step = field.dataset.step;
|
|
} else {
|
|
input = document.createElement('input');
|
|
input.type = fieldType;
|
|
input.value = currentValue;
|
|
}
|
|
|
|
input.className = 'w-full border-gray-300 rounded-lg form-input dark:border-gray-600 dark:bg-gray-700 dark:text-white';
|
|
input.dataset.originalValue = currentValue;
|
|
input.dataset.fieldName = fieldName;
|
|
|
|
// Replace content with input
|
|
field.textContent = '';
|
|
field.appendChild(input);
|
|
});
|
|
|
|
// Show save/cancel buttons
|
|
const actionButtons = document.createElement('div');
|
|
actionButtons.className = 'flex gap-2 mt-2';
|
|
actionButtons.innerHTML = `
|
|
<button class="px-4 py-2 text-white bg-blue-600 rounded-lg hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600" data-save-button>
|
|
<i class="mr-2 fas fa-save"></i>Save Changes
|
|
</button>
|
|
<button class="px-4 py-2 text-gray-700 bg-gray-200 rounded-lg hover:bg-gray-300 dark:bg-gray-600 dark:text-gray-200 dark:hover:bg-gray-500" data-cancel-button>
|
|
<i class="mr-2 fas fa-times"></i>Cancel
|
|
</button>
|
|
${this.dataset.requireReason ? `
|
|
<div class="flex-grow">
|
|
<input type="text" class="w-full border-gray-300 rounded-lg form-input dark:border-gray-600 dark:bg-gray-700 dark:text-white"
|
|
placeholder="Reason for changes (required)"
|
|
data-reason-input>
|
|
<input type="text" class="w-full mt-1 border-gray-300 rounded-lg form-input dark:border-gray-600 dark:bg-gray-700 dark:text-white"
|
|
placeholder="Source (optional)"
|
|
data-source-input>
|
|
</div>
|
|
` : ''}
|
|
`;
|
|
|
|
const container = editableFields[0].closest('.editable-container');
|
|
container.appendChild(actionButtons);
|
|
|
|
// Hide edit button while editing
|
|
this.style.display = 'none';
|
|
});
|
|
});
|
|
|
|
// Handle form submissions
|
|
document.querySelectorAll('form[data-submit-type]').forEach(form => {
|
|
form.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const submitType = this.dataset.submitType;
|
|
const formData = new FormData(this);
|
|
const data = {};
|
|
|
|
formData.forEach((value, key) => {
|
|
data[key] = value;
|
|
});
|
|
|
|
// Get CSRF token from meta tag
|
|
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
|
|
|
// Submit form
|
|
fetch(this.action, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': csrfToken
|
|
},
|
|
body: JSON.stringify({
|
|
submission_type: submitType,
|
|
...data
|
|
})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.status === 'success') {
|
|
showNotification(data.message, 'success');
|
|
if (data.redirect_url) {
|
|
window.location.href = data.redirect_url;
|
|
}
|
|
} else {
|
|
showNotification(data.message, 'error');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
showNotification('An error occurred while submitting the form.', 'error');
|
|
console.error('Error:', error);
|
|
});
|
|
});
|
|
});
|
|
|
|
// Handle save button clicks using event delegation
|
|
document.addEventListener('click', function(e) {
|
|
if (e.target.matches('[data-save-button]')) {
|
|
const container = e.target.closest('.editable-container');
|
|
const contentId = container.querySelector('[data-editable]').dataset.contentId;
|
|
const contentType = container.querySelector('[data-edit-button]').dataset.contentType;
|
|
const editableFields = container.querySelectorAll('[data-editable]');
|
|
|
|
// Collect changes
|
|
const changes = {};
|
|
editableFields.forEach(field => {
|
|
const input = field.querySelector('input, textarea, select');
|
|
if (input && input.value !== input.dataset.originalValue) {
|
|
changes[input.dataset.fieldName] = input.value;
|
|
}
|
|
});
|
|
|
|
// If no changes, just cancel
|
|
if (Object.keys(changes).length === 0) {
|
|
cancelEdit(container);
|
|
return;
|
|
}
|
|
|
|
// Get reason and source if required
|
|
const reasonInput = container.querySelector('[data-reason-input]');
|
|
const sourceInput = container.querySelector('[data-source-input]');
|
|
const reason = reasonInput ? reasonInput.value : '';
|
|
const source = sourceInput ? sourceInput.value : '';
|
|
|
|
// Validate reason if required
|
|
if (reasonInput && !reason) {
|
|
alert('Please provide a reason for your changes.');
|
|
return;
|
|
}
|
|
|
|
// Get CSRF token from meta tag
|
|
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
|
|
|
// Submit changes
|
|
fetch(window.location.pathname, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': csrfToken
|
|
},
|
|
body: JSON.stringify({
|
|
content_type: contentType,
|
|
content_id: contentId,
|
|
changes,
|
|
reason,
|
|
source
|
|
})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.status === 'success') {
|
|
if (data.auto_approved) {
|
|
// Update the display immediately
|
|
Object.entries(changes).forEach(([field, value]) => {
|
|
const element = container.querySelector(`[data-editable][data-field-name="${field}"]`);
|
|
if (element) {
|
|
element.textContent = value;
|
|
}
|
|
});
|
|
}
|
|
showNotification(data.message, 'success');
|
|
if (data.redirect_url) {
|
|
window.location.href = data.redirect_url;
|
|
}
|
|
} else {
|
|
showNotification(data.message, 'error');
|
|
}
|
|
cancelEdit(container);
|
|
})
|
|
.catch(error => {
|
|
showNotification('An error occurred while saving changes.', 'error');
|
|
console.error('Error:', error);
|
|
cancelEdit(container);
|
|
});
|
|
}
|
|
});
|
|
|
|
// Handle cancel button clicks using event delegation
|
|
document.addEventListener('click', function(e) {
|
|
if (e.target.matches('[data-cancel-button]')) {
|
|
const container = e.target.closest('.editable-container');
|
|
cancelEdit(container);
|
|
}
|
|
});
|
|
});
|
|
|
|
function cancelEdit(container) {
|
|
// Restore original content
|
|
container.querySelectorAll('[data-editable]').forEach(field => {
|
|
const input = field.querySelector('input, textarea, select');
|
|
if (input) {
|
|
field.textContent = input.dataset.originalValue;
|
|
}
|
|
});
|
|
|
|
// Remove action buttons
|
|
const actionButtons = container.querySelector('.flex.gap-2');
|
|
if (actionButtons) {
|
|
actionButtons.remove();
|
|
}
|
|
|
|
// Show edit button
|
|
const editButton = container.querySelector('[data-edit-button]');
|
|
if (editButton) {
|
|
editButton.style.display = '';
|
|
}
|
|
}
|
|
|
|
function showNotification(message, type = 'info') {
|
|
const notification = document.createElement('div');
|
|
notification.className = `fixed bottom-4 right-4 p-4 rounded-lg shadow-lg text-white ${
|
|
type === 'success' ? 'bg-green-600 dark:bg-green-500' :
|
|
type === 'error' ? 'bg-red-600 dark:bg-red-500' :
|
|
'bg-blue-600 dark:bg-blue-500'
|
|
}`;
|
|
notification.textContent = message;
|
|
|
|
document.body.appendChild(notification);
|
|
|
|
// Remove after 5 seconds
|
|
setTimeout(() => {
|
|
notification.remove();
|
|
}, 5000);
|
|
}
|