165 lines
5.5 KiB
JavaScript
165 lines
5.5 KiB
JavaScript
// Auto-save custom fields on blur (subnet page)
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const customFieldsForm = document.getElementById('custom-fields-form');
|
|
if (!customFieldsForm) {
|
|
return; // No custom fields form on this page
|
|
}
|
|
|
|
const subnetId = customFieldsForm.action.match(/\/subnet\/(\d+)\/update_custom_fields/)?.[1];
|
|
if (!subnetId) {
|
|
return;
|
|
}
|
|
|
|
// Get all form fields
|
|
const formFields = customFieldsForm.querySelectorAll('input, textarea, select');
|
|
const originalValues = new Map();
|
|
|
|
// Store original values
|
|
formFields.forEach(field => {
|
|
if (field.type === 'checkbox') {
|
|
originalValues.set(field, field.checked);
|
|
} else {
|
|
originalValues.set(field, field.value);
|
|
}
|
|
});
|
|
|
|
// Helper function to show toast notification (reuse from subnet.js if available)
|
|
function showToast(message, type = 'success') {
|
|
const toast = document.createElement('div');
|
|
toast.className = `fixed top-20 right-4 px-4 py-3 rounded-lg shadow-lg z-50 ${
|
|
type === 'success'
|
|
? 'bg-green-500 text-white'
|
|
: 'bg-red-500 text-white'
|
|
}`;
|
|
toast.textContent = message;
|
|
document.body.appendChild(toast);
|
|
|
|
setTimeout(() => {
|
|
toast.style.transition = 'opacity 0.3s';
|
|
toast.style.opacity = '0';
|
|
setTimeout(() => toast.remove(), 300);
|
|
}, 3000);
|
|
}
|
|
|
|
// Auto-resize textareas
|
|
const textareas = customFieldsForm.querySelectorAll('textarea');
|
|
textareas.forEach(textarea => {
|
|
textarea.style.overflow = 'hidden';
|
|
textarea.style.resize = 'none';
|
|
|
|
function autoResize() {
|
|
textarea.style.height = 'auto';
|
|
textarea.style.height = textarea.scrollHeight + 'px';
|
|
}
|
|
autoResize();
|
|
textarea.addEventListener('input', autoResize);
|
|
});
|
|
|
|
// Check if form has changes
|
|
function hasChanges() {
|
|
for (const field of formFields) {
|
|
let currentValue;
|
|
if (field.type === 'checkbox') {
|
|
currentValue = field.checked;
|
|
} else {
|
|
currentValue = field.value;
|
|
}
|
|
|
|
const originalValue = originalValues.get(field);
|
|
if (currentValue !== originalValue) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Save all custom fields
|
|
let saveInProgress = false;
|
|
async function saveCustomFields() {
|
|
if (saveInProgress) {
|
|
return; // Prevent multiple simultaneous saves
|
|
}
|
|
|
|
if (!hasChanges()) {
|
|
return; // No changes to save
|
|
}
|
|
|
|
saveInProgress = true;
|
|
|
|
// Show loading indicator on form
|
|
const originalOpacity = customFieldsForm.style.opacity;
|
|
customFieldsForm.style.opacity = '0.6';
|
|
customFieldsForm.style.pointerEvents = 'none';
|
|
|
|
try {
|
|
// Create FormData from form and convert to JSON
|
|
const formData = new FormData(customFieldsForm);
|
|
const data = {};
|
|
|
|
// Process all fields
|
|
for (const [key, value] of formData.entries()) {
|
|
data[key] = value;
|
|
}
|
|
|
|
// Handle checkboxes that weren't checked (they don't appear in FormData)
|
|
formFields.forEach(field => {
|
|
if (field.type === 'checkbox' && !field.checked) {
|
|
data[field.name] = '';
|
|
}
|
|
});
|
|
|
|
const response = await fetch(customFieldsForm.action, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
if (response.ok) {
|
|
// Update original values
|
|
formFields.forEach(field => {
|
|
if (field.type === 'checkbox') {
|
|
originalValues.set(field, field.checked);
|
|
} else {
|
|
originalValues.set(field, field.value);
|
|
}
|
|
});
|
|
|
|
showToast('Custom fields saved successfully', 'success');
|
|
} else {
|
|
const data = await response.json().catch(() => ({}));
|
|
const errorMsg = data.errors ? data.errors.join(', ') : (data.error || 'Failed to save custom fields');
|
|
showToast(errorMsg, 'error');
|
|
}
|
|
} catch (error) {
|
|
showToast('Error saving custom fields. Please try again.', 'error');
|
|
console.error('Error saving custom fields:', error);
|
|
} finally {
|
|
customFieldsForm.style.opacity = originalOpacity;
|
|
customFieldsForm.style.pointerEvents = '';
|
|
saveInProgress = false;
|
|
}
|
|
}
|
|
|
|
// Add blur event listeners to all fields
|
|
formFields.forEach(field => {
|
|
// Skip if it's a checkbox (we'll handle change event instead)
|
|
if (field.type === 'checkbox') {
|
|
field.addEventListener('change', () => {
|
|
// Small delay to ensure value is updated
|
|
setTimeout(saveCustomFields, 100);
|
|
});
|
|
} else {
|
|
field.addEventListener('blur', saveCustomFields);
|
|
}
|
|
});
|
|
|
|
// Prevent form submission (since we're using auto-save)
|
|
customFieldsForm.addEventListener('submit', (e) => {
|
|
e.preventDefault();
|
|
saveCustomFields();
|
|
});
|
|
});
|
|
|