refactor(NetworkConfigManager): improve layout and styling of server cards for better user experience and readability
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m47s

This commit is contained in:
2026-01-25 14:08:30 +07:00
parent 3b858441a2
commit 4feb84338a
+18 -25
View File
@@ -2242,23 +2242,17 @@ function NetworkConfigManager() {
const isUnassigned = serverId === '__unassigned__'; const isUnassigned = serverId === '__unassigned__';
return ( return (
<div key={serverId} className="mb-4"> <div key={serverId} className="card mb-3">
{/* Server header - улучшенная структура с четкой иерархией */} {/* Server header - улучшенная структура с четкой иерархией */}
<div
className="card mb-3"
style={{
borderLeft: '4px solid rgba(32, 107, 196, 0.3)',
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.08)'
}}
>
<div <div
className="card-header py-3 px-4" className="card-header py-3 px-4"
style={{ style={{
backgroundColor: 'rgba(32, 107, 196, 0.06)', backgroundColor: 'rgba(32, 107, 196, 0.06)',
borderBottom: '1px solid rgba(32, 107, 196, 0.15)' borderBottom: '1px solid rgba(32, 107, 196, 0.15)',
borderLeft: '4px solid rgba(32, 107, 196, 0.3)'
}} }}
> >
<div className="d-flex align-items-start justify-content-between"> <div className="d-flex align-items-start flex-wrap gap-3">
{/* Левая часть: основная информация */} {/* Левая часть: основная информация */}
<div className="d-flex align-items-start flex-grow-1" style={{ minWidth: 0 }}> <div className="d-flex align-items-start flex-grow-1" style={{ minWidth: 0 }}>
{isUnassigned ? ( {isUnassigned ? (
@@ -2267,7 +2261,7 @@ function NetworkConfigManager() {
<IconServer size={24} className="text-muted" /> <IconServer size={24} className="text-muted" />
</span> </span>
<div className="flex-grow-1"> <div className="flex-grow-1">
<h3 className="mb-1 fw-bold text-muted">Без привязки к серверу</h3> <h3 className="mb-0 fw-bold text-muted">Без привязки к серверу</h3>
</div> </div>
</> </>
) : ( ) : (
@@ -2278,17 +2272,17 @@ function NetworkConfigManager() {
<div className="flex-grow-1" style={{ minWidth: 0 }}> <div className="flex-grow-1" style={{ minWidth: 0 }}>
{/* Основная строка: название сервера */} {/* Основная строка: название сервера */}
<div className="d-flex align-items-center mb-2 flex-wrap gap-2"> <div className="d-flex align-items-center mb-2 flex-wrap gap-2">
<h3 className="mb-0 fw-bold" style={{ fontSize: '1.25rem' }}> <h3 className="mb-0 fw-bold" style={{ fontSize: '1.25rem', lineHeight: '1.3' }}>
{server?.dns ? server.dns.split('.')[0] : (server?.name || serverId)} {server?.dns ? server.dns.split('.')[0] : (server?.name || serverId)}
</h3> </h3>
{server?.country && ( {server?.country && (
<span className="badge bg-blue-lt text-blue d-flex align-items-center" style={{ fontSize: '0.875rem', padding: '4px 10px' }}> <span className="badge bg-blue-lt text-blue d-flex align-items-center flex-shrink-0" style={{ fontSize: '0.875rem', padding: '4px 10px' }}>
<span className="me-1" style={{ fontSize: '1rem' }}>{countryToFlag(server.country)}</span> <span className="me-1" style={{ fontSize: '1rem' }}>{countryToFlag(server.country)}</span>
{server.country} {server.country}
</span> </span>
)} )}
{server?.provider && ( {server?.provider && (
<span className={`badge bg-${getProviderColor(server.provider)}-lt text-${getProviderColor(server.provider)}`} style={{ fontSize: '0.875rem', padding: '4px 10px' }}> <span className={`badge bg-${getProviderColor(server.provider)}-lt text-${getProviderColor(server.provider)} flex-shrink-0`} style={{ fontSize: '0.875rem', padding: '4px 10px' }}>
{server.provider} {server.provider}
</span> </span>
)} )}
@@ -2297,15 +2291,15 @@ function NetworkConfigManager() {
{/* Дополнительная информация: DNS и IP */} {/* Дополнительная информация: DNS и IP */}
<div className="d-flex align-items-center flex-wrap gap-3" style={{ fontSize: '0.875rem' }}> <div className="d-flex align-items-center flex-wrap gap-3" style={{ fontSize: '0.875rem' }}>
{server?.dns && ( {server?.dns && (
<div className="d-flex align-items-center"> <div className="d-flex align-items-center flex-shrink-0">
<span className="text-muted me-1">DNS:</span> <span className="text-muted me-1">DNS:</span>
<code className="text-dark" style={{ fontSize: '0.875rem', backgroundColor: 'rgba(0, 0, 0, 0.04)', padding: '2px 6px', borderRadius: '4px' }}> <code className="text-dark" style={{ fontSize: '0.875rem', backgroundColor: 'rgba(0, 0, 0, 0.04)', padding: '2px 6px', borderRadius: '4px', wordBreak: 'break-all' }}>
{server.dns} {server.dns}
</code> </code>
</div> </div>
)} )}
{server?.ip && ( {server?.ip && (
<div className="d-flex align-items-center"> <div className="d-flex align-items-center flex-shrink-0">
<span className="text-muted me-1">IP:</span> <span className="text-muted me-1">IP:</span>
<code className="text-dark" style={{ fontSize: '0.875rem', backgroundColor: 'rgba(0, 0, 0, 0.04)', padding: '2px 6px', borderRadius: '4px' }}> <code className="text-dark" style={{ fontSize: '0.875rem', backgroundColor: 'rgba(0, 0, 0, 0.04)', padding: '2px 6px', borderRadius: '4px' }}>
{server.ip} {server.ip}
@@ -2319,13 +2313,13 @@ function NetworkConfigManager() {
</div> </div>
{/* Правая часть: счетчик и действия */} {/* Правая часть: счетчик и действия */}
<div className="d-flex align-items-center gap-2 flex-shrink-0 ms-3"> <div className="d-flex align-items-center gap-2 flex-shrink-0">
<span className="badge bg-primary text-white" style={{ fontSize: '0.875rem', padding: '6px 12px', fontWeight: '600' }}> <span className="badge bg-primary text-white" style={{ fontSize: '0.875rem', padding: '6px 12px', fontWeight: '600', whiteSpace: 'nowrap' }}>
{items.length} {type === 'gateway' ? (items.length === 1 ? 'gateway' : 'gateways') : (items.length === 1 ? 'интерфейс' : 'интерфейсов')} {items.length} {type === 'gateway' ? (items.length === 1 ? 'gateway' : 'gateways') : (items.length === 1 ? 'интерфейс' : 'интерфейсов')}
</span> </span>
{type === 'interface' && !isUnassigned && items.length > 0 && ( {type === 'interface' && !isUnassigned && items.length > 0 && (
<button <button
className="btn btn-primary btn-sm" className="btn btn-primary btn-sm flex-shrink-0"
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
handleGenerateMikrotikCodeForServer(serverId, type); handleGenerateMikrotikCodeForServer(serverId, type);
@@ -2348,7 +2342,7 @@ function NetworkConfigManager() {
<small>Нет элементов для отображения</small> <small>Нет элементов для отображения</small>
</div> </div>
) : ( ) : (
<div className="row g-3"> <div className="row row-cards g-3">
{items.map(item => ( {items.map(item => (
<div key={item.id} className="col-12 col-lg-6"> <div key={item.id} className="col-12 col-lg-6">
{type === 'gateway' ? renderGatewayCard(item) : {type === 'gateway' ? renderGatewayCard(item) :
@@ -2360,7 +2354,6 @@ function NetworkConfigManager() {
)} )}
</div> </div>
</div> </div>
</div>
); );
}; };
@@ -2410,7 +2403,7 @@ function NetworkConfigManager() {
const IndicatorIcon = IconDatabase; const IndicatorIcon = IconDatabase;
return ( return (
<div className="card mb-2" style={{ borderRadius: '12px', maxWidth: '100%' }}> <div className="card" style={{ borderRadius: '12px', maxWidth: '100%' }}>
<div className="card-body p-0"> <div className="card-body p-0">
<div className="d-flex align-items-stretch"> <div className="d-flex align-items-stretch">
{/* Левая часть: тип индикатора */} {/* Левая часть: тип индикатора */}
@@ -2536,7 +2529,7 @@ function NetworkConfigManager() {
} }
return ( return (
<div className="card mb-2" style={{ borderRadius: '12px', maxWidth: '100%' }}> <div className="card" style={{ borderRadius: '12px', maxWidth: '100%' }}>
<div className="card-body p-0"> <div className="card-body p-0">
<div className="d-flex align-items-stretch"> <div className="d-flex align-items-stretch">
{/* Левая часть: тип индикатора (как в ServerCard) */} {/* Левая часть: тип индикатора (как в ServerCard) */}
@@ -2662,7 +2655,7 @@ function NetworkConfigManager() {
const displayIp = displayRemoteIp !== '—' ? displayRemoteIp : displayLocalIp; const displayIp = displayRemoteIp !== '—' ? displayRemoteIp : displayLocalIp;
return ( return (
<div className="card mb-2" style={{ borderRadius: '12px', maxWidth: '100%' }}> <div className="card" style={{ borderRadius: '12px', maxWidth: '100%' }}>
<div className="card-body p-0"> <div className="card-body p-0">
<div className="d-flex align-items-stretch"> <div className="d-flex align-items-stretch">
{/* Левая часть: тип интерфейса (как в ServerCard) */} {/* Левая часть: тип интерфейса (как в ServerCard) */}