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:
taylanbakircioglu
2026-02-18 19:32:30 +03:00
parent f526c3b6b6
commit 16c502dc17
2 changed files with 43 additions and 19 deletions
+14 -14
View File
@@ -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>
);
},
},
+29 -5
View File
@@ -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) => {