refactor: Simplify App component by removing sidebar functionality and updating navigation structure for improved UI consistency
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 16m13s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 16m13s
This commit is contained in:
+144
-278
@@ -1,48 +1,38 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Container, Navbar, Tabs, Tab } from 'react-bootstrap';
|
import { Container } from 'react-bootstrap';
|
||||||
import {
|
import {
|
||||||
IconBrandTabler,
|
IconBrandTabler,
|
||||||
IconWorld,
|
IconWorld,
|
||||||
IconNetwork,
|
IconNetwork,
|
||||||
IconSettings,
|
IconSettings,
|
||||||
IconMenu2,
|
|
||||||
IconX,
|
|
||||||
IconHome,
|
IconHome,
|
||||||
IconDatabase,
|
|
||||||
IconUsers,
|
|
||||||
IconBell,
|
|
||||||
IconSearch,
|
|
||||||
IconChevronDown,
|
|
||||||
IconLogout,
|
|
||||||
IconUser,
|
|
||||||
IconDashboard,
|
|
||||||
IconFileText,
|
IconFileText,
|
||||||
IconCloud,
|
IconCloud,
|
||||||
IconShield,
|
IconShield,
|
||||||
IconActivity
|
IconActivity,
|
||||||
|
IconBell,
|
||||||
|
IconChevronDown,
|
||||||
|
IconUser
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import DataManager from './DataManager';
|
import DataManager from './DataManager';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
const [activeTab, setActiveTab] = useState('dashboard');
|
const [activeTab, setActiveTab] = useState('dashboard');
|
||||||
const [notifications] = useState([
|
const [notifications] = useState([
|
||||||
{ id: 1, title: 'Новый домен добавлен', message: 'example.com был добавлен в список', time: '2 мин назад' },
|
{ id: 1, title: 'Новый домен добавлен', message: 'example.com был добавлен в список', time: '2 мин назад' },
|
||||||
{ id: 2, title: 'Изменения сохранены', message: 'Список AS обновлен в S3', time: '5 мин назад' }
|
{ id: 2, title: 'Изменения сохранены', message: 'Список AS обновлен в S3', time: '5 мин назад' }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const toggleSidebar = () => setSidebarOpen(!sidebarOpen);
|
const navItems = [
|
||||||
|
{ id: 'dashboard', title: 'Dashboard', icon: IconHome },
|
||||||
const sidebarItems = [
|
{ id: 'domains', title: 'Домены', icon: IconWorld },
|
||||||
{ id: 'dashboard', title: 'Dashboard', icon: IconDashboard, badge: null },
|
{ id: 'asns', title: 'AS', icon: IconNetwork },
|
||||||
{ id: 'domains', title: 'Домены', icon: IconWorld, badge: '12' },
|
{ id: 'files', title: 'Файлы', icon: IconFileText },
|
||||||
{ id: 'asns', title: 'AS', icon: IconNetwork, badge: '8' },
|
{ id: 'cloud', title: 'Облако', icon: IconCloud },
|
||||||
{ id: 'files', title: 'Файлы', icon: IconFileText, badge: null },
|
{ id: 'security', title: 'Безопасность', icon: IconShield },
|
||||||
{ id: 'cloud', title: 'Облако', icon: IconCloud, badge: null },
|
{ id: 'activity', title: 'Активность', icon: IconActivity },
|
||||||
{ id: 'security', title: 'Безопасность', icon: IconShield, badge: null },
|
{ id: 'settings', title: 'Настройки', icon: IconSettings }
|
||||||
{ id: 'activity', title: 'Активность', icon: IconActivity, badge: '3' },
|
|
||||||
{ id: 'settings', title: 'Настройки', icon: IconSettings, badge: null }
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
@@ -70,297 +60,173 @@ function App() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPageTitle = () => {
|
|
||||||
const item = sidebarItems.find(item => item.id === activeTab);
|
|
||||||
return item ? item.title : 'Dashboard';
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page">
|
<div className="page">
|
||||||
{/* Sidebar */}
|
{/* Верхнее меню Tabler Admin */}
|
||||||
<aside className={`navbar navbar-vertical navbar-expand-lg ${sidebarOpen ? 'navbar-show' : ''}`}>
|
<header className="navbar navbar-expand-md navbar-light d-print-none" style={{boxShadow: '0 1px 0 0 #e9ecef'}}>
|
||||||
<div className="container-fluid">
|
<div className="container-xl">
|
||||||
<button
|
<a href="#" className="navbar-brand d-flex align-items-center">
|
||||||
className="navbar-toggler"
|
|
||||||
type="button"
|
|
||||||
onClick={toggleSidebar}
|
|
||||||
>
|
|
||||||
<IconX className="icon" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<h1 className="navbar-brand navbar-brand-autodark">
|
|
||||||
<IconBrandTabler className="navbar-brand-icon me-2" />
|
<IconBrandTabler className="navbar-brand-icon me-2" />
|
||||||
S3 Lists Manager
|
<span className="fw-bold">S3 Lists Manager</span>
|
||||||
</h1>
|
</a>
|
||||||
|
<div className="collapse navbar-collapse show" id="navbar-menu">
|
||||||
<div className="navbar-nav flex-row d-lg-none">
|
<ul className="navbar-nav me-auto">
|
||||||
<div className="nav-item dropdown">
|
{navItems.map((item) => (
|
||||||
<a href="#" className="nav-link d-flex lh-1 text-reset p-0" data-bs-toggle="dropdown">
|
|
||||||
<span className="avatar avatar-sm" style={{backgroundImage: 'url(./static/avatars/000m.jpg)'}}></span>
|
|
||||||
</a>
|
|
||||||
<div className="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
|
|
||||||
<a href="#" className="dropdown-item">Profile</a>
|
|
||||||
<a href="#" className="dropdown-item">Settings</a>
|
|
||||||
<div className="dropdown-divider"></div>
|
|
||||||
<a href="#" className="dropdown-item">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="collapse navbar-collapse" id="sidebar-menu">
|
|
||||||
<ul className="navbar-nav pt-lg-auto">
|
|
||||||
{sidebarItems.map((item) => (
|
|
||||||
<li key={item.id} className="nav-item">
|
<li key={item.id} className="nav-item">
|
||||||
<a
|
<a
|
||||||
className={`nav-link ${activeTab === item.id ? 'active' : ''}`}
|
className={`nav-link d-flex align-items-center ${activeTab === item.id ? 'active fw-bold' : ''}`}
|
||||||
href="#"
|
href="#"
|
||||||
onClick={(e) => { e.preventDefault(); setActiveTab(item.id); }}
|
onClick={e => { e.preventDefault(); setActiveTab(item.id); }}
|
||||||
>
|
>
|
||||||
<item.icon className="nav-link-icon" />
|
<item.icon className="nav-link-icon me-1" size={20} />
|
||||||
<span className="nav-link-title">{item.title}</span>
|
{item.title}
|
||||||
{item.badge && (
|
|
||||||
<span className="badge badge-sm bg-green-lt text-green ms-auto">
|
|
||||||
{item.badge}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
<ul className="navbar-nav ms-auto">
|
||||||
</div>
|
<li className="nav-item dropdown">
|
||||||
</aside>
|
<a href="#" className="nav-link px-0" data-bs-toggle="dropdown" tabIndex="-1">
|
||||||
|
<IconBell className="icon" />
|
||||||
{/* Header */}
|
<span className="badge badge-sm bg-red"></span>
|
||||||
<header className="navbar navbar-expand-md navbar-light d-none d-lg-flex d-print-none">
|
</a>
|
||||||
<div className="container-xl">
|
<div className="dropdown-menu dropdown-menu-arrow dropdown-menu-end dropdown-menu-card">
|
||||||
<button
|
<div className="card">
|
||||||
className="navbar-toggler"
|
<div className="card-header">
|
||||||
type="button"
|
<h3 className="card-title">Уведомления</h3>
|
||||||
onClick={toggleSidebar}
|
</div>
|
||||||
>
|
<div className="list-group list-group-flush">
|
||||||
<IconMenu2 className="icon" />
|
{notifications.map((notification) => (
|
||||||
</button>
|
<div key={notification.id} className="list-group-item">
|
||||||
|
<div className="row align-items-center">
|
||||||
<div className="navbar-nav flex-row order-md-last">
|
<div className="col-auto">
|
||||||
<div className="nav-item dropdown d-none d-md-flex me-3">
|
<span className="status-dot status-dot-animated bg-red d-block"></span>
|
||||||
<a href="#" className="nav-link px-0" data-bs-toggle="dropdown" tabIndex="-1">
|
</div>
|
||||||
<IconBell className="icon" />
|
<div className="col text-truncate">
|
||||||
<span className="badge badge-sm bg-red"></span>
|
<a href="#" className="text-body d-block">{notification.title}</a>
|
||||||
</a>
|
<div className="d-block text-muted text-truncate mt-n1">
|
||||||
<div className="dropdown-menu dropdown-menu-arrow dropdown-menu-end dropdown-menu-card">
|
{notification.message}
|
||||||
<div className="card">
|
</div>
|
||||||
<div className="card-header">
|
|
||||||
<h3 className="card-title">Уведомления</h3>
|
|
||||||
</div>
|
|
||||||
<div className="list-group list-group-flush">
|
|
||||||
{notifications.map((notification) => (
|
|
||||||
<div key={notification.id} className="list-group-item">
|
|
||||||
<div className="row align-items-center">
|
|
||||||
<div className="col-auto">
|
|
||||||
<span className="status-dot status-dot-animated bg-red d-block"></span>
|
|
||||||
</div>
|
|
||||||
<div className="col text-truncate">
|
|
||||||
<a href="#" className="text-body d-block">{notification.title}</a>
|
|
||||||
<div className="d-block text-muted text-truncate mt-n1">
|
|
||||||
{notification.message}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-auto">
|
|
||||||
<a href="#" className="list-group-item-actions">
|
|
||||||
<IconX className="icon" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
</div>
|
<li className="nav-item dropdown ms-3">
|
||||||
|
<a href="#" className="nav-link d-flex lh-1 text-reset p-0" data-bs-toggle="dropdown">
|
||||||
<div className="nav-item dropdown">
|
<span className="avatar avatar-sm" style={{backgroundImage: 'url(./static/avatars/000m.jpg)'}}></span>
|
||||||
<a href="#" className="nav-link d-flex lh-1 text-reset p-0" data-bs-toggle="dropdown">
|
<span className="d-none d-xl-block ps-2">
|
||||||
<span className="avatar avatar-sm" style={{backgroundImage: 'url(./static/avatars/000m.jpg)'}}></span>
|
<span>Admin User</span>
|
||||||
<span className="d-none d-xl-block ps-2">
|
<IconChevronDown className="icon" />
|
||||||
<span>Admin User</span>
|
</span>
|
||||||
<IconChevronDown className="icon" />
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<div className="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
|
|
||||||
<a href="#" className="dropdown-item">
|
|
||||||
<IconUser className="icon me-2" />
|
|
||||||
Profile
|
|
||||||
</a>
|
</a>
|
||||||
<a href="#" className="dropdown-item">
|
<div className="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
|
||||||
<IconSettings className="icon me-2" />
|
<a href="#" className="dropdown-item">
|
||||||
Settings
|
<IconUser className="icon me-2" />
|
||||||
</a>
|
Профиль
|
||||||
<div className="dropdown-divider"></div>
|
</a>
|
||||||
<a href="#" className="dropdown-item">
|
<a href="#" className="dropdown-item">
|
||||||
<IconLogout className="icon me-2" />
|
<IconSettings className="icon me-2" />
|
||||||
Logout
|
Настройки
|
||||||
</a>
|
</a>
|
||||||
</div>
|
<div className="dropdown-divider"></div>
|
||||||
</div>
|
<a href="#" className="dropdown-item">
|
||||||
</div>
|
Выйти
|
||||||
|
</a>
|
||||||
<div className="navbar-nav flex-row">
|
</div>
|
||||||
<div className="nav-item d-none d-md-flex me-3">
|
</li>
|
||||||
<div className="input-icon">
|
</ul>
|
||||||
<IconSearch className="icon" />
|
|
||||||
<input type="text" className="form-control" placeholder="Поиск..." />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
<main className="page-wrapper">
|
||||||
{/* Main Content */}
|
<div className="container-xl mt-4">
|
||||||
<div className="page-wrapper">
|
{renderContent()}
|
||||||
<div className="container-xl">
|
|
||||||
{/* Page Header */}
|
|
||||||
<div className="page-header d-print-none">
|
|
||||||
<div className="row align-items-center">
|
|
||||||
<div className="col">
|
|
||||||
<div className="page-pretitle">
|
|
||||||
S3 Lists Manager
|
|
||||||
</div>
|
|
||||||
<h2 className="page-title">
|
|
||||||
{getPageTitle()}
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
<div className="col-auto ms-auto d-print-none">
|
|
||||||
<div className="btn-list">
|
|
||||||
<span className="d-none d-sm-inline">
|
|
||||||
<a href="#" className="btn btn-white">
|
|
||||||
Новый домен
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<a href="#" className="btn btn-primary d-none d-sm-inline-block">
|
|
||||||
<IconDatabase className="icon me-2" />
|
|
||||||
Сохранить в S3
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* Breadcrumbs */}
|
|
||||||
<div className="page-header-breadcrumb">
|
|
||||||
<ol className="breadcrumb">
|
|
||||||
<li className="breadcrumb-item">
|
|
||||||
<a href="#" onClick={(e) => { e.preventDefault(); setActiveTab('dashboard'); }}>
|
|
||||||
<IconHome className="icon me-2" />
|
|
||||||
Главная
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li className="breadcrumb-item active" aria-current="page">
|
|
||||||
{getPageTitle()}
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</main>
|
||||||
<div className="page-body">
|
|
||||||
<div className="container-xl">
|
|
||||||
{renderContent()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Footer */}
|
|
||||||
<footer className="footer footer-transparent d-print-none">
|
|
||||||
<div className="container-xl">
|
|
||||||
<div className="row text-center align-items-center flex-row-reverse">
|
|
||||||
<div className="col-12 col-lg-auto mt-3 mt-lg-0">
|
|
||||||
<ul className="list-inline list-inline-dots mb-0">
|
|
||||||
<li className="list-inline-item">
|
|
||||||
Copyright © 2024
|
|
||||||
<a href="." className="link-secondary">S3 Lists Manager</a>.
|
|
||||||
All rights reserved.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dashboard Component
|
|
||||||
function Dashboard() {
|
function Dashboard() {
|
||||||
const stats = [
|
|
||||||
{ title: 'Всего доменов', value: '1,234', icon: IconWorld, color: 'blue' },
|
|
||||||
{ title: 'Всего AS', value: '567', icon: IconNetwork, color: 'green' },
|
|
||||||
{ title: 'Активные шлюзы', value: '12', icon: IconDatabase, color: 'orange' },
|
|
||||||
{ title: 'Последние изменения', value: '3', icon: IconActivity, color: 'red' }
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="row row-deck row-cards">
|
<div>
|
||||||
{/* Stats Cards */}
|
<div className="page-header d-print-none mb-4">
|
||||||
{stats.map((stat, index) => (
|
<div className="row align-items-center">
|
||||||
<div key={index} className="col-sm-6 col-lg-3">
|
<div className="col">
|
||||||
|
<h2 className="page-title">Dashboard</h2>
|
||||||
|
<div className="page-pretitle">Главная / Dashboard</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row row-deck">
|
||||||
|
<div className="col-sm-6 col-lg-3">
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
|
<div className="h1 mb-3">1,234</div>
|
||||||
<div className="d-flex align-items-center">
|
<div className="d-flex align-items-center">
|
||||||
<div className="subheader">{stat.title}</div>
|
<IconWorld className="icon me-2" />
|
||||||
</div>
|
<span className="text-muted">Всего доменов</span>
|
||||||
<div className="h1 mb-3">{stat.value}</div>
|
|
||||||
<div className="d-flex mb-2">
|
|
||||||
<stat.icon className={`icon icon-sm text-${stat.color}`} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
<div className="col-sm-6 col-lg-3">
|
||||||
|
<div className="card">
|
||||||
{/* Main Content Card */}
|
<div className="card-body">
|
||||||
<div className="col-12">
|
<div className="h1 mb-3">567</div>
|
||||||
<div className="card">
|
<div className="d-flex align-items-center">
|
||||||
<div className="card-header">
|
<IconNetwork className="icon me-2" />
|
||||||
<h3 className="card-title">Добро пожаловать в S3 Lists Manager</h3>
|
<span className="text-muted">Всего AS</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="card-body">
|
</div>
|
||||||
<p>Выберите раздел в боковом меню для управления списками доменов и AS.</p>
|
<div className="col-sm-6 col-lg-3">
|
||||||
<div className="row">
|
<div className="card">
|
||||||
<div className="col-md-6">
|
<div className="card-body">
|
||||||
<div className="card card-sm">
|
<div className="h1 mb-3">12</div>
|
||||||
<div className="card-body">
|
<div className="d-flex align-items-center">
|
||||||
<div className="row align-items-center">
|
<IconCloud className="icon me-2" />
|
||||||
<div className="col-auto">
|
<span className="text-muted">Активные шлюзы</span>
|
||||||
<IconWorld className="icon icon-lg text-blue" />
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col">
|
</div>
|
||||||
<div className="font-weight-medium">
|
</div>
|
||||||
Управление доменами
|
<div className="col-sm-6 col-lg-3">
|
||||||
</div>
|
<div className="card">
|
||||||
<div className="text-muted">
|
<div className="card-body">
|
||||||
Добавляйте, редактируйте и управляйте списками доменов
|
<div className="h1 mb-3">3</div>
|
||||||
</div>
|
<div className="d-flex align-items-center">
|
||||||
</div>
|
<IconActivity className="icon me-2" />
|
||||||
</div>
|
<span className="text-muted">Последние изменения</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="card mt-4">
|
||||||
|
<div className="card-body">
|
||||||
|
<h3 className="card-title mb-3">Добро пожаловать в S3 Lists Manager</h3>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-6 mb-3">
|
||||||
|
<div className="d-flex align-items-center">
|
||||||
|
<IconWorld className="icon me-2" size={32} />
|
||||||
|
<div>
|
||||||
|
<div className="fw-bold">Управление доменами</div>
|
||||||
|
<div className="text-muted">Добавляйте, редактируйте и управляйте списками доменов</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-6">
|
</div>
|
||||||
<div className="card card-sm">
|
<div className="col-md-6 mb-3">
|
||||||
<div className="card-body">
|
<div className="d-flex align-items-center">
|
||||||
<div className="row align-items-center">
|
<IconNetwork className="icon me-2" size={32} />
|
||||||
<div className="col-auto">
|
<div>
|
||||||
<IconNetwork className="icon icon-lg text-green" />
|
<div className="fw-bold">Управление AS</div>
|
||||||
</div>
|
<div className="text-muted">Добавляйте, редактируйте и управляйте списками AS</div>
|
||||||
<div className="col">
|
|
||||||
<div className="font-weight-medium">
|
|
||||||
Управление AS
|
|
||||||
</div>
|
|
||||||
<div className="text-muted">
|
|
||||||
Добавляйте, редактируйте и управляйте списками AS
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user