wip
This commit is contained in:
parent
5a309a0f6d
commit
1ab129b798
5 changed files with 499 additions and 107 deletions
177
app/static/js/validation.js
Normal file
177
app/static/js/validation.js
Normal file
|
@ -0,0 +1,177 @@
|
|||
// Application Name Validation
|
||||
function validateAppName() {
|
||||
const nameField = document.getElementById('app-name');
|
||||
const serverField = document.getElementById('server-id');
|
||||
const feedbackElement = document.getElementById('name-feedback');
|
||||
const submitButton = document.querySelector('button[type="submit"]');
|
||||
|
||||
if (!nameField || !serverField) return;
|
||||
|
||||
const name = nameField.value.trim();
|
||||
const serverId = serverField.value;
|
||||
const appId = document.getElementById('app-id')?.value;
|
||||
|
||||
if (!name || !serverId) {
|
||||
clearFeedback(feedbackElement);
|
||||
return;
|
||||
}
|
||||
|
||||
// Debounce to avoid too many requests
|
||||
clearTimeout(nameField.timer);
|
||||
nameField.timer = setTimeout(() => {
|
||||
fetch(`/api/validate/app-name?name=${encodeURIComponent(name)}&server_id=${serverId}${appId ? '&app_id=' + appId : ''}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (!data.valid) {
|
||||
showError(feedbackElement, data.message);
|
||||
if (data.edit_url) {
|
||||
feedbackElement.innerHTML += ` <a href="${data.edit_url}" class="alert-link">Edit this app instead?</a>`;
|
||||
}
|
||||
submitButton.disabled = true;
|
||||
} else if (data.warning) {
|
||||
showWarning(feedbackElement, data.warning);
|
||||
if (data.similar_apps && data.similar_apps.length > 0) {
|
||||
feedbackElement.innerHTML += '<ul class="mb-0 mt-1">';
|
||||
data.similar_apps.forEach(app => {
|
||||
feedbackElement.innerHTML += `<li><a href="/dashboard/app/${app.id}/edit" class="alert-link">${app.name}</a></li>`;
|
||||
});
|
||||
feedbackElement.innerHTML += '</ul>';
|
||||
}
|
||||
submitButton.disabled = false;
|
||||
} else {
|
||||
showSuccess(feedbackElement, "App name is available");
|
||||
submitButton.disabled = false;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Validation error:', error);
|
||||
clearFeedback(feedbackElement);
|
||||
});
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// Port Validation
|
||||
function validatePort(portField, protocolField) {
|
||||
const serverField = document.getElementById('server-id');
|
||||
const feedbackElement = portField.nextElementSibling;
|
||||
const submitButton = document.querySelector('button[type="submit"]');
|
||||
|
||||
if (!portField || !serverField || !protocolField) return;
|
||||
|
||||
const port = portField.value.trim();
|
||||
const protocol = protocolField.value;
|
||||
const serverId = serverField.value;
|
||||
const appId = document.getElementById('app-id')?.value;
|
||||
|
||||
if (!port || !serverId) {
|
||||
clearFeedback(feedbackElement);
|
||||
return;
|
||||
}
|
||||
|
||||
// Debounce to avoid too many requests
|
||||
clearTimeout(portField.timer);
|
||||
portField.timer = setTimeout(() => {
|
||||
fetch(`/api/validate/app-port?port_number=${encodeURIComponent(port)}&protocol=${protocol}&server_id=${serverId}${appId ? '&app_id=' + appId : ''}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (!data.valid) {
|
||||
showError(feedbackElement, data.message);
|
||||
if (data.edit_url) {
|
||||
feedbackElement.innerHTML += ` <a href="${data.edit_url}" class="alert-link">Edit the conflicting app?</a>`;
|
||||
}
|
||||
portField.classList.add('is-invalid');
|
||||
submitButton.disabled = true;
|
||||
} else {
|
||||
clearFeedback(feedbackElement);
|
||||
portField.classList.remove('is-invalid');
|
||||
portField.classList.add('is-valid');
|
||||
submitButton.disabled = false;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Validation error:', error);
|
||||
clearFeedback(feedbackElement);
|
||||
});
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// Helper functions for feedback display
|
||||
function showError(element, message) {
|
||||
if (!element) return;
|
||||
element.className = 'invalid-feedback d-block';
|
||||
element.textContent = message;
|
||||
}
|
||||
|
||||
function showWarning(element, message) {
|
||||
if (!element) return;
|
||||
element.className = 'text-warning d-block';
|
||||
element.textContent = message;
|
||||
}
|
||||
|
||||
function showSuccess(element, message) {
|
||||
if (!element) return;
|
||||
element.className = 'valid-feedback d-block';
|
||||
element.textContent = message;
|
||||
}
|
||||
|
||||
function clearFeedback(element) {
|
||||
if (!element) return;
|
||||
element.className = '';
|
||||
element.textContent = '';
|
||||
}
|
||||
|
||||
// Set up event listeners when the document is loaded
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const nameField = document.getElementById('app-name');
|
||||
const serverField = document.getElementById('server-id');
|
||||
|
||||
if (nameField) {
|
||||
nameField.addEventListener('input', validateAppName);
|
||||
|
||||
if (serverField) {
|
||||
serverField.addEventListener('change', validateAppName);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up validation for existing port fields
|
||||
setupPortValidation();
|
||||
|
||||
// Make sure new port rows get validation too
|
||||
const addPortButton = document.getElementById('add-port-btn');
|
||||
if (addPortButton) {
|
||||
addPortButton.addEventListener('click', function () {
|
||||
// Wait a moment for the new row to be added
|
||||
setTimeout(setupPortValidation, 100);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function setupPortValidation() {
|
||||
const portFields = document.querySelectorAll('input[name="port_numbers[]"]');
|
||||
const protocolFields = document.querySelectorAll('select[name="protocols[]"]');
|
||||
|
||||
portFields.forEach((field, index) => {
|
||||
if (!field.hasValidationSetup) {
|
||||
const protocolField = protocolFields[index];
|
||||
|
||||
field.addEventListener('input', function () {
|
||||
validatePort(field, protocolField);
|
||||
});
|
||||
|
||||
if (protocolField) {
|
||||
protocolField.addEventListener('change', function () {
|
||||
validatePort(field, protocolField);
|
||||
});
|
||||
}
|
||||
|
||||
// Add a div for feedback if it doesn't exist
|
||||
if (!field.nextElementSibling || !field.nextElementSibling.classList.contains('feedback')) {
|
||||
const feedback = document.createElement('div');
|
||||
feedback.className = 'feedback';
|
||||
field.parentNode.insertBefore(feedback, field.nextSibling);
|
||||
}
|
||||
|
||||
field.hasValidationSetup = true;
|
||||
}
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue