-
This commit is contained in:
2
kms/web/dist/665.js
vendored
2
kms/web/dist/665.js
vendored
File diff suppressed because one or more lines are too long
2
kms/web/dist/main.js
vendored
2
kms/web/dist/main.js
vendored
File diff suppressed because one or more lines are too long
@ -1,11 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Title, Tabs, Stack, Text } from '@mantine/core';
|
import { Box, Title, Tabs, Stack, Text, ActionIcon, Group, Select } from '@mantine/core';
|
||||||
import {
|
import {
|
||||||
IconApps,
|
IconApps,
|
||||||
IconKey,
|
IconKey,
|
||||||
IconTestPipe,
|
IconTestPipe,
|
||||||
IconFileText,
|
IconFileText,
|
||||||
IconDashboard
|
IconDashboard,
|
||||||
|
IconStar,
|
||||||
|
IconStarFilled
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import Applications from './components/Applications';
|
import Applications from './components/Applications';
|
||||||
import Tokens from './components/Tokens';
|
import Tokens from './components/Tokens';
|
||||||
@ -25,6 +27,8 @@ const App: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const [currentRoute, setCurrentRoute] = React.useState(getCurrentRoute());
|
const [currentRoute, setCurrentRoute] = React.useState(getCurrentRoute());
|
||||||
|
const [isFavorited, setIsFavorited] = React.useState(false);
|
||||||
|
const [selectedColor, setSelectedColor] = React.useState('');
|
||||||
|
|
||||||
// Listen for URL changes (for when the shell navigates)
|
// Listen for URL changes (for when the shell navigates)
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -51,6 +55,21 @@ const App: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleFavorite = () => {
|
||||||
|
setIsFavorited(prev => !prev);
|
||||||
|
};
|
||||||
|
|
||||||
|
const colorOptions = [
|
||||||
|
{ value: 'red', label: 'Red' },
|
||||||
|
{ value: 'blue', label: 'Blue' },
|
||||||
|
{ value: 'green', label: 'Green' },
|
||||||
|
{ value: 'purple', label: 'Purple' },
|
||||||
|
{ value: 'orange', label: 'Orange' },
|
||||||
|
{ value: 'pink', label: 'Pink' },
|
||||||
|
{ value: 'teal', label: 'Teal' },
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
switch (currentRoute) {
|
switch (currentRoute) {
|
||||||
case 'applications':
|
case 'applications':
|
||||||
@ -67,15 +86,45 @@ const App: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box w="100%">
|
<Box w="100%" pos="relative">
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<div>
|
<div>
|
||||||
<Title order={1} size="h2" mb="xs">
|
<Group justify="space-between" align="flex-start">
|
||||||
Key Management System
|
<div>
|
||||||
</Title>
|
<Group align="center" gap="sm" mb="xs">
|
||||||
<Text c="dimmed" size="sm">
|
<Title order={1} size="h2">
|
||||||
Manage API keys, tokens, and access permissions
|
Key Management System
|
||||||
</Text>
|
</Title>
|
||||||
|
<ActionIcon
|
||||||
|
variant="subtle"
|
||||||
|
size="lg"
|
||||||
|
onClick={toggleFavorite}
|
||||||
|
aria-label={isFavorited ? "Remove from favorites" : "Add to favorites"}
|
||||||
|
>
|
||||||
|
{isFavorited ? (
|
||||||
|
<IconStarFilled size={20} color="gold" />
|
||||||
|
) : (
|
||||||
|
<IconStar size={20} />
|
||||||
|
)}
|
||||||
|
</ActionIcon>
|
||||||
|
</Group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right-side controls */}
|
||||||
|
<Group align="flex-start" gap="lg">
|
||||||
|
<div>
|
||||||
|
<Select
|
||||||
|
placeholder="Choose a color"
|
||||||
|
data={colorOptions}
|
||||||
|
value={selectedColor}
|
||||||
|
onChange={(value) => setSelectedColor(value || '')}
|
||||||
|
size="sm"
|
||||||
|
w={150}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Group>
|
||||||
|
|
||||||
|
</Group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Tabs value={currentRoute} onChange={handleTabChange}>
|
<Tabs value={currentRoute} onChange={handleTabChange}>
|
||||||
|
|||||||
@ -233,9 +233,6 @@ const Applications: React.FC = () => {
|
|||||||
<Title order={2} mb="xs">
|
<Title order={2} mb="xs">
|
||||||
Applications
|
Applications
|
||||||
</Title>
|
</Title>
|
||||||
<Text c="dimmed">
|
|
||||||
Manage your registered applications and their configurations
|
|
||||||
</Text>
|
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconPlus size={16} />}
|
leftSection={<IconPlus size={16} />}
|
||||||
|
|||||||
@ -202,9 +202,6 @@ const Audit: React.FC = () => {
|
|||||||
<Title order={2} mb="xs">
|
<Title order={2} mb="xs">
|
||||||
Audit Log
|
Audit Log
|
||||||
</Title>
|
</Title>
|
||||||
<Text c="dimmed">
|
|
||||||
View and search system audit events and security logs
|
|
||||||
</Text>
|
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconRefresh size={16} />}
|
leftSection={<IconRefresh size={16} />}
|
||||||
|
|||||||
@ -110,15 +110,6 @@ const Dashboard: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<div>
|
|
||||||
<Title order={2} mb="xs">
|
|
||||||
Dashboard Overview
|
|
||||||
</Title>
|
|
||||||
<Text c="dimmed">
|
|
||||||
Monitor your key management system status and metrics
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<SimpleGrid cols={{ base: 1, sm: 2, lg: 4 }} spacing="lg">
|
<SimpleGrid cols={{ base: 1, sm: 2, lg: 4 }} spacing="lg">
|
||||||
{statCards.map((stat) => (
|
{statCards.map((stat) => (
|
||||||
<Card key={stat.title} shadow="sm" radius="md" withBorder p="lg">
|
<Card key={stat.title} shadow="sm" radius="md" withBorder p="lg">
|
||||||
|
|||||||
@ -136,15 +136,6 @@ const TokenTester: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<div>
|
|
||||||
<Title order={2} mb="xs">
|
|
||||||
Token Tester
|
|
||||||
</Title>
|
|
||||||
<Text c="dimmed">
|
|
||||||
Test and verify API tokens against your applications
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={{ base: 12, md: 6 }}>
|
<Grid.Col span={{ base: 12, md: 6 }}>
|
||||||
<Card shadow="sm" radius="md" withBorder p="lg">
|
<Card shadow="sm" radius="md" withBorder p="lg">
|
||||||
|
|||||||
@ -242,9 +242,6 @@ const Tokens: React.FC = () => {
|
|||||||
<Title order={2} mb="xs">
|
<Title order={2} mb="xs">
|
||||||
API Tokens
|
API Tokens
|
||||||
</Title>
|
</Title>
|
||||||
<Text c="dimmed">
|
|
||||||
Manage static API tokens for your applications
|
|
||||||
</Text>
|
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconPlus size={16} />}
|
leftSection={<IconPlus size={16} />}
|
||||||
|
|||||||
2
web/dist/main.js
vendored
2
web/dist/main.js
vendored
File diff suppressed because one or more lines are too long
@ -1,20 +1,27 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Routes, Route } from 'react-router-dom';
|
import { Routes, Route } from 'react-router-dom';
|
||||||
import { AppShell } from '@mantine/core';
|
import { AppShell } from '@mantine/core';
|
||||||
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
import Header from './components/Header';
|
import Header from './components/Header';
|
||||||
import Navigation from './components/Navigation';
|
import Navigation from './components/Navigation';
|
||||||
import HomePage from './pages/HomePage';
|
import HomePage from './pages/HomePage';
|
||||||
import AppLoader from './components/AppLoader';
|
import AppLoader from './components/AppLoader';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
const [collapsed, { toggle: toggleNavbar }] = useDisclosure(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppShell
|
<AppShell
|
||||||
header={{ height: 60 }}
|
header={{ height: 60 }}
|
||||||
navbar={{ width: 300, breakpoint: 'sm' }}
|
navbar={{
|
||||||
|
width: 300,
|
||||||
|
breakpoint: 'sm',
|
||||||
|
collapsed: { mobile: collapsed, desktop: collapsed }
|
||||||
|
}}
|
||||||
padding="md"
|
padding="md"
|
||||||
>
|
>
|
||||||
<AppShell.Header>
|
<AppShell.Header>
|
||||||
<Header />
|
<Header onToggleNavbar={toggleNavbar} />
|
||||||
</AppShell.Header>
|
</AppShell.Header>
|
||||||
<AppShell.Navbar>
|
<AppShell.Navbar>
|
||||||
<Navigation />
|
<Navigation />
|
||||||
|
|||||||
@ -2,24 +2,30 @@ import React from 'react';
|
|||||||
import {
|
import {
|
||||||
Group,
|
Group,
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Select,
|
|
||||||
TextInput,
|
TextInput,
|
||||||
Text,
|
Text,
|
||||||
Avatar,
|
|
||||||
Flex,
|
Flex,
|
||||||
Box,
|
Box,
|
||||||
|
Burger,
|
||||||
|
Avatar,
|
||||||
Menu,
|
Menu,
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
IconSearch,
|
IconSearch,
|
||||||
IconBell,
|
IconBell,
|
||||||
|
IconHome,
|
||||||
|
IconStar,
|
||||||
IconSettings,
|
IconSettings,
|
||||||
IconMail,
|
|
||||||
IconUser,
|
|
||||||
IconLogout,
|
IconLogout,
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
|
|
||||||
const Header: React.FC = () => {
|
interface HeaderProps {
|
||||||
|
onToggleNavbar: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Header: React.FC<HeaderProps> = ({ onToggleNavbar }) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
const [currentTime, setCurrentTime] = React.useState(new Date());
|
const [currentTime, setCurrentTime] = React.useState(new Date());
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -64,6 +70,13 @@ const Header: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<Box h={60} px="md">
|
<Box h={60} px="md">
|
||||||
<Flex align="center" h="100%" gap="md">
|
<Flex align="center" h="100%" gap="md">
|
||||||
|
{/* Burger menu for navbar toggle */}
|
||||||
|
<Burger
|
||||||
|
onClick={onToggleNavbar}
|
||||||
|
size="sm"
|
||||||
|
aria-label="Toggle navigation"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<Text size="xl" fw={700} c="blue">
|
<Text size="xl" fw={700} c="blue">
|
||||||
Skybridge
|
Skybridge
|
||||||
@ -71,30 +84,22 @@ const Header: React.FC = () => {
|
|||||||
|
|
||||||
{/* Icon Buttons */}
|
{/* Icon Buttons */}
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<ActionIcon variant="subtle" size="lg">
|
<ActionIcon
|
||||||
|
variant="subtle"
|
||||||
|
size="lg"
|
||||||
|
aria-label="Home"
|
||||||
|
onClick={() => navigate('/')}
|
||||||
|
>
|
||||||
|
<IconHome size={18} />
|
||||||
|
</ActionIcon>
|
||||||
|
<ActionIcon variant="subtle" size="lg" aria-label="Favorites">
|
||||||
|
<IconStar size={18} />
|
||||||
|
</ActionIcon>
|
||||||
|
<ActionIcon variant="subtle" size="lg" aria-label="Notifications">
|
||||||
<IconBell size={18} />
|
<IconBell size={18} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
<ActionIcon variant="subtle" size="lg">
|
|
||||||
<IconMail size={18} />
|
|
||||||
</ActionIcon>
|
|
||||||
<ActionIcon variant="subtle" size="lg">
|
|
||||||
<IconSettings size={18} />
|
|
||||||
</ActionIcon>
|
|
||||||
<ActionIcon variant="subtle" size="lg">
|
|
||||||
<IconUser size={18} />
|
|
||||||
</ActionIcon>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
{/* Application Dropdown */}
|
|
||||||
<Select
|
|
||||||
placeholder="Select Application"
|
|
||||||
data={[
|
|
||||||
{ value: 'demo', label: 'Demo App' },
|
|
||||||
{ value: 'dashboard', label: 'Dashboard' },
|
|
||||||
{ value: 'analytics', label: 'Analytics' },
|
|
||||||
]}
|
|
||||||
w={200}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Search Box */}
|
{/* Search Box */}
|
||||||
<TextInput
|
<TextInput
|
||||||
@ -161,6 +166,7 @@ const Header: React.FC = () => {
|
|||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Menu.Dropdown>
|
</Menu.Dropdown>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,12 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NavLink, Stack, Text, Group } from '@mantine/core';
|
import { NavLink, Stack, Text } from '@mantine/core';
|
||||||
import { useNavigate, useLocation } from 'react-router-dom';
|
import { useNavigate, useLocation } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
IconHome,
|
|
||||||
IconApps,
|
|
||||||
IconDashboard,
|
IconDashboard,
|
||||||
IconChartLine,
|
|
||||||
IconStar,
|
|
||||||
IconKey,
|
IconKey,
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
|
|
||||||
@ -14,25 +10,8 @@ const Navigation: React.FC = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
const navigationItems = [
|
// Define all available applications
|
||||||
{
|
const allAvailableApplications = [
|
||||||
label: 'Home',
|
|
||||||
icon: IconHome,
|
|
||||||
path: '/',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Favorites',
|
|
||||||
icon: IconStar,
|
|
||||||
path: '/favorites',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'All Applications',
|
|
||||||
icon: IconApps,
|
|
||||||
path: '/apps',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const applications = [
|
|
||||||
{
|
{
|
||||||
label: 'Demo App',
|
label: 'Demo App',
|
||||||
icon: IconDashboard,
|
icon: IconDashboard,
|
||||||
@ -43,34 +22,26 @@ const Navigation: React.FC = () => {
|
|||||||
icon: IconKey,
|
icon: IconKey,
|
||||||
path: '/app/kms',
|
path: '/app/kms',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: 'Analytics',
|
|
||||||
icon: IconChartLine,
|
|
||||||
path: '/app/analytics',
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Define which apps are favorited (you could make this dynamic later)
|
||||||
|
const favoritePaths = ['/app/demo'];
|
||||||
|
|
||||||
|
const favoriteApplications = allAvailableApplications.filter(app =>
|
||||||
|
favoritePaths.includes(app.path)
|
||||||
|
);
|
||||||
|
|
||||||
|
const nonFavoriteApplications = allAvailableApplications.filter(app =>
|
||||||
|
!favoritePaths.includes(app.path)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap="xs" p="md">
|
<Stack gap="xs" p="md">
|
||||||
<Text size="sm" fw={600} c="dimmed" tt="uppercase" mb="xs">
|
<Text size="sm" fw={600} c="dimmed" tt="uppercase" mb="xs">
|
||||||
Navigation
|
Favorites
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{navigationItems.map((item) => (
|
{favoriteApplications.map((app) => (
|
||||||
<NavLink
|
|
||||||
key={item.path}
|
|
||||||
label={item.label}
|
|
||||||
leftSection={<item.icon size={16} />}
|
|
||||||
active={location.pathname === item.path}
|
|
||||||
onClick={() => navigate(item.path)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<Text size="sm" fw={600} c="dimmed" tt="uppercase" mt="lg" mb="xs">
|
|
||||||
Applications
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
{applications.map((app) => (
|
|
||||||
<NavLink
|
<NavLink
|
||||||
key={app.path}
|
key={app.path}
|
||||||
label={app.label}
|
label={app.label}
|
||||||
@ -79,6 +50,24 @@ const Navigation: React.FC = () => {
|
|||||||
onClick={() => navigate(app.path)}
|
onClick={() => navigate(app.path)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
{nonFavoriteApplications.length > 0 && (
|
||||||
|
<>
|
||||||
|
<Text size="sm" fw={600} c="dimmed" tt="uppercase" mt="lg" mb="xs">
|
||||||
|
All Applications
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
{nonFavoriteApplications.map((app) => (
|
||||||
|
<NavLink
|
||||||
|
key={`all-${app.path}`}
|
||||||
|
label={app.label}
|
||||||
|
leftSection={<app.icon size={16} />}
|
||||||
|
active={location.pathname.startsWith(app.path)}
|
||||||
|
onClick={() => navigate(app.path)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,11 +14,7 @@ import {
|
|||||||
IconStar,
|
IconStar,
|
||||||
IconStarFilled,
|
IconStarFilled,
|
||||||
IconDashboard,
|
IconDashboard,
|
||||||
IconChartLine,
|
IconKey,
|
||||||
IconSettings,
|
|
||||||
IconUsers,
|
|
||||||
IconFiles,
|
|
||||||
IconMail,
|
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import Breadcrumbs from '../components/Breadcrumbs';
|
import Breadcrumbs from '../components/Breadcrumbs';
|
||||||
|
|
||||||
@ -33,56 +29,24 @@ interface App {
|
|||||||
|
|
||||||
const HomePage: React.FC = () => {
|
const HomePage: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [favoriteApps, setFavoriteApps] = useState<string[]>(['demo', 'analytics']);
|
const [favoriteApps, setFavoriteApps] = useState<string[]>(['demo']);
|
||||||
|
|
||||||
const availableApps: App[] = [
|
const availableApps: App[] = [
|
||||||
{
|
{
|
||||||
id: 'demo',
|
id: 'demo',
|
||||||
name: 'Demo App',
|
name: 'Demo App',
|
||||||
description: 'Sample application for testing',
|
description: 'Sample microfrontend application for testing module federation',
|
||||||
icon: IconDashboard,
|
icon: IconDashboard,
|
||||||
path: '/app/demo',
|
path: '/app/demo',
|
||||||
category: 'Development',
|
category: 'Development',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'analytics',
|
id: 'kms',
|
||||||
name: 'Analytics',
|
name: 'Key Management System',
|
||||||
description: 'Data analytics and reporting',
|
description: 'Manage API keys, tokens, and access permissions for applications',
|
||||||
icon: IconChartLine,
|
icon: IconKey,
|
||||||
path: '/app/analytics',
|
path: '/app/kms',
|
||||||
category: 'Analytics',
|
category: 'Security',
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'settings',
|
|
||||||
name: 'Settings',
|
|
||||||
description: 'System configuration',
|
|
||||||
icon: IconSettings,
|
|
||||||
path: '/app/settings',
|
|
||||||
category: 'System',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'users',
|
|
||||||
name: 'User Management',
|
|
||||||
description: 'Manage users and permissions',
|
|
||||||
icon: IconUsers,
|
|
||||||
path: '/app/users',
|
|
||||||
category: 'Administration',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'files',
|
|
||||||
name: 'File Manager',
|
|
||||||
description: 'Browse and manage files',
|
|
||||||
icon: IconFiles,
|
|
||||||
path: '/app/files',
|
|
||||||
category: 'Utilities',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'mail',
|
|
||||||
name: 'Mail Client',
|
|
||||||
description: 'Email management',
|
|
||||||
icon: IconMail,
|
|
||||||
path: '/app/mail',
|
|
||||||
category: 'Communication',
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user