wip
This commit is contained in:
parent
1ab129b798
commit
af4b75acb4
3 changed files with 93 additions and 6 deletions
|
@ -546,4 +546,60 @@
|
|||
|
||||
.app-link:hover {
|
||||
color: var(--highlight-color);
|
||||
}
|
||||
|
||||
/* Validation styles */
|
||||
.is-invalid {
|
||||
border-color: #dc3545 !important;
|
||||
padding-right: calc(1.5em + 0.75rem);
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right calc(0.375em + 0.1875rem) center;
|
||||
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
||||
}
|
||||
|
||||
.is-valid {
|
||||
border-color: #198754 !important;
|
||||
padding-right: calc(1.5em + 0.75rem);
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right calc(0.375em + 0.1875rem) center;
|
||||
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
||||
}
|
||||
|
||||
.invalid-feedback {
|
||||
display: none;
|
||||
width: 100%;
|
||||
margin-top: 0.25rem;
|
||||
font-size: 0.875em;
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.invalid-feedback.d-block {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.valid-feedback {
|
||||
display: none;
|
||||
width: 100%;
|
||||
margin-top: 0.25rem;
|
||||
font-size: 0.875em;
|
||||
color: #198754;
|
||||
}
|
||||
|
||||
.valid-feedback.d-block {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
/* Fix position for validation messages in table cells */
|
||||
td.position-relative {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
td .feedback {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 100%;
|
||||
z-index: 5;
|
||||
}
|
|
@ -53,6 +53,13 @@ function validateAppName() {
|
|||
// Port Validation
|
||||
function validatePort(portField, protocolField) {
|
||||
const serverField = document.getElementById('server-id');
|
||||
// Create feedback element if it doesn't exist
|
||||
if (!portField.nextElementSibling || !portField.nextElementSibling.classList.contains('feedback')) {
|
||||
const feedback = document.createElement('div');
|
||||
feedback.className = 'feedback';
|
||||
portField.parentNode.insertBefore(feedback, portField.nextSibling);
|
||||
}
|
||||
|
||||
const feedbackElement = portField.nextElementSibling;
|
||||
const submitButton = document.querySelector('button[type="submit"]');
|
||||
|
||||
|
@ -65,6 +72,26 @@ function validatePort(portField, protocolField) {
|
|||
|
||||
if (!port || !serverId) {
|
||||
clearFeedback(feedbackElement);
|
||||
portField.classList.remove('is-invalid');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for duplicate ports within the form first
|
||||
const allPortFields = document.querySelectorAll('input[name="port_numbers[]"]');
|
||||
const allProtocolFields = document.querySelectorAll('select[name="protocols[]"]');
|
||||
let duplicateFound = false;
|
||||
|
||||
allPortFields.forEach((field, index) => {
|
||||
if (field !== portField &&
|
||||
field.value === port &&
|
||||
allProtocolFields[index].value === protocol) {
|
||||
duplicateFound = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (duplicateFound) {
|
||||
portField.classList.add('is-invalid');
|
||||
showError(feedbackElement, `Duplicate port ${port}/${protocol} in your form`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -75,22 +102,22 @@ function validatePort(portField, protocolField) {
|
|||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (!data.valid) {
|
||||
portField.classList.add('is-invalid');
|
||||
showError(feedbackElement, data.message);
|
||||
if (data.edit_url) {
|
||||
feedbackElement.innerHTML += ` <a href="${data.edit_url}" class="alert-link">Edit the conflicting app?</a>`;
|
||||
feedbackElement.innerHTML += ` <a href="${data.edit_url}" class="alert-link">Edit 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;
|
||||
showSuccess(feedbackElement, "Port available");
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Validation error:', error);
|
||||
clearFeedback(feedbackElement);
|
||||
portField.classList.remove('is-invalid');
|
||||
portField.classList.remove('is-valid');
|
||||
});
|
||||
}, 300);
|
||||
}
|
||||
|
|
|
@ -256,9 +256,10 @@
|
|||
const tbody = document.querySelector('#ports-table tbody');
|
||||
const newRow = document.createElement('tr');
|
||||
newRow.innerHTML = `
|
||||
<td>
|
||||
<td class="position-relative">
|
||||
<input type="number" name="port_numbers[]" class="form-control"
|
||||
min="1" max="65535" value="${portNumber}" required>
|
||||
<div class="feedback"></div>
|
||||
</td>
|
||||
<td>
|
||||
<select name="protocols[]" class="form-select">
|
||||
|
@ -279,6 +280,9 @@
|
|||
</td>
|
||||
`;
|
||||
tbody.appendChild(newRow);
|
||||
|
||||
// Set up validation for the new row
|
||||
setTimeout(setupPortValidation, 50);
|
||||
}
|
||||
|
||||
function removePortRow(button) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue