mirror of
https://github.com/taylanbakircioglu/haproxy-openmanager.git
synced 2026-09-28 13:09:29 +00:00
ui: improve backend servers column and cluster selector visibility
- Replace wrapping "active" text in Servers column with compact tag showing active/total count with tooltip for details - Add subtle pulse animation and dashed border to cluster selector when no cluster is selected to guide new users Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1047,28 +1047,28 @@ const BackendServers = () => {
|
||||
title: 'Servers',
|
||||
dataIndex: 'servers',
|
||||
key: 'servers',
|
||||
width: 100,
|
||||
render: (servers = []) => {
|
||||
// CRITICAL FIX: Handle null/undefined servers array for backends without servers
|
||||
if (!servers || !Array.isArray(servers)) {
|
||||
return (
|
||||
<Space>
|
||||
<Tag color="red">0</Tag>
|
||||
<span>/0</span>
|
||||
<Text type="secondary">active</Text>
|
||||
<Tooltip title="No servers configured. Please add at least one server.">
|
||||
<Tag color="warning" style={{ marginLeft: 4, fontSize: '10px' }}>⚠️ Empty</Tag>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
<Tooltip title="No servers configured. Please add at least one server.">
|
||||
<Tag color="red" style={{ cursor: 'pointer' }}>0 / 0</Tag>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
const activeServers = servers.filter(s => s.is_active).length;
|
||||
const totalServers = servers.length;
|
||||
const allActive = activeServers === totalServers;
|
||||
const tooltipText = `${activeServers} active / ${totalServers} total server${totalServers !== 1 ? 's' : ''}`;
|
||||
return (
|
||||
<Space>
|
||||
<Tag color="green">{activeServers}</Tag>
|
||||
<span>/{totalServers}</span>
|
||||
<Text type="secondary">active</Text>
|
||||
</Space>
|
||||
<Tooltip title={tooltipText}>
|
||||
<Tag
|
||||
color={allActive ? 'green' : 'orange'}
|
||||
style={{ cursor: 'default', fontWeight: 500 }}
|
||||
>
|
||||
{activeServers} / {totalServers}
|
||||
</Tag>
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -82,16 +82,40 @@ const ClusterSelector = () => {
|
||||
return Math.max(250, Math.min(estimated, 500));
|
||||
};
|
||||
|
||||
const isUnselected = !selectedCluster;
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', minWidth: 0 }}>
|
||||
<CloudServerOutlined style={{ color: '#1890ff', flexShrink: 0 }} />
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '10px',
|
||||
minWidth: 0,
|
||||
padding: '4px 12px',
|
||||
borderRadius: 8,
|
||||
background: isUnselected ? 'rgba(24, 144, 255, 0.06)' : 'rgba(24, 144, 255, 0.03)',
|
||||
border: isUnselected ? '1.5px dashed rgba(24, 144, 255, 0.45)' : '1px solid transparent',
|
||||
transition: 'all 0.3s ease',
|
||||
animation: isUnselected ? 'clusterPulse 2.5s ease-in-out infinite' : 'none',
|
||||
}}>
|
||||
<style>{`
|
||||
@keyframes clusterPulse {
|
||||
0%, 100% { border-color: rgba(24, 144, 255, 0.25); background: rgba(24, 144, 255, 0.04); }
|
||||
50% { border-color: rgba(24, 144, 255, 0.55); background: rgba(24, 144, 255, 0.09); }
|
||||
}
|
||||
`}</style>
|
||||
<CloudServerOutlined style={{ color: '#1890ff', flexShrink: 0, fontSize: 16 }} />
|
||||
{isUnselected && (
|
||||
<span style={{ fontSize: 12, color: '#1890ff', fontWeight: 500, whiteSpace: 'nowrap', flexShrink: 0 }}>
|
||||
Cluster:
|
||||
</span>
|
||||
)}
|
||||
<Select
|
||||
value={selectedCluster?.id}
|
||||
showSearch
|
||||
style={{
|
||||
style={{
|
||||
width: getSelectWidth(),
|
||||
minWidth: 180,
|
||||
maxWidth: 500
|
||||
minWidth: 180,
|
||||
maxWidth: 500,
|
||||
}}
|
||||
placeholder="Select HAProxy Cluster"
|
||||
onChange={(clusterId) => {
|
||||
|
||||
Reference in New Issue
Block a user