feat: Integrate Pagination component into ASNsNewManager, DomainsNewManager, IPRangesManager, and FilterManager for improved navigation and user experience across multiple pages of data.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m46s

This commit is contained in:
2025-12-24 15:29:46 +07:00
parent f4a6ceed08
commit 6dfcaa584d
6 changed files with 162 additions and 261 deletions
+6 -41
View File
@@ -25,49 +25,14 @@ import {
IconWorld
} from '@tabler/icons-react';
import GraphView from './GraphView';
import {
makeGateway,
normalizeGateways,
needsGateways as NEEDS_GATEWAYS,
SERVER_TYPE_OPTIONS
} from './utils/serverUtils.js';
const API_URL = '/api';
const SERVER_TYPE_OPTIONS = [
{ value: 'jumphost', label: 'Jumphost' },
{ value: 'exit', label: 'Выходная нода' },
];
const NEEDS_GATEWAYS = (type) => ['jumphost', 'exit'].includes(String(type || '').toLowerCase());
const makeGateway = (over = {}) => ({
id: `${Date.now()}-${Math.random().toString(16).slice(2, 8)}`,
name: '',
ip: '',
comment: '',
primary: false,
...over,
});
const normalizeGateways = (gateways = [], fallbackName = '') => {
if (!Array.isArray(gateways)) return [];
const cleaned = gateways
.map((g, idx) => ({
id: g?.id || `${Date.now()}-${idx}`,
name: String(g?.name || '').trim(),
ip: String(g?.ip || '').trim(),
comment: String(g?.comment || '').trim(),
primary: Boolean(g?.primary),
}))
.filter(g => g.name || g.ip || g.comment);
if (cleaned.length === 0) {
return [{ id: `${Date.now()}-primary`, name: fallbackName || 'gateway', ip: '', comment: '', primary: true }];
}
// ensure single primary
let hasPrimary = false;
cleaned.forEach((g, i) => {
if (g.primary && !hasPrimary) {
hasPrimary = true;
} else {
g.primary = false;
}
});
if (!hasPrimary) cleaned[0].primary = true;
return cleaned;
};
function ServerManager() {
const [servers, setServers] = useState([]);