fix(ui): Various

This commit is contained in:
Richard Palethorpe
2025-03-27 11:45:50 +00:00
parent 11231f23ea
commit c96c8d8009
17 changed files with 204 additions and 378 deletions

View File

@@ -6,12 +6,7 @@ import ConfigForm from './ConfigForm';
* Renders action configuration forms based on field group metadata
*/
const ActionForm = ({ actions = [], onChange, onRemove, onAdd, fieldGroups = [] }) => {
// Debug logging
console.log('ActionForm:', { actions, fieldGroups });
// Handle action change
const handleActionChange = (index, updatedAction) => {
console.log('Action change:', { index, updatedAction });
onChange(index, updatedAction);
};

View File

@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { useNavigate, useOutletContext } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
// Import form sections
import BasicInfoSection from './agent-form-sections/BasicInfoSection';
@@ -10,6 +10,7 @@ import MemorySettingsSection from './agent-form-sections/MemorySettingsSection';
import ModelSettingsSection from './agent-form-sections/ModelSettingsSection';
import PromptsGoalsSection from './agent-form-sections/PromptsGoalsSection';
import AdvancedSettingsSection from './agent-form-sections/AdvancedSettingsSection';
import ExportSection from './agent-form-sections/ExportSection';
const AgentForm = ({
isEdit = false,
@@ -20,10 +21,9 @@ const AgentForm = ({
submitButtonText,
isGroupForm = false,
noFormWrapper = false,
metadata = null
metadata = null,
}) => {
const navigate = useNavigate();
const { showToast } = useOutletContext();
const [activeSection, setActiveSection] = useState(isGroupForm ? 'model-section' : 'basic-section');
// Handle input changes
@@ -57,16 +57,27 @@ const AgentForm = ({
// Handle navigation between sections
const handleSectionChange = (section) => {
console.log('Changing section to:', section);
setActiveSection(section);
};
// Handle connector change (simplified)
const handleConnectorChange = (index, updatedConnector) => {
const updatedConnectors = [...formData.connectors];
updatedConnectors[index] = updatedConnector;
setFormData({
...formData,
connectors: updatedConnectors
});
};
// Handle adding a connector
const handleAddConnector = () => {
setFormData({
...formData,
connectors: [
...(formData.connectors || []),
{ name: '', config: '{}' }
{ type: '', config: '{}' }
]
});
};
@@ -81,55 +92,6 @@ const AgentForm = ({
});
};
// Handle connector name change
const handleConnectorNameChange = (index, value) => {
const updatedConnectors = [...formData.connectors];
updatedConnectors[index] = {
...updatedConnectors[index],
type: value
};
setFormData({
...formData,
connectors: updatedConnectors
});
};
// Handle connector config change
const handleConnectorConfigChange = (index, key, value) => {
const updatedConnectors = [...formData.connectors];
const currentConnector = updatedConnectors[index];
// Parse the current config if it's a string
let currentConfig = {};
if (typeof currentConnector.config === 'string') {
try {
currentConfig = JSON.parse(currentConnector.config);
} catch (err) {
console.error('Error parsing config:', err);
currentConfig = {};
}
} else if (currentConnector.config) {
currentConfig = currentConnector.config;
}
// Update the config with the new key-value pair
currentConfig = {
...currentConfig,
[key]: value
};
// Update the connector with the stringified config
updatedConnectors[index] = {
...currentConnector,
config: JSON.stringify(currentConfig)
};
setFormData({
...formData,
connectors: updatedConnectors
});
};
// Handle adding an MCP server
const handleAddMCPServer = () => {
setFormData({
@@ -231,6 +193,17 @@ const AgentForm = ({
<i className="fas fa-cogs"></i>
Advanced Settings
</li>
{isEdit && (
<>
<li
className={`wizard-nav-item ${activeSection === 'export-section' ? 'active' : ''}`}
onClick={() => handleSectionChange('export-section')}
>
<i className="fas fa-file-export"></i>
Export Data
</li>
</>
)}
</ul>
</div>
@@ -248,7 +221,7 @@ const AgentForm = ({
</div>
<div style={{ display: activeSection === 'connectors-section' ? 'block' : 'none' }}>
<ConnectorsSection formData={formData} handleAddConnector={handleAddConnector} handleRemoveConnector={handleRemoveConnector} handleConnectorNameChange={handleConnectorNameChange} handleConnectorConfigChange={handleConnectorConfigChange} metadata={metadata} />
<ConnectorsSection formData={formData} handleAddConnector={handleAddConnector} handleRemoveConnector={handleRemoveConnector} handleConnectorChange={handleConnectorChange} metadata={metadata} />
</div>
<div style={{ display: activeSection === 'actions-section' ? 'block' : 'none' }}>
@@ -270,6 +243,14 @@ const AgentForm = ({
<div style={{ display: activeSection === 'advanced-section' ? 'block' : 'none' }}>
<AdvancedSettingsSection formData={formData} handleInputChange={handleInputChange} metadata={metadata} />
</div>
{isEdit && (
<>
<div style={{ display: activeSection === 'export-section' ? 'block' : 'none' }}>
<ExportSection agentName={formData.name} />
</div>
</>
)}
</div>
) : (
<form className="agent-form" onSubmit={handleSubmit} noValidate>
@@ -283,7 +264,7 @@ const AgentForm = ({
</div>
<div style={{ display: activeSection === 'connectors-section' ? 'block' : 'none' }}>
<ConnectorsSection formData={formData} handleAddConnector={handleAddConnector} handleRemoveConnector={handleRemoveConnector} handleConnectorNameChange={handleConnectorNameChange} handleConnectorConfigChange={handleConnectorConfigChange} metadata={metadata} />
<ConnectorsSection formData={formData} handleAddConnector={handleAddConnector} handleRemoveConnector={handleRemoveConnector} handleConnectorChange={handleConnectorChange} metadata={metadata} />
</div>
<div style={{ display: activeSection === 'actions-section' ? 'block' : 'none' }}>
@@ -306,13 +287,21 @@ const AgentForm = ({
<AdvancedSettingsSection formData={formData} handleInputChange={handleInputChange} metadata={metadata} />
</div>
{isEdit && (
<>
<div style={{ display: activeSection === 'export-section' ? 'block' : 'none' }}>
<ExportSection agentName={formData.name} />
</div>
</>
)}
{/* Form Controls */}
<div className="form-actions">
<button type="button" className="btn btn-secondary" onClick={() => navigate('/agents')}>
Cancel
<div className="form-actions" style={{ display: 'flex', gap: '1rem', justifyContent: 'flex-end' }}>
<button type="button" className="action-btn" onClick={() => navigate('/agents')}>
<i className="fas fa-times"></i> Cancel
</button>
<button type="submit" className="btn btn-primary" disabled={loading}>
{submitButtonText || (isEdit ? 'Update Agent' : 'Create Agent')}
<button type="submit" className="action-btn" disabled={loading}>
<i className="fas fa-save"></i> {submitButtonText || (isEdit ? 'Update Agent' : 'Create Agent')}
</button>
</div>
</form>

View File

@@ -24,9 +24,6 @@ const ConfigForm = ({
typeField = 'type',
addButtonText = 'Add Item'
}) => {
// Debug logging
console.log(`ConfigForm for ${itemType}:`, { items, fieldGroups });
// Generate options from fieldGroups
const typeOptions = [
{ value: '', label: `Select a ${itemType} type` },
@@ -35,8 +32,6 @@ const ConfigForm = ({
label: group.label
}))
];
console.log(`${itemType} type options:`, typeOptions);
// Parse the config JSON string to an object
const parseConfig = (item) => {
@@ -82,15 +77,13 @@ const ConfigForm = ({
// Find the field group that matches this item's type
const fieldGroup = fieldGroups.find(group => group.name === itemTypeName);
console.log(`Item ${index} type: ${itemTypeName}, Found field group:`, fieldGroup);
return (
<div key={index} className="config-item mb-4 card">
<div className="config-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1rem' }}>
<h4 style={{ margin: 0 }}>{itemType.charAt(0).toUpperCase() + itemType.slice(1)} #{index + 1}</h4>
<button
type="button"
className="remove-btn"
className="action-btn delete-btn"
onClick={() => onRemove(index)}
>
<i className="fas fa-times"></i>
@@ -134,7 +127,7 @@ const ConfigForm = ({
<button
type="button"
className="add-btn"
className="action-btn"
onClick={onAdd}
>
<i className="fas fa-plus"></i> {addButtonText}

View File

@@ -9,36 +9,16 @@ function ConnectorForm({
connectors = [],
onAddConnector,
onRemoveConnector,
onConnectorNameChange,
onConnectorConfigChange,
onChange,
fieldGroups = []
}) {
// Debug logging
console.log('ConnectorForm:', { connectors, fieldGroups });
// Handle connector change
const handleConnectorChange = (index, updatedConnector) => {
console.log('Connector change:', { index, updatedConnector });
if (updatedConnector.type !== connectors[index].type) {
onConnectorNameChange(index, updatedConnector.type);
} else {
onConnectorConfigChange(index, updatedConnector.config);
}
};
// Handle adding a new connector
const handleAddConnector = () => {
console.log('Adding new connector');
onAddConnector();
};
return (
<ConfigForm
items={connectors}
fieldGroups={fieldGroups}
onChange={handleConnectorChange}
onChange={onChange}
onRemove={onRemoveConnector}
onAdd={handleAddConnector}
onAdd={onAddConnector}
itemType="connector"
typeField="type"
addButtonText="Add Connector"

View File

@@ -8,8 +8,7 @@ const ConnectorsSection = ({
formData,
handleAddConnector,
handleRemoveConnector,
handleConnectorNameChange,
handleConnectorConfigChange,
handleConnectorChange,
metadata
}) => {
return (
@@ -23,8 +22,7 @@ const ConnectorsSection = ({
connectors={formData.connectors || []}
onAddConnector={handleAddConnector}
onRemoveConnector={handleRemoveConnector}
onConnectorNameChange={handleConnectorNameChange}
onConnectorConfigChange={handleConnectorConfigChange}
onChange={handleConnectorChange}
fieldGroups={metadata?.connectors || []}
/>
</div>

View File

@@ -0,0 +1,28 @@
import React, { useEffect } from 'react';
const ExportSection = ({ agentName }) => {
useEffect(() => {
console.log('ExportSection rendered with agentName:', agentName);
}, [agentName]);
return (
<div className="">
<div className="section-title">
<h2>Export Data</h2>
</div>
<div className="section-content">
<p className="mb-4">Export your agent configuration for backup or transfer.</p>
<a
href={`/settings/export/${agentName}`}
className="action-btn"
style={{ display: 'inline-flex', alignItems: 'center', textDecoration: 'none' }}
>
<i className="fas fa-file-export"></i> Export Configuration
</a>
</div>
</div>
);
};
export default ExportSection;

View File

@@ -46,7 +46,7 @@ const MCPServersSection = ({
<h4>MCP Server #{index + 1}</h4>
<button
type="button"
className="remove-btn"
className="action-btn delete-btn"
onClick={() => handleRemoveMCPServer(index)}
>
<i className="fas fa-times"></i>
@@ -64,7 +64,7 @@ const MCPServersSection = ({
<button
type="button"
className="add-btn"
className="action-btn"
onClick={handleAddMCPServer}
>
<i className="fas fa-plus"></i> Add MCP Server

View File

@@ -7,3 +7,5 @@ export { default as MemorySettingsSection } from './MemorySettingsSection';
export { default as PromptsGoalsSection } from './PromptsGoalsSection';
export { default as AdvancedSettingsSection } from './AdvancedSettingsSection';
export { default as FormNavSidebar } from './FormNavSidebar';
export { default as ExportSection } from './ExportSection';
export { default as ControlSection } from './ControlSection';

View File

@@ -1,221 +1,5 @@
/* Agent Form Section Styles */
.form-section {
padding: 1.5rem;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 1.5rem;
}
.section-title {
font-size: 1.5rem;
margin-bottom: 1.5rem;
color: #333;
border-bottom: 1px solid #eee;
padding-bottom: 0.5rem;
}
.section-description {
color: #666;
color: #cecece;
margin-bottom: 1.5rem;
}
.hidden {
display: none;
}
.active {
display: block;
}
/* Form Controls */
.form-controls {
display: flex;
justify-content: flex-end;
margin-top: 2rem;
padding: 1rem;
background-color: #f8f9fa;
border-top: 1px solid #eee;
}
.submit-btn {
background-color: #4a6cf7;
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 4px;
cursor: pointer;
font-weight: 600;
transition: background-color 0.2s;
}
.submit-btn:hover {
background-color: #3a5ce5;
}
.submit-btn:disabled {
background-color: #a0a0a0;
cursor: not-allowed;
}
/* Error Message */
.error-message {
background-color: #f8d7da;
color: #721c24;
padding: 1rem;
border-radius: 4px;
margin-bottom: 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.close-btn {
background: none;
border: none;
color: #721c24;
cursor: pointer;
font-size: 1rem;
}
/* Navigation Sidebar */
.wizard-sidebar {
width: 250px;
background-color: #f8f9fa;
border-right: 1px solid #eee;
padding: 1.5rem 0;
}
.wizard-nav {
list-style: none;
padding: 0;
margin: 0;
}
.wizard-nav-item {
padding: 0.75rem 1.5rem;
cursor: pointer;
transition: background-color 0.2s;
display: flex;
align-items: center;
gap: 0.75rem;
}
.wizard-nav-item:hover {
background-color: #e9ecef;
}
.wizard-nav-item.active {
background-color: #e9ecef;
border-left: 4px solid #4a6cf7;
font-weight: 600;
}
.wizard-nav-item i {
width: 20px;
text-align: center;
}
/* Form Layout */
.agent-form-container {
display: flex;
min-height: 80vh;
border: 1px solid #eee;
border-radius: 8px;
overflow: hidden;
}
.form-content-area {
flex: 1;
padding: 1.5rem;
overflow-y: auto;
}
/* Input Styles */
input[type="text"],
input[type="password"],
input[type="number"],
textarea,
select {
width: 100%;
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
margin-top: 0.25rem;
}
textarea {
min-height: 100px;
resize: vertical;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
}
.checkbox-label {
display: flex;
align-items: center;
gap: 0.5rem;
cursor: pointer;
}
.checkbox-label input[type="checkbox"] {
margin: 0;
}
/* Add and Remove Buttons */
.add-btn,
.remove-btn {
background: none;
border: none;
cursor: pointer;
transition: color 0.2s;
}
.add-btn {
color: #4a6cf7;
font-weight: 600;
padding: 0.5rem 0;
display: flex;
align-items: center;
gap: 0.5rem;
}
.add-btn:hover {
color: #3a5ce5;
}
.remove-btn {
color: #dc3545;
}
.remove-btn:hover {
color: #c82333;
}
/* Item Containers */
.action-item,
.mcp-server-item {
border: 1px solid #eee;
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
}
.action-header,
.mcp-server-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.action-header h4,
.mcp-server-header h4 {
margin: 0;
}

View File

@@ -33,6 +33,9 @@ const FormFieldDefinition = ({
helpText={field.helpText || ''}
options={field.options || []}
required={field.required || false}
min={field.min || 0}
max={field.max || 2**31}
step={field.step || 1}
/>
</div>
))}