enhance update form

Signed-off-by: mudler <mudler@localai.io>
This commit is contained in:
mudler
2025-03-17 16:13:03 +01:00
parent 3c3b5a774c
commit 29a8713427
5 changed files with 681 additions and 184 deletions

254
webui/public/css/wizard.css Normal file
View File

@@ -0,0 +1,254 @@
/* Agent Form Wizard Styles */
.agent-form-container {
display: flex;
gap: 2rem;
margin-bottom: 2rem;
}
/* Wizard Sidebar */
.wizard-sidebar {
width: 250px;
background: var(--surface);
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 1.5rem 0;
flex-shrink: 0;
}
.wizard-nav {
list-style: none;
padding: 0;
margin: 0;
}
.wizard-nav-item {
padding: 12px 20px;
cursor: pointer;
transition: all 0.2s ease;
border-left: 4px solid transparent;
display: flex;
align-items: center;
}
.wizard-nav-item i {
margin-right: 10px;
width: 20px;
text-align: center;
}
.wizard-nav-item:hover {
background: rgba(var(--primary-rgb), 0.1);
}
.wizard-nav-item.active {
background: rgba(var(--primary-rgb), 0.15);
border-left-color: var(--primary);
color: var(--primary);
font-weight: 600;
}
/* Form Content Area */
.form-content-area {
flex: 1;
padding: 1.5rem;
background: var(--surface);
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.section-title {
font-size: 1.5rem;
margin-bottom: 1.5rem;
padding-bottom: 0.75rem;
border-bottom: 1px solid rgba(var(--border-rgb), 0.5);
color: var(--text);
}
.form-section {
display: none;
}
.form-section.active {
display: block;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Improved input styles */
.mb-4 {
margin-bottom: 1.5rem;
}
.form-section label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: var(--text);
}
.form-section input[type="text"],
.form-section input[type="number"],
.form-section textarea,
.form-section select {
width: 100%;
padding: 10px 12px;
border-radius: 6px;
border: 1px solid rgba(var(--border-rgb), 0.8);
background-color: var(--input-bg);
color: var(--text);
font-size: 16px;
transition: border-color 0.2s ease;
}
.form-section textarea {
min-height: 120px;
resize: vertical;
}
.form-section input[type="text"]:focus,
.form-section input[type="number"]:focus,
.form-section textarea:focus,
.form-section select:focus {
border-color: var(--primary);
outline: none;
box-shadow: 0 0 0 2px rgba(var(--primary-rgb), 0.2);
}
/* Button Styles */
.button-container {
margin: 1.5rem 0;
}
.action-btn {
background: linear-gradient(135deg, var(--primary), var(--secondary));
color: white;
border: none;
padding: 10px 16px;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
justify-content: center;
}
.action-btn i {
margin-right: 6px;
}
.action-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
.action-btn:active {
transform: translateY(0);
}
/* Navigation controls - improved layout */
.wizard-controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 1.5rem;
padding-top: 1.5rem;
border-top: 1px solid rgba(var(--border-rgb), 0.5);
}
.wizard-controls-left {
flex: 1;
text-align: left;
}
.wizard-controls-center {
flex: 2;
text-align: center;
}
.wizard-controls-right {
flex: 1;
text-align: right;
}
.nav-btn {
background: var(--surface);
color: var(--text);
border: 1px solid rgba(var(--border-rgb), 0.8);
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
}
.nav-btn i {
margin-right: 6px;
}
.nav-btn:last-child i {
margin-right: 0;
margin-left: 6px;
}
.nav-btn:hover {
background: rgba(var(--primary-rgb), 0.1);
}
.progress-indicator {
display: inline-block;
font-size: 0.9rem;
color: var(--text-muted);
font-weight: 500;
margin-top: 0.5rem;
}
.progress-dots {
display: flex;
justify-content: center;
margin-bottom: 8px;
gap: 6px;
}
.progress-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: rgba(var(--border-rgb), 0.4);
transition: all 0.2s ease;
}
.progress-dot.active {
background-color: var(--primary);
transform: scale(1.2);
}
/* Responsive adjustments */
@media (max-width: 768px) {
.wizard-controls {
flex-direction: column;
gap: 1rem;
}
.wizard-controls-left,
.wizard-controls-center,
.wizard-controls-right {
width: 100%;
text-align: center;
}
.progress-dots {
margin: 12px 0;
}
}

139
webui/public/js/wizard.js Normal file
View File

@@ -0,0 +1,139 @@
/**
* Agent Form Wizard - Navigation and UI functionality
*/
document.addEventListener('DOMContentLoaded', function() {
// Check if the wizard exists on the page
const wizardSidebar = document.querySelector('.wizard-sidebar');
if (!wizardSidebar) return;
// Get all sections and nav items
const navItems = document.querySelectorAll('.wizard-nav-item');
const sections = document.querySelectorAll('.form-section');
const prevButton = document.getElementById('prevSection');
const nextButton = document.getElementById('nextSection');
const currentStepLabelEl = document.getElementById('currentStepLabel');
const progressDotsContainer = document.getElementById('progressDots');
// Create progress dots
const totalSteps = sections.length;
// Create dots for each section
if (progressDotsContainer) {
for (let i = 0; i < totalSteps; i++) {
const dot = document.createElement('div');
dot.className = 'progress-dot';
dot.setAttribute('data-index', i);
dot.addEventListener('click', () => setActiveSection(i));
progressDotsContainer.appendChild(dot);
}
}
// Get all progress dots
const progressDots = document.querySelectorAll('.progress-dot');
// Track current active section
let currentSectionIndex = 0;
// Initialize
updateNavigation();
// Add click events to nav items
navItems.forEach((item, index) => {
item.addEventListener('click', () => {
setActiveSection(index);
});
});
// Add click events to prev/next buttons
if (prevButton) {
prevButton.addEventListener('click', () => {
if (currentSectionIndex > 0) {
setActiveSection(currentSectionIndex - 1);
}
});
}
if (nextButton) {
nextButton.addEventListener('click', () => {
if (currentSectionIndex < sections.length - 1) {
setActiveSection(currentSectionIndex + 1);
}
});
}
/**
* Set the active section and update navigation
*/
function setActiveSection(index) {
// Remove active class from all sections and nav items
sections.forEach(section => section.classList.remove('active'));
navItems.forEach(item => item.classList.remove('active'));
progressDots.forEach(dot => dot.classList.remove('active'));
// Add active class to current section, nav item, and dot
sections[index].classList.add('active');
navItems[index].classList.add('active');
if (progressDots[index]) {
progressDots[index].classList.add('active');
}
// Update current section index
currentSectionIndex = index;
// Update navigation state
updateNavigation();
// Scroll to top of section
sections[index].scrollIntoView({behavior: 'smooth', block: 'start'});
}
/**
* Update navigation buttons and progress
*/
function updateNavigation() {
// Update section label
if (currentStepLabelEl && navItems[currentSectionIndex]) {
// Extract text content without the icon
const navText = navItems[currentSectionIndex].textContent.trim();
currentStepLabelEl.textContent = navText;
}
// Update prev/next buttons
if (prevButton) {
prevButton.disabled = currentSectionIndex === 0;
prevButton.style.opacity = currentSectionIndex === 0 ? 0.5 : 1;
}
if (nextButton) {
nextButton.disabled = currentSectionIndex === sections.length - 1;
nextButton.style.opacity = currentSectionIndex === sections.length - 1 ? 0.5 : 1;
// Change text for last step
if (currentSectionIndex === sections.length - 2) {
nextButton.innerHTML = 'Finish <i class="fas fa-check"></i>';
} else {
nextButton.innerHTML = 'Next <i class="fas fa-arrow-right"></i>';
}
}
}
// Helper function to validate current section before proceeding
function validateCurrentSection() {
// Implement validation logic here based on the current section
// Return true if valid, false if not
return true;
}
// Add to initAgentFormCommon function if it exists
if (typeof window.initAgentFormCommon === 'function') {
const originalInit = window.initAgentFormCommon;
window.initAgentFormCommon = function(options) {
// Call the original initialization function
originalInit(options);
// Now initialize the wizard navigation
setActiveSection(0);
};
}
});