mirror of
https://github.com/taylanbakircioglu/haproxy-openmanager.git
synced 2026-10-12 15:49:26 +00:00
feat: add intelligent HAProxy validation error display in UI
- Add haproxy_error_parser.py: Parses HAProxy validation errors with confidence scoring, extracts entity type/name, line number, error type - Add ValidationErrorModal.js: Rich modal with parsed error summary, quick fix suggestions, and manual troubleshooting guide - Update cluster.py: Integrate error parser into agent-sync and config-versions endpoints with graceful fallback - Update ApplyManagement.js: Add validation error banner with quick navigation buttons and error detail modal - Update FrontendManagement.js & BackendServers.js: Handle URL params for deep-linking to entity edit forms with field highlighting Enables users to see actionable validation failure details directly in the UI without needing server access for debugging.
This commit is contained in:
@@ -12,7 +12,7 @@ import {
|
||||
WarningOutlined, SearchOutlined, HistoryOutlined, PlayCircleOutlined, LoadingOutlined
|
||||
} from '@ant-design/icons';
|
||||
import axios from 'axios';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useCluster } from '../contexts/ClusterContext';
|
||||
import { VersionHistory } from './VersionHistory';
|
||||
|
||||
@@ -60,6 +60,7 @@ const { TextArea } = Input;
|
||||
const FrontendManagement = () => {
|
||||
const { selectedCluster } = useCluster();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const [frontends, setFrontends] = useState([]);
|
||||
const [backends, setBackends] = useState([]);
|
||||
const [sslCertificates, setSslCertificates] = useState([]);
|
||||
@@ -162,6 +163,37 @@ const FrontendManagement = () => {
|
||||
checkPendingChanges();
|
||||
}, [selectedCluster]);
|
||||
|
||||
// Handle URL parameters for quick edit navigation (from validation error modal)
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(location.search);
|
||||
const editId = params.get('edit');
|
||||
const highlightField = params.get('highlight');
|
||||
|
||||
if (editId && frontends.length > 0) {
|
||||
const frontendToEdit = frontends.find(f => f.id === parseInt(editId));
|
||||
if (frontendToEdit) {
|
||||
// Open edit modal for the frontend
|
||||
setEditingFrontend(frontendToEdit);
|
||||
form.setFieldsValue({
|
||||
...frontendToEdit,
|
||||
ssl_enabled: frontendToEdit.ssl_enabled || false,
|
||||
ssl_certificate_ids: frontendToEdit.ssl_certificate_ids || [],
|
||||
acl_rules: frontendToEdit.acl_rules || [],
|
||||
use_backend_rules: frontendToEdit.use_backend_rules || [],
|
||||
});
|
||||
setModalVisible(true);
|
||||
|
||||
// Clear URL params after opening modal
|
||||
navigate(location.pathname, { replace: true });
|
||||
|
||||
// Show notification about which field to check
|
||||
if (highlightField) {
|
||||
message.info(`Please check the "${highlightField}" field - it may have caused a validation error.`, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [location.search, frontends]);
|
||||
|
||||
const fetchFrontends = async () => {
|
||||
// CRITICAL FIX: Don't fetch if no cluster selected to prevent race condition
|
||||
// Same race condition as BackendServers - prevents all frontends from appearing
|
||||
|
||||
Reference in New Issue
Block a user