nice
This commit is contained in:
@ -1,26 +1,60 @@
|
||||
import React, { useState } from 'react';
|
||||
import { MantineProvider, AppShell, Title, Group, Badge, Text } from '@mantine/core';
|
||||
import { Notifications } from '@mantine/notifications';
|
||||
import { IconFunction } from '@tabler/icons-react';
|
||||
import { Box, Title, Tabs, Stack, ActionIcon, Group, Select } from '@mantine/core';
|
||||
import {
|
||||
IconFunction,
|
||||
IconPlayerPlay,
|
||||
IconStar,
|
||||
IconStarFilled
|
||||
} from '@tabler/icons-react';
|
||||
import { FunctionList } from './components/FunctionList';
|
||||
import { FunctionForm } from './components/FunctionForm';
|
||||
import { ExecutionModal } from './components/ExecutionModal';
|
||||
import { FunctionDefinition } from './types';
|
||||
|
||||
// Default Mantine theme
|
||||
const theme: any = {
|
||||
colorScheme: 'light',
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
// Determine current route based on pathname
|
||||
const getCurrentRoute = () => {
|
||||
const path = window.location.pathname;
|
||||
if (path.includes('/functions')) return 'functions';
|
||||
if (path.includes('/executions')) return 'executions';
|
||||
return 'functions';
|
||||
};
|
||||
|
||||
const [currentRoute, setCurrentRoute] = useState(getCurrentRoute());
|
||||
const [isFavorited, setIsFavorited] = useState(false);
|
||||
const [selectedColor, setSelectedColor] = useState('');
|
||||
const [functionFormOpened, setFunctionFormOpened] = useState(false);
|
||||
const [executionModalOpened, setExecutionModalOpened] = useState(false);
|
||||
const [editingFunction, setEditingFunction] = useState<FunctionDefinition | null>(null);
|
||||
const [executingFunction, setExecutingFunction] = useState<FunctionDefinition | null>(null);
|
||||
const [refreshKey, setRefreshKey] = useState(0);
|
||||
|
||||
// Listen for URL changes (for when the shell navigates)
|
||||
React.useEffect(() => {
|
||||
const handlePopState = () => {
|
||||
setCurrentRoute(getCurrentRoute());
|
||||
};
|
||||
|
||||
window.addEventListener('popstate', handlePopState);
|
||||
return () => window.removeEventListener('popstate', handlePopState);
|
||||
}, []);
|
||||
|
||||
const handleTabChange = (value: string | null) => {
|
||||
if (value) {
|
||||
// Use history.pushState to update URL and notify shell router
|
||||
const basePath = '/app/faas';
|
||||
const newPath = `${basePath}/${value}`;
|
||||
|
||||
// Update the URL and internal state
|
||||
window.history.pushState(null, '', newPath);
|
||||
setCurrentRoute(value);
|
||||
|
||||
// Dispatch a custom event so shell can respond if needed
|
||||
window.dispatchEvent(new PopStateEvent('popstate', { state: null }));
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreateFunction = () => {
|
||||
console.log('handleCreateFunction called');
|
||||
setEditingFunction(null);
|
||||
setFunctionFormOpened(true);
|
||||
};
|
||||
@ -49,49 +83,121 @@ const App: React.FC = () => {
|
||||
setExecutingFunction(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<MantineProvider theme={theme}>
|
||||
<Notifications />
|
||||
<AppShell
|
||||
header={{ height: 60 }}
|
||||
padding="md"
|
||||
>
|
||||
<AppShell.Header>
|
||||
<Group h="100%" px="md" justify="space-between">
|
||||
<Group>
|
||||
<IconFunction size={24} />
|
||||
<Title order={3}>Function as a Service</Title>
|
||||
<Badge variant="light" color="blue">FaaS</Badge>
|
||||
</Group>
|
||||
<Text size="sm" c="dimmed">
|
||||
Serverless Functions Platform
|
||||
</Text>
|
||||
</Group>
|
||||
</AppShell.Header>
|
||||
const toggleFavorite = () => {
|
||||
setIsFavorited(prev => !prev);
|
||||
};
|
||||
|
||||
<AppShell.Main>
|
||||
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 = () => {
|
||||
switch (currentRoute) {
|
||||
case 'functions':
|
||||
return (
|
||||
<FunctionList
|
||||
key={refreshKey}
|
||||
onCreateFunction={handleCreateFunction}
|
||||
onEditFunction={handleEditFunction}
|
||||
onExecuteFunction={handleExecuteFunction}
|
||||
/>
|
||||
|
||||
<FunctionForm
|
||||
opened={functionFormOpened}
|
||||
onClose={handleFormClose}
|
||||
onSuccess={handleFormSuccess}
|
||||
editFunction={editingFunction}
|
||||
);
|
||||
case 'executions':
|
||||
return <div>Executions view coming soon...</div>;
|
||||
default:
|
||||
return (
|
||||
<FunctionList
|
||||
key={refreshKey}
|
||||
onCreateFunction={handleCreateFunction}
|
||||
onEditFunction={handleEditFunction}
|
||||
onExecuteFunction={handleExecuteFunction}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
<ExecutionModal
|
||||
opened={executionModalOpened}
|
||||
onClose={handleExecutionClose}
|
||||
function={executingFunction}
|
||||
/>
|
||||
</AppShell.Main>
|
||||
</AppShell>
|
||||
</MantineProvider>
|
||||
return (
|
||||
<Box w="100%" pos="relative">
|
||||
<Stack gap="lg">
|
||||
<div>
|
||||
<Group justify="space-between" align="flex-start">
|
||||
<div>
|
||||
<Group align="center" gap="sm" mb="xs">
|
||||
<Title order={1} size="h2">
|
||||
Function as a Service
|
||||
</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>
|
||||
|
||||
<Tabs value={currentRoute} onChange={handleTabChange}>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab
|
||||
value="functions"
|
||||
leftSection={<IconFunction size={16} />}
|
||||
>
|
||||
Functions
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
value="executions"
|
||||
leftSection={<IconPlayerPlay size={16} />}
|
||||
>
|
||||
Executions
|
||||
</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
|
||||
<Box pt="md">
|
||||
{renderContent()}
|
||||
</Box>
|
||||
</Tabs>
|
||||
</Stack>
|
||||
|
||||
<FunctionForm
|
||||
opened={functionFormOpened}
|
||||
onClose={handleFormClose}
|
||||
onSuccess={handleFormSuccess}
|
||||
editFunction={editingFunction}
|
||||
/>
|
||||
|
||||
<ExecutionModal
|
||||
opened={executionModalOpened}
|
||||
onClose={handleExecutionClose}
|
||||
function={executingFunction}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user