This commit is contained in:
2025-08-27 12:27:50 -04:00
parent 0663646e40
commit 7e584ba53b
13 changed files with 144 additions and 156 deletions

2
kms/web/dist/665.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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}>

View File

@ -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} />}

View File

@ -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} />}

View File

@ -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">

View File

@ -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">

View File

@ -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

File diff suppressed because one or more lines are too long

View File

@ -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 />

View File

@ -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>
); );

View File

@ -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>
); );
}; };

View File

@ -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',
}, },
]; ];