feat: Revamp Dashboard component with new icons, improved layout, and quick action links for enhanced user navigation and experience
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 6m14s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 6m14s
This commit is contained in:
+40
-74
@@ -1,21 +1,22 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import {
|
import {
|
||||||
IconWorld,
|
IconWorld,
|
||||||
IconNetwork,
|
IconNetwork,
|
||||||
IconServer,
|
IconServer,
|
||||||
IconDatabase,
|
|
||||||
IconActivity,
|
|
||||||
IconTrendingUp,
|
|
||||||
IconTrendingDown,
|
|
||||||
IconClock,
|
IconClock,
|
||||||
IconMapPin,
|
IconMapPin,
|
||||||
IconCloud,
|
IconCloud,
|
||||||
IconShield,
|
IconShield,
|
||||||
IconAlertTriangle
|
IconAlertTriangle,
|
||||||
|
IconRefresh,
|
||||||
|
IconFilter,
|
||||||
|
IconDownload,
|
||||||
|
IconCreditCard
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
|
|
||||||
function StatCard({ icon: Icon, color, value, title, subtitle, trend, trendValue }) {
|
function StatCard({ icon: Icon, color, value, title, subtitle }) {
|
||||||
return (
|
return (
|
||||||
<div className="card h-100">
|
<div className="card h-100">
|
||||||
<div className="card-body d-flex align-items-center">
|
<div className="card-body d-flex align-items-center">
|
||||||
@@ -25,12 +26,6 @@ function StatCard({ icon: Icon, color, value, title, subtitle, trend, trendValue
|
|||||||
<div className="flex-grow-1">
|
<div className="flex-grow-1">
|
||||||
<div className="h3 mb-0 fw-bold">{value} <span className="fs-5 fw-normal">{title}</span></div>
|
<div className="h3 mb-0 fw-bold">{value} <span className="fs-5 fw-normal">{title}</span></div>
|
||||||
<div className="text-muted lh-1">{subtitle}</div>
|
<div className="text-muted lh-1">{subtitle}</div>
|
||||||
{trend && (
|
|
||||||
<div className={`mt-2 d-flex align-items-center ${trend === 'up' ? 'text-success' : 'text-danger'}`}>
|
|
||||||
{trend === 'up' ? <IconTrendingUp size={16} /> : <IconTrendingDown size={16} />}
|
|
||||||
<span className="ms-1 small">{trendValue}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -158,16 +153,13 @@ function Dashboard() {
|
|||||||
<div className="page-header d-print-none mb-4">
|
<div className="page-header d-print-none mb-4">
|
||||||
<div className="row align-items-center">
|
<div className="row align-items-center">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<h2 className="page-title">Dashboard</h2>
|
<h2 className="page-title">Панель</h2>
|
||||||
<div className="page-pretitle">Главная / Dashboard</div>
|
<div className="page-pretitle">Краткая сводка по данным</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-auto ms-auto d-print-none">
|
<div className="col-auto ms-auto d-print-none">
|
||||||
<div className="btn-list">
|
<button className="btn btn-outline-primary" onClick={() => window.location.reload()}>
|
||||||
<button className="btn btn-primary">
|
<IconRefresh className="me-2" /> Обновить
|
||||||
<IconActivity className="icon" />
|
</button>
|
||||||
Обновить данные
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -181,8 +173,6 @@ function Dashboard() {
|
|||||||
value={loading ? '...' : stats.domainsCount ?? '—'}
|
value={loading ? '...' : stats.domainsCount ?? '—'}
|
||||||
title="Доменов"
|
title="Доменов"
|
||||||
subtitle="Всего доменов в системе"
|
subtitle="Всего доменов в системе"
|
||||||
trend="up"
|
|
||||||
trendValue="+12% за неделю"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-3">
|
<div className="col-md-3">
|
||||||
@@ -192,8 +182,6 @@ function Dashboard() {
|
|||||||
value={loading ? '...' : stats.ipRangesCount ?? '—'}
|
value={loading ? '...' : stats.ipRangesCount ?? '—'}
|
||||||
title="IP-диапазонов"
|
title="IP-диапазонов"
|
||||||
subtitle="Всего IP диапазонов"
|
subtitle="Всего IP диапазонов"
|
||||||
trend="up"
|
|
||||||
trendValue="+5% за неделю"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-3">
|
<div className="col-md-3">
|
||||||
@@ -203,8 +191,6 @@ function Dashboard() {
|
|||||||
value={loading ? '...' : stats.asnsCount ?? '—'}
|
value={loading ? '...' : stats.asnsCount ?? '—'}
|
||||||
title="AS"
|
title="AS"
|
||||||
subtitle="Всего Autonomous Systems"
|
subtitle="Всего Autonomous Systems"
|
||||||
trend="down"
|
|
||||||
trendValue="-2% за неделю"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-3">
|
<div className="col-md-3">
|
||||||
@@ -214,8 +200,6 @@ function Dashboard() {
|
|||||||
value={loading ? '...' : stats.serversCount ?? '—'}
|
value={loading ? '...' : stats.serversCount ?? '—'}
|
||||||
title="Серверов"
|
title="Серверов"
|
||||||
subtitle="Всего серверов"
|
subtitle="Всего серверов"
|
||||||
trend="up"
|
|
||||||
trendValue="+8% за неделю"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -252,60 +236,42 @@ function Dashboard() {
|
|||||||
<div className="col-md-2">
|
<div className="col-md-2">
|
||||||
<MetricCard
|
<MetricCard
|
||||||
title="Последнее обновление"
|
title="Последнее обновление"
|
||||||
value={loading ? '...' : (stats.lastModified ? new Date(stats.lastModified).toLocaleString() : '—')}
|
value={loading ? '...' : (stats.lastModified ? stats.lastModified : '—')}
|
||||||
icon={IconClock}
|
icon={IconClock}
|
||||||
color="orange"
|
color="orange"
|
||||||
description="S3 синхронизация"
|
description="S3 синхронизация"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-2">
|
|
||||||
<MetricCard
|
|
||||||
title="Активность"
|
|
||||||
value="98%"
|
|
||||||
icon={IconActivity}
|
|
||||||
color="purple"
|
|
||||||
description="Система работает"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-2">
|
|
||||||
<MetricCard
|
|
||||||
title="API статус"
|
|
||||||
value={loading ? '...' : (error ? 'Ошибка' : 'ОК')}
|
|
||||||
icon={IconDatabase}
|
|
||||||
color={loading ? 'secondary' : (error ? 'danger' : 'success')}
|
|
||||||
description={error ? 'Проблемы с подключением' : 'Все API работают'}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Графики и диаграммы (заглушки для будущего) */}
|
{/* Быстрые действия */}
|
||||||
<div className="row g-3">
|
<div className="card">
|
||||||
<div className="col-md-6">
|
<div className="card-header">
|
||||||
<div className="card">
|
<h3 className="card-title">Быстрые действия</h3>
|
||||||
<div className="card-header">
|
|
||||||
<h3 className="card-title">Распределение по странам</h3>
|
|
||||||
</div>
|
|
||||||
<div className="card-body">
|
|
||||||
<div className="text-center text-muted py-4">
|
|
||||||
<IconMapPin size={48} className="mb-3" />
|
|
||||||
<p>График распределения серверов по странам</p>
|
|
||||||
<small>Будет добавлен в следующем обновлении</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-6">
|
<div className="card-body">
|
||||||
<div className="card">
|
<div className="btn-list">
|
||||||
<div className="card-header">
|
<Link to="/domains" className="btn btn-outline-primary">
|
||||||
<h3 className="card-title">Активность обновлений</h3>
|
<IconWorld className="me-2" /> Домены
|
||||||
</div>
|
</Link>
|
||||||
<div className="card-body">
|
<Link to="/ip-ranges" className="btn btn-outline-primary">
|
||||||
<div className="text-center text-muted py-4">
|
<IconNetwork className="me-2" /> IP-диапазоны
|
||||||
<IconActivity size={48} className="mb-3" />
|
</Link>
|
||||||
<p>График активности обновлений данных</p>
|
<Link to="/asns" className="btn btn-outline-primary">
|
||||||
<small>Будет добавлен в следующем обновлении</small>
|
<IconNetwork className="me-2" /> AS
|
||||||
</div>
|
</Link>
|
||||||
</div>
|
<Link to="/servers" className="btn btn-outline-primary">
|
||||||
|
<IconServer className="me-2" /> Серверы
|
||||||
|
</Link>
|
||||||
|
<Link to="/filters" className="btn btn-outline-primary">
|
||||||
|
<IconFilter className="me-2" /> Фильтры
|
||||||
|
</Link>
|
||||||
|
<Link to="/auto-urls" className="btn btn-outline-primary">
|
||||||
|
<IconDownload className="me-2" /> Авто URL
|
||||||
|
</Link>
|
||||||
|
<Link to="/billing" className="btn btn-outline-primary">
|
||||||
|
<IconCreditCard className="me-2" /> Биллинг
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user